upxo.pxtal.twinned_simple_3d.viz_3d module
viz_3d.py
Visualization utilities for the twinned simple 3D pipeline.
- upxo.pxtal.twinned_simple_3d.viz_3d.plot_ipf_slice(lgi_3d: numpy.ndarray, all_quats: Dict[int, numpy.ndarray], axis: int = 2, slice_idx: int | None = None, sample_direction: Tuple[float, float, float] = (0.0, 0.0, 1.0), figsize: Tuple[float, float] = (7.0, 7.0), dpi: int = 150, title: str | None = None)[source]
Plot an IPF-coloured 2D slice through a 3D grain structure.
- upxo.pxtal.twinned_simple_3d.viz_3d.plot_ipf_triangle_key(ax=None, n: int = 200, corner_labels: Tuple[str, str, str] = ('[001]', '[011]', '[111]'), figsize: Tuple[float, float] = (4.0, 4.0))[source]
Plot the IPF colour-key triangle matching
plot_ipf_slice()’s colour formula.
- upxo.pxtal.twinned_simple_3d.viz_3d.render_lgi_3d(lgi: numpy.ndarray, voxel_size=1.0, title: str | None = None, cmap: str = 'tab20', rng_seed: int = 0, show_edges: bool = False)[source]
Render a 3D grain-label field in a separate PyVista window, each grain shown in a distinct colour via a qualitative colormap.
Shared by
TwinnedSimple3DBase.plot_temporal_slice_3d(which buildslgifrom a raw MC state array and must transpose it first – see that method) and the GUI’s “View Grain Structure” button, which passesTwinnedSimple3DBase.lgidirectly.- Parameters:
lgi (ndarray (nx, ny, nz), int) – Grain label field, already in PyVista’s (nx, ny, nz) axis convention – the same convention
render_3d()expects forlgi_twinned. NOT the rawpxt.gs[...].s(nz, ny, nx) order.voxel_size (float or (float, float, float)) – Physical voxel edge length(s). Isotropic spacing if a bare float.
title (str or None) – Window title text; defaults to a grain-count summary.
cmap (str) – Qualitative PyVista/matplotlib colormap name.
rng_seed (int) – Seed for the ID -> colour-position shuffle. cc3d/regionprops-style labelling assigns numerically close IDs to spatially close grains; without shuffling, tab20’s discrete cycle repeats faster than IDs vary, so neighbouring grains land on near-identical colours and visually merge. Scattering IDs across the colour range keeps real grain boundaries distinct.
show_edges (bool) – Draw voxel-cell edges as a wireframe overlay on the mesh.
- upxo.pxtal.twinned_simple_3d.viz_3d.render_lgi_3d_compare(lgi_old: numpy.ndarray, lgi_new: numpy.ndarray, voxel_size_old=1.0, voxel_size_new=1.0, title_old: str | None = None, title_new: str | None = None, cmap: str = 'tab20', rng_seed: int = 0, show_edges: bool = True)[source]
Render two grain-label fields side by side in a single PyVista window (two linked-camera subplots) – e.g. an original vs. a stretched/ rescaled grain structure on Transformations’ “Introduce non-equiaxiality to SGS” page, so the two are visually comparable at a glance instead of two separate, independently-sized windows.
- Parameters:
lgi_old (ndarray (nx, ny, nz), int) – Grain label fields, already in PyVista’s (nx, ny, nz) axis convention – see
render_lgi_3d().lgi_new (ndarray (nx, ny, nz), int) – Grain label fields, already in PyVista’s (nx, ny, nz) axis convention – see
render_lgi_3d().voxel_size_old (float or (float, float, float)) – Physical voxel edge length(s) for each structure.
voxel_size_new (float or (float, float, float)) – Physical voxel edge length(s) for each structure.
title_old (str or None) – Per-panel title text; default to a grain-count summary.
title_new (str or None) – Per-panel title text; default to a grain-count summary.
cmap (str) – Qualitative PyVista/matplotlib colormap name.
rng_seed (int) – Seed for the ID -> colour-position shuffle (see
render_lgi_3d()); the same seed is used for both panels.show_edges (bool) – Draw voxel-cell edges as a wireframe overlay on both meshes.
- upxo.pxtal.twinned_simple_3d.viz_3d.render_lgi_3d_by_size(lgi: numpy.ndarray, size_thresholds: Tuple[float, float], voxel_size=1.0, title: str | None = None, band_colors: Tuple[str, str, str] | None = None, band_opacities: Tuple[float, float, float] = (1.0, 0.6, 0.3))[source]
Render a 3D grain-label field in a separate PyVista window, grains coloured and opacity-banded by their own voxel count into 3 size domains – e.g. to compare a grain structure before vs. after cleaning (small-grain merging measurably shifts the size distribution, which a uniform per-grain colouring can’t show).
- Parameters:
lgi (ndarray (nx, ny, nz), int) – Grain label field, already in PyVista’s (nx, ny, nz) axis convention (matching
render_3d()’s convention – transpose first if coming from the pipeline’s native (nz, ny, nx) array; seerender_lgi_3d()’s docstring).size_thresholds ((float, float)) –
(t1, t2)voxel-count cut points, t1 < t2. Domain 1: grains withvoxel_count < t1. Domain 2:t1 <= voxel_count < t2. Domain 3:voxel_count >= t2.voxel_size (float or (float, float, float)) – Physical voxel edge length(s). Isotropic if a bare float.
title (str or None) – Window title text; defaults to a per-domain grain-count summary.
band_colors ((str, str, str) or None) – PyVista colour names for domains 1/2/3. Defaults to
_DEFAULT_SIZE_BAND_COLORS(steelblue, seagreen, firebrick).band_opacities ((float, float, float)) – Opacity per domain. Defaults to (1.0, 0.60, 0.30) – smallest grains fully opaque, largest grains most transparent, so small grains (the ones cleaning actually acts on) stay visible instead of being hidden behind the bulk of the structure.
- upxo.pxtal.twinned_simple_3d.viz_3d.render_3d(lgi_twinned: numpy.ndarray, twin_role: Dict[int, str], role_opacity: Dict[str, float] | None = None, role_color: Dict[str, str] | None = None, nonhost_cmap: str | None = 'Greens')[source]
3D PyVista voxel render with per-role solid colour and opacity.
Host, primary_twin and secondary_twin roles are rendered with solid colours so
add_legend()shows correct swatches. Non-host grains are rendered with per-grain scalar colouring usingnonhost_cmapso individual matrix grains are visible rather than a uniform grey.- Parameters:
twin_role (dict {int: str}) – Role map: ‘host’ | ‘primary_twin’ | ‘secondary_twin’ | ‘non_host’.
role_opacity (dict {str: float} or None) – Per-role opacity. Defaults to
_DEFAULT_ROLE_OPACITY.role_color (dict {str: str} or None) – Per-role PyVista colour name for solid-coloured roles. Defaults to
_DEFAULT_ROLE_COLOR.nonhost_cmap (str or None) – Matplotlib / PyVista colormap name for non-host grains. Each grain is mapped to a unique hue so individual matrix grains are distinguishable. The colormap should not overlap with the solid role colours (steelblue, darkorange, crimson). Defaults to
'Greens'. PassNoneto fall back to the solidrole_color['non_host']colour instead.