# pyfplo.common

- BandFileContext
- BandPlot
- BandHeader
- BandWeights
- WeightDefinitions
- WeightDefinition
- OptionSet
- Site
- Watch
- Version
- Vlevel
- Constants

This module contains a collection of usefull objects related to FPLO band/bandweights routines. You can easily write these files and read them into `numpy.ndarray`s for further processing. Have a look at `..../FPLO22.00-62/DOC/pyfplo/Examples/bandplot/model.py` for better understanding.

## BandFileContext

class `BandFileContext`

  This class wraps data to easily manage the creation of FPLO band/bandweight files. This class cannot be instantiated directly. It only is produced and returned via a call to `BandPlot.openBandFile()`

  Example:

      # A simple band structure plotting using low level routines
      # based on slabify.
      import pyfplo.slabify as sla
      import numpy as np
      import numpy.linalg as LA

      s=sla.Slabify()
      s.dirname='.'
      s.object='3d'
      hamdata='+hamdata'
      s.prepare(hamdata)

      bp=sla.BandPlot()
      bp.points=[
              ['$~G',[0,  0,0]],
              ['X'  ,[0.5,0,0]]
      ]
      bp.ndiv=100
      bp.calculateBandPlotMesh(s.dirname)
      dists=bp.kdists
      kpts=bp.kpnts

      with bp.openBandFile(s.dirname+'/+b',s.nspin,len(kpts),\
                             progress='bandplot') as fb:

          # now fb is an instance of `BandFileContext`

          for ik,k in enumerate(kpts):
              for ms in range(s.nspin):
                  Hk=s.hamAtKPoint(k*s.kscale,ms)
                  (EV,C)=LA.eigh(Hk)
                  fb.write(ms,dists[ik],k,EV)

  `close`()

    Explicitely close the file. Usefull, if multiple files are used in the same loop, in which case the `with`-statement is not usefull. The underlying file gets closed when this object gets garbage collected (after its scope is exited). For cleanliness it is a good measure to always close files.

    Method1:

        with bp.openBandFile(...) as f:
           doseomthing with f
        # here f is closed

    Method2:

        f=bp.openBandFile(...):
        do something with f
        f.close()
        # here f is closed

  `write`(ispin, dk, k, energies, weights=None)

    Parameters: | ispin (int) – spin number (NSP or FREL: 0, SP: 0 or 1) dk (float) – scalar path length along k-path k (3-vector of float) – k-point energies (sequence (list,tuple,..)) – sequence of energies for all bands at this k-point weights – all weights for all bands at this k-point

    Write the energies for spin component ispin and k-vector k and scalar path-length variable dk to the file. ispin must be 0 if there is only one spin. It must loop over [0,1] if there are two spins. See the nspin argument in `BandPlot.openBandFile()`. The spin loop must be inside the k-loop!

    If a weight file is writen (weightlabels argument in `BandPlot.openBandFile()`) a matrix like argument (e.g. a `numpy.ndarray`) must be given as last argument to `write()` whose rows correspond to the weights and the columns to the bands.

## BandPlot

