Skip to main content

v2

scan_metadata record, v2 — canonical aliases.

v2 is v1's table, with scan_datetime normalised. There is no schema change at all: the ORM, the record and the store are v1's, re-exported rather than copied.

Copying them was the first shape and it was wrong. A version package that duplicates its predecessor freezes that predecessor as it was on the day it was copied, so every later change to v1 — new columns, new helpers, a reworded reason string — silently fails to reach anyone reading through v2. v1 gained a reasons module and a reworked store within weeks of this being written, and a copied v2 would have reverted both for its consumers.

What v2 adds is migrations.upgrade, a data migration that rewrites the column into one comparable spelling. A version is the only thing the migration engine will hang that on, which is why v2 exists at all.

The record registry requires ORM, Record and store on a version package and does not care where they come from, so re-exporting satisfies it. Both versions therefore name one ORM class and one table — deliberately, since they describe the same table.

Module​

Submodules​

Functions​

upgrade​

def upgrade(op: Operations) ‑> None:

Rewrite every scan_datetime into ISO-8601 UTC (see the module docstring).

Idempotent: a row already in the target spelling normalises to itself and is not rewritten, so replaying the hop by hand is safe.

Arguments

  • op: The bound Alembic operations handle; its connection is the one the caller's per-hop transaction runs in, so the rewrite commits or rolls back with the version bump.

Classes​

ORM​

class ORM(**kwargs):

SQLAlchemy model for the scan_metadata cache table.

Stores vendor-normalized, header-only per-scan metadata (laterality, geometry, patient demographics, device) extracted from ophthalmology files without any pixel decode or model inference. One row per acquisition series.

A simple constructor that allows initialization from kwargs.

Sets attributes on the constructed instance using the names and values in kwargs.

Only keys that are present as attributes of the instance's class are allowed. These could be, for example, any mapped columns or relationships.

Variables​

  • dataset_identifier : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • date_of_birth : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • dimensions_mm_depth : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • dimensions_mm_height : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • dimensions_mm_width : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • file_path : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • first_name : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • fixation : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • gender : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • last_name : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • laterality : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • manufacturer : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • num_bscans : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • patient_key : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • processed_at : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • protocol : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • reason : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • resolutions_mm_depth : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • resolutions_mm_height : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • resolutions_mm_width : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • run_id : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • scan_datetime : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • scanner_model : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • series_description : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • series_index : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • size_height : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • size_width : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • slo_dimensions_mm_height : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • slo_dimensions_mm_width : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • slo_size_height : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • slo_size_width : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • source_file_hash : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]
  • tags : Union[sqlalchemy.orm.attributes.InstrumentedAttribute[+_T_co], +_T_co]

Record​

class Record(**data: Any):

Record of a single stored row from the scan_metadata table (one per scan).

Extends NormalizedScanFields with the composite primary key (file_path, series_index) and the control/provenance columns.

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 dataset_identifier : str | None
  • static file_path : str
  • static model_config
  • static reason : str | None
  • static run_id : str | None
  • static series_index : int
  • static source_file_hash : str | None