v3
scan_metadata record, v3 — canonical aliases.
v3 is v2's table, which is v1's table. There is no schema change: the ORM, the record and the store are v1's, re-exported, for the reasons v2's docstring sets out.
What v3 adds is migrations.upgrade, a data migration that clears the
scan_datetime values the old parse order could have written wrong, and marks
their files for re-extraction. A version is the only thing the migration
engine will hang that on, which is why v3 exists at all.
Module
Submodules
- bitfount.cache.types.scan_metadata.v3.migrations - Migration for
scan_metadatav2 -> v3: drop rows whose timestamp may be wrong.
Functions
upgrade
def upgrade(op: Operations) ‑> None:Delete the rows of every file holding a timestamp that may be wrong.
Idempotent: the rows it would delete are gone after the first pass, and a file it left alone holds nothing suspect, 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 deletion 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.
Ancestors
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.
Ancestors
Variables
- static
dataset_identifier : str | None
- static
file_path : str
- static
model_config
- static
processed_at : datetime.datetime
- static
reason : str | None
- static
run_id : str | None
- static
series_index : int
- static
source_file_hash : str | None
- static
tags : dict[str, typing.Any] | None