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.
Ancestors
Variables
- static
appointment_history : AppointmentHistoryCriterion | None
- static
cnv_threshold : float | None
- static
code_exclusion_time_windows : dict[str, dict[str, int]] | None
- static
column_criteria : list[ColumnCriterion] | 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
criteria_tree : Union[ColumnCriterion, CodeCriterion, ObservationCriterion, MedicationCriterion, AllergyCriterion, DeviceCriterion, AndGroup, OrGroup, AtLeastGroup, NotGroup, ForwardRef(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 genericColumnCriterion:column_criteriaplus tree leaves.has_ga_related_filtersand the biomarker-column materialisation helpers (_referenced_labelsand related helpers inv1/task.py) need every generically-addressed column a config might reference, not justcolumn_criteria— otherwise acriteria_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 percriteria_matching_taskrun, each of which would otherwise re-walk the wholecriteria_tree.Filtered to
ColumnCriterionspecifically, not everyCriterionLeaf: aCodeCriteriontree leaf has no.columnat all, so including one here would break every caller'scriterion.columnaccess, not just widen what they see.
-
has_ez_span_filter : bool- Whether the EZ-integrity span criterion is configured.A generic
column_criteriaentry (orcriteria_treeleaf) targeting the same column counts, so the criterion triggers its diagnostic however it was expressed — the same rulehas_ga_related_filtersfollows.
-
has_ga_related_filters : bool- Whether any GA-metric-derived filter is configured.These filters need
ga_metricsto 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 genericcolumn_criteriaentry (orcriteria_treeColumnCriterionleaf — seeall_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 alesion_calculationgroup column.Covers both the typed
drusen_roi_max_base_width_lower_boundand 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 ofLESION_GROUP_METRIC_SUFFIXESwith 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_SUFFIXESis 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_centreis fluid's own canonically-prefixed field, not a group namedfluid— andLesionCalculationConfigrejects such a group name outright, so it cannot be one. Without the exclusion a criterion on a fluid column warns that alesion_metricssource is missing, which sends the reader after the wrong step.Used to warn when such a criterion is configured with no
lesion_metricssource wired — otherwise the column is simply absent and every row evaluatesunknownwith no signal that the step is missing from the DAG.