Skip to main content

column

Column-based trial inclusion filter.

Module

Functions

normalize_column_name

def normalize_column_name(name: str)> str:

Normalize a column name for case/space-insensitive comparison.

Lower-cases and strips spaces so "totalgaarea" matches "Total GA Area". The single source of truth for how a column name is resolved — matched_column (and grain resolution in criteria_matching.functions) call this so they cannot drift apart.

Arguments

  • name: The raw column name.

Returns The normalized name.

resolve_column

def resolve_column(name: str, columns: typing.Iterable[str])> str | None:

Resolve name to the actual column in columns, case/space-insensitively.

Prefers an exact match (fast path), then falls back to a normalized match via normalize_column_name so "totalgaarea" resolves "Total GA Area". This is the shared resolution both ColumnFilter and MethodFilter use so that a criterion whose configured column name differs only in casing/spacing from the produced frame column reads the right cell instead of treating it as missing.

Arguments

  • name: The column name to resolve (e.g. from a column_criteria entry).
  • columns: The actual column names to resolve against (a frame's columns or a row's index).

Returns The matching column name from columns, or None if none matches.

Classes

ColumnFilter

class ColumnFilter(    column: str,    operator: str,    value: str | int | float | list[str | int | float],    how: PartialMatchingType = 'all',    config_field: str | None = None,    output_field: str | None = None,    grain: CriterionGrain = scan,    family: CriterionFamily | None = None,    tree_node_id: str | None = None,):

Dataclass for basic single column filtering.

Arguments

  • column: The column name on which the filter will be applied.
  • operator: The operator for the filtering operation.
  • value: The value for the filter.
  • how: Partial matching type ("any" or "all").
  • config_field: Originating CriteriaMatchConfig field name, or None if this filter was not built from a config (e.g. constructed directly in a test).
  • output_field: Logical field name this filter's outcome is reported under (typically the filter's column), or None if unset.
  • grain: Whether this filter is evaluated per scan or per patient. Defaults to CriterionGrain.SCAN. This is the grain (cardinality) axis, not provenance — a criterion's data source is resolved from its column in build_criterion_outcomes, not set here.
  • family: The semantic criterion family this filter belongs to (see CriterionFamily), declared by the build site in build_eligibility_filters. Pod-internal: a task config authoring a ColumnFilter by hand leaves it unset, which is why it is optional rather than required. None therefore means "not built by build_eligibility_filters", and the served criterion reports no family.
  • tree_node_id: The criteria_tree leaf id this filter was built from, or None for a filter not built from a tree leaf. Stamped onto the resulting CriterionOutcome by build_criterion_outcomes.

A ColumnFilter is one declarative, self-describing scalar comparison: a single column compared against a scalar value (or, for in/not in, a value-set) with an operator, evaluated vectorized over the column. Use it whenever the criterion is a single-column scalar comparison. For anything that is not — multi-column rules, list/collection-valued cells, glob/regex matching — use a MethodFilter instead. A produced CriterionOutcome from a ColumnFilter carries kind="column".

Variables

  • static column : str
  • static config_field : str | None
  • static how : Literal['any', 'all']
  • static operator : str
  • static output_field : str | None
  • static tree_node_id : str | None
  • static value : str | int | float | list[str | int | float]
  • identifier : str - Identifying string for this filter to use in logs.

Methods


apply_filter

def apply_filter(    self, df: pd.DataFrame, rename_columns: typing.Mapping[str, str] | None = None,)> pandas.core.frame.DataFrame:

Apply self filter to a dataframe.

evaluate_row

def evaluate_row(    self, row: pd.Series, matched: str | None,)> CriterionOutcome:

Evaluate this filter against one row, returning a structured outcome.

Self-contained: computes pass/fail directly from the operator (mirroring apply_filter's op(value) & notnull), so it does not depend on apply_filter having written any column. An absent target column or a NaN value yields unknown; absent_column distinguishes the two so the regenerated "not found" reason can render the raw column name (absent) rather than its display rename (present but NaN), matching apply_filter.

Arguments

  • row: The df row.
  • matched: The resolved df column (from matched_column), or None.

Returns The CriterionOutcome for this filter on this row.

matched_column

def matched_column(self, df: pd.DataFrame)> str | None:

Resolve the actual df column this filter targets, or None.

Matching is case- and space-insensitive (e.g. "totalgaarea" matches "Total GA Area"), mirroring the resolution apply_filter performs.

Arguments

  • df: The DataFrame whose columns are searched.

Returns The matching column name, or None if no column matches.

result_column

def result_column(self, matched: str)> str:

The per-filter boolean column name apply_filter writes.

Arguments

  • matched: The resolved df column name (from matched_column).

Returns The column name holding this filter's per-row pass/fail bool.