class `BandPlot`

  This is a helper class for data which control the path through the BZ for routines creating band structure or energy distribution cut plots. After setting the data (`points` and `ndiv`) `calculateBandPlotMesh()` must be called before using `BandPlot`. Alternatively `readBandPlotMesh()` can be called to import from `=.kp`.

  This class is used by certain methods of `pyfplo.slabify.Slabify`.

  Usage:

      import pyfplo.slabify as sla
      import pyfplo.common as com
      s=sla.Slabify()

      bp=com.BandPlot()
      bp.points=[ ['$~G',[0,0,0]],... ]
      bp.ndiv=100
      bp.calculateBandPlotMesh(s.dirname)

      s.calculateBandStructure(bp)

  This class also allows to read `+band` type files for further processing:

      bp=com.BandPlot()
      [bh,kdists,kptns,erg]=bp.readBands('+band')
      print 'bandheader +b: nkp={0} nband={1} nspin={2}'\
          .format(bh.nkp,bh.nband,bh.nspin)
      print 'kdists2 shape :',dists2.shape
      print 'kptns2 shape :',kptns2.shape
      print 'erg shape :',erg.shape
      # now do something with the information

  Create a new `BandPlot` instance via:

      import pyfplo.slabify as sla
      bp=sla.BandPlot()

  or:

      import pyfplo.common as com
      bp=com.BandPlot()

  `calculateBandPlotMesh`(pointsfileoutputdir)

    Parameters: | pointsfileoutputdir (str) – directory in which to create `+points`

    Finalize the bandplot definition. This actually calculates the k-points for the BZ-path from the input settings (`points` and `ndiv`). pointsfileoutputdir usually should be `Slabify.dirname`:

        import pyfplo.slabify as sla
        s=sla.Slabify()
        ...
        bp.points=[...]
        bp.calculateBandPlotMesh(s.dirname)
        ...

    It serves to put the file `+points` in the right place.

  `readBandPlotMesh`(kpfilename)

    Parameters: | kpfilename (str) – name of an xfplo `=.kp`-type file

    Read file `=.kp` (from xfplo) for mesh definition. `BandPlot` restrictions (see `setOutputRestrictions()`) are still applied and restrictions inside `=.kp` are ignored. IMPORTANT: do not use `=.in`… files from the Slabify output in context of visualizing the Fermi surface with xfplo. It will not work! Use the `=.in` files from the underlying FPLO calculation instead.”

  `openBandFile`(filename, nspin, nkpts, weightlabels=None, progress=None)

    Parameters: | filename (str) – the name of the `+band`-type file nspin (int) – number of spins nkpts (int) – number of k-points weightlabels – a `list` of labels (`str`) or `None` progress – a progress message (`str`) or `None`
    Returns: | band file context
    Return type: | `BandFileContext`

    Low level routine. Return an object of type `BandFileContext` for creation of FPLO band files.

    The returned object will open the file and organizes the proper file format. Its `BandFileContext.write()` method can be used to write the actual data. If the object gets deleted (automatic if the scope is left) the file gets closed. The `BandFileContext.close()` method can be called explicitly.

    The best way to use it is in a `with`-statement. Then it is closed automatically after the `with`-block is exited:

        with bp.openBandFile(...) as f:
          for ...:
            f.write(...)
        pass # now the file is closed.

    If multiple files are written at the same time one can do the following:

        f1=bp.openBandFile(filename1,...)
        f2=bp.openBandFile(filename2,...)
        for ...:
          f1.write(data1,...)
          f2.write(data2,...)
        f1.close()
        f2.close()
        pass # now the files are closed.

    nspin is the number of effective spins:

    > not full relativistic:

    > > - nspin=1 for non spin polarized
    > > - nspin=2 for spin polarized

    > full relativistic:

    > > - nspin=1

    nkpts is the number of k-points.

    If weightlabels is given and is a list of weight lables the resulting file will be a bandweight file.

    If progress is set to a string a progress message is written in subsequent calls to `BandFileContext.write()`.

    see help of `BandFileContext`.

  `readBands`(filename)

    Parameters: | filename (str) – name of a `+band`-type band structure file
    Returns: | (bh, kdists, kpnts, erg), see below
    Return type: | tuple

    Read the bandfile (NOT bandweight file) called filename and return (bh, kdists, kpnts, erg) where

    > bh is an instance of `BandHeader`

    > kdists is a 1d `numpy.ndarray` containing the k-path variable.

    > kpnts is a C-ordered 2d `numpy.ndarray` containing the k-vectors with dimension `[nkp,3]`.

    > erg is a 3d `numpy.ndarray` of energies, which is C-orderd, meaning that the last dimension is the innermost dimension. The three dimensions are `BandHeader.nspin`, `BandHeader.nband` and `BandHeader.nkp`.

  `on`()

    Activate bandstructure creation.

  `off`()

    Deactivate bandstructure creation.

  `setOutputRestrictions`(active, ewindow=[-20, 20], offset=[0, 0])

    Parameters: | active (int) – restrictions are active ewindow (sequence (list,tuple,..)) – a `float` `list`: [emin,emax] offset (sequence (list,tuple,..)) – an `int` `list`: [lower,upper]

    Convenience function: To reduce the size of the resulting files output restrictions can be set. If active (equivalent to `outputpartoccubands`) is `True`, ewindow determines the energy interval of bands which are considered for output. This is a relatively crude algorithm, which usually only checks the band energies at the first point of the path. If more bands are needed it is often easier to additionally define a lower and upper band index offset (`partoccuoffset`) which widens the interval of considered band indices. Positive numbers for both lower and upper offset make the interval wider. Negative numbers make it narrower. Be carefull with these restrictions you might remove bands from the output without realizing it!

  `active`

    Make band structure routines active.

  `ndiv`

    Maximum number of points between two high symmetry points along the path in the Brillouin zone. The actual number in a path segment is adjusted such that the individual points are placed as equidistant as possible.

  `lowerdepthdatalimit`

    Limit the weight data written to files to the layers with `depth<=lowerDepthDataLimit` measured from the lower end of the finite (two-sided) slab. Beware that the default for both (lower/upper) limits is 1.0e30. So, if only one side’s datalimit is set the other side’s limit likely will still be big enough to enable all layers. Simply put, define both limits unless it is a semislab.

  `upperdepthdatalimit`

    Limit the weight data written to files to the layers with `depth<=upperDepthDataLimit` measured from the upper end of the finite (two-sided) slab or semi-finite (one-sided) semislab. Beware that the default for both (lower/upper) limits is 1.0e30. So, if only one side’s datalimit is set the other side’s limit likely still will be big enough to enable all layers. Simply put, define both limits unless it is a semislab. For semislabs the upperdepthdatalimit determines which layers are used for the spectral density.

  `outputpartoccubands`

    See `setOutputRestrictions()`

  `partoccuoffset`

    See `setOutputRestrictions()`

  `ewindow`

    See `setOutputRestrictions()`

  `points`

    A list of high symmetry points. Example:

        bp.points=[
            ['$~G' , [0,0,0] ],
            ['X' , [0.5,0,0] ],
             ... ]
        print bp.points

  `kpnts`

    Return a `numpy.ndarray` of the k-points along the path. The first index runs over the k-points. The number of points in each segment is proportional to the length of the intervall. The max number is `ndiv`.

  `kdists`

    Return a `numpy.ndarray` of the scalar path-length variable along the path.

