upxo.pxtalops.gssmooth2d module
gssmooth2d.py — 2D grain-structure post-pixellation smoothing pipeline.
Public API
- smooth_gs_sliceFull single-slice pipeline; returns a result dict.
Supports method=’taubin’, ‘moving_average’, ‘mean_coords’.
introduce_twins_in_shapely : Geometric S3 twin introduction via Shapely boolean ops.
Private helpers (module-internal)
_fix_diagonal_pinches : Restore 4-connectivity at diagonal-only pinches. _fill_staircase_concavities : Widen 1-px staircase twins to 2-px ribbons. _merge_small_grains : Merge isolated grains into their largest neighbour. _merge_enclosed_polygons : Union polygons that lie entirely inside another. _compute_polygon_neighbors : Build adjacency dict via Shapely .touches(). _mean_coordinates : MA smoothing of an open boundary segment; endpoints pinned. _mean_coordinates_ring : Circular MA smoothing of a closed ring (island grains). _smooth_mean_coords : Segment-based mean-coordinate smoother for all polygons. _make_lamella_strip : Shapely rectangle for a twin lamella strip. _truncate_twin_shapely : Keep the entry-side half of an abrupt twin polygon. _compute_s3_twin_quat : Apply S3 misorientation to parent quaternion + scatter.
- upxo.pxtalops.gssmooth2d.smooth_gs_slice(lfi: np.ndarray, seeds: np.ndarray | None = None, area_threshold: int = 1, smooth_iter: int = 10, smooth_lambda: float = 0.5, smooth_mu: float = -0.53, trim_bounds: tuple = (0, 0, 200, 200), coord_decimals: int = 6, verbose: bool = False, method: str = 'taubin', ma_window: int = 3, corner_angle_deg: float = 30.0, upscale_factor: int = 1, thin_grain_px: float = 0.0, fix_diagonal: bool = True, merge_enclosed: bool = True, close_staircase: bool = True, **seed_kwargs) dict[source]
Full post-pixellation smoothing pipeline for a single MC grain-structure slice.
Steps
1 Merge grains <= area_threshold px into their largest neighbour. 2 Generate seeds (if not supplied) and tessellate into GrainManifold2D. 3 Smooth polygon boundaries (Taubin / moving_average / mean_coords). 4 Trim to RVE. 5 Remove empty / invalid polygons. 6 Build polygon neighbour graph. 7 Renumber GIDs to contiguous 1 → N. 8 Geometry validation. 9 Symmetric grain-pair list. 10 Shared-boundary interface extraction. 11 Junction-point (triple-point) extraction.
- param lfi:
- type lfi:
2-D integer label field (0 = background).
- param seeds:
- type seeds:
(N, 2) Cartesian seed array. Generated internally when None.
- param area_threshold:
- type area_threshold:
Grains with <= this many pixels are merged (Step 1).
- param smooth_iter:
- type smooth_iter:
Iterations / passes for the chosen smoothing method.
- param smooth_lambda:
- type smooth_lambda:
Taubin forward-pass weight (method=’taubin’ only).
- param smooth_mu:
- type smooth_mu:
Taubin backward-pass weight, must be negative (method=’taubin’ only).
- param trim_bounds:
- type trim_bounds:
(xmin, ymin, xmax, ymax) — RVE clip rectangle.
- param coord_decimals:
- type coord_decimals:
Decimal places for junction-point coordinate rounding.
- param verbose:
- type verbose:
Print step-by-step progress.
- param method:
‘mean_coords’. ‘mean_coords’ uses segment-based uniform moving-average smoothing with junction vertices pinned; island grains (no junction vertices) use circular convolution.
- type method:
Smoothing algorithm — ‘taubin’ (default), ‘moving_average’, or
- param ma_window:
‘moving_average’ and ‘mean_coords’.
- type ma_window:
Moving-average kernel half-width (vertices); used by
- param **seed_kwargs:
when seeds is None (e.g. target_spacing, bulk_spacing).
- type **seed_kwargs:
Extra kwargs forwarded to generate_constrained_hybrid_seeds
- returns:
manifold GrainManifold2D instance (cells already updated). cells {gid: Shapely Polygon}. polygon_neighbors {gid: [gids]}. validity_report {gid: {‘is_valid’: bool, ‘has_area’: bool, ‘area’: float}}. cell_pairs_list [(gid1, gid2), …] — sorted symmetric pairs. cell_pair_interfaces {(gid1, gid2): LineString | MultiLineString}. junction_points [Point, …]. jp_dict {jp_id: [order, (gids,)]}. old_to_new_gid {old_gid: new_gid}. n_grains int. n_invalid int.
- rtype:
dict
- upxo.pxtalops.gssmooth2d.introduce_twins_in_shapely(cells: dict, smooth_quats: dict, host_gids: list, twin_thickness: dict, abrupt_frac: float, rng, n_twins_per_parent: int = 1, secondary_host_frac: float = 0.0, twin_orient_scatter_deg: float = 1.5) dict[source]
Introduce S3 twin lamellae into parent Shapely polygons via geometric strip operations. Twin boundaries are analytically straight — no pixellation artefact, no post-hoc repair needed.
- Parameters:
cells ({gid: Polygon} — smoothed parent polygons.)
host_gids (subset of cells.keys() that receive twins.)
twin_thickness ({'thick_px': 1-D array of half-widths in px}.)
abrupt_frac (fraction of twins that are abrupt (do not span parent).)
rng (numpy.random.Generator.)
n_twins_per_parent (how many strips to cut per host grain.)
secondary_host_frac (fraction of primary twins that become secondary hosts) – (currently reserved; set to 0 to skip).
twin_orient_scatter_deg (Gaussian scatter on twin orientation (degrees).)
- Returns:
cells : {gid: Polygon} — updated dict (parents + twins). twin_gids : {host_gid: [twin_gid, …]} — new GIDs per host. twin_quats : {gid: ndarray(4,)} — orientations including new twin GIDs.
- Return type:
dict with keys