upxo.pxtal.twinned_simple_3d.repr_validator_3d module

repr_validator_3d.py

Multi-axis 2D slice representativeness validation for the twinned simple 3D pipeline.

class upxo.pxtal.twinned_simple_3d.repr_validator_3d.RepresentativenessValidator3D(n_slices_x: int = 10, n_slices_y: int = 10, n_slices_z: int = 10, test_along_x: bool = True, test_along_y: bool = True, test_along_z: bool = True, p_percentage: float = 60.0, p_percentage_x: float | None = None, p_percentage_y: float | None = None, p_percentage_z: float | None = None, wasserstein_threshold: float = 0.5)[source]

Bases: object

Multi-axis 2D slice representativeness validator.

Two modes: - morphological (pre-twin): Wasserstein distance on normalised

grain-size distributions.

  • crystallographic (post-twin): Wasserstein distance on misorientation angle distributions.

A 3D structure is accepted when at least p_percentage percent of slices pass on every tested axis.

n_slices_x
n_slices_y
n_slices_z
test_along_x
test_along_y
test_along_z
p_percentage
p_percentage_x
p_percentage_y
p_percentage_z
wasserstein_threshold
slice_results: Dict
axis_acceptance: Dict
overall_accepted: bool | None
validate_morphological(lgi_3d: numpy.ndarray, ebsd_areas: numpy.ndarray)[source]

Pre-twin morphological validation against EBSD grain-size distribution.

Calls section_from_3d and get_grain_size_distribution_from_slice per slice.

validate_crystallographic(lgi_3d: numpy.ndarray, quat_3d: numpy.ndarray, ebsd_miso_deg: numpy.ndarray)[source]

Post-twin crystallographic validation against EBSD MDF.

Calls extract_2d_slice_pair, find_neighs2d, and compute_mdf_from_quats per slice.

aggregate()[source]

Aggregate slice results into per-axis acceptance.

report() → str[source]

Return a formatted text summary of the validation results.

upxo.pxtal.twinned_simple_3d.repr_validator_3d.compute_representative_slice_mdfs(validator, cleaner, quat_3d_clean, axes=None)[source]

Per-axis misorientation distribution (MDF) for every PASSING slice already identified by validator.validate_crystallographic, plus their mean – the representative-slice MDF a passing 2D section should reproduce, for comparison against the full EBSD MDF.

Parameters:
  • validator (RepresentativenessValidator3D) – Already run via validate_crystallographic – slice_results supplies the passing/failing slice positions per axis.

  • cleaner – Post-cleaning structure (lgi_clean – duck-typed, matching StructureCleaner3D and its subset variants).

  • quat_3d_clean (ndarray, shape lgi_clean.shape + (4,)) – Per-voxel quaternion field (see crystal_orientation.expand_grain_quats_to_voxels).

  • axes (iterable of str, optional) – Which axes (‘X’/’Y’/’Z’) to compute for. Defaults to every axis with at least one slice result recorded.

Returns:

dict {axis_name – ‘mean_bin_centers’: ndarray or None,

’mean_density’: ndarray or None}}

Each slice_mdfs entry is one passing slice’s compute_mdf_from_quats result (skipped if the slice has no grains or its MDF computation fails). mean_bin_centers/ mean_density are None when no slice yielded a usable MDF.

Return type:

{‘n_passing’: int, ‘slice_mdfs’: list of dict,