chemparseplot 1.9.16__tar.gz → 1.9.17__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.
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/PKG-INFO +3 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/_version.py +2 -2
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/api.py +1 -2
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/chemgp_hdf5.py +1 -0
- chemparseplot-1.9.17/chemparseplot/parse/eon/__init__.py +22 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/_trajectory_common.py +4 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/dimer_trajectory.py +2 -3
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/frame_series.py +5 -3
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/min_trajectory.py +2 -4
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/saddle_search.py +1 -3
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/grammar/__init__.py +7 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/grammar/orca_text.py +3 -4
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/grammar/xyz.py +11 -8
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/sella/saddle_search.py +4 -3
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/types.py +1 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/geomscan.py +7 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/neb.py +13 -18
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/optimization.py +2 -6
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/structs.py +1 -3
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/pyproject.toml +41 -11
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/fixtures/orca_energy_coords_snippet.out +0 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/_con_fixtures.py +5 -6
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/grammar/test_orca_text_grammar.py +2 -2
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/grammar/test_xyz_grammar.py +1 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_con_io.py +1 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_eon_trajectory_common.py +17 -8
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_frame_series.py +3 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_min_trajectory.py +1 -2
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_neb_stitch.py +6 -4
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_orca_public_api.py +9 -4
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_readcon_boundary.py +3 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_neb_helpers.py +3 -2
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_neb_renderers.py +7 -8
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_optimization.py +7 -2
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_strip_rendering.py +3 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/test_full_coverage.py +32 -5
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/tutorials/test_chemparseplot.py +3 -2
- chemparseplot-1.9.16/chemparseplot/parse/eon/__init__.py +0 -8
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/.gitignore +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/LICENSE +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/chemgp_jsonl.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/converter.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/con_io.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/gprd.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/minimization.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/neb.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/eon/stitch.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/file_.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/grammar/_deps.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/neb_utils.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/orca/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/orca/_opi.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/orca/geomscan.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/orca/neb/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/orca/neb/interp.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/orca/neb/opi_parser.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/patterns.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/plumed.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/projection.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/trajectory/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/trajectory/hdf5.py +5 -5
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/parse/trajectory/neb.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/chemgp.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/plumed.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/plot/theme.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/units.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/chemparseplot/util.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/readme.md +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/_optional_imports.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/conftest.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/fixtures/h2mol.xyz +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/fixtures_geomscan_snippet.txt +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/grammar/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/grammar/test_grammar_deps.py +1 -1
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/orca/test_geomscan.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/orca/test_interp.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_chemgp_hdf5.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_chemgp_jsonl_types.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_converter.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_dimer_trajectory.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_eon_neb_types.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_minimization_result.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_neb_utils.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_parser_types.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_patterns.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_plumed.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_projection.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_saddle_results.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_sella_saddle.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_trajectory_hdf5.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/parse/test_trajectory_neb.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/__init__.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_chemgp_utils.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_orca_neb_payload.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_projection_refactor.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_structs_units.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/plot/test_surface_auto_thin.py +0 -0
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/test_coverage_batch.py +2 -2
- {chemparseplot-1.9.16 → chemparseplot-1.9.17}/tests/test_public_api.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chemparseplot
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.17
|
|
4
4
|
Summary: Parsers and plotting tools for computational chemistry
|
|
5
5
|
Project-URL: Documentation, https://chemparseplot.rgoswami.me
|
|
6
6
|
Project-URL: Issues, https://github.com/HaoZeke/chemparseplot/issues
|
|
@@ -65,6 +65,7 @@ Requires-Dist: wheel>=0.40; extra == 'release'
|
|
|
65
65
|
Provides-Extra: test
|
|
66
66
|
Requires-Dist: ase>=3.22; extra == 'test'
|
|
67
67
|
Requires-Dist: h5py>=3.0; extra == 'test'
|
|
68
|
+
Requires-Dist: jax[cpu]>=0.4; extra == 'test'
|
|
68
69
|
Requires-Dist: matplotlib>=3.8.2; extra == 'test'
|
|
69
70
|
Requires-Dist: parsimonious>=0.10.0; extra == 'test'
|
|
70
71
|
Requires-Dist: polars>=0.20; extra == 'test'
|
|
@@ -73,6 +74,7 @@ Requires-Dist: pytest>=7.4.3; extra == 'test'
|
|
|
73
74
|
Requires-Dist: readcon>=0.13.1; extra == 'test'
|
|
74
75
|
Requires-Dist: rgpycrumbs; extra == 'test'
|
|
75
76
|
Requires-Dist: scipy>=1.11; extra == 'test'
|
|
77
|
+
Requires-Dist: xyzrender>=0.1.3; extra == 'test'
|
|
76
78
|
Provides-Extra: xyzrender
|
|
77
79
|
Requires-Dist: xyzrender>=0.1.2; extra == 'xyzrender'
|
|
78
80
|
Description-Content-Type: text/markdown
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.9.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 9,
|
|
21
|
+
__version__ = version = '1.9.17'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 9, 17)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -101,7 +101,6 @@ def parse_orca_final_energy(path_or_text: str):
|
|
|
101
101
|
return summary.final_energy
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
|
|
105
104
|
def extract_orca_geomscan_energy(
|
|
106
105
|
data: str, energy_type: str = "Actual Energy"
|
|
107
106
|
) -> tuple[Q_, Q_]:
|
|
@@ -138,6 +137,6 @@ def suite_pins() -> dict[str, str]:
|
|
|
138
137
|
try:
|
|
139
138
|
cfg = load_config()
|
|
140
139
|
pins.update(cfg.merged_package_pins_normalized())
|
|
141
|
-
except Exception:
|
|
140
|
+
except Exception:
|
|
142
141
|
pass
|
|
143
142
|
return pins
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2023-present Rohit Goswami <rog32@hi.is>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""eOn trajectory parsers.
|
|
5
|
+
|
|
6
|
+
``con_io`` is always importable (readcon loads on first CON call).
|
|
7
|
+
``frame_series`` needs the ``neb`` extra (readcon + polars + ase) and is
|
|
8
|
+
lazy so bare ``import chemparseplot.parse`` stays light.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from chemparseplot.parse.eon import con_io
|
|
12
|
+
|
|
13
|
+
__all__ = ["con_io", "frame_series"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def __getattr__(name: str):
|
|
17
|
+
if name == "frame_series":
|
|
18
|
+
from chemparseplot.parse.eon import frame_series as _frame_series
|
|
19
|
+
|
|
20
|
+
return _frame_series
|
|
21
|
+
msg = f"module {__name__!r} has no attribute {name!r}"
|
|
22
|
+
raise AttributeError(msg)
|
|
@@ -141,7 +141,10 @@ def frame_rows_to_table(
|
|
|
141
141
|
rows: list[dict[str, Any]] = []
|
|
142
142
|
saw_complete_row = False
|
|
143
143
|
for frame in frames:
|
|
144
|
-
row = {
|
|
144
|
+
row = {
|
|
145
|
+
column: coerce_metadata_value(column, metadata_value(frame, column))
|
|
146
|
+
for column in columns
|
|
147
|
+
}
|
|
145
148
|
if any(value is None for value in row.values()):
|
|
146
149
|
if saw_complete_row or not allow_leading_incomplete:
|
|
147
150
|
return pl.DataFrame()
|
|
@@ -16,11 +16,10 @@ from pathlib import Path
|
|
|
16
16
|
import numpy as np
|
|
17
17
|
import polars as pl
|
|
18
18
|
import readcon
|
|
19
|
-
|
|
20
|
-
from chemparseplot.parse.eon import con_io
|
|
21
19
|
from ase import Atoms
|
|
22
20
|
|
|
23
|
-
from .
|
|
21
|
+
from chemparseplot.parse.eon import con_io
|
|
22
|
+
from chemparseplot.parse.eon._trajectory_common import (
|
|
24
23
|
frame_rows_to_table,
|
|
25
24
|
load_movie_and_table,
|
|
26
25
|
load_optional_payload,
|
|
@@ -25,12 +25,10 @@ from chemparseplot.parse.eon._trajectory_common import (
|
|
|
25
25
|
metadata_value,
|
|
26
26
|
)
|
|
27
27
|
from chemparseplot.parse.eon.dimer_trajectory import (
|
|
28
|
-
DIMER_METADATA_COLUMNS,
|
|
29
28
|
DimerTrajectoryData,
|
|
30
29
|
table_from_dimer_metadata,
|
|
31
30
|
)
|
|
32
31
|
from chemparseplot.parse.eon.min_trajectory import (
|
|
33
|
-
MIN_METADATA_COLUMNS,
|
|
34
32
|
MinTrajectoryData,
|
|
35
33
|
table_from_min_metadata,
|
|
36
34
|
)
|
|
@@ -121,7 +119,11 @@ def neb_path_arrays(frames: Sequence[Any]) -> dict[str, Any]:
|
|
|
121
119
|
ok = True
|
|
122
120
|
for frame in frames:
|
|
123
121
|
v = metadata_value(frame, key)
|
|
124
|
-
if v is None and key in (
|
|
122
|
+
if v is None and key in (
|
|
123
|
+
"reaction_coordinate",
|
|
124
|
+
"relative_energy",
|
|
125
|
+
"parallel_force",
|
|
126
|
+
):
|
|
125
127
|
# optional NEB stamps
|
|
126
128
|
ok = False
|
|
127
129
|
break
|
|
@@ -15,14 +15,12 @@ from pathlib import Path
|
|
|
15
15
|
|
|
16
16
|
import polars as pl
|
|
17
17
|
import readcon
|
|
18
|
-
|
|
19
|
-
from chemparseplot.parse.eon import con_io
|
|
20
18
|
from ase import Atoms
|
|
21
19
|
|
|
22
|
-
from .
|
|
20
|
+
from chemparseplot.parse.eon import con_io
|
|
21
|
+
from chemparseplot.parse.eon._trajectory_common import (
|
|
23
22
|
frame_rows_to_table,
|
|
24
23
|
load_movie_and_table,
|
|
25
|
-
read_first_structure,
|
|
26
24
|
read_optional_first,
|
|
27
25
|
)
|
|
28
26
|
|
|
@@ -369,9 +369,7 @@ def parse_eon_saddle(eresp: Path, rloc: "SpinID") -> "SaddleMeasure":
|
|
|
369
369
|
dimer_trans=meth.trans,
|
|
370
370
|
init_energy=init_energy,
|
|
371
371
|
barrier=(
|
|
372
|
-
results_data.saddle_energy - init_energy
|
|
373
|
-
if init_energy is not None
|
|
374
|
-
else None
|
|
372
|
+
results_data.saddle_energy - init_energy if init_energy is not None else None
|
|
375
373
|
),
|
|
376
374
|
mol_id=getattr(rloc, "mol_id", None),
|
|
377
375
|
spin=getattr(rloc, "spin", None),
|
|
@@ -30,7 +30,13 @@ __all__ = [
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def __getattr__(name: str):
|
|
33
|
-
if name in (
|
|
33
|
+
if name in (
|
|
34
|
+
"parse_xyz_text",
|
|
35
|
+
"parse_xyz_file",
|
|
36
|
+
"XyzFrame",
|
|
37
|
+
"XyzAtom",
|
|
38
|
+
"write_xyz_text",
|
|
39
|
+
):
|
|
34
40
|
from chemparseplot.parse.grammar import xyz as _xyz
|
|
35
41
|
|
|
36
42
|
return getattr(_xyz, name)
|
|
@@ -151,7 +151,7 @@ def extract_final_energies_hartree(text: str) -> list[float]:
|
|
|
151
151
|
line = m.group(0).strip()
|
|
152
152
|
try:
|
|
153
153
|
tree = g.parse(line)
|
|
154
|
-
except Exception:
|
|
154
|
+
except Exception:
|
|
155
155
|
continue
|
|
156
156
|
v = EnergyVisitor()
|
|
157
157
|
v.visit(tree)
|
|
@@ -192,14 +192,13 @@ def extract_cartesian_angstrom_blocks(text: str) -> list[list[OrcaAtomCoord]]:
|
|
|
192
192
|
for m in _CART_BLOCK_RE.finditer(text):
|
|
193
193
|
chunk = (
|
|
194
194
|
"CARTESIAN COORDINATES (ANGSTROEM)\n"
|
|
195
|
-
"---------------------------------\n"
|
|
196
|
-
+ m.group(1)
|
|
195
|
+
"---------------------------------\n" + m.group(1)
|
|
197
196
|
)
|
|
198
197
|
if not chunk.endswith("\n"):
|
|
199
198
|
chunk += "\n"
|
|
200
199
|
try:
|
|
201
200
|
tree = g.parse(chunk)
|
|
202
|
-
except Exception:
|
|
201
|
+
except Exception:
|
|
203
202
|
continue
|
|
204
203
|
v = CartVisitor()
|
|
205
204
|
v.visit(tree)
|
|
@@ -29,8 +29,8 @@ _XYZ_GRAMMAR_SRC = r"""
|
|
|
29
29
|
meta = natoms newline comment_line newline coord_block ws?
|
|
30
30
|
natoms = ~r"\d+"
|
|
31
31
|
comment_line = ~r"[^\n]*"
|
|
32
|
-
coord_block = (
|
|
33
|
-
|
|
32
|
+
coord_block = (atom_line newline?)+
|
|
33
|
+
atom_line = ws? atype ws float_ ws float_ ws float_ ws?
|
|
34
34
|
atype = ~r"[A-Za-z][a-zA-Z0-9]{0,2}"
|
|
35
35
|
float_ = ~r"[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)?"
|
|
36
36
|
newline = ~r"\n"
|
|
@@ -107,26 +107,29 @@ def _make_visitor() -> Any:
|
|
|
107
107
|
self.comment: str = ""
|
|
108
108
|
self.atoms: list[XyzAtom] = []
|
|
109
109
|
|
|
110
|
-
def visit_natoms(self, node: Any,
|
|
110
|
+
def visit_natoms(self, node: Any, _visited_children: Any) -> int:
|
|
111
111
|
self.natoms = int(node.text)
|
|
112
112
|
return self.natoms
|
|
113
113
|
|
|
114
|
-
def visit_comment_line(self, node: Any,
|
|
114
|
+
def visit_comment_line(self, node: Any, _visited_children: Any) -> str:
|
|
115
115
|
self.comment = node.text
|
|
116
116
|
return self.comment
|
|
117
117
|
|
|
118
|
-
def
|
|
118
|
+
def visit_atom_line(self, node: Any, visited_children: Any) -> XyzAtom:
|
|
119
|
+
del node # structure from visited_children
|
|
119
120
|
flat = _flatten(visited_children)
|
|
120
|
-
symbol = next(
|
|
121
|
+
symbol = next(
|
|
122
|
+
x for x in flat if isinstance(x, str) and x.strip() and x[0].isalpha()
|
|
123
|
+
)
|
|
121
124
|
nums = [x for x in flat if isinstance(x, float)]
|
|
122
125
|
atom = XyzAtom(symbol=symbol, x=nums[0], y=nums[1], z=nums[2])
|
|
123
126
|
self.atoms.append(atom)
|
|
124
127
|
return atom
|
|
125
128
|
|
|
126
|
-
def visit_atype(self, node: Any,
|
|
129
|
+
def visit_atype(self, node: Any, _visited_children: Any) -> str:
|
|
127
130
|
return node.text
|
|
128
131
|
|
|
129
|
-
def visit_float_(self, node: Any,
|
|
132
|
+
def visit_float_(self, node: Any, _visited_children: Any) -> float:
|
|
130
133
|
return float(node.text)
|
|
131
134
|
|
|
132
135
|
def generic_visit(self, node: Any, visited_children: Any) -> Any:
|
|
@@ -18,13 +18,14 @@ except ImportError:
|
|
|
18
18
|
|
|
19
19
|
log = logging.getLogger(__name__)
|
|
20
20
|
|
|
21
|
+
|
|
21
22
|
@dataclass(frozen=True, slots=True)
|
|
22
23
|
class SellaLog:
|
|
23
24
|
"""Typed record for a single Sella geometry-step log entry.
|
|
24
25
|
|
|
25
|
-
```{versionadded} 0.0.3
|
|
26
|
-
```
|
|
27
|
-
"""
|
|
26
|
+
```{versionadded} 0.0.3
|
|
27
|
+
```
|
|
28
|
+
"""
|
|
28
29
|
|
|
29
30
|
step_id: int
|
|
30
31
|
time_float: float
|
|
@@ -84,7 +84,7 @@ class OrcaNebResult(DataclassMapping):
|
|
|
84
84
|
|
|
85
85
|
def __post_init__(self) -> None:
|
|
86
86
|
if self.n_images is None:
|
|
87
|
-
object.__setattr__(self, "n_images",
|
|
87
|
+
object.__setattr__(self, "n_images", len(self.energies))
|
|
88
88
|
|
|
89
89
|
@classmethod
|
|
90
90
|
def from_mapping(cls, data: Mapping[str, Any]) -> OrcaNebResult:
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import matplotlib.pyplot as plt
|
|
2
2
|
|
|
3
|
-
from chemparseplot.plot.structs import
|
|
3
|
+
from chemparseplot.plot.structs import (
|
|
4
|
+
AxisUnits,
|
|
5
|
+
BasePlotter,
|
|
6
|
+
EnergyPath,
|
|
7
|
+
axis_label,
|
|
8
|
+
to_magnitude,
|
|
9
|
+
)
|
|
4
10
|
|
|
5
11
|
|
|
6
12
|
def plot_energy_paths(
|
|
@@ -2,16 +2,14 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import io
|
|
4
4
|
import logging
|
|
5
|
-
import shutil
|
|
6
5
|
import tempfile
|
|
6
|
+
from collections.abc import Mapping
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
|
-
from collections.abc import Mapping
|
|
12
|
-
|
|
13
|
-
import matplotlib.pyplot as plt
|
|
14
11
|
import matplotlib.patheffects as path_effects
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
15
13
|
import numpy as np
|
|
16
14
|
from ase.io import write as ase_write
|
|
17
15
|
from matplotlib import tri
|
|
@@ -554,7 +552,7 @@ def plot_structure_strip(
|
|
|
554
552
|
max_cols=6,
|
|
555
553
|
renderer="xyzrender",
|
|
556
554
|
col_spacing=1.5,
|
|
557
|
-
show_dividers=False,
|
|
555
|
+
show_dividers=False,
|
|
558
556
|
xyzrender_config="paton",
|
|
559
557
|
divider_color="gray",
|
|
560
558
|
divider_style="--",
|
|
@@ -1044,15 +1042,15 @@ def plot_landscape_surface(
|
|
|
1044
1042
|
method="grad_matern",
|
|
1045
1043
|
rbf_smooth=None,
|
|
1046
1044
|
cmap="viridis",
|
|
1047
|
-
show_pts=True,
|
|
1045
|
+
show_pts=True,
|
|
1048
1046
|
variance_threshold=0.05,
|
|
1049
|
-
project_path=True,
|
|
1047
|
+
project_path=True,
|
|
1050
1048
|
extra_points=None,
|
|
1051
1049
|
n_inducing=None,
|
|
1052
1050
|
xlim=None,
|
|
1053
1051
|
ylim=None,
|
|
1054
1052
|
basis=None,
|
|
1055
|
-
auto_thin: bool = False,
|
|
1053
|
+
auto_thin: bool = False,
|
|
1056
1054
|
max_surface_points: int = 64,
|
|
1057
1055
|
surface_fit: SurfaceFitConfig | Mapping[str, Any] | None = None,
|
|
1058
1056
|
) -> Any:
|
|
@@ -1130,8 +1128,7 @@ def plot_landscape_surface(
|
|
|
1130
1128
|
if auto_thin and n_obs > max_surface_points:
|
|
1131
1129
|
fit_idx = surface_fit_indices(n_obs, max_surface_points)
|
|
1132
1130
|
log.warning(
|
|
1133
|
-
"auto_thin: fitting surface on %d of %d points "
|
|
1134
|
-
"(max_surface_points=%d)",
|
|
1131
|
+
"auto_thin: fitting surface on %d of %d points (max_surface_points=%d)",
|
|
1135
1132
|
len(fit_idx),
|
|
1136
1133
|
n_obs,
|
|
1137
1134
|
max_surface_points,
|
|
@@ -1428,7 +1425,7 @@ def plot_landscape_path_overlay(
|
|
|
1428
1425
|
z,
|
|
1429
1426
|
cmap,
|
|
1430
1427
|
z_label,
|
|
1431
|
-
project_path=True,
|
|
1428
|
+
project_path=True,
|
|
1432
1429
|
all_r=None,
|
|
1433
1430
|
all_p=None,
|
|
1434
1431
|
all_z=None,
|
|
@@ -1539,7 +1536,7 @@ def plot_mmf_peaks_overlay(
|
|
|
1539
1536
|
peak_rmsd_r,
|
|
1540
1537
|
peak_rmsd_p,
|
|
1541
1538
|
peak_energies,
|
|
1542
|
-
project_path=True,
|
|
1539
|
+
project_path=True,
|
|
1543
1540
|
path_rmsd_r=None,
|
|
1544
1541
|
path_rmsd_p=None,
|
|
1545
1542
|
) -> None:
|
|
@@ -1613,7 +1610,7 @@ def plot_phase_points_overlay(
|
|
|
1613
1610
|
rmsd_r,
|
|
1614
1611
|
rmsd_p,
|
|
1615
1612
|
*,
|
|
1616
|
-
project_path=True,
|
|
1613
|
+
project_path=True,
|
|
1617
1614
|
path_rmsd_r=None,
|
|
1618
1615
|
path_rmsd_p=None,
|
|
1619
1616
|
phase_color="#FF8F00",
|
|
@@ -1667,7 +1664,7 @@ def plot_neb_evolution(
|
|
|
1667
1664
|
ax,
|
|
1668
1665
|
step_rmsd_r_list: list[np.ndarray],
|
|
1669
1666
|
step_rmsd_p_list: list[np.ndarray],
|
|
1670
|
-
project_path=True,
|
|
1667
|
+
project_path=True,
|
|
1671
1668
|
cmap="Blues",
|
|
1672
1669
|
) -> None:
|
|
1673
1670
|
"""Show NEB band evolution across optimization iterations.
|
|
@@ -1767,9 +1764,7 @@ def landscape_half_span(
|
|
|
1767
1764
|
_s, _d = project_to_sd(np.asarray(final_r), np.asarray(final_p), basis)
|
|
1768
1765
|
half_span = max(abs(float(_d.max())), abs(float(_d.min())), min_half) * path_pad
|
|
1769
1766
|
for overlay in additional_atoms_data or []:
|
|
1770
|
-
_, add_d = project_to_sd(
|
|
1771
|
-
np.array([overlay.r]), np.array([overlay.p]), basis
|
|
1772
|
-
)
|
|
1767
|
+
_, add_d = project_to_sd(np.array([overlay.r]), np.array([overlay.p]), basis)
|
|
1773
1768
|
half_span = max(half_span, abs(float(add_d[0])) * path_pad)
|
|
1774
1769
|
if equal_metric and x_limits is not None:
|
|
1775
1770
|
s_half = 0.5 * max(float(x_limits[1] - x_limits[0]), 1e-9)
|
|
@@ -1934,7 +1929,7 @@ def plot_orca_neb_profile(
|
|
|
1934
1929
|
image_indices = list(range(n_images))
|
|
1935
1930
|
ax.plot(image_indices, energies, "o-", linewidth=2, markersize=8)
|
|
1936
1931
|
|
|
1937
|
-
|
|
1932
|
+
_plot_orca_profile_keypoints(
|
|
1938
1933
|
ax,
|
|
1939
1934
|
x_values=np.asarray(image_indices, dtype=float),
|
|
1940
1935
|
energies=energies,
|
|
@@ -415,9 +415,7 @@ def render_single_ended_landscape(
|
|
|
415
415
|
cap = float(np.min(display_e)) + energy_cap_window
|
|
416
416
|
if cap is not None:
|
|
417
417
|
factor = float(convert_energy(np.array([1.0]), energy_unit)[0])
|
|
418
|
-
energies_plot = np.minimum(
|
|
419
|
-
energies_plot, cap / factor if factor else cap
|
|
420
|
-
)
|
|
418
|
+
energies_plot = np.minimum(energies_plot, cap / factor if factor else cap)
|
|
421
419
|
display_e = convert_energy(energies_plot, energy_unit)
|
|
422
420
|
|
|
423
421
|
f_para = -np.gradient(energies_plot)
|
|
@@ -466,9 +464,7 @@ def render_single_ended_landscape(
|
|
|
466
464
|
)
|
|
467
465
|
m = min(len(ra), len(atoms_ov))
|
|
468
466
|
ra, rb = ra[:m], rb[:m]
|
|
469
|
-
px, py, _ = project_landscape_path(
|
|
470
|
-
ra, rb, project_path=project_path, basis=basis
|
|
471
|
-
)
|
|
467
|
+
px, py, _ = project_landscape_path(ra, rb, project_path=project_path, basis=basis)
|
|
472
468
|
color = OVERLAY_COLORS[idx % len(OVERLAY_COLORS)]
|
|
473
469
|
if len(overlays) > 1:
|
|
474
470
|
ax.plot(
|
|
@@ -135,9 +135,7 @@ class BasePlotter:
|
|
|
135
135
|
```
|
|
136
136
|
"""
|
|
137
137
|
|
|
138
|
-
def __init__(
|
|
139
|
-
self, figsize=(3.2, 2.5), dpi=200, pad=0.2, colormap=None, style="bmh"
|
|
140
|
-
):
|
|
138
|
+
def __init__(self, figsize=(3.2, 2.5), dpi=200, pad=0.2, colormap=None, style="bmh"):
|
|
141
139
|
if colormap is None:
|
|
142
140
|
from cmcrameri import cm # optional plot extra
|
|
143
141
|
|
|
@@ -55,15 +55,11 @@ opi = ["orca-pi>=0.1.0"]
|
|
|
55
55
|
# Grammar/AST track (parsimonious) for XYZ and text-heavy ORCA sections.
|
|
56
56
|
grammar = ["parsimonious>=0.10.0"]
|
|
57
57
|
all = ["chemparseplot[plot,neb,xyzrender,opi,grammar]"]
|
|
58
|
-
release = [
|
|
59
|
-
"build>=0.10",
|
|
60
|
-
"towncrier>=24.8.0",
|
|
61
|
-
"twine>=4.0",
|
|
62
|
-
"wheel>=0.40",
|
|
63
|
-
]
|
|
58
|
+
release = ["build>=0.10", "towncrier>=24.8.0", "twine>=4.0", "wheel>=0.40"]
|
|
64
59
|
test = [
|
|
65
60
|
"ase>=3.22",
|
|
66
61
|
"h5py>=3.0",
|
|
62
|
+
"jax[cpu]>=0.4",
|
|
67
63
|
"matplotlib>=3.8.2",
|
|
68
64
|
"parsimonious>=0.10.0",
|
|
69
65
|
"polars>=0.20",
|
|
@@ -72,6 +68,7 @@ test = [
|
|
|
72
68
|
"readcon>=0.13.1",
|
|
73
69
|
"rgpycrumbs",
|
|
74
70
|
"scipy>=1.11",
|
|
71
|
+
"xyzrender>=0.1.3",
|
|
75
72
|
]
|
|
76
73
|
lint = ["ruff>=0.1.6"]
|
|
77
74
|
[project.urls]
|
|
@@ -172,9 +169,6 @@ ban-relative-imports = "all"
|
|
|
172
169
|
"S603",
|
|
173
170
|
"T201",
|
|
174
171
|
] # doctest scripts
|
|
175
|
-
"chemparseplot/parse/**/*" = [
|
|
176
|
-
"PLC0415",
|
|
177
|
-
] # deferred imports for optional deps (h5py, pandas, polars)
|
|
178
172
|
"tests/**/*" = [
|
|
179
173
|
"ARG001",
|
|
180
174
|
"ARG002",
|
|
@@ -182,6 +176,8 @@ ban-relative-imports = "all"
|
|
|
182
176
|
"B007",
|
|
183
177
|
"B017",
|
|
184
178
|
"E402",
|
|
179
|
+
"EM101",
|
|
180
|
+
"EM102",
|
|
185
181
|
"F401",
|
|
186
182
|
"ICN001",
|
|
187
183
|
"N806",
|
|
@@ -193,8 +189,13 @@ ban-relative-imports = "all"
|
|
|
193
189
|
"S101",
|
|
194
190
|
"S108",
|
|
195
191
|
"S110",
|
|
192
|
+
"S603",
|
|
196
193
|
"T201",
|
|
197
194
|
"TID252",
|
|
195
|
+
"UP031",
|
|
196
|
+
"RUF007",
|
|
197
|
+
"F841",
|
|
198
|
+
"RUF043",
|
|
198
199
|
]
|
|
199
200
|
# __init__.py can import without use and use lazy __getattr__
|
|
200
201
|
"__init__.py" = ["F401", "PLC0415"]
|
|
@@ -209,9 +210,38 @@ ban-relative-imports = "all"
|
|
|
209
210
|
"FBT002",
|
|
210
211
|
"PLW2901",
|
|
211
212
|
]
|
|
212
|
-
"chemparseplot/plot/structs.py" = ["PLC0415"]
|
|
213
213
|
"chemparseplot/plot/geomscan.py" = ["PLC0415"]
|
|
214
|
-
"chemparseplot/
|
|
214
|
+
"chemparseplot/units.py" = [
|
|
215
|
+
"F822", # lazy Q_/ureg via __getattr__
|
|
216
|
+
"EM102",
|
|
217
|
+
"N806", # pint Quantity alias Q
|
|
218
|
+
"PLW0603",
|
|
219
|
+
"PLC0415", # lazy pint import
|
|
220
|
+
"RUF059",
|
|
221
|
+
]
|
|
222
|
+
"chemparseplot/__init__.py" = ["PLC0414", "EM102", "F401"]
|
|
223
|
+
"chemparseplot/api.py" = ["PLR2004", "S110", "PLC0415"]
|
|
224
|
+
"chemparseplot/util.py" = ["PLC0415"]
|
|
225
|
+
"chemparseplot/parse/**/*" = [
|
|
226
|
+
"PLC0415",
|
|
227
|
+
"EM102",
|
|
228
|
+
"N806",
|
|
229
|
+
"ARG002", # NodeVisitor signatures
|
|
230
|
+
"S112",
|
|
231
|
+
"PLW0603",
|
|
232
|
+
"UP047",
|
|
233
|
+
]
|
|
234
|
+
"chemparseplot/plot/neb.py" = [
|
|
235
|
+
"PLR2004",
|
|
236
|
+
"PLC0415",
|
|
237
|
+
"C408",
|
|
238
|
+
"RUF046",
|
|
239
|
+
"FBT001",
|
|
240
|
+
"FBT002",
|
|
241
|
+
]
|
|
242
|
+
"chemparseplot/plot/optimization.py" = ["N803", "PLC0415"]
|
|
243
|
+
"chemparseplot/plot/structs.py" = ["PLC0415", "F401", "N806"]
|
|
244
|
+
"chemparseplot/parse/orca/**/*" = ["PLW0603", "PLC0415", "N806"]
|
|
215
245
|
"chemparseplot/parse/orca/neb/opi_parser.py" = [
|
|
216
246
|
"PLC0415", # late imports for optional deps (ase)
|
|
217
247
|
"PLW0603", # global for lazy-loaded OPI module
|
|
@@ -8,7 +8,9 @@ from __future__ import annotations
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def band_text(
|
|
11
|
+
def band_text(
|
|
12
|
+
frames: list[tuple[float, float]], *, extra_meta: dict | None = None
|
|
13
|
+
) -> str:
|
|
12
14
|
"""Build multi-frame CON text. Each item is ``(energy_eV, z)`` for a single H."""
|
|
13
15
|
blocks = []
|
|
14
16
|
for idx, (energy, z) in enumerate(frames):
|
|
@@ -17,8 +19,7 @@ def band_text(frames: list[tuple[float, float]], *, extra_meta: dict | None = No
|
|
|
17
19
|
meta.update(extra_meta)
|
|
18
20
|
meta_json = (
|
|
19
21
|
'{"con_spec_version":%(con_spec_version)d,'
|
|
20
|
-
'"energy":%(energy)r,"frame_index":%(frame_index)d'
|
|
21
|
-
% meta
|
|
22
|
+
'"energy":%(energy)r,"frame_index":%(frame_index)d' % meta
|
|
22
23
|
)
|
|
23
24
|
for key, value in meta.items():
|
|
24
25
|
if key in {"con_spec_version", "energy", "frame_index"}:
|
|
@@ -51,9 +52,7 @@ def write_band(path: Path, frames: list[tuple[float, float]], **kwargs) -> Path:
|
|
|
51
52
|
return path
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
def min_metadata_band(
|
|
55
|
-
path: Path, rows: list[tuple[float, float, float]]
|
|
56
|
-
) -> Path:
|
|
55
|
+
def min_metadata_band(path: Path, rows: list[tuple[float, float, float]]) -> Path:
|
|
57
56
|
"""Write minimization movie frames.
|
|
58
57
|
|
|
59
58
|
Each row is ``(energy, step_size, convergence)`` with sequential frame_index.
|
|
@@ -11,8 +11,8 @@ import pytest
|
|
|
11
11
|
|
|
12
12
|
pytest.importorskip("parsimonious")
|
|
13
13
|
|
|
14
|
-
from chemparseplot.api import parse_orca_final_energy
|
|
15
|
-
from chemparseplot.parse.grammar.orca_text import (
|
|
14
|
+
from chemparseplot.api import parse_orca_final_energy
|
|
15
|
+
from chemparseplot.parse.grammar.orca_text import (
|
|
16
16
|
extract_cartesian_angstrom_blocks,
|
|
17
17
|
extract_final_energies_hartree,
|
|
18
18
|
parse_orca_text_summary,
|
|
@@ -117,7 +117,7 @@ def test_frame_with_energy_scalar_metadata_fallback(tmp_path: Path):
|
|
|
117
117
|
return self._energy
|
|
118
118
|
|
|
119
119
|
fake_readcon = SimpleNamespace(ConFrame=_RecordingConFrame)
|
|
120
|
-
|
|
120
|
+
SimpleNamespace(
|
|
121
121
|
_readcon=lambda: fake_readcon,
|
|
122
122
|
frame_with_energy=con_io_mod.frame_with_energy,
|
|
123
123
|
)
|