tesliper.writing.writer_base

Interface for witing data to disk.

This module contains writer() factory function that enables to dynamically create a writer object that’s responsible for saving data in a desired output format. writer() instantiates a subclass of WriterBase, an Abstract Base Class also defined here. WriterBase provides an interface for all serial data writers (objects that export conformers’ data to multiple files) used by tesliper.

WriterBase expects it’s subclasses to provide an extention class attribute, which is used as an extension of files produced by this particular writer, and also as an identifier for the output format, used by the writer() factory function. tesliper is shipped with four such writers: TxtWriter for writting to .txt files, CsvWriter for writting in CSV format, XlsxWriter for creating Excel files, and GjfWriter for preparing Gaussian input files.

You may want to export your data to other file formats - in such case you will need to implement your own writer. To do this, subclass WriterBase, provide it’s extension as mentioned above, and implement writing methods for data you intend to support in your writer. The table below lists these methods, along with a brief description and DataArray-like object, for which the method will be called by writer’s write() method.

Methods used by default to write certain data

Writer’s Method

Description

Associated array

generic()

Generic data: any genre that provides one value for each conformer.

DataArray, IntegerArray, FloatArray, BooleanArray, InfoArray.

overview()

General information about conformers: energies, imaginary frequencies, stoichiometry.

Energies

energies()

Detailed information about conformers’ relative energy, including calculated populations

Energies

single_spectrum()

A spectrum - calculated for single conformer or averaged.

SingleSpectrum

spectral_data()

Data related to spectral activity, but not convertible to spectra.

SpectralData

spectral_activities()

Data that may be used to simulate conformers’ spectra.

SpectralActivities

spectra()

Spectra for multiple conformers.

Spectra

transitions()

Electronic transitions from ground to excited state, contributing to each band.

Transitions

geometry()

Geometry (positions of atoms in space) of conformers.

Geometry

Note

These methods are not abstract methods, but will still raise a NotImplementedError if called. This is to let you omit implementation of methods you don’t need or wouldn’t make sense for the particular format and still provide an abstract interface. tesliper takes advantage of this in it’s implementation of GjfWriter, which only implements geometry() method, because export of, e.g. a calculated spectrum as a Gaussian input would be pointless.

Writer object decides which of these methods to call based on the type of each DataArray-like object passed to the write() method. For some of them, it also passes additional DataArray-like objects, referred to as extras, e.g. correspomding Bands for spectral data. See documentation for particular method to learn, which of its parameters are mandatory, which are optional, and which should expect None as a possible value of extra.

When implementing one of these methods in your writer, you should take care of opening and closing file files, formatting data you export, and writing to the file. For the first part you may use one of the helper methods that provide a ready-to-use file handles: _iter_handles() for writing to many files in batch or _get_handle() for writing to one file only. Both require a template that will be used to generate filename for produced files. To learn more about how these templates are handled by tesliper, see make_name() documentation.

As mentioned before, writer object uses type of the DataArray-like object (or, more precisely, a name of its class) to decide which method to use for writing to disk. If you introduce a new subclass of DataArray for handling some genres, you will need to tell the Writer class, how it should handle these new objects. This is done by implementing a custom handler method. It’s name should begin with an underscore, followed by the name of your subclass in lower case, followed by “_handler”. Also, it should take two parameters: data and extras. First one is a list of instances of your subclass, second one is a dictionary of special-case genres, both retrieved from arguments given to write() method (for details on which genres as treated as special cases, see distribute_data()). Handler is responsible for calling appropriate writing method with arguments it needs.

Here is an example: let’s assume you have implemented a custom DataArray subclass for “ldip” and “lrot” genres with some additional functionality, but you’d like tesliper to treat it as the original ElectronicActivities class for purposes of writing to disk.

class LengthActivities(ElectronicActivities):
    associated_genres = ("ldip", "lrot")
    ...  # custom functionality implemented here

class UpdatedTxtWriter(TxtWriter):
    extension = "txt"

    def _lengthactivities_handler(self, data, extras):
        # written like ``ElectronicActivities``, so just delegate to its handler
        self._electronicactivities_handler(data, extras)

If you’d like to treat this new subclass differently, then you should provide a custom writting method for this kind of data:

