midas-plotting 0.3.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.
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: midas-plotting
3
+ Version: 0.3.0
4
+ Summary: Standard plots for MIDAS reconstructions - near-field, far-field and Laue: IPF maps and legends, grain maps, pole figures, strain and size distributions, and Laue texture diagnostics against their chance levels.
5
+ Author-email: Hemant Sharma <hsharma@anl.gov>
6
+ License: BSD-3-Clause
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Science/Research
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Topic :: Scientific/Engineering :: Physics
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: numpy>=1.22
15
+ Requires-Dist: matplotlib>=3.5
16
+ Requires-Dist: midas-stress>=0.1
17
+ Provides-Extra: dev
18
+ Requires-Dist: pytest>=7; extra == "dev"
19
+ Requires-Dist: scipy>=1.9; extra == "dev"
20
+
21
+ # midas-plotting
22
+
23
+ Standard plots for MIDAS reconstructions.
24
+
25
+ ```python
26
+ from midas_plotting import read_mic, orientation_map, compare_maps
27
+
28
+ m = read_mic("Ce5Y_mr.2.mic")
29
+ print(m.summary())
30
+ orientation_map(m, space_group=225, cmin=0.3)
31
+ ```
32
+
33
+ ```bash
34
+ midas-plot Ce5Y.0.mic Ce5Y_sum3thr2.0.mic --kind orientation --cmin 0.3 \
35
+ --titles "baseline|sum3+thr2" -o compare.png
36
+ ```
37
+
38
+ ## Why
39
+
40
+ IPF colouring, `.mic` parsing and map plotting had been re-implemented in
41
+ several one-off analysis scripts, each with its own conventions. Two things that
42
+ kept going wrong and are now handled in one place:
43
+
44
+ - **Euler→RGB is not an orientation map.** Two orientations a fraction of a
45
+ degree apart can produce very different Euler triplets near gimbal lock, so a
46
+ single grain renders as several colours. `ipf_rgb` colours by the crystal
47
+ direction along a sample axis instead.
48
+ - **A permissive confidence cut fills the whole grid.** The fit returns *an*
49
+ orientation for every voxel it evaluates, so plotting at C ≥ 0.1 shows
50
+ plausible microstructure whether or not material is there. `orientation_map`
51
+ annotates the figure when asked to plot below `TRUST_FLOOR` (0.3).
52
+
53
+ Symmetry operators come from `midas_stress`; nothing is hand-listed here.
54
+
55
+ Implemented Laue families: cubic (SG 195–230) and hexagonal (168–194).
56
+ Anything else raises rather than silently falling back to cubic.
57
+
58
+ ## Far-field (`Grains.csv`)
59
+
60
+ ```python
61
+ from midas_plotting import ff, read_grains
62
+
63
+ g = read_grains("Grains.csv")
64
+ print(len(g), g.space_group) # symmetry is read from the file's header
65
+
66
+ ff.summary(g) # one-page overview
67
+ ff.grain_map(g, color="ipf") # IPF-coloured grain centres
68
+ ff.ipf_legend(g.space_group) # the colour key
69
+ ff.pole_figure(g, hkl=(1, 1, 1))
70
+ ff.strain_map(g, kind="vonmises")
71
+ ```
72
+
73
+ ```bash
74
+ midas-plot Grains.csv --kind summary -o overview.png
75
+ midas-plot Grains.csv --kind pole --hkl 1,1,1
76
+ midas-plot Grains.csv --kind strain --strain-kind hydrostatic
77
+ ```
78
+
79
+ FF output is a **grain list**, not a voxel grid, so these are scatter and
80
+ distribution plots. They are namespaced under `ff` rather than exported flat
81
+ because both modalities have a `grain_map` and they mean different things:
82
+ `maps.grain_map` labels a near-field voxel grid, `ff.grain_map` scatters
83
+ far-field grain centres.
84
+
85
+ Things the module will not let you get wrong:
86
+
87
+ * **Symmetry comes from the file.** `Grains.csv` states its space group in the
88
+ preamble; the plots use it. Defaulting to cubic would colour a hexagonal
89
+ sample with the wrong IPF triangle and produce a plausible, wrong figure.
90
+ * **Columns are read by name.** `Grains.csv` has 47 columns and
91
+ `midas-fit-grain` 0.5.6 shipped a cyclic rotation of three of them; a
92
+ positional reader inherits that silently.
93
+ * **Euler angles are cross-checked against `O11..O33`.** They describe the same
94
+ orientation, so disagreement means the row is being sliced wrong — you get a
95
+ warning instead of a wrong colour.
96
+ * **Strain is already microstrain.** The `eFab`/`eKen` columns are not
97
+ dimensionless; they are not rescaled.
98
+
99
+ Two caveats the plots cannot fix: FF grain positions are good to ~100 µm (not
100
+ the six decimals the file prints), and `GrainRadius` is only correct with
101
+ `midas-process-grains >= 0.6.1`.
102
+
103
+ ## Laue (`solutions.txt`, `spots.txt`)
104
+
105
+ ```python
106
+ from midas_plotting import laue, read_solutions, read_spots
107
+
108
+ sol = read_solutions("solutions.txt") # one row per orientation PER FRAME
109
+ print(sol.summary()) # ... 4,746 distinct orientations ...
110
+ sol = sol.gate(11) # the measured null for THAT scan
111
+
112
+ c = laue.cluster(sol, 1.0, space_group=194)
113
+ print(c) # <GrainClusters 631 grains at 1.0deg (of 636 clusters,
114
+ # 5 spanning >half the map), n_eff 309.5>
115
+
116
+ reps = c.representatives(sol.orient_mat) # one orientation per grain
117
+ laue.tilt_histogram(reps) # against the random reference
118
+ laue.texture_strength(reps) # (peak, chance, peak/chance)
119
+ laue.summary(sol)
120
+ ```
121
+
122
+ ```bash
123
+ midas-plot solutions.txt --kind tilt --gate 11 --sg 194
124
+ midas-plot validated.npz --kind summary --sg 194 --tol 1.0
125
+ ```
126
+
127
+ Laue output is neither a voxel grid nor a grain list: it is one row per
128
+ *orientation per frame*, so a crystal seen at twenty positions appears twenty
129
+ times. Nothing is a grain until it has been clustered, and every grain count
130
+ here carries the tolerance that produced it.
131
+
132
+ Four things the module will not let you get wrong:
133
+
134
+ * **Half of a random population lies more than 60° from any fixed direction.**
135
+ That is solid angle, not texture. `tilt_histogram` draws
136
+ `random_tilt_fractions()` beside the data by default, because "70% of grains
137
+ lie near the surface plane" reads as a strong texture and is very nearly
138
+ random — and 30% there is a *depletion*.
139
+ * **A raw pole density is not comparable between datasets.** A small grain
140
+ population peaks higher by chance alone, and its chance level rises to match.
141
+ `texture_strength` returns the ratio to its own measured null, which is what
142
+ makes 85 grains and 631 grains commensurable.
143
+ * **An orientation present at every raster position is not a grain.** The beam
144
+ moves a micron or two between frames. `cluster` flags anything spanning more
145
+ than half the map; on one dataset a single such object held 59% of all
146
+ measurements and dragged the effective sample size from 29 to 2.5. The Kish
147
+ effective n sits next to every grain count for the same reason.
148
+ * **`orientationRowNr` is column 34 and `misOrientationPostRefinement` is 33.**
149
+ Reading 33 for 34 does not raise — it returns a near-zero float for every
150
+ row, so distinct-orientation counts collapse to single digits and the scan
151
+ looks like it found one crystal. Columns are read by name.
152
+
153
+ Geometry is explicit, never assumed: `SURFACE_NORMAL_34IDE` and the `COS45`
154
+ stage correction are module constants with 34-ID-E defaults, and every function
155
+ takes `normal=`. The out-of-plane stage axis sits at 45°, so quoting its raw
156
+ extent as a map size understates it by 1.41× — a 200 × 100 µm map reads as
157
+ 200 × 71.
158
+
159
+ The acceptance gate has **no default**. It is the largest number of reflections
160
+ a randomly oriented crystal achieves on those frames, it is a property of the
161
+ scan, and `midas-plot` says so when you omit `--gate` rather than picking one.
@@ -0,0 +1,14 @@
1
+ midas_plotting/__init__.py,sha256=yZ6BNYFA3_urRXjfctjAw3olBEuHZexOsAJWEmpw-JE,2382
2
+ midas_plotting/cli.py,sha256=esR1UeVCnujPtBKjKhFLP0W97pVPtDNljntc1vQfkx0,10910
3
+ midas_plotting/ff.py,sha256=J7Tt81Tl0BOzPhpN98zKV2-67IbER0W9eeJlM0d9868,22784
4
+ midas_plotting/grains.py,sha256=5JWwRMZRYrKwJ7RdXKJakHvEvqZUiB8HaR-hq7Afs38,11323
5
+ midas_plotting/ipf.py,sha256=wXf8YK0S-XAo56V-f9jr5uM8AGnE1gjydsX1JFf2IBM,6499
6
+ midas_plotting/laue.py,sha256=G9XEOFFNE1B9N9wtxvQbb7vMsfBirbYTpwcvhlsKbbY,28909
7
+ midas_plotting/maps.py,sha256=5RADpFeUDUFG2rCzFEWPeY7PaoVfKQr4wQDyOinQNCI,6959
8
+ midas_plotting/mic.py,sha256=q8FyV2vo5J82D4-gY8XXTjGdWwaxAKrIuips9CdVniI,2671
9
+ midas_plotting/solutions.py,sha256=ocOxCkV1Fdx5gENlUw7-IcyDtOh0hznTZQFfnz1OPNs,16461
10
+ midas_plotting-0.3.0.dist-info/METADATA,sha256=En0iY6A471whTYEupJnkT9SaFBUCPw_tqV-YoRXW26E,7197
11
+ midas_plotting-0.3.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
12
+ midas_plotting-0.3.0.dist-info/entry_points.txt,sha256=FxczuNMWzMDFr3yzjz02ImtbA1uesGqlHpSgXK0YWDg,55
13
+ midas_plotting-0.3.0.dist-info/top_level.txt,sha256=rBNH3JyOV22g1nWH-MsQnzy4Suc0mREmWjWSiCW69XE,15
14
+ midas_plotting-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ midas-plot = midas_plotting.cli:main
@@ -0,0 +1 @@
1
+ midas_plotting