lammpsparser 0.0.2__tar.gz → 0.0.4__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.
@@ -0,0 +1,218 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lammpsparser
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Summary: Vector-oriented LAMMPS interface to rapidly iterate over series of atomistic structures or interatomic potentials.
5
5
  Project-URL: Homepage, https://github.com/pyiron/lammpsparser
6
6
  Project-URL: Documentation, https://github.com/pyiron/lammpsparser
@@ -51,8 +51,10 @@ Classifier: Topic :: Scientific/Engineering :: Physics
51
51
  Requires-Python: <3.15,>=3.9
52
52
  Requires-Dist: ase<=3.28.0,>=3.22.1
53
53
  Requires-Dist: numpy<=2.4.3,>=1.26.0
54
- Requires-Dist: pandas<=3.0.1,>=2.0.3
54
+ Requires-Dist: pandas<=3.0.2,>=2.0.3
55
55
  Requires-Dist: scipy<=1.17.1,>=1.11.1
56
+ Provides-Extra: compatibility
57
+ Requires-Dist: structuretoolkit<=0.0.42,>=0.0.30; extra == 'compatibility'
56
58
  Provides-Extra: h5md
57
59
  Requires-Dist: h5py<=3.16.0,>=3.9.0; extra == 'h5md'
58
60
  Description-Content-Type: text/markdown
