optimade-maker 0.8.0__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.8.0 → optimade_maker-0.9.0}/.github/workflows/ci.yml +6 -6
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/PKG-INFO +14 -15
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/README.md +4 -2
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/optimade.yaml +3 -3
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/pyproject.toml +9 -11
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/convert.py +3 -3
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/parsers.py +50 -40
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/PKG-INFO +14 -15
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/SOURCES.txt +1 -1
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/requires.txt +9 -15
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/tests/test_convert.py +5 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/tests/test_serve.py +14 -4
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/uv.lock +16 -24
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.github/CODEOWNERS +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.github/dependabot.yml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.github/workflows/release_and_publish.yml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.pre-commit-config.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/LICENSE +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/README.md +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/data.csv +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/example.aiida +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/part_1.json.bz2 +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl/optimade.jsonl +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/example.jsonl.gz +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/prop1.csv +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/prop2.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/structures.zip +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/.testing/first_entry.json +0 -0
- /optimade_maker-0.8.0/examples/simple_zip_of_cif/data.csv → /optimade_maker-0.9.0/examples/simple_zip_of_cif/properties.csv +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/structures.zip +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/C_1.xyz +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/H_1.xyz +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/H_2.xyz +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/data.csv +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/README.md +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/data.tar.gz +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/override_config.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/structures.zip +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/.gitignore +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/.testing/first_entry.json +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/optimade.yaml +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/structures.zip +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/setup.cfg +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/__init__.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/aiida_plugin/__init__.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/aiida_plugin/config.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/cli.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/config.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/logger.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/mongo_utils.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/serve.py +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/dependency_links.txt +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/entry_points.txt +0 -0
- {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/top_level.txt +0 -0
- {optimade_maker-0.8.0 → 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.4
|
|
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
|
```
|
|
@@ -9,10 +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,14 +19,15 @@ classifiers = [
|
|
|
19
19
|
]
|
|
20
20
|
|
|
21
21
|
dependencies = [
|
|
22
|
-
"pydantic
|
|
23
|
-
"optimade[server]~=1.4
|
|
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):
|
|
@@ -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
|
|
|
@@ -71,9 +60,7 @@ def load_csv_file(
|
|
|
71
60
|
and prop_def.name in df.columns
|
|
72
61
|
):
|
|
73
62
|
# Replace NaN -> "null"
|
|
74
|
-
df[prop_def.name] = (
|
|
75
|
-
df[prop_def.name].fillna(np.nan).replace({np.nan: "null"})
|
|
76
|
-
)
|
|
63
|
+
df[prop_def.name] = df[prop_def.name].fillna("null")
|
|
77
64
|
try:
|
|
78
65
|
df[prop_def.name] = df[prop_def.name].apply(
|
|
79
66
|
lambda v: json.loads(v) if isinstance(v, str) else v
|
|
@@ -139,6 +126,29 @@ TYPE_MAP: dict[DataType, type] = {
|
|
|
139
126
|
}
|
|
140
127
|
|
|
141
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
|
+
|
|
142
152
|
def wrapped_json_parser(parser):
|
|
143
153
|
"""This wrapper allows `from_dict` parser functions to be called
|
|
144
154
|
on a single JSON file.
|
|
@@ -174,19 +184,8 @@ def wrapped_json_parser(parser):
|
|
|
174
184
|
return _wrapped_json_parser
|
|
175
185
|
|
|
176
186
|
|
|
177
|
-
ENTRY_PARSERS: dict[str, list[Callable[[Path], Any]]] = {
|
|
178
|
-
"structures": [
|
|
179
|
-
ase.io.read,
|
|
180
|
-
wrapped_json_parser(
|
|
181
|
-
pymatgen.entries.computed_entries.ComputedStructureEntry.from_dict
|
|
182
|
-
),
|
|
183
|
-
wrapped_json_parser(pymatgen.core.Structure.from_dict),
|
|
184
|
-
],
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
187
|
def convert_pymatgen_computed_structure_entry(
|
|
189
|
-
pmg_entry
|
|
188
|
+
pmg_entry,
|
|
190
189
|
prop_defs: list[PropertyDefinition] | None = None,
|
|
191
190
|
prefix: str | None = None,
|
|
192
191
|
) -> dict:
|
|
@@ -213,17 +212,28 @@ def convert_pymatgen_computed_structure_entry(
|
|
|
213
212
|
return entry
|
|
214
213
|
|
|
215
214
|
|
|
216
|
-
def
|
|
217
|
-
|
|
215
|
+
def add_pymatgen_parsers():
|
|
216
|
+
try:
|
|
217
|
+
import pymatgen.core
|
|
218
|
+
import pymatgen.entries.computed_entries
|
|
218
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
|
+
)
|
|
219
228
|
|
|
220
|
-
OPTIMADE_CONVERTERS
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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()
|
|
@@ -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.4
|
|
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
|
```
|
|
@@ -32,8 +32,8 @@ examples/properties/prop2.json
|
|
|
32
32
|
examples/properties/structures.zip
|
|
33
33
|
examples/properties/.testing/first_entry.json
|
|
34
34
|
examples/simple_zip_of_cif/.gitignore
|
|
35
|
-
examples/simple_zip_of_cif/data.csv
|
|
36
35
|
examples/simple_zip_of_cif/optimade.yaml
|
|
36
|
+
examples/simple_zip_of_cif/properties.csv
|
|
37
37
|
examples/simple_zip_of_cif/structures.zip
|
|
38
38
|
examples/simple_zip_of_cif/.testing/first_entry.json
|
|
39
39
|
examples/xyz_files_no_compression/.gitignore
|
|
@@ -1,31 +1,24 @@
|
|
|
1
|
-
pydantic
|
|
2
|
-
optimade[server]~=1.4
|
|
3
|
-
pymongo
|
|
1
|
+
pydantic<3,>=2
|
|
2
|
+
optimade[server]~=1.4
|
|
3
|
+
pymongo<5,>=4
|
|
4
4
|
pyyaml~=6.0
|
|
5
5
|
tqdm~=4.65
|
|
6
6
|
requests~=2.31
|
|
7
|
-
numpy<3,>=1.22
|
|
8
7
|
click~=8.1
|
|
9
|
-
|
|
10
|
-
[aiida]
|
|
11
|
-
aiida-core>=2.6.3
|
|
12
|
-
|
|
13
|
-
[ase]
|
|
8
|
+
pandas<3,>=1.5
|
|
14
9
|
ase~=3.22
|
|
15
10
|
|
|
16
|
-
[
|
|
17
|
-
|
|
11
|
+
[aiida]
|
|
12
|
+
aiida-core~=2.6
|
|
18
13
|
|
|
19
14
|
[dev]
|
|
15
|
+
optimade-maker[tests]
|
|
20
16
|
ruff
|
|
21
17
|
pre-commit
|
|
22
18
|
mypy
|
|
23
19
|
|
|
24
20
|
[ingest]
|
|
25
|
-
optimade-maker[aiida,
|
|
26
|
-
|
|
27
|
-
[pandas]
|
|
28
|
-
pandas<3,>=1.5
|
|
21
|
+
optimade-maker[aiida,pymatgen]
|
|
29
22
|
|
|
30
23
|
[pymatgen]
|
|
31
24
|
pymatgen>=2023.9
|
|
@@ -33,3 +26,4 @@ pymatgen>=2023.9
|
|
|
33
26
|
[tests]
|
|
34
27
|
pytest~=8.3
|
|
35
28
|
pytest-cov~=6.0
|
|
29
|
+
numpy<3,>=1.22
|
|
@@ -10,6 +10,7 @@ from optimade.models import EntryInfoResource
|
|
|
10
10
|
from optimade_maker.convert import convert_archive
|
|
11
11
|
|
|
12
12
|
AIIDA_AVAILABLE = bool(importlib.util.find_spec("aiida"))
|
|
13
|
+
PYMATGEN_AVAILABLE = bool(importlib.util.find_spec("pymatgen"))
|
|
13
14
|
|
|
14
15
|
EXAMPLE_ARCHIVES = (Path(__file__).parent.parent / "examples").glob("*")
|
|
15
16
|
|
|
@@ -28,6 +29,10 @@ def test_convert_example_archives(archive_path, tmp_path):
|
|
|
28
29
|
pytest.skip(
|
|
29
30
|
"Skipping test for AiiDA archive, as it requires AiiDA to be installed."
|
|
30
31
|
)
|
|
32
|
+
if "pymatgen" in archive_path.name and not PYMATGEN_AVAILABLE:
|
|
33
|
+
pytest.skip(
|
|
34
|
+
"Skipping test for pymatgen archive, as it requires pymatgen to be installed."
|
|
35
|
+
)
|
|
31
36
|
# copy example into temporary path
|
|
32
37
|
tmp_path = tmp_path / archive_path.name
|
|
33
38
|
shutil.copytree(archive_path, tmp_path)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import importlib.util
|
|
2
2
|
import json
|
|
3
3
|
import shutil
|
|
4
|
+
import socket
|
|
4
5
|
import subprocess
|
|
5
6
|
import time
|
|
6
7
|
from pathlib import Path
|
|
@@ -9,11 +10,18 @@ import pytest
|
|
|
9
10
|
import requests
|
|
10
11
|
|
|
11
12
|
AIIDA_AVAILABLE = bool(importlib.util.find_spec("aiida"))
|
|
13
|
+
PYMATGEN_AVAILABLE = bool(importlib.util.find_spec("pymatgen"))
|
|
12
14
|
|
|
13
15
|
EXAMPLE_ARCHIVES = (Path(__file__).parent.parent / "examples").glob("*")
|
|
14
16
|
|
|
15
17
|
|
|
16
|
-
def
|
|
18
|
+
def _get_free_port(host: str) -> int:
|
|
19
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
20
|
+
s.bind((host, 0))
|
|
21
|
+
return s.getsockname()[1]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def wait_for_server_to_start(url, retries=10, delay=1):
|
|
17
25
|
for _ in range(retries):
|
|
18
26
|
try:
|
|
19
27
|
response = requests.get(url)
|
|
@@ -33,6 +41,10 @@ def test_serve_example_archives(archive_path, tmp_path):
|
|
|
33
41
|
pytest.skip(
|
|
34
42
|
"Skipping test for AiiDA archive, as it requires AiiDA to be installed."
|
|
35
43
|
)
|
|
44
|
+
if "pymatgen" in archive_path.name and not PYMATGEN_AVAILABLE:
|
|
45
|
+
pytest.skip(
|
|
46
|
+
"Skipping test for pymatgen archive, as it requires pymatgen to be installed."
|
|
47
|
+
)
|
|
36
48
|
# copy example into temporary path
|
|
37
49
|
tmp_path = tmp_path / archive_path.name
|
|
38
50
|
shutil.copytree(archive_path, tmp_path)
|
|
@@ -46,11 +58,9 @@ def test_serve_example_archives(archive_path, tmp_path):
|
|
|
46
58
|
if override_config is not None:
|
|
47
59
|
custom_prefix = override_config.get("provider", {}).get("prefix")
|
|
48
60
|
|
|
49
|
-
# use an uncommon port that hopefully is unused
|
|
50
|
-
port = 43486
|
|
51
61
|
host = "127.0.0.1"
|
|
62
|
+
port = _get_free_port(host)
|
|
52
63
|
|
|
53
|
-
# use subprocess to start the api via the cli
|
|
54
64
|
command = [
|
|
55
65
|
"optimake",
|
|
56
66
|
"serve",
|
|
@@ -1391,9 +1391,10 @@ server = [
|
|
|
1391
1391
|
name = "optimade-maker"
|
|
1392
1392
|
source = { editable = "." }
|
|
1393
1393
|
dependencies = [
|
|
1394
|
+
{ name = "ase" },
|
|
1394
1395
|
{ name = "click" },
|
|
1395
|
-
{ name = "numpy" },
|
|
1396
1396
|
{ name = "optimade", extra = ["server"] },
|
|
1397
|
+
{ name = "pandas" },
|
|
1397
1398
|
{ name = "pydantic" },
|
|
1398
1399
|
{ name = "pymongo" },
|
|
1399
1400
|
{ name = "pyyaml" },
|
|
@@ -1405,51 +1406,42 @@ dependencies = [
|
|
|
1405
1406
|
aiida = [
|
|
1406
1407
|
{ name = "aiida-core" },
|
|
1407
1408
|
]
|
|
1408
|
-
ase = [
|
|
1409
|
-
{ name = "ase" },
|
|
1410
|
-
]
|
|
1411
|
-
core = [
|
|
1412
|
-
{ name = "ase" },
|
|
1413
|
-
{ name = "pandas" },
|
|
1414
|
-
{ name = "pymatgen" },
|
|
1415
|
-
]
|
|
1416
1409
|
dev = [
|
|
1417
1410
|
{ name = "mypy" },
|
|
1411
|
+
{ name = "numpy" },
|
|
1418
1412
|
{ name = "pre-commit" },
|
|
1413
|
+
{ name = "pytest" },
|
|
1414
|
+
{ name = "pytest-cov" },
|
|
1419
1415
|
{ name = "ruff" },
|
|
1420
1416
|
]
|
|
1421
1417
|
ingest = [
|
|
1422
1418
|
{ name = "aiida-core" },
|
|
1423
|
-
{ name = "ase" },
|
|
1424
|
-
{ name = "pandas" },
|
|
1425
1419
|
{ name = "pymatgen" },
|
|
1426
1420
|
]
|
|
1427
|
-
pandas = [
|
|
1428
|
-
{ name = "pandas" },
|
|
1429
|
-
]
|
|
1430
1421
|
pymatgen = [
|
|
1431
1422
|
{ name = "pymatgen" },
|
|
1432
1423
|
]
|
|
1433
1424
|
tests = [
|
|
1425
|
+
{ name = "numpy" },
|
|
1434
1426
|
{ name = "pytest" },
|
|
1435
1427
|
{ name = "pytest-cov" },
|
|
1436
1428
|
]
|
|
1437
1429
|
|
|
1438
1430
|
[package.metadata]
|
|
1439
1431
|
requires-dist = [
|
|
1440
|
-
{ name = "aiida-core", marker = "extra == 'aiida'", specifier = "
|
|
1441
|
-
{ name = "ase",
|
|
1432
|
+
{ name = "aiida-core", marker = "extra == 'aiida'", specifier = "~=2.6" },
|
|
1433
|
+
{ name = "ase", specifier = "~=3.22" },
|
|
1442
1434
|
{ name = "click", specifier = "~=8.1" },
|
|
1443
1435
|
{ name = "mypy", marker = "extra == 'dev'" },
|
|
1444
|
-
{ name = "numpy", specifier = ">=1.22,<3" },
|
|
1445
|
-
{ name = "optimade", extras = ["server"], specifier = "~=1.4
|
|
1446
|
-
{ name = "optimade-maker", extras = ["aiida", "
|
|
1447
|
-
{ name = "optimade-maker", extras = ["
|
|
1448
|
-
{ name = "pandas",
|
|
1436
|
+
{ name = "numpy", marker = "extra == 'tests'", specifier = ">=1.22,<3" },
|
|
1437
|
+
{ name = "optimade", extras = ["server"], specifier = "~=1.4" },
|
|
1438
|
+
{ name = "optimade-maker", extras = ["aiida", "pymatgen"], marker = "extra == 'ingest'" },
|
|
1439
|
+
{ name = "optimade-maker", extras = ["tests"], marker = "extra == 'dev'" },
|
|
1440
|
+
{ name = "pandas", specifier = ">=1.5,<3" },
|
|
1449
1441
|
{ name = "pre-commit", marker = "extra == 'dev'" },
|
|
1450
|
-
{ name = "pydantic", specifier = "
|
|
1442
|
+
{ name = "pydantic", specifier = ">=2,<3" },
|
|
1451
1443
|
{ name = "pymatgen", marker = "extra == 'pymatgen'", specifier = ">=2023.9" },
|
|
1452
|
-
{ name = "pymongo" },
|
|
1444
|
+
{ name = "pymongo", specifier = ">=4,<5" },
|
|
1453
1445
|
{ name = "pytest", marker = "extra == 'tests'", specifier = "~=8.3" },
|
|
1454
1446
|
{ name = "pytest-cov", marker = "extra == 'tests'", specifier = "~=6.0" },
|
|
1455
1447
|
{ name = "pyyaml", specifier = "~=6.0" },
|
|
@@ -1457,7 +1449,7 @@ requires-dist = [
|
|
|
1457
1449
|
{ name = "ruff", marker = "extra == 'dev'" },
|
|
1458
1450
|
{ name = "tqdm", specifier = "~=4.65" },
|
|
1459
1451
|
]
|
|
1460
|
-
provides-extras = ["
|
|
1452
|
+
provides-extras = ["pymatgen", "aiida", "ingest", "tests", "dev"]
|
|
1461
1453
|
|
|
1462
1454
|
[[package]]
|
|
1463
1455
|
name = "orjson"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/.testing/first_entry.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/.testing/first_entry.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl/.testing/first_entry.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/example.jsonl.gz
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/.testing/first_entry.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/optimade.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/.testing/first_entry.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|