AKFReader

The AKFReader Python class provides a convenient way to read annotated data from the binary KF files generated by AMS.

Below is an example demonstrating some of the AKFReader class’s functionality

#!/usr/bin/env amspython

from scm.akfreader import AKFReader

# Load a kf file.
akf = AKFReader("test.results/dftb.rkf")


# Print a summary of the content in the kf file:
print(akf.table_of_content())

# Also print comments and extra info for all variables
print(akf.table_of_content(verbose=True))


# Read a specific variable from file.
coordinates = akf.read("Molecule%Coords")
print("Coordinates:")
print(coordinates)

# Coordinates:
# [[-1.65367945e+00  4.59827802e+00 -9.59515212e-09]
#  ...
#  [-2.21256221e+00  5.05007997e+00 -1.93285786e+00]]


# Retrieve the description, units, and additional information for a variable:
description_dict = akf.description("Molecule%Coords")
print("'Molecule%Coords' description:")
print(description_dict)

# 'Molecule%Coords' description:
# {'_type': 'float_array',
#  '_shape': [3, 'nAtoms'],
#  '_comment': 'Coordinates of the nuclei (x,y,z)',
#  '_unit': 'bohr'}


# Read another variable, and do a unit conversion:
energy_in_eV = akf.read("AMSResults%Energy", units="eV")
print(f"Energy: {energy_in_eV} [eV]")


# Read all variables matching the pattern:
history_energies = akf.read("History%Energy(#)")
print(history_energies)

# [('History%Energy(1)', -5.758015498298242),
#  ('History%Energy(2)', -5.765039556660788),
#  ('History%Energy(3)', -5.766261662994689),
#  ('History%Energy(4)', -5.766288141072665)]

Note

The KFFile Python class can also be used to read KF files. Key differences between the AKFReader and the KFFile:

  • The AKFReader can provide ‘extra information’ on the content of the KF files: it can give descriptions of sections, variables, units, and automatically reshapes matrices to the proper size/shape.

  • The KFFile can also be used to write KF files (while the AKFReader can only read).

See also

A command line utility $AMSBIN/akf (described here) offers an alternative way of using the AKFReader tool.

See also

The list of possible variables for the various kf files can be found in the respective user manuals: ams.rkf, adf.rkf, band.rkf, dftb.rkf

API documentation:

class AKFReader(path: str, kf_def_path=None, strict=False, verbose=False)

A python class for reading AMS binary KF files.

Parameters:
  • path (str): the path of the KF file (.rkf) to open. Can be wither relative or absolute path. (the other optional constructor parameters are expert options and are best left untouched)

Example:

from scm.akfreader import AKFReader

akf = AKFReader("test.results/dftb.rkf") # <- path to ams .rkf result file

print(akf.table_of_content())

coordinates = akf.read("Molecule%Coords")
energy = akf.read("AMSResults%Energy", units="eV")
read(name: str, units=None)

Read and return the value of a variable on file.

Parameters:
  • name (str): The name of the variable to read. This should be of the form “SectionName%VariableName”, so for example akf.read(“Molecule%Coords”) means “read the variable ‘Coords’ from Section ‘Molecule’)

  • units (str): the desired output units. See the :Units: class for more info on avaiable units.

Returns:
  • The content of the variable. The return type depends on the variable you are reading. So, if the variable is an integer, and int will be return. If it’s an array, a numpy array will be returned.

Example:

>>> energy = akf.read("AMSResults%Energy")
>>> energy_in_eV = akf.read("AMSResults%Energy", units="eV")

Note: in case the variable is a “pattern” (i.e. the variable name contains “#” or “*” characters, the result will be a list of tuples of all variables matching the pattern. E.g.: ‘foo(#)’ will return [(‘foo(1)’, value1), (‘foo(2)’, value2)]

table_of_content(verbose=False) str

Returns the table of content of the KF file (i.e. the list of all sections and variables on file) in text format.

Parameters:
  • verbose (bool): if verbose is True, the full description of all variables will be included

Example:

>>> print(akf.table_of_content())

Content for KF file: /test/dftb.rkf

== AMSResults ==

    - AMSResults%Energy
    - AMSResults%Gradients
    - AMSResults%DipoleMoment
    ...

>>> print(akf.table_of_content(verbose=True))

Content for KF file: /test/dftb.rkf

== AMSResults ==

    comment   : Generic results of the DFTB evaluation.
    type      : section

    - AMSResults%Energy
        comment   : The energy computed by the engine.
        type      : float
        unit      : hartree

    - AMSResults%Gradients
        comment   : The nuclear gradients.
        shape     : [3, 'Molecule%nAtoms']
        type      : float_array
        unit      : hartree/bohr

    - AMSResults%DipoleMoment
        comment   : Dipole moment vector (x,y,z)
        shape     : [3]
        type      : float_array
        unit      : e*bohr
    ...
variables(include_hidden=False) List[str]

Returns the list of all variables on the KF file (in the form “section%variable”).

Example:

>>> all_variables = akf.variables()
>>> print(all_variables)

['AMSResults%Charges',
'AMSResults%DipoleMoment',
...
...
'Orbitals%Energies(#)'
'Orbitals%Occupations(#)']
sections() List[str]

Returns the list of all sections on the KF file.

Example:

>>> print(akf.sections())

['General', 'AMSResults', 'Molecule', 'Orbitals', ...]
variables_in_section(section: str) List[str]

Returns the list of all variables in the specified section.

Example:

>>> print(akf.variables_in_section("Molecule"))

['Molecule%AtomMasses', 'Molecule%Coords', 'Molecule%AtomicNumbers', ...]

>>> for v in akf.variables_in_section("Molecule"):
>>>     print(f"{v}: {akf.read(v)}")
__contains__(name: str)

Whether or not ‘name’ is present in the KF file. This can either be a section (e.g. “Molecule”) or a variable (e.g. “Molecule%Coords”) Example:

if "Molecule%Coords" in akf:
    coords = akf.read("Molecule%Coords")
else:
    print("Variable 'Molecule%Coords' not present of file")
    print("Is the 'Molecule' section present? ", "Molecule" in akf)
description(name: str) Dict[str, Any]

Return the description (meta-data) of the variable as a dictionary.

Parameters:
  • name (str): The name of the variable (this should be in the form “Section%Variable”)

Returns:
  • dictionary containing the available meta-data for the entry. Note that not meta-data entries are defined for all variables. For example, if a variable does not have a unit, the “_unit” key will not be present in the resulting dictionary

Example:

>>> d = akf.description("Molecule%Coords")
>>> print(type(d))

<class 'dict'>

>>> print(d)
{'_type': 'float_array',
 '_shape': [3, 'nAtoms'],
 '_comment': 'Coordinates of the nuclei (x,y,z)',
 '_unit': 'bohr'}
str_description(name: str) str

Return the description of the variable as a string.

Example:

>>> print(akf.str_description("Molecule%Coords"))

comment   : Coordinates of the nuclei (x,y,z)
shape     : [3, 'nAtoms']
type      : float_array
unit      : bohr
units(name: str) str | None

Return the unit of measurement of the variable if specified, otherwise returns None.