class UpdatedTxtWriter(TxtWriter):
    extension = "txt"

    def length_activities(
        self,
        band: Bands,
        data: List[LengthActivities],
        name_template: Union[str, Template] = "${conf}.${cat}-${det}.${ext}",
    ):
        # we will use ``_iter_handles`` method for opening/closing files
        template_params = {"genre": band.genre, "cat": "activity", "det": "length"}
        handles = self._iter_handles(band.filenames, name_template, template_params)
        # we will iterate conformer by conformer
        values = zip(*[arr.values for arr in data])
        for values, handle in zip(values, handles):
            ...  # writting logic

    def _lengthactivities_handler(self, data, extras):
        self.length_activities(band=extras["wavelengths"], data=data)

In both cases UpdatedTxtWriter will be picked by the writer() instead of the original TxtWriter, thanks to the automatic registration done by the base class WriterBase.

Warning

If extension = "txt" line would be omitted in the UpdatedTxtWriter definition, it would be picked by the writer() for “txt” format anyway, because extension’s value would be inherited from TxtWriter. If you want to prevent this, you can provide a falsy value for the extension class attribute, i.e. an empty string or None. If your custom writer should still use the same extension as one of the default writers, provide extension also as an instance-level attribute:

class UpdatedTxtWriter(TxtWriter):
    extension = ""  # do not register

    def __init__(self, destination, mode):
        super().__init__(destination, mode)
        self.extension = "txt"  # use in generated filenames

Functions

writer(fmt, destination[, mode])

Factory function that returns concrete implementation of WriterBase subclass, most recently defined for export to fmt file format.

Classes

WriterBase(destination[, mode])

Base class for writers that handle export process based on genre of exported data.

tesliper.writing.writer_base.writer(fmt: str, destination: Union[str, pathlib.Path], mode: str = 'x', **kwargs) tesliper.writing.writer_base.WriterBase[source]

Factory function that returns concrete implementation of WriterBase subclass, most recently defined for export to fmt file format.

Parameters
  • fmt (str) – File format, to which export will be done.

  • destination (Union[str, Path]) – Path to file or direcotry, to which export will be done.

  • mode (str) – Specifies how writing to file should be handled. Should be one of characters: “a” (append to existing file), “x” (only write if file doesn’t exist yet), or “w” (overwrite file if it already exists). Defaults to “x”.

  • kwargs – Any additional keword arguments will be passed as-is to the constructor of the retrieved WriterBase subclass.

Returns

Initialized WriterBase subclass most recently defined for export to fmt file format.

Return type

WriterBase

Raises

ValueError – If WriterBase subclass for export to fmt file format was not defined.

class tesliper.writing.writer_base.WriterBase(destination: Union[str, pathlib.Path], mode: str = 'x')[source]

Base class for writers that handle export process based on genre of exported data.

Subclasses should provide an extension class-level attribute and writting methods that subclass intend to support (see below). Value of extension will be used to register subclass as a default writer for export to files that this value indicates (“txt”, “csv”, etc.). Not providing value for this attribute results in a TypeError exception. If subclass should not be registered, use an empty string as the attribute’s value.

WriterBase provides a write() method for writing arbitrary DataArray-like objects to disk. It dispatches those objects to appropriate writing methods, based on their type. Those writing methods are:

To learn more about implementing custom writers, see their documentation and writer_base documentation or extend section.

Parameters
  • destination (str or pathlib.Path) – Directory, to which generated files should be written.

  • mode (str) – Specifies how writing to file should be handled. Should be one of characters: ‘a’ (append to existing file), ‘x’ (only write if file doesn’t exist yet), or ‘w’ (overwrite file if it already exists).

energies_order = ['zpe', 'ten', 'ent', 'gib', 'scf']

Default order, in which energy-related data is written to files.

abstract property extension

Identifier of this writer, indicating the format of files generated, and a default extension of those files used by the make_name() method. A falsy value, i.e. an empty string or None prevents this writer from being registered and used by writer() factory function.

Returns

Default extension of files generated by this writer and it’s identifier.

Return type

str

property mode

Specifies how writing to file should be handled. Should be one of characters: “a”, “x”, or “w”. “a” - append to existing file; “x” - only write if file doesn’t exist yet; “w” - overwrite file if it already exists.

Raises

ValueError – If given anything other than “a”, “x”, or “w”.

property destination: pathlib.Path

Directory, to which generated files should be written.

Raises

FileNotFoundError – If given destination doesn’t exist or is not a directory.

Type

pathlib.Path

static distribute_data(data: List) Tuple[Dict[str, List], Dict[str, Any]][source]

Sorts given data by genre category for use by specialized writing methods.

