pyfplo.fploio

This module contains the parser interface to read data from =.in type files. It can also be used to change data in the file. WARNING: it is better to use pyfplo.fedit for changing input. The fedit interface is kept reasonably clean, while the naming conventions in =.in which is accessed directly by the parser is at times chaotic. Furthermore, there are semantic dependencies in the file, as e.g. descriptors which are for readability only. If the user changes the underlying value but not the descriptor the idea of having descriptors is lost. Furthermore, there are data which depend on the symmetry. fedit takes care of all of that.

Please note, that the underlying data representation is in str format. This allows to use '1/3' insted of 0.33333... for real values. Hence, the natural return value of the data is str. If however an explicite int or float representation is wanted and if the type of the specific data conforms to these types an int value is returned by PObj.L and a float by PObj.D.

Logicals are handled as 'f' or 't' internally. Hence, PObj.S returns these values. However, if returned by PObj.L, True and False are represented by 1 or 0 respectively. When writing a logical via PObj.S 't', 'T' and '+' are considered to be True any other string as False. When writing a logical via PObj.L 0 and any nonzero int represent False and True, respectively.

Character variables defined as ‘char some_char=’x’; ‘ in the =. file (which are not used currently) are returned as str by PObj.S and as int by PObj.L. The latter interpretation is machine dependend and not recommended. Similarily, the variable can be written in both ways.

fploExecutable(suffix='')
Parameters:suffix (str) – for convenience, suffix is appended to the exec name

Return the name of the fplo executable as str, which fits the pyfplo version. This is an educated guess. There is no garantee that it is correct. If you compiled with a non-default build branch, this function does not return the name including the build branch suffix but just the generic name. Use suffix to select the correct executable or just write it out explicitely anyway.

INParser

class INParser

This class is a low-level class for reading the =.in files. For manipulating =.in use the pyfplo.fedit class. This is safer, since it ensures data (semantics) consistency.

To see how to use some of the low-level routines consult Reading =.in files, Write =.in with low level routines and =.files to json.

Create an instance of the FPLO parser for files of type =.in in the following way:

import pyfplo.fploio as fploio
p=fploio.INParser()
parseFile(filename)
Parameters:filename (str) – the filename of an existing file in FPLO =.-format

This opens and reads the file given in filename. Safe use:

import os
import pyfplo.fploio as fploio
p=fploio.INParser()
if not os.path.exists('=.in'):
  raise RuntimeError('cannot find the file')
try:
  p.parseFile("=.in")
except RuntimeError,ex:
  print(ex)
  pass # do whatever to handle the error or quit the program
writeFile(filename)
Parameters:filename (str) – the filename of the new file in FPLO =.-format

Write the parser content to a file called filename.

__call__()

Return the root of the data tree. The returned object is an instance of class PObj, which can be used to access individual data.

varExists(varname)
Parameters:varname (str) – the name of the queried variable
Returns:existence of variable definition
Return type:bool

Check if a variable definition exists in the parse table. Return True if it does. This function tests the struct array definition not the actual elements. Example:

d=p() # p is a INParser object and d is parser root
d2=d('wyckoff_positions')# d2 is node wyckoff_positions (struct array)
print d2[0].varExists('element') # -> True
print d.varExists('wyckoff_positions.element') # -> False   but
print p.varExists('wyckoff_positions.element') # -> True
#also
print d.varExists('wyckoff_positions[1].element') # -> True
print d('wyckoff_positions')[1].varExists('element') # -> True

Compare this to PObj.varExists.

PObj

class PObj

This class is a low-level class for reading the =.in files. For manipulating =.in use the pyfplo.fedit class. This is safer, since it ensures data (semantics) consistency.

To see how to use some of the low-level routines consult Reading =.in files, Write =.in with low level routines and =.files to json.

Usually PObj instances are returned by other methods. One does not create a PObj by itself.

fullName()

Return the full node name. This includes element access (e.g. nkxyz[3]).

varExists(varname)
Parameters:varname (str) – the name of the queried variable
Returns:existence of variable definition
Return type:bool

Check if a variable exists under the current node. Return True if it does. This function tests struct array elements in detail. Example:

