Source code for pyfli.simulator.separate.sim_model_image_generator

# simulator/sim_model_image_generator.py

"""Full-image FLI dataset generation with per-ROI simulator configuration.

Provides ``FLIModelImageGenerator``, which builds a 2-D image of simulated
FLI pixel decays by assigning a ``ContinousEqSim`` (ICCD) or
``PhotonCountSim`` (photon-counting) simulator instance to each region of
interest (ROI) in an optional label mask, and simulating every pixel
individually.

Shared mask loading, simulator selection, and pixel-loop logic live in
:mod:`pyfli.simulator.image_generator_common`.
"""

import numpy as np

from ..image_generator_common import BaseFLIImageGenerator
from .main_factory_gen import ContinuousSimulator, PhotonCountSimulator


[docs] class FLIModelImageGenerator(BaseFLIImageGenerator): """Generates a full 2-D FLI image dataset with per-ROI simulator configs. Loads an optional intensity mask (to scale per-pixel photon budget) and an optional ROI label mask (to assign different simulator parameters to different regions), instantiates one ``ContinousEqSim``/``PhotonCountSim`` per ROI value, and simulates every pixel to build stacked decay/IRF/fit cubes and parameter maps. """ continuous_cls = ContinuousSimulator discrete_cls = PhotonCountSimulator include_background_roi_in_maps = False def __init__( self, irf_data, intensity_image: str | np.ndarray | None = None, roi_mask: str | np.ndarray | None = None, roi_params=None, image_shape=(32, 32), method="continuous", verbose=True, bool_mask: str | np.ndarray | None = None, ): """Loads masks and instantiates one simulator per ROI. Args: irf_data: IRF data (1-D trace or 3-D IRF stack). If 3-D, a per-pixel IRF slice is used during simulation; otherwise a single IRF (picked via ``irf_picker``) is shared across pixels. intensity_image: Optional color or grayscale image (any bit depth) — a path to a PNG/TIFF/etc. file, or an already-loaded array — used to derive a per-pixel binary mask: any pixel with a nonzero value (any nonzero color channel, or a nonzero grayscale value) is foreground (1.0); pure zero/black is background (0.0). An already-binary source passes through unchanged. If omitted, a mask of ones with shape ``image_shape`` is used (no masking). roi_mask: Optional ROI label mask — a path to a grayscale/label image file, or an already-loaded integer-labeled array — where values 0, 1, 2, ... identify different ROIs; resized (nearest-neighbor) to match the intensity mask shape if needed. If omitted, all pixels belong to ROI 0. roi_params: Optional list of per-ROI config dicts (indexed by ROI value) forwarded as ``**cfg`` to the simulator constructor for that ROI; may include a ``sensor_type`` key. ROI values without a matching entry get an empty config. image_shape: Fallback ``(H, W)`` image shape when no intensity image is provided. method: Simulation method string (case-insensitive); stored lower-cased as ``self.method``. Used only as the default ``sensor_type`` for ROIs whose config doesn't set one: ``'continuous'`` defaults to ``'continuous'`` (selecting ``ContinousEqSim``); any other value defaults to ``'discrete'`` (selecting ``PhotonCountSim``). Each ROI's effective ``sensor_type`` (explicit or defaulted) is what actually decides which of the two classes is used for that ROI. verbose: If True, prints progress info and shows the tqdm progress bar during ``generate_image``. bool_mask: Optional boolean mask of shape ``image_shape`` used to zero out pixels outside the mask in the final output cubes/maps — a path to an image file (binarized the same way as ``intensity_image``), or an already-loaded boolean/numeric array. """ super().__init__( irf_data=irf_data, intensity_image=intensity_image, roi_mask=roi_mask, roi_params=roi_params, image_shape=image_shape, method=method, verbose=verbose, bool_mask=bool_mask, )