upxo.pxtalops.grain_boundary_zones module
- upxo.pxtalops.grain_boundary_zones.introduce_boundary_zones(gs, fids=[], niterations=5, method='use_min_core_size', min_core_size=50, threshold_bz_thickness=2, structure_nx=3, structure_ny=3, reset_others=False, renumber_fid_map=True, morph_char=False, topo_char=False, remap_scalars=False, perform_topology_checks=False, see_plot=False, figure_size=(5, 5), figure_dpi=100)[source]
Introduce boundary zones and cores within grains using morphological erosion.
This function partitions each grain into a boundary zone (outer region) and a core (inner region) by applying binary erosion. The method parameter controls how the boundary zone thickness is determined.
- Parameters:
gs (mcgs2_grain_structure) – Grain structure object (temporal slice) from UPXO. Note: This object is modified in-place; attributes bbox_bz and bbox_core are added to each grain. Pass a deep copy if you need to preserve the original.
fids (list of int, optional) – List of grain IDs (gid) to process. If empty (default), processes all grains in gs.gid. Use to selectively apply boundary zone detection to specific grains.
niterations (int, default=5) – Maximum number of morphological erosion iterations to attempt. Higher values allow thicker boundary zones but may eliminate small grains entirely.
method ({'use_min_core_size', 'simple', 'thresholded'}, default='use_min_core_size') –
Algorithm for defining boundary zones:
’use_min_core_size’: Erodes until core size drops below min_core_size, then backs off to maintain minimum core dimension (recommended for ensuring non-trivial cores).
’simple’: Uses maximum successful erosion without size constraints (may produce very small cores).
’thresholded’: Stops erosion when boundary zone reaches specific thickness defined by threshold_bz_thickness.
min_core_size (int, default=50) – Minimum number of pixels required in the grain core (used only with method=’use_min_core_size’). Grains smaller than this after maximum erosion will have their entire bbox assigned as boundary zone with bbox_core=None.
threshold_bz_thickness (int, default=2) – Number of erosion iterations to define boundary zone thickness (used only with method=’thresholded’). Boundary zone is the result of eroding exactly this many iterations.
structure_nx (int, default=3) – Width of the morphological structuring element (connectivity kernel). Value of 3 creates 8-connectivity for erosion (includes diagonals). Use 2 for 4-connectivity.
structure_ny (int, default=3) – Height of the morphological structuring element. Typically set equal to structure_nx for isotropic erosion.
see_plot (bool, default=False) – If True, generates a matplotlib visualization showing boundary zones overlaid on the grain structure with distinct colormap (useful for debugging).
figure_size (tuple of float, default=(5, 5)) – Width and height of the plot figure in inches (used only if see_plot=True).
figure_dpi (int, default=100) – Resolution of the plot figure in dots per inch (used only if see_plot=True).
- Returns:
lgi_new – 2D label image with boundary zones visualized as separate grain IDs. Shape matches gs.lgi. Original grain cores retain their IDs; boundary zones are assigned new sequential IDs starting from max(gs.gid) + 1.
- Return type:
ndarray of int
- Raises:
ValueError – If method is not one of the recognized options.
Side Effects –
------------ –
Modifies the input gs object in-place by adding two attributes to each processed grain: –
:raises - gs.g[gid][‘grain’].bbox_bz : ndarray of bool: Boolean mask of the boundary zone within the grain’s bounding box. Shape matches grain.bbox. Pixels marked True belong to the boundary zone. :raises - gs.g[gid][‘grain’].bbox_core : ndarray of bool or None: Boolean mask of the core region. If the grain is too small or erosion eliminates the core entirely, this is set to None.
Notes
Uses scipy.ndimage.binary_erosion for morphological operations.
For grains with bbox_core=None, the entire grain bbox is considered boundary zone.
To avoid modifying the original grain structure, pass a deep copy: lgi_new = introduce_boundary_zones(deepcopy(gs), …)
The returned lgi_new is for visualization only; actual boundary zone data is stored in gs.g[gid][‘grain’].bbox_bz.
Examples
>>> from upxo.pxtalops.grain_boundary_zones import introduce_boundary_zones >>> from copy import deepcopy >>> # Apply to all grains with minimum core size constraint >>> lgi_bz = introduce_boundary_zones(gs, method='use_min_core_size', min_core_size=100) >>> >>> # Process specific grains with simple erosion >>> lgi_bz = introduce_boundary_zones(gs, fids=[1, 5, 10], method='simple', niterations=3) >>> >>> # Preserve original structure >>> gs_copy = deepcopy(gs) >>> lgi_bz = introduce_boundary_zones(gs_copy, see_plot=True)
See also
introduce_bz__use_min_core_sizeImplementation of ‘use_min_core_size’ method.
introduce_bz__simpleImplementation of ‘simple’ method.
introduce_bz__thresholdedImplementation of ‘thresholded’ method.
Usage,-----,from,Authors,-------,Dr.
- upxo.pxtalops.grain_boundary_zones.introduce_bz__use_min_core_size(gs, fids=[], niterations=5, min_core_size=50, structure_nx=3, structure_ny=3, reset_others=False, renumber_fid_map=True, morph_char=False, topo_char=False, remap_scalars=False, perform_topology_checks=False, see_plot=False, figure_size=(5, 5), figure_dpi=100)[source]
Introduce boundary zones in the grains of a grain structure using minimum core size criterion.
- Parameters:
gs (GrainStructure) – The grain structure object containing grains to process.
fids (list, optional) – List of grain IDs to process. If empty, all grains will be processed.
niterations (int, optional) – Number of erosion iterations to perform. Default is 5.
min_core_size (int, optional) – Minimum core size to maintain during erosion. Default is 50.
structure_nx (int, optional) – Size of the structuring element in x-direction. Default is 3.
structure_ny (int, optional) – Size of the structuring element in y-direction. Default is 3.
see_plot (bool, optional) – Whether to plot the resulting grain structure with boundary zones. Default is False.
figure_size (tuple, optional) – Size of the plot figure. Default is (5, 5).
figure_dpi (int, optional) – DPI of the plot figure. Default is 100.
- Returns:
lgi_new – The updated grain structure image with boundary zones introduced.
- Return type:
ndarray
- Raises:
ValueError – If the fids list is empty.
Usage –
----- –
from pxtalops.grain_boundary_zones import introduce_bz__use_min_core_size –
- upxo.pxtalops.grain_boundary_zones.introduce_bz__simple(gs, fids=[], niterations=5, structure_nx=3, structure_ny=3, reset_others=False, renumber_fid_map=True, morph_char=False, topo_char=False, remap_scalars=False, perform_topology_checks=False, see_plot=False, figure_size=(5, 5), figure_dpi=100)[source]
Introduce boundary zones in the grains of a grain structure using simple erosion.
- Parameters:
gs (GrainStructure) – The grain structure object containing grains to process.
fids (list, optional) – List of grain IDs to process. If empty, all grains will be processed.
niterations (int, optional) – Number of erosion iterations to perform. Default is 5.
structure_nx (int, optional) – Size of the structuring element in x-direction. Default is 3.
structure_ny (int, optional) – Size of the structuring element in y-direction. Default is 3.
see_plot (bool, optional) – Whether to plot the resulting grain structure with boundary zones. Default is False.
figure_size (tuple, optional) – Size of the plot figure. Default is (5, 5).
figure_dpi (int, optional) – DPI of the plot figure. Default is 100.
- Returns:
lgi_new – The updated grain structure image with boundary zones introduced.
- Return type:
ndarray
- Raises:
ValueError – If the fids list is empty.
Usage –
----- –
from pxtalops.grain_boundary_zones import introduce_bz__simple –
- upxo.pxtalops.grain_boundary_zones.introduce_bz__thresholded(gs, fids=[], niterations=5, threshold_bz_thickness=2, structure_nx=3, structure_ny=3, reset_others=False, renumber_fid_map=True, morph_char=False, topo_char=False, remap_scalars=False, perform_topology_checks=False, see_plot=False, figure_size=(5, 5), figure_dpi=100)[source]
Introduce boundary zones in the grains of a grain structure using thresholded erosion.
- Parameters:
gs (GrainStructure) – The grain structure object containing grains to process.
fids (list, optional) – List of grain IDs to process. If empty, all grains will be processed.
niterations (int, optional) – Number of erosion iterations to perform. Default is 5.
threshold_bz_thickness (int, optional) – Threshold for boundary zone thickness. Default is 2.
structure_nx (int, optional) – Size of the structuring element in x-direction. Default is 3.
structure_ny (int, optional) – Size of the structuring element in y-direction. Default is 3.
see_plot (bool, optional) – Whether to plot the resulting grain structure with boundary zones. Default is False.
figure_size (tuple, optional) – Size of the plot figure. Default is (5, 5).
figure_dpi (int, optional) – DPI of the plot figure. Default is 100.
- Returns:
lgi_new – The updated grain structure image with boundary zones introduced.
- Return type:
ndarray
- Raises:
ValueError – If the fids list is empty.
Usage –
----- –
from pxtalops.grain_boundary_zones import introduce_bz__thresholded –
- upxo.pxtalops.grain_boundary_zones.determine_buffer_geometric_GS(cell, min_cell_area=5, buffer_quality_factor=0.25, min_area_retention=0.3, max_allowed_holes=2, max_iterations=20, verbose=True)[source]
Determine an appropriate buffer distance for creating a boundary zone within a grain cell using geometric properties of the cell. The function iteratively tests buffer distances to ensure that the resulting buffered cell does not create too many holes (disconnected interiors).
- Parameters:
cell (shapely.geometry.Polygon) – The polygon representing the grain cell to buffer.
buffer_quality_factor (float, default=0.25) – Fraction of the inscribed radius to use as the initial buffer distance. Higher values may create thicker boundary zones but risk creating holes. Adjust based on desired balance between boundary zone thickness and core integrity.
min_area_retention (float, default=0.30) – Minimum fraction of the original cell area that must be retained in the buffered cell. This is used to calculate a maximum buffer distance based on area loss.
max_allowed_holes (int, default=2) – Maximum number of holes (disconnected interiors) allowed in the buffered cell. Set to 0 for no holes, or a higher number if some fragmentation is acceptable.
max_iterations (int, default=20) – Maximum number of iterations to test different buffer distances. The buffer distance is reduced iteratively if the resulting buffered cell has too many holes or is empty.
verbose (bool, default=True) – If True, prints detailed information about the buffering process, including geometric properties, buffer distances tested, and hole counts.
- Returns:
bufferDist (float or None) – The final buffer distance that meets the criteria, or None if no valid buffer distance was found.
bufferCell (list of shapely.geometry.Polygon or None) – List of polygons representing the buffered cell structure: - If no holes created: list with single polygon (the buffered cell) - If holes created: list with outer polygon (index 0) followed by each hole as a separate polygon - None if no valid buffer distance was found.
boundaryZone (shapely.geometry.Polygon or shapely.geometry.MultiPolygon or None) – The boundary zone region (original cell minus buffered cell). May be a MultiPolygon if holes were created. None if no valid buffer distance was found.
Usage
—–
from upxo.pxtalops.grain_boundary_zones import determine_buffer_geometric_GS as find_buffer_geom
- upxo.pxtalops.grain_boundary_zones.process_grain_boundary_zones(smoothed_grains, ignoreFids=[], min_cell_area=80, buffer_quality_factor=0.55, min_area_retention=0.3, max_allowed_holes=2, max_iterations=20, verbose=False)[source]
Orchestrator function to process all grains and create boundary zones.
- Parameters:
smoothed_grains (dict) – Dictionary of grain IDs to Shapely Polygon geometries
min_cell_area (int, default=80) – Minimum cell area threshold for processing
buffer_quality_factor (float, default=0.55) – Buffer quality factor for geometric calculation
min_area_retention (float, default=0.30) – Minimum area fraction to retain in buffered cell
max_allowed_holes (int, default=2) – Maximum number of holes allowed in buffered cell
max_iterations (int, default=20) – Maximum iterations for buffer refinement
verbose (bool, default=False) – Print detailed processing information
- Returns:
BZ_1_cells (dict) – Dictionary mapping grain IDs to boundary zone polygons
BZ_1_thickness (dict) – Dictionary mapping grain IDs to buffer distances
CZ_1_cells (dict) – Dictionary mapping grain IDs to core zone polygon lists
CZ1 (list) – Flat list of all core zone polygons
combined_multipolygon (shapely.geometry.MultiPolygon) – MultiPolygon containing all valid boundary zones and core zones for visualization
Usage
—–
from upxo.pxtalops.grain_boundary_zones import process_grain_boundary_zones