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:
objectAnalyzer 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
- 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
- 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:
objectUnified 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
imageparameter.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)
- 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
- 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:
objectLow-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
- 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_results_summary() Dict[str, str][source]
Get a formatted summary of analysis results.
- Returns:
Dictionary with key measurements formatted as strings.
- 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
- 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:
objectAnalyzer that samples concentric circular profiles for uniformity checks.
- 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:
objectAnalyzer for CatPhan’s CTP528 high-contrast (line pair) module.
- 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
- 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:
objectAnalyzer 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
Noneand the analyzer falls back tocompute_phantom_boundary(...)when it needs a boundary for plotting or diagnostics.
- REGIONS = ['centre', 'north', 'south', 'east', 'west']
- 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
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:
objectAnalyzer 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
Noneand the analyzer falls back tocompute_phantom_boundary(...)when it needs a boundary for plotting or diagnostics.
- REGIONS = ['centre', 'north', 'south', 'east', 'west']
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:
objectAnalyzer that samples concentric circular profiles for uniformity checks.
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:
objectAnalyzer for CatPhan’s CTP528 high-contrast (line pair) module.
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:
objectAnalyzer 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
- 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:
objectUnified 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
imageparameter.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)
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:
objectLow-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
- 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_results_summary() Dict[str, str][source]
Get a formatted summary of analysis results.
- Returns:
Dictionary with key measurements formatted as strings.
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
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
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
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
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
Plotters
Uniformity Plotter
Creates comprehensive visualization plots for uniformity analysis results.
- class alexandria.plotters.uniformity_plotter.UniformityPlotter(analyzer)[source]
Bases:
objectPlotter for UniformityAnalyzer results.
Detailed Uniformity Plotter
Plots concentric profile values (angle vs HU) and overlayed histograms.
- class alexandria.plotters.detailed_uniformity_plotter.DetailedUniformityPlotter(analyzer)[source]
Bases:
objectPlotter for DetailedUniformityAnalyzer results.
High Contrast Plotter
Creates visualization plots for MTF/resolution analysis results.
- class alexandria.plotters.high_contrast_plotter.HighContrastPlotter(analyzer)[source]
Bases:
objectCreates visualization plots for HighContrastAnalyzer results.
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:
objectPlotter for AnalyzerCTP401 results.
CTP404 Plotter
Creates visualization plots for 9-ROI contrast/sensitometry analysis results.
- class alexandria.plotters.ctp404_plotter.CTP404Plotter(analyzer)[source]
Bases:
objectCreates visualization plots for CTP404Analyzer results.
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:
objectPlotter 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.
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 estimate_noise(image: ndarray, roi_center: Tuple[float, float] | None = None, roi_size: int = 50) float[source]
Geometry Utilities for CatPhan Phantom Analysis
Provides functions for finding phantom centers, rotations, and geometric measurements.
- class alexandria.utils.geometry.CatPhanGeometry[source]
Bases:
objectLegacy 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
centertoward the wire ramp, identifies the column with the highest integrated signal, locates the ramp peak withscipy.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:
- 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 + 1slices centred ontarget_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_indexto 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 exceedingthreshold, and derives the phantom radius as the average of the horizontal and vertical extents. Falls back tofallback_thresholdif the primary threshold yields no crossings. As a last resort, ifpixel_spacingis 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
imgand locates the first and last pixels abovethreshold. The centre is the midpoint of those crossings. If the primary threshold fails,fallback_thresholdis 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_diametersis False. (center_row, center_col, diameter_y_px, diameter_x_px) when True. Diameter values areNoneif 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 asUniformityAnalyzer.center_findercan switch algorithms without special case unpacking. This algorithm estimates centre only; it does not directly measure phantom diameters, so the diameter slots are returned asNone.- 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
Nonefor this method. diameter_x_px: AlwaysNonefor 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_thresholdpixels, 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