Skip to content

phaser.state

phaser.state

ProbeState module-attribute

ObjectState module-attribute

Patterns

Source code in phaser/state.py
@tree_dataclass
class Patterns:
    patterns: NDArray[numpy.floating]
    """Raw diffraction patterns, with 0-frequency sample in corner"""
    pattern_mask: NDArray[numpy.floating]
    """Mask indicating which portions of the diffraction patterns contain data."""

    def to_numpy(self) -> Self:
        return self.__class__(
            to_numpy(self.patterns), to_numpy(self.pattern_mask)
        )

patterns instance-attribute

patterns: NDArray[floating]

Raw diffraction patterns, with 0-frequency sample in corner

pattern_mask instance-attribute

pattern_mask: NDArray[floating]

Mask indicating which portions of the diffraction patterns contain data.

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        to_numpy(self.patterns), to_numpy(self.pattern_mask)
    )

IterState

Source code in phaser/state.py
@tree_dataclass
class IterState:
    engine_num: int
    """Engine number. 1-indexed (0 means before any reconstruction)."""
    engine_iter: int
    """Iteration number on this engine. 1-indexed (0 means before any iterations)."""
    total_iter: int
    """Total iteration number. 1-indexed (0 means before any iterations)."""

    n_engine_iters: int | None = None
    """Total number of iterations in this engine."""
    n_total_iters: int | None = None
    """Total number of iterations in the reconstruction."""

    def to_numpy(self) -> Self:
        return self.__class__(
            int(self.engine_num), int(self.engine_iter), int(self.total_iter),
            int(self.n_engine_iters) if self.n_engine_iters else None,
            int(self.n_total_iters) if self.n_total_iters else None,
        )

    def copy(self) -> Self:
        import copy
        return copy.deepcopy(self)

    @staticmethod
    def empty() -> 'IterState':
        return IterState(0, 0, 0)

engine_num instance-attribute

engine_num: int

Engine number. 1-indexed (0 means before any reconstruction).

engine_iter instance-attribute

engine_iter: int

Iteration number on this engine. 1-indexed (0 means before any iterations).

total_iter instance-attribute

total_iter: int

Total iteration number. 1-indexed (0 means before any iterations).

n_engine_iters class-attribute instance-attribute

n_engine_iters: int | None = None

Total number of iterations in this engine.

n_total_iters class-attribute instance-attribute

n_total_iters: int | None = None

Total number of iterations in the reconstruction.

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        int(self.engine_num), int(self.engine_iter), int(self.total_iter),
        int(self.n_engine_iters) if self.n_engine_iters else None,
        int(self.n_total_iters) if self.n_total_iters else None,
    )

copy

copy() -> Self
Source code in phaser/state.py
def copy(self) -> Self:
    import copy
    return copy.deepcopy(self)

empty staticmethod

empty() -> IterState
Source code in phaser/state.py
@staticmethod
def empty() -> 'IterState':
    return IterState(0, 0, 0)

PixelatedProbeState

Source code in phaser/state.py
@tree_dataclass(static_fields=('sampling', 'meta', 'ty'))
class PixelatedProbeState:
    sampling: Sampling
    """Probe coordinate system. See `Sampling` for more details."""
    data: NDArray[numpy.complexfloating]
    """Probe wavefunction, in realspace. Shape (modes, y, x)"""

    meta: frozendict[str, t.Any] = field(default_factory=frozendict)
    ty: t.Literal['pixelated'] = 'pixelated'

    def resample(
        self, new_samp: Sampling,
        rotation: float = 0.0,
        order: int = 1,
        mode: '_InterpBoundaryMode' = 'grid-constant',
    ) -> Self:
        new_data = self.sampling.resample(
            self.data, new_samp,
            rotation=rotation,
            order=order,
            mode=mode,
        )
        return self.__class__(new_samp, new_data, self.meta)

    def to_xp(self, xp: t.Any) -> Self:
        return self.__class__(
            self.sampling, xp.asarray(self.data), self.meta
        )

    def to_numpy(self) -> Self:
        return self.__class__(
            self.sampling, to_numpy(self.data), self.meta
        )

    def copy(self) -> Self:
        import copy
        return copy.deepcopy(self)