## BandHeader

class `BandHeader`

  The class is returned by `BandPlot.readBands` or `BandWeights.readBandWeights` and contains information about the header information in fplo `+band` or `+bweights` like files.

  `__str__`()

    return printable representation. You do not need to call this explicitly. An object obj with this function provides usefull info when printed:

        print(obj)

  `nkp`

    The number of k-points.

  `nband`

    The number of bands.

  `nspin`

    The number of spins (full-relativistic – 1, otherwise – 1 or 2).

  `norb`

    The number of weights (if present)

  `ilower`

    The index of the lowest band present in the data.

  `iupper`

    The index of the highest band present in the data.

  `labels`

    A list of labels.

## BandWeights

class `BandWeights`(infile)

  Use this to sum up weights contained in a bandweigths file or to read the content of a weights file into `numpy` arrays. The resulting weigths will be written to another bandweights file.

  Example:

      import pyfplo.common as com
      wds=com.WeightDefinitions()
      # add a new state (a single sum of certain weights)
      w=wds.add(name="all")
      # add labels
      w.addLabels(labels=["Al(001)3s+0","Al(001)3p-1","Al(001)3p+0",
                          "Al(001)3p+1"],fac=1)
      # or add via orbital info, if the bandweights file contains
      # default weight labels.
      w.addAtoms(atom='Al',sites=[1],orbitals=['3s','3p'],fac=1)

      print wds # want see what we did

      # read a bandweights file (more general file example)
      bw=com.BandWeights("+bweights")
      # add weights and write to +bwsum
      bw.addWeights(wds,'+bwsum')

  For further information see: `WeightDefinitions` and `WeightDefinition`

  `BandWeights(infile)` creates a new `BandWeights` object with the input bandweights file name set to the string infile.

  `header`()

    Returns: | header information
    Return type: | `BandHeader`

    Return the header information of the underlying file.

  `addWeights`(weightdefs, outfile, ewindow=[], vlevel=100)

    Parameters: | weightdefs (`WeightDefinitions`) – the definitions for the resulting weights. outfile (str) – the name of the output file with resulting weights. ewindow (sequence (list,tuple,..)) – optional, `list of two `float`: `[emin,emax]`: the energy interval to which to restrict the output bands vlevel (int) – optional: verbosity level.

    Take state definitions for resulting weights from the weightdefs (instance of `WeightDefinitions`) which is similar to the definitions in the file `=.addwei` for `faddwei...` and create a new weights file outfile, with the weights added up according to the weightdefs.

    Restrict number of bands in outfile according to the energywindow ewindow.

  `readBandWeights`()

    Returns: | (bh, kdists, erg, wei), see below
    Return type: | tuple

    Read the bandweights file given as argument to `BandWeights` and return (bh, kdists, erg, wei) where

    > bh is an instance of `BandHeader`

    > kdists is a 1d `numpy.ndarray` containing the k-path variable.

    > erg is a 3d `numpy.ndarray` of energies, which is C-orderd, meaning that the last dimension is the innermost dimension. The three dimensions are `BandHeader.nspin`, `BandHeader.nband` and `BandHeader.nkp`.

    > wei is a 4d `numpy.ndarray` of energies, which is C-orderd, meaning that the last dimension is the innermost dimension. The four dimensions are `BandHeader.nspin`, `BandHeader.nband`, `BandHeader.norb` and `BandHeader.nkp`.

    This function does not return the list of k-vectors, since these are not part of the weights file. If you need them and have a corresponding band file you could get them from there via `BandPlot.readBands`.

## WeightDefinitions

class `WeightDefinitions`

  Helper class to collect input for `BandWeights.addWeights()` or for usage in some `Slabify` routines. This is the python equivalent of `faddwei...`.

  Example:

      import pyfplo.common as com
      wds=com.WeightDefinitions()
      # get a new state
      w=wds.add(name='all')
      # add labels
      w.addLabels(labels=['Al(001)3s+0','Al(001)3p-1','Al(001)3p+0','Al(001)3p+1'],fac=1)
      # or add via orbital info
      w.addAtoms(atom='Al',sites=[1],orbitals=['3s','3p'],fac=1)

      print wds
      bw=com.BandWeights('+bweights')
      bw.addWeights(wds,'+bwsum')

      #fictitious more efficient example

      wds=com.WeightDefinitions()
      w=wds.add('plaquette')\\
         .addAtoms('Cu',[9,10],['3d'])\\
         .addAtoms('O',[1,2],['2p'])

  For further information see `WeightDefinition` and `BandWeights`

  `WeightDefinitions()` creates a new `WeightDefinitions` object.

  `add`(name='')

    Parameters: | name (str) – name of the new weight sum (`WeightDefinition`)
    Returns: | a new weight definition
    Return type: | `WeightDefinition`

    Add a new state definition (weight sum) called name to the collection of states and return an instance of `WeightDefinition`, which can be used to add specific input weights.

  `__str__`()

    return printable representation. You do not need to call this explicitly. An object obj with this function provides usefull info when printed:

        print(obj)

## WeightDefinition

class `WeightDefinition`

  This collects information for a single weight (state) definition. This object cannot be created directly. Rather it is returned by `WeightDefinitions.add()`.

  `addLabels`(labels, fac=1)

    Parameters: | labels (list of str) – a list of existing weight labels (as found in the input bandweights file header) fac (float) – the weights enter the weight sum with this factor
    Returns: | current instance of WeightDefinition
    Return type: | `WeightDefinition`

    This routine adds the labels to the current `WeightDefinition` and returns the current instance of `WeightDefinition`, in order to allow constructions like:

        w.addLabels(...)\
         .addAtoms(...)

  `addAtoms`(atom, sites, orbitals, fac=1, spin='')

    Parameters: | atom (str) – element name sites (sequence (list,tuple,..)) – list of site numbers (`int`) orbitals (list of str) – list of orbitals (e.g. ‘3d’ or ‘3d+1’ or ‘3d5/2-1/2’ or ‘all’) fac (float) – the weights enter the weight sum with this factor. spin (str) – ‘up’, ‘dn’, or ‘both’
    Returns: | current instance of WeightDefinition
    Return type: | `WeightDefinition`

    Defines a set of single orbital weights to be added to this state. Note, that in the full relativistic case spin must be specified if the orbitals in the input weight file refer to pseudo non-relativistic symmetries (e.g. ‘Pt(001)5d+1 up’).

    It returns the current instance of `WeightDefinition`, in order to allow constructions like:

        w.addAtoms(...)\
         .addAtoms(...)\
         .addLabels(...)

  `__str__`()

    return printable representation. You do not need to call this explicitly. An object obj with this function provides usefull info when printed:

        print(obj)

## OptionSet

class `OptionSet`

  A collection of options for debugging output. This class cannot be instantiated directly. It only is returned from objects, which have an `OptionSet` member variable (see `Slabify.options`). Example usage:

      s=sla.Slabify()
      op=s.options # a possible way to get an OptionSet object

      print op # print the option list including their values
      print op.names # print the available option names

      for n in op.names:  # python loop for option print
          print n,op[n]

      for n in op.names:  # python loop to set all options
          if n.startswith('prep'):
              op[n]=True

      # or let us suppose there is an option called prep_pairs

      op['prep_pairs']=True

  `__getitem__`(self, n)

    Parameters: | n (`str`) – option name

    Return the value of the option n as `int`:

        op=s.options # just an example
        print op['some_option_name']

  `__setitem__`(self, n, value)

    Parameters: | n (`str`) – option name value (`int` ot `bool`) – the options value (on or off)

    Set the value of the option called n:

        op=s.options # just an example
        op['some_option_name']=True

  `__str__`()

    return printable representation. You do not need to call this explicitly. An object obj with this function provides usefull info when printed:

        print(obj)

  `names`

    Return a list of available options:

        s=sla.Slabify()
        op=s.options # just an example
        print op.names

## Site

class `Site`

  A list of instances of this class is returned by `pyfplo.slabify.Slabify.layerSites` or `pyfplo.fploio.OutGrep.sites`.

  `__str__`()

    return printable representation. You do not need to call this explicitly. An object obj with this function provides usefull info when printed:

        print(obj)

  `element`

    the atom name

    Type: | `str`

  `type`

    the atom’s type

    Type: | `int`

  `sort`

    the atom’s sort (Wyckoff position)

    Type: | `int`

  `tau`

    the position of the atom

    Type: | `3-vector`

## Watch

class `Watch`(name, decimals=2)

  Measure time with this or print progress reports.

  Example:

      import pyfplo.common as com

      nk=100
      wa=com.Watch('task').setProgress(nk,0.02)
      for ik in range(nk):
          wa.printProgress(ik)
          do_something()
          if ik%50 == 0: print(wa.status('50 steps done'))

      print(wa.status('total'))

  Parameters: | name (str) – a name for the task decimals (int) – how many decimals of time to print

  `stop`()

    Returns: | self to allow call chaining as in `Watch.stop(...).setSomethingElse(...)`
    Return type: | `Watch`

    Halt the clock.

  `go`()

    Returns: | self to allow call chaining as in `Watch.go(...).setSomethingElse(...)`
    Return type: | `Watch`

    Let it run/continue.

  `reset`()

    Returns: | self to allow call chaining as in `Watch.reset(...).setSomethingElse(...)`
    Return type: | `Watch`

    Reset the clock to zero.

  `status`(txt='total', prefix='', suffix='')

    Parameters: | txt (str) – some additinal information prefix (str) – some additinal information suffix (str) – some additinal information
    Returns: | status – a printable version of the ellapsed time
    Return type: | `str`

    Return a printable string of the time which ellapsed while the clock was running (not stopped).

  `setProgress`(steps, delta=0.1)

    Parameters: | steps (int) – total number of steps in the taks to be progrss reported on delta (float) – print progress information if this amount of time of the estimated total has passed. `delta=0.1` means every 10%.
    Returns: | self to allow call chaining as in `Watch.setProgress(...).setSomethingElse(...)`
    Return type: | `Watch`

    Set the parameters of a progress report.

  `printProgress`(istep, prefix='\t', text='', suffix='')

    Parameters: | istep (int) – the current step of the running task prefix (str) – some additional info text (str) – some additional info suffix (str) – some additional info

    Print the progress with an estimate of the total time needed to complete the task.

## Version

class `Version`

  This class manages the version numbers of pyfplo. The easiest use is:

      import pyfplo.common as com
      ...
      print 'pyfplo version ',com.version
      # one can protect scripts in the following way:
      if com.version!='22.00': raise RuntimeError('pyfplo version is incorrect.')

  version is also bound as a module variable in `pyfplo`, `pyfplo.slabify` and `pyfplo.fploio` such that the example above could read:

      import pyfplo.slabify as sla
      ...
      print 'pyfplo version '+str(sla.version)
      # one can protect scripts in the following way:
      if sla.version!='22.00': raise RuntimeError('pyfplo version is incorrect.')

  `release`()

    Returns: | release number
    Return type: | str

  `mainVersion`()

    Returns: | main version number
    Return type: | str

  `__eq__`()

    Compare the main version (for code sanity purposes). Example:

        if com.version!='22.00': raise RuntimeError('pyfplo version is incorrect.')

  `__ne__`()

    Compare the main version (for code sanity purposes). Example:

        if com.version!='22.00': raise RuntimeError('pyfplo version is incorrect.')

  `__str__`()

    return printable representation. You do not need to call this explicitly. An object obj with this function provides usefull info when printed:

        print(obj)

## Vlevel

class `Vlevel`

  This class merely defines the verbosity level constants (Silent, Info,…, All). You can use any int where ever a vlevel is needed as an argument. For an arbitrary int N as argument the actual vlevel is set to the largest constant (defined below), which is <= N or to 0 (Silent) if int<0; One can use the constants:

      print com.Vlevel.All

  `Silent` = 0
  `Info` = 100
  `More` = 200
  `Many` = 300
  `All` = 1000

## Constants

A collection of physical constants.

`c_abtoang`

  Bohr radii / Angstroem

`c_hatoev`

  Hartree/eV

`c_speed_of_light_mpers`

  speed of light in m/s

`c_hbar_Js`

  Planck constant/2pi in Js

`c_me_kg`

  electron mass in Kg

`c_angstroem_m`

  angstroem in m

`c_echarge_C`

  electron charge in C

`c_elements`

  all elements

Predefined:

`version`

  instance of `Version`