forked from ovito-org/pyironFileReader
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
226 additions
and
70 deletions.
There are no files selected for viewing
Empty file.
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from ovito.io import import_file | ||
|
||
|
||
def main(): | ||
pipeline = import_file("lmp.h5") | ||
data = pipeline.compute() | ||
|
||
print("Particle properties:") | ||
for prop in data.particles.keys(): | ||
print(prop) | ||
print("\nAttributes:") | ||
for attr in data.attributes.keys(): | ||
print(attr) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from pyiron_atomistics import Project | ||
|
||
pr = Project("test") | ||
structure = pr.create.structure.ase.bulk("Al", cubic=True) | ||
structure.set_repeat([9, 9, 9]) | ||
job = pr.create.job.Lammps("lmp") | ||
job.structure = structure | ||
job.calc_md(n_ionic_steps=1000, n_print=10, temperature=500.0) | ||
job.run() |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,64 @@ | ||
# PythonFileReaderTemplate | ||
# pyiron File Reader | ||
*OVITO* Python file reader for the h5 data containers written by *pyiron*. | ||
|
||
Template for a custom Python-based file reader that hooks into *OVITO* and can easily be shared with other users. | ||
## Description | ||
Python file reader for *OVITO* that reads structural data from the hdf5 containers written by [*pyiron*](https://pyiron.org/). After installation, *OVITO* will auto-detect *pyiron* files and open them for analysis and visualization. | ||
Note, that the *"status"* of the pyiron job needs to be *"finished"* before its file can be read. | ||
The following table gives an overview over all *particle properties* and *attributes* currently understood by this parser. Optional properties will be skipped if they are not included in the file **and** the parser is not in strict mode. | ||
|
||
This repository contains a template for creating your own [Python file reader](https://docs.ovito.org/python/introduction/custom_modifiers.html) !!WRONG LINK!!, which can be installed into *OVITO Pro* or the [`ovito`](https://pypi.org/project/ovito/) Python module using *pip*. | ||
**Particle properties** | ||
| pyiron name | OVITO name | Components | Optional | | ||
| --- | --- | :---: | :---: | | ||
| `generic/indices` | `Particle Type` | `1` | | | ||
| `generic/unwrapped_positions` | `Position` | `3` | `x*` | | ||
| `generic/positions` | `Position` | `3` | `x*`| | ||
| `generic/forces` | `Force` | `3` | `x` | | ||
| `generic/velocities` | `Velocity` | `3` | `x` | | ||
|
||
## Getting Started | ||
`*` One of `generic/unwrapped_positions` or `generic/positions` is required. | ||
|
||
1. Click the "Use this template" button to create your own repository based on this template. | ||
2. Rename `src/FileReaderName` to reflect the name of your modifier. | ||
3. Implement your [file reader](https://docs.ovito.org/python/introduction/custom_modifiers.html#advanced-interface) !!WRONG LINK!! in [`src/FileReaderName/__init__.py`](src/FileReaderName/__init__.py). Fill in the predefined functions as needed. More details on this method can be found in the [OVITO Python docs](https://www.ovito.org/docs/current/python/introduction/custom_modifiers.html#writing-custom-modifiers-advanced-interface) !!WRONG LINK!!. | ||
4. Fill in the [`pyproject.toml`](pyproject.toml) file. Fields that need to be replaced with your information are enclosed in descriptive `[[field]]` tags. Please make sure to include ovito>=3.9 as a dependency. Depending on your needs, you can add additional fields to the `pyproject.toml` file. Information can be found [here](https://setuptools.pypa.io/en/latest/userguide/index.html). | ||
5. Fill in the [`README_Template.md`](README_Template.md) file. Again, the `[[fields]]` placeholders should guide you. Feel free to add other sections like "Images", "Citation", or "References" as needed. | ||
6. Add meaningful examples and data sample files to the `Examples` directory to help others understand the use of your modifier. | ||
7. Pick a license for your project and replace the current (MIT) [`LICENSE`](LICENSE) file with your license. If you keep the MIT license, please update the name and year in the current file. | ||
8. Once you're done, rename `README_Template.md` to `README.md`, replacing this file. | ||
**Attributes** | ||
| pyiron name | OVITO name | Components | Optional | | ||
| --- | --- | :---: | :---: | | ||
| `generic/steps` | `Timestep` | 1 | | | ||
| `generic/natoms` | `Number of atoms` | 1 | | | ||
| `generic/temperature` | `Temperature` | 1 | `x` | | ||
| `generic/energy_tot` | `Total energy` | 1 | `x` | | ||
|
||
The file reader can be installed either into *OVITO Pro* or the [*OVITO* Python module](https://pypi.org/project/ovito/) Python module using *pip*. | ||
|
||
## Parameters | ||
- `roundCell` / "Round cell to orthogonal": Round the off-diagonal components of the simulation cell to `0` if they are below a threshold value currently hard-coded to `1e-8` A. | ||
- `strict` / "Strict mode": Activate strict mode which requires all optional keys to be present in the pyiron data container. In strict mode, any missing key will raise a `KeyError`. The default (non-strict) mode silently skips all missing optional keys. | ||
|
||
## Example | ||
1. [Example 01](Examples/example_01.py) loads the [`lmp.h5` structure file](Examples/lmp.h5) and prints all *particle properties* and *attributes* found therein. | ||
|
||
The following image shows the same file in the *OVITO PRO* desktop application. | ||
 | ||
|
||
### Example data generation | ||
The example data was generated using the [`generate_example_data_01.py`](Examples/generate_example_data_01.py) script using `pyiron`. For more information visit their [website](https://pyiron.org/). | ||
|
||
## Installation | ||
- OVITO PRO built-in Python interpreter | ||
``` | ||
ovitos -m pip install --user https://github.com/nnn911/pyironFileReader/main/archive.zip | ||
``` | ||
- Standalone Python package or Conda environment | ||
``` | ||
pip install --user https://github.com/nnn911/pyironFileReader/main/archive.zip | ||
``` | ||
- Please note that the `--user` tag is recommended but optional and depends on your Python installation. | ||
|
||
## Technical information / dependencies | ||
- Tested with *OVITO* 3.9.0 | ||
- Depends on: | ||
- `numpy` | ||
- `h5py` | ||
|
||
## Adding new properties or attributes | ||
New optional *particle properties* and *attributes* can be included in the parser quite easily. To add new particle properties, include them in the `particle_props_dict` of the `PyironFileReader` class, which can be found [here](src/pyironFileReader/__init__.py). Similarly, new attributes need to be added to the `attributes_dict`. Both dictionaries map `pyiron names` to `OVITO names`. If you add new properties consider contacting the author or submitting a pull request to make these changes available to the whole community. | ||
|
||
## Contact | ||
- Daniel Utt ([email protected]) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,26 +3,26 @@ requires = ["setuptools"] | |
build-backend = "setuptools.build_meta" | ||
|
||
[project] | ||
name = "[[FileReaderName]]" | ||
version = "[[Version number]]" | ||
description = "[[Short description]]" | ||
name = "pyironFileReader" | ||
version = "2023.0" | ||
description = "OVITO Python file reader for the h5 data containers written by pyiron." | ||
keywords = ["ovito", "python-file-reader"] | ||
authors = [{name = "[[Author 1 name]]", email = "[[Author 1 email]]"}, {name = "[[Author 2 name]]", email = "[[Author 2 email]]"}] | ||
maintainers = [{name = "[[Maintainer 1 name]]", email = "[[Maintainer 1 email]]"}, {name = "[[Maintainer 2 name]]", email = "[[Maintainer 2 email]]"}] | ||
license = {text = "[[License]]"} | ||
authors = [{name = "Daniel Utt", email = "[email protected]"}] | ||
maintainers = [{name = "Daniel Utt", email = "[email protected]"}] | ||
license = {text = "MIT License"} | ||
readme = "README.md" | ||
requires-python = "[[>=3.7]]" | ||
requires-python = ">=3.7" | ||
dependencies = [ | ||
"ovito >= [[VersionNumber]]", # OVITO must be >=3.9! | ||
# "[[dependency1]]", | ||
# "[[dependency2 == Version]]", | ||
"ovito >= 3.9.0", | ||
"numpy", | ||
"h5py" | ||
] | ||
|
||
[project.urls] | ||
repository = "[[Repository Link]]" | ||
repository = "https://github.com/nnn911/pyironFileReader" | ||
|
||
[project.entry-points.'OVITO.FileReader'] | ||
"[[Human readable file reader name]]" = "[[FileReaderName]]:[[FileReaderName]]" | ||
"pyiron File Reader" = "pyironFileReader:PyironFileReader" | ||
|
||
[tool.setuptools.packages.find] | ||
where = ["src"] |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
from ovito.data import DataCollection | ||
from ovito.io import FileReaderInterface | ||
import numpy as np | ||
from typing import Callable, Any | ||
from traits.api import Bool | ||
import h5py | ||
|
||
|
||
class PyironFileReader(FileReaderInterface): | ||
roundCell = Bool(False, label="Round cell to orthogonal") | ||
roundCellBy = 1e-8 | ||
strict = Bool(False, label="Strict mode") | ||
|
||
particle_props_dict = { | ||
"output/generic/forces": "Force", | ||
"output/generic/velocities": "Velocity", | ||
} | ||
|
||
attributes_dict = { | ||
"output/generic/steps": "Timestep", | ||
"output/generic/natoms": "Number of atoms", | ||
"output/generic/temperature": "Temperature", | ||
"output/generic/energy_tot": "Total energy", | ||
} | ||
|
||
@staticmethod | ||
def detect(filename: str): | ||
try: | ||
with h5py.File(filename, "r") as f: | ||
for k in f.keys(): | ||
# Check if all jobs in the h5 container have status "finished" -> (encoded as ascii array) | ||
if not np.all( | ||
f[k]["status"][:] == [102, 105, 110, 105, 115, 104, 101, 100] | ||
): | ||
break | ||
else: | ||
return True | ||
except Exception: | ||
pass | ||
return False | ||
|
||
def scan(self, filename: str, register_frame: Callable[..., None]): | ||
with h5py.File(filename, "r") as f: | ||
for k in f.keys(): | ||
for i in range(len(f[k]["output/generic/natoms"])): | ||
register_frame( | ||
parser_data=i, | ||
label=f"{k}: {f[k]['output/generic/steps'][i]}", | ||
) | ||
|
||
def parse( | ||
self, data: DataCollection, filename: str, parser_data: tuple, **kwargs: Any | ||
): | ||
with h5py.File(filename, "r") as f: | ||
# Map from global frame index (parser_data) to local run in the h5 file | ||
keys = list(f.keys()) | ||
if len(keys) > 1: | ||
total = [len(f[key]["output/generic/natoms"]) for key in keys] | ||
total = np.cumsum(total) | ||
keyIdx = np.argmin(total <= parser_data) | ||
key = keys[keyIdx] | ||
localIdx = parser_data - total[keyIdx - 1] | ||
else: | ||
key = keys[0] | ||
localIdx = parser_data | ||
|
||
# Create particles | ||
particles = data.create_particles( | ||
count=int(f[key]["output/generic/natoms"][localIdx]) | ||
) | ||
# Particle type | ||
typeProperty = particles.create_property("Particle Type") | ||
typeList = eval( | ||
"".join([chr(item) for item in f[key]["output/structure/species"][:]]) | ||
) | ||
uTypesH5 = np.unique(f[key]["output/generic/indices"][localIdx]) | ||
uTypesOvito = np.zeros(uTypesH5[-1] + 1, dtype=int) | ||
for u in uTypesH5: | ||
uTypesOvito[u] = typeProperty.add_type_name(typeList[u], particles).id | ||
types = np.array(f[key]["output/generic/indices"][localIdx]) | ||
for u in uTypesH5: | ||
typeProperty[types == u] = uTypesOvito[u] | ||
|
||
# Positions -> preference for unwrapped positions | ||
try: | ||
particles.create_property( | ||
"Position", | ||
data=f[key]["output/generic/unwrapped_positions"][localIdx], | ||
) | ||
except KeyError: | ||
particles.create_property( | ||
"Position", | ||
data=f[key]["output/generic/positions"][localIdx], | ||
) | ||
|
||
# Optional particle properties | ||
for h5Key, ovitoKey in self.particle_props_dict.items(): | ||
try: | ||
particles.create_property( | ||
ovitoKey, | ||
data=f[key][h5Key][localIdx], | ||
) | ||
except KeyError: | ||
if self.strict: | ||
raise KeyError( | ||
f"{key}/{h5Key} requested but not found in pyirion data container. Consider not running in strict mode." | ||
) | ||
|
||
# Cell | ||
cellMatrix = np.zeros((3, 4)) | ||
cellMatrix[:3, :3] = f[key]["output/generic/cells"][localIdx] | ||
if self.roundCell: | ||
for idx in ((0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)): | ||
cellMatrix[idx] = ( | ||
0 if cellMatrix[idx] <= self.roundCellBy else cellMatrix[idx] | ||
) | ||
data.create_cell(cellMatrix, pbc=f[key]["output/structure/cell/pbc"][:]) | ||
|
||
# Attributes | ||
for h5Key, ovitoKey in self.attributes_dict.items(): | ||
try: | ||
data.attributes[ovitoKey] = f[key][h5Key][localIdx] | ||
except KeyError: | ||
if self.strict: | ||
raise KeyError( | ||
f"{key}/{h5Key} requested but not found in pyirion data container. Consider not running in strict mode." | ||
) |