sampling instance-attribute

sampling: Sampling

Probe coordinate system. See Sampling for more details.

data instance-attribute

Probe wavefunction, in realspace. Shape (modes, y, x)

meta class-attribute instance-attribute

meta: frozendict[str, Any] = field(
    default_factory=frozendict
)

ty class-attribute instance-attribute

ty: Literal['pixelated'] = 'pixelated'

resample

resample(
    new_samp: Sampling,
    rotation: float = 0.0,
    order: int = 1,
    mode: _InterpBoundaryMode = "grid-constant",
) -> Self
Source code in phaser/state.py
def resample(
    self, new_samp: Sampling,
    rotation: float = 0.0,
    order: int = 1,
    mode: '_InterpBoundaryMode' = 'grid-constant',
) -> Self:
    new_data = self.sampling.resample(
        self.data, new_samp,
        rotation=rotation,
        order=order,
        mode=mode,
    )
    return self.__class__(new_samp, new_data, self.meta)

to_xp

to_xp(xp: Any) -> Self
Source code in phaser/state.py
def to_xp(self, xp: t.Any) -> Self:
    return self.__class__(
        self.sampling, xp.asarray(self.data), self.meta
    )

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        self.sampling, to_numpy(self.data), self.meta
    )

copy

copy() -> Self
Source code in phaser/state.py
def copy(self) -> Self:
    import copy
    return copy.deepcopy(self)

PixelatedObjectState

Source code in phaser/state.py
@tree_dataclass(static_fields=('sampling', 'meta', 'ty'))
class PixelatedObjectState:
    sampling: ObjectSampling
    """Object coordinate system. See `ObjectSampling` for more details."""
    data: NDArray[numpy.complexfloating]
    """Object wavefunction. Shape (z, y, x)"""
    thicknesses: NDArray[numpy.floating]
    """
    Slice thicknesses (in length units).
    Length < 2 for single slice, equal to the number of slices otherwise.
    """

    meta: frozendict[str, t.Any] = field(default_factory=frozendict)
    ty: t.Literal['pixelated'] = 'pixelated'

    def to_xp(self, xp: t.Any) -> Self:
        return self.__class__(
            self.sampling, xp.asarray(self.data), xp.asarray(self.thicknesses), self.meta,
        )

    def to_numpy(self) -> Self:
        return self.__class__(
            self.sampling, to_numpy(self.data), to_numpy(self.thicknesses), self.meta,
        )

    def zs(self) -> NDArray[numpy.floating]:
        xp = get_array_module(self.thicknesses)
        if len(self.thicknesses) < 2:
            return xp.asarray([0.], dtype=self.thicknesses.dtype)
        return xp.cumsum(self.thicknesses) - self.thicknesses

    def copy(self) -> Self:
        import copy
        return copy.deepcopy(self)

sampling instance-attribute

sampling: ObjectSampling

Object coordinate system. See ObjectSampling for more details.

data instance-attribute

Object wavefunction. Shape (z, y, x)

thicknesses instance-attribute

thicknesses: NDArray[floating]

Slice thicknesses (in length units). Length < 2 for single slice, equal to the number of slices otherwise.

meta class-attribute instance-attribute

meta: frozendict[str, Any] = field(
    default_factory=frozendict
)

ty class-attribute instance-attribute

ty: Literal['pixelated'] = 'pixelated'

to_xp

to_xp(xp: Any) -> Self
Source code in phaser/state.py
def to_xp(self, xp: t.Any) -> Self:
    return self.__class__(
        self.sampling, xp.asarray(self.data), xp.asarray(self.thicknesses), self.meta,
    )

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        self.sampling, to_numpy(self.data), to_numpy(self.thicknesses), self.meta,
    )

zs

