upxo.pxtal.twinned_simple_3d.steps.steps_temporal_slice_sweep module

Temporal-Slice Sweep – advanced-tier extension, run at the end of the pipeline.

Part G’s ranking picks a single “best” temporal slice cheaply, from 2D cross-sectional grain-count/property comparisons alone – it never runs the actual downstream pipeline, so it cannot know a slice’s ACHIEVED total twin volume fraction (that number only exists once host allocation, orientation assignment, twin generation, and cleaning have all actually run for that slice). This module re-runs that full downstream chain for every requested saved temporal slice and reports which ones reach a given percentage of the EBSD-partitioned twin-volume-fraction target – the only way to answer that question directly, at the cost of repeating the most expensive part of the pipeline once per slice swept.

Every slice’s downstream chain is independent of every other slice’s (TwinnedSimple3DBase.from_mcgs copies its input label grid rather than aliasing shared state), so the per-slice work below is written as one module-level function, _run_one_slice, callable identically from a plain sequential loop or from a worker process pool.

upxo.pxtal.twinned_simple_3d.steps.steps_temporal_slice_sweep.sweep_temporal_slices(pxt, rg, parent_info, vf_targets, twin_thickness, tslice_keys=None, vf_threshold_pct=90.0, host_alloc_kwargs=None, orientation_kwargs=None, twin_gen_kwargs=None, clean_kwargs=None, export_passing=True, output_dir=None, base_filename='temporal_slice_sweep', verbose=True, n_workers=1)[source]

Re-runs host allocation, orientation assignment, twin generation, and cleaning for every requested temporal slice, and reports whether each slice’s achieved total twin volume fraction reaches vf_threshold_pct of the EBSD-partitioned target (Stage-1 + Secondary-2a + Secondary-2b from vf_targets).

tslice_keys: None or an empty list sweeps every slice pxt saved except index 0 (the Monte Carlo simulation’s un-annealed seed state, excluded for the same reason Part G’s own ranking excludes it – see Part G’s markdown). Given an explicit list, only the keys actually present in pxt.m are used; any others are dropped with a printed note rather than raising an error.

host_alloc_kwargs/orientation_kwargs/twin_gen_kwargs/ clean_kwargs: passed through to steps_host_allocation.allocate_hosts() / steps_orientation_assignment.assign_orientations() / steps_twin_generation.generate_twins() / steps_twin_generation.clean_structure() respectively – pass the same dicts of named parameters already configured earlier in the notebook so every swept slice is evaluated under identical settings.

n_workers: 1 (default) sweeps every slice sequentially, in this process, exactly as before. An integer greater than 1 instead distributes the requested slices across that many worker processes (concurrent.futures.ProcessPoolExecutor) – process-based rather than thread-based, because each slice’s work is ordinary CPU/NumPy-bound Python that the interpreter’s global lock would prevent threads from actually overlapping. pxt, rg, parent_info, and the four kwargs dicts are pickled once per worker process (not once per slice) via the pool’s initializer. n_workers is capped at min(n_workers, os.cpu_count(), number of slices actually swept). With more than one worker, per-slice progress prints as each slice finishes rather than as it starts, since several are in flight concurrently; the returned list is still ordered to match the order slices were swept in, identically to the sequential case.

Data export protocol: every slice whose achieved fraction reaches vf_threshold_pct (when export_passing=True, the default) shares ONE master folder for the whole sweep, <output_dir>/TwinnedFCC/Grain Structures/<base_filename><N>/ (auto-numbered via steps_visualization_export.next_master_folder(), picked once at the start of this sweep – not once per slice, so every passing slice in this run lands under the SAME master folder, while a later, separate sweep gets a fresh one and never collides with this one). Inside it, each passing slice gets its own tslice_<key>/ subfolder (via steps_visualization_export.export_raw()’s master_folder argument), so results from different slices in the same sweep never collide or overwrite one another either. Abaqus mesh export is deliberately NOT run here, as it is comparatively expensive per slice; re-run Parts I-P for one specific tslice_key afterward if a mesh is needed for a particular passing slice.

Returns:

  • list of dict (one row per swept slice, in the order swept – see)

  • _run_one_slice()’s docstring for each row’s shape.