ptyrad.analysis.analyzer#

User-facing wrapper around a PtyRAD model.hdf5 output.

Analyzer is a thin delegator: every get_* method is a 1-2 line call into the pure functions in ptyrad.analysis.extract, and every plotting method forwards directly to the existing helpers in ptyrad.plotting. Model rebuild is lazy via Analyzer.build_model().

Typical use:

from ptyrad.analysis import Analyzer

a = Analyzer("path/to/model_iter0100.hdf5")
obj   = a.get_object(fov="crop")          # complex (omode, Nz, Ny, Nx)
probe = a.get_probe(space="fourier")      # complex (pmode, Ny, Nx)
pos   = a.get_probe_positions(units="Ang")  # (N, 2) in Ångströms
a.plot_dashboard()

model = a.build_model(device="cpu")   # rebuild for forward passes
dp    = a.forward([0, 1, 2, 3])

Classes

Analyzer(source)

Wrapper around a loaded PtyRAD model.hdf5 reconstruction.

class ptyrad.analysis.analyzer.Analyzer(source)[source]#

Bases: object

Wrapper around a loaded PtyRAD model.hdf5 reconstruction.

Parameters:

source (str | os.PathLike | dict) – Either a path to a .hdf5 / .h5 reconstruction output (the file is loaded via ptyrad.io.load.load_ptyrad()) or an already-loaded dict. When constructed from a dict the analyzer cannot retrieve HDF5 root attributes (provenance); that path returns None from provenance with a one-time UserWarning.

Notes

Construction is cheap: only the HDF5 datasets/groups are loaded into a nested dict (provenance is deferred, the PtychoModel is not built until build_model() is called).

The class is a thin delegator: every get_* method is a one-line forward to the corresponding pure function in ptyrad.analysis.extract, so users who prefer raw dicts can skip the class entirely and call the functions directly.

property data: dict#
property path: str | None#
property opt_tensors: dict#
property model_attrs: dict#
property params: dict#
property provenance: dict | None#

Lazy-loaded provenance dict; None if unavailable.

Reads the provenance_json root HDF5 attr via extract.extract_provenance() on first access and caches the result. Returns None (with a one-time UserWarning) when the Analyzer was constructed from an in-memory dict, since root attrs are not preserved by ptyrad.io.load.load_ptyrad().

property dx: float#
property dk: float#
property lambd: float#
property probe_shape: tuple[int, int]#
property pmode: int#
property omode: int#
property nslice: int#
property is_multislice: bool#
property niter: int | None#
property model#

The cached PtychoModel instance built via build_model(), or None.

get_object(fov='full', *, as_torch=False, device='cpu')[source]#

Complex object obja * exp(1j * objp); see extract.extract_object().

Parameters:
  • fov (Literal['full', 'crop'])

  • as_torch (bool)

  • device (str)

get_object_amplitude(fov='full', *, as_torch=False, device='cpu')[source]#

Object amplitude obja; see extract.extract_object_amplitude().

Parameters:
  • fov (Literal['full', 'crop'])

  • as_torch (bool)

  • device (str)

get_object_phase(fov='full', *, as_torch=False, device='cpu')[source]#

Object phase objp; see extract.extract_object_phase().

Parameters:
  • fov (Literal['full', 'crop'])

  • as_torch (bool)

  • device (str)

get_probe(space='real', *, as_torch=False, device='cpu')[source]#

Complex probe modes; see extract.extract_probe().

Parameters:
  • space (Literal['real', 'fourier'])

  • as_torch (bool)

  • device (str)

get_probe_positions(fov='full', *, target='probe', units='px', include_sub_px_shifts=True, as_torch=False, device='cpu')[source]#

Probe-center or crop-window positions; see extract.extract_probe_positions().

include_sub_px_shifts controls whether the optimized probe_pos_shifts offsets are included. target='probe' returns probe centers; target='crop' returns crop-window top-left positions, which can be negative when combined with fov='crop'.

Power users who hold only a sub-dict (e.g. just optimizable_tensors from a streaming loader) should call the standalone extract.extract_probe_positions() with explicit model_attrs.

