midas-process-grains 0.1.0__py3-none-any.whl
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.
- midas_process_grains/__init__.py +41 -0
- midas_process_grains/__main__.py +9 -0
- midas_process_grains/cli.py +145 -0
- midas_process_grains/compute/__init__.py +35 -0
- midas_process_grains/compute/c_parity.py +498 -0
- midas_process_grains/compute/c_parity_emit.py +653 -0
- midas_process_grains/compute/c_parity_run.py +286 -0
- midas_process_grains/compute/canonicalize.py +131 -0
- midas_process_grains/compute/cluster.py +515 -0
- midas_process_grains/compute/conflict.py +245 -0
- midas_process_grains/compute/geometry.py +116 -0
- midas_process_grains/compute/pass_a.py +218 -0
- midas_process_grains/compute/refine_cluster.py +347 -0
- midas_process_grains/compute/strain.py +608 -0
- midas_process_grains/compute/stress.py +86 -0
- midas_process_grains/compute/symmetry.py +189 -0
- midas_process_grains/compute/twins.py +180 -0
- midas_process_grains/device.py +60 -0
- midas_process_grains/io/__init__.py +42 -0
- midas_process_grains/io/binary.py +317 -0
- midas_process_grains/io/consolidated.py +142 -0
- midas_process_grains/io/csv.py +179 -0
- midas_process_grains/io/hkls.py +61 -0
- midas_process_grains/io/ids_hash.py +111 -0
- midas_process_grains/modes.py +77 -0
- midas_process_grains/params.py +214 -0
- midas_process_grains/pipeline.py +836 -0
- midas_process_grains/result.py +157 -0
- midas_process_grains-0.1.0.dist-info/METADATA +176 -0
- midas_process_grains-0.1.0.dist-info/RECORD +33 -0
- midas_process_grains-0.1.0.dist-info/WHEEL +5 -0
- midas_process_grains-0.1.0.dist-info/entry_points.txt +2 -0
- midas_process_grains-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""midas-process-grains: pure-Python FF-HEDM grain-determination + strain.
|
|
2
|
+
|
|
3
|
+
Drop-in replacement for ``FF_HEDM/src/ProcessGrains.c``. Reads the binary
|
|
4
|
+
outputs of the upstream pipeline (``IndexBest{,Full}.bin``, ``FitBest.bin``,
|
|
5
|
+
``Key.bin``, ``OrientPosFit.bin``, ``ProcessKey.bin``) and emits the canonical
|
|
6
|
+
MIDAS grain artefacts (``Grains.csv``, ``SpotMatrix.csv``, ``GrainIDsKey.csv``).
|
|
7
|
+
|
|
8
|
+
Three operating modes (`mode=` kwarg):
|
|
9
|
+
|
|
10
|
+
* ``"legacy"`` — bit-for-bit reproduce the current C ProcessGrains
|
|
11
|
+
output (used for regression tests during migration).
|
|
12
|
+
* ``"paper_claim"`` — the §3.6 spec from the MIDAS methodology paper that
|
|
13
|
+
the current C code does not actually enforce
|
|
14
|
+
(90% shared peaks, 0.01° misorientation, 15 µm pos).
|
|
15
|
+
* ``"spot_aware"`` — DEFAULT. Symmetry-aware row-aligned per-hkl SpotID
|
|
16
|
+
consistency, Jaccard pre-screen, union-of-cluster
|
|
17
|
+
emission, lstsq strain. No position gate.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
__version__ = "0.1.0"
|
|
23
|
+
|
|
24
|
+
from .params import ProcessGrainsParams, read_paramstest_pg
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"__version__",
|
|
28
|
+
"ProcessGrainsParams",
|
|
29
|
+
"read_paramstest_pg",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def __getattr__(name):
|
|
34
|
+
"""Lazy import of pipeline-level symbols (avoid module cycles during build-up)."""
|
|
35
|
+
if name == "ProcessGrains":
|
|
36
|
+
from .pipeline import ProcessGrains
|
|
37
|
+
return ProcessGrains
|
|
38
|
+
if name == "ProcessGrainsResult":
|
|
39
|
+
from .result import ProcessGrainsResult
|
|
40
|
+
return ProcessGrainsResult
|
|
41
|
+
raise AttributeError(f"module 'midas_process_grains' has no attribute {name!r}")
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""CLI: ``midas-process-grains`` (and ``python -m midas_process_grains``).
|
|
2
|
+
|
|
3
|
+
Mirrors the C ``ProcessGrains`` invocation pattern (single positional arg:
|
|
4
|
+
the parameter file path) with optional flags to override mode, device,
|
|
5
|
+
dtype, and a couple of merge knobs.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import List, Optional
|
|
14
|
+
|
|
15
|
+
from . import __version__
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
19
|
+
p = argparse.ArgumentParser(
|
|
20
|
+
prog="midas-process-grains",
|
|
21
|
+
description=(
|
|
22
|
+
"Pure-Python FF-HEDM grain-determination + strain pipeline "
|
|
23
|
+
"(drop-in for ProcessGrains)."
|
|
24
|
+
),
|
|
25
|
+
)
|
|
26
|
+
p.add_argument(
|
|
27
|
+
"param_file",
|
|
28
|
+
type=Path,
|
|
29
|
+
help="Path to paramstest.txt (the same file IndexerOMP/FitPosOrStrains "
|
|
30
|
+
"consumed for this run).",
|
|
31
|
+
)
|
|
32
|
+
p.add_argument(
|
|
33
|
+
"num_procs", type=int, nargs="?", default=1,
|
|
34
|
+
help="CPU thread count (used only on cpu device). Default 1.",
|
|
35
|
+
)
|
|
36
|
+
p.add_argument(
|
|
37
|
+
"--mode", choices=("legacy", "paper_claim", "spot_aware", "c_parity"),
|
|
38
|
+
default="spot_aware",
|
|
39
|
+
help="Pipeline mode. Use 'c_parity' for a bit-level replica of the "
|
|
40
|
+
"C ProcessGrains pipeline (writes Grains.csv, GrainIDsKey.csv, "
|
|
41
|
+
"SpotMatrix.csv in C's exact format).",
|
|
42
|
+
)
|
|
43
|
+
p.add_argument(
|
|
44
|
+
"--min-nr-spots", type=int, default=None,
|
|
45
|
+
help="MinNrSpots threshold (Stage 1 cluster-size cutoff). C ProcessGrains "
|
|
46
|
+
"default is 1; the original peakfit_hard run used 3.",
|
|
47
|
+
)
|
|
48
|
+
p.add_argument("--device", choices=("cpu", "cuda", "mps"), default=None)
|
|
49
|
+
p.add_argument("--dtype", choices=("float32", "float64"), default=None)
|
|
50
|
+
p.add_argument("--misori-tol", type=float, default=None,
|
|
51
|
+
help="Override the Phase 1 misorientation tolerance (degrees).")
|
|
52
|
+
p.add_argument(
|
|
53
|
+
"--strain-method",
|
|
54
|
+
choices=(
|
|
55
|
+
"kenesei", "kenesei_unbounded", "fable_beaudoin", "both",
|
|
56
|
+
# backwards-compat aliases (resolved in params.validated())
|
|
57
|
+
"lstsq", "lattice",
|
|
58
|
+
),
|
|
59
|
+
default=None,
|
|
60
|
+
help="Per-grain strain solver. Default: kenesei (bounded ±0.01, "
|
|
61
|
+
"matches C reference). Use fable_beaudoin for the lattice-"
|
|
62
|
+
"parameter route, or both to emit each.",
|
|
63
|
+
)
|
|
64
|
+
p.add_argument("--material", default=None,
|
|
65
|
+
help="Material name for stiffness lookup (e.g. Cu, Ni, Fe).")
|
|
66
|
+
p.add_argument("--stiffness-file", type=Path, default=None,
|
|
67
|
+
help="Path to a 6×6 stiffness matrix (CSV/TXT/NPY).")
|
|
68
|
+
p.add_argument("--out-dir", type=Path, default=None,
|
|
69
|
+
help="Where to write outputs. Default: param-file directory.")
|
|
70
|
+
p.add_argument("--no-h5", action="store_true",
|
|
71
|
+
help="Skip writing data_consolidated.h5.")
|
|
72
|
+
p.add_argument("--no-diagnostics-h5", action="store_true",
|
|
73
|
+
help="Skip writing processgrains_diagnostics.h5.")
|
|
74
|
+
p.add_argument("--max-seeds", type=int, default=None,
|
|
75
|
+
help="Process only the first N alive seeds (smoke / dev).")
|
|
76
|
+
p.add_argument("--version", action="version",
|
|
77
|
+
version=f"midas-process-grains {__version__}")
|
|
78
|
+
return p
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def main(argv: Optional[List[str]] = None) -> int:
|
|
82
|
+
"""CLI entry point. Returns process exit code."""
|
|
83
|
+
args = _build_parser().parse_args(argv)
|
|
84
|
+
|
|
85
|
+
from .device import apply_cpu_threads, resolve_device, resolve_dtype
|
|
86
|
+
from .pipeline import ProcessGrains
|
|
87
|
+
|
|
88
|
+
# ── c_parity mode: dispatch to the C-replica pipeline and return ────────
|
|
89
|
+
if args.mode == "c_parity":
|
|
90
|
+
from .compute.c_parity_run import run_c_parity_pipeline_from_disk
|
|
91
|
+
run_dir = args.param_file.parent
|
|
92
|
+
out_dir = args.out_dir if args.out_dir is not None else run_dir
|
|
93
|
+
device = resolve_device(args.device)
|
|
94
|
+
# torch device strings: "cpu" / "cuda" / "cuda:0" / "mps"
|
|
95
|
+
device_str = str(device) if not hasattr(device, "type") else (
|
|
96
|
+
device.type if device.index is None else f"{device.type}:{device.index}"
|
|
97
|
+
)
|
|
98
|
+
apply_cpu_threads(args.num_procs, device)
|
|
99
|
+
run_c_parity_pipeline_from_disk(
|
|
100
|
+
run_dir=run_dir,
|
|
101
|
+
out_dir=out_dir,
|
|
102
|
+
min_nr_spots=(args.min_nr_spots
|
|
103
|
+
if args.min_nr_spots is not None else 1),
|
|
104
|
+
device=device_str,
|
|
105
|
+
)
|
|
106
|
+
return 0
|
|
107
|
+
|
|
108
|
+
pg = ProcessGrains.from_param_file(
|
|
109
|
+
args.param_file,
|
|
110
|
+
device=args.device,
|
|
111
|
+
dtype=args.dtype,
|
|
112
|
+
)
|
|
113
|
+
apply_cpu_threads(args.num_procs, pg.device)
|
|
114
|
+
|
|
115
|
+
# CLI overrides on top of paramstest.
|
|
116
|
+
if args.misori_tol is not None:
|
|
117
|
+
pg.params.MisoriTol = float(args.misori_tol)
|
|
118
|
+
if args.strain_method is not None:
|
|
119
|
+
pg.params.StrainMethod = args.strain_method
|
|
120
|
+
if args.material is not None:
|
|
121
|
+
pg.params.MaterialName = args.material
|
|
122
|
+
if args.stiffness_file is not None:
|
|
123
|
+
pg.params.StiffnessFile = str(args.stiffness_file)
|
|
124
|
+
pg.params = pg.params.validated()
|
|
125
|
+
|
|
126
|
+
if args.max_seeds is not None:
|
|
127
|
+
pg.params.raw["__max_seeds__"] = [str(args.max_seeds)]
|
|
128
|
+
|
|
129
|
+
result = pg.run(mode=args.mode)
|
|
130
|
+
out_dir = args.out_dir if args.out_dir is not None else pg.run_dir
|
|
131
|
+
result.write(
|
|
132
|
+
out_dir,
|
|
133
|
+
h5=not args.no_h5,
|
|
134
|
+
diagnostics_h5=not args.no_diagnostics_h5,
|
|
135
|
+
)
|
|
136
|
+
print(
|
|
137
|
+
f"midas-process-grains {__version__}: "
|
|
138
|
+
f"{result.n_grains} grains written to {out_dir}",
|
|
139
|
+
file=sys.stderr,
|
|
140
|
+
)
|
|
141
|
+
return 0
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
sys.exit(main())
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Compute submodule.
|
|
2
|
+
|
|
3
|
+
Pure-tensor implementations of:
|
|
4
|
+
- symmetry table builders (24-op cubic / hexagonal / etc.)
|
|
5
|
+
- hkl-row permutation under each symmetry op
|
|
6
|
+
- cluster-level orientation canonicalisation
|
|
7
|
+
- misorientation graph + connected components (Phase 1)
|
|
8
|
+
- spot-aware sub-clustering (Phase 2)
|
|
9
|
+
- per-hkl SpotID conflict resolution (Phase 3)
|
|
10
|
+
- lstsq strain solver (Phase 4)
|
|
11
|
+
- Hooke's-law stress (Phase 5)
|
|
12
|
+
- twin post-processor
|
|
13
|
+
|
|
14
|
+
Design rule: every public function takes a ``device`` / ``dtype`` argument or
|
|
15
|
+
honours the caller's tensors' device + dtype, mirroring the conventions of
|
|
16
|
+
``midas_index`` and ``midas_transforms``.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from .symmetry import (
|
|
20
|
+
SymmetryTable,
|
|
21
|
+
build_symmetry_table,
|
|
22
|
+
apply_sym_to_hkl_int,
|
|
23
|
+
)
|
|
24
|
+
from .canonicalize import (
|
|
25
|
+
pick_best_sym_op,
|
|
26
|
+
align_member_to_rep,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"SymmetryTable",
|
|
31
|
+
"build_symmetry_table",
|
|
32
|
+
"apply_sym_to_hkl_int",
|
|
33
|
+
"pick_best_sym_op",
|
|
34
|
+
"align_member_to_rep",
|
|
35
|
+
]
|