Strain#

lauelab.strain calculates reference-volume-normalized deviatoric Biot lattice strain from assigned measured directions. The guide gives a complete synthetic workflow; the algorithm defines conventions and numerical support checks.

This public surface adds a configured refiner and functional stages because users need both repeated notebook/script configuration and direct numerical access. The object composes the same stage implementation. No implicit current pattern or accumulated fit state is retained.

class lauelab.strain.StrainRefiner(reference, *, geometry=None, detector_index=None, fit='110111', coordinates='beamline', max_nfev=1000, condition_limit=100000000.0)[source]#

Reusable strain configuration with independent results for each call.

Parameters:
  • reference (lauelab.indexing.Cell or lauelab.indexing.Crystal) – Explicit unstrained reference, independent of source indexing metadata.

  • geometry (lauelab.indexing.Geometry or str or pathlib.Path or None) – Calibration for measured centroids; saved source geometry is used when None. Prepared directions retain their original fixed calibration.

  • detector_index (int or None) – Physical detector slot, resolved from source metadata when omitted.

  • fit (str or tuple of str) – Igor mask or free parameter names, default "110111".

  • coordinates (str) – Result frame, default "beamline".

  • max_nfev (int) – Maximum optimizer function evaluations, default 1000.

  • condition_limit (float) – Numerical joint Jacobian condition bound, default 1e8.

Notes

Model, frames and numerical controls follow refine_deviatoric. Configuration is read-only; use replace to change it. No previous fit or active pattern is retained. Invalid configuration raises InputError, TypeError or ValueError.

replace(**changes)[source]#

Return an independently validated refiner with changed configuration.

refine(source, *, frame_id=None, pattern=0, peak_indices=None, depth=None)[source]#

Return one result; malformed selected input raises an exception.

Parameters:
  • source (object) – Any source accepted by prepare_reflections, including prepared data.

  • frame_id (str or int or None) – Source frame; required when the source contains multiple frames.

  • pattern (int) – Nonnegative pattern rank, default zero.

  • peak_indices (numpy.ndarray or None) – Original measured-peak IDs to select in source assignment order.

  • depth (float or None) – Sample depth override in µm, including explicit zero.

Returns:

StrainResult – Independent fit result, including unsuccessful numerical outcomes.

Notes

Sources and selections follow prepare_reflections. Geometry is taken from this configuration, or from a saved source when not configured. The explicit reference is never replaced by source crystal metadata.

refine_many(source, *, frame_ids=None, patterns='all')[source]#

Return ordered outcomes, fitting all patterns by default.

Parameters:
  • source (object) – Any source accepted by prepare_reflections. Saved files are read once.

  • frame_ids (tuple or None) – Explicit frame IDs to include; None includes all frames. Results retain source order independently of filter order.

  • patterns (str or tuple of int) – "all" (default), "best" (lowest rank per frame), or explicit nonnegative ranks to include.

Returns:

list of StrainResult – Independent results in source frame/pattern order.

Notes

Expected per-pattern input errors are recorded as invalid_input results; unexpected/internal or shared-source failures propagate. No support prefilter is applied.

lauelab.strain.prepare_reflections(source, *, frame_id=None, pattern=0, geometry=None, detector_index=None, depth=None, peak_indices=None)[source]#

Prepare one indexed pattern using measured centroids and calibration.

Parameters:
  • source (object) – FrameResult, ResultSet, VisualizationDataset, prepared StrainReflections or an indexing XML/HDF5 path. Existing readers are reused directly.

  • frame_id (str or int or None) – Required for a multi-frame source; a sole frame is selected by default.

  • pattern (int) – Nonnegative pattern rank, default zero.

  • geometry (lauelab.indexing.Geometry or str or pathlib.Path or None) – Effective calibration, overriding saved geometry when supplied.

  • detector_index (int or None) – Physical geometry slot, not ordinal active-detector position. Must agree with recorded detector identity. Ambiguous selection errors.

  • depth (float or None) – Sample depth in µm. Explicit zero also overrides stored depth.

  • peak_indices (numpy.ndarray or None) – Unique original measured-peak IDs to select, retaining source assignment order. No automatic rejection or rematching occurs.

