Skip to main content

config

Config for the criteria matching step (v1).

Classes

CriteriaMatchConfig

class CriteriaMatchConfig(**data: Any):

Config for the inclusion-criteria matching step.

Every bound is optional: when a bound is None the corresponding filter is not applied. The code lists (conditions_* / procedures_*) follow the same rule — an empty/None list applies no filter. Codes support * glob wildcards (e.g. "E11*" matches "E11.65").

The three boolean switches are blankable (see BlankableDefaultsConfig): a modeller who leaves one blank gets its declared default, not a validation error. exclude_foveal_ga defaults off; the two eligible_on_*_codes_lat_unknown policies default permissive, which is not the same as off — they decide the verdict when a matched code's laterality is indeterminate, so a None reaching the code filters would be read as UNKNOWN and mark those patients ineligible.

Inclusion codes: a patient is eligible if any one of their codes matches. Exclusion codes: a patient is ineligible if any one of their codes matches.

The any-eye lists (conditions_inclusion, conditions_exclusion, procedures_inclusion, procedures_exclusion) match regardless of eye. The _study_eye lists narrow their non-suffixed counterpart to codes whose laterality is inferred to include the scan's study eye (procedures_inclusion has no study-eye variant). eligible_on_*_lat_unknown govern the code-laterality-indeterminate case. code_exclusion_time_windows maps an exclusion code (or * glob) to a {within_days|within_months|within_years} recency window.

column_criteria matches arbitrary produced columns by name; prefer a typed field above where one already exists for the column.

hypertransmission_threshold, neurosensory_retina_atrophy_threshold, hard_exudates_threshold, and wet_amd_threshold are the single-scan biomarker thresholds: a patient is eligible when the biomarker's area (or, for wet_amd, its max classification probability) is at or below (<=) the configured bound.

The drusen thresholds are single-scan biomarker inclusion signals (>=), in contrast to the <= exclusion thresholds above. hard_drusen_threshold, soft_drusen_threshold, and confluent_drusen_threshold each gate on their own subtype's max_<subtype>_probability being at or above the bound. drusen_threshold is the combined signal: a patient qualifies when any of the three subtype probabilities is at or above its bound (an OR across subtypes), evaluated with its own threshold value.

