excitingtools

excitingtools: An exciting Workflow Tool - Published in JOSS (2023)

https://github.com/exciting/excitingtools

Science Score: 98.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 1 DOI reference(s) in JOSS metadata
  • Academic publication links
    Links to: joss.theoj.org, zenodo.org
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
    Published in Journal of Open Source Software

Scientific Fields

Economics Social Sciences - 40% confidence
Last synced: 4 months ago · JSON representation ·

Repository

An exciting Workflow Tool

Basic Info
  • Host: GitHub
  • Owner: exciting
  • License: lgpl-3.0
  • Language: Python
  • Default Branch: main
  • Size: 608 KB
Statistics
  • Stars: 3
  • Watchers: 4
  • Forks: 2
  • Open Issues: 1
  • Releases: 1
Created about 3 years ago · Last pushed over 1 year ago
Metadata Files
Readme Contributing License Citation

README.md

excitingtools

excitingtools is a collection of modules to facilitate the generation of exciting inputs and the post-processing of exciting outputs.

excitingtools currently provides functionality for:

  • Generation of the exciting input XML file using Python classes:

    • Currently supported for groundstate, structure and BSE
  • Parsing of exciting outputs into Python dictionaries

  • High-level class API for interacting with results:

    • Currently implemented for eigenvalues, band structure and DOS (without SO coupling)

making it is possible to define a calculation, run it, and parse the relevant outputs all from within Python.

excitingtools is used by, or in conjunction with:

  • exciting's regression-testing framework
    • Parsing of output data
  • exciting's Jupyter notebook tutorials
    • Data handling
  • Atomic Simulation Environment (ASE)
    • Input and output handling in ASE's exciting calculator
  • Jobflow
    • For the development of complex, automated exciting workflows

Installation

If one wishes to import excitingtools in their own scripts, it can be installed from this project's root directory ($EXCITING_ROOT/tools/exciting_tools) with:

bash pip install -e .

or downloaded directly from pip:

bash pip install excitingtools

External Package Dependencies

If a new external dependency is introduced to the package, this also requires adding to setup.py such that pip is aware of the new dependency.

Basic File Structure

In general, modules should begin with a docstring giving an overview of the module's purpose. External python libraries should then be imported, followed by a space, then local modules belonging to excitingtools. Local modules should be loaded with absolute paths rather than relative paths or prepending the system path sys.path.insert(0,'/path/to/module_directory'):

```angular2html """ Functions that operate on lattice vectors """ import numpy as np

from excitingtools.maths.mathutils import tripleproduct ```

Exposed modules, forming user API, should be defined in __init__.py where ever possible.

Code Formatting

We currently favour yapf formatter, which by default applies PEP8 formatting to the code.

After installing yapf, if you are in the root directory of excitingtools, you can simply type:

bash yapf -i excitingtools/path/to/file.py

and it will do the formatting for you. Note: This will automatically use our custom .style.yapf style-file.

Documentation

Writing Documentation

All functions and classes should be documented. The favoured docstring is reStructuredText:

```python class SimpleEquation: def demo(self, a: int, b: int, c: int) -> list: """Function definition.

:param int a: quadratic coefficient
:param int b: linear coefficient 
:param c: free term
:type c: int
:return list y: Function values   
"""

```

where the type can be specified in the param description, or separately using the type tag. For more details on the documentation syntax, please refer to this link. The google style guide for reStructuredText docstrings is also acceptable to follow.

Generating Documentation

Documentation can straightforwardly be generated using the pdoc package:

bash pip install pdoc pdoc -o documentation -d restructuredtext --math excitingtools/

Basic Usage

Input XML Generation

excitingtools maps the XML tags and attributes of input.xml onto Python classes, enabling the generation of XML-formatted inputs directly from Python. A simple ground state calculation could like this:

