F1ReplayTiming
Visualisation of real-time track data and telemetry synced to F1 replays.
Grain Texture And Response Analysis for Crystal Exploration
DataPython · SWIGGitHub @applied-material-modelingOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗An end-to-end crystal-plasticity toolkit for grain-scale materials experiments: reconstruct or generate 3D microstructures from HEDM/EBSD, calibrate the material model, run GPU CPFE, track grains across load steps, and identify rare events for targeted measurement.
graintrace works with far-field and near-field high-energy diffraction microscopy (HEDM) and EBSD, closing the loop from raw grain-scale measurements to a calibrated crystal-plasticity prediction — and back to which grains and regions are worth measuring in more detail.
Architecture. graintrace is the Python orchestration layer over a compiled scientific stack:
The pipeline runs reconstruct, calibrate, simulate (CPFE), then analyze and identify rare events.
Features
examples/demonstrate_farfield.py, examples/demonstrate_cpfe_nfff.py, examples/demonstrate_grid_segmentation_mesh.py.examples/demonstrate_hedm_study.py.examples/demonstrate_cpfe.py, examples/demonstrate_material_calibration.py.examples/demonstrate_graintracking.py.examples/demonstrate_reorientation_fragmentation.py.mesh_out/) or a regular grid (grid_out/, online or resampled offline via GridResampler). See examples/demonstrate_rei_pipeline.py.Analysis (field distributions, macroscopic stress vs strain, pole figures, IPF coloring) rounds out the pipeline. See examples/demonstrate_postprocess.py.
Documentation: https://applied-material-modeling.github.io/graintrace/
Full documentation (installation tiers, per-stage tutorials, configuration
reference, the MCP server, and the API reference) is built with Sphinx under
docs/. Build it locally with:
sudo apt-get install pandoc # system binary, not a pip package; nbsphinx needs it
pip install -e ".[docs]"
cd docs && make html # open docs/_build/html/index.html
pandoc converts the notebook tutorials; without it the build fails with
nbsphinx.PandocMissing. See https://pandoc.org/installing.html for macOS,
Windows, and conda installs.
See docs/development.rst for the strict build, doctest, and linkcheck
targets, and the definition-of-done checklist for new code.
graintrace is the Python layer. Some features are pure-Python and run straight from
pip install graintrace; others drive a compiled or licensed stack you install separately.
graintrace/__init__.py lazy-imports the compiled stack, so import graintrace always works and
a feature raises a clear error only when a tool it needs is missing.
| Capability | pip install graintrace | NEML2 (Python) | PUMA puma-opt | NEPER | CUBIT/SCULPT |
|---|---|---|---|---|---|
| Post-processing (distributions, stress–strain) | ✅ | ||||
| Rare-event identification (REI) + REI comparison | ✅ | ||||
| HEDM stitching, similarity metrics | ✅ | ||||
| FF Voronoi reconstruction, grain tracking | ✅ | ✅ | |||
| Reorientation & fragmentation analysis | ✅ | ✅² | |||
| NF / EBSD segmentation + hex meshing | ✅ | ✅ | |||
| Material calibration | ✅ | ✅ | |||
| Pole figures / orientation math | ✅ | ✅ | |||
| CPFE simulation | ✅ | ✅ | ✅ | ✅¹ | ✅¹ |
¹ CPFE needs a mesh: by default all of FF/NF/EBSD are meshed to hex with CUBIT/SCULPT (FF also uses NEPER for the tessellation). A no-CUBIT voxel-hex dump and a NEPER/gmsh tet mesh (which CPFE also runs on) are fallbacks.
² Reorientation tracking, sub-grain segmentation, and orientation averaging use NEML2 (Python) for the orientation math (and networkit for Leiden); the cross-step grain-split detector core is pure NumPy/SciPy.
pyzag is installed automatically by pip install graintrace (it is pure-Python and on PyPI). The
NEML2 (Python) column is the neml2 package built by PUMA (see Install); PUMA
puma-opt is the compiled solver binary, built with MOOSE + libtorch. CUBIT/SCULPT is
proprietary (Coreform license); NEPER is a separate tool graintrace drives. graintrace does not
install NEML2 from PyPI: PUMA builds NEML2 from its pinned submodule so puma-opt's C++ library and
the Python neml2 stay ABI-matched.
puma-opt), linked with NEML2 v3 + libtorch — for CPFEThree tiers by capability (see the table above). Each higher tier adds the PUMA-built native stack on top of the pip install.
Post-processing, REI, REI comparison, stitching, similarity metrics. No conda or native build needed:
pip install graintrace
# from a source checkout instead: pip install -e .
# optional extras:
pip install "graintrace[gnn]" # grain-graph / GNN utilities (torch-geometric)
pip install "graintrace[mcp]" # MCP server (drive graintrace from Claude Desktop/Code or any MCP client)
pip install "graintrace[examples]" # deps used by examples/ (meshio)
pip install "graintrace[dev]" # test/lint/build tooling (pytest, black, isort, build, twine)
import graintrace works with no NEML2 present (the compiled stack is lazy-imported). This tier
also installs pyzag.
To run the examples or benchmarks, clone the repo and install from the checkout — the PyPI
package ships only the graintrace library, not examples/, benchmark/, or the mwe_data/
sample datasets:
git clone https://github.com/applied-material-modeling/graintrace.git
cd graintrace
pip install -e ".[examples]" # editable install; examples/, benchmark/, mwe_data/ are now local
Material calibration and pole figures need the NEML2 Python package but not the full
MOOSE/puma-opt solver. Build only NEML2 from PUMA's submodule — the lightweight "NEML2-only" PUMA
path (no PETSc/libMesh/MOOSE build):
git clone https://github.com/applied-material-modeling/graintrace.git
cd graintrace
git submodule update --init external/puma # pulls puma -> moose + neml2
# Create the PUMA Python environment (see external/puma/README.md "Python environment"):
conda create -n puma python=3.13 mpich gcc_linux-64 gxx_linux-64 gfortran_linux-64 \
cmake make ninja hdf5 netcdf4 zlib libaec bison flex m4 pkg-config
conda activate puma
pip install torch nmhit scikit-build-core ninja
# Build ONLY the NEML2 Python package from the submodule (skip the MOOSE/puma-opt build):
cd external/puma
git submodule update --init neml2
pip install ./neml2 --no-deps # NEML2 v3 Python + `neml2-compile`
cd ../..
pip install -e . # graintrace + pyzag into the same env
--no-deps on NEML2 keeps the pyzag==2.0.0 that graintrace installs; the published NEML2 PyPI
wheel pins an older, incompatible pyzag, which is why NEML2 comes from source here.
Reconstruct → simulate needs the whole native stack: MOOSE + libtorch + puma-opt + NEML2. Build
it via PUMA, then install graintrace into that same env:
git clone https://github.com/applied-material-modeling/graintrace.git
cd graintrace
git submodule update --init external/puma
# Build the native stack: follow external/puma/README.md end to end (conda env, submodules,
# PETSc/libMesh/WASP, NEML2, `make -j`, and `neml2-compile` for the material models).
cd external/puma
# ... PUMA build steps ...
cd ../..
pip install -e . # or: pip install -e ".[dev]" to run the tests
graintrace depends on PUMA one-way: at runtime it needs the puma-opt binary at
external/puma/puma-opt; pass it as moose_run_file to CPFESimulation (see
examples/demonstrate_cpfe.py). NEML2 comes from PUMA's build so puma-opt's C++ library and the
Python neml2 stay in lockstep; pyzag is provided by graintrace's pip install.
The native stack is pinned via one submodule; PUMA carries MOOSE and NEML2 as its own submodules, so graintrace pins PUMA once and gets the whole stack:
| Submodule | Repo | Branch | Carries |
|---|---|---|---|
external/puma | github.com/applied-material-modeling/puma | development | moose/ + neml2/ (its own submodules) |
git submodule update --init external/puma # graintrace -> puma
cd external/puma && git submodule update --init # puma -> moose/ + neml2/
The init is intentionally not recursive: it stops at PUMA's moose/ and neml2/. MOOSE's own
submodules (PETSc, libMesh, WASP) are initialized by MOOSE's build scripts during the PUMA build,
not here. Each gitlink pins a specific commit, so updates are deliberate: to re-point, update
.gitmodules and the external/puma gitlink, then re-init.
Coreform CUBIT (National-Lab, commercial, or education license) provides CUBIT + SCULPT: https://coreform.com/. Obtain and install it under your own account.
Never commit CUBIT license material (
*.lic, license servers, keys) to this or any repo.sculpt_configin the examples takes only executable paths, no license tokens. Set them to your install, e.g.:sculpt_config = { "launcher": "/path/to/cubit/bin/mpi/bin/mpiexec", "psculpt": "/path/to/cubit/bin/psculpt", "epu": "/path/to/cubit/bin/epu", "nprocs": int(ncore), "environment": {"OPAL_LIBDIR": "/path/to/cubit/bin/mpi/lib", "OPAL_PREFIX": "/path/to/cubit/bin/mpi"}, }
gmsh is a pip package (declared in pyproject.toml), so it is installed automatically with
pip install graintrace (or pip install -e .). Nothing extra to do.
NEPER is an external tool graintrace drives (like CUBIT/SCULPT); it is not a pip package, so you install it yourself. Install NEPER once, then point graintrace at it:
NEPER environment variable set to the absolute path of the neper binary
(export NEPER=/abs/path/to/neper),graintrace_tools.json with a "neper" key (see graintrace/mcp/tools.example.json; the
search order is $GRAINTRACE_TOOLS_JSON → ./graintrace_tools.json → ~/.config/graintrace/tools.json),neper on your PATH,neper_path=/abs/path/to/neper (or a prepared env=) to VoronoiMeshBuilder /
CrystalGenerator.If NEPER cannot be found, the builders raise a clear error with these instructions. On Linux you can
also pass auto_install=True to build GSL + OpenBLAS + NEPER into ~/.local.
examples/demonstrate_*.py are runnable, self-contained tutorials (flat top-level ## INPUT
style), mostly backed by the small datasets under mwe_data/. Each maps to a /skill guide
(.claude/skills/…). The Needs column: pip only runs from pip install graintrace alone;
the rest need the external tool(s) shown (see the capabilities table).
| Example | What it shows | Needs |
|---|---|---|
demonstrate_hedm_study.py | synthetic crystal → overlapping HEDM z-scans → stitch → compare to truth | NEPER |
demonstrate_hedm_anisotropic.py | anisotropic (aspratio) microstructure generation benchmark | NEPER |
demonstrate_farfield.py | FF Voronoi reconstruction: orientations, initial elastic strain, .tess | NEPER |
demonstrate_grid_segmentation_mesh.py | EBSD/gridded-NF voxel graph-segmentation + SCULPT hex mesh | CUBIT/SCULPT |
demonstrate_synthetic_cpfe.py | meshing options — SCULPT flags and the no-CUBIT voxel-hex dump | NEPER, CUBIT/SCULPT |
demonstrate_material_calibration.py | pyzag-adjoint Taylor calibration of 6 crystal-plasticity params | NEML2 |
demonstrate_cpfe.py | FF CPFE via NEML2 AOTI + puma-opt (ships a 10-grain mesh) | NEML2, puma-opt |
demonstrate_cpfe_nfff.py | end-to-end: NF geometry + FF initial strain CPFE | full stack |
demonstrate_postprocess.py | field distributions / macroscopic stress–strain / IPF | pip only |
demonstrate_rei_pipeline.py | rare-event ID: graph cluster → hierarchical merge → rare VTK | pip only |
demonstrate_rei_example_2D.py, ..._3D.py | REI on 2D / 3D synthetic fields | pip only |
demonstrate_rei_comparison.py | compare two REI point clouds → overlap metrics + classified VTK | pip only |
demonstrate_graintracking.py | match grains across load steps via a grain graph | NEPER |
demonstrate_reorientation_fragmentation.py | IPF reorientation tracking → intragranular fragmentation (1×2 figure + annotated Exodus) → FF/NF/EBSD split detection → rare (most-fragmented) grains | NEML2 |
full stack = NEML2 + puma-opt + NEPER + CUBIT/SCULPT. The minimum end-to-end check is
demonstrate_cpfe_nfff.py; before running, edit the sculpt_config, moose_run_file, ncore,
and device at the top of the script to match your machine.
examples/run_experiment_*.py are real-experiment driver templates (FF-only, NF+FF, the AFRL
dataset, stitching comparison, crystal reconstruction) that read your own scan data — copy and
adapt one rather than running it as-is. .claude/CLAUDE.md §12 maps each workflow segment →
example → skill.
pip install -e ".[dev]"
pytest tests/
101 tests. On a plain checkout without the PUMA-built NEML2, the NEML2/pyzag-dependent tests
(orientation math, dependency checks) skip via pytest.importorskip rather than error, so the
pure-Python subset (data classes, similarity metrics, clustering, post-processing, stitching, REI
comparison) runs green. Run inside the PUMA-built env to exercise the full suite
(then 99 pass, 2 skip; the 2 skips are the CUBIT-binary checks, which skip unless you set
PSCULPT / CUBIT_MPIEXEC or CUBIT_BIN_DIR).
pytest tests/ -m "not slow" # fast pure-Python subset
pytest tests/test_dependencies.py -v # environment checks
MIT. See LICENSE. Copyright 2026, UChicago Argonne, LLC / Argonne National Laboratory.