Skip to content

Core Modules

ImageAnalyzer API

image_analysis.base.ImageAnalyzer

ImageAnalyzer(**config)

Abstract base class for device-specific image image_analyzer.

Derived classes should implement: - analyze_image() - init()

Initialize the ImageAnalyzer with optional background and keyword configuration parameters.

As the same ImageAnalyzer instance can be applied to many images, the image is not passed in the constructor but in analyze_image. The image, or value should be passed as a parameter, however.

The init() method of derived classes should define all the parameters for that derived class, including type annotations, defaults, and documentation. These are all used for LivePostProcessing for example.

It should also call super().init()

Parameters:

Name Type Description Default
**config

Optional configuration kwargs.

{}

Methods:

Name Description
analyze_image

Calculate metrics from an image or list of images.

analyze_image_file

Method to enable the use of a file path (or list of paths) rather than arrays.

load_image

Load an image from a path, or multiple images from a list of paths.

Source code in image_analysis/base.py
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def __init__(self, **config):
    """Initialize the ImageAnalyzer with optional background and keyword configuration parameters.

    As the same ImageAnalyzer instance can be applied to many images,
    the image is not passed in the constructor but in analyze_image. The
    image, or value should be passed as a parameter, however.

    The __init__() method of derived classes should define all the
    parameters for that derived class, including type annotations,
    defaults, and documentation. These are all used for LivePostProcessing
    for example.

    It should also call super().__init__()

    Parameters
    ----------
    **config :
        Optional configuration kwargs.
    """
    pass

analyze_image

analyze_image(image: Union[Array1D, Array2D, list[Array1D], list[Array2D]], auxiliary_data: Optional[dict] = None) -> ImageAnalyzerResult

Calculate metrics from an image or list of images.

This function should be implemented by each device's ImageAnalyzer subclass, to run on an image from that device (obviously).

Should take full-size (i.e. uncropped) image.

For multi-device analyzers (e.g. multi-camera diagnostics), a list of arrays may be passed — one per device. The analyzer is responsible for combining them as needed and returning a single result.

Parameters:

Name Type Description Default
image Union[Array1D, Array2D, list[Array1D], list[Array2D]]

A single 2D array (e.g. MxN), a single 1D dataset (e.g. Nx2), or a list of such arrays for multi-device analysis.

required
auxiliary_data dict

Additional data used by the image analyzer for this image, such as image range.

None

Returns:

Type Description
ImageAnalyzerResult

Structured result containing processed data, scalars, and metadata.

Source code in image_analysis/base.py
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def analyze_image(
    self,
    image: Union[Array1D, Array2D, list[Array1D], list[Array2D]],
    auxiliary_data: Optional[dict] = None,
) -> ImageAnalyzerResult:
    """Calculate metrics from an image or list of images.

    This function should be implemented by each device's ImageAnalyzer subclass,
    to run on an image from that device (obviously).

    Should take full-size (i.e. uncropped) image.

    For multi-device analyzers (e.g. multi-camera diagnostics), a list of
    arrays may be passed — one per device. The analyzer is responsible for
    combining them as needed and returning a single result.

    Parameters
    ----------
    image : Union[Array1D, Array2D, list[Array1D], list[Array2D]]
        A single 2D array (e.g. MxN), a single 1D dataset (e.g. Nx2),
        or a list of such arrays for multi-device analysis.
    auxiliary_data : dict, optional
        Additional data used by the image analyzer for this image, such as
        image range.

    Returns
    -------
    ImageAnalyzerResult
        Structured result containing processed data, scalars, and metadata.

    """
    raise NotImplementedError()

analyze_image_file

analyze_image_file(image_filepath: Union[Path, list[Path]], auxiliary_data: Optional[dict] = None) -> ImageAnalyzerResult

Method to enable the use of a file path (or list of paths) rather than arrays.

For multi-device analyzers, a list of file paths can be passed — one per device. The paths are loaded via :meth:load_image and the resulting array(s) are passed to :meth:analyze_image.

Parameters:

Name Type Description Default
image_filepath Union[Path, list[Path]]

A single file path or a list of file paths for multi-device analysis.

required
auxiliary_data dict

Additional data used by the image analyzer for this image, such as image range.

None

Returns:

Type Description
ImageAnalyzerResult

Structured result containing processed data, scalars, and metadata.

