Source code for upxo.pxtal.twinned_simple_3d.steps.steps_transformations
"""Transformations -- Part G of the Twinned FCC walkthrough (OPTIONAL).
Rescales then stretches the selected temporal slice's base grain
structure to introduce non-equiaxiality before Host Allocation. All
factors default to 1.0 (identity -- no change), so this stage is
genuinely optional: if you never call `apply_transform`, just use
TwinnedSimple3DBase.from_mcgs(pxt, tslice_key) directly and Host
Allocation gets the unmodified structure.
"""
[docs]
def apply_transform(pxt, tslice_key, scale_factor=1.0, sf_x=1.0, sf_y=1.0, sf_z=1.0):
"""Rescales (isotropic `scale_factor`) then stretches (per-axis
sf_x/sf_y/sf_z) the base grain structure at `tslice_key`, always
composed FROM THE ORIGINAL structure (never chained onto a previous
transform) so re-calling this with new factors replaces, rather than
compounds, the previous result.
Returns
-------
(new_base, original_base) : both TwinnedSimple3DBase instances.
"""
from upxo.pxtal.twinned_simple_3d.base_3d import TwinnedSimple3DBase
import upxo.gsdataops.grid_ops as gridOps
original = TwinnedSimple3DBase.from_mcgs(pxt, int(tslice_key))
lgi = gridOps.rescale_grid_3d(original.lgi, scale_factor, method='nearest')
voxel_size = original.voxel_size / scale_factor
lgi, _px_x, _px_y, _px_z, _new_shape = gridOps.stretch_grid_3d(
lgi, stretch_x=sf_x, stretch_y=sf_y, stretch_z=sf_z,
px_size_x=voxel_size, px_size_y=voxel_size, px_size_z=voxel_size)
new_base = TwinnedSimple3DBase(lgi, voxel_size, original.units)
new_base._tslice_key = original._tslice_key
return new_base, original