ovito-auto-viz 0.4.2__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.
- ovito_auto_viz-0.4.2/CITATION.cff +37 -0
- ovito_auto_viz-0.4.2/LICENSE +28 -0
- ovito_auto_viz-0.4.2/MANIFEST.in +3 -0
- ovito_auto_viz-0.4.2/PKG-INFO +506 -0
- ovito_auto_viz-0.4.2/README.md +489 -0
- ovito_auto_viz-0.4.2/pyproject.toml +33 -0
- ovito_auto_viz-0.4.2/setup.cfg +4 -0
- ovito_auto_viz-0.4.2/src/ovito_auto_viz.egg-info/PKG-INFO +506 -0
- ovito_auto_viz-0.4.2/src/ovito_auto_viz.egg-info/SOURCES.txt +29 -0
- ovito_auto_viz-0.4.2/src/ovito_auto_viz.egg-info/dependency_links.txt +1 -0
- ovito_auto_viz-0.4.2/src/ovito_auto_viz.egg-info/entry_points.txt +2 -0
- ovito_auto_viz-0.4.2/src/ovito_auto_viz.egg-info/requires.txt +4 -0
- ovito_auto_viz-0.4.2/src/ovito_auto_viz.egg-info/top_level.txt +1 -0
- ovito_auto_viz-0.4.2/src/ovzm/__init__.py +24 -0
- ovito_auto_viz-0.4.2/src/ovzm/card.py +160 -0
- ovito_auto_viz-0.4.2/src/ovzm/cli.py +164 -0
- ovito_auto_viz-0.4.2/src/ovzm/crystal.py +158 -0
- ovito_auto_viz-0.4.2/src/ovzm/grains.py +252 -0
- ovito_auto_viz-0.4.2/src/ovzm/grid.py +210 -0
- ovito_auto_viz-0.4.2/src/ovzm/importer.py +147 -0
- ovito_auto_viz-0.4.2/src/ovzm/labels.py +223 -0
- ovito_auto_viz-0.4.2/src/ovzm/pipelinebuild.py +375 -0
- ovito_auto_viz-0.4.2/src/ovzm/presets/dxa-standard.yaml +25 -0
- ovito_auto_viz-0.4.2/src/ovzm/presets/segregation-map.yaml +20 -0
- ovito_auto_viz-0.4.2/src/ovzm/runner.py +472 -0
- ovito_auto_viz-0.4.2/src/ovzm/scene.py +383 -0
- ovito_auto_viz-0.4.2/src/ovzm/schema/vizcard.schema.json +713 -0
- ovito_auto_viz-0.4.2/tests/test_example_physics.py +72 -0
- ovito_auto_viz-0.4.2/tests/test_grains.py +312 -0
- ovito_auto_viz-0.4.2/tests/test_ovito_compat.py +194 -0
- ovito_auto_viz-0.4.2/tests/test_packaging.py +120 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
title: ovito-auto-viz
|
|
4
|
+
abstract: >-
|
|
5
|
+
Declarative, reproducible OVITO visualization of LAMMPS files: YAML
|
|
6
|
+
viz-cards rendered to publication-quality images, comparison grids,
|
|
7
|
+
movies, or ready-to-open OVITO sessions, with all crystallographic
|
|
8
|
+
labels (Burgers vectors, line directions, character angles) computed
|
|
9
|
+
from the data itself and full provenance embedded in every output.
|
|
10
|
+
type: software
|
|
11
|
+
authors:
|
|
12
|
+
- family-names: Bitzek
|
|
13
|
+
given-names: Erik
|
|
14
|
+
orcid: "https://orcid.org/0000-0001-7430-3694"
|
|
15
|
+
email: e.bitzek@mpi-susmat.de
|
|
16
|
+
affiliation: >-
|
|
17
|
+
Max-Planck-Institut for Sustainable Materials, Düsseldorf, Germany;
|
|
18
|
+
Institute of Materials Simulation (WW8), Friedrich-Alexander-Universität
|
|
19
|
+
Erlangen-Nürnberg (FAU), Fürth, Germany
|
|
20
|
+
doi: 10.5281/zenodo.21796154
|
|
21
|
+
identifiers:
|
|
22
|
+
- type: doi
|
|
23
|
+
value: 10.5281/zenodo.21796154
|
|
24
|
+
description: Concept DOI, resolves to the latest version
|
|
25
|
+
repository-code: "https://github.com/biterik/ovito-auto-viz"
|
|
26
|
+
url: "https://github.com/biterik/ovito-auto-viz"
|
|
27
|
+
license: BSD-3-Clause
|
|
28
|
+
version: 0.4.2
|
|
29
|
+
date-released: 2026-09-24
|
|
30
|
+
keywords:
|
|
31
|
+
- OVITO
|
|
32
|
+
- LAMMPS
|
|
33
|
+
- molecular dynamics
|
|
34
|
+
- dislocations
|
|
35
|
+
- visualization
|
|
36
|
+
- materials science
|
|
37
|
+
- reproducibility
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Erik Bitzek
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ovito-auto-viz
|
|
3
|
+
Version: 0.4.2
|
|
4
|
+
Summary: Declarative, reproducible OVITO visualization of LAMMPS files: YAML viz-cards -> images, movies, or ready-to-open OVITO sessions.
|
|
5
|
+
Author-email: Erik Bitzek <e.bitzek@mpi-susmat.de>
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/biterik/ovito-auto-viz
|
|
8
|
+
Project-URL: Repository, https://github.com/biterik/ovito-auto-viz
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: ovito>=3.12
|
|
13
|
+
Requires-Dist: PyYAML>=6.0
|
|
14
|
+
Requires-Dist: jsonschema>=4.0
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# ovito-auto-viz
|
|
19
|
+
|
|
20
|
+
[](https://doi.org/10.5281/zenodo.21796154)
|
|
21
|
+
[](https://github.com/biterik/ovito-auto-viz/actions/workflows/ci.yml)
|
|
22
|
+
[](https://pypi.org/project/ovito-auto-viz/)
|
|
23
|
+
[](LICENSE)
|
|
24
|
+
|
|
25
|
+
**Fast, automated, reproducible and FAIR visualization of atomistic
|
|
26
|
+
simulations with [OVITO](https://www.ovito.org/) — self-labeling figures
|
|
27
|
+
with complete metadata and provenance.**
|
|
28
|
+
|
|
29
|
+
You — or the LLM of your choice — describe the figure in a ~20-line YAML
|
|
30
|
+
**viz card**; the `ovzm` CLI turns
|
|
31
|
+
it into a publication-quality image, movie, or ready-to-open OVITO session.
|
|
32
|
+
Everything on the figure — Burgers vectors, line directions, character
|
|
33
|
+
angles, composition, colorbars, per-grain tripods — is **computed from the
|
|
34
|
+
data itself**. And every figure **permanently remembers** who made it, from
|
|
35
|
+
which data file (SHA-256), with which settings, under which funding, and
|
|
36
|
+
which publication it belongs to: the full provenance record is embedded
|
|
37
|
+
inside the PNG. Works hands-on, in scripts, on HPC clusters — and
|
|
38
|
+
conversationally through an LLM agent skill.
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
*The whole story in one picture: a LAMMPS dump and the simulation project's
|
|
43
|
+
context go in; a ~20-line **viz card** — written by you or by an AI agent —
|
|
44
|
+
tells `ovzm render` what the figure is; out come a publication-ready image
|
|
45
|
+
AND its complete provenance, embedded inside the PNG itself.*
|
|
46
|
+
|
|
47
|
+
## Why
|
|
48
|
+
|
|
49
|
+
Scientific figures take time to make and are amongst the **least FAIR objects** in a publication:
|
|
50
|
+
pixels with no metadata, produced by GUI clicks nobody can repeat, separated
|
|
51
|
+
from their data the moment they are exported. `ovzm` inverts this:
|
|
52
|
+
|
|
53
|
+
- **The figure is a text file.** The card is versionable, diffable,
|
|
54
|
+
reviewable, and re-runs identically on your laptop or a cluster. Same
|
|
55
|
+
card + same data = same figure, years later. The card can even be
|
|
56
|
+
extracted from the figure if it goes missing.
|
|
57
|
+
- **The physics labels itself.** DXA dislocation segments get their Burgers
|
|
58
|
+
vector, line direction, and character angle computed from the data —
|
|
59
|
+
nucleated defects with zero metadata are labeled just as well as
|
|
60
|
+
constructed ones. Composition, colorbar limits, and crystal-axis tripods
|
|
61
|
+
are derived, never typed.
|
|
62
|
+
- **A figure never forgets.** Creator (mandatory — the run aborts without
|
|
63
|
+
it), affiliation, ORCID, project, funding, input file with SHA-256, the
|
|
64
|
+
fully resolved card and scene: all of it is written to a `.prov.yaml`
|
|
65
|
+
sidecar AND embedded into the PNG itself as a compressed text chunk.
|
|
66
|
+
Image and provenance cannot be separated by copying, renaming, emailing,
|
|
67
|
+
or archiving.
|
|
68
|
+
- **Comparisons are honest.** `ovzm grid` renders one card over many inputs
|
|
69
|
+
with identical camera, magnification, styling, and colorbar limits — the
|
|
70
|
+
manual-GUI failure mode this tool exists to kill.
|
|
71
|
+
- **LLM-ready by design.** The card is one shared interface for humans,
|
|
72
|
+
scripts, and AI agents. With the bundled agent skill, *"glide-plane view
|
|
73
|
+
of dump.1530000.gz, Cu segregation, paper quality"* becomes a rendered
|
|
74
|
+
figure — the agent writes the card, collects attribution context from
|
|
75
|
+
your project directory, and asks (never guesses) whatever the data cannot
|
|
76
|
+
provide. The tool itself requires no AI; the skill is an optional adapter
|
|
77
|
+
on top.
|
|
78
|
+
|
|
79
|
+
## The showcase figure
|
|
80
|
+
|
|
81
|
+

|
|
82
|
+
|
|
83
|
+
*A crack in tungsten runs in from the left, kinks onto a phosphorus-decorated
|
|
84
|
+
grain boundary, and continues along it (bcc W dark gray, defective atoms
|
|
85
|
+
white, P orange, one Miller-labeled tripod per grain — CNA + the
|
|
86
|
+
`structure_colors`/pinned-species styling and the `grains:` tripods, all from
|
|
87
|
+
one card). Configuration from
|
|
88
|
+
[Tian et al., Acta Materialia 259 (2023) 119256](https://doi.org/10.1016/j.actamat.2023.119256).
|
|
89
|
+
The image carries its own receipt — clone the repo and ask it where it comes
|
|
90
|
+
from:*
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
ovzm prov docs/readme-hero.png # prints creator, input file + SHA-256,
|
|
94
|
+
# the resolved card, and the paper's DOI
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Install
|
|
98
|
+
|
|
99
|
+
`ovzm` is an ordinary Python package (Python ≥ 3.9). Its main dependency,
|
|
100
|
+
the [`ovito`](https://pypi.org/project/ovito/) Python module (free of
|
|
101
|
+
charge, DXA included), is installed **automatically** by pip — you do NOT
|
|
102
|
+
need the OVITO desktop application. Install into a conda/mamba environment
|
|
103
|
+
or a venv, **never** into a system Python (many systems ship no
|
|
104
|
+
user-writable `pip`, and installing one globally is a good way to break the
|
|
105
|
+
OS package manager).
|
|
106
|
+
|
|
107
|
+
**Linux**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
python -m venv ~/venvs/ovzm && source ~/venvs/ovzm/bin/activate # or: conda activate <env>
|
|
111
|
+
pip install ovito-auto-viz
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Headless machines (clusters, CI, containers) additionally need the
|
|
115
|
+
graphics runtime the `ovito` module links against — no GPU or display
|
|
116
|
+
required (rendering uses the Tachyon software ray-tracer). Since ovito 3.16
|
|
117
|
+
the Linux module renders through **Vulkan** and needs a Vulkan *driver*
|
|
118
|
+
even for offscreen renders; Mesa's `lavapipe` software driver does the job
|
|
119
|
+
without a GPU:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
sudo apt-get install libopengl0 libegl1 libgl1 libglx0 libxkbcommon0 mesa-vulkan-drivers # Debian/Ubuntu
|
|
123
|
+
# Fedora/RHEL: libglvnd-opengl libglvnd-egl libglvnd-glx libxkbcommon mesa-vulkan-drivers
|
|
124
|
+
# openSUSE: ... libvulkan_lvp
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If `ovzm render` stops with "Could not initialize the Vulkan graphics
|
|
128
|
+
backend", that driver is what is missing. On a cluster without root, ask the
|
|
129
|
+
admins for it or fall back to `pip install "ovito<3.16"`, which still uses
|
|
130
|
+
OpenGL and needs only the first five packages.
|
|
131
|
+
|
|
132
|
+
On HPC, install into a venv under scratch (never `$HOME`) and run renders
|
|
133
|
+
inside a batch job, not on a login node.
|
|
134
|
+
|
|
135
|
+
**macOS** (Intel and Apple Silicon)
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
conda activate <your-env> # conda-forge env recommended on macOS
|
|
139
|
+
pip install ovito-auto-viz
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Known upstream wheel bug: on Apple-silicon Macs `ovito==3.16.1` fails to
|
|
143
|
+
import with `Library not loaded: @loader_path/libospray.3.2.0.dylib` (the
|
|
144
|
+
wheel ships the file only as `libospray.3.dylib`). Either
|
|
145
|
+
`pip install "ovito==3.15.5"`, or add the missing name:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
ln -s libospray.3.dylib "$(python -c 'import ovito,os;print(os.path.dirname(ovito.__file__))')/plugins/libospray.3.2.0.dylib"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Windows**
|
|
152
|
+
|
|
153
|
+
The `ovito` module ships Windows wheels, so the same install should work in
|
|
154
|
+
an Anaconda Prompt or venv (not yet routinely tested — reports welcome):
|
|
155
|
+
|
|
156
|
+
```powershell
|
|
157
|
+
pip install ovito-auto-viz
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
If anything misbehaves natively, WSL2 + the Linux instructions above is the
|
|
161
|
+
reliable fallback.
|
|
162
|
+
|
|
163
|
+
**Check the install** — this must print JSON:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
ovzm schema | head -3
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The latest development version comes straight from GitHub:
|
|
170
|
+
`pip install git+https://github.com/biterik/ovito-auto-viz.git` — and for
|
|
171
|
+
development, install editable from a clone:
|
|
172
|
+
`pip install -e /absolute/path/to/ovito-auto-viz`.
|
|
173
|
+
|
|
174
|
+
## Quickstart
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
# my-figure.yaml
|
|
178
|
+
name: d90-glideplane
|
|
179
|
+
extends: dxa-standard # preset: PTM + DXA + auto labels
|
|
180
|
+
input:
|
|
181
|
+
file: dump_min_sgcmc_d90_T300.1530000.gz
|
|
182
|
+
crystal:
|
|
183
|
+
x: [-1, 0, 1] # or "auto" -> parsed from x-101_y1-21_z111 filenames
|
|
184
|
+
y: [1, -2, 1]
|
|
185
|
+
z: [1, 1, 1]
|
|
186
|
+
lattice: fcc
|
|
187
|
+
view:
|
|
188
|
+
direction: top # named view, or a Miller direction like [111]
|
|
189
|
+
atoms:
|
|
190
|
+
show: non_fcc
|
|
191
|
+
names: {1: Ni, 2: Cu}
|
|
192
|
+
colors: {1: [0.62, 0.66, 0.72], 2: [0.90, 0.45, 0.10]}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
ovzm render my-figure.yaml # -> <input>__<name>.png + .prov.yaml sidecar
|
|
197
|
+
ovzm grid comparison.yaml # same card over grid.inputs -> one labeled grid
|
|
198
|
+
ovzm session my-figure.yaml # -> .ovito file: open in the GUI, pipeline + camera preset
|
|
199
|
+
ovzm import something.ovito # best-effort reverse: GUI session -> card YAML
|
|
200
|
+
ovzm info dump.gz # types, box, frames, filename-parsed orientation
|
|
201
|
+
ovzm prov figure.png # print the provenance embedded in the image
|
|
202
|
+
ovzm validate my-figure.yaml # schema check with readable errors
|
|
203
|
+
ovzm schema # print the JSON schema
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Try it in five minutes
|
|
207
|
+
|
|
208
|
+
`examples/try-it/` is fully self-contained — nothing to download: a
|
|
209
|
+
numpy-only script generates a small fcc Ni box with four edge dislocations
|
|
210
|
+
(a quadrupole — a closed system with **net b = 0**), and one card renders it
|
|
211
|
+
with every label computed from the positions alone:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cd examples/try-it
|
|
215
|
+
python make_edge_dipoles.py # ~14k atoms, a few seconds
|
|
216
|
+
ovzm render edge-dipoles.yaml --ask # asks once who you are — attribution is mandatory
|
|
217
|
+
ovzm prov edge-dipoles__edge-dipoles.png
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
See [`examples/try-it/README.md`](examples/try-it/README.md) for the
|
|
221
|
+
walkthrough and the expected (computed) label block;
|
|
222
|
+
`tests/test_example_physics.py` asserts the DXA ground truth of this
|
|
223
|
+
example in CI.
|
|
224
|
+
|
|
225
|
+
## Using it with an LLM (the agent skill)
|
|
226
|
+
|
|
227
|
+
`skills/ovito-auto-viz/SKILL.md` is an
|
|
228
|
+
[Agent Skill](https://github.com/anthropics/skills): a plain instruction
|
|
229
|
+
file (no code) that teaches a Claude session when to use `ovzm`, how to
|
|
230
|
+
compose cards from the presets, and — crucially — what it must **ask**
|
|
231
|
+
instead of guessing (species names, crystal orientation, figure creator,
|
|
232
|
+
colorbar units). Attribution context is collected automatically from the
|
|
233
|
+
project directory (`ovzm-project.yaml`, personal identity file, filename
|
|
234
|
+
conventions), so a one-line request becomes a rendered, fully attributed
|
|
235
|
+
figure plus the card to version with your project. The tool itself never
|
|
236
|
+
requires any AI — the skill is an optional adapter on top.
|
|
237
|
+
|
|
238
|
+
Install:
|
|
239
|
+
|
|
240
|
+
- **Claude Code** (CLI): copy the skill folder into your skills directory —
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
mkdir -p ~/.claude/skills
|
|
244
|
+
cp -R skills/ovito-auto-viz ~/.claude/skills/
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
It then triggers automatically on requests like "render the standard DXA
|
|
248
|
+
view of this dump" in any project where `ovzm` is installed.
|
|
249
|
+
|
|
250
|
+
- **Claude Desktop / Cowork**: add the skill via the app's
|
|
251
|
+
Settings → Capabilities/Skills (upload or point it at
|
|
252
|
+
`skills/ovito-auto-viz/`), or ask Claude in a session to package
|
|
253
|
+
`SKILL.md` as an installable `.skill` file for your account.
|
|
254
|
+
|
|
255
|
+
Usage is then conversational: *"glide-plane view of
|
|
256
|
+
`SGCMC-D90/dump.1530000.gz`, Cu segregation, paper quality"* — the session
|
|
257
|
+
writes the card (asking for whatever the required-information table says it
|
|
258
|
+
cannot detect), runs `ovzm render`, and shows you the PNG plus the card so
|
|
259
|
+
you can version it with the project.
|
|
260
|
+
|
|
261
|
+
## Attribution of figures
|
|
262
|
+
|
|
263
|
+
Every figure records who made it. `meta.creator` is **mandatory** (the run
|
|
264
|
+
aborts without it); `project`, `funding`, `affiliation`, `email`, `orcid`
|
|
265
|
+
are optional. Because people work on several projects with different
|
|
266
|
+
funding and even different affiliations, attribution is resolved
|
|
267
|
+
**per key, git-config style**:
|
|
268
|
+
|
|
269
|
+
1. the card's own `meta:` block (most specific),
|
|
270
|
+
2. an **`ovzm-project.yaml`** found by walking UP the directory tree from
|
|
271
|
+
the card and from the input data — put one in each simulation project
|
|
272
|
+
root (e.g. `SIMULATIONS/EAM-DISLOCS-Ni-Cu/ovzm-project.yaml`); a file in
|
|
273
|
+
a subdirectory (thread) overrides the project root's,
|
|
274
|
+
3. a personal `~/.config/ovzm/identity.yaml` (or `$OVZM_IDENTITY`) —
|
|
275
|
+
typically just `creator: Jane Doe`,
|
|
276
|
+
4. `--ask` prompts interactively as the last resort (creator only).
|
|
277
|
+
|
|
278
|
+
A project file for a single-user project:
|
|
279
|
+
|
|
280
|
+
```yaml
|
|
281
|
+
# SIMULATIONS/EAM-DISLOCS-Ni-Cu/ovzm-project.yaml
|
|
282
|
+
project: EAM-DISLOCS-Ni-Cu
|
|
283
|
+
funding: NFDI-MatWerk (DFG 460247524)
|
|
284
|
+
creator: Erik Bitzek
|
|
285
|
+
people:
|
|
286
|
+
Erik Bitzek:
|
|
287
|
+
affiliation: MPI for Sustainable Materials, Duesseldorf / FAU WW8, Fuerth
|
|
288
|
+
orcid: 0000-0001-7430-3694
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
For multi-user projects, omit the top-level `creator` (each user's identity
|
|
292
|
+
file supplies their name) and list everyone under `people:` — the resolved
|
|
293
|
+
creator's entry fills in their affiliation/email/ORCID for that project.
|
|
294
|
+
All resolved values land in the `.prov.yaml` and inside the PNG; every YAML
|
|
295
|
+
the tool writes carries the tool-credit header ("created with
|
|
296
|
+
ovito-auto-viz … funded by NFDI-MatWerk").
|
|
297
|
+
|
|
298
|
+
## Reading the provenance inside a PNG
|
|
299
|
+
|
|
300
|
+
The embedded record is a standard PNG text chunk (key `ovzm_prov`), so it
|
|
301
|
+
is accessible with or without this tool:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
ovzm prov figure.png # with ovito-auto-viz installed
|
|
305
|
+
ovzm prov figure.png > figure.prov.yaml # ... e.g. to regenerate a lost sidecar
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Without `ovzm`, two lines of Python (Pillow):
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
from PIL import Image
|
|
312
|
+
print(Image.open("figure.png").text["ovzm_prov"])
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
or on the command line with common metadata tools:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
exiftool -b -Ovzm_prov figure.png # exiftool
|
|
319
|
+
identify -verbose figure.png # ImageMagick: listed under Properties
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
The chunk survives copying, renaming, emailing, and archiving — anything
|
|
323
|
+
that treats the file as bytes. It does NOT survive operations that
|
|
324
|
+
re-encode the pixels: screenshots, format conversion (PNG→JPEG), or
|
|
325
|
+
"export/save for web" in image editors. For a figure that will be
|
|
326
|
+
re-encoded (e.g. embedded in a PDF), keep the `.prov.yaml` sidecar
|
|
327
|
+
alongside — it is the identical record.
|
|
328
|
+
|
|
329
|
+
## Comparison grids
|
|
330
|
+
|
|
331
|
+
`ovzm grid` renders the SAME card over several inputs (`grid.inputs`,
|
|
332
|
+
optional `grid.labels`/`grid.cols`) into one figure with **identical camera,
|
|
333
|
+
magnification, styling, and colorbar limits** across panels — the manual-GUI
|
|
334
|
+
failure mode this tool exists to kill. Tripod and legend are drawn once
|
|
335
|
+
(first panel; `grid.tripod: all` for every panel); each panel carries only
|
|
336
|
+
its title, and the per-panel analysis results (composition, DXA, …) live in
|
|
337
|
+
the grid's provenance under `panels:`.
|
|
338
|
+
|
|
339
|
+
## Per-grain tripods (bicrystals, polycrystals)
|
|
340
|
+
|
|
341
|
+
A `grains:` block draws one labeled coordinate tripod per grain — anchored at
|
|
342
|
+
a user-provided origin, oriented by user-provided Miller triplets (`x`/`y`/`z`
|
|
343
|
+
are the crystal directions of *this grain* lying along the sim-box axes, same
|
|
344
|
+
semantics as the `crystal:` block). Origins and orientations are **never
|
|
345
|
+
guessed**; give them inline or via an external grains file (`file:` XOR
|
|
346
|
+
`items:`):
|
|
347
|
+
|
|
348
|
+
```yaml
|
|
349
|
+
grains:
|
|
350
|
+
file: grains-d005.yaml # EITHER external file (path relative to the card)
|
|
351
|
+
items: # OR inline — exactly one of the two
|
|
352
|
+
- name: upper # optional; defaults g1, g2, ...
|
|
353
|
+
origin: [12.0, 40.0, 88.5] # Å, cartesian, simulation frame
|
|
354
|
+
x: [-1, 0, 1]
|
|
355
|
+
y: [1, -2, 1]
|
|
356
|
+
z: [1, 1, 1]
|
|
357
|
+
tripod: # styling, all optional
|
|
358
|
+
size: 20 # arm length in Å (default: 5% of the largest box edge, min 10 Å)
|
|
359
|
+
axes: box # 'box' (arms along the box axes, labeled with each
|
|
360
|
+
# grain's x/y/z) or 3 Miller triplets drawn in each
|
|
361
|
+
# grain's own frame, e.g. [[1,0,0],[0,1,0],[0,0,1]]
|
|
362
|
+
show_names: true
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The external grains file is a YAML mapping with the same `grains:` list —
|
|
366
|
+
write it by hand, from a Voronoi construction, or from a segmentation tool
|
|
367
|
+
(float triplets are accepted). Arms are drawn on top of the atoms with
|
|
368
|
+
world-anchored length, so tripods stay visible inside dense grains and come
|
|
369
|
+
out identical on every `ovzm grid` panel. The resolved grains (plus the
|
|
370
|
+
grains-file SHA-256) land in the provenance like everything else.
|
|
371
|
+
`tests/make_bicrystal.py` generates a Σ5 [001] bicrystal + grains file to
|
|
372
|
+
try it on. (The hero image above uses exactly this feature — one tripod per
|
|
373
|
+
grain of the W bicrystal.)
|
|
374
|
+
|
|
375
|
+
## Required minimum information
|
|
376
|
+
|
|
377
|
+
`ovzm` refuses to guess what cannot be auto-detected. The contract:
|
|
378
|
+
|
|
379
|
+
| info | auto-detected from | if not detectable |
|
|
380
|
+
|------|--------------------|-------------------|
|
|
381
|
+
| input file | — | always required in the card |
|
|
382
|
+
| species names (multi-type files) | type names in the file (data files); dumps have none | **hard error** — add `atoms.names: {1: Ni, 2: Cu}` or run with `--ask` to be prompted |
|
|
383
|
+
| crystal orientation | `x-101_y1-21_z111`-style filenames | b/ξ labels fall back to DXA's lattice frame, flagged in the label block |
|
|
384
|
+
| grain origins/orientations (tripods) | — | **hard error** if a `grains:` block is incomplete — never guessed |
|
|
385
|
+
| figure creator | ovzm-project.yaml / identity file | **hard error** — attribution is not optional |
|
|
386
|
+
| lattice (for DXA) | — | preset default (`fcc` in `dxa-standard`); set `crystal.lattice` |
|
|
387
|
+
| view | — | preset default (`front`); set `view.direction` |
|
|
388
|
+
| what is shown | — | preset default (`non_fcc` in `dxa-standard`); set `atoms.show` |
|
|
389
|
+
| colorbar units | — | set `annotate.colorbar.units`; limits are resolved automatically and recorded in the prov file |
|
|
390
|
+
|
|
391
|
+
`ovzm info <file>` prints what a file does and does not carry (types, frames,
|
|
392
|
+
box, filename-encoded orientation) — use it before writing a card.
|
|
393
|
+
|
|
394
|
+
## Naming convention
|
|
395
|
+
|
|
396
|
+
Every figure has an ID: `<input-stem>__<card-name>[__<tag>]`. The card name
|
|
397
|
+
encodes the figure's identity (view + analysis, e.g. `d90-dxa-top`); the
|
|
398
|
+
optional `output.tag` distinguishes variants. Image and provenance sidecar
|
|
399
|
+
share the ID exactly:
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
dump_min_sgcmc_d90.1530000__d90-dxa-top.png
|
|
403
|
+
dump_min_sgcmc_d90.1530000__d90-dxa-top.png.prov.yaml
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Multiple figures from the same input differ in card name; the same card on
|
|
407
|
+
multiple inputs differs in stem. The `.prov.yaml` records the ID, input
|
|
408
|
+
SHA-256, the resolved card, AND the fully resolved scene: per-type species
|
|
409
|
+
names / colors / radii, colorbar limits + units, camera, composition, and the
|
|
410
|
+
complete DXA result (per-segment b, ξ, character, net Burgers vector, and the
|
|
411
|
+
measured lattice-constant estimate). The image itself can therefore stay
|
|
412
|
+
visually clean — nothing is lost as long as the sidecar travels with it.
|
|
413
|
+
|
|
414
|
+
## What gets labeled automatically
|
|
415
|
+
|
|
416
|
+
With `annotate.labels: auto` (the default in `dxa-standard`), the label block
|
|
417
|
+
is composed from the data: timestep; total composition (e.g. `x(Cu) = 0.0100`)
|
|
418
|
+
plus shown-atom counts; DXA segment count and total line length; per-family
|
|
419
|
+
breakdown (perfect, Shockley, stair-rod, Hirth, Frank); the **net Burgers
|
|
420
|
+
vector with its character** (`net b = 1/2[-101], 90° edge`); and per-segment
|
|
421
|
+
`b = 1/6[-211] (Shockley partial), ξ = [1-21], 60° mixed, L = 100 Å`.
|
|
422
|
+
|
|
423
|
+
Frame discipline: DXA's `true_burgers_vector` lives in DXA's own lattice
|
|
424
|
+
frame, which can differ from the card's crystal frame by a cubic symmetry
|
|
425
|
+
operation. All geometry (Miller indices in the card frame, line directions,
|
|
426
|
+
character angles) is therefore computed from the segment's *spatial* Burgers
|
|
427
|
+
vector; the true vector is used only for family classification and the
|
|
428
|
+
|b_spatial|/|b_true| lattice-constant estimate. Character names are
|
|
429
|
+
conservative: `edge` ≥ 85°, `screw` ≤ 5°, otherwise the angle plus `mixed`.
|
|
430
|
+
If a dcreator `.disparam` is around it can serve as a cross-check, but
|
|
431
|
+
nothing requires metadata — nucleated dislocations label identically.
|
|
432
|
+
|
|
433
|
+
The coordinate tripod is labeled with the crystal axes (`x=[-101]`, …) and a
|
|
434
|
+
`view.fit_margin` (default 1.15) keeps all overlays outside the projected
|
|
435
|
+
cell. **Whenever atoms carry color information there is a legend**: a
|
|
436
|
+
continuous colorbar for `color_coding` (limits resolved from the shown data
|
|
437
|
+
when `range: auto`, units from `annotate.colorbar.units`), or a discrete
|
|
438
|
+
per-type legend when coloring by species.
|
|
439
|
+
|
|
440
|
+
## Presets and styling
|
|
441
|
+
|
|
442
|
+
Cards inherit via `extends:` (chains allowed; search path: `$OVZM_PRESET_PATH`,
|
|
443
|
+
then `./presets/`, then the presets bundled with the package in
|
|
444
|
+
`src/ovzm/presets/`). Shipped:
|
|
445
|
+
|
|
446
|
+
- `dxa-standard` — PTM + DXA, non-fcc atoms only, Miller tripod, auto labels.
|
|
447
|
+
- `segregation-map` — all atoms colored by type, solute rendered larger.
|
|
448
|
+
|
|
449
|
+
Output quality presets: `draft` (1280×720, fast), `slide` (1920×1080),
|
|
450
|
+
`paper` (3200×2400, ambient occlusion) — override `width`/`height` freely
|
|
451
|
+
(the hero above is `paper` at 1600×1600). Background `white`/`black`/
|
|
452
|
+
`transparent`. Mixed coloring is a card key away: `color_by: structure` with
|
|
453
|
+
`atoms.structure_colors` (e.g. bcc dark gray, defective atoms white) while
|
|
454
|
+
types listed in `atoms.colors` stay pinned to their species color — that is
|
|
455
|
+
how the hero shows a structure-colored W matrix with orange P solutes.
|
|
456
|
+
|
|
457
|
+
## Multimillion-atom workflow
|
|
458
|
+
|
|
459
|
+
The intended pattern for big data is **analyze once, render many**: the
|
|
460
|
+
expensive step is PTM/DXA, not rendering. Typical defect views delete the
|
|
461
|
+
fcc/bulk atoms (`atoms.show: non_fcc`), which cuts the rendered particle count
|
|
462
|
+
by ~100×. For files too large for a laptop, run the same card on the cluster
|
|
463
|
+
headless inside a batch job; only PNGs come back. Positions at `%.4f` Å are
|
|
464
|
+
well above every OVITO method's noise floor.
|
|
465
|
+
|
|
466
|
+
## Documentation
|
|
467
|
+
|
|
468
|
+
- `docs/SCHEMA.md` — every card key, generated from
|
|
469
|
+
`src/ovzm/schema/vizcard.schema.json` (regenerate with
|
|
470
|
+
`python tools/gen-schema-md.py`).
|
|
471
|
+
- Put `# yaml-language-server: $schema=<path>/vizcard.schema.json` at the top
|
|
472
|
+
of a card for editor autocompletion.
|
|
473
|
+
- `skills/ovito-auto-viz/SKILL.md` — the agent skill (see above).
|
|
474
|
+
|
|
475
|
+
## Author, funding, citation
|
|
476
|
+
|
|
477
|
+
**Author:** Erik Bitzek ([ORCID 0000-0001-7430-3694](https://orcid.org/0000-0001-7430-3694),
|
|
478
|
+
<e.bitzek@mpi-susmat.de>) — ¹ Max-Planck-Institut for Sustainable Materials,
|
|
479
|
+
Düsseldorf, Germany; ² Institute of Materials Simulation (WW8),
|
|
480
|
+
Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU), Fürth, Germany.
|
|
481
|
+
Built with Claude/LLM assistance.
|
|
482
|
+
|
|
483
|
+
**Funding:** Deutsche Forschungsgemeinschaft (DFG, German Research
|
|
484
|
+
Foundation) — NFDI 38/1, project number 460247524
|
|
485
|
+
(**[NFDI-MatWerk](https://nfdi-matwerk.de) consortium**).
|
|
486
|
+
|
|
487
|
+
**License:** BSD-3-Clause. **Citation:** see [`CITATION.cff`](CITATION.cff)
|
|
488
|
+
(GitHub's "Cite this repository" button).
|
|
489
|
+
|
|
490
|
+
## Known issues / roadmap
|
|
491
|
+
|
|
492
|
+
- **Sessions carry overlays only with ovito ≥ 3.16.1**: older modules
|
|
493
|
+
(observed on 3.15.5) write corrupt `.ovito` files when viewport overlays
|
|
494
|
+
are in the scene, so there `ovzm session` skips them (grain tripods
|
|
495
|
+
included) and says so; the pipeline, styling and camera are always saved.
|
|
496
|
+
Use `ovzm render` for annotated output on older versions. The
|
|
497
|
+
provenance records which case applied (`session_overlays`).
|
|
498
|
+
- Keep the OVITO GUI and the `ovito` module on matching versions when
|
|
499
|
+
exchanging session files.
|
|
500
|
+
- Roadmap: a small self-contained example (generated structure, nothing to
|
|
501
|
+
download) to try everything on; DXA segment b/ξ re-expressed in each
|
|
502
|
+
grain's local frame; grain origins/orientations imported from grain
|
|
503
|
+
segmentation / Voronoi tool output; comparison-grid shared colorbar for
|
|
504
|
+
multi-property panels; movie polish (frame ranges); `.zst` input; broader
|
|
505
|
+
`ovzm import` modifier coverage; ontology-mapped (JSON-LD) provenance
|
|
506
|
+
export.
|