zs() -> NDArray[floating]
Source code in phaser/state.py
def zs(self) -> NDArray[numpy.floating]:
    xp = get_array_module(self.thicknesses)
    if len(self.thicknesses) < 2:
        return xp.asarray([0.], dtype=self.thicknesses.dtype)
    return xp.cumsum(self.thicknesses) - self.thicknesses

copy

copy() -> Self
Source code in phaser/state.py
def copy(self) -> Self:
    import copy
    return copy.deepcopy(self)

ScanState

Source code in phaser/state.py
@tree_dataclass(static_fields=('meta',))
class ScanState:
    data: NDArray[numpy.floating]
    """Scan coordinates (y, x), in length units. Shape (..., 2)"""
    initial: NDArray[numpy.floating]
    """Inital scan coordinates (y, x), in length units."""
    tilt: NDArray[numpy.floating] | None = None
    """Tilt angles (y, x) per scan position, in mrad. Shape (..., 2)"""

    meta: frozendict[str, t.Any] = field(default_factory=frozendict)

    def to_xp(self, xp: t.Any) -> Self:
        return self.__class__(
            xp.asarray(self.data),
            xp.asarray(self.initial),
            None if self.tilt is None else xp.asarray(self.tilt),
            self.meta,
        )

    def to_numpy(self) -> Self:
        return self.__class__(
            to_numpy(self.data),
            to_numpy(self.initial),
            None if self.tilt is None else to_numpy(self.tilt),
            self.meta,
        )

    def copy(self) -> Self:
        import copy
        return copy.deepcopy(self)

data instance-attribute

Scan coordinates (y, x), in length units. Shape (..., 2)

initial instance-attribute

initial: NDArray[floating]

Inital scan coordinates (y, x), in length units.

tilt class-attribute instance-attribute

tilt: NDArray[floating] | None = None

Tilt angles (y, x) per scan position, in mrad. Shape (..., 2)

meta class-attribute instance-attribute

meta: frozendict[str, Any] = field(
    default_factory=frozendict
)

to_xp

to_xp(xp: Any) -> Self
Source code in phaser/state.py
def to_xp(self, xp: t.Any) -> Self:
    return self.__class__(
        xp.asarray(self.data),
        xp.asarray(self.initial),
        None if self.tilt is None else xp.asarray(self.tilt),
        self.meta,
    )

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        to_numpy(self.data),
        to_numpy(self.initial),
        None if self.tilt is None else to_numpy(self.tilt),
        self.meta,
    )

copy

copy() -> Self
Source code in phaser/state.py
def copy(self) -> Self:
    import copy
    return copy.deepcopy(self)

ProgressState

Source code in phaser/state.py
@tree_dataclass
class ProgressState:
    iters: list[int] = field(default_factory=list)
    """Iterations error measurements were taken at."""
    values: list[float] = field(default_factory=list)
    """Detector error measurements at those iterations"""

    def copy(self) -> Self:
        import copy
        return copy.deepcopy(self)

iters class-attribute instance-attribute

iters: list[int] = field(default_factory=list)

Iterations error measurements were taken at.

values class-attribute instance-attribute

values: list[float] = field(default_factory=list)

Detector error measurements at those iterations

copy

copy() -> Self
Source code in phaser/state.py
def copy(self) -> Self:
    import copy
    return copy.deepcopy(self)

ReconsState

Source code in phaser/state.py
@tree_dataclass(kw_only=True, drop_fields=('progress',))
class ReconsState:
    iter: IterState
    wavelength: Float

    probe: ProbeState
    object: ObjectState
    scan: ScanState

    progress: dict[str, ProgressState] = field(default_factory=dict)

    def to_xp(self, xp: t.Any) -> Self:
        return self.__class__(
            iter=self.iter,
            probe=self.probe.to_xp(xp),
            object=self.object.to_xp(xp),
            scan=self.scan.to_xp(xp),
            progress=self.progress,
            wavelength=self.wavelength,
        )

    def to_numpy(self) -> Self:
        return self.__class__(
            iter=self.iter.to_numpy(),
            probe=self.probe.to_numpy(),
            object=self.object.to_numpy(),
            scan=self.scan.to_numpy(),
            progress=self.progress,
            wavelength=float(self.wavelength),
        )

    def copy(self) -> Self:
        import copy
        return copy.deepcopy(self)

    def write_hdf5(self, file: 'HdfLike'):
        from phaser.utils.io import hdf5_write_state
        hdf5_write_state(self, file)

    @staticmethod
    def read_hdf5(file: 'HdfLike') -> 'ReconsState':
        from phaser.utils.io import hdf5_read_state
        return hdf5_read_state(file).to_complete()