Returns:

StrainReflections – Owned float64 directions/centroids, integer HKLs and calibration provenance. An already prepared input is returned with its fixed context; conflicting selection/context overrides raise InputError.

Notes

Invalid selected inputs raise InputError, ValueError or TypeError. File I/O errors propagate. Raw directions can be passed to refine_deviatoric without geometry.

lauelab.strain.refine_deviatoric(qhat, hkl=None, *, reference, initial_reciprocal=None, fit='110111', coordinates='beamline', max_nfev=1000, condition_limit=100000000.0)[source]#

Refine assigned directions with Igor’s uniform chord objective.

Parameters:
  • qhat (numpy.ndarray or StrainReflections) – Measured directions, shape (n, 3), normalized internally, or a preparation-stage result supplying all measurement arguments.

  • hkl (numpy.ndarray or None) – Aligned integer Miller indices, shape (n, 3). Omit for prepared data.

  • reference (lauelab.indexing.Cell or lauelab.indexing.Crystal) – Explicit unstrained reference metric; independent of the initial fit.

  • initial_reciprocal (numpy.ndarray or None) – Starting reciprocal rows, shape (3, 3), 1/nm including 2π. Required for array inputs; omit for prepared data.

  • fit (str or tuple of str) – Six binary flags or unique parameter names in a,b,c,alpha,beta,gamma order. Default "110111" gives five shape and three rotational parameters. At least one length must be held. Excluded working-cell values come from reference before reference-volume normalization.

  • coordinates (str) – "beamline" (default), "crystal", "xhf" or "sample".

  • max_nfev (int) – Maximum optimizer function evaluations, default 1000.

  • condition_limit (float) – Joint dimensionless Jacobian condition bound, default 1e8; must be finite and greater than one. This is not an experimental error bar.

Returns:

StrainResult – Owned fit evidence, including unsuccessful support/convergence outcomes with NaN tensors. No automatic reflection rejection, weighting or reassignment is performed.

Notes

Invalid inputs raise InputError or TypeError. Empirical Igor export comparisons remain a separate validation gate.

lauelab.strain.strain_from_reciprocal(reciprocal, *, reference, coordinates='crystal')[source]#

Calculate Igor deviatoric stretch strain from a refined lattice.

Parameters:
  • reciprocal (numpy.ndarray) – Reciprocal rows in 1/nm, including 2π, shape (..., 3, 3).

  • reference (lauelab.indexing.Cell or lauelab.indexing.Crystal) – Explicit reference in the native c-parallel-z basis. Cell metrics are used as supplied; Crystal uses native space-group constraints.

  • coordinates (str) – "crystal" (default), "beamline", "xhf" or "sample". Beamline conversion uses the fitted canonical-cell orientation; sample/XHF use the fixed Igor presets.

Returns:

numpy.ndarray – Dimensionless float64 tensor(s) with the input shape. Normalize to reference cell volume, then calculate dev(sqrt(F.T @ F) - I). The square root is a symmetric matrix square root.

Notes

The beamline transform uses Igor’s orientation convention, which can differ from the polar rotation of F at finite shear. This function performs no measurement fit or uncertainty estimate. Invalid lattices or frame names raise InputError; an unsupported reference raises TypeError.

lauelab.strain.transform_strain(tensor, rotation)[source]#

Transform tensor components with R @ tensor @ R.T.

Parameters:
  • tensor (numpy.ndarray) – Symmetric dimensionless tensor(s), shape (..., 3, 3), with tensor shear, without engineering-shear doubling.

  • rotation (numpy.ndarray) – Proper orthonormal coordinate transform(s), shape (..., 3, 3). Leading dimensions broadcast against those of tensor.