d=p() # p is a INParser object and d is parser root
d2=d('wyckoff_positions')# d2 is node wyckoff_positions (struct array)
print d2[0].varExists('element') # -> True
print d.varExists('wyckoff_positions.element') # -> False   but
print p.varExists('wyckoff_positions.element') # -> True
#also
print d.varExists('wyckoff_positions[1].element') # -> True
print d('wyckoff_positions')[1].varExists('element') # -> True

Compare this to INParser.varExists.

size(dim=1)
Parameters:dim (int) – dimension
Returns:size of the dimension
Return type:int

If PObj is array-like return its size`

For struct arrays and rank-one arrays size() returns the array size.

For rank>1 arrays size(dim) returns the size of the dim-th dimension.

sizes()
Returns:a list of all array sizes, such that rank==len(n.sizes())
Return type:list of int
resize(size)
Parameters:size (int or list) – can be a scalar int or a list of int in case of multidimensional arrays.

If PObj is an array or struct array, resize it. Note, that for multidimensional arrays only the last dimension can be resized in the moment. But =.in does not use multidimensional arrays. (=.dens does though, which however should not be touched.)

__call__(name)
Parameters:name (str) – name of the node

Return a new PObj which references the node called name under the current PObsparse tree node:

d=p() # parse tree root
ds=d('spin')
print ds('mspin').L

Compound names are possible:

d=p() # parse tree root
print d('spin.mspin').L
__getitem__(*args)

If the node pointed to by PObj represents a 1d array type the operator [i] returns the PObj, which represents the i-th element. For flag arrays the operator [flagname] returns the PObj, which represents this flag (if it exists). Use S to print the full flag name and use L to read or set the flags value. If PObj represents a multidimensional array (up to 5d) the operator [i,j,...] returns the corresponding PObj of the element.

args can be:

index1, index2,…: between one and five int indices:

dw2=d('wyckoff_positions')[2]

flagname: a single str which names a flag in a flag array:

d('options')['FULLBZ'].L=True
name()

Return the node name. This excludes element access (e.g. nkxyz[3]).

first()
Returns:first node on the current level. See =.files to json
Return type:PObj
next()
Returns:the next node on the current level. See =.files to json
Return type:PObj
hasNext()
Returns:True if next node exists. See =.files to json
Return type:bool
isScalar()
Returns:True if node is a scalar. See =.files to json
Return type:bool
isArray()
Returns:True if node is an array. See =.files to json
Return type:bool
isStruct()
Returns:True if node is a srtuct. See =.files to json
Return type:bool
isStructArray()
Returns:True if node is a srtuct array. See =.files to json
Return type:bool
isInt()
Returns:True if node is a scalar int. See =.files to json
Return type:bool
isReal()
Returns:True if node is a scalar int. See =.files to json
Return type:bool
isLogical()
Returns:True if node is a scalar int. See =.files to json
Return type:bool
isString()
Returns:True if node is a scalar int. See =.files to json
Return type:bool
isChar()
Returns:True if node is a scalar int. See =.files to json
Return type:bool
isFlag()
Returns:True if node is a scalar int. See =.files to json
Return type:bool
__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)
listS

If PObj refers to a 1d array, return it’s elements as a list of str or assign a list of str to the array elements. On assignment to a fixed size array the list must have the proper length On assignment to a variable size array, the array is resized accordingly. One can assign a list of str to integer and real arrays as long as the list’s elements represent the correct type:

d('wyckoff_positions')[1]('tau').listD=[1./2,2./3,1./4]
d('wyckoff_positions')[1]('tau').listS=['1/2','2/3','1/4']

Note, the dot in 2./3, which is needed to have float division while in the string version it is not allowed.

listD

If PObj refers to a real 1d array, return the elements as a list of float or assign the list (see listS).

listL

If PObj refers to an integer 1d array, return is elements as a list of int or assign the list (see listS).

L

If the current node refers to an integer type, return it as int. If it refers to a flag, 1 is returned if the flag is switched on, 0 otherwise. Assignment is possible:

d('spin.mspin').L=2
D

If the current node refers to a real type, return it as float. Assignment is possible:

d('wyckoff_positions')[0]('tau')[1].D=5.4
S

The current PObj instance sits at a certain node of the data tree, depending on the history of calls, which created it.

If the current PObj instance refers to a node, which represents a single value (scalar) the value is returned as str representation.

If PObj refers to a flag the flagname followed by (+) or (-) is returned.

A new str value can be assigned to S. The user must ensure the correctness of the data, e.g. that a str representing an underlying float is actually a valid float.

Let us assume there is a real tolerance=1e-12; in =.in. Then one can set this value as:

# d is assumed to be the PObj under which the node tolerance sits.
d('tolerance').D=1e-13
# or
d('tolerance').S='1e-13'

FPLOInput

class FPLOInput(fname=None)

FPLOInput is used to manage the manipulation of =.in files. It creates new files or reads existing files. The symmetry update functionality of fedit is hidden in this class. This is a low level interface. It is strongly recommended to use pyfplo.fedit for manipulating data instead.

An example of proper usage is found in Write =.in with mid level routines.

Parameters:fname – the name of an existing =.in file or None or nothing

Create a fresh FPLOInput object via:

import pyfplo.fploio as fploio
...
fio=fploio.FPLOInput()

Create a fresh FPLOInput object and read a file and update the version, if needed, or create fresh input if the file does not exist via:

import pyfplo.fploio as fploio
...
fio=fploio.FPLOInput('=.in')

which is equivalent to the following code:

import os
import pyfplo.fploio as fploio
...
fio=fploio.FPLOInput()
if os.path.exists('=.in'):
    fio.parseInFile(True,'=.in')
else:
    fio.createNewFileContent() # make fresh content
    ... # or handle this case differently
parseInFile(forceupdate, fname='=.in', newifnonexistent=False)

Read the =. file called fname into an internal parse tree and optional update version or create fresh content. If something goes wrong an exception is raised.

Parameters:
  • forceupdate (int) – If True, convert older version files into new ones
  • fname (str) – =.in-type file name
  • newifnonexistent (int) – If True and the file called fname does not exist, create fresh content in the parse tree (does not cretae a file).
symmetryUpdate()

After changing symmetry settings call this to update the rest of the data. A message is returned.

resetNonSymmetrySections()

Reset all data in the internal parse table except for the symmetry section. This is used to reset all non symmetry data to default values.

writeFile(name)
Parameters:name (str) – filename of =.in-type file

Write the parser content to the file called fname.

structureFromCIFFile(ciffilename, wyckofftolerance=1e-06, symblockindex=0, symoptionindex=0, determinesymmetry=False, keeprotation=False)

Read the cif-file called ciffilename and import the structure data into the parse tree.

To see how to use this consult Reading cif-files.

wyckofftolerance is used to convert approximations like 0.3333 into 1/3. If the round off error (as in 0.3333) is smaller than wyckofftolerance all numbers which are approximate fractionals n/d, d in [1,12] are replaced by the fractional. This is especially necessary for hexagonal structures where an approximation like 0.3333 for 1/3 leads to trouble (doubling of atoms, missing symmetry operations and such).

Some cif files contain more than one data block. If several blocks are present and if several of these contain symmetry information symblockindex selects the corresponding symmetry block. By default symblockindex is 0, which selects the first such block. The available blocks are written to the output. An example could produce the following output:

------------------------------------------------------------------------
Blocks contained in cif file 'cg049782osi20040706_123518.cif':
------------------------------------------------------------------------
symmetry block No.   name
------------------------------------------------------------------------
                     global
     0               cu2as2o7
     1               cuasbeta
                     profile
------------------------------------------------------------------------

There are four blocks of which two contain structure/symmetry information. Possible values for symblockindex are 0 or 1.

In principle it is possible that a symmetry containing block has contradicting group information. Often the cif files contains a Hall-symbol, the xyz-operation symbol table and the space group number (or combinations of these). The space group number is not a good indicator, since it does not encode settings. Hence, we analyse the Hall- and xyz-symbols to determine the group. Only if both are missing we rely on the space group number. If, however, Hall- and xyz-symbols lead to different groups (rare but possible), we can select, which of the two to use. The possible symmetry options are written to the output and symoptionindex selects the corresponding option. By default symoptionindex is 0, which selects the first such option. The output of symmetry options could look like this:

Symmetry information for datablock: data_1
Space group number: 227
Name-Hall         : F 4d 2 3 -1d
xyz-symbol        :  gives hallsymbol -F 4vw 2vw 3

Hall symbol: OK
xyz symbols: OK but not equivalent

The following symmetry options are available:
  0 'Hall symbol'
  1 'xyz-symbols'

You can see that the xyz symbols give a different setting than the Hall symbol. Hence, we have to chose symoptionindex from 0 or 1. You also understand that 227 is not a complete description.

If determinesymmetry is True the cif data are symmetry analysed before creating =.in.

If determinesymmetry is True and keeprotation is True the orientation of the cell is retained during symmetry analysis.

A possible way of importing a cif file works like this:

import pyfplo.fploio as fploio
import pyfplo.fedit as fedit

fio=fploio.FPLOInput('=.in')
fio.structureFromCIFFile('data.cif',wyckofftolerance=1e-4,
   symblockindex=0,symoptionindex=0)
fio.writeFile('=.in') # now we have created or update =.in from the cif file

fed=fedit.Fedit(recreate=True) # reset default input (except symmetry)
fed.iteration(n=100) # ... and more settings
fed.pipeFedit() # apply the settings
reset()

Reset the internal parse tree to nothing. The resulting FPLOInput object is like a newly created one.

createNewFileContent()

Create a completely new default file in the internal parse tree.

parser()
Returns:the underlying INParser
Return type:INParser

OutGrep

class OutGrep(outfilename='out', dir='.')

OutGrep helps to grep results from fplo output files directly into python variables.

Parameters:
  • outfilename (str) – the name of the fplo output file
  • dir (str) – the directory in which it sits

This reads the whole output file, so that using grep in a loop is more efficient.

  • Example: grep last total energy and gap:

    import pyfplo.fploio as fploio
    ...
    og=fploio.OutGrep('out')
    print('etot=',og.grep('EE')[-1],', gap=',og.grep('gap')[-1])
    
  • Example: show iteration progress:

    import os
    import pyfplo.fploio as fploio
    ...
    og=fploio.OutGrep('out')
    with open('res','w') as fh:
        res=og.grep('it')
        for i,r in enumerate(res):
            fh.write('{} {}\n'.format(i,r))
    os.system('xfbp res')
    
  • Example: grep all atom spins (as a function of iteration) and write them to file res:

    import os
    import pyfplo.fploio as fploio
    og=fploio.OutGrep('out')
    si=og.sites()
    
    with open('res','w') as fh:
        for i,s in enumerate(si):
            site=i+1
            res=og.grep('SSat',site)
            fh.write('# {}{}\n'.format(s.element,site))
            for it,r in enumerate(res):
                fh.write('{} {}\n'.format(it,r))
            fh.write('\n')
    os.system('xfbp res')
    

More exmples in Extract =.basdef from output file

modes
Type:dict of mode:long-name

class variable of all available OutGrep modes as in grepfplo -h

for k in fploio.OutGrep.modes.keys():
    print('mode: {0:15s} : {1}'.format(k,fploio.OutGrep.modes[k]))
sites()

return a list of pyfplo.common.Site, which contains info for sites in output file.

grep(mode, site=1, orbital=0)
Parameters:
  • mode (str) – one of the modes defined as keys in dict OutGrep.modes
  • site (int) – some modes need a site number (one-based, as in fplo output)
  • orbital (int) – some modes (population analysis modes) need an orbital number. orbital is the one-based number of the wanted orbital in the order as printed in the population analysis. If orbital is out of range (e.g. 0) the total site population number is printed. For the mode N_gros there is one more number than for N_net and S_..., which is the number of excess electrons of the site.

return a list of str of mode-dependend results for all iterations found in the output file. Some modes return a single result since it is not iteration dependend. If you need float results, convert like float(og.grep('EE')[-1]) or list(map(float,og.grep('EE'))).

See, examples under OutGrep.

Basis

class Basis(version=None, elementsoratomicnumbers=None, basdeffile=None)

Basis gives a low-level access to the basis definition. The basic operations are:

  • Create a default basis for all sorts via input: basis-version + list of elements/atomic numbers.
  • Optionally, read basis definitions from =.basdef (overwrites the default).
  • Modify the basis thusly obtained.
  • Write file =.basdef.

Consequently, at minimum one needs to know the list of elements. See examples Extract default basis into =.basdef and User defined basis (in =.basdef). If a =.in already exists one can obtain this list via:

import pyfplo.common as com
import pyfplo.fploio as fploio
p=fploio.INParser()
p.parseFile('=.in')
d=p()('wyckoff_positions')
elements=[d[i]('element').S for i in range(d.size())]
# optionally:
atomicnumbers=list(map(lambda x: com.c_elements.index(x),elements))
print(elements)
print(atomicnumbers)

To create an FPLO9 default basis in =.basdef do this:

import pyfplo.fploio as fploio
...
b=fploio.Basis('default FPLO9 basis',elements)
# modify b if needed, then
b.writeFile('=.basdef')

To read and modify =.basdef do this:

import pyfplo.fploio as fploio
...
b=fploio.Basis('default FPLO9 basis',elements,basdeffile='=.basdef')
# modify b if needed, then
b.writeFile('=.basdef')

Note

Note, that you always need to provide the default version and the element/atomic number list, because some adjustments take place internally based on the elements.

Parameters:
  • version (int or str) – ID (int) or unique search string (case sensitive) into version table. The version table is obtained via the class variable pyfplo.fploio.Basis.versions, which is a list of available basis versions, where each list member has two members: a unique ID (int) and a str, which can be used for searching.
  • elementsoratomicnumbers (list of str and/or int) – list of element names or atomic numbers for each sort
  • basdeffile (str or None) – read (and overwrite default) from file basdeffile if not None!
versions

class variable of all available Basis versions

Type:list of 2-lists of structure [ID,versionname]
writeFile(filename='=.basdef')
Parameters:filename (str) – the basis definitions file name. For use with fplo this needs to be =.basdef.

Write the basis definitions to file filename.

__getitem__()

basis[i] returns basis (BasDef) of sort i

BasDef

class BasDef

BasDef contains the basis of a particular atom. This class is return by pyfplo.fploio.Basis.__getitem__ and cannot be instantiated otherwise.

__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)
core
semicore
valence

BasDefSection

class BasDefSection
append(nl, Q=None, P=None, S=None)
Parameters:
  • nl (str) – multiorbital name, e.g. '3d'
  • Q (float or list of float-s) –
  • P (float or list of float-s) –
  • S (float or list of float-s) –

append a double 4f-orbtial like D4f Q=(q1,q2) P=(p1,p2) via:

basdef.valence.append('4f',Q=[q1,q2],P=[p1,p2])

or a single 4f-orbtial like s4f Q=(q1) P=(p1) via:

basdef.valence.append('4f',Q=q1,P=p1)
remove(i)
Parameters:i (int) –
__len__()

len(b) returns the size of the Basis section (number of multi-orbitals).

__getitem__()

BasDefSection[i] returns the i-th MultiOrbital

__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)

MultiOrbital

class MultiOrbital

This class is return by pyfplo.fploio.BasDefSection.__getitem__ and such

append(Q=0.0, P=1.0, S=0.0)
Parameters:
  • Q (float) –
  • P (float) –
  • S (float) –
removeLast()
removeFirst()
qns(mult)
Parameters:mult (int) –
Returns:
Return type:str
Q(mult)
Parameters:mult (int) –
Returns:
Return type:float
S(mult)
Parameters:mult (int) –
Returns:
Return type:float
P(mult)
Parameters:mult (int) –
Returns:
Return type:float
set(mult, Q=None, P=None, S=None)
Parameters:
  • mult (int) –
  • Q (float or None) –
  • P (float or None) –
  • S (float or None) –
__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)
name
multiplicity

Data

For convenience:

version

copy of pyfplo.common.version

Version

copy of pyfplo.common.Version

c_elements

copy of pyfplo.common.c_elements