optimade-maker 0.7.2__tar.gz → 0.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/.github/workflows/ci.yml +6 -6
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/.gitignore +1 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/PKG-INFO +14 -15
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/README.md +4 -2
- optimade_maker-0.9.0/examples/properties/.testing/first_entry.json +1 -0
- optimade_maker-0.9.0/examples/properties/optimade.yaml +45 -0
- optimade_maker-0.9.0/examples/properties/prop1.csv +3 -0
- optimade_maker-0.9.0/examples/properties/prop2.json +18 -0
- optimade_maker-0.9.0/examples/simple_zip_of_cif/.gitignore +2 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/.testing/first_entry.json +1 -1
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/optimade.yaml +3 -8
- optimade_maker-0.9.0/examples/simple_zip_of_cif/properties.csv +3 -0
- optimade_maker-0.9.0/examples/simple_zip_of_cif/structures.zip +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/pyproject.toml +9 -11
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/convert.py +4 -4
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/parsers.py +109 -58
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/serve.py +5 -4
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/PKG-INFO +14 -15
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/SOURCES.txt +7 -11
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/requires.txt +9 -15
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/tests/test_convert.py +5 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/tests/test_serve.py +14 -4
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/uv.lock +20 -28
- optimade_maker-0.7.2/examples/simple_zip_of_cif/data.csv +0 -3
- optimade_maker-0.7.2/scripts/aiida_to_jsonl/aiida_to_jsonl.py +0 -69
- optimade_maker-0.7.2/scripts/cifs_to_jsonl/cifs/55c564f6-ac6a-4122-b8d9-0ad9fe61e961.cif +0 -46
- optimade_maker-0.7.2/scripts/cifs_to_jsonl/cifs/991bec7a-b3a8-49af-ba6d-be5afd685cd4.cif +0 -34
- optimade_maker-0.7.2/scripts/cifs_to_jsonl/cifs/cc1a41b1-a841-4818-baf1-a6c1441dc52a.cif +0 -52
- optimade_maker-0.7.2/scripts/cifs_to_jsonl/cifs_to_jsonl.py +0 -50
- optimade_maker-0.7.2/scripts/cifs_to_jsonl/optimade.jsonl +0 -4
- optimade_maker-0.7.2/scripts/jsonl_server/load_data.py +0 -68
- optimade_maker-0.7.2/scripts/jsonl_server/requirements.txt +0 -1
- optimade_maker-0.7.2/scripts/odbx_file_serialization/requirements.txt +0 -1
- optimade_maker-0.7.2/scripts/odbx_file_serialization/run.py +0 -33
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/.github/CODEOWNERS +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/.github/dependabot.yml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/.github/workflows/release_and_publish.yml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/.pre-commit-config.yaml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/LICENSE +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/aiida_archive/.gitignore +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/aiida_archive/.testing/first_entry.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/aiida_archive/README.md +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/aiida_archive/data.csv +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/aiida_archive/example.aiida +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/aiida_archive/optimade.yaml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/.gitignore +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/.testing/first_entry.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/optimade.yaml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/part_1.json.bz2 +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/direct_from_jsonl/.testing/first_entry.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/direct_from_jsonl/optimade.jsonl +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/direct_from_jsonl/optimade.yaml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/.gitignore +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/.testing/first_entry.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/example.jsonl.gz +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/optimade.yaml +0 -0
- {optimade_maker-0.7.2/examples/simple_zip_of_cif → optimade_maker-0.9.0/examples/properties}/.gitignore +0 -0
- {optimade_maker-0.7.2/examples/simple_zip_of_cif → optimade_maker-0.9.0/examples/properties}/structures.zip +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/.gitignore +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/.testing/first_entry.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/C_1.xyz +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/H_1.xyz +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/H_2.xyz +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/data.csv +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/optimade.yaml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif/.gitignore +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif/.testing/first_entry.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif/README.md +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif/data.tar.gz +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif/optimade.yaml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif/override_config.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif/structures.zip +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/.gitignore +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/.testing/first_entry.json +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/optimade.yaml +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/structures.zip +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/setup.cfg +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/__init__.py +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/aiida_plugin/__init__.py +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/aiida_plugin/config.py +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/cli.py +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/config.py +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/logger.py +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker/mongo_utils.py +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/dependency_links.txt +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/entry_points.txt +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/top_level.txt +0 -0
- {optimade_maker-0.7.2 → optimade_maker-0.9.0}/tests/test_yaml.py +0 -0
|
@@ -63,21 +63,21 @@ jobs:
|
|
|
63
63
|
version: "0.8.x"
|
|
64
64
|
enable-cache: true
|
|
65
65
|
|
|
66
|
-
- name: Install
|
|
66
|
+
- name: Install the minimum environment with testing
|
|
67
67
|
run: |
|
|
68
|
-
uv sync --locked --
|
|
68
|
+
uv sync --locked --extra dev
|
|
69
69
|
|
|
70
70
|
- name: Run tests
|
|
71
71
|
run: |
|
|
72
72
|
uv run pytest -vv --cov=./src/optimade_maker --cov-report=xml --cov-report=term ./tests
|
|
73
73
|
|
|
74
|
-
- name: Reinstall environment
|
|
74
|
+
- name: Reinstall the full environment with all extras
|
|
75
75
|
run: |
|
|
76
|
-
uv sync --locked --
|
|
76
|
+
uv sync --locked --all-extras --dev
|
|
77
77
|
|
|
78
|
-
- name: Rerun tests
|
|
78
|
+
- name: Rerun tests
|
|
79
79
|
run: |
|
|
80
|
-
uv run pytest -vv --cov=./src/optimade_maker --cov-report=xml --cov-report=term ./tests
|
|
80
|
+
uv run pytest -vv --cov=./src/optimade_maker --cov-report=xml --cov-report=term ./tests
|
|
81
81
|
|
|
82
82
|
- name: Upload coverage
|
|
83
83
|
uses: codecov/codecov-action@v3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: optimade-maker
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Tools for making OPTIMADE APIs from raw structural data.
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: optimade,jsonapi,materials
|
|
@@ -15,30 +15,27 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
15
15
|
Requires-Python: <3.13,>=3.10
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: pydantic
|
|
19
|
-
Requires-Dist: optimade[server]~=1.
|
|
20
|
-
Requires-Dist: pymongo
|
|
18
|
+
Requires-Dist: pydantic<3,>=2
|
|
19
|
+
Requires-Dist: optimade[server]~=1.4
|
|
20
|
+
Requires-Dist: pymongo<5,>=4
|
|
21
21
|
Requires-Dist: pyyaml~=6.0
|
|
22
22
|
Requires-Dist: tqdm~=4.65
|
|
23
23
|
Requires-Dist: requests~=2.31
|
|
24
|
-
Requires-Dist: numpy<3,>=1.22
|
|
25
24
|
Requires-Dist: click~=8.1
|
|
26
|
-
|
|
27
|
-
Requires-Dist: ase~=3.22
|
|
25
|
+
Requires-Dist: pandas<3,>=1.5
|
|
26
|
+
Requires-Dist: ase~=3.22
|
|
28
27
|
Provides-Extra: pymatgen
|
|
29
28
|
Requires-Dist: pymatgen>=2023.9; extra == "pymatgen"
|
|
30
|
-
Provides-Extra: pandas
|
|
31
|
-
Requires-Dist: pandas<3,>=1.5; extra == "pandas"
|
|
32
29
|
Provides-Extra: aiida
|
|
33
|
-
Requires-Dist: aiida-core
|
|
34
|
-
Provides-Extra: core
|
|
35
|
-
Requires-Dist: optimade-maker[ase,pandas,pymatgen]; extra == "core"
|
|
30
|
+
Requires-Dist: aiida-core~=2.6; extra == "aiida"
|
|
36
31
|
Provides-Extra: ingest
|
|
37
|
-
Requires-Dist: optimade-maker[aiida,
|
|
32
|
+
Requires-Dist: optimade-maker[aiida,pymatgen]; extra == "ingest"
|
|
38
33
|
Provides-Extra: tests
|
|
39
34
|
Requires-Dist: pytest~=8.3; extra == "tests"
|
|
40
35
|
Requires-Dist: pytest-cov~=6.0; extra == "tests"
|
|
36
|
+
Requires-Dist: numpy<3,>=1.22; extra == "tests"
|
|
41
37
|
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: optimade-maker[tests]; extra == "dev"
|
|
42
39
|
Requires-Dist: ruff; extra == "dev"
|
|
43
40
|
Requires-Dist: pre-commit; extra == "dev"
|
|
44
41
|
Requires-Dist: mypy; extra == "dev"
|
|
@@ -75,6 +72,8 @@ This repository contains the src/optimade-maker Python package and the correspon
|
|
|
75
72
|
Install with
|
|
76
73
|
|
|
77
74
|
```bash
|
|
75
|
+
pip install optimade-maker
|
|
76
|
+
# or to get all ingestion plugins (e.g. pymatgen, aiida):
|
|
78
77
|
pip install optimade-maker[ingest]
|
|
79
78
|
```
|
|
80
79
|
|
|
@@ -106,8 +105,8 @@ entries:
|
|
|
106
105
|
- file: properties.csv
|
|
107
106
|
property_definitions:
|
|
108
107
|
- name: energy
|
|
109
|
-
title: Total energy
|
|
110
|
-
description: DFT total energy
|
|
108
|
+
title: Total energy
|
|
109
|
+
description: DFT total energy
|
|
111
110
|
unit: eV/atom
|
|
112
111
|
type: float
|
|
113
112
|
```
|
|
@@ -29,6 +29,8 @@ This repository contains the src/optimade-maker Python package and the correspon
|
|
|
29
29
|
Install with
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
+
pip install optimade-maker
|
|
33
|
+
# or to get all ingestion plugins (e.g. pymatgen, aiida):
|
|
32
34
|
pip install optimade-maker[ingest]
|
|
33
35
|
```
|
|
34
36
|
|
|
@@ -60,8 +62,8 @@ entries:
|
|
|
60
62
|
- file: properties.csv
|
|
61
63
|
property_definitions:
|
|
62
64
|
- name: energy
|
|
63
|
-
title: Total energy
|
|
64
|
-
description: DFT total energy
|
|
65
|
+
title: Total energy
|
|
66
|
+
description: DFT total energy
|
|
65
67
|
unit: eV/atom
|
|
66
68
|
type: float
|
|
67
69
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id": "set1/101", "type": "structures", "links": null, "meta": null, "attributes": {"immutable_id": "structures.zip/cifs/set1/101.cif", "last_modified": "2026-02-16T13:34:52.085191", "elements": ["Ba", "C", "N", "S"], "nelements": 4, "elements_ratios": [0.14285714285714285, 0.2857142857142857, 0.2857142857142857, 0.2857142857142857], "chemical_formula_descriptive": "C4Ba2N4S4", "chemical_formula_reduced": "BaC2N2S2", "chemical_formula_hill": null, "chemical_formula_anonymous": "A2B2C2D", "dimension_types": [1, 1, 1], "nperiodic_dimensions": 3, "lattice_vectors": [[6.3587627540404945, 0.0, 0.0], [-2.672647488887009, 5.769819681958754, 0.0], [0.25844951934994664, -0.16511343006546234, 8.71190314896161]], "space_group_symmetry_operations_xyz": null, "space_group_symbol_hall": null, "space_group_symbol_hermann_mauguin": null, "space_group_symbol_hermann_mauguin_extended": null, "space_group_it_number": null, "cartesian_site_positions": [[3.4987802863851005, 5.049341739457014, 6.533927361693402], [0.4457844982025419, 0.5553645123824795, 2.177975787264444], [0.37416734784252487, 2.642448780492868, 5.291889331690525], [2.6281157156591126, 1.202488098280357, 7.775965391700042], [3.5703974366609055, 2.962257471400425, 3.420013817271085], [1.316449068841148, 4.402218153614962, 0.9359377571616379], [0.3512600296798777, 4.156339511491648, 5.900755701251229], [4.011419364830723, 1.818004876809729, 7.167099022143105], [3.5933047547393455, 1.4483667404554434, 2.8111474477141454], [-0.06685458032729186, 3.786701375083563, 1.5448041268185058], [0.3773832460379156, 1.5350786992068879, 4.8597303327393915], [1.621957615426957, 0.7399681351855376, 8.208124390751108], [3.567181538468686, 4.069627552684378, 3.8521728163221476], [2.3226071690796486, 4.864738116705728, 0.5037787583104332]], "nsites": 14, "species": [{"name": "N", "chemical_symbols": ["N"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}, {"name": "Ba", "chemical_symbols": ["Ba"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}, {"name": "C", "chemical_symbols": ["C"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}, {"name": "S", "chemical_symbols": ["S"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}], "species_at_sites": ["Ba", "Ba", "C", "C", "C", "C", "S", "S", "S", "S", "N", "N", "N", "N"], "assemblies": null, "structure_features": [], "_optimake_json_list": [[1, 2.0, 3]], "_optimake_dict_property": {"a": 1, "b": 2}, "_optimake_list_property": [[1, 2.0, 3], [3, 2, 3], [1, 5, 6]], "_optimake_json_nested_dict": {"a": 1, "b": {"c": 2, "d": [1, 2, 3]}}, "_optimake_json_float": 2.5, "_optimake_energy": 2.5}, "relationships": null}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
config_version: 0.1.1
|
|
2
|
+
database_description: Simple database
|
|
3
|
+
|
|
4
|
+
entries:
|
|
5
|
+
- entry_type: structures
|
|
6
|
+
entry_paths:
|
|
7
|
+
- file: structures.zip
|
|
8
|
+
matches:
|
|
9
|
+
- cifs/*/*.cif
|
|
10
|
+
# (optional) property file and definitions:
|
|
11
|
+
property_paths:
|
|
12
|
+
- file: prop1.csv
|
|
13
|
+
- file: prop2.json
|
|
14
|
+
property_definitions:
|
|
15
|
+
# properties in the csv file
|
|
16
|
+
- name: energy
|
|
17
|
+
title: Total energy per atom
|
|
18
|
+
description: The total energy per atom as computed by DFT
|
|
19
|
+
unit: eV/atom
|
|
20
|
+
type: float
|
|
21
|
+
- name: list_property
|
|
22
|
+
title: List property
|
|
23
|
+
description: A 3x3 matrix property
|
|
24
|
+
type: list
|
|
25
|
+
- name: dict_property
|
|
26
|
+
title: Dictionary property
|
|
27
|
+
description: A dictionary property
|
|
28
|
+
type: dictionary
|
|
29
|
+
# properties in the json file
|
|
30
|
+
- name: json_float
|
|
31
|
+
title: JSON float property
|
|
32
|
+
description: A JSON float property
|
|
33
|
+
type: float
|
|
34
|
+
aliases:
|
|
35
|
+
- json_float_alias1
|
|
36
|
+
- json_float_alias2
|
|
37
|
+
- json_float_alias3
|
|
38
|
+
- name: json_list
|
|
39
|
+
title: JSON list property
|
|
40
|
+
description: A JSON list property
|
|
41
|
+
type: list
|
|
42
|
+
- name: json_nested_dict
|
|
43
|
+
title: JSON nested dictionary property
|
|
44
|
+
description: A nested dictionary property in JSON format
|
|
45
|
+
type: dictionary
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"set1/101": {
|
|
3
|
+
"json_float_alias2": 2.5,
|
|
4
|
+
"json_list": [[1, 2.0, 3]],
|
|
5
|
+
"json_nested_dict": {
|
|
6
|
+
"a": 1,
|
|
7
|
+
"b": {
|
|
8
|
+
"c": 2,
|
|
9
|
+
"d": [1, 2, 3]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"structures.zip/cifs/set2/102.cif": {
|
|
14
|
+
"json_float_alias3": 3.2,
|
|
15
|
+
"json_list": null,
|
|
16
|
+
"json_nested_dict": null
|
|
17
|
+
}
|
|
18
|
+
}
|
{optimade_maker-0.7.2 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/.testing/first_entry.json
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id": "set1/101", "type": "structures", "links": null, "meta": null, "attributes": {"immutable_id": "structures.zip/cifs/set1/101.cif", "last_modified": "
|
|
1
|
+
{"id": "set1/101", "type": "structures", "links": null, "meta": null, "attributes": {"immutable_id": "structures.zip/cifs/set1/101.cif", "last_modified": "2026-02-16T13:37:21.465430", "elements": ["Ba", "C", "N", "S"], "nelements": 4, "elements_ratios": [0.14285714285714285, 0.2857142857142857, 0.2857142857142857, 0.2857142857142857], "chemical_formula_descriptive": "C4Ba2N4S4", "chemical_formula_reduced": "BaC2N2S2", "chemical_formula_hill": null, "chemical_formula_anonymous": "A2B2C2D", "dimension_types": [1, 1, 1], "nperiodic_dimensions": 3, "lattice_vectors": [[6.3587627540404945, 0.0, 0.0], [-2.672647488887009, 5.769819681958754, 0.0], [0.25844951934994664, -0.16511343006546234, 8.71190314896161]], "space_group_symmetry_operations_xyz": null, "space_group_symbol_hall": null, "space_group_symbol_hermann_mauguin": null, "space_group_symbol_hermann_mauguin_extended": null, "space_group_it_number": null, "cartesian_site_positions": [[3.4987802863851005, 5.049341739457014, 6.533927361693402], [0.4457844982025419, 0.5553645123824795, 2.177975787264444], [0.37416734784252487, 2.642448780492868, 5.291889331690525], [2.6281157156591126, 1.202488098280357, 7.775965391700042], [3.5703974366609055, 2.962257471400425, 3.420013817271085], [1.316449068841148, 4.402218153614962, 0.9359377571616379], [0.3512600296798777, 4.156339511491648, 5.900755701251229], [4.011419364830723, 1.818004876809729, 7.167099022143105], [3.5933047547393455, 1.4483667404554434, 2.8111474477141454], [-0.06685458032729186, 3.786701375083563, 1.5448041268185058], [0.3773832460379156, 1.5350786992068879, 4.8597303327393915], [1.621957615426957, 0.7399681351855376, 8.208124390751108], [3.567181538468686, 4.069627552684378, 3.8521728163221476], [2.3226071690796486, 4.864738116705728, 0.5037787583104332]], "nsites": 14, "species": [{"name": "C", "chemical_symbols": ["C"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}, {"name": "S", "chemical_symbols": ["S"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}, {"name": "Ba", "chemical_symbols": ["Ba"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}, {"name": "N", "chemical_symbols": ["N"], "concentration": [1.0], "mass": null, "original_name": null, "attached": null, "nattached": null}], "species_at_sites": ["Ba", "Ba", "C", "C", "C", "C", "S", "S", "S", "S", "N", "N", "N", "N"], "assemblies": null, "structure_features": [], "_optimake_energy": 2.5}, "relationships": null}
|
|
@@ -9,15 +9,10 @@ entries:
|
|
|
9
9
|
- cifs/*/*.cif
|
|
10
10
|
# (optional) property file and definitions:
|
|
11
11
|
property_paths:
|
|
12
|
-
- file:
|
|
12
|
+
- file: properties.csv
|
|
13
13
|
property_definitions:
|
|
14
14
|
- name: energy
|
|
15
|
-
title: Total energy
|
|
16
|
-
description:
|
|
15
|
+
title: Total energy
|
|
16
|
+
description: DFT total energy
|
|
17
17
|
unit: eV/atom
|
|
18
18
|
type: float
|
|
19
|
-
- name: list_property
|
|
20
|
-
title: List property
|
|
21
|
-
description: A 3x3 matrix property encoded as a string
|
|
22
|
-
type: list
|
|
23
|
-
unit: null
|
|
Binary file
|
|
@@ -19,14 +19,15 @@ classifiers = [
|
|
|
19
19
|
]
|
|
20
20
|
|
|
21
21
|
dependencies = [
|
|
22
|
-
"pydantic
|
|
23
|
-
"optimade[server]~=1.
|
|
24
|
-
"pymongo",
|
|
22
|
+
"pydantic>=2,<3",
|
|
23
|
+
"optimade[server]~=1.4",
|
|
24
|
+
"pymongo>=4,<5",
|
|
25
25
|
"pyyaml~=6.0",
|
|
26
26
|
"tqdm~=4.65",
|
|
27
27
|
"requests~=2.31",
|
|
28
|
-
"numpy >= 1.22, < 3",
|
|
29
28
|
"click~=8.1",
|
|
29
|
+
"pandas>=1.5,<3",
|
|
30
|
+
"ase~=3.22",
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
[project.scripts]
|
|
@@ -41,14 +42,11 @@ fallback_version = "0.1.0"
|
|
|
41
42
|
version_scheme = "post-release"
|
|
42
43
|
|
|
43
44
|
[project.optional-dependencies]
|
|
44
|
-
ase = ["ase ~= 3.22"]
|
|
45
45
|
pymatgen = ["pymatgen >= 2023.9"]
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
tests = ["pytest~=8.3", "pytest-cov~=6.0"]
|
|
51
|
-
dev = ["ruff", "pre-commit", "mypy"]
|
|
46
|
+
aiida = ["aiida-core ~= 2.6"]
|
|
47
|
+
ingest = ["optimade-maker[pymatgen,aiida]"]
|
|
48
|
+
tests = ["pytest~=8.3", "pytest-cov~=6.0", "numpy >= 1.22, < 3"]
|
|
49
|
+
dev = ["optimade-maker[tests]", "ruff", "pre-commit", "mypy"]
|
|
52
50
|
|
|
53
51
|
[tool.ruff]
|
|
54
52
|
target-version = "py311"
|
|
@@ -173,7 +173,7 @@ def inflate_archive(archive_path: Path, data_path: Path) -> None:
|
|
|
173
173
|
# If .tar in filename suffixes, use `tarfile`'s compression detection
|
|
174
174
|
elif ".tar" in real_path.suffixes:
|
|
175
175
|
with tarfile.open(real_path, "r") as tar:
|
|
176
|
-
tar.extractall(path=real_path.parent)
|
|
176
|
+
tar.extractall(path=real_path.parent, filter="data")
|
|
177
177
|
|
|
178
178
|
# Otherwise assume this is a single compressed file
|
|
179
179
|
# Decompress it and write it using the appropriate
|
|
@@ -306,11 +306,11 @@ def _parse_entries(
|
|
|
306
306
|
entry_ids.append(id_root)
|
|
307
307
|
break
|
|
308
308
|
except Exception as exc:
|
|
309
|
-
exceptions[parser] = exc
|
|
309
|
+
exceptions[parser.__name__] = exc
|
|
310
310
|
continue
|
|
311
311
|
else:
|
|
312
312
|
raise RuntimeError(
|
|
313
|
-
f"None of the provided parsers
|
|
313
|
+
f"None of the provided parsers could parse {_path}. Errors: {exceptions}"
|
|
314
314
|
)
|
|
315
315
|
|
|
316
316
|
if len(set(entry_ids)) != len(entry_ids):
|
|
@@ -573,7 +573,7 @@ def construct_entries_from_files(
|
|
|
573
573
|
try:
|
|
574
574
|
entry = converter(
|
|
575
575
|
entry,
|
|
576
|
-
|
|
576
|
+
prop_defs=entry_config.property_definitions,
|
|
577
577
|
prefix=provider_prefix,
|
|
578
578
|
) # type: ignore[call-arg]
|
|
579
579
|
if not isinstance(entry, dict):
|
|
@@ -3,19 +3,8 @@ import warnings
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Any, Callable
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
try:
|
|
9
|
-
import ase.io
|
|
10
|
-
import pandas
|
|
11
|
-
import pymatgen.core
|
|
12
|
-
import pymatgen.entries.computed_entries
|
|
13
|
-
from pymatgen.entries.computed_entries import ComputedStructureEntry
|
|
14
|
-
except ImportError as exc:
|
|
15
|
-
raise ImportError(
|
|
16
|
-
"The parsers module requires the `ingest` extra of this package to be installed."
|
|
17
|
-
) from exc
|
|
18
|
-
|
|
6
|
+
import ase.io
|
|
7
|
+
import pandas
|
|
19
8
|
from optimade.adapters import Structure
|
|
20
9
|
from optimade.models import DataType, EntryResource
|
|
21
10
|
|
|
@@ -24,7 +13,7 @@ from optimade_maker.config import PropertyDefinition
|
|
|
24
13
|
|
|
25
14
|
def load_csv_file(
|
|
26
15
|
p: Path,
|
|
27
|
-
|
|
16
|
+
prop_defs: list[PropertyDefinition] | None = None,
|
|
28
17
|
) -> dict[str, dict[str, Any]]:
|
|
29
18
|
"""Parses a CSV file found at path `p` and returns a dictionary
|
|
30
19
|
of properties keyed by ID.
|
|
@@ -34,7 +23,7 @@ def load_csv_file(
|
|
|
34
23
|
|
|
35
24
|
Parameters:
|
|
36
25
|
p: Path to the CSV file.
|
|
37
|
-
|
|
26
|
+
prop_defs: List of property definitions to extract from the CSV file.
|
|
38
27
|
|
|
39
28
|
Returns:
|
|
40
29
|
A dictionary of ID -> properties.
|
|
@@ -55,40 +44,79 @@ def load_csv_file(
|
|
|
55
44
|
df["id"] = df[id_key]
|
|
56
45
|
df = df.set_index("id")
|
|
57
46
|
|
|
58
|
-
for
|
|
47
|
+
for prop_def in prop_defs or []:
|
|
59
48
|
# loop through any property aliases, saving the value if found and only checking
|
|
60
49
|
# the real name if not
|
|
61
|
-
for alias in
|
|
50
|
+
for alias in prop_def.aliases or []:
|
|
62
51
|
if alias in df:
|
|
63
|
-
df[
|
|
52
|
+
df[prop_def.name] = df[alias]
|
|
64
53
|
df.drop(columns=[alias], inplace=True)
|
|
65
54
|
break
|
|
66
55
|
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
56
|
+
# For list and dict types, interpret string values as JSON
|
|
57
|
+
for prop_def in prop_defs or []:
|
|
58
|
+
if (
|
|
59
|
+
prop_def.type in (DataType.LIST, DataType.DICTIONARY)
|
|
60
|
+
and prop_def.name in df.columns
|
|
61
|
+
):
|
|
62
|
+
# Replace NaN -> "null"
|
|
63
|
+
df[prop_def.name] = df[prop_def.name].fillna("null")
|
|
71
64
|
try:
|
|
72
|
-
df[
|
|
73
|
-
|
|
74
|
-
.fillna(np.nan)
|
|
75
|
-
.replace([np.nan], ["null"])
|
|
76
|
-
.apply(json.loads)
|
|
65
|
+
df[prop_def.name] = df[prop_def.name].apply(
|
|
66
|
+
lambda v: json.loads(v) if isinstance(v, str) else v
|
|
77
67
|
)
|
|
78
68
|
except Exception as exc:
|
|
79
69
|
warnings.warn(
|
|
80
|
-
f"Tried to interpret property {
|
|
70
|
+
f"Tried to interpret property {prop_def.name!r} as JSON, but got "
|
|
71
|
+
f"{exc.__class__.__name__}: {exc!r}"
|
|
81
72
|
)
|
|
82
|
-
pass
|
|
83
73
|
|
|
84
74
|
return df.to_dict(orient="index")
|
|
85
75
|
|
|
86
76
|
|
|
77
|
+
def load_json_file(
|
|
78
|
+
p: Path,
|
|
79
|
+
prop_defs: list[PropertyDefinition] | None = None,
|
|
80
|
+
) -> dict[str, dict[str, Any]]:
|
|
81
|
+
"""Parses a JSON file found at path `p` and returns a dictionary
|
|
82
|
+
of properties keyed by ID.
|
|
83
|
+
|
|
84
|
+
Expects either a list of objects (each with an "id" field) or a dictionary
|
|
85
|
+
already keyed by IDs. If a list is provided, the "id" field of each object
|
|
86
|
+
will be used as the dictionary key.
|
|
87
|
+
|
|
88
|
+
Parameters:
|
|
89
|
+
p: Path to the JSON file.
|
|
90
|
+
prop_defs: List of property definitions to extract from the JSON data.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
A dictionary of ID -> properties.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
with open(p, "r") as f:
|
|
97
|
+
data = json.load(f)
|
|
98
|
+
|
|
99
|
+
if isinstance(data, list):
|
|
100
|
+
data_dict = {}
|
|
101
|
+
for item in data:
|
|
102
|
+
id_value = item.get("id")
|
|
103
|
+
if not id_value:
|
|
104
|
+
raise RuntimeError(f"JSON item {item} missing 'id'")
|
|
105
|
+
data_dict[id_value] = item
|
|
106
|
+
data = data_dict
|
|
107
|
+
|
|
108
|
+
for prop_def in prop_defs or []:
|
|
109
|
+
for alias in prop_def.aliases or []:
|
|
110
|
+
for row_id, row in data.items():
|
|
111
|
+
if alias in row:
|
|
112
|
+
row[prop_def.name] = row.pop(alias)
|
|
113
|
+
|
|
114
|
+
return data
|
|
115
|
+
|
|
116
|
+
|
|
87
117
|
PROPERTY_PARSERS: dict[
|
|
88
118
|
str, list[Callable[[Path, list[PropertyDefinition] | None], Any]]
|
|
89
|
-
] = {
|
|
90
|
-
".csv": [load_csv_file],
|
|
91
|
-
}
|
|
119
|
+
] = {".csv": [load_csv_file], ".json": [load_json_file]}
|
|
92
120
|
|
|
93
121
|
TYPE_MAP: dict[DataType, type] = {
|
|
94
122
|
DataType.FLOAT: float,
|
|
@@ -98,6 +126,29 @@ TYPE_MAP: dict[DataType, type] = {
|
|
|
98
126
|
}
|
|
99
127
|
|
|
100
128
|
|
|
129
|
+
ENTRY_PARSERS: dict[str, list[Callable[[Path], Any]]] = {
|
|
130
|
+
"structures": [ase.io.read],
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def structure_ingest_wrapper(entry, prop_defs=None, prefix=None): # type: ignore
|
|
135
|
+
return Structure.ingest_from(entry)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
OPTIMADE_CONVERTERS: dict[
|
|
139
|
+
str,
|
|
140
|
+
list[
|
|
141
|
+
Callable[
|
|
142
|
+
[Any, list[PropertyDefinition] | None, str | None], EntryResource | dict
|
|
143
|
+
]
|
|
144
|
+
],
|
|
145
|
+
] = {
|
|
146
|
+
"structures": [structure_ingest_wrapper],
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#### Wrappers for third-party parsers and converters, such as pymatgen ####
|
|
150
|
+
|
|
151
|
+
|
|
101
152
|
def wrapped_json_parser(parser):
|
|
102
153
|
"""This wrapper allows `from_dict` parser functions to be called
|
|
103
154
|
on a single JSON file.
|
|
@@ -133,20 +184,9 @@ def wrapped_json_parser(parser):
|
|
|
133
184
|
return _wrapped_json_parser
|
|
134
185
|
|
|
135
186
|
|
|
136
|
-
ENTRY_PARSERS: dict[str, list[Callable[[Path], Any]]] = {
|
|
137
|
-
"structures": [
|
|
138
|
-
ase.io.read,
|
|
139
|
-
wrapped_json_parser(
|
|
140
|
-
pymatgen.entries.computed_entries.ComputedStructureEntry.from_dict
|
|
141
|
-
),
|
|
142
|
-
wrapped_json_parser(pymatgen.core.Structure.from_dict),
|
|
143
|
-
],
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
187
|
def convert_pymatgen_computed_structure_entry(
|
|
148
|
-
pmg_entry
|
|
149
|
-
|
|
188
|
+
pmg_entry,
|
|
189
|
+
prop_defs: list[PropertyDefinition] | None = None,
|
|
150
190
|
prefix: str | None = None,
|
|
151
191
|
) -> dict:
|
|
152
192
|
"""Convert a pymatgen ComputedStructureEntry to an OPTIMADE EntryResource."""
|
|
@@ -159,7 +199,7 @@ def convert_pymatgen_computed_structure_entry(
|
|
|
159
199
|
entry["id"] = id
|
|
160
200
|
break
|
|
161
201
|
|
|
162
|
-
for p in
|
|
202
|
+
for p in prop_defs or []:
|
|
163
203
|
# loop through any property aliases, saving the value if found and only checking
|
|
164
204
|
# the real name if not
|
|
165
205
|
for alias in p.aliases or []:
|
|
@@ -172,17 +212,28 @@ def convert_pymatgen_computed_structure_entry(
|
|
|
172
212
|
return entry
|
|
173
213
|
|
|
174
214
|
|
|
175
|
-
def
|
|
176
|
-
|
|
215
|
+
def add_pymatgen_parsers():
|
|
216
|
+
try:
|
|
217
|
+
import pymatgen.core
|
|
218
|
+
import pymatgen.entries.computed_entries
|
|
177
219
|
|
|
220
|
+
ENTRY_PARSERS["structures"].extend(
|
|
221
|
+
[
|
|
222
|
+
wrapped_json_parser(
|
|
223
|
+
pymatgen.entries.computed_entries.ComputedStructureEntry.from_dict
|
|
224
|
+
),
|
|
225
|
+
wrapped_json_parser(pymatgen.core.Structure.from_dict),
|
|
226
|
+
]
|
|
227
|
+
)
|
|
178
228
|
|
|
179
|
-
OPTIMADE_CONVERTERS
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
229
|
+
OPTIMADE_CONVERTERS["structures"].append(
|
|
230
|
+
convert_pymatgen_computed_structure_entry
|
|
231
|
+
)
|
|
232
|
+
except ImportError:
|
|
233
|
+
warnings.warn(
|
|
234
|
+
"pymatgen is not installed, so corresponding parsers and converters will not be available. "
|
|
235
|
+
"To use these, install the 'pymatgen' extra."
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
add_pymatgen_parsers()
|
|
@@ -287,11 +287,12 @@ class OptimakeServer:
|
|
|
287
287
|
LOGGER.info("Using the MongoMock backend.")
|
|
288
288
|
if skip_mock:
|
|
289
289
|
return
|
|
290
|
-
#
|
|
291
|
-
|
|
292
|
-
from optimade.server.entry_collections.mongo import
|
|
290
|
+
# Get the MongoMock client from optimade-python-tools
|
|
291
|
+
from optimade.server.config import ServerConfig
|
|
292
|
+
from optimade.server.entry_collections.mongo import get_mongo_client
|
|
293
293
|
|
|
294
|
-
|
|
294
|
+
client = get_mongo_client(ServerConfig())
|
|
295
|
+
mongo_db = client[db_name]
|
|
295
296
|
else:
|
|
296
297
|
raise ValueError(
|
|
297
298
|
f"Unknown database backend '{db_backend}'. "
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: optimade-maker
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Tools for making OPTIMADE APIs from raw structural data.
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: optimade,jsonapi,materials
|
|
@@ -15,30 +15,27 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
15
15
|
Requires-Python: <3.13,>=3.10
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: pydantic
|
|
19
|
-
Requires-Dist: optimade[server]~=1.
|
|
20
|
-
Requires-Dist: pymongo
|
|
18
|
+
Requires-Dist: pydantic<3,>=2
|
|
19
|
+
Requires-Dist: optimade[server]~=1.4
|
|
20
|
+
Requires-Dist: pymongo<5,>=4
|
|
21
21
|
Requires-Dist: pyyaml~=6.0
|
|
22
22
|
Requires-Dist: tqdm~=4.65
|
|
23
23
|
Requires-Dist: requests~=2.31
|
|
24
|
-
Requires-Dist: numpy<3,>=1.22
|
|
25
24
|
Requires-Dist: click~=8.1
|
|
26
|
-
|
|
27
|
-
Requires-Dist: ase~=3.22
|
|
25
|
+
Requires-Dist: pandas<3,>=1.5
|
|
26
|
+
Requires-Dist: ase~=3.22
|
|
28
27
|
Provides-Extra: pymatgen
|
|
29
28
|
Requires-Dist: pymatgen>=2023.9; extra == "pymatgen"
|
|
30
|
-
Provides-Extra: pandas
|
|
31
|
-
Requires-Dist: pandas<3,>=1.5; extra == "pandas"
|
|
32
29
|
Provides-Extra: aiida
|
|
33
|
-
Requires-Dist: aiida-core
|
|
34
|
-
Provides-Extra: core
|
|
35
|
-
Requires-Dist: optimade-maker[ase,pandas,pymatgen]; extra == "core"
|
|
30
|
+
Requires-Dist: aiida-core~=2.6; extra == "aiida"
|
|
36
31
|
Provides-Extra: ingest
|
|
37
|
-
Requires-Dist: optimade-maker[aiida,
|
|
32
|
+
Requires-Dist: optimade-maker[aiida,pymatgen]; extra == "ingest"
|
|
38
33
|
Provides-Extra: tests
|
|
39
34
|
Requires-Dist: pytest~=8.3; extra == "tests"
|
|
40
35
|
Requires-Dist: pytest-cov~=6.0; extra == "tests"
|
|
36
|
+
Requires-Dist: numpy<3,>=1.22; extra == "tests"
|
|
41
37
|
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: optimade-maker[tests]; extra == "dev"
|
|
42
39
|
Requires-Dist: ruff; extra == "dev"
|
|
43
40
|
Requires-Dist: pre-commit; extra == "dev"
|
|
44
41
|
Requires-Dist: mypy; extra == "dev"
|
|
@@ -75,6 +72,8 @@ This repository contains the src/optimade-maker Python package and the correspon
|
|
|
75
72
|
Install with
|
|
76
73
|
|
|
77
74
|
```bash
|
|
75
|
+
pip install optimade-maker
|
|
76
|
+
# or to get all ingestion plugins (e.g. pymatgen, aiida):
|
|
78
77
|
pip install optimade-maker[ingest]
|
|
79
78
|
```
|
|
80
79
|
|
|
@@ -106,8 +105,8 @@ entries:
|
|
|
106
105
|
- file: properties.csv
|
|
107
106
|
property_definitions:
|
|
108
107
|
- name: energy
|
|
109
|
-
title: Total energy
|
|
110
|
-
description: DFT total energy
|
|
108
|
+
title: Total energy
|
|
109
|
+
description: DFT total energy
|
|
111
110
|
unit: eV/atom
|
|
112
111
|
type: float
|
|
113
112
|
```
|