The CST/GCC/fluid range fields (cst_min_um/cst_max_um, gcc_superior_*, gcc_inferior_*, and the *_fluid_*/*_volume pairs) are inclusive-window scan-metric criteria: a patient is eligible when the metric column is >= the min bound and <= the max bound. They gate on the columns produced by the CST/GCC/fluid calc steps.

drusen_roi_max_base_width_lower_bound is a lesion-geometry inclusion criterion: a scan qualifies when the widest drusen lesion inside the fovea-centred ROI is strictly WIDER THAN (>) the bound. Unlike the drusen probability thresholds it reads a lesion_calculation group column (DRUSEN_ROI_MAX_BASE_WIDTH_COL), so that step must be wired and must measure a group named drusen with measure_lesions: true.

ez_intact_max_span_lower_bound is the EZ-integrity inclusion criterion: a scan qualifies when the widest contiguous span of un-attenuated ellipsoid zone on the fovea-reference B-scan is strictly greater (>) than the bound, in micrometres. It gates on ez_intact_max_span_um, which only cst_calculation v2 produces, and only when that step has its own ez_attenuation_threshold_um set. Those two numbers are different thresholds doing different jobs: the step's is a per-A-scan separation applied before the run-length reduction, and cannot live here because a ColumnFilter can only compare the resulting scalar; this one is the span length the trial protocol asks for. Setting this bound while the step is on v1, or on v2 with no threshold, leaves the column absent or all-null and marks every scan unknown — see _warn_on_unusable_ez_span_column.

appointment_history requires the patient's appointment/encounter history to span years years with at least min_per_year appointments in each of them. current_patient_months requires an appointment within that many months of now. Both read the EHR-sourced appointment columns, so both report UNKNOWN when the ehr_query step ran without fetch_appointments.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Variables

  • static cnv_threshold : float | None
  • static code_exclusion_time_windows : dict[str, dict[str, int]] | None
  • static conditions_exclusion : Optional[list[str]]
  • static conditions_exclusion_study_eye : Optional[list[str]]
  • static conditions_inclusion : Optional[list[str]]
  • static conditions_inclusion_study_eye : Optional[list[str]]
  • static confluent_drusen_threshold : float | None
  • static cst_max_um : float | None
  • static cst_min_um : float | None
  • static current_patient_months : int | None
  • static distance_from_fovea_lower_bound : float | None
  • static distance_from_fovea_upper_bound : float | None
  • static drusen_roi_max_base_width_lower_bound : float | None
  • static drusen_threshold : float | None
  • static eligible_on_exclusion_codes_lat_unknown : bool
  • static eligible_on_inclusion_codes_lat_unknown : bool
  • static exclude_foveal_ga : bool
  • static ez_intact_max_span_lower_bound : float | None
  • static gcc_inferior_max_um : float | None
  • static gcc_inferior_min_um : float | None
  • static gcc_superior_max_um : float | None
  • static gcc_superior_min_um : float | None
  • static hard_drusen_threshold : float | None
  • static hard_exudates_threshold : float | None
  • static hypertransmission_threshold : float | None
  • static intraretinal_fluid_max_volume : float | None
  • static intraretinal_fluid_min_volume : float | None
  • static largest_ga_lesion_lower_bound : float | None
  • static largest_ga_lesion_upper_bound : float | None
  • static model_config
  • static n_scan_diabetic_macular_edema_typical_width_micrometers : float | None
  • static n_scan_diffuse_edema_typical_width_micrometers : float | None
  • static n_scan_epiretinal_fibrosis_typical_width_micrometers : float | None
  • static n_scan_intraretinal_cystoid_fluid_typical_width_micrometers : float | None
  • static n_scan_subretinal_fluid_typical_width_micrometers : float | None
  • static n_scan_subretinal_hyperreflective_material__shrm__typical_width_micrometers : float | None
  • static neurosensory_retina_atrophy_threshold : float | None
  • static patient_age_lower_bound : int | None
  • static patient_age_upper_bound : int | None
  • static procedures_exclusion : Optional[list[str]]
  • static procedures_exclusion_study_eye : Optional[list[str]]
  • static procedures_inclusion : Optional[list[str]]
  • static serous_rpe_detachment_max_volume : float | None
  • static serous_rpe_detachment_min_volume : float | None
  • static soft_drusen_threshold : float | None
  • static subretinal_fluid_max_volume : float | None
  • static subretinal_fluid_min_volume : float | None
  • static total_fluid_max_volume : float | None
  • static total_fluid_min_volume : float | None
  • static total_ga_area_lower_bound : float | None
  • static total_ga_area_upper_bound : float | None
  • static wet_amd_threshold : float | None
  • all_generic_criteria - Every generic ColumnCriterion: column_criteria plus tree leaves.

    has_ga_related_filters and the biomarker-column materialisation helpers (_referenced_labels and related helpers in v1/task.py) need every generically-addressed column a config might reference, not just column_criteria — otherwise a criteria_tree-only reference to a GA-derived column is invisible to those checks. Cached: a config is immutable once parsed, and this is read from several call sites per criteria_matching_task run, each of which would otherwise re-walk the whole criteria_tree.

    Filtered to ColumnCriterion specifically, not every CriterionLeaf: a CodeCriterion tree leaf has no .column at all, so including one here would break every caller's criterion.column access, not just widen what they see.

  • has_ez_span_filter : bool - Whether the EZ-integrity span criterion is configured.

    A generic column_criteria entry (or criteria_tree leaf) targeting the same column counts, so the criterion triggers its diagnostic however it was expressed — the same rule has_ga_related_filters follows.

  • has_ga_related_filters : bool - Whether any GA-metric-derived filter is configured.

    These filters need ga_metrics to be supplied in order to be evaluated; if they are set but no metrics are provided the relevant columns are absent and every row fails them. A generic column_criteria entry (or criteria_tree ColumnCriterion leaf — see all_generic_criteria) targeting a GA-derived column counts too, so a GA threshold expressed either way still triggers the missing-metrics warning and the all-GA-missing early exit.

  • has_lesion_related_filters : bool - Whether any criterion targets a lesion_calculation group column.

    Covers both the typed drusen_roi_max_base_width_lower_bound and any generic criterion whose column looks like a group metric.

    Area-group column names are <group>_<metric> with the group set by the step's own config, so — unlike _GA_RELATED_COLUMNS — there is no static universe to test membership against. Match on the metric suffix instead: a column ending in one of LESION_GROUP_METRIC_SUFFIXES with a non-empty group prefix can only come from an area source. No pre-existing scan column ends in one of those suffixes; a unit test pins that assumption, so it fails loudly if one ever does.

    LESION_GROUP_METRIC_SUFFIXES is already lowercase and space-free, so only the criterion's column needs normalizing before the suffix comparison.

    A column another scan-metrics source already owns is excluded, because the shape is ambiguous: fluid_distance_from_image_centre is fluid's own canonically-prefixed field, not a group named fluid — and LesionCalculationConfig rejects such a group name outright, so it cannot be one. Without the exclusion a criterion on a fluid column warns that a lesion_metrics source is missing, which sends the reader after the wrong step.

    Used to warn when such a criterion is configured with no lesion_metrics source wired — otherwise the column is simply absent and every row evaluates unknown with no signal that the step is missing from the DAG.