Returns

  • distr (dict) – Dictionary with DataArray-like objects, sorted by their type. Each {key: value} pair is {name of the type in lowercase format: list of DataArray objects of this type}.

  • extras (dict) – Spacial-case genres: extra information used by some writer methods when exporting data. Available {key: value} pairs (if given in data) are:

    corrections: dict of {“energy genre”: FloatArray},
    frequencies: Bands,
    wavelengths: Bands,
    excitation: Bands,
    stoichiometry: InfoArray,
    charge: IntegerArray,
    multiplicity: IntegerArray

make_name(template: Union[str, string.Template], conf: str = '', num: Union[str, int] = '', genre: str = '', cat: str = '', det: str = '', ext: str = '') str[source]

Create filename using given template and given or global values for known identifiers. The identifier should be used in the template as "${identifier}" where “identifier” is the name of identifier. Available names and their meaning are:

${ext} - appropriate file extension
${conf} - name of the conformer
${num} - number of the file according to internal counter
${genre} - genre of exported data
${cat} - category of produced output
${det} - category-specific detail

The ${ext} identifier is filled with the value of Writers extension attribute if not explicitly given as parameter to this method’s call. Values for other identifiers should be provided by the caller.

Parameters
  • template (str or string.Template) – Template that will be used to generate filenames. It should contain only known identifiers, listed above.

  • conf (str) – value for ${conf} identifier, defaults to empty string.

  • num (str or int) – value for ${str} identifier, defaults to empty string.

  • genre (str) – value for ${genre} identifier, defaults to empty string.

  • cat (str) – value for ${cat} identifier, defaults to empty string.

  • det (str) – value for ${det} identifier, defaults to empty string.

  • ext (str) – value for ${ext} identifier, defaults to empty string.

Raises

ValueError – If given template or string contains any unexpected identifiers.

Examples

Must be first subclassed and instantiated:

>>> class MyWriter(WriterBase):
>>>     extension = "foo"
>>> wrt = MyWriter("/path/to/some/directory/")
>>> wrt.make_name(template="somefile.${ext}")
"somefile.foo"
>>> wrt.make_name(template="${conf}.${ext}")
".foo"  # conf is empty string by default
>>> wrt.make_name(template="${conf}.${ext}", conf="conformer")
"conformer.foo"
>>> wrt.make_name(template="Unknown_identifier_${bla}.${ext}")
Traceback (most recent call last):
ValueError: Unexpected identifiers given: bla.
_get_handle(template: Union[str, string.Template], template_params: dict, open_params: Optional[dict] = None) Iterator[IO][source]

Helper method for creating files. Given additional kwargs will be passed to Path.open() method. Implemented as context manager for use with with statement.

Parameters
  • template (str or string.Template) – Template that will be used to generate filenames.

  • template_params (dict) – Dictionary of {identifier: value} for .make_name method.

  • open_params (dict, optional) – Arguments for Path.open() used to open file.

Yields
  • IO – file handle, will be closed automatically after with statement exits

  • meta public:

_iter_handles(filenames: Iterable[str], template: Union[str, string.Template], template_params: dict, open_params: Optional[dict] = None) Iterator[IO][source]

Helper method for iteration over generated files. Given additional kwargs will be passed to Path.open() method.

Parameters
  • filenames (list of str) – list of source filenames, used as value for ${conf} placeholder in name_template

  • template_params (dict) – Dictionary of {identifier: value} for .make_name method.

  • open_params (dict, optional) – arguments for Path.open() used to open file.

Yields
  • TextIO – file handle, will be closed automatically on next iteration

  • meta public:

write(data: List) None[source]

Writes DataArray-like objects to disk, decides how to write them based on the type of each object. If some types of given objects are not supported by this writer, data of this type is ignored and a warning is emitted.

Parameters

data (List) – DataArray-like objects that should be written to disk.

generic(data: List[Union[tesliper.glassware.arrays.DataArray, tesliper.glassware.arrays.IntegerArray, tesliper.glassware.arrays.FloatArray, tesliper.glassware.arrays.BooleanArray, tesliper.glassware.arrays.InfoArray]], name_template: Union[str, string.Template] = '')[source]

Interface for writing generic data: any that provides one value for each conformer. Evoked when handling DataArray, IntegerArray, FloatArray, BooleanArray, or InfoArray.

Parameters

data – List of objects that provide one value for each conformer.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