Source code in image_analysis/base.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def analyze_image_file(
    self,
    image_filepath: Union[Path, list[Path]],
    auxiliary_data: Optional[dict] = None,
) -> ImageAnalyzerResult:
    """
    Method to enable the use of a file path (or list of paths) rather than arrays.

    For multi-device analyzers, a list of file paths can be passed — one
    per device. The paths are loaded via :meth:`load_image` and the
    resulting array(s) are passed to :meth:`analyze_image`.

    Parameters
    ----------
    image_filepath : Union[Path, list[Path]]
        A single file path or a list of file paths for multi-device analysis.
    auxiliary_data : dict, optional
        Additional data used by the image analyzer for this image, such as
        image range.

    Returns
    -------
    ImageAnalyzerResult
        Structured result containing processed data, scalars, and metadata.

    """
    image = self.load_image(image_filepath)

    return self.analyze_image(image, auxiliary_data)

load_image

load_image(file_path: Union[Path, list[Path]]) -> Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]

Load an image from a path, or multiple images from a list of paths.

When given a single path, loads and returns a single array using :func:read_imaq_image (or subclass override).

When given a list of paths, recursively calls self.load_image on each path and returns a list of arrays. This means subclasses that override load_image for custom file formats (e.g. .himg) automatically get list support for free.

Parameters:

Name Type Description Default
file_path Union[Path, list[Path]]

A single file path or a list of file paths for multi-device loading.

required

Returns:

Type Description
Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]

A single array for a single path, or a list of arrays for a list of paths.

Source code in image_analysis/base.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def load_image(
    self, file_path: Union[Path, list[Path]]
) -> Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]:
    """
    Load an image from a path, or multiple images from a list of paths.

    When given a single path, loads and returns a single array using
    :func:`read_imaq_image` (or subclass override).

    When given a list of paths, recursively calls ``self.load_image`` on
    each path and returns a list of arrays. This means subclasses that
    override ``load_image`` for custom file formats (e.g. ``.himg``)
    automatically get list support for free.

    Parameters
    ----------
    file_path : Union[Path, list[Path]]
        A single file path or a list of file paths for multi-device loading.

    Returns
    -------
    Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]
        A single array for a single path, or a list of arrays for a list
        of paths.
    """
    if isinstance(file_path, list):
        return [self.load_image(p) for p in file_path]

    image = read_imaq_image(file_path)

    return image
StandardAnalyzer API

image_analysis.analyzers.standard_analyzer.StandardAnalyzer

StandardAnalyzer(camera_config: CameraConfig, *, output_name: Optional[str] = None)

Bases: ImageAnalyzer

Standard image analyzer with configurable processing pipeline.

This analyzer provides a general-purpose foundation for image analysis using: - Type-safe camera configuration via Pydantic models - Externalized configuration in YAML files - Unified processing pipeline - Path-keyed background caching across analyze_image calls - Proper 16-bit image handling - Extensible preprocessing algorithms - Clean separation of concerns

This class is designed to be inherited by specialized analyzers that add domain-specific analysis capabilities (e.g., beam statistics, spectral analysis).

Parameters:

Name Type Description Default
camera_config CameraConfig

Validated camera configuration model. Use image_analysis.config.loader.load_camera_config(name) to load from disk by name before constructing.

required
output_name str

Output identifier for this analyzer instance — the string used as the per-analyzer output directory name and (via the output_name property) read by downstream consumers like SingleDeviceScanAnalyzer for path construction.

The diagnostic factory passes diag.effective_output_name here so the analyzer's identifier matches the s-file column prefix that ScanAnalysis applies. Defaults to None — standalone notebook use doesn't need an identifier.

