Results#

FrameResult contains the output and provenance for one processed frame. Native allocations are released before the object is returned. Peak and pattern data are copied into NumPy arrays.

Frame-level status#

Use these properties for a summary:

Property

Meaning

indexed

True when at least one pattern was identified

n_peaks

Number of detected peaks

n_indexed

Total assignments across all patterns

n_patterns

Number of identified patterns

elapsed_seconds

Sum of recorded peak-search and orientation-indexing times

n_indexed counts assignments, not necessarily unique peaks. Use indexed_peak_indices when you need the unique set of peaks assigned to any pattern.

Peaks#

result.peaks is a one-dimensional structured array with one row per detected peak.

Field

Shape

Units

Meaning

fit_x

scalar

frame px

Zero-based fitted x coordinate

fit_y

scalar

frame px

Zero-based fitted y coordinate

intens

scalar

detector counts

Fitted peak intensity

integral

scalar

implementation-defined

Integrated fitted intensity

hwhm_x

scalar

px

Fitted half-width along the x fit axis

hwhm_y

scalar

px

Fitted half-width along the y fit axis

tilt

scalar

deg

Fitted peak tilt

chisq

scalar

dimensionless

Normalized fit residual reported by peak search

background

scalar

detector counts

Fitted background level

qhat

(3,)

dimensionless

Unit scattering vector in the 34-ID-E laboratory convention

Extract ordinary arrays by field name:

import numpy as np

xy = np.column_stack((result.peaks["fit_x"], result.peaks["fit_y"]))
qhat = result.peaks["qhat"]
intensity = result.peaks["intens"]

A frame coordinate (x, y) corresponds to NumPy access image[y, x]. Fitted coordinates are floating-point values and can lie between pixel centers.

Patterns#

Each Pattern represents one orientation returned by the native indexer.

Field

Shape

Units

Meaning

euler_deg

(3,)

deg

Euler-angle representation of the orientation

rotation

(3, 3)

dimensionless

Orientation rotation matrix

reciprocal

(3, 3)

1/nm

Reciprocal-lattice matrix, with a*, b*, and c* as rows

goodness

scalar

implementation-defined

Native pattern goodness score

rms_error_deg

scalar

deg

Root-mean-square angular indexing error

hkl

(n, 3)

Miller indices

Assigned reflection indices

pk_index

(n,)

array indices

Zero-based indices into result.peaks

err_deg

(n,)

deg

Angular error for each assignment

energy_kev

(n,)

keV

Photon energy for each assignment

pred_intens

(n,)

implementation-defined

Predicted intensity for each assignment

pattern.n_indexed is len(pattern.pk_index). Rows in hkl, err_deg, energy_kev, and pred_intens correspond to the same assignments.

The reciprocal basis follows the native setDirectRecip convention. Its direct basis has c parallel to positive z, b in the yz plane, and a completing the right-handed basis. Reciprocal vectors include the 2*pi factor and are stored as rows in 1/nm, so q = hkl @ pattern.reciprocal.

Before constructing this basis, the native crystal model forces ideal metric constraints from the space group: cubic forces equal lengths and right angles; hexagonal forces a = b, alpha = beta = 90 deg, and gamma = 120 deg; tetragonal forces a = b and right angles; orthorhombic forces right angles; and monoclinic forces alpha = gamma = 90 deg. Trigonal cells use hexagonal axes when the supplied angles are already 90, 90, 120 deg within native tolerance; otherwise they use a rhombohedral cell with equal lengths and angles.

This convention also defines rotations reconstructed while loading XML. Compared with releases that used the JZT reference basis, XML-derived orientations for non-orthogonal cells change by the fixed rotation between those bases, including 30 degrees about c for hexagonal cells. Native live results and newly loaded XML now use the same basis. Prefer the full rotation matrix when exchanging orientations with other software, and confirm that software’s basis convention.

Indexed and unindexed peaks#

Pattern indices refer to result.peaks:

for pattern in result.patterns:
    measured = result.peaks[pattern.pk_index]
    assert len(measured) == pattern.n_indexed

result.indexed_peak_indices returns sorted, unique indices assigned to at least one pattern. result.unindexed_peak_indices returns the complement over all detected peaks.

indexed = result.peaks[result.indexed_peak_indices]
unindexed = result.peaks[result.unindexed_peak_indices]

These arrays are useful when a peak can appear in more than one pattern or when n_indexed must not be treated as a unique count.

Frame statistics and timing#

The result records:

  • threshold_used

  • total_sum

  • sum_above_threshold

  • num_above_threshold

  • threshold_ratio

  • peak_minwidth

  • peak_maxwidth

  • peak_max_cent_to_fit

  • peak_boxsize

  • peaksearch_seconds

  • indexing_seconds

total_sum, sum_above_threshold, and num_above_threshold exclude masked pixels and describe the raw input image. With PeakParams(smooth=True), smoothing applies to peak detection and fitting; an automatically derived threshold_used is then computed from the smoothed image (matching the LaueGo peaksearch program), while the sums above it still count raw pixels.

indexing_seconds measures the orientation-indexing section. It includes the negligible branch when no crystal is supplied or too few peaks are present. Pixel-to-q conversion is not included in either timing field. elapsed_seconds therefore does not measure complete call latency.

metadata contains supplied values and recognized HDF5 provenance. input_image is the HDF5 path for file input and None for an in-memory array. image_shape, start, group, and depth record the frame geometry used by the call.

Retained images#

index_frame() and Indexer.index() retain a contiguous uint16 image by default. A retained image can alias a C-contiguous array supplied by the caller. Native smoothing uses a separate working copy, so result.image remains the unsmoothed input. Set keep_image=False when downstream work only needs processed data.

Indexer.index_many() does not retain images by default. This avoids keeping one detector-sized array per result.

The FrameResult dataclass is frozen, but its arrays and metadata mapping can remain mutable. Copy them before modification when the unchanged result must remain available.

Write XML#

Write one result in the established Laue XML format:

result.write_xml("indexed-frame.xml")

Write several results in iteration order:

indexer.write_many_xml(results, "indexed-scan.xml")

Existing destination files are replaced. These methods serialize a snapshot captured when each result was created. Later mutations to result arrays do not update that snapshot.

Compatibility conversion#

result.to_step() returns a deep copy of the internal LaueGo XML model. This method is a compatibility bridge for code that must interact with that representation. It is not the preferred analysis model, and the serialization classes are not part of the curated public API.

Empty results#

No detected peaks is a valid result. The structured peak array is empty and no patterns are returned.

Detected peaks with no identified orientation is also valid. n_peaks is positive, patterns is empty, and indexed is False.

Exceptions represent invalid input, allocation failure, or failure inside a native stage. Do not convert a scientifically empty result into an exception unless your application requires that policy.