upxo.pxtal.geometrification module
Geometrification module for converting raster grain structures to polygon representations.
- class upxo.pxtal.geometrification.polygonised_grain_structure(lgi, gids, neigh_gid_pxtal)[source]
Bases:
objectRaster-to-polygon geometrification of a 2D labelled grain image.
Converts an LFI /
lgifield into Shapely polygons, grain-boundary segments, junction points, and neighbour topology for geometric analysis and conformal meshing. Intermediate stores include raw and smoothed GB multipolylines, centroids, and quality metrics.- lgi, gid, n
Source label image, grain IDs, and grain count.
- polygons, GRAINS, POLYXTAL
Grain polygons and assembled geometric polycrystal views.
- neigh_gid, gid_pair_ids*
Neighbour topology and unique neighbour pairs.
- GBSEG*, GBP*, JNP*, gbsegments*
Grain-boundary segments, points, and junction points (raw/sorted).
- centroids, quality, smoothed
Centroids, polygonisation quality flags, smoothing state.
- EPS_coord_coincide = 1e-08
- lgi
- gid
- neigh_gid_pxtal
- n
- GBSEG
- polygons
- polygons_raw_exteriors
- polygons_raw_holes
- gsmp
- smoothed
- polygonize(user_lgi=False, lgi=None, user_gids=False, gids=None, verbose=True)[source]
Polygonize grains in self.lgi.
- make_polygonal_grains_raw(verbose=True, perform_xtal_dict_check=True)[source]
Build and return polygonal grains raw.
- property expol
Expol.
- property hlpol
Hlpol.
- property holes_exist
Holes exist.
- property allpol
Allpol.
- find_neighbors(verbose=True)[source]
Calculate neighbouring polygon IDs for all polygons in the grain structure.
- get_polygon_touch_lines(poly1, poly2)[source]
Calculate the lines or points where two Shapely polygons touch.
- Parameters:
poly1 (shapely.geometry.Polygon) – The two polygon objects to test.
poly2 (shapely.geometry.Polygon) – The two polygon objects to test.
- Returns:
List of Shapely LineString objects if the polygons share edges, or Shapely Point objects if they touch at a single point.
- Return type:
- get_multilinestring_touch_points(mls2)[source]
Calculate the point(s) where two Shapely MultiLineStrings touch.
- Parameters:
mls1 (shapely.geometry.MultiLineString) – The two MultiLineString objects to test.
mls2 (shapely.geometry.MultiLineString) – The two MultiLineString objects to test.
- Returns:
List of Shapely Point objects at touch points, or empty list if none.
- Return type:
- area_gid(gid, gsrepr='raw')[source]
Return area of gid grain. Valid values for gsrepr are self.gsmp.keys(). In any case, the returned area will be geometric and not pixellated.
Examples
self.area_gid(1, gsrepr='raw')
- plot_linestrings(ax=None, color='blue', linewidth=1, **kwargs)[source]
Plot a list of Shapely LineStrings and return the axis.
- Parameters:
linestrings (list) – A list of LineString or MultiLineString objects.
ax (matplotlib.axes.Axes, optional) – Axes object to plot on. If None, a new figure and axis are created.
color (str, optional) – Line colour. Default is
'blue'.linewidth (float, optional) – Line width. Default is
1.**kwargs – Additional keyword arguments passed to
plt.plot().
- Returns:
The Axes object on which the lines were plotted.
- Return type:
matplotlib.axes.Axes
- plot_gsmp(raw=True, overlay_on_lgi=False, xoffset=0.5, yoffset=0.5, ax=None)[source]
Plot multi-polygon form of the grain structure.
- Parameters:
raw (bool, optional) – If True, plot the raw gsmp. Default is True.
overlay_on_lgi (bool, optional) – If True, overlay the polygons on the lgi image. Default is False.
xoffset (float, optional) – Coordinate offsets applied before plotting. Default is 0.5.
yoffset (float, optional) – Coordinate offsets applied before plotting. Default is 0.5.
ax (matplotlib.axes.Axes, optional) – Axes object to plot on. If None, a new figure and axis are created.
- Return type:
matplotlib.axes.Axes
- plot_grains_gids(gids, add_points=True, points=None, gclr='color', title='user grains', cmap_name='viridis', plot_centroids=True, add_gid_text=True, plot_gbseg=False, bjp_kwargs={'marker': 'o', 'mec': 'black', 'mfc': 'yellow', 'ms': 2.5}, addpoints_kwargs={'marker': 'x', 'mec': 'black', 'mfc': 'black', 'ms': 5})[source]
- Parameters:
- Return type:
matplotlib.axes.Axes
Examples
# After acquiring gids for aspect_ratio between ranks 80 and 100, # visualize those grains. gid, _, __ = PXGS.gs[8].get_gid_prop_range(PROP_NAME='aspect_ratio', range_type='rank', rank_range=[80, 100]) PXGS.gs[8].plot_grains_gids(gid, cmap_name='CMRmap_r')
- subdivide_gbsegments(method=1)[source]
Subdivide grain boundary segments by inserting additional nodes.
- set_grain_centroids_raw(verbose=True)[source]
Set raw grain centroids computed from lgi pixel locations.
- pix_to_geom(polygonisation_offset=0.5, verbose=True, perform_xtal_dict_check=True)[source]
Pix to geom.
Grain structures with island grains (a grain enclosed by another) are split into a hole-free structure plus one structure per island cluster; see
_pix_to_geom_islands().
- get_bounds_from_grain_boundary_points()[source]
Get x and y bounds from grain boundary points.
Notes
Works on grain boundary points obtained from polygonization of the raster image.
self.xyoffsetis subtracted from polygonization end coordinates to align with MCGS 2D results.Examples
xmin, xmax, ymin, ymax = self.get_bounds_from_grain_boundary_points()
- set_grain_loc_ids(verbose=True)[source]
Identify the location of grains and place their IDs in self.grain_loc_ids dictionary.
- get_junction_points_from_grain_intersections(verbose=True)[source]
Return the junction points from grain intersections.
For every pair of intersecting grain polygons the end points of their shared boundary are junction points: both ends of a line, the boundary points of a multi-line, or a single touching point. Mixed intersections (a line plus an isolated point) contribute nothing, as before. Pairs come from an R-tree query and all intersections are computed in one vectorised call.
- extract_GBP(verbose=True)[source]
Extract grain boundary points data from polygonization coordinate results.
- set_up_quality_measures(verbose=True)[source]
Initiate the quality dictionary to hold results on operation quality.
- find_GBP_at_boundary(verbose=True)[source]
Identify grain boundary points lying on the grain structure boundary.
- update_JNP_from_GBP_at_boundary(verbose=True)[source]
Update junction points with the grain boundary points which are on the boundaries of the poly-xtal.
- build_jnp_objects(verbose=True)[source]
Build coordinates, UPXO Point2d objects and shapely point objects of all junction points.
- build_all_gbp_objects(verbose=True)[source]
Build coordinates of all grain boundary points. Global.
- get_gbp_grain_wise_coords(verbose=True)[source]
Build coordinates of all grain boundary points, grain-wise.
- build_jnp_grain_wise_indices(verbose=True)[source]
Build indices of jnp for every grain. Indices will be from jnp_all_coords. These indices relate to:
jnp_all_coords, jnp_all_upxo, jnp_all_shapely
jnp_all_upxo_mp.points, jnp_all_upxo_mp.coords
Examples
# Data access: jnp_all_coords[jnp_grain_wise_indices[gid]] jnp_all_upxo[jnp_grain_wise_indices[gid]] jnp_all_upxo_mp.points[jnp_grain_wise_indices[gid]] # Verification: gid = 10 plt.imshow(geom.lgi) coord = jnp_all_coords[jnp_grain_wise_indices[gid]] plt.plot(coord[:, 0], coord[:, 1], 'ko')
Notes
jnp_all_upxo and jnp_all_upxo_mp.points share the same objects:
id(jnp_all_upxo[i]) == id(jnp_all_upxo_mp.points[i])
- build_gbp_grain_wise_indices_geometric(verbose=True)[source]
This is to correct inconsistencies in build_jnp_grain_wise_indices method. There are cases which lead to mulline constityutent lines intersecting each other. This step is crucial to avoid it.
- build_gbp_grain_wise_indices_coordbased(verbose=True)[source]
Build and return gbp grain wise indices coordbased.
- build_gbp_grain_wise_indices_pointsbased(verbose=True)[source]
Build and return gbp grain wise indices pointsbased.
- build_gbmullines_grain_wise(verbose=True)[source]
Build grain boundary multi-linestring objects from grain boundary point data.
- arrange_junction_point_coords_new(gbcoords_thisgrain, junction_points_coord)[source]
Arrange junction point coords new.
- align_gbmullines_start_to_jnp_start(plot_bf=False, plot_af=False, verbose=True)[source]
Align gbmullines start to jnp start.
- splice_grain_boundary_segments_at_junction_points(plot=False, verbose=True)[source]
Splice the grain boundary into grain boundary segments using jnp point data
- find_quality_of_grain_boundary_segmentation(verbose=True)[source]
Assess quality of grain boundary segmentation by comparing segment counts per grain.
- create_neigh_gid_pair_ids(neigh_gid, verbose=True)[source]
Create a dictionary mapping unique grain pairs to integer IDs.
- get_random_gbpoint_between_jnpoints(gbcoords, jnpcoords)[source]
Return a random grain boundary point located between two junction points.
- get_random_gbpoints_between_jnpoints(gid)[source]
Return random grain boundary points between junction points for a given grain.
- setup_neigh_connectivity_flags_DS(neigh_sense='lr', field_names=['gbseg', 'nnodes_eq', 'length_eq', 'n', 'areas_raw', 'uniquified'], verbose=True)[source]
Setup neigh connectivity flags ds.
- extract_end_coordinates_of_grain_boundary_segments_grain_wise(gid)[source]
Extract end coordinates of grain boundary segments grain wise.
- set_neigh_connectivity_flags_DS(centroid_eq_EPS=1e-08, verbose=True)[source]
Set or update neigh connectivity flags DS.
- get_unique_object_indices(nnodes, lengths, centroids, tol=1e-08)[source]
Find indices of unique objects based on nnodes, lengths, and centroids.
- Parameters:
nnodes (np.ndarray) – 1D array of nnode values.
lengths (np.ndarray) – 1D array of length values.
centroids (np.ndarray) – 2D array of centroid coordinates.
tol (float, optional) – Tolerance for centroid coordinate comparison. Default is
1e-8.
- Returns:
1D array of indices corresponding to unique objects.
- Return type:
np.ndarray
- gather_grain_boundary_segments_of_all_pairs(verbose=True)[source]
Gather grain boundary segments of all pairs.
- consolidate_gbsegments(squeeze_segment_data_structure=False, verbose=True)[source]
Consolidate grain boundary segments by grain ID.
- update_consolidated_segments_with_boundary_grain_gids(plot=False, verbose=True)[source]
Set or update te consolidated segments with boundary grain gids.
- check_if_all_gbsegs_can_form_closed_rings(GBSEGS, _print_individual_excoord_order_=True, _print_statement_=True)[source]
Check or validate check if all gbsegs can form closed rings.
- flip_segments_to_reorder_GBS(plot_each_grain_details=False, verbose=True)[source]
Flip segments to reorder gbs.
- sort_subsets_by_original_order(CA, subsets)[source]
Sort subsets of coordinates based on their original order in the CA array.
- Parameters:
CA (np.ndarray) – The original 2D coordinate array (N x 2).
subsets (list) – A list of np.ndarrays, each representing a subset of coordinates.
- Returns:
list – Sorted np.ndarrays, each subset ordered according to its position in CA.
np.ndarray – 1D array of the original subset indices in sorted order.
- calculate_grain_boundary_coordinates_after_gbseg_reordering(verbose=True)[source]
Calculate grain boundary coordinates after gbseg reordering.
- plot_reordered_GBCoords(gid, force_close=True)[source]
Visualise reordered GBCoords using Matplotlib or PyVista.
- plot_user_gbcoords1(gbcoords, lw=1.5)[source]
Visualise user gbcoords1 using Matplotlib or PyVista.
- construct_geometric_xtals_from_gbcoords(coord_loop_dict, dtype='shapely', saa=True, throw=False, smoothed=None)[source]
self.construct_geometric_xtals_from_gbcoords(GBCoords).
dtype=’upxo’ wraps self.GB[gid] (already a ring2d) directly into a Polygon2d – zero-copy, ignores coord_loop_dict (which was only ever a coordinate array derived from that same ring). A gid with island hole(s) recorded in self.GB_holes (see _assemble_island_results) becomes a NestedPolygon2d instead.
smoothed(dtype=’upxo’ only) is thenamegiven tosmooth_gbsegs: the smoothed rings and holes inself.smoothed[name]are wrapped instead of the raw ones.
- construct_geometric_polyxtal_from_gbcoords(coord_loop_dict, dtype='shapely', saa=True, throw=False, plot_polyxtal=False, verbose=True)[source]
Construct geometric polyxtal from gbcoords.
- smooth_gbsegs(GB, npasses=2, max_smooth_levels=[3, 3], plot=True, name='kali')[source]
Smooth gbsegs.
For a structure with islands,
GBis ignored: the filled structure and each island cluster are smoothed from their ownGB.
- plotgs(gs_geometric, fig=None, ax=None, cmap='tab20', edgecolor='black', alpha=0.7, lw=1, figsize=(10, 10), dpi=100)[source]
Plotgs.
- pxtal
- neigh_gid
- gbsegments_raw
- gbsegments_mls
- gbseg_smoothed
- GBPOINTS
- raster_img_polygonisation_results
- neigh_pols
- centroids_raw
- centroids
- xyoffset
- grain_loc_ids
- JNP
- GBP
- GBP_pure
- GBP_at_boundary
- jnp_all_coords
- quality
- sorted_segs
- jnp_all_upxo
- jnp_all_shapely
- gbp_all_coords
- gbp_all_upxo
- gbp_all_shapely
- jnp_grain_wise_indices
- gbp_grain_wise_coords
- gbp_grain_wise_indices
- gbp_grain_wise_points
- gbmullines_grain_wise
- junction_points_coord
- jnp_all_sorted_coords
- jnp_all_sorted_upxo
- gbsegments
- gid_pair_ids
- gid_pair_ids_unique_lr
- gid_pair_ids_unique_rl
- nconn
- GBSEGMENTS
- consolidated_segments
- GB
- GBCoords
- GB_holes
- GRAINS
- POLYXTAL
- mids_all_gbsegs
- sgseg_obj_list
- class upxo.pxtal.geometrification.VoronoiMasking(lfi)[source]
Bases:
ABCAbstract base: Voronoi cells masked by sampling a label field (LFI).
Seeds define a tessellation; each seed samples
lfito obtain a grain/feature ID, then dimension-specific subclasses merge cells sharing an ID into manifolds (Shapely 2D / PyVista 3D).Factory methods (abstract):
by_tessellation,load_tessellation.- map_seeds_to_lfi(channel=0)[source]
Samples the LFI at seed coordinates. Correctly handles the conversion from Cartesian (x, y) seeds to array indices (row, col) for sampling.
- abstractmethod classmethod by_tessellation(lfi, seeds)[source]
Factory method to create instance via new Voronoi computation.
- class upxo.pxtal.geometrification.GrainManifold2D(lfi)[source]
Bases:
VoronoiMasking2D grain manifolds from Voronoi tessellation + LFI sampling.
Each seed maps to a label in the LFI; Voronoi polygons with the same label are unioned (Shapely) into one manifold per grain/feature ID. Construct via
by_tessellation(lfi, seeds).- classmethod load_tessellation(lfi, filepath)[source]
Placeholder implementation to satisfy abstract requirement.
- smooth_interfaces(iterations=10, lmbda=0.5, mu=-0.53, method='taubin', ma_window=3, corner_angle_deg=30.0, thin_grain_px=1.5)[source]
Smooth interfaces.
- Parameters:
thin_grain_px (float, optional) – Vertices of every grain whose minimum bounding-rectangle width is below this (pixel units) are held fixed. Smoothing shrinks any small closed loop, since its Laplacian modes all lie outside the Taubin passband. A four-vertex single-pixel grain retains about 0.77 of its size per iteration, so an island (whose vertices are not junctions and so are not pinned otherwise) collapsed to a sliver. Default 1.5 keeps single-pixel grains and one-pixel-wide grains exact. Use 0 to disable.
- gb_smooth(ma_window=3, taubin_iter=10, lmbda=0.5, mu=-0.5, ma_smoother_version=2)[source]
Gb smooth.
- class upxo.pxtal.geometrification.GrainManifold3D(lfi)[source]
Bases:
VoronoiMasking3D grain manifolds from Voronoi tessellation + LFI sampling.
3D counterpart of
GrainManifold2D: seeds sample a 3D label volume; clipped Voronoi solids (PyVista) are grouped by feature ID.assemble_cellsis currently a stub for full boolean union merge.