The analyzer itself never uses this for scalar-key formation; it emits bare keys and ScanAnalysis namespaces them at consumption time (#412).

None

Initialize the standard analyzer with a validated camera config.

Scalar-key prefix/suffix used to live here (name_suffix, metric_suffix) but was promoted to ScanAnalysis per #412 — all output-naming concerns now live on the diagnostic config (output_name / metric_suffix) and are applied by :class:SingleDeviceScanAnalyzer when storing per-shot results. The analyzer emits bare scalar keys.

output_name is stored as analyzer state purely so downstream consumers (output-dir construction in SingleDeviceScanAnalyzer; per-file paths in MagSpec) can read a stable identifier off the analyzer instance. It is not used internally for any per-shot computation.

The string-by-name convenience that this constructor used to offer has moved to the loader layer — call image_analysis.config.loader.load_camera_config(name) (or image_analysis.config.load_image_analyzer(name)) to get a CameraConfig first, then hand it here.

Methods:

Name Description
preprocess_image

Apply the complete processing pipeline to a single image.

get_camera_info

Get comprehensive camera configuration information.

set_camera_config

Replace the entire camera configuration with a validated instance.

update_config

Update camera configuration sections dynamically.

analyze_image

Analyze a single image using the full processing pipeline.

render_image

Render the processed image from an analysis result.

visualize

Render and optionally display a visualization of the result.

analyze_image_file

Method to enable the use of a file path (or list of paths) rather than arrays.

load_image

Load an image from a path, or multiple images from a list of paths.

Attributes:

Name Type Description
output_name Optional[str]

Return the output identifier configured for this analyzer instance.

Source code in image_analysis/analyzers/standard_analyzer.py
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
def __init__(
    self,
    camera_config: cfg_2d.CameraConfig,
    *,
    output_name: Optional[str] = None,
):
    """Initialize the standard analyzer with a validated camera config.

    Scalar-key prefix/suffix used to live here (``name_suffix``,
    ``metric_suffix``) but was promoted to ScanAnalysis per #412 —
    all output-naming concerns now live on the diagnostic config
    (``output_name`` / ``metric_suffix``) and are applied by
    :class:`SingleDeviceScanAnalyzer` when storing per-shot
    results. The analyzer emits bare scalar keys.

    ``output_name`` is stored as analyzer state purely so
    downstream consumers (output-dir construction in
    ``SingleDeviceScanAnalyzer``; per-file paths in MagSpec) can
    read a stable identifier off the analyzer instance. It is not
    used internally for any per-shot computation.

    The string-by-name convenience that this constructor used to
    offer has moved to the loader layer — call
    ``image_analysis.config.loader.load_camera_config(name)`` (or
    ``image_analysis.config.load_image_analyzer(name)``) to get a
    ``CameraConfig`` first, then hand it here.
    """
    self.camera_config = camera_config
    self._output_name: Optional[str] = output_name
    logger.info("Using provided CameraConfig (output_name=%r)", self._output_name)

    # Path-keyed cache for ``apply_background``. Loaded backgrounds
    # are reused across analyze_image calls; the cache is rebuilt
    # transparently if the config's file_path changes.
    self._bg_cache: Dict[str, Array2D] = {}

    # Store analyzer state
    self.run_analyze_image_asynchronously = True

    super().__init__()

output_name property

output_name: Optional[str]

Return the output identifier configured for this analyzer instance.

This is the string used by scan analyzers to label per-analyzer output directories, and by any analyzer that writes per-file outputs (e.g. MagSpec's -interp/ subdirectories). Set at construction time from the diagnostic's effective_output_name. None in standalone notebook use where no identifier was supplied.

preprocess_image

preprocess_image(image: ndarray) -> np.ndarray

Apply the complete processing pipeline to a single image.

This method handles the core image preprocessing including background subtraction, ROI cropping, thresholding, masking, and any other configured processing steps.

Parameters:

Name Type Description Default
image ndarray

Input image to process

required

Returns:

Type Description
ndarray

Processed image ready for analysis

Source code in image_analysis/analyzers/standard_analyzer.py
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
def preprocess_image(self, image: np.ndarray) -> np.ndarray:
    """
    Apply the complete processing pipeline to a single image.

    This method handles the core image preprocessing including background
    subtraction, ROI cropping, thresholding, masking, and any other
    configured processing steps.

    Parameters
    ----------
    image : np.ndarray
        Input image to process

    Returns
    -------
    np.ndarray
        Processed image ready for analysis
    """
    logger.info("Applying camera processing pipeline")

    # Use the unified processing pipeline
    processed_image = apply_camera_processing_pipeline(
        image, self.camera_config, background_cache=self._bg_cache
    )

    return processed_image

get_camera_info

get_camera_info() -> Dict[str, Any]

Get comprehensive camera configuration information.

Source code in image_analysis/analyzers/standard_analyzer.py
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
def get_camera_info(self) -> Dict[str, Any]:
    """Get comprehensive camera configuration information."""
    info: Dict[str, Any] = {
        "description": self.camera_config.description,
        "bit_depth": self.camera_config.bit_depth,
        "processing_dtype": str(self.camera_config.processing_dtype),
        "storage_dtype": str(self.camera_config.storage_dtype),
        "background_enabled": (
            self.camera_config.background is not None
            and any(
                step.value == "background"
                for step in self.camera_config.pipeline.steps
            )
        ),
    }
    if self._output_name is not None:
        info["output_name"] = self._output_name
    return info

set_camera_config

set_camera_config(new_cfg: CameraConfig) -> None

Replace the entire camera configuration with a validated instance.

Source code in image_analysis/analyzers/standard_analyzer.py
198
199
200
201
202
203
204
205
206
def set_camera_config(self, new_cfg: cfg_2d.CameraConfig) -> None:
    """Replace the entire camera configuration with a validated instance."""
    old_bg = self.camera_config.background
    self.camera_config = cfg_2d.CameraConfig.model_validate(new_cfg)
    if self.camera_config.background != old_bg:
        # Background source may have changed; drop the cache so the
        # next analyze_image reloads from the new file.
        self._bg_cache.clear()
    logger.info("Replaced camera configuration (output_name=%r)", self._output_name)

update_config

update_config(**section_updates: Union[BaseModel, Dict[str, Any]]) -> None

Update camera configuration sections dynamically.

This method allows updating any configuration section by passing it as a keyword argument. Sections can be updated with either: - A Pydantic model instance (replaces the section) - A dictionary (merges with existing values)

Parameters:

Name Type Description Default
**section_updates Union[BaseModel, Dict[str, Any]]

Configuration sections to update. Valid section names include: background, roi, crosshair_masking, circular_mask, thresholding, filtering, transforms, pipeline

{}
Source code in image_analysis/analyzers/standard_analyzer.py
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
def update_config(
    self, **section_updates: Union[BaseModel, Dict[str, Any]]
) -> None:
    """
    Update camera configuration sections dynamically.

    This method allows updating any configuration section by passing it as a
    keyword argument. Sections can be updated with either:
    - A Pydantic model instance (replaces the section)
    - A dictionary (merges with existing values)

    Parameters
    ----------
    **section_updates : Union[BaseModel, Dict[str, Any]]
        Configuration sections to update. Valid section names include:
        background, roi, crosshair_masking, circular_mask, thresholding,
        filtering, transforms, pipeline

    """
    # Start with current config as dict
    cfg_dict = self.camera_config.model_dump()
    bg_changed = False

    for section_name, value in section_updates.items():
        # Validate section name
        if not hasattr(self.camera_config, section_name):
            logger.warning(f"Unknown configuration section: {section_name}")
            continue

        # Track if background changed
        if section_name == "background":
            bg_changed = True

        current = getattr(self.camera_config, section_name)

        # Handle different value types
        if isinstance(value, BaseModel):
            # Direct model replacement
            cfg_dict[section_name] = value
        elif isinstance(value, dict):
            # Merge dict with existing config
            if current is not None:
                cfg_dict[section_name] = {**current.model_dump(), **value}
            else:
                cfg_dict[section_name] = value
        else:
            logger.warning(
                f"Section '{section_name}' must be a Pydantic model or dict, "
                f"got {type(value).__name__}"
            )
            continue

    # Validate and update the entire config
    new_cfg = cfg_2d.CameraConfig.model_validate(cfg_dict)

    if new_cfg != self.camera_config:
        self.camera_config = new_cfg

        # Drop the background cache if bg config changed — next
        # analyze_image will reload from the new file_path.
        if bg_changed:
            self._bg_cache.clear()

        logger.info("Configuration updated: %s", list(section_updates.keys()))

analyze_image

analyze_image(image: ndarray, auxiliary_data: Optional[Dict] = None) -> ImageAnalyzerResult

Analyze a single image using the full processing pipeline.

This method applies the complete processing pipeline to the image, including background subtraction (loaded from file if computed in batch), ROI cropping, masking, thresholding, and any other configured steps.

Parameters:

Name Type Description Default
image ndarray

Input image to analyze

required
auxiliary_data dict

Additional data (e.g., file path for logging)

None

Returns:

Type Description
ImageAnalyzerResult

Structured result containing processed image and metadata

Source code in image_analysis/analyzers/standard_analyzer.py
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
def analyze_image(
    self, image: np.ndarray, auxiliary_data: Optional[Dict] = None
) -> ImageAnalyzerResult:
    """
    Analyze a single image using the full processing pipeline.

    This method applies the complete processing pipeline to the image,
    including background subtraction (loaded from file if computed in batch),
    ROI cropping, masking, thresholding, and any other configured steps.

    Parameters
    ----------
    image : np.ndarray
        Input image to analyze
    auxiliary_data : dict, optional
        Additional data (e.g., file path for logging)

    Returns
    -------
    ImageAnalyzerResult
        Structured result containing processed image and metadata
    """
    file_path = (
        auxiliary_data.get("file_path", "Unknown") if auxiliary_data else "Unknown"
    )
    logger.info("Analyzing image from: %s", file_path)

    # Apply full processing pipeline
    # (Background will be loaded from file if it was computed in batch)
    final_image = self.preprocess_image(image)

    # Build input parameters dictionary
    input_params = self._build_input_parameters()

    # Ensure `scalars` exists (subclasses may add keys later)
    scalars: Dict[str, Any] = {}

    # Build and return result
    result = ImageAnalyzerResult(
        data_type="2d",
        processed_image=final_image,
        scalars=scalars,  # No scalars by default, subclasses can add them
        metadata=input_params,
    )

    return result

render_image staticmethod

render_image(result: ImageAnalyzerResult, vmin: Optional[float] = None, vmax: Optional[float] = None, cmap: str = 'plasma', figsize: Tuple[float, float] = (4, 4), dpi: int = 150, ax: Optional[Axes] = None) -> Tuple[plt.Figure, plt.Axes]

Render the processed image from an analysis result.

Provides a baseline rendering that subclasses can extend by overriding this method and adding domain-specific overlays.

Parameters:

Name Type Description Default
result ImageAnalyzerResult

The analysis result containing the processed image.

required
vmin float

Colour-scale limits.

None
vmax float

Colour-scale limits.

None
cmap str

Matplotlib colour-map name.

'plasma'
figsize tuple of float

Figure size in inches (width, height).

(4, 4)
dpi int

Figure resolution.

150
ax matplotlib Axes

Existing axes to draw into. A new figure is created when None.

None

Returns:

Name Type Description
fig Figure
ax Axes
Source code in image_analysis/analyzers/standard_analyzer.py
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
@staticmethod
def render_image(
    result: ImageAnalyzerResult,
    vmin: Optional[float] = None,
    vmax: Optional[float] = None,
    cmap: str = "plasma",
    figsize: Tuple[float, float] = (4, 4),
    dpi: int = 150,
    ax: Optional[plt.Axes] = None,
) -> Tuple[plt.Figure, plt.Axes]:
    """Render the processed image from an analysis result.

    Provides a baseline rendering that subclasses can extend by
    overriding this method and adding domain-specific overlays.

    Parameters
    ----------
    result : ImageAnalyzerResult
        The analysis result containing the processed image.
    vmin, vmax : float, optional
        Colour-scale limits.
    cmap : str
        Matplotlib colour-map name.
    figsize : tuple of float
        Figure size in inches ``(width, height)``.
    dpi : int
        Figure resolution.
    ax : matplotlib Axes, optional
        Existing axes to draw into.  A new figure is created when
        *None*.

    Returns
    -------
    fig : matplotlib.figure.Figure
    ax : matplotlib.axes.Axes
    """
    from image_analysis.tools.rendering import base_render_image

    fig, ax = base_render_image(
        result=result,
        vmin=vmin,
        vmax=vmax,
        cmap=cmap,
        figsize=figsize,
        dpi=dpi,
        ax=ax,
    )
    return fig, ax

visualize

visualize(results: ImageAnalyzerResult, *, show: bool = True, close: bool = True, ax: Optional[Axes] = None, vmin: Optional[float] = None, vmax: Optional[float] = None, cmap: str = 'plasma') -> Tuple[plt.Figure, plt.Axes]

Render and optionally display a visualization of the result.

Convenience wrapper around :meth:render_image that handles plt.show() / plt.close() lifecycle.

Parameters:

Name Type Description Default
results ImageAnalyzerResult

Analysis result to visualize.

required
show bool

Call plt.show() after rendering.

True
close bool

Call plt.close(fig) after rendering.

True
ax matplotlib Axes

Existing axes to draw into.

None
vmin float

Colour-scale limits.

None
vmax float

Colour-scale limits.

None
cmap str

Matplotlib colour-map name.

'plasma'

Returns:

Name Type Description
fig Figure
ax Axes
Source code in image_analysis/analyzers/standard_analyzer.py
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
def visualize(
    self,
    results: ImageAnalyzerResult,
    *,
    show: bool = True,
    close: bool = True,
    ax: Optional[plt.Axes] = None,
    vmin: Optional[float] = None,
    vmax: Optional[float] = None,
    cmap: str = "plasma",
) -> Tuple[plt.Figure, plt.Axes]:
    """Render and optionally display a visualization of the result.

    Convenience wrapper around :meth:`render_image` that handles
    ``plt.show()`` / ``plt.close()`` lifecycle.

    Parameters
    ----------
    results : ImageAnalyzerResult
        Analysis result to visualize.
    show : bool
        Call ``plt.show()`` after rendering.
    close : bool
        Call ``plt.close(fig)`` after rendering.
    ax : matplotlib Axes, optional
        Existing axes to draw into.
    vmin, vmax : float, optional
        Colour-scale limits.
    cmap : str
        Matplotlib colour-map name.

    Returns
    -------
    fig : matplotlib.figure.Figure
    ax : matplotlib.axes.Axes
    """
    fig, ax = self.render_image(
        result=results,
        vmin=vmin,
        vmax=vmax,
        cmap=cmap,
        ax=ax,
    )

    if show:
        plt.show()
    if close:
        plt.close(fig)

    return fig, ax

analyze_image_file

analyze_image_file(image_filepath: Union[Path, list[Path]], auxiliary_data: Optional[dict] = None) -> ImageAnalyzerResult

Method to enable the use of a file path (or list of paths) rather than arrays.

For multi-device analyzers, a list of file paths can be passed — one per device. The paths are loaded via :meth:load_image and the resulting array(s) are passed to :meth:analyze_image.

Parameters:

Name Type Description Default
image_filepath Union[Path, list[Path]]

A single file path or a list of file paths for multi-device analysis.

required
auxiliary_data dict

Additional data used by the image analyzer for this image, such as image range.

None

Returns:

Type Description
ImageAnalyzerResult

Structured result containing processed data, scalars, and metadata.

Source code in image_analysis/base.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def analyze_image_file(
    self,
    image_filepath: Union[Path, list[Path]],
    auxiliary_data: Optional[dict] = None,
) -> ImageAnalyzerResult:
    """
    Method to enable the use of a file path (or list of paths) rather than arrays.

    For multi-device analyzers, a list of file paths can be passed — one
    per device. The paths are loaded via :meth:`load_image` and the
    resulting array(s) are passed to :meth:`analyze_image`.

    Parameters
    ----------
    image_filepath : Union[Path, list[Path]]
        A single file path or a list of file paths for multi-device analysis.
    auxiliary_data : dict, optional
        Additional data used by the image analyzer for this image, such as
        image range.

    Returns
    -------
    ImageAnalyzerResult
        Structured result containing processed data, scalars, and metadata.

    """
    image = self.load_image(image_filepath)

    return self.analyze_image(image, auxiliary_data)

load_image

load_image(file_path: Union[Path, list[Path]]) -> Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]

Load an image from a path, or multiple images from a list of paths.

When given a single path, loads and returns a single array using :func:read_imaq_image (or subclass override).

When given a list of paths, recursively calls self.load_image on each path and returns a list of arrays. This means subclasses that override load_image for custom file formats (e.g. .himg) automatically get list support for free.

Parameters:

Name Type Description Default
file_path Union[Path, list[Path]]

A single file path or a list of file paths for multi-device loading.

required

Returns:

Type Description
Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]

A single array for a single path, or a list of arrays for a list of paths.

Source code in image_analysis/base.py
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def load_image(
    self, file_path: Union[Path, list[Path]]
) -> Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]:
    """
    Load an image from a path, or multiple images from a list of paths.

    When given a single path, loads and returns a single array using
    :func:`read_imaq_image` (or subclass override).

    When given a list of paths, recursively calls ``self.load_image`` on
    each path and returns a list of arrays. This means subclasses that
    override ``load_image`` for custom file formats (e.g. ``.himg``)
    automatically get list support for free.

    Parameters
    ----------
    file_path : Union[Path, list[Path]]
        A single file path or a list of file paths for multi-device loading.

    Returns
    -------
    Union[Array1D, Array2D, list[Union[Array1D, Array2D]]]
        A single array for a single path, or a list of arrays for a list
        of paths.
    """
    if isinstance(file_path, list):
        return [self.load_image(p) for p in file_path]

    image = read_imaq_image(file_path)

    return image