@@ -36,7 +36,7 @@ classifiers = [
36
36
  dependencies = [
37
37
  "ase>=3.22.1,<=3.28.0",
38
38
  "numpy>=1.26.0,<=2.4.3",
39
- "pandas>=2.0.3,<=3.0.1",
39
+ "pandas>=2.0.3,<=3.0.2",
40
40
  "scipy>=1.11.1,<=1.17.1",
41
41
  ]
42
42
  dynamic = ["version"]
@@ -48,6 +48,7 @@ Repository = "https://github.com/pyiron/lammpsparser"
48
48
 
49
49
  [project.optional-dependencies]
50
50
  h5md = ["h5py>=3.9.0,<=3.16.0"]
51
+ compatibility = ["structuretoolkit>=0.0.30,<=0.0.42"]
51
52
 
52
53
  [tool.hatch.build]
53
54
  include = [
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.0.4'
22
+ __version_tuple__ = version_tuple = (0, 0, 4)
23
+
24
+ __commit_id__ = commit_id = None
@@ -1,4 +1,5 @@
1
1
  import warnings
2
+ from typing import Any, cast
2
3
 
3
4
  import numpy as np
4
5
  from ase.atoms import Atoms
@@ -121,7 +122,7 @@ def calc_md(
121
122
  "Target temperature for fix nvt/npt/nph cannot be 0 or negative"
122
123
  )
123
124
 
124
- force_skewed = False
125
+ # force_skewed = False
125
126
  pressure = _pressure_to_lammps(
126
127
  pressure=pressure, rotation_matrix=rotation_matrix, units=units
127
128
  )
@@ -139,8 +140,8 @@ def calc_md(
139
140
  pressure_string += " {0} {1} {1} {2}".format(
140
141
  coord, value, pressure_damping_timescale
141
142
  )
142
- if ii > 2:
143
- force_skewed = True
143
+ # if ii > 2:
144
+ # force_skewed = True
144
145
 
145
146
  if langevin: # NPT(Langevin)
146
147
  fix_ensemble_str = "fix ensemble all nph" + pressure_string
@@ -277,7 +278,7 @@ def calc_minimize(
277
278
  pressure=pressure, rotation_matrix=rotation_matrix, units=units
278
279
  )
279
280
  if np.isscalar(pressure):
280
- str_press = " iso {}".format(pressure)
281
+ str_press = " iso {}".format(float(cast(Any, pressure)))
281
282
  else:
282
283
  str_press = ""
283
284
  for ii, (press, str_axis) in enumerate(
@@ -2,7 +2,7 @@ import numpy as np
2
2
  from ase.atoms import Atoms
3
3
 
4
4
 
5
- def _get_fixed_atom_boolean_vector(structure: Atoms):
5
+ def _get_fixed_atom_boolean_vector(structure: Atoms) -> np.ndarray:
6
6
  fixed_atom_vector = np.array([[False, False, False]] * len(structure))
7
7
  for c in structure.constraints:
8
8
  c_dict = c.todict()
@@ -27,8 +27,8 @@ def _get_fixed_atom_boolean_vector(structure: Atoms):
27
27
  return fixed_atom_vector
28
28
 
29
29
 
30
- def set_selective_dynamics(structure: Atoms, calc_md: bool = False):
31
- control_dict = {}
30
+ def set_selective_dynamics(structure: Atoms, calc_md: bool = False) -> dict[str, str]:
31
+ control_dict: dict[str, str] = {}
32
32
  if len(structure.constraints) > 0:
33
33
  sel_dyn = _get_fixed_atom_boolean_vector(structure=structure)
34
34
  # Enter loop only if constraints present
@@ -0,0 +1,33 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional, Union
3
+
4
+ import numpy as np
5
+
6
+
7
+ @dataclass
8
+ class CalcMDInput:
9
+ temperature: Optional[Union[float, list]] = None
10
+ pressure: Optional[Union[float, list, np.ndarray]] = None
11
+ n_ionic_steps: int = 1
12
+ time_step: float = 1.0
13
+ n_print: int = 100
14
+ temperature_damping_timescale: float = 100.0
15
+ pressure_damping_timescale: float = 1000.0
16
+ seed: int = 80996
17
+ tloop: Optional[int] = None
18
+ initial_temperature: Optional[float] = None
19
+ langevin: bool = False
20
+ delta_temp: Optional[float] = None
21
+ delta_press: Optional[float] = None
22
+ rotation_matrix: Optional[Union[list, np.ndarray]] = None
23
+
24
+
25
+ @dataclass
26
+ class CalcMinimizeInput:
27
+ ionic_energy_tolerance: float = 0.0
28
+ ionic_force_tolerance: float = 1e-4
29
+ max_iter: int = 100000
30
+ pressure: Optional[Union[float, list, np.ndarray]] = None
31
+ n_print: int = 1
32
+ style: str = "cg"
33
+ rotation_matrix: Optional[Union[list, np.ndarray]] = None
@@ -1,7 +1,8 @@
1
1
  import os
2
2
  import shutil
3
3
  import subprocess
4
- from typing import Optional
4
+ from dataclasses import asdict
5
+ from typing import Optional, Union
5
6
 
6
7
  import pandas
7
8
  from ase.atoms import Atoms
@@ -12,6 +13,7 @@ from lammpsparser.compatibility.calculate import (
12
13
  calc_static,
13
14
  )
14
15
  from lammpsparser.compatibility.constraints import set_selective_dynamics
16
+ from lammpsparser.compatibility.data import CalcMDInput, CalcMinimizeInput
15
17
  from lammpsparser.output import parse_lammps_output
16
18
  from lammpsparser.potential import get_potential_by_name
17
19
  from lammpsparser.structure import write_lammps_datafile
@@ -23,8 +25,9 @@ def lammps_file_interface_function(
23
25
  potential: str,
24
26
  calc_mode: str = "static",
25
27
  calc_kwargs: Optional[dict] = None,
28
+ calc_dataclass: Optional[Union[CalcMDInput, CalcMinimizeInput]] = None,
26
29
  units: str = "metal",
27
- lmp_command: str = "mpiexec -n 1 --oversubscribe lmp_mpi -in lmp.in",
30
+ lmp_command: Optional[str] = None,
28
31
  resource_path: Optional[str] = None,
29
32
  input_control_file: Optional[dict] = None,
30
33
  write_restart_file: bool = False,
@@ -61,13 +64,15 @@ def lammps_file_interface_function(
61
64
  "static": No parameters
62
65
  "md": "temperature", "pressure", "n_ionic_steps", "time_step", "n_print", "temperature_damping_timescale",
63
66
  "pressure_damping_timescale", "seed", "tloop", "initial_temperature", "langevin", "delta_temp",
64
- "delta_press", job_name", "rotation_matrix"
67
+ "delta_press", "rotation_matrix"
65
68
  "minimize": "ionic_energy_tolerance", "ionic_force_tolerance", "max_iter", "pressure", "n_print", "style",
66
69
  "rotation_matrix"
67
70
  "vcsgc": "mu", "ordered_element_list", "target_concentration", "kappa", "mc_step_interval", "swap_fraction",
68
71
  "temperature_mc", "window_size", "window_moves", "temperature", "pressure", "n_ionic_steps",
69
72
  "time_step", "n_print", "temperature_damping_timescale", "pressure_damping_timescale", "seed",
70
- "initial_temperature", "langevin", "job_name", "rotation_matrix"
73
+ "initial_temperature", "langevin", "rotation_matrix"
74
+ calc_dataclass (CalcMDInput or CalcMinimizeInput): dataclass containing the parameters for the calculation,
75
+ if calc_dataclass is provided
71
76
  cutoff_radius (float): cut-off radius for the interatomic potential
72
77
  units (str): Units for LAMMPS
73
78
  bonds_kwargs (dict): key-word arguments to create atomistic bonds:
@@ -88,11 +93,29 @@ def lammps_file_interface_function(
88
93
  str, dict, bool: Tuple consisting of the shell output (str), the parsed output (dict) and a boolean flag if
89
94
  the execution raised an accepted error.
90
95
  """
96
+ if calc_dataclass is not None:
97
+ if isinstance(calc_dataclass, CalcMDInput):
98
+ calc_mode = "md"
99
+ calc_kwargs = asdict(calc_dataclass)
100
+
101
+ elif isinstance(calc_dataclass, CalcMinimizeInput):
102
+ calc_mode = "minimize"
103
+ calc_kwargs = asdict(calc_dataclass)
104
+ else:
105
+ raise TypeError(
106
+ "calc_dataclass must be an instance of either CalcMDInput or CalcMinimizeInput"
107
+ )
91
108
  if calc_kwargs is None:
92
109
  calc_kwargs = {}
93
110
  else:
94
111
  calc_kwargs = calc_kwargs.copy()
95
112
 
113
+ if lmp_command is None:
114
+ lmp_command = (
115
+ os.getenv("ASE_LAMMPSRUN_COMMAND", "mpiexec -n 1 --oversubscribe lmp_mpi")
116
+ + " -in lmp.in"
117
+ )
118
+
96
119
  os.makedirs(working_directory, exist_ok=True)
97
120
  potential_lst, potential_replace, species = _get_potential(
98
121
  potential=potential, resource_path=resource_path
@@ -100,21 +123,23 @@ def lammps_file_interface_function(
100
123
 
101
124
  lmp_str_lst = []
102
125
  atom_type = "atomic"
103
- for l in lammps_file_initialization(
126
+ for line in lammps_file_initialization(
104
127
  structure=structure,
105
128
  units=units,
106
129
  read_restart_file=read_restart_file,
107
130
  restart_file=restart_file,
108
131
  ):
109
- if l.strip().startswith("units") and "units" in potential_replace:
132
+ if line.strip().startswith("units") and "units" in potential_replace:
110
133
  lmp_str_lst.append(potential_replace["units"])
111
- elif l.strip().startswith("atom_style") and "atom_style" in potential_replace:
134
+ elif (
135
+ line.strip().startswith("atom_style") and "atom_style" in potential_replace
136
+ ):
112
137
  lmp_str_lst.append(potential_replace["atom_style"])
113
138
  atom_type = potential_replace["atom_style"].split()[-1]
114
- elif l.strip().startswith("dimension") and "dimension" in potential_replace:
139
+ elif line.strip().startswith("dimension") and "dimension" in potential_replace:
115
140
  lmp_str_lst.append(potential_replace["dimension"])
116
141
  else:
117
- lmp_str_lst.append(l)
142
+ lmp_str_lst.append(line)
118
143
 
119
144
  lmp_str_lst += potential_lst
120
145
  lmp_str_lst += ["variable dumptime equal {} ".format(calc_kwargs.get("n_print", 1))]
@@ -185,7 +210,7 @@ def lammps_file_interface_function(
185
210
  lmp_str_lst.append(f"write_restart {os.path.basename(restart_file)}")
186
211
 
187
212
  with open(os.path.join(working_directory, "lmp.in"), "w") as f:
188
- f.writelines([l + "\n" for l in lmp_str_lst])
213
+ f.writelines([line + "\n" for line in lmp_str_lst])
189
214
 
190
215
  write_lammps_datafile(
191
216
  structure=structure,
@@ -240,15 +265,15 @@ def _modify_input_dict(
240
265
  ):
241
266
  if input_control_file is not None:
242
267
  lmp_tmp_lst, keys_used = [], []
243
- for l in lmp_str_lst:
244
- ls = l.split()
268
+ for line in lmp_str_lst:
269
+ ls = line.split()
245
270
  if len(ls) >= 1: # Remove empty lines
246
271
  key = ls[0]
247
272
  if key in input_control_file.keys():
248
273
  lmp_tmp_lst.append(key + " " + input_control_file[key])
249
274
  keys_used.append(key)
250
275
  else:
251
- lmp_tmp_lst.append(l)
276
+ lmp_tmp_lst.append(line)
252
277
  for k, v in input_control_file.items():
253
278
  if k not in keys_used:
254
279
  lmp_tmp_lst.append(k + " " + v)
@@ -272,14 +297,14 @@ def _get_potential(potential, resource_path: Optional[str] = None):
272
297
 
273
298
  potential_replace = {}
274
299
  potential_lst = []
275
- for l in potential_dataframe["Config"]:
276
- if l.startswith("units"):
277
- potential_replace["units"] = l
278
- elif l.startswith("atom_style"):
279
- potential_replace["atom_style"] = l
280
- elif l.startswith("dimension"):
281
- potential_replace["dimension"] = l
300
+ for line in potential_dataframe["Config"]:
301
+ if line.startswith("units"):
302
+ potential_replace["units"] = line
303
+ elif line.startswith("atom_style"):
304
+ potential_replace["atom_style"] = line
305
+ elif line.startswith("dimension"):
306
+ potential_replace["dimension"] = line
282
307
  else:
283
- potential_lst.append(l)
308
+ potential_lst.append(line)
284
309
 
285
310
  return potential_lst, potential_replace, potential_dataframe["Species"]
@@ -0,0 +1,38 @@
1
+ from ase.atoms import Atoms
2
+
3
+
4
+ def structure_from_parsed_output(
5
+ initial_structure: Atoms,
6
+ parsed_output: dict,
7
+ *,
8
+ wrap: bool = False,
9
+ index: int = -1,
10
+ ) -> Atoms:
11
+ """Construct an `Atoms` object from parsed output data.
12
+
13
+ Args:
14
+ initial_structure: The initial atomic structure to use as a template.
15
+ parsed_output: Parsed output containing atomic positions, cell, and indices.
16
+ wrap: Whether to wrap the atomic positions to the simulation cell (default is False).
17
+ Keeping the unwrapped positions is more beneficial if structures are passed between
18
+ different LAMMPS simulations in one workflow to ensure continuity.
19
+ index: The index of the frame to use from the parsed output (default is -1, i.e., the last frame).
20
+
21
+ Returns:
22
+ An `Atoms` object with updated positions and cell.
23
+
24
+ Example:
25
+ >>> new_atoms = structure_from_parsed_output(atoms, lammps_output)
26
+
27
+ """
28
+ # Take a copy of the initial structure as template and update the relevant properties
29
+ atoms_copy = initial_structure.copy()
30
+ atoms_copy.set_array("indices", parsed_output["generic"]["indices"][index])
31
+ atoms_copy.set_positions(parsed_output["generic"]["positions"][index])
32
+ atoms_copy.set_velocities(parsed_output["generic"]["velocities"][index])
33
+ atoms_copy.set_cell(parsed_output["generic"]["cells"][index])
34
+ atoms_copy.set_pbc(True)
35
+ if wrap:
36
+ atoms_copy.wrap()
37
+
38
+ return atoms_copy
@@ -17,7 +17,7 @@ class LammpsStructureCompatibility(LammpsStructure):
17
17
  atom_type: str = "atomic",
18
18
  ):
19
19
  super().__init__(bond_dict=bond_dict, units=units, atom_type=atom_type)
20
- self._molecule_ids = []
20
+ self._molecule_ids: list[int] = []
21
21
 
22
22
  @property
23
23
  def structure(self) -> Optional[Atoms]:
@@ -211,7 +211,7 @@ class LammpsStructureCompatibility(LammpsStructure):
211
211
  <= cutoff_dist
212
212
  )
213
213
  act_ind = ind[bool_1]
214
- bool_2 = np.in1d(act_ind, el_2_list)
214
+ bool_2 = np.isin(act_ind, el_2_list)
215
215
  final_ind = act_ind[bool_2]
216
216
  # Get the bond and angle type
217
217
  bond_type = val["bond_type_list"][i]
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
  import warnings
5
- from typing import Dict, List, Optional, Tuple, Union
5
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
6
6
 
7
7
  import numpy as np
8
8
  import pandas as pd
@@ -66,8 +66,8 @@ def parse_lammps_output(
66
66
  dump_h5_file_name: str = "dump.h5",
67
67
  dump_out_file_name: str = "dump.out",
68
68
  log_lammps_file_name: str = "log.lammps",
69
- remap_indices_funct: callable = remap_indices_ase,
70
- ) -> Dict:
69
+ remap_indices_funct: Callable[..., np.ndarray] = remap_indices_ase,
70
+ ) -> Dict[str, Dict[str, Any]]:
71
71
  if prism is None:
72
72
  prism = UnfoldingPrism(structure.cell)
73
73
  dump_dict = _parse_dump(
@@ -86,7 +86,7 @@ def parse_lammps_output(
86
86
 
87
87
  convert_units = UnitConverter(units).convert_array_to_pyiron_units
88
88
 
89
- hdf_output = {"generic": {}, "lammps": {}}
89
+ hdf_output: Dict[str, Dict[str, Any]] = {"generic": {}, "lammps": {}}
90
90
  hdf_generic = hdf_output["generic"]
91
91
  hdf_lammps = hdf_output["lammps"]
92
92
 
@@ -128,8 +128,8 @@ def _parse_dump(
128
128
  prism: UnfoldingPrism,
129
129
  structure: Atoms,
130
130
  potential_elements: Union[np.ndarray, List],
131
- remap_indices_funct: callable = remap_indices_ase,
132
- ) -> Dict:
131
+ remap_indices_funct: Callable[..., np.ndarray] = remap_indices_ase,
132
+ ) -> Dict[str, Any]:
133
133
  if os.path.isfile(dump_h5_full_file_name):
134
134
  if not _check_ortho_prism(prism=prism):
135
135
  raise RuntimeError(
@@ -157,14 +157,14 @@ def _collect_dump_from_text(
157
157
  prism: UnfoldingPrism,
158
158
  structure: Atoms,
159
159
  potential_elements: Union[np.ndarray, List],
160
- remap_indices_funct: callable = remap_indices_ase,
161
- ) -> Dict:
160
+ remap_indices_funct: Callable[..., np.ndarray] = remap_indices_ase,
161
+ ) -> Dict[str, Any]:
162
162
  """
163
163
  general purpose routine to extract static from a lammps dump file
164
164
  """
165
165
  rotation_lammps2orig = prism.R.T
166
166
  dump_lammps_dict = parse_raw_dump_from_text(file_name=file_name)
167
- dump_dict = {}
167
+ dump_dict: Dict[str, Any] = {}
168
168
  for key, val in dump_lammps_dict.items():
169
169
  if key in ["cells"]:
170
170
  dump_dict[key] = [prism.unfold_cell(cell=cell) for cell in val]
@@ -337,4 +337,4 @@ def _check_ortho_prism(
337
337
  Returns:
338
338
  boolean: True or False
339
339
  """
340
- return np.isclose(prism.R, np.eye(3), rtol=rtol, atol=atol).all()
340
+ return bool(np.isclose(prism.R, np.eye(3), rtol=rtol, atol=atol).all())
@@ -221,25 +221,25 @@ def parse_raw_lammps_log(file_name: str) -> pd.DataFrame:
221
221
  with open(file_name, "r") as f:
222
222
  dfs = []
223
223
  read_thermo = False
224
- for l in f:
225
- l = l.lstrip()
224
+ for line in f:
225
+ line = line.lstrip()
226
226
 
227
- if l.startswith("Step"):
227
+ if line.startswith("Step"):
228
228
  thermo_lines = ""
229
229
  read_thermo = True
230
230
 
231
231
  if read_thermo:
232
- if l.startswith("Loop") or l.startswith("ERROR"):
232
+ if line.startswith("Loop") or line.startswith("ERROR"):
233
233
  read_thermo = False
234
234
  dfs.append(
235
235
  pd.read_csv(StringIO(thermo_lines), sep="\\s+", engine="c")
236
236
  )
237
237
 
238
- elif l.startswith("WARNING:"):
239
- warnings.warn(f"A warning was found in the log:\n{l}")
238
+ elif line.startswith("WARNING:"):
239
+ warnings.warn(f"A warning was found in the log:\n{line}")
240
240
 
241
241
  else:
242
- thermo_lines += l
242
+ thermo_lines += line
243
243
 
244
244
  if len(dfs) == 1:
245
245
  df = dfs[0]
@@ -49,8 +49,8 @@ class PotentialAbstract:
49
49
  def __init__(
50
50
  self,
51
51
  potential_df: pandas.DataFrame,
52
- default_df: pandas.DataFrame = None,
53
- selected_atoms: list[str] = None,
52
+ default_df: Optional[pandas.DataFrame] = None,
53
+ selected_atoms: Optional[list[str]] = None,
54
54
  ):
55
55
  self._potential_df = potential_df
56
56
  self._default_df = default_df
@@ -328,7 +328,7 @@ def update_potential_paths(
328
328
 
329
329
 
330
330
  def get_resource_path_from_conda(
331
- env_variables: tuple[str] = ("CONDA_PREFIX", "CONDA_DIR"),
331
+ env_variables: tuple[str, ...] = ("CONDA_PREFIX", "CONDA_DIR"),
332
332
  ) -> str:
333
333
  env = os.environ
334
334
  for conda_var in env_variables:
@@ -359,7 +359,7 @@ def get_potential_by_name(potential_name: str, resource_path: Optional[str] = No
359
359
 
360
360
  def validate_potential_dataframe(
361
361
  potential_dataframe: pandas.DataFrame,
362
- ) -> pandas.DataFrame:
362
+ ) -> Union[pandas.DataFrame, pandas.Series]:
363
363
  if isinstance(potential_dataframe, pandas.Series):
364
364
  return potential_dataframe
365
365
  elif isinstance(potential_dataframe, pandas.DataFrame):
@@ -7,7 +7,7 @@ from __future__ import annotations
7
7
  import decimal as dec
8
8
  import posixpath
9
9
  import warnings
10
- from typing import Any, Dict, List, Optional, Tuple, Union
10
+ from typing import Any, Dict, List, Optional, Tuple, Union, cast
11
11
 
12
12
  import numpy as np
13
13
  from ase.atoms import Atoms
@@ -16,12 +16,14 @@ from ase.data import atomic_masses, atomic_numbers
16
16
  from lammpsparser.units import UnitConverter
17
17
 
18
18
  try:
19
- from ase.calculators.lammps import Prism
19
+ from ase.calculators.lammps import Prism as PrismBase
20
20
  except ImportError:
21
21
  try:
22
- from ase.calculators.lammpsrun import Prism
22
+ from ase.calculators.lammpsrun import Prism as PrismBase
23
23
  except ImportError:
24
- from ase.calculators.lammpsrun import prism as Prism
24
+ from ase.calculators.lammpsrun import (
25
+ prism as PrismBase, # type: ignore[attr-defined,no-redef]
26
+ )
25
27
 
26
28
  __author__ = "Joerg Neugebauer, Sudarsan Surendralal, Yury Lysogorskiy, Jan Janssen, Markus Tautschnig"
27
29
  __copyright__ = (
@@ -35,7 +37,7 @@ __status__ = "production"
35
37
  __date__ = "Sep 1, 2017"
36
38
 
37
39
 
38
- class UnfoldingPrism(Prism):
40
+ class UnfoldingPrism(PrismBase):
39
41
  """
40
42
  Create a lammps-style triclinic prism object from a cell
41
43
 
@@ -69,7 +71,7 @@ class UnfoldingPrism(Prism):
69
71
  cell, pbc=np.array(pbc), tolerance=float("1e-{}".format(digits))
70
72
  )
71
73
  except TypeError:
72
- super(UnfoldingPrism, self).__init__(cell, pbc=np.array(pbc), digits=digits)
74
+ super(UnfoldingPrism, self).__init__(cell, pbc=np.array(pbc), digits=digits) # type: ignore[call-arg]
73
75
  a, b, c = cell
74
76
  an, bn, cn = [np.linalg.norm(v) for v in cell]
75
77
 
@@ -270,8 +272,8 @@ class LammpsStructure:
270
272
  input_str += format_str.format(id_atom, x, y, z)
271
273
  elif len(self._structure.positions[0]) == 2:
272
274
  format_str = "{0:d} {1:f} {2:f}\n"
273
- for id_atom, (x, y) in enumerate(vels, start=1):
274
- input_str += format_str.format(id_atom, x, y)
275
+ for id_atom, velocity in enumerate(vels, start=1):
276
+ input_str += format_str.format(id_atom, velocity[0], velocity[1])
275
277
  return input_str
276
278
 
277
279
  @property
@@ -352,7 +354,7 @@ class LammpsStructure:
352
354
  + "0. {} zlo zhi\n".format(zhi)
353
355
  )
354
356
 
355
- if is_skewed(self.structure) or self._force_skewed:
357
+ if is_skewed(self._structure) or self._force_skewed:
356
358
  simulation_cell += "{0} {1} {2} xy xz yz\n".format(xy, xz, yz)
357
359
 
358
360
  return simulation_cell
@@ -383,7 +385,7 @@ class LammpsStructure:
383
385
  )
384
386
  return (
385
387
  self.lammps_header(
386
- structure=self.structure,
388
+ structure=self._structure,
387
389
  cell_dimensions=self.simulation_cell(),
388
390
  species_lammps_id_dict=species_lammps_id_dict,
389
391
  )
@@ -500,7 +502,7 @@ def is_skewed(structure: Atoms, tolerance: float = 1.0e-8) -> bool:
500
502
 
501
503
  def write_lammps_datafile(
502
504
  structure: Atoms,
503
- potential_elements: Union[np.ndarray, list],
505
+ potential_elements: Union[np.ndarray, list[str]],
504
506
  bond_dict: Optional[Dict] = None,
505
507
  units: str = "metal",
506
508
  file_name: str = "lammps.data",
@@ -508,7 +510,7 @@ def write_lammps_datafile(
508
510
  atom_type: str = "atomic",
509
511
  ) -> None:
510
512
  lammps_str = LammpsStructure(bond_dict=bond_dict, units=units, atom_type=atom_type)
511
- lammps_str.el_eam_lst = potential_elements
513
+ lammps_str.el_eam_lst = cast(List[str], list(potential_elements))
512
514
  lammps_str.structure = structure
513
515
  lammps_str.write_file(file_name=file_name, cwd=working_directory)
514
516
 
@@ -1,34 +0,0 @@
1
- # file generated by setuptools-scm
2
- # don't change, don't track in version control
3
-
4
- __all__ = [
5
- "__version__",
6
- "__version_tuple__",
7
- "version",
8
- "version_tuple",
9
- "__commit_id__",
10
- "commit_id",
11
- ]
12
-
13
- TYPE_CHECKING = False
14
- if TYPE_CHECKING:
15
- from typing import Tuple
16
- from typing import Union
17
-
18
- VERSION_TUPLE = Tuple[Union[int, str], ...]
19
- COMMIT_ID = Union[str, None]
20
- else:
21
- VERSION_TUPLE = object
22
- COMMIT_ID = object
23
-
24
- version: str
25
- __version__: str
26
- __version_tuple__: VERSION_TUPLE
27
- version_tuple: VERSION_TUPLE
28
- commit_id: COMMIT_ID
29
- __commit_id__: COMMIT_ID
30
-
31
- __version__ = version = '0.0.2'
32
- __version_tuple__ = version_tuple = (0, 0, 2)
33
-
34
- __commit_id__ = commit_id = None
File without changes
File without changes