overview(energies: Sequence[tesliper.glassware.arrays.Energies], frequencies: Optional[tesliper.glassware.arrays.Bands] = None, stoichiometry: Optional[tesliper.glassware.arrays.InfoArray] = None, name_template: Union[str, string.Template] = '')[source]

Intercafe for generating an overview of known conformers: values of energies, number of imaginary frequencies, and stoichiometry for each conformer. Evoked when handling Energies objects.

Parameters
  • energies – List of objects representing different energies genres for each conformer. Mandatory in custom implementation.

  • frequenciesBands of “freq” genre, with list of frequencies for each conformer. Mandatory in custom implementation. May be None when method evoked by handler.

  • stoichiometry – Stoichiometry of each conformer. Mandatory in custom implementation. May be None when method evoked by handler.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

energies(energies: tesliper.glassware.arrays.Energies, corrections: Optional[tesliper.glassware.arrays.FloatArray] = None, name_template: Union[str, string.Template] = '')[source]

Interface for writing energies values, and optionally their corrections. Evoked when handling Energies objects.

Parameters
  • energies – Conformers’ energies. Mandatory in custom implementation.

  • corrections – Correction of energies values. Mandatory in custom implementation. May be None when method evoked by handler.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

single_spectrum(spectrum: tesliper.glassware.spectra.SingleSpectrum, name_template: Union[str, string.Template] = '')[source]

Interface for writing a single spectrum to disk: calculated for one conformer or averaged. Evoked when handling SingleSpectrum objects.

Parameters
  • spectrum – Single calculated spectrum. Mandatory in custom implementation.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

spectral_data(band: tesliper.glassware.arrays.Bands, data: List[tesliper.glassware.arrays.SpectralData], name_template: Union[str, string.Template] = '')[source]

Interface for writing multiple objects with spectral data that is not a spectral activity (cannot be converted to signal intensity). Evoked when handling one of the: VibrationalData, ElectronicData, ScatteringData objects.

Parameters
  • band – Band at which transitions occur for each conformer. Mandatory in custom implementation.

  • data – List of objects representing different spectral data genres (but not spectral activities). Mandatory in custom implementation.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

spectral_activities(band: tesliper.glassware.arrays.Bands, data: List[tesliper.glassware.arrays.SpectralActivities], name_template: Union[str, string.Template] = '')[source]

Interface for writing multiple objects with spectral activities (data that may be converted to signal intensity). Evoked when handling one of the: VibrationalActivities, ElectronicActivities, ScatteringActivities objects.

Parameters
  • band – Band at which transitions occur for each conformer. Mandatory in custom implementation.

  • data – List of objects representing different spectral activities genres. Mandatory in custom implementation.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

spectra(spectra: tesliper.glassware.spectra.Spectra, name_template: Union[str, string.Template] = '')[source]

Interface for writing a set of spectra of one type calculated for many conformers. Evoked when handling Spectra objects.

Parameters
  • spectra – Spectra of one type calculated for multiple conformers. Mandatory in custom implementation.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

transitions(transitions: tesliper.glassware.arrays.Transitions, wavelengths: tesliper.glassware.arrays.Bands, only_highest: bool = True, name_template: Union[str, string.Template] = '')[source]

Interface for writing single object with electronic transitions data. Evoked when handling Transitions objects.

Parameters
  • transitions – List of objects representing different spectral data genres (but not spectral_activities). Mandatory in custom implementation.

  • wavelengths – Wavelengths at which transitions occur for each conformer. Mandatory in custom implementation.

  • only_highest – Boolean flag indicating if all transitions should be written to disk or only these transition that contributes the most for each wavelength/ May be omitted in custom implementation.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.

geometry(geometry: tesliper.glassware.arrays.Geometry, charge: Optional[Union[tesliper.glassware.arrays.IntegerArray, Sequence[int], int]] = None, multiplicity: Optional[Union[tesliper.glassware.arrays.IntegerArray, Sequence[int], int]] = None, name_template: Union[str, string.Template] = '')[source]

Interface for writing single object with geometry of each conformer. Evoked when handling Geometry objects.

Parameters
  • geometry – Positions of atoms in each conformer. Mandatory in custom implementation.

  • charge – Value of each structure’s charge. Mandatory in custom implementation.

  • multiplicity – Value of each structure’s multiplicity. Mandatory in custom implementation.

  • name_template – Template that defines naming scheme for files generated by this method. May be omitted in custom implementation.

Raises

NotImplementedError – Whenever called, this is an interface that should not be used directly.