```python import ase import numpy as np

from excitingtools.input.structure import ExcitingStructure from excitingtools.input.groundstate import ExcitingGroundStateInput from excitingtools.input.inputxml import excitinginputxml_str

Lattice and positions in angstrom, as expected by ASE

lattice = np.array([[3.168394160510246, 0.0, 0.0], [-1.5841970805453853, 2.7439098312114987, 0.0], [0.0, 0.0, 39.58711265]]) positions = np.array([[0.00000000, 0.00000000, 16.68421565], [1.58419708, 0.91463661, 18.25982194], [1.58419708, 0.91463661, 15.10652203], [1.58419708, 0.91463661, 22.90251866], [0.00000000, 0.00000000, 24.46831689], [0.00000000, 0.00000000, 21.33906353]]) symbols = ['W', 'S', 'S', 'Mo', 'S', 'S'] atoms = ase.atoms.Atoms(symbols=symbols, positions=positions, cell=lattice)

structure = ExcitingStructure(atoms, species_path='.')

groundstate = ExcitingGroundStateInput( rgkmax=8.0, do="fromscratch", ngridk=[6, 6, 6], xctype="GGAPBE_SOL", vkloff=[0, 0, 0], tforce=True, nosource=False )

inputxmlstr = excitinginputxmlstr(structure, groundstate, title="My exciting Crystal")

with open("input.xml", "w") as fid: fid.write(inputxmlstr) ```

Here we defined the attributes required to perform a ground state calculation as seperate classes, and composed the final XML string with exciting_input_xml_str. If the user does not have access to ASE, they can instead use a List[dict] to define the container with atoms data:

```python atoms = [{'species': 'W', 'position': [0.00000000, 0.00000000, 16.68421565]}, {'species': 'S', 'position': [1.58419708, 0.91463661, 18.25982194]}, {'species': 'S', 'position': [1.58419708, 0.91463661, 15.10652203]}, {'species': 'Mo','position': [1.58419708, 0.91463661, 22.90251866]}, {'species': 'S', 'position': [0.00000000, 0.00000000, 24.46831689]}, {'species': 'S', 'position': [0.00000000, 0.00000000, 21.33906353]}]

structure = ExcitingStructure(atoms, lattice, species_path='.') ```

Additional examples can be found in the test cases, exciting_tools/tests/input. We note that not all XML tags currently map onto Python classes. One can consult exciting_tools/excitingtools/input to see what is available. Development follows a continuous integration and deployment workflow, therefore if one wishes for additional features, please make a request on Github issues or open a merge request.

Binary Execution

Next we can define a runner and run our calculation:

```python from excitingtools.runner.runner import BinaryRunner

runner = BinaryRunner('excitingsmp', runcmd=[''], ompnumthreads=4, timeout=500) runstatus = runner.run() ```

Parsing Outputs

After the successful completion of the calculation, we can parse the relevant output files as dictionaries, using parser_chooser. These are the main files one would be interested in after performing a ground state calculation, for example:

```python from excitingtools import parser_chooser

infoout: dict = parserchooser("INFO.OUT") eigvalinfo: dict = parserchooser("eigval.xml") atomsinfo: dict = parserchooser("atoms.xml") ```

A full list of parsers is provided in excitingtools/exciting_dict_parsers/parser_factory.py. If we wish to perform analysis of the data, excitingtools provides classes with high-level API. To perform a band structure plot using the BandData class:

```python """ Plot silicon band structure """ import matplotlib.pyplot as plt

from excitingtools.excitingobjparsers.ksbandstructure import parsebandstructure from excitingtools.dataclasses.band_structure import BandData

banddata: BandData = parsebandstructure("bandstructure.xml") vertices, labels = banddata.band_path()

hatoev = 27.2114 fig, ax = plt.subplots(figsize=(6, 9))

ax.setxticks(vertices) ax.setxticklabels(labels) plt.ylabel('Energy (eV)')

Font sizes

ax.yaxis.label.setsize(20) ax.tickparams(axis='both', which='major', labelsize=20)

Vertical lines at high symmetry points

for x in vertices: plt.axvline(x, linestyle='--', color='black')

Fermi reference

e_fermi = 0.0

Number of valence bands

n_valence = 4

Colour valence and conduction bands differently

linecolour = {key:'blue' for key in range(0, nvalence)} linecolour.update({key:'red' for key in range(nvalence, banddata.nbands)})

for ib in range(0, banddata.nbands): plt.plot(banddata.flattenedkpoints, hatoev * banddata.bands[:, ib], color=line_colour[ib]) ```