Returns:

numpy.ndarray – Independent float64 array of transformed components.

Raises:

lauelab.indexing.InputError – Invalid tensor/rotation, nonfinite entries or incompatible shapes.

class lauelab.strain.StrainReflections(qhat, hkl, initial_reciprocal, xy=None, peak_indices=None, frame_id=None, pattern_index=0, provenance_json='{}')[source]#

Owned aligned measurements prepared for one independent pattern fit.

Parameters:
  • qhat (numpy.ndarray) – Measured directions and integer Miller indices, both shape (n, 3). Directions are normalized. Zero HKLs and coincident harmonics error.

  • hkl (numpy.ndarray) – Measured directions and integer Miller indices, both shape (n, 3). Directions are normalized. Zero HKLs and coincident harmonics error.

  • initial_reciprocal (numpy.ndarray or None) – Starting reciprocal rows, shape (3, 3), in 1/nm including 2π. None is permitted for invalid-input records, but cannot be fitted.

  • xy (numpy.ndarray or None) – Zero-based frame centroids (x, y), shape (n, 2). None gives all-NaN pixels for direction-only data.

  • peak_indices (numpy.ndarray or None) – Unique original measured-peak IDs, shape (n,). Defaults to row indices; these IDs are never renumbered after preparation/subsetting.

  • frame_id (str or int or None) – Source identity; integer and string identities remain distinct.

  • pattern_index (int) – Nonnegative source pattern rank, default zero.

  • provenance_json (str) – JSON object recording source and calibration context, default "{}".

Notes

Arrays are copied and marked read-only. provenance returns a copy. No fitted or predicted values occur here. Malformed arrays or identities raise InputError.

class lauelab.strain.StrainResult(status, message, coordinates, fit_mask, tensor, reciprocal, reference_reciprocal, rotation, cell_parameters, working_cell_parameters, measurements, predicted_qhat, predicted_xy, angular_residual_deg, n_parameters, rank, condition_number, nfev, provenance_json='{}')[source]#

Independent evidence for one pattern’s deviatoric-strain refinement.

tensor is (3,3), dimensionless tensor shear in coordinates. reciprocal and reference_reciprocal are rows in 1/nm including 2π. rotation is the fitted canonical-cell orientation. Failed fits have a NaN tensor; a finite candidate lattice may remain for diagnosis. measurements preserves selected inputs and source identities. Predictions/residuals follow that same row order. Arrays are owned and read-only; provenance access returns a copy. Convergence/support are numerical diagnostics, not calibrated experimental confidence.

status, message

Numerical outcome and diagnostic explanation. success is true only for "converged".

Type:

str

coordinates, fit_mask

Tensor frame and six effective cell-parameter flags.

Type:

str

tensor, rotation

Dimensionless strain and proper fitted canonical-cell rotation, each shape (3, 3).

Type:

numpy.ndarray

reciprocal, reference_reciprocal

Refined and reference reciprocal rows, shape (3, 3), 1/nm with 2π.

Type:

numpy.ndarray

cell_parameters, working_cell_parameters

Final volume-normalized and pre-normalization fitted cell values, respectively: a,b,c in nm, alpha,beta,gamma in degrees, shape (6,).

Type:

numpy.ndarray

measurements#

Original prepared inputs, identities and calibration snapshot.

Type:

StrainReflections

predicted_qhat, predicted_xy, angular_residual_deg

Aligned unit directions (n, 3), zero-based frame pixels (n, 2) and nonnegative angular errors in degrees (n,). Unavailable predictions are NaN.

Type:

numpy.ndarray

n_parameters, rank, nfev

Free parameter count, joint Jacobian rank and optimizer evaluations.

Type:

int

condition_number#

Joint Jacobian condition number; infinity when unavailable.

Type:

float

provenance_json#

