Skip to main content

thickness_calculation

Shared per-file thickness-calculation runner.

Ports the per-file orchestration loop of the legacy abstract base _BaseThicknessWorkerSide.run() (federated/algorithms/ophthalmology/base_thickness_calculation_algorithm.py, lines 134-273) into a single free function generic over the metric type.

Both the CST/CRT step and the GCC step share this entire orchestration — they differ only in the per-file calculate_metric closure they pass in. The metric-specific maths lives in each step's functions.py; the pure retinal-layer primitives live in thickness_metrics.py. This module is the only one that touches the datasource, so it is kept separate from the pure-math module.

Module

Functions

run_thickness_calculation

def run_thickness_calculation(    datasource: BaseSource,    layer_predictions: pd.DataFrame,    center_predictions: pd.DataFrame,    filenames: list[str],    *,    center_landmark_type: str,    metric_name: str,    calculate_metric: Callable[[pd.Series, pd.Series], T | str | None],)> dict[str, typing.Union[~T, str, NoneType]]:

Calculate a per-file thickness metric from model predictions.

Ported from _BaseThicknessWorkerSide.run(). Per-instance configuration previously read from self (the center-landmark type, the metric name used in logs, and the _calculate_metric hook) is passed as explicit parameters so both the CST and GCC steps reuse this unchanged.

An uncomputable file is recorded as a reason string rather than a silent None: no datasource metadata row yields "missing_data:metadata" and a raised exception yields "calculation_error:<detail>". A per-file calculate_metric hook may also return its own reason string. Callers persist a metric object to metrics_json and a reason string to error.

Arguments

  • datasource: File-iterable datasource providing DICOM metadata for each file (slice thickness, pixel spacing, etc.).
  • layer_predictions: DataFrame with retinal layer segmentation predictions (one Pixel_Data_*_prediction column per B-scan) and an _original_filename column.
  • center_predictions: DataFrame with predictions for the landmark centre (usually fovea or macular centre). Should contain central_slice and landmarks columns plus _original_filename.
  • filenames: List of files the results correspond to. If not provided (None), filenames are taken from layer_predictions.
  • center_landmark_type: Nature of the center landmark ("fovea"/"macula"). Used as the merge suffix for the center predictions.
  • metric_name: Name of the metric being calculated. Used only for log and error text.
  • calculate_metric: Per-file metric hook, called as calculate_metric(layer_pred, file_row). Returns the metric object, or a reason string when it cannot be computed.

Returns Dictionary mapping each original filename to its metric object, or a reason string (missing_data:* / calculation_error:*) when the file could not be computed.

widen_predictions

def widen_predictions(df: pd.DataFrame)> pandas.core.frame.DataFrame:

Expand the packed inferences_json dict column into wide columns.

The cache stores each row's predictions as a single packed dict under inferences_json; the thickness runner (ported from the v8 base) reads per-field wide columns (Pixel_Data_*_prediction for retinal layers, central_slice/landmarks for the fovea/macula centre). Mirrors the store's CollectedModelInferenceQueryResult.as_df(). Returns df unchanged when it has no packed column.

Shared by the CST and GCC calculation steps (both call it on their two RAW cached frames before handing them to run_thickness_calculation).