API Reference

This page contains the autodocumented API for the primary alexandria modules.

Alexandria - Unified CatPhan Phantom Analysis Library

A comprehensive library for analyzing CatPhan CT phantom DICOM images. Provides modular analyzers for uniformity, resolution, contrast, and linearity analysis.

class alexandria.CTP401Analyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, roi_radius: float = 3.5, material_distance: float = 58.5, edge_threshold: float = 100.0, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = -950, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer for CTP401 linearity module (4-ROI version).

This module measures HU values for 4 material inserts (LDPE, Air, Teflon, Acrylic), calculates low contrast visibility, verifies spatial scaling, and can automatically detect phantom rotation.

Supports both single-image mode and DICOM-series mode with 3-slice averaging.

Key Features: - 4 Material ROI analysis (LDPE at 0°, Air at 90° (south/bottom), Teflon at 180°, Acrylic at 270° (north/top)) - Automatic rotation detection using air ROI position - Low Contrast Visibility (LCV) calculation - Spatial scaling verification (X and Y axes)

image

2D CT image of the module.

Type:

np.ndarray

center

(x, y) coordinates of phantom center in pixels.

Type:

tuple

pixel_spacing

Pixel spacing in mm.

Type:

float

results

Analysis results.

Type:

dict

ROI_CONFIG = {'Acrylic': 270, 'Air': 90, 'LDPE': 0, 'Teflon': 180}
analyze(t_offset: float = 0.0, verbose: bool = False) Dict[source]

Perform ROI analysis on the stored image.

Parameters:
  • t_offset – Rotational offset for ROIs in degrees

  • verbose – Print progress information

Returns:

  • ‘ROIs’: Dictionary of ROI results (mean, std for each material)

  • ’LCV_percent’: Low contrast visibility percentage

  • ’Scale’: Spatial scaling factors (scaleX_cm, scaleY_cm)

Return type:

Dictionary containing analysis results with

detect_rotation(initial_angle_deg: float = 0.0)[source]

Detect phantom rotation using material insert positions.

Locates the Air (90°) and Acrylic (270°) inserts via iterative edge detection and calculates rotation from their deviation from vertical alignment.

Parameters:

initial_angle_deg – Initial rotation guess in degrees (default 0).

Returns:

Tuple of (rotation_angle_deg, top_point, bottom_point). rotation_angle_deg is also stored as self.rotation_offset.

class alexandria.CTP401ModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, roi_radius: float = 3.5, material_distance: float = 58.5, edge_threshold: float = 100.0)[source]

Bases: object