Tests demonstrating further usage are present in excitingtools/tests/dataclasses. We note that the high-level objects and their parsers are separated. In principle, the data classes should only define a sensible schema or API for accepting relevant data, rather than know anything about the parsing. Object parsers (defined in obj_parsers) by definition should return to data classes, but the data classes dictate the format of the data, not vice versa.

Testing

Every function should have a test where possible, unless the function is correct by inspection. The naming convention for a module called module.py is to prepend it with test_, which allows it to be automatically recognised and run by pytest:

bash excitingtools/module.py # Collection of functions tests/test_module.py # Collection of tests for functions in module.py

Tests are intended to be run using pytest, for which the documentation can be found here. One is able to run pytest from the exciting_tools root with no arguments. By default, all test files, classes and functions defined in the specification, exciting_tools/pytest.ini, will get executed.

Parsers

The parsers are used in the test suite. Therefore, they should only return dictionaries with a specific structure.

The tolerance comparison will only evaluate the values of lowest-nested keys. As such, one should consider how they structure the parsed data. For example, it makes more sense to structure data like:

python {‘wannier1’: {‘localisation_vector’: np.array(shape=(3)), ‘Omega’: float } }

such that the tolerances will be w.r.t. localisation_vector, and Omega, rather than using the structure:

python {‘localisation_vector’: {‘wannier1’: np.array(shape=(3)) ‘wannier2’: np.array(shape=(3)) }, ‘Omega’: {‘wannier1’: float ‘wannier2’: float } }

which will results in tolerances defined w.r.t. wannier1 and wannier2. One can see in the latter case, there is no distinction between localisation_vector and Omega. In general, we’re more likely to want to set different tolerances for different properties, rather than for different functions with the same set of properties. One could also structure the data like:

python {‘localisation_vector’: np.array(shape=(n_wannier, 3)), ‘Omega’: : np.array(shape=(n_wannier) }

where the less serialised data removes the key nesting.

Usage in Workflow Engines

excitingtools has been designed with materials workflows in mind, and can be used to as a means of interacting with exciting from python, to define calculations or parse results. A workflow can be imagined as a series of single-responsibility function calls, forming a recipe of computational steps. For example, one might wish to design a workflow to converge a quantity such as k-sampling. Abstractly, this might look like:

```python """Simple convergence workflow """

Read input from input file:

specifiedinput = readinput(Path("input.yml").absolute())

Define convergence criterion

convergencecriteria = getconvergencecriteria(specifiedinput)

Set up jobs

excitingcalc = setupexcitingcalculation(specifiedinput) convergencejob = convergengridk(excitingcalc.output, convergencecriteria, [])

Run workflow using Jobflow

responses = runlocally(Flow([excitingcalc, convergence_job]), store=JobStore(MemoryStore())) ```

where an exciting calculation or calculator can be defined using excitingtools functionality. It is then down to the developer to determine how to concretely implement a means of constructing calculators with different k-sampling, and how to evaluate convergence. For each step in a workflow, Jobflow can be used as a decorator, allowing it to capture steps and serialise the information passed between functions. Tutorials on developing a workflow using Jobflow can be found on here.

Uploading to PyPi (for developers)

excitingtools is available as a separate package on PyPi. In order to upload a new version:

```bash

Ensure build and twine are installed

pip3 install twine

Build the wheel, in excitingtools root

python -m build

Test the distribution and uploading (one requires a test-PyPi account)

twine check dist/* twine upload --repository-url https://test.pypi.org/legacy/ dist/*

Upload to PyPi

twine upload dist/* ```

Before doing so, please ensure the semantic versioning is appropriately updated in setup.py.

Citing

To cite excitingtools, please refer to the CITATION.cff.

excitingtools tag "1.3.0" is published in the Journal of Open Source Software and archived on Zenodo:

DOI

Contributors

The following people (in alphabetic order by their family names) have contributed to excitingtools:

  • Alexander Buccheri
  • Hannah Kleine
  • Martin Kuban
  • Benedikt Maurer
  • Fabian Peschel
  • Daniel Speckhard
  • Elisa Stephan
  • Mara Voiculescu

Owner

  • Name: exciting
  • Login: exciting
  • Kind: organization
  • Location: IRIS Adlershof, Humboldt-Universität zu Berlin

JOSS Publication

excitingtools: An exciting Workflow Tool
Published
May 03, 2023
Volume 8, Issue 85, Page 5148
Authors
Alexander Buccheri ORCID
Humboldt-Universität zu Berlin, Berlin, Germany, Max Planck Institute for the Structure and Dynamics of Matter, Hamburg, Germany
Fabian Peschel ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Benedikt Maurer ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Mara Voiculescu ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Daniel T. Speckhard ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Hannah Kleine ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Elisa Stephan ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Martin Kuban ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Claudia Draxl ORCID
Humboldt-Universität zu Berlin, Berlin, Germany
Editor
Richard Gowers ORCID
Tags
Physics DFT Workflow

Citation (CITATION.cff)

cff-version: 1.2.0
title: 'excitingtools: An exciting Workflow Tool'
message: >-
  If you use this software, please cite it using the
  metadata from this file.
type: software
version: 1.1.0
date-released: 2022-09-20
authors:
  - given-names: Alexander
    family-names: Buccheri
    email: alexander.buccheri@mpsd.mpg.de
    affiliation: >-
      Max Planck Institute for the Structure and
      Dynamics of Matter
    orcid: 'https://orcid.org/0000-0001-5983-8631'
  - given-names: Hannah
    family-names: Kleine
    email: kleineha@physik.hu-berlin.de
    affiliation: >-
      Humboldt-Universität zu Berlin
    orcid: 'https://orcid.org/0000-0003-2251-8719'
  - given-names: Martin
    family-names: Kuban
    email: kuban@physik.hu-berlin.de
    affiliation: >-
      Humboldt-Universität zu Berlin
    orcid: 'https://orcid.org/0000-0002-1619-2460'
  - given-names: Benedikt
    family-names: Maurer
    email: benedikt.moritz.maurer@physik.hu-berlin.de
    affiliation: >-
      Humboldt-Universität zu Berlin
    orcid: 'https://orcid.org/0000-0001-9152-7390'
  - given-names: Fabian
    family-names: Peschel
    email: peschelf@physik.hu-berlin.de
    affiliation: >-
      Humboldt-Universität zu Berlin
    orcid: 'https://orcid.org/0000-0003-0619-6713'
  - given-names: Daniel T.
    family-names: Speckhard
    email: speckhard@fhi.mpg.de
    affiliation: >-
      Fritz-Haber-Institut der Max-Planck-Gesellschaft, Humboldt-Universität zu Berlin
    orcid: 'https://orcid.org/0000-0002-9849-0022'
  - given-names: Elisa
    family-names: Stephan
    email: stephael@physik.hu-berlin.de
    affiliation: >-
      Humboldt-Universität zu Berlin
    orcid: 'https://orcid.org/0000-0002-6359-9044'
  - given-names: Mara
    family-names: Voiculescu
    email: voiculem@physik.hu-berlin.de
    affiliation: >-
      Humboldt-Universität zu Berlin
    orcid: 'https://orcid.org/0000-0003-4393-8528'

GitHub Events

Total
Last Year

Committers

Last synced: 5 months ago

All Time
  • Total Commits: 18
  • Total Committers: 1
  • Avg Commits per committer: 18.0
  • Development Distribution Score (DDS): 0.0
Past Year
  • Commits: 0
  • Committers: 0
  • Avg Commits per committer: 0.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Alex Buccheri a****i@g****m 18

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 0
  • Total pull requests: 7
  • Average time to close issues: N/A
  • Average time to close pull requests: 6 days
  • Total issue authors: 0
  • Total pull request authors: 3
  • Average comments per issue: 0
  • Average comments per pull request: 0.86
  • Merged pull requests: 4
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 0
  • Pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • FabiPi3 (1)
Pull Request Authors
  • AlexBuccheri (4)
  • speckhard (2)
  • FabiPi3 (1)
Top Labels
Issue Labels
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 101 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 1
  • Total versions: 23
  • Total maintainers: 2
pypi.org: excitingtools

Utilities for aiding in the construction of exciting inputs and the postprocessing exciting outputs.

  • Versions: 23
  • Dependent Packages: 0
  • Dependent Repositories: 1
  • Downloads: 101 Last month
Rankings
Dependent packages count: 10.1%
Downloads: 12.7%
Average: 14.8%
Dependent repos count: 21.6%
Maintainers (2)
Last synced: 4 months ago