JSON snapshot of effective model, optimizer settings and conventions.

Type:

str

tensor_in(coordinates='beamline')[source]#

Return tensor components in a named Igor frame without refitting.

property von_mises_strain#

Return Igor’s scalar sqrt(3/2 * sum(epsilon_dev**2)).

property sum_abs_epsilon_crystal#

Crystal-frame component sum; this quantity is not rotation invariant.

property predicted_energy_kev#

Calculated reflection energies using Igor’s hc=1.239841857 keV nm.

These are predictions, not measured energies. Invalid incident-beam scattering directions and unavailable fitted lattices return NaN.

property reflections#

Return an immutable notebook Table of aligned inputs/predictions.

lauelab.strain.save_strain_results(results, path, *, overwrite=False)[source]#

Save one result or an ordered collection, including failed fits.

Parameters:
  • results (StrainResult or list of StrainResult) – A result or an ordered iterable of results, including failed fits.

  • path (str or pathlib.Path) – Separate HDF5 destination. Its parent directory must exist.

  • overwrite (bool) – Replace an existing destination only when True, default False.

Returns:

pathlib.Path – Published destination.

Notes

Scientific arrays use float64; identities/HKL use integer or JSON string encodings without loss. Inputs, calibration snapshots, settings, status, frames and conventions are retained. The temporary file is validated before atomic publication. Existing destinations raise FileExistsError by default. Source indexing files cannot be overwritten by this writer.

lauelab.strain.load_strain_results(path)[source]#

Load and validate an ordered list of self-contained strain results.

Parameters:

path (str or pathlib.Path) – Standalone strain-results HDF5 file.

Returns:

list of StrainResult – Results in saved order, including failed fits. Arrays are owned and read-only exactly as with freshly computed results.

Notes

No experimental inputs or original geometry paths are reopened. Reject unsupported versions, inconsistent shapes/units/types and result tensors inconsistent with their saved lattice/reference/frame with InputError. File I/O errors propagate.

lauelab.strain.export_strain_csv(results, catalogue_path, reflections_path, *, overwrite=False)[source]#

Export separate fit-summary and reflection CSV tables.

Parameters:
  • results (StrainResult or list of StrainResult) – A result or ordered iterable, including failed fits.

  • catalogue_path (str or pathlib.Path) – Distinct destinations, one row per fit and one row per reflection, respectively. Parent directories must exist.

  • reflections_path (str or pathlib.Path) – Distinct destinations, one row per fit and one row per reflection, respectively. Parent directories must exist.

  • overwrite (bool) – Replace existing destinations only when True, default False.

Returns:

tuple of pathlib.Path – Published catalogue and reflection paths, in that order.

Notes

Column names state units. Each row records the fit frame, Biot measure, reference-volume normalization and tensor shear. Source frame IDs use JSON to preserve string versus integer identity. NaN means unavailable. Files are published independently after both are written; this is not a two-file transaction. HDF5 is the complete provenance-preserving artifact.

The numerical input arrays have shapes (n, 3) for unit measured directions and integer HKLs; reciprocal matrices have shape (3, 3) with rows in 1/nm, including 2*pi. Prepared centroids and predicted pixels have shape (n, 2) in zero-based (x, y) frame coordinates. Depth is in µm. Cell lengths are stored in nm and angles in degrees. Rotations are proper, dimensionless matrices. Tensor arrays have shape (3, 3) and use tensor shear.

Full fit results and their measurements own read-only arrays. Accessing provenance returns an independent dictionary. Pure conversion and transformation functions return NumPy arrays without inventing measurement-fit diagnostics.

Expected scientific failures return an unsuccessful result with a NaN tensor. Invalid single inputs raise InputError, ValueError or TypeError; missing/unreadable files raise their I/O errors. Serial batches record expected item-input errors and propagate shared-source or unexpected internal errors. Saving refuses existing destinations by default.