iter instance-attribute

iter: IterState

wavelength instance-attribute

wavelength: Float

probe instance-attribute

probe: ProbeState

object instance-attribute

object: ObjectState

scan instance-attribute

scan: ScanState

progress class-attribute instance-attribute

progress: dict[str, ProgressState] = field(
    default_factory=dict
)

to_xp

to_xp(xp: Any) -> Self
Source code in phaser/state.py
def to_xp(self, xp: t.Any) -> Self:
    return self.__class__(
        iter=self.iter,
        probe=self.probe.to_xp(xp),
        object=self.object.to_xp(xp),
        scan=self.scan.to_xp(xp),
        progress=self.progress,
        wavelength=self.wavelength,
    )

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        iter=self.iter.to_numpy(),
        probe=self.probe.to_numpy(),
        object=self.object.to_numpy(),
        scan=self.scan.to_numpy(),
        progress=self.progress,
        wavelength=float(self.wavelength),
    )

copy

copy() -> Self
Source code in phaser/state.py
def copy(self) -> Self:
    import copy
    return copy.deepcopy(self)

write_hdf5

write_hdf5(file: HdfLike)
Source code in phaser/state.py
def write_hdf5(self, file: 'HdfLike'):
    from phaser.utils.io import hdf5_write_state
    hdf5_write_state(self, file)

read_hdf5 staticmethod

read_hdf5(file: HdfLike) -> ReconsState
Source code in phaser/state.py
@staticmethod
def read_hdf5(file: 'HdfLike') -> 'ReconsState':
    from phaser.utils.io import hdf5_read_state
    return hdf5_read_state(file).to_complete()

PartialReconsState

Source code in phaser/state.py
@tree_dataclass(kw_only=True, static_fields=('progress',))
class PartialReconsState:
    iter: IterState | None = None
    wavelength: Float | None = None

    probe: ProbeState | None = None
    object: ObjectState | None = None
    scan: ScanState | None = None
    progress: dict[str, ProgressState] | None = None

    def to_numpy(self) -> Self:
        return self.__class__(
            iter=self.iter.to_numpy() if self.iter is not None else None,
            probe=self.probe.to_numpy() if self.probe is not None else None,
            object=self.object.to_numpy() if self.object is not None else None,
            scan=self.scan.to_numpy() if self.scan is not None else None,
            wavelength=float(self.wavelength) if self.wavelength is not None else None,
            progress=self.progress,
        )

    def to_complete(self) -> ReconsState:
        missing = tuple(filter(lambda k: getattr(self, k) is None, ('probe', 'object', 'scan', 'wavelength')))
        if len(missing):
            raise ValueError(f"ReconsState missing {', '.join(map(repr, missing))}")

        progress = self.progress if self.progress is not None else {}
        iter = self.iter if self.iter is not None else IterState.empty()

        return ReconsState(
            wavelength=t.cast(Float, self.wavelength),
            probe=t.cast(ProbeState, self.probe),
            object=t.cast(ObjectState, self.object),
            scan=t.cast(ScanState, self.scan),
            progress=progress, iter=iter,
        )

    def write_hdf5(self, file: 'HdfLike'):
        from phaser.utils.io import hdf5_write_state
        hdf5_write_state(self, file)

    @staticmethod
    def read_hdf5(file: 'HdfLike') -> 'PartialReconsState':
        from phaser.utils.io import hdf5_read_state
        return hdf5_read_state(file)

iter class-attribute instance-attribute

iter: IterState | None = None

wavelength class-attribute instance-attribute

wavelength: Float | None = None

probe class-attribute instance-attribute

probe: ProbeState | None = None

object class-attribute instance-attribute

object: ObjectState | None = None

scan class-attribute instance-attribute

scan: ScanState | None = None

progress class-attribute instance-attribute

progress: dict[str, ProgressState] | None = None

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        iter=self.iter.to_numpy() if self.iter is not None else None,
        probe=self.probe.to_numpy() if self.probe is not None else None,
        object=self.object.to_numpy() if self.object is not None else None,
        scan=self.scan.to_numpy() if self.scan is not None else None,
        wavelength=float(self.wavelength) if self.wavelength is not None else None,
        progress=self.progress,
    )

to_complete

to_complete() -> ReconsState
Source code in phaser/state.py
def to_complete(self) -> ReconsState:
    missing = tuple(filter(lambda k: getattr(self, k) is None, ('probe', 'object', 'scan', 'wavelength')))
    if len(missing):
        raise ValueError(f"ReconsState missing {', '.join(map(repr, missing))}")

    progress = self.progress if self.progress is not None else {}
    iter = self.iter if self.iter is not None else IterState.empty()

    return ReconsState(
        wavelength=t.cast(Float, self.wavelength),
        probe=t.cast(ProbeState, self.probe),
        object=t.cast(ObjectState, self.object),
        scan=t.cast(ScanState, self.scan),
        progress=progress, iter=iter,
    )

write_hdf5

write_hdf5(file: HdfLike)
Source code in phaser/state.py
def write_hdf5(self, file: 'HdfLike'):
    from phaser.utils.io import hdf5_write_state
    hdf5_write_state(self, file)

read_hdf5 staticmethod

read_hdf5(file: HdfLike) -> PartialReconsState
Source code in phaser/state.py
@staticmethod
def read_hdf5(file: 'HdfLike') -> 'PartialReconsState':
    from phaser.utils.io import hdf5_read_state
    return hdf5_read_state(file)

PreparedRecons

Source code in phaser/state.py
@tree_dataclass(static_fields=('name', 'observer'))
class PreparedRecons:
    patterns: Patterns
    state: ReconsState
    name: str
    observer: 'ObserverSet'

    def to_xp(self, xp: t.Any) -> Self:
        return self.__class__(
            self.patterns,
            self.state.to_xp(xp),
            self.name, self.observer,
        )

    def to_numpy(self) -> Self:
        return self.__class__(
            self.patterns.to_numpy(), self.state.to_numpy(), self.name, self.observer
        )

    def with_observer(self, observer: t.Union['Observer', t.Iterable['Observer']]) -> Self:
        from phaser.observer import Observer, ObserverSet

        observers = list(self.observer.inner)
        if isinstance(observer, Observer):
            observers.append(observer)
        else:
            observers.extend(observer)

        return self.__class__(self.patterns, self.state, self.name, ObserverSet(observers))

patterns instance-attribute

patterns: Patterns

state instance-attribute

state: ReconsState

name instance-attribute

name: str

observer instance-attribute

observer: ObserverSet

to_xp

to_xp(xp: Any) -> Self
Source code in phaser/state.py
def to_xp(self, xp: t.Any) -> Self:
    return self.__class__(
        self.patterns,
        self.state.to_xp(xp),
        self.name, self.observer,
    )

to_numpy

to_numpy() -> Self
Source code in phaser/state.py
def to_numpy(self) -> Self:
    return self.__class__(
        self.patterns.to_numpy(), self.state.to_numpy(), self.name, self.observer
    )

with_observer

with_observer(
    observer: Union[Observer, Iterable[Observer]],
) -> Self
Source code in phaser/state.py
def with_observer(self, observer: t.Union['Observer', t.Iterable['Observer']]) -> Self:
    from phaser.observer import Observer, ObserverSet

    observers = list(self.observer.inner)
    if isinstance(observer, Observer):
        observers.append(observer)
    else:
        observers.extend(observer)

    return self.__class__(self.patterns, self.state, self.name, ObserverSet(observers))