upxo.pxtal.twinned_simple_3d.steps.steps_distribution_viewer module

Distribution Viewer – Part M of the Twinned FCC walkthrough.

An EBSD-vs-SGS “Comparison Properties” overlay (misorientation / twin thickness / host grain size / twin volume fraction) – the headline “did the finished synthetic structure end up matching EBSD” comparison. A second comparison mode, compare_role_properties() below, breaks morphology down by grain role (non-hosting matrix / host / twin) instead of pooling everything together. Two further functions, compute_texture_component_vf_comparison() and compute_pole_figure_delta_mud_iqr(), compare crystallographic TEXTURE (the population of absolute grain orientations) rather than morphology or neighbour-pair misorientation.

upxo.pxtal.twinned_simple_3d.steps.steps_distribution_viewer.compare_ebsd_vs_sgs(cleaner, tg, base, rg, parent_info, mdf, twin_thickness, n_per_axis=5, axes=('x', 'y', 'z'), properties=('misorientation', 'twin_thickness', 'host_grain_size', 'twin_volume_fraction'))[source]

Assembles the pooled EBSD-vs-SGS arrays for the requested comparison properties – ready to hand to upxo.viz.vizDistr.plot_grouped_distributions for a side-by-side overlay, or just inspect directly (e.g. np.mean(arr)).

Returns:

dict

Return type:

{prop_name: {‘ebsd’: ndarray, ‘sgs’: ndarray}}

upxo.pxtal.twinned_simple_3d.steps.steps_distribution_viewer.compare_role_properties(rg, parent_info, cleaner, voxel_size=1.0, selected_props=('area', 'aspect_ratio'), n_slices_per_axis=5, axes=('x', 'y', 'z'))[source]

Per-property morphology comparison between EBSD and the synthetic structure (SGS), broken down by grain role – not just pooled overall like compare_ebsd_vs_sgs() above.

EBSD’s grain-role taxonomy (pure_parents/pure_twins/intermediates/ non_role, from Grain-Role Properties in EBSD Analysis-2) and the SGS structure’s taxonomy (nonhost/host/primary/seca/secb, from twin generation) don’t correspond 1:1 – ‘intermediates’ (an EBSD twin that itself hosts a further twin) has no direct SGS equivalent, since the SGS primary/secondary split is about nucleation generation, not about whether a twin itself hosts one. Both sides are therefore pooled down to the same three coarse buckets this function CAN defend: ‘non_hosting’ (EBSD non_role / SGS nonhost), ‘host’ (EBSD pure_parents / SGS host), and ‘twin’ (EBSD pure_twins+intermediates pooled / SGS primary+seca+secb pooled – any generation, either side).

Returns:

  • dict ({prop_name: {‘non_hosting’: {‘ebsd’:ndarray,’sgs’:ndarray},)

  • ’host’ ({…}, ‘twin’: {…}}})

upxo.pxtal.twinned_simple_3d.steps.steps_distribution_viewer.role_property_match_summary(role_prop_data, tolerance_pct=25.0)[source]

Per-property EBSD-vs-SGS match summary for compare_role_properties()’s output. For each property, averages TwinnedSimple3DBase.compare_property_distributions()’s per-bucket ‘representativeness_score’ (a [0, 1] measure) and ‘ratio’ (trimmed SGS mean / trimmed EBSD mean) across the three role buckets, then applies the same ratio-tolerance acceptance rule mc_qualification.prop_qualifies() uses for temporal-slice qualification (Part G): a property “accepts” when its mean ratio falls within +/- tolerance_pct% of 1.0. The default (25%) is looser than Part G’s own property-tolerance defaults (typically 5%), since those compare EBSD-detection-derived candidate statistics at a much larger sample size, whereas this compares role-bucket populations drawn from 2D cross-sections of the finished, cleaned structure – inherently smaller samples with more run-to-run variability.

Returns:

  • dict ({prop_name: {‘score’: float or None, ‘ratio’: float or None,)

  • ’accepted’ (bool}} – ‘accepted’ is False whenever ‘ratio’ is None)

  • (no bucket had values on both sides after outlier trimming).

upxo.pxtal.twinned_simple_3d.steps.steps_distribution_viewer.compute_texture_component_vf_comparison(rg, cleaner, n_peaks=4, bandwidth_deg=10.0)[source]

Texture representativeness, measure 1: does the same set of texture components exist in similar amounts, EBSD vs. the synthetic structure? Runs detect_texture_component_peaks() independently on each population’s grain orientations, then compares the volume fractions of components that auto-matched to the SAME standard name on both sides (generic “Component N” peaks – ones that didn’t match any standard component closely enough – aren’t comparable across the two independent detection runs, so they’re excluded from the matched comparison, though still returned in full).

No pass/fail threshold is applied here (none is established anywhere in the pipeline for texture) – this reports the achieved numbers for you to judge, not a verdict.

Returns:

  • dict ({‘ebsd_components’, ‘sgs_components’ (full peak-detection)

  • results, each), ‘matched’ (list of {‘component’, ‘ebsd_vf_pct’,

  • ’sgs_vf_pct’, ‘abs_diff_pct’}), ‘total_abs_deviation_pct’ (float,

  • sum of |diff| across matched components – lower is more alike)}

upxo.pxtal.twinned_simple_3d.steps.steps_distribution_viewer.compute_pole_figure_delta_mud_iqr(rg, cleaner, pole_family='100', grid_points='auto', half_width_deg=7.5, unit_normalize=False, apply_sample_symmetry=True, use_rd=True, use_td=True, use_nd=True)[source]

Texture representativeness, measure 2: builds a {pole_family} pole figure for each population (EBSD vs. the synthetic structure) and computes the interquartile range of their MUD (Multiples of Uniform Density) grid difference – a single-number summary of how much the two pole figures disagree, independent of any texture- component naming/matching (measure 1 above). Lower IQR = more alike.

No pass/fail threshold is applied here either – reports the achieved number, not a verdict.

Returns:

  • dict ({‘Xi’, ‘Yi’, ‘zi_diff’ (grid arrays, for plotting the)

  • difference map yourself), ‘iqr’ (float)}

upxo.pxtal.twinned_simple_3d.steps.steps_distribution_viewer.plot_texture_residual(ebsd_stage, sgs_stage, pole_family='100', grid_points='auto', half_width_deg=7.5, unit_normalize=False, title_ebsd='EBSD', title_sgs='SGS', apply_sample_symmetry=True, use_rd=True, use_td=True, use_nd=True)[source]

The three-panel EBSD | SGS | Difference pole-figure plot – MUD density for each population side by side, then their difference, with its IQR shown in the difference panel’s own title.

ebsd_stage/sgs_stage: one matching entry each from steps_ebsd_analysis_2.ebsd_pole_figure_stages()/ steps_visualization_export.sgs_pole_figure_stages() (e.g. both ‘full’, or EBSD ‘parents’ paired with SGS ‘host’).

Return type:

(fig, (ax_ebsd, ax_sgs, ax_diff), iqr)