Parameters:
  • fov (Literal['full', 'crop'])

  • target (Literal['probe', 'crop'])

  • units (Literal['px', 'pixel', 'Ang'])

  • include_sub_px_shifts (bool)

  • as_torch (bool)

  • device (str)

get_loss_curves()[source]#

Loss-history fields; see extract.extract_loss_curves().

Return type:

dict

get_keys()[source]#

Flat dotted-key listing of the loaded data dict.

Return type:

list[str]

get_fov_bbox()[source]#

Inclusive scanned-FOV bbox over probe-center positions.

Returns (y_min, y_max, x_min, x_max) matching the slicing of the saved *_crop TIFFs.

Return type:

tuple[int, int, int, int]

plot_loss(**kw)[source]#

Plot the loss curve via ptyrad.plotting.plot_loss_curves().

plot_probe(space='real', amp_or_phase='amplitude', **kw)[source]#

Plot probe modes via ptyrad.plotting.plot_probe_modes().

space and amp_or_phase map directly to that function’s real_or_fourier and amp_or_phase arguments.

Parameters:
  • space (Literal['real', 'fourier'])

  • amp_or_phase (Literal['amplitude', 'phase'])

plot_positions(fov='full', *, target='probe', **kw)[source]#

Scatter scan positions via ptyrad.plotting.plot_scan_positions().

See get_probe_positions() for the fov / target semantics.

Parameters:
  • fov (Literal['full', 'crop'])

  • target (Literal['probe', 'crop'])

plot_tilts(**kw)[source]#

Plot per-position object tilts via ptyrad.plotting.plot_obj_tilts().

plot_slice_thickness(**kw)[source]#

Plot slice-thickness evolution via ptyrad.plotting.plot_slice_thickness().

plot_dashboard(**kw)[source]#

Convergence dashboard via ptyrad.plotting.plot_convergence_dashboard().

Pulls loss_iters, lr_iters, dz_iters, avg_tilt_iters, convergence_iters straight from the loaded dict — no rebuilt model required.

plot_summary(indices, **kw)[source]#

Summary figure via ptyrad.plotting.plot_summary().

Requires a rebuilt model — call build_model() first. output_path is read from kw (default '.').

plot_forward_pass(indices, *, dp_power=0.5, **kw)[source]#

Forward-pass diagnostic via ptyrad.plotting.plot_forward_pass().

Requires a rebuilt model — call build_model() first.

Parameters:

dp_power (float)

build_model(device='cuda', overrides=None)[source]#

Rebuild a PtychoModel from the saved params and weights.

Runs ptyrad.init.initializer.Initializer against data['params']['init_params'] to construct the init_variables dict, instantiates the model, copies the saved optimizable_tensors (obja, objp, probe, probe_pos_shifts, obj_tilts, slice_thickness) into the fresh model, and finally restores the iteration histories (loss_iters, dz_iters, lr_iters, avg_tilt_iters, convergence_iters) so the rebuilt model is plottable via plot_summary() / plot_forward_pass() and suitable for forward-pass diagnostics.

The model and its init_variables are cached on self after a successful build.

Parameters:
  • device (str) – Torch device string (e.g. 'cpu', 'cuda', 'cuda:0').

  • overrides (Mapping[str, Any] | None) –

    Dict deep-merged into params before initialization. The common use is to redirect the measurement file path when the original measurement data has moved:

    a.build_model(
        overrides={'init_params': {'meas_params': {'path': '/new/path.raw'}}}
    )
    

Raises:

FileNotFoundError – If init_params['meas_params']['path'] does not resolve. The error names the missing path explicitly rather than failing deep in the dataloader.

forward(indices, *, return_raw=False, enable_grad=False)[source]#

Run a forward pass on the rebuilt model.

Thin wrapper around self.model.forward(indices, return_raw=...). Requires build_model() to have been called first; indices is coerced to np.ndarray before being passed through.

By default this runs under torch.no_grad() because analysis and plotting calls usually do not need autograd graphs. Set enable_grad=True to record gradients for offline custom losses or refinement experiments.

Parameters:
  • return_raw (bool)

  • enable_grad (bool)