analyze(t_offset: float = 0.0, verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(t_offset: float = 0.0, verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
detect_rotation(initial_angle_deg: float = 0.0) float[source]
get_summary() str[source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 150, **kwargs)[source]
class alexandria.CTP404Analyzer(image: ndarray | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, rotation_offset: float = 0.0, roi_radius: float = 3.5, material_distance: float = 58.5)[source]

Bases: object

Unified CTP404 sensitometry analyzer.

This analyzer computes mean and standard deviation values for the standard CatPhan CTP404 contrast module which contains nine circular ROIs containing different materials. The implementation supports two initialization modes:

  • Single-image mode: caller passes a prepared 2D NumPy image array via the image parameter.

  • DICOM-series mode: caller provides a list of pydicom dataset objects and a slice_index; the analyzer will form a simple 3-slice average to improve SNR before analysis.

MATERIALS = ['Delrin', 'none', 'Acrylic', 'Air', 'Polystyrene', 'LDPE', 'PMP', 'Teflon', 'Air2']
ROI_ANGLES = [0, 30, 60, 90, 120, 180, -120, -60, -90]
analyze(verbose: bool = False) Dict[source]

Perform contrast analysis on all 9 ROIs.

Parameters:

verbose – Print progress information

Returns:

Dictionary containing analysis results

detect_rotation(initial_angle_deg: float = 0.0) float[source]

Detect phantom rotation using insert positions (delegates to shared utility).

Parameters:

initial_angle_deg – Initial rotation guess in degrees (default 0)

Returns:

Rotation angle in degrees (sets and returns self.rotation_offset)

get_results_summary() str[source]

Get formatted summary of analysis results.

Returns:

Multi-line string summary

to_dict() Dict[source]

Export results as dictionary.

Returns:

Results dictionary

class alexandria.CTP404ModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, rotation_offset: float = 0.0, roi_radius: float = 3.5, material_distance: float = 58.5)[source]

Bases: object

analyze(verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() str[source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 150, **kwargs)[source]
class alexandria.CTP515Analyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, angle_offset: float = 0.0, dicom_set: List | None = None, slice_index: int | None = None, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = 400.0, center_threshold_fallback: float = 300)[source]

Bases: object

Low-contrast detectability analyzer for CatPhan CTP515 module.

Detects and analyzes six low-contrast circular inserts of varying diameters positioned at fixed angles and distance from center. Computes Contrast-to-Noise Ratio (CNR) and contrast percentage for each ROI relative to a background region.

CNR quantifies detectability: higher values indicate the insert is more easily distinguished from background noise.

Supports both single-image mode and DICOM-series mode with 3-slice averaging.

image

2D CT image of the low-contrast module.

Type:

np.ndarray

center

(x, y) center of phantom in pixels.

Type:

tuple

pixel_spacing

Pixel spacing in mm.

Type:

float

angle_offset

Angular offset for ROI positioning in degrees.

Type:

float

results

Analysis results populated by analyze().

Type:

dict

ROI_ANGLES = [-87.4, -69.1, -52.7, -38.5, -25.1, -12.9]
ROI_DISTANCE_MM = 50
ROI_RADII_MM = [6, 3.5, 3, 2.5, 2, 1.5]
ROI_SETTINGS = {'15': {'angle_idx': 0, 'radius_mm': 6}, '5': {'angle_idx': 5, 'radius_mm': 1.5}, '6': {'angle_idx': 4, 'radius_mm': 2}, '7': {'angle_idx': 3, 'radius_mm': 2.5}, '8': {'angle_idx': 2, 'radius_mm': 3}, '9': {'angle_idx': 1, 'radius_mm': 3.5}}
analyze(verbose: bool = True) Dict[str, Any][source]

Perform low-contrast detectability analysis.

This method: 1. Defines ROI locations based on predefined angles and distances. 2. For each ROI, creates a circular mask and computes mean/std. 3. Computes a common background ROI for noise reference. 4. Calculates CNR for each ROI against the background. 5. Returns a summary of detected ROIs and their metrics.

Parameters:

verbose – Whether to print progress information.

Returns:

Contains ‘n_detected’ (int) and ‘blobs’ (dict of blob stats).

Each blob entry has position, size, means, std, and CNR.

Return type:

Dict

get_plot_data() Dict[str, Any][source]

Get data needed for plotting visualizations.

get_results_summary() Dict[str, str][source]

Get a formatted summary of analysis results.

Returns:

Dictionary with key measurements formatted as strings.

prepare_image()[source]

Prepare image for analysis.

In DICOM mode: Create 3-slice averaged image for improved SNR. In single-image mode: Use the provided image directly.

Returns:

Prepared image array

to_dict() Dict[str, Any][source]

Return JSON-compatible results dictionary.

Returns:

Dictionary with all analysis results.

class alexandria.CTP515ModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, angle_offset: float = 0.0, dicom_set: List | None = None, slice_index: int | None = None)[source]

Bases: object

analyze(verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() Dict[str, str][source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 300, **kwargs)[source]
class alexandria.DetailedUniformityAnalyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, radii_mm: List[float] | None = None, sample_step_mm: float = 1.0, n_samples: int = 360, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = 400.0, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer that samples concentric circular profiles for uniformity checks.

analyze() Dict[str, Any][source]
prepare_image() ndarray[source]

Prepare image for analysis.

class alexandria.HighContrastAnalyzer(image: ndarray | None = None, pixel_spacing: float | None = None, center: Tuple[float, float] | None = None, t_offset_deg: float = 0.0, rotation_offset: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, lp_r_mm: float = 48.0, samples_per_segment: int = 50, center_threshold: float = -980, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer for CatPhan’s CTP528 high-contrast (line pair) module.

analyze(write_log: bool = False, verbose: bool = True) dict[source]
prepare_image()[source]
to_dict() Dict[str, Any][source]
class alexandria.HighContrastModuleReporter(image: Any | None = None, pixel_spacing: float | None = None, center: Tuple[float, float] | None = None, t_offset_deg: float = 0.0, rotation_offset: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, lp_r_mm: float = 48.0, samples_per_segment: int = 50)[source]

Bases: object

analyze(write_log: bool = False, verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() Dict[str, str][source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 300, **kwargs)[source]
class alexandria.UniformityAnalyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, roi_box_size: float = 15.0, roi_offset: float = 50.0, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = 400.0, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer for CT scanner uniformity using the CTP486 module.

This class evaluates uniformity by measuring mean and standard deviation in five fixed ROIs (center, north, south, east, west) relative to the phantom center. Supports both single-image analysis and DICOM series with 3-slice averaging for improved SNR.

Center handling:

A center may be provided explicitly, or the analyzer may compute one on demand by calling center_finder. The expected return contract for a center finder is either (row, col) or (row, col, diameter_y_px, diameter_x_px).

Some center finders, such as mirror-correlation symmetry methods, only estimate the center and do not naturally provide diameters. That case is handled explicitly: missing diameters are treated as None and the analyzer falls back to compute_phantom_boundary(...) when it needs a boundary for plotting or diagnostics.

REGIONS = ['centre', 'north', 'south', 'east', 'west']
analyze(verbose: bool = True) Dict[str, Any][source]

Perform the uniformity analysis on five ROIs.

analyze_uniformity() Tuple[List, ndarray, List][source]

Analyze uniformity by measuring HU values in 5 regions.

prepare_image()[source]

Prepare image for analysis.

class alexandria.UniformityModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, roi_box_size: float = 15.0, roi_offset: float = 50.0)[source]

Bases: object

analyze(verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() Dict[str, str][source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 300, **kwargs)[source]

Analyzers

Unified Uniformity Analyzer for CatPhan Phantom Analysis

This module combines the uniformity analysis functionality from both catphan404 and XVI-CatPhan projects, providing a comprehensive analyzer for CTP486 uniformity module with both single-image and DICOM-series modes.

class alexandria.analyzers.uniformity.UniformityAnalyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, roi_box_size: float = 15.0, roi_offset: float = 50.0, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = 400.0, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer for CT scanner uniformity using the CTP486 module.

This class evaluates uniformity by measuring mean and standard deviation in five fixed ROIs (center, north, south, east, west) relative to the phantom center. Supports both single-image analysis and DICOM series with 3-slice averaging for improved SNR.

Center handling:

A center may be provided explicitly, or the analyzer may compute one on demand by calling center_finder. The expected return contract for a center finder is either (row, col) or (row, col, diameter_y_px, diameter_x_px).

Some center finders, such as mirror-correlation symmetry methods, only estimate the center and do not naturally provide diameters. That case is handled explicitly: missing diameters are treated as None and the analyzer falls back to compute_phantom_boundary(...) when it needs a boundary for plotting or diagnostics.

REGIONS = ['centre', 'north', 'south', 'east', 'west']
analyze(verbose: bool = True) Dict[str, Any][source]

Perform the uniformity analysis on five ROIs.

analyze_uniformity() Tuple[List, ndarray, List][source]

Analyze uniformity by measuring HU values in 5 regions.

prepare_image()[source]

Prepare image for analysis.

Detailed Uniformity Analyzer

Samples pixel values along concentric circular profiles and records angle/value pairs for each radius.

class alexandria.analyzers.detailed_uniformity.DetailedUniformityAnalyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, radii_mm: List[float] | None = None, sample_step_mm: float = 1.0, n_samples: int = 360, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = 400.0, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer that samples concentric circular profiles for uniformity checks.

analyze() Dict[str, Any][source]
prepare_image() ndarray[source]

Prepare image for analysis.

Unified High Contrast Analyzer for CatPhan Phantom Analysis

This module combines the high-contrast/resolution analysis functionality from both catphan404 and XVI-CatPhan projects, providing a comprehensive analyzer for CTP528 line pair module with both single-image and DICOM-series modes.

class alexandria.analyzers.high_contrast.HighContrastAnalyzer(image: ndarray | None = None, pixel_spacing: float | None = None, center: Tuple[float, float] | None = None, t_offset_deg: float = 0.0, rotation_offset: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, lp_r_mm: float = 48.0, samples_per_segment: int = 50, center_threshold: float = -980, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer for CatPhan’s CTP528 high-contrast (line pair) module.

analyze(write_log: bool = False, verbose: bool = True) dict[source]
prepare_image()[source]
to_dict() Dict[str, Any][source]

CTP401 Analyzer - Linearity Module (4-ROI)

This module handles the CTP401 linearity analysis with 4 material ROIs: LDPE, Air, Teflon, and Acrylic positioned at 0°, 90°, 180°, and 270°.

Provides comprehensive analysis including: - Material ROI contrast measurements (HU accuracy) - Low Contrast Visibility (LCV) - Spatial scaling/linearity verification - Automatic rotation detection using air ROI positions

class alexandria.analyzers.ctp401.CTP401Analyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, roi_radius: float = 3.5, material_distance: float = 58.5, edge_threshold: float = 100.0, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = -950, center_threshold_fallback: float = -900.0)[source]

Bases: object

Analyzer for CTP401 linearity module (4-ROI version).

This module measures HU values for 4 material inserts (LDPE, Air, Teflon, Acrylic), calculates low contrast visibility, verifies spatial scaling, and can automatically detect phantom rotation.

Supports both single-image mode and DICOM-series mode with 3-slice averaging.

Key Features: - 4 Material ROI analysis (LDPE at 0°, Air at 90° (south/bottom), Teflon at 180°, Acrylic at 270° (north/top)) - Automatic rotation detection using air ROI position - Low Contrast Visibility (LCV) calculation - Spatial scaling verification (X and Y axes)

image

2D CT image of the module.

Type:

np.ndarray

center

(x, y) coordinates of phantom center in pixels.

Type:

tuple

pixel_spacing

Pixel spacing in mm.

Type:

float

results

Analysis results.

Type:

dict

ROI_CONFIG = {'Acrylic': 270, 'Air': 90, 'LDPE': 0, 'Teflon': 180}
analyze(t_offset: float = 0.0, verbose: bool = False) Dict[source]

Perform ROI analysis on the stored image.

Parameters:
  • t_offset – Rotational offset for ROIs in degrees

  • verbose – Print progress information

Returns:

  • ‘ROIs’: Dictionary of ROI results (mean, std for each material)

  • ’LCV_percent’: Low contrast visibility percentage

  • ’Scale’: Spatial scaling factors (scaleX_cm, scaleY_cm)

Return type:

Dictionary containing analysis results with

detect_rotation(initial_angle_deg: float = 0.0)[source]

Detect phantom rotation using material insert positions.

Locates the Air (90°) and Acrylic (270°) inserts via iterative edge detection and calculates rotation from their deviation from vertical alignment.

Parameters:

initial_angle_deg – Initial rotation guess in degrees (default 0).

Returns:

Tuple of (rotation_angle_deg, top_point, bottom_point). rotation_angle_deg is also stored as self.rotation_offset.

CTP404 Analyzer - Contrast and Sensitometry Module

Unified analyzer for CTP404 sensitometry analysis, combining functionality from catphan404 and XVI-CatPhan implementations.

class alexandria.analyzers.ctp404.CTP404Analyzer(image: ndarray | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, rotation_offset: float = 0.0, roi_radius: float = 3.5, material_distance: float = 58.5)[source]

Bases: object

Unified CTP404 sensitometry analyzer.

This analyzer computes mean and standard deviation values for the standard CatPhan CTP404 contrast module which contains nine circular ROIs containing different materials. The implementation supports two initialization modes:

  • Single-image mode: caller passes a prepared 2D NumPy image array via the image parameter.

  • DICOM-series mode: caller provides a list of pydicom dataset objects and a slice_index; the analyzer will form a simple 3-slice average to improve SNR before analysis.

MATERIALS = ['Delrin', 'none', 'Acrylic', 'Air', 'Polystyrene', 'LDPE', 'PMP', 'Teflon', 'Air2']
ROI_ANGLES = [0, 30, 60, 90, 120, 180, -120, -60, -90]
analyze(verbose: bool = False) Dict[source]

Perform contrast analysis on all 9 ROIs.

Parameters:

verbose – Print progress information

Returns:

Dictionary containing analysis results

detect_rotation(initial_angle_deg: float = 0.0) float[source]

Detect phantom rotation using insert positions (delegates to shared utility).

Parameters:

initial_angle_deg – Initial rotation guess in degrees (default 0)

Returns:

Rotation angle in degrees (sets and returns self.rotation_offset)

get_results_summary() str[source]

Get formatted summary of analysis results.

Returns:

Multi-line string summary

to_dict() Dict[source]

Export results as dictionary.

Returns:

Results dictionary

Unified CTP515 Low-Contrast Analyzer for CatPhan Phantom Analysis

This module provides low-contrast detectability analysis for the CatPhan CTP515 module. Analyzes circular inserts of varying diameters (15, 9, 8, 7, 6, 5 mm) to measure Contrast-to-Noise Ratio (CNR) and contrast detectability.

class alexandria.analyzers.ctp515.CTP515Analyzer(image: ndarray | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, angle_offset: float = 0.0, dicom_set: List | None = None, slice_index: int | None = None, center_finder: Callable[[...], Tuple] | None = None, center_finder_kwargs: Dict[str, Any] | None = None, center_threshold: float = 400.0, center_threshold_fallback: float = 300)[source]

Bases: object

Low-contrast detectability analyzer for CatPhan CTP515 module.

Detects and analyzes six low-contrast circular inserts of varying diameters positioned at fixed angles and distance from center. Computes Contrast-to-Noise Ratio (CNR) and contrast percentage for each ROI relative to a background region.

CNR quantifies detectability: higher values indicate the insert is more easily distinguished from background noise.

Supports both single-image mode and DICOM-series mode with 3-slice averaging.

image

2D CT image of the low-contrast module.

Type:

np.ndarray

center

(x, y) center of phantom in pixels.

Type:

tuple

pixel_spacing

Pixel spacing in mm.

Type:

float

angle_offset

Angular offset for ROI positioning in degrees.

Type:

float

results

Analysis results populated by analyze().

Type:

dict

ROI_ANGLES = [-87.4, -69.1, -52.7, -38.5, -25.1, -12.9]
ROI_DISTANCE_MM = 50
ROI_RADII_MM = [6, 3.5, 3, 2.5, 2, 1.5]
ROI_SETTINGS = {'15': {'angle_idx': 0, 'radius_mm': 6}, '5': {'angle_idx': 5, 'radius_mm': 1.5}, '6': {'angle_idx': 4, 'radius_mm': 2}, '7': {'angle_idx': 3, 'radius_mm': 2.5}, '8': {'angle_idx': 2, 'radius_mm': 3}, '9': {'angle_idx': 1, 'radius_mm': 3.5}}
analyze(verbose: bool = True) Dict[str, Any][source]

Perform low-contrast detectability analysis.

This method: 1. Defines ROI locations based on predefined angles and distances. 2. For each ROI, creates a circular mask and computes mean/std. 3. Computes a common background ROI for noise reference. 4. Calculates CNR for each ROI against the background. 5. Returns a summary of detected ROIs and their metrics.

Parameters:

verbose – Whether to print progress information.

Returns:

Contains ‘n_detected’ (int) and ‘blobs’ (dict of blob stats).

Each blob entry has position, size, means, std, and CNR.

Return type:

Dict

get_plot_data() Dict[str, Any][source]

Get data needed for plotting visualizations.

get_results_summary() Dict[str, str][source]

Get a formatted summary of analysis results.

Returns:

Dictionary with key measurements formatted as strings.

prepare_image()[source]

Prepare image for analysis.

In DICOM mode: Create 3-slice averaged image for improved SNR. In single-image mode: Use the provided image directly.

Returns:

Prepared image array

to_dict() Dict[str, Any][source]

Return JSON-compatible results dictionary.

Returns:

Dictionary with all analysis results.

Wrappers

Uniformity Module Wrapper

Combines UniformityAnalyzer with UniformityPlotter for convenient analysis and visualization in a single class.

class alexandria.wrappers.uniformity_wrapper.UniformityModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, roi_box_size: float = 15.0, roi_offset: float = 50.0)[source]

Bases: object

analyze(verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() Dict[str, str][source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 300, **kwargs)[source]

High Contrast Module Wrapper

Combines HighContrastAnalyzer with HighContrastPlotter for convenient MTF/resolution analysis and visualization.

class alexandria.wrappers.high_contrast_wrapper.HighContrastModuleReporter(image: Any | None = None, pixel_spacing: float | None = None, center: Tuple[float, float] | None = None, t_offset_deg: float = 0.0, rotation_offset: float | None = None, dicom_set: List | None = None, slice_index: int | None = None, lp_r_mm: float = 48.0, samples_per_segment: int = 50)[source]

Bases: object

analyze(write_log: bool = False, verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() Dict[str, str][source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 300, **kwargs)[source]

CTP401 Module Wrapper

Combines CTP401Analyzer with CTP401Plotter for convenient 4-ROI linearity analysis and visualization in a single class.

class alexandria.wrappers.ctp401_wrapper.CTP401ModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, roi_radius: float = 3.5, material_distance: float = 58.5, edge_threshold: float = 100.0)[source]

Bases: object

analyze(t_offset: float = 0.0, verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(t_offset: float = 0.0, verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
detect_rotation(initial_angle_deg: float = 0.0) float[source]
get_summary() str[source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 150, **kwargs)[source]

CTP404 Module Wrapper

Combines CTP404Analyzer with CTP404Plotter for convenient 9-ROI sensitometry analysis and visualization in a single class.

class alexandria.wrappers.ctp404_wrapper.CTP404ModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, spacing: float | None = None, dicom_set: List[Any] | None = None, slice_index: int | None = None, rotation_offset: float = 0.0, roi_radius: float = 3.5, material_distance: float = 58.5)[source]

Bases: object

analyze(verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() str[source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 150, **kwargs)[source]

CTP515 Module Wrapper

Combines CTP515Analyzer with CTP515Plotter for convenient low-contrast analysis and visualization.

class alexandria.wrappers.ctp515_wrapper.CTP515ModuleReporter(image: Any | None = None, center: Tuple[float, float] | None = None, pixel_spacing: float | None = None, angle_offset: float = 0.0, dicom_set: List | None = None, slice_index: int | None = None)[source]

Bases: object

analyze(verbose: bool = True) Dict[str, Any][source]
analyze_and_plot(verbose: bool = True, show: bool = False, **kwargs) Tuple[Dict[str, Any], Figure][source]
close_plot()[source]
get_summary() Dict[str, str][source]
plot(show: bool = False, **kwargs) Figure[source]
save_plot(filepath: str, dpi: int = 300, **kwargs)[source]

Plotters

Uniformity Plotter

Creates comprehensive visualization plots for uniformity analysis results.

class alexandria.plotters.uniformity_plotter.UniformityPlotter(analyzer)[source]

Bases: object

Plotter for UniformityAnalyzer results.

plot()[source]

Detailed Uniformity Plotter

Plots concentric profile values (angle vs HU) and overlayed histograms.

class alexandria.plotters.detailed_uniformity_plotter.DetailedUniformityPlotter(analyzer)[source]

Bases: object

Plotter for DetailedUniformityAnalyzer results.

plot(bins: int = 25, figsize: tuple = (14, 20)) Figure[source]

High Contrast Plotter

Creates visualization plots for MTF/resolution analysis results.

class alexandria.plotters.high_contrast_plotter.HighContrastPlotter(analyzer)[source]

Bases: object

Creates visualization plots for HighContrastAnalyzer results.

plot(figsize: tuple = None, vmin: float = None, vmax: float = None, **kwargs) Figure[source]

CTP401 Plotter

Creates comprehensive visualization plots for 4-ROI linearity analysis results. Displays main image with ROI circles, per-ROI histograms, and 2D heatmaps.

class alexandria.plotters.ctp401_plotter.CTP401Plotter(analyzer, vmin: float = None, vmax: float = None)[source]

Bases: object

Plotter for AnalyzerCTP401 results.

plot()[source]

CTP404 Plotter

Creates visualization plots for 9-ROI contrast/sensitometry analysis results.

class alexandria.plotters.ctp404_plotter.CTP404Plotter(analyzer)[source]

Bases: object

Creates visualization plots for CTP404Analyzer results.

plot(figsize: tuple | None = None, vmin: float | None = None, vmax: float | None = None, **kwargs) Figure[source]

CTP515 Plotter

Creates comprehensive visualization plots for low-contrast detectability analysis results. Displays image with color-coded ROIs, dual-axis CNR/Contrast plots, and statistics table.

class alexandria.plotters.ctp515_plotter.CTP515Plotter(analyzer)[source]

Bases: object

Plotter for AnalyzerCTP515 (low-contrast detectability) results.

Creates a 2x2 layout displaying:
  • Image with color-coded ROI circles and background ROI

  • Dual-axis plot of CNR and Contrast vs. ROI diameter

  • Statistics table showing mean, std, CNR, and contrast for each ROI

ROIs are color-coded by diameter size with adaptive contrast windowing to enhance visibility of low-contrast features.

Parameters:

analyzer (AnalyzerCTP515) – Completed analyzer instance with results.

plot()[source]

Generate visualization of low-contrast ROI analysis.

Layout:
  • Top left: Image with ROI overlays

  • Top right: CNR and Contrast vs. ROI Diameter (dual y-axes)

  • Bottom: Statistics table

Utilities

Image Processing utilities used across Alexandria analyzers.

This module collects lightweight, well-documented image processing helpers commonly needed by CatPhan analyzers and plotters.

class alexandria.utils.image_processing.ImageProcessor[source]

Bases: object

static apply_gaussian_filter(image: ndarray, sigma: float = 1.0) ndarray[source]
static estimate_noise(image: ndarray, roi_center: Tuple[float, float] | None = None, roi_size: int = 50) float[source]
static extract_profile(image: ndarray, start: Tuple[float, float], end: Tuple[float, float], n_points: int = 100) ndarray[source]
static find_edges(image: ndarray, method: str = 'sobel') ndarray[source]
static threshold_image(image: ndarray, threshold: float, mode: str = 'above') ndarray[source]

Geometry Utilities for CatPhan Phantom Analysis

Provides functions for finding phantom centers, rotations, and geometric measurements.

class alexandria.utils.geometry.CatPhanGeometry[source]

Bases: object

Legacy class-based geometry helpers. Prefer the module-level functions for new code.

static calculate_slice_thickness(image: ndarray, pixel_spacing: float, center: Tuple[float, float]) float[source]

Measure slice thickness via FWHM of the wire-ramp profile.

Extracts a strip ROI offset from center toward the wire ramp, identifies the column with the highest integrated signal, locates the ramp peak with scipy.signal.find_peaks(), and converts the FWHM to mm using the 23-degree ramp angle.

Parameters:
  • image – 2-D CT image array containing the wire-ramp feature.

  • pixel_spacing – In-plane pixel size in mm.

  • center – (x, y) phantom centre in pixels.

Returns:

Slice thickness in mm.

static find_center(image: ndarray, threshold: float = 400) Tuple[List[float], List[ndarray]][source]

Locate the phantom centre from a 2-D CT image using threshold crossings.

Scans the horizontal and vertical profiles through the image midpoint and finds the first/last pixel that exceeds threshold. If no crossings are found at the requested threshold, retries at 300 HU.

Parameters:
  • image – 2-D CT image array (HU values).

  • threshold – HU threshold used to detect the phantom edge (default 400).

Returns:

[x, y] coordinates of the phantom centre in pixels. boundary: [outer_x, outer_y] arrays tracing the estimated circular

phantom boundary.

Return type:

center

static select_optimal_ctp528_slices(dicom_set: List, target_index: int, search_range: int = 2) Tuple[ndarray, ndarray, float][source]

Select the optimal CTP528 slice image via 3-slice averaging.

Loads 2 * search_range + 1 slices centred on target_index, traces a semicircular line-pair profile through each, identifies the slice with the highest mean profile intensity, then returns a pixel-averaged image from the three slices surrounding that peak (or two slices at the boundary).

Parameters:
  • dicom_set – Ordered list of DICOM dataset objects covering the CTP528 module.

  • target_index – Index of the intended CTP528 slice within dicom_set.

  • search_range – Number of slices either side of target_index to consider when selecting the optimal slice (default 2).

Returns:

Averaged 2-D image array. means : Mean profile intensity for each candidate slice. z_mean: Mean slice offset (relative to target_index) of the averaged slices.

Return type:

im

alexandria.utils.geometry.circular_roi_mask(shape: Tuple[int, int], center: Tuple[float, float], radius: float) ndarray[source]

Create a boolean mask for a circular ROI.

Parameters:
  • shape – Image dimensions as (height, width).

  • center – (x, y) centre of the circle in pixels.

  • radius – Circle radius in pixels.

Returns:

Boolean array of shape; True inside the circle, False outside.

alexandria.utils.geometry.compute_phantom_boundary(image: ndarray, center: Tuple[float, float], pixel_spacing: float | None = None, threshold: float = -900, fallback_threshold: float = -900) Tuple[Tuple[float, float], Tuple[ndarray, ndarray]][source]

Estimate the circular phantom boundary from a CT image.

Scans the row and column that pass through center, finds the first and last pixel exceeding threshold, and derives the phantom radius as the average of the horizontal and vertical extents. Falls back to fallback_threshold if the primary threshold yields no crossings. As a last resort, if pixel_spacing is provided, assumes a 100 mm radius.

Parameters:
  • image – 2-D CT image array.

  • center – (x, y) phantom centre in pixels.

  • pixel_spacing – Pixel size in mm; used only for the last-resort fallback.

  • threshold – Primary HU threshold for edge detection (default -900).

  • fallback_threshold – Secondary threshold tried when the primary fails.

Returns:

Refined (x, y) centre derived from the threshold crossings. boundary : (outer_x, outer_y) arrays tracing the estimated circular boundary. On complete failure returns ((0, 0), (empty, empty)).

Return type:

detected_center

alexandria.utils.geometry.draw_boundary(center: Tuple[float, float], diameter_x_px: float | None, diameter_y_px: float | None, n_points: int = 100) Tuple[ndarray, ndarray][source]

Compute the perimeter points of an elliptical phantom boundary.

Parameters:
  • center – (x, y) centre of the boundary in pixels.

  • diameter_x_px – Full horizontal diameter in pixels.

  • diameter_y_px – Full vertical diameter in pixels.

  • n_points – Number of points used to discretise the perimeter (default 100).

Returns:

(x_coords, y_coords) arrays of boundary points. Returns empty arrays if either diameter is None.

alexandria.utils.geometry.find_center_edge_detection(img: ndarray, threshold: float = -900, fallback_threshold: float = -900, return_diameters: bool = False)[source]

Find the phantom centre using threshold crossings along the image midlines.

Extracts the central row and column of img and locates the first and last pixels above threshold. The centre is the midpoint of those crossings. If the primary threshold fails, fallback_threshold is tried. If both fail, the geometric image centre is returned.

Parameters:
  • img – 2-D CT image array.

  • threshold – Primary HU threshold for phantom edge detection (default -900).

  • fallback_threshold – Secondary threshold used when the primary fails.

  • return_diameters – If True, also return the detected horizontal and vertical diameters in pixels.

Returns:

(center_row, center_col) when return_diameters is False. (center_row, center_col, diameter_y_px, diameter_x_px) when True. Diameter values are None if detection failed entirely.

alexandria.utils.geometry.find_center_mirror_correlation(image: ndarray, max_shift: int | None = None) Tuple[float, float, None, None][source]

Estimate phantom centre from whole-image mirror-correlation symmetry.

This optional centre finder treats left-right and top-bottom symmetry as two separate 1-D alignment problems. For each axis it mirrors the image, slides the mirrored copy over a range of integer shifts, evaluates a normalized correlation score at each shift, and then refines the best shift with a three-point parabolic fit. The refined horizontal and vertical shifts are converted into a centre estimate relative to the image midpoint.

The return signature intentionally matches the contract already used by find_center_edge_detection() so callers such as UniformityAnalyzer.center_finder can switch algorithms without special case unpacking. This algorithm estimates centre only; it does not directly measure phantom diameters, so the diameter slots are returned as None.

Parameters:
  • image – 2-D phantom image array.

  • max_shift – Optional cap on the integer shift search range for each axis.

Returns:

Estimated centre row in pixels. center_col : Estimated centre column in pixels. diameter_y_px: Always None for this method. diameter_x_px: Always None for this method.

Return type:

center_row

alexandria.utils.geometry.find_rotation(image: ndarray, center: Tuple[float, float] | None, pixel_spacing: float | Tuple[float, float] | List[float], insert_radius_mm: float = 58.5, edge_threshold: float = 100.0, center_threshold: float = 30, iterations: int = 5, profile_length: int = 25, granularity: int = 4, interp_kwargs: dict | None = None, initial_angle_deg: float = 0.0)[source]

Detect phantom rotation by locating the top and bottom air/insert positions.

Seeds two search points at the 270° (top) and 90° (bottom) positions on the insert ring. Each point is iteratively refined by fitting horizontal and vertical profiles through the insert and finding the midpoint between the two sharpest edges. The rotation angle is derived from the final vector between the two refined points.

The refinement loop is aborted and the seed positions are restored if any iteration moves a point by more than center_threshold pixels, which guards against edge-detection failures on noisy or low-contrast images.

Parameters:
  • image – 2-D CT image array.

  • center – (x, y) phantom centre in pixels. Detected automatically if None.

  • pixel_spacing – Pixel size in mm. Accepts a scalar, or the first element of a sequence (e.g. DICOM PixelSpacing).

  • insert_radius_mm – Distance from phantom centre to the insert ring in mm (default 58.5 mm).

  • edge_threshold – Minimum absolute derivative height required to accept a peak as an insert edge (default 100.0 HU/px). Lower this for smooth or low-contrast reconstructions.

  • center_threshold – Maximum allowed shift per iteration in pixels before the refinement is abandoned (default 30 px).

  • iterations – Maximum number of refinement iterations (default 5).

  • profile_length – Half-length of each sampling profile in pixels (default 25).

  • granularity – Number of sub-pixel samples per pixel along the profile (default 3). Higher values improve precision at the cost of more interpolation calls.

  • interp_kwargs – Keyword arguments forwarded to scipy.interpolate.interpn. Defaults to {'bounds_error': False, 'fill_value': 0}.

  • initial_angle_deg – Seed rotation angle in degrees (default 0). Use when you know the phantom is already rotated significantly.

Returns:

Rotation angle in degrees (positive = CCW). ct : Refined (x, y) position of the top insert (nominally 270°). cb : Refined (x, y) position of the bottom insert (nominally 90°).

Return type:

rotation_from_y