from abc import ABC, abstractmethod
import numpy as np
[docs]
class Dataset(ABC):
"""Abstract base class for tomviz Dataset objects.
The Dataset is the standard object that is passed to operators within tomviz.
It provides a unified interface for accessing and manipulating tilt image
stacks and volumetric data, including scalar arrays, spacing information,
tilt series metadata (such as tilt angles), and calibration data
(dark/white fields).
This object will always be automatically provided as the first argument in
the `transform()` function within operators. For example, for the
`Rotate` operator:
.. code-block:: python
def transform(dataset, rotation_angle=90.0, rotation_axis=0):
# ...
array = dataset.active_scalars
# ...
.. note::
Concrete subclasses of this abstract base class are internal to tomviz.
This documentation describes the public API that is accessible on
Dataset instances passed to operators and other user-facing code.
Users should interact with Dataset objects through this interface
rather than instantiating subclasses directly.
"""
@property
@abstractmethod
def active_scalars(self) -> np.ndarray:
"""The currently active scalar array data as a numpy array.
The shape and dtype depend on the specific dataset.
"""
pass
@active_scalars.setter
@abstractmethod
def active_scalars(self, v: np.ndarray):
"""Set the currently active scalar array data."""
pass
@property
@abstractmethod
def active_name(self) -> str:
"""The name of the currently active scalar array."""
pass
@property
@abstractmethod
def num_scalars(self) -> int:
"""The total number of scalar arrays stored in this dataset."""
pass
@property
@abstractmethod
def scalars_names(self) -> list[str]:
"""List containing the name of each scalar array in the dataset."""
pass
[docs]
@abstractmethod
def scalars(self, name: str | None = None) -> np.ndarray:
"""Get a scalar array by name.
:param name: The name of the scalar array to retrieve. If None, returns the
active scalar array.
:return: The requested scalar array data.
:raises KeyError: If the specified name does not exist in the dataset.
"""
pass
[docs]
@abstractmethod
def set_scalars(self, name: str, array: np.ndarray):
"""Add or update a scalar array in the dataset.
:param name: The name to assign to this scalar array. If a field with this name
already exists, it will be overwritten.
:param array: The scalar array data to store.
"""
pass
[docs]
@abstractmethod
def remove_scalars(self, name: str):
"""Remove a scalar array from the dataset.
:param name: The name of the scalar array to remove.
:raises KeyError: If the specified name does not exist in the dataset.
"""
pass
@property
@abstractmethod
def spacing(self) -> tuple[int, int, int]:
"""Voxel spacing in physical units for (x, y, z) dimensions.
Units depend on the dataset but are typically in nanometers or similar
physical units.
"""
pass
@spacing.setter
@abstractmethod
def spacing(self, v: tuple[int, int, int]):
"""Set the voxel spacing in physical units for (x, y, z) dimensions."""
pass
@property
@abstractmethod
def tilt_angles(self) -> np.ndarray | None:
"""Array of tilt angles for tomographic tilt series.
Tilt angles are typically in degrees for each projection in a tilt series.
Returns None if this is not a tilt series dataset or if tilt angles have
not been set.
"""
pass
@tilt_angles.setter
@abstractmethod
def tilt_angles(self, v: np.ndarray | None):
"""Set the tilt angles for tomographic tilt series.
Provide None to clear tilt angles.
"""
pass
@property
@abstractmethod
def tilt_axis(self) -> int | None:
"""The axis index around which tilting occurs in a tomographic tilt series.
- 0 = x-axis
- 1 = y-axis
- 2 = z-axis
- None = not applicable or not set
"""
pass
@property
@abstractmethod
def scan_ids(self) -> np.ndarray | None:
"""Array of scan IDs associated with each projection in a tilt series.
Returns None if scan IDs have not been set.
"""
pass
@scan_ids.setter
@abstractmethod
def scan_ids(self, v: np.ndarray | None):
"""Set the scan IDs for projections in a tilt series.
Provide None to clear scan IDs.
"""
pass
@property
@abstractmethod
def dark(self) -> np.ndarray | None:
"""Dark field calibration data.
Dark field images are captured with no illumination and represent the
baseline signal level of the detector (electronic noise, thermal noise, etc.).
Returns None if not available.
"""
pass
@property
@abstractmethod
def white(self) -> np.ndarray | None:
"""White field (flat field) calibration data.
White field images are captured with uniform illumination and no sample,
representing the detector response and illumination variations. Used for
flat-field correction. Returns None if not available.
"""
pass
@property
@abstractmethod
def file_name(self) -> str | None:
"""The original filename this dataset was loaded from.
Returns None if the dataset was not loaded from a file or if the
filename is not available.
"""
return self._data_source.file_name
@property
@abstractmethod
def metadata(self) -> dict:
"""Dictionary containing arbitrary metadata associated with the dataset.
Can include acquisition parameters, instrument settings, timestamps, etc.
"""
return self._data_source.metadata
[docs]
@abstractmethod
def create_child_dataset(self) -> 'Dataset':
"""Create a new child dataset derived from this dataset.
Child datasets typically share some properties with their parent but
may represent derived or processed versions of the data.
This is often used, for example, in reconstruction operators, for
creating reconstruction output objects.
:return: A new Dataset instance that is a child of this dataset.
"""
pass