Skip to content

v0.2.0

Latest

Choose a tag to compare

@hdt5kt hdt5kt released this 26 Oct 16:58
· 2 commits to main since this release
b34caea

graintrace 0.2.0

This release makes the NF/FF/EBSD experiment path work end to end inside graintrace: state the frame transform between datasets, reconstruct NF with a confidence mask and graph segmentation, mesh it with SCULPT, and match grains across datasets and load steps. It contains API and default changes, so read Breaking and behaviour changes before upgrading.

Highlights

  • FrameTransform (new, graintrace.frame_transform, #61): a stated sample-frame change x' = Q(s⊙x) + t, g' = g Qᵀ, ε' = Q ε Qᵀ that moves positions, orientations and strain tensors consistently. Tilt is part of Q; s is a per-axis sign only (no scale). It has adapters for FF grain CSVs, point clouds, voxel grids and the headerless reconstruction_cpfe_ee.csv, plus inside_voxel_solid for building overlap masks. Inverse, composition and JSON records are exact. Orientation math goes through neml2.
  • NF confidence mask (#62): min_confidence, max_point_distance and voxel_size_um in NearFieldMeshBuilder.reconstruct, NFGridConversion and the NF point-cloud gridding, so air and low-confidence points become void instead of being nearest-neighbour filled. The per-voxel confidence is written beside the grid.
  • Graph (Leiden) segmentation in NearFieldMeshBuilder (#62): segmentation={"method": "graph", ...} with an optional in-plane downsample. The .mic reader also accepts MIDAS per-layer subfolders.
  • Size-aware split detection (#63): FragmentationAnalyzer.detect_splits gains d_tol_mode="radius"/"radius_sum", assignment="one_to_one" (Hungarian), per-side recall with in_overlap_a/b masks, and a chance-link null (n_null).
  • Segmentation without a grain-size cap (#64): FragmentationAnalyzer.segment no longer caps grain size by default. Small fragments are absorbed only into a neighbour of similar orientation (absorb_max_miso_deg). The adjacency re-merge is agglomerative and checks the merged cluster's spread. cluster_leak_check detects orientation leaks. seg_to_grain_table(trim_miso_deg=...) gives a trimmed grain mean.
  • .ang converter (new, graintrace.ang_conversion.AngConverter, #56): converts EDAX/TSL .ang layers to .mic for NearFieldMeshBuilder, or to the merged x, y, z, Eul0..2 CSV for VoxelMeshBuilder. Layers are ordered by the parsed layer index.

Breaking and behaviour changes

  • graintrace.nf.convert.pointcloud_to_fixed_grid now returns (grid, confidence) instead of grid.
  • Passing nx/ny together with voxel_size_um raises ValueError.
  • SCULPT --void_mat is now set by graintrace. SCULPT numbers spn values from 1, so the void (spn 0) is material 1. The previously documented --void_mat 0 meshed the void as a block. mesh_sculpt now passes --void_mat 1 when the grid has void and replaces a user value with a warning. Remove --void_mat from your sculpt_options.
  • SCULPT meshes are mapped from SCULPT's voxel-index coordinates exactly. Earlier meshes were shrunk by one voxel per axis, and masked (void-bordered) grids were stretched over the full scan box.
  • SCULPT block ids are renumbered to a contiguous 1..N. <mesh>_block_map.csv records each block's original SCULPT id and grain. Orientation row k belongs to block k+1.
  • A phase column is no longer treated as a void marker implicitly. Opt in with void_marker_col.
  • Isolated solid islands left unsegmented after cleanup become void instead of aborting write_spn.
  • FragmentationAnalyzer.segment defaults: no grain-size cap, orientation-gated absorption, and a spread-checked re-merge. Segmentations may keep more small, distinct grains than before. percolation_max_frac=0.03 restores the previous behaviour exactly.
  • grain_fragments uses gamma=0.25 when seg_kwargs gives none.
  • orientation_helper.matrix_to_euler wraps φ1/φ2 to [0, 360) (or [0, 2π)) and resolves gimbal lock deterministically. The rotations are unchanged, but stored Euler values can differ numerically.
  • VoronoiMeshBuilder(rotate_angles=...) now rotates orientations on the sample side (g Qᵀ). The old crystal-side update was a no-op for cubic crystals. orientation_active_convention is deprecated and ignored.
  • FrameTransform rejects non-unit quaternions. detect_splits raises on negative or NaN tolerances, and treats NaN or negative radii as 0 with a warning.
  • AngConverter defaults to TSL Bunge radians and raises when angles labelled as radians exceed 4π.

Fixes

  • VoronoiMeshBuilder auto_rotate no longer raises on about 8% of inputs; the axis signs are aligned before handedness is restored.
  • FrameTransform.mrp returns the short MRP set; it no longer blows up to NaN near 180° rotations.
  • The chain-merge in adjacency_remerge without a cap is fixed (#64). Labels below 0 and the background label are left untouched consistently across segmentation helpers.
  • Grain-orientation averaging folds crystal-symmetry variants first (#20).
  • An unsegmented voxel no longer corrupts the SCULPT mesh. Discarded flood segments stay rejected (#33). Mesh blocks are matched to their own grain's voxels (#38).
  • The flood out-of-domain mask is applied in place. Experiment rotation refuses a row-count mismatch. IPF block colouring defaults to Bunge degrees (#55).
  • detect_splits keeps a parent's best candidate when no two children are adjacent (#37).
  • Graph-affecting and weighting parameters are validated when resuming a segmentation checkpoint (#18, #22). The mutual-kNN neighbour count is clamped to N−1 (#16). DBSCAN summaries are labelled with their columns (#17). Top-k prune ties are resolved consistently, with a faster half-edge grouping (#39, #41).
  • validate_topology refuses a broken tessellation at any verbosity (#42). GrainMatcher output files follow output_prefix (#40). Examples write to their own output folders (#36). Lazy-import errors name the install tier needed (#34).

Documentation

  • New API page for FrameTransform, a .ang section in File formats, and updated configuration, pitfalls and tutorials (NF reconstruction, NF+FF, reorientation/fragmentation, voxel segmentation).
  • The docs build now lists pandoc as a prerequisite (#35). The maths and tutorial pages are expanded (#54).

Upgrade notes

  1. Drop --void_mat from sculpt_options, and re-mesh any masked NF grid: earlier meshes included the air as a block and were stretched.
  2. Unpack grid, confidence = pointcloud_to_fixed_grid(...).
  3. For NF data, use min_confidence (about 0.5–0.6) with graph segmentation instead of relying on a grain-size cap.
  4. To move FF data into the NF frame, state the transform with FrameTransform instead of rotate_angles with orientation_active_convention.