From 307cc9b8d759ed328694cf9b7296d322fd485063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Jan=C3=9Fen?= Date: Thu, 3 Oct 2024 19:32:46 +0200 Subject: [PATCH] Add Readme --- .github/workflows/format_black.yml | 33 ++++++++++++ .github/workflows/minimal.yml | 5 +- .github/workflows/pypicheck.yml | 21 ++++++++ README.md | 29 ++++++++++ .../v1/converter.py | 53 ++++++++++--------- tests/test_pyiron_atomistics_live.py | 17 +++--- tests/test_pyiron_atomistics_static.py | 44 ++------------- 7 files changed, 122 insertions(+), 80 deletions(-) create mode 100644 .github/workflows/format_black.yml create mode 100644 .github/workflows/pypicheck.yml create mode 100644 README.md rename tests/convert.py => pyiron_dataclasses/v1/converter.py (97%) diff --git a/.github/workflows/format_black.yml b/.github/workflows/format_black.yml new file mode 100644 index 0000000..e3fdafd --- /dev/null +++ b/.github/workflows/format_black.yml @@ -0,0 +1,33 @@ +# This workflow will checkout the branch of the PR, apply black formatting and commit the result to the PR. Does not work for forks. + +name: Format black + +on: + pull_request: + types: [labeled] + +jobs: + build: + if: contains(github.event.pull_request.labels.*.name, 'format_black' ) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.DEPENDABOT_WORKFLOW_TOKEN }} + ref: ${{ github.event.pull_request.head.ref }} # Check out the head of the actual branch, not the PR + fetch-depth: 0 # otherwise, you will fail to push refs to dest repo + - name: format black + uses: psf/black@stable + with: + options: "" + src: "./${{ github.event.repository.name }}" + - name: commit + run: | + git config --local user.email "pyiron@mpie.de" + git config --local user.name "pyiron-runner" + git commit -m "Format black" -a + - name: push + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.DEPENDABOT_WORKFLOW_TOKEN }} + branch: ${{ github.event.pull_request.head.ref }} \ No newline at end of file diff --git a/.github/workflows/minimal.yml b/.github/workflows/minimal.yml index 2700a8c..bec7fe0 100644 --- a/.github/workflows/minimal.yml +++ b/.github/workflows/minimal.yml @@ -21,9 +21,6 @@ jobs: condarc-file: .condarc environment-file: .ci_support/environment-mini.yml - name: Test - shell: bash -l {0} - timeout-minutes: 5 - run: | - pip install versioneer[toml]==0.29 + pip install versioneer[toml]==0.29 pip install . --no-deps --no-build-isolation python -m unittest discover tests diff --git a/.github/workflows/pypicheck.yml b/.github/workflows/pypicheck.yml new file mode 100644 index 0000000..34ae6b3 --- /dev/null +++ b/.github/workflows/pypicheck.yml @@ -0,0 +1,21 @@ +# This workflow is used to test, if the installation of the pypi package works + +name: Pip check + +on: + push: + branches: [ main ] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Pip check + shell: bash -l {0} + run: | + pip install versioneer[toml]==0.29 + pip install . --no-deps --no-build-isolation + pip check \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d487cf --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Dataclasses for pyiron +The `pyiron_dataclasses` module provides a series of [dataclasses](https://docs.python.org/3/library/dataclasses.html) +for the `pyiron` workflow framework. It can load HDF5 files created by `pyiron_atomistics` and read the content stored +in those files, without depending on `pyiron_atomistics`. Furthermore, it is not fixed to a single version of +`pyiron_atomistics` but rather matches multiple versions of `pyiron_atomistics` to the same API version of +`pyiron_dataclasses`. + +## Usage +Using the `get_dataclass()` function of the built-in converter: +```python +from h5io_browser import read_dict_from_hdf +from pyiron_dataclasses.v1.converter import get_dataclass + +job_classes = get_dataclass( + job_dict=read_dict_from_hdf( + file_name=job.project_hdf5.file_name, + h5_path="/", + recursive=True, + slash='ignore', + )[job.job_name] +) +job_classes +``` + +## Supported Versions +### Version 1 - `v1` +Supported versions of `pyiron_atomistics`: +* `0.6.13` +* `0.6.12` diff --git a/tests/convert.py b/pyiron_dataclasses/v1/converter.py similarity index 97% rename from tests/convert.py rename to pyiron_dataclasses/v1/converter.py index 6dad9ba..8e115b7 100644 --- a/tests/convert.py +++ b/pyiron_dataclasses/v1/converter.py @@ -61,15 +61,24 @@ ) -def convert_sphinx_job_dict(job_dict: dict) -> SphinxJob: +def get_dataclass(job_dict): + funct_dict = { + "": _convert_lammps_job_dict, + "": _convert_sphinx_job_dict, + "": _convert_vasp_job_dict, + } + return funct_dict[job_dict["TYPE"]](job_dict=job_dict) + + +def _convert_sphinx_job_dict(job_dict: dict) -> SphinxJob: ureg = UnitRegistry() - sphinx_input_parameter_dict = convert_datacontainer_to_dictionary( + sphinx_input_parameter_dict = _convert_datacontainer_to_dictionary( data_container_dict=job_dict["input"]["parameters"] ) - generic_input_dict = convert_generic_parameters_to_dictionary( + generic_input_dict = _convert_generic_parameters_to_dictionary( generic_parameter_dict=job_dict["input"]["generic"], ) - output_dict = convert_datacontainer_to_dictionary( + output_dict = _convert_datacontainer_to_dictionary( data_container_dict=job_dict["output"]["generic"] ) if "ricQN" in sphinx_input_parameter_dict["sphinx"]["main"]: @@ -461,9 +470,9 @@ def convert_sphinx_job_dict(job_dict: dict) -> SphinxJob: ) -def convert_lammps_job_dict(job_dict: dict) -> LammpsJob: +def _convert_lammps_job_dict(job_dict: dict) -> LammpsJob: ureg = UnitRegistry() - generic_input_dict = convert_generic_parameters_to_dictionary( + generic_input_dict = _convert_generic_parameters_to_dictionary( generic_parameter_dict=job_dict["input"]["generic"], ) return LammpsJob( @@ -541,10 +550,10 @@ def convert_lammps_job_dict(job_dict: dict) -> LammpsJob: species=job_dict["input"]["potential_inp"]["potential"]["Species"], ), input_files=LammpsInputFiles( - control_inp=convert_generic_parameters_to_string( + control_inp=_convert_generic_parameters_to_string( generic_parameter_dict=job_dict["input"]["control_inp"] ), - potential_inp=convert_generic_parameters_to_string( + potential_inp=_convert_generic_parameters_to_string( generic_parameter_dict=job_dict["input"]["potential_inp"] ), ), @@ -609,9 +618,9 @@ def convert_lammps_job_dict(job_dict: dict) -> LammpsJob: ) -def convert_vasp_job_dict(job_dict): +def _convert_vasp_job_dict(job_dict): ureg = UnitRegistry() - generic_input_dict = convert_generic_parameters_to_dictionary( + generic_input_dict = _convert_generic_parameters_to_dictionary( generic_parameter_dict=job_dict["input"]["generic"], ) return VaspJob( @@ -693,14 +702,14 @@ def convert_vasp_job_dict(job_dict): fix_spin_constraint=generic_input_dict.get("fix_spin_constraint", None), max_iter=generic_input_dict.get("max_iter", None), ), - incar=convert_generic_parameters_to_string( + incar=_convert_generic_parameters_to_string( generic_parameter_dict=job_dict["input"]["incar"] ), - kpoints=convert_generic_parameters_to_string( + kpoints=_convert_generic_parameters_to_string( generic_parameter_dict=job_dict["input"]["kpoints"] ), potcar=PotCar( - xc=convert_generic_parameters_to_dictionary( + xc=_convert_generic_parameters_to_dictionary( generic_parameter_dict=job_dict["input"]["potcar"] )["xc"] ), @@ -915,16 +924,7 @@ def convert_vasp_job_dict(job_dict): ) -def convert(job_dict): - funct_dict = { - "": convert_lammps_job_dict, - "": convert_sphinx_job_dict, - "": convert_vasp_job_dict, - } - return funct_dict[job_dict["TYPE"]](job_dict=job_dict) - - -def convert_generic_parameters_to_string(generic_parameter_dict: dict) -> str: +def _convert_generic_parameters_to_string(generic_parameter_dict: dict) -> str: output_str = "" for p, v in zip( generic_parameter_dict["data_dict"]["Parameter"], @@ -934,7 +934,7 @@ def convert_generic_parameters_to_string(generic_parameter_dict: dict) -> str: return output_str[:-1] -def convert_generic_parameters_to_dictionary(generic_parameter_dict: dict) -> dict: +def _convert_generic_parameters_to_dictionary(generic_parameter_dict: dict) -> dict: return { p: v for p, v in zip( @@ -976,7 +976,7 @@ def recursive_sort(input_value: dict) -> dict: else: ind_dict[int(ind)] = key content_dict[key] = recursive_sort(input_value=v) - elif k != "DICT_VERSION": + else: content_dict[k] = recursive_sort(input_value=v) if content_lst_flag: return [ind_dict[ind] for ind in sorted(list(ind_dict.keys()))] @@ -991,7 +991,7 @@ def recursive_sort(input_value: dict) -> dict: raise KeyError(ind_dict, content_dict) -def convert_datacontainer_to_dictionary(data_container_dict: dict) -> dict: +def _convert_datacontainer_to_dictionary(data_container_dict: dict) -> dict: return _sort_dictionary_from_datacontainer( input_dict=_filter_dict( input_dict=data_container_dict, @@ -999,6 +999,7 @@ def convert_datacontainer_to_dictionary(data_container_dict: dict) -> dict: "NAME", "TYPE", "OBJECT", + "DICT_VERSION", "HDF_VERSION", "READ_ONLY", "VERSION", diff --git a/tests/test_pyiron_atomistics_live.py b/tests/test_pyiron_atomistics_live.py index 57852ee..fe38bc0 100644 --- a/tests/test_pyiron_atomistics_live.py +++ b/tests/test_pyiron_atomistics_live.py @@ -1,12 +1,9 @@ import unittest -from h5io_browser.base import read_dict_from_hdf +from h5io_browser import read_dict_from_hdf from pint import UnitRegistry -from convert import ( - convert_sphinx_job_dict, - convert_lammps_job_dict, -) +from pyiron_dataclasses.v1.converter import get_dataclass try: from pyiron_atomistics import Project @@ -45,7 +42,7 @@ def test_sphinx_calc_minimize(self): recursive=True, slash='ignore', ) - job_sphinx = convert_sphinx_job_dict(job_dict[job.job_name]) + job_sphinx = get_dataclass(job_dict[job.job_name]) self.assertEqual(job_sphinx.calculation_output.generic.energy_tot[-1], -228.78315943905295 * ureg.eV) def test_sphinx_calc_static(self): @@ -59,7 +56,7 @@ def test_sphinx_calc_static(self): recursive=True, slash='ignore', ) - job_sphinx = convert_sphinx_job_dict(job_dict[job.job_name]) + job_sphinx = get_dataclass(job_dict[job.job_name]) self.assertEqual(job_sphinx.calculation_output.generic.energy_tot[-1], -228.78315953829286 * ureg.eV) def test_lammps_calc_static(self): @@ -74,7 +71,7 @@ def test_lammps_calc_static(self): recursive=True, slash='ignore', ) - job_lammps = convert_lammps_job_dict(job_dict[job.job_name]) + job_lammps = get_dataclass(job_dict[job.job_name]) self.assertEqual(job_lammps.calculation_output.generic.energy_tot[-1], -13.4486826111902 * ureg.eV) def test_lammps_calc_md(self): @@ -89,7 +86,7 @@ def test_lammps_calc_md(self): recursive=True, slash='ignore', ) - job_lammps = convert_lammps_job_dict(job_dict[job.job_name]) + job_lammps = get_dataclass(job_dict[job.job_name]) self.assertEqual(len(job_lammps.calculation_output.generic.energy_tot), 11) def test_lammps_calc_minimize(self): @@ -104,5 +101,5 @@ def test_lammps_calc_minimize(self): recursive=True, slash='ignore', ) - job_lammps = convert_lammps_job_dict(job_dict[job.job_name]) + job_lammps = get_dataclass(job_dict[job.job_name]) self.assertEqual(job_lammps.calculation_output.generic.energy_tot[-1], -13.4486826111902 * ureg.eV) diff --git a/tests/test_pyiron_atomistics_static.py b/tests/test_pyiron_atomistics_static.py index 8eb58dc..e597bd3 100644 --- a/tests/test_pyiron_atomistics_static.py +++ b/tests/test_pyiron_atomistics_static.py @@ -1,51 +1,15 @@ import os from unittest import TestCase -from h5io_browser.base import read_dict_from_hdf +from h5io_browser import read_dict_from_hdf from pint import UnitRegistry -from convert import ( - convert, - convert_sphinx_job_dict, - convert_lammps_job_dict, - convert_vasp_job_dict, +from pyiron_dataclasses.v1.converter import ( + get_dataclass, ) class TestPyironAtomisticsStatic(TestCase): - def test_sphinx(self): - ureg = UnitRegistry() - job_dict = read_dict_from_hdf( - file_name=os.path.join(os.path.dirname(__file__), "pyiron_atomistics_0_6_13", "sx.h5"), - h5_path="/sx", - recursive=True, - slash='ignore', - ) - job_sphinx = convert_sphinx_job_dict(job_dict=job_dict) - self.assertEqual(job_sphinx.calculation_output.generic.energy_tot[-1], -228.7831594379917 * ureg.eV) - - def test_lammps(self): - ureg = UnitRegistry() - job_dict = read_dict_from_hdf( - file_name=os.path.join(os.path.dirname(__file__), "pyiron_atomistics_0_6_13", "lmp.h5"), - h5_path="/lmp", - recursive=True, - slash='ignore', - ) - job_lammps = convert_lammps_job_dict(job_dict=job_dict) - self.assertEqual(job_lammps.calculation_output.generic.energy_tot[-1], -9428.45286561574 * ureg.eV) - - def test_vasp(self): - ureg = UnitRegistry() - job_dict = read_dict_from_hdf( - file_name=os.path.join(os.path.dirname(__file__), "pyiron_atomistics_0_6_13", "vasp.h5"), - h5_path="/vasp", - recursive=True, - slash='ignore', - ) - job_vasp = convert_vasp_job_dict(job_dict=job_dict) - self.assertEqual(job_vasp.calculation_output.generic.energy_tot[-1], -14.7459202 * ureg.eV) - def test_all(self): ureg = UnitRegistry() static_folder = os.path.join(os.path.dirname(__file__), "pyiron_atomistics_0_6_13") @@ -62,6 +26,6 @@ def test_all(self): slash='ignore', )[hdf5_file.split(".")[0]] self.assertEqual( - convert(job_dict=job_dict).calculation_output.generic.energy_tot[-1], + get_dataclass(job_dict=job_dict).calculation_output.generic.energy_tot[-1], energy_dict[hdf5_file] )