Domain models
Structured issues emitted by each ETL stage.
- class acmad_uploader.domain.issues.IssueSeverity(*values)
Bases:
StrEnumSeverity of a pipeline issue.
- ERROR = 'error'
- WARNING = 'warning'
- INFO = 'info'
- class acmad_uploader.domain.issues.PipelineIssue(code, severity, message, location=None)
Bases:
objectMachine-readable issue with an optional source location.
- code: str
- severity: IssueSeverity
- message: str
- location: SourceLocation | None
- display()
Return a concise representation suitable for CLI output.
- Return type:
str
- acmad_uploader.domain.issues.has_errors(issues)
Return whether an issue collection contains an error.
- Return type:
bool
Infrastructure-independent provenance attached to clinical values.
- class acmad_uploader.domain.provenance.SourceLocation(path, sheet=None, cell=None)
Bases:
objectLocation of a value in a source package.
- path: Path
- sheet: str | None
- cell: str | None
- display()
Return a concise, human-readable representation.
- Return type:
str
Canonical value for an out-of-band site acronym supplied by the caller.
- class acmad_uploader.domain.site_override.SiteOverride(acronym, source)
Bases:
objectA site acronym supplied via a CLI flag or package config file.
Cross-checked against (or used to fill in) each contributing workbook’s own
site_idfield - seetransformers.forms.cross_check_site_id.- acronym: str
- source: str
Canonical PatientEvent metadata shared by every event-creating ETL slice.
- class acmad_uploader.domain.patient_event.PatientEventDetails(year_of_assessment, region, state, country, irsd_decile, irsad_decile, ieo_decile, ier_decile)
Bases:
objectOptional demographic fields common to every
PatientEvent.Every event-creating slice (gait assessment, surgery) extracts these from its own anchor workbook and merges them into whichever
PatientEventit resolves or creates. All fields are optional at the API: the data dictionary marksyear_of_assessment/countryas required for clinics filling out the sheet, but the destination model itself allows them blank, so the ETL doesn’t enforce that here.- year_of_assessment: int | None
- region: str | None
- state: str | None
- country: str | None
- irsd_decile: int | None
- irsad_decile: int | None
- ieo_decile: int | None
- ier_decile: int | None
- static empty()
Return an instance with every field absent.
- Return type:
Canonical patient values shared by ETL stages.
- class acmad_uploader.domain.patient.BiologicalSex(*values)
Bases:
StrEnumBiological sex values accepted by the ACMAD API.
- FEMALE = 'female'
- MALE = 'male'
- NOT_SPECIFIED = 'not specified'
- NOT_APPLICABLE = 'not applicable'
- class acmad_uploader.domain.patient.Ethnicity(*values)
Bases:
StrEnumEthnicity values accepted by the ACMAD API.
- EUROPEAN = 'European'
- AUSTRALIAN = 'Australian'
- ABORIGINAL_TORRES_STRAIT_ISLANDER = 'Aboriginal/Torres Strait Islander'
- NEW_ZEALANDER = 'New Zealander'
- MAORI = 'Māori'
- PACIFIC_POLYNESIAN = 'Pacific/Polynesian'
- ASIAN = 'Asian'
- MIDDLE_EASTERN_LATIN_AMERICAN_AFRICAN = 'Middle Eastern/Latin American/African'
- OTHER = 'Other'
- UNKNOWN = 'Unknown'
- NOT_RECORDED = 'Not Recorded'
- class acmad_uploader.domain.patient.PatientRecord(site_patient_id, site_abbreviation, biological_sex, ethnicity, patient_hash, source)
Bases:
objectValidated patient master data independent of its source and destination.
- site_patient_id: str
- site_abbreviation: str
- biological_sex: BiologicalSex
- patient_hash: str | None
- source: SourceLocation
Canonical diagnosis values shared by ETL stages.
- class acmad_uploader.domain.diagnosis.DiagnosisType(*values)
Bases:
StrEnumWhether a diagnosis is a patient’s primary or a secondary diagnosis.
- PRIMARY = 'primary'
- SECONDARY = 'secondary'
- class acmad_uploader.domain.diagnosis.DiagnosisLaterality(*values)
Bases:
StrEnumLaterality values accepted by the ACMAD API.
Values match the API’s stored codes, not the data dictionary’s human labels (for example the workbook’s “not applicable” maps to
NA).- LEFT = 'left'
- RIGHT = 'right'
- BILATERAL = 'bilateral'
- NOT_SPECIFIED = 'not specified'
- NOT_APPLICABLE = 'NA'
- class acmad_uploader.domain.diagnosis.DiagnosisRecord(site_patient_id, site_abbreviation, diagnosis_type, age_at_diagnosis_days, diagnosis_group, diagnosis_subgroup, diagnosis_detail, laterality, source)
Bases:
objectValidated diagnosis independent of its source and destination.
definition(the matching admin-maintained diagnosis reference record) is deliberately not resolved here: the API matches and validates it server-side fromdiagnosis_group/diagnosis_subgroup/diagnosis_detail, and reference data can change independently of this package’s release cycle.- site_patient_id: str
- site_abbreviation: str
- diagnosis_type: DiagnosisType
- age_at_diagnosis_days: int
- diagnosis_group: str
- diagnosis_subgroup: str | None
- diagnosis_detail: str | None
- laterality: DiagnosisLaterality | None
- source: SourceLocation
Canonical gait assessment event values shared by ETL stages.
- class acmad_uploader.domain.gait_assessment.GaitAssessmentRecord(site_patient_id, site_abbreviation, age_in_days, event_details, sources)
Bases:
objectLinkage between a patient and one gait assessment event.
age_in_daystogether withsite_patient_idis the natural key shared by every workbook belonging to the same assessment (physical exam, function/PROMs and mocap), so records extracted from separate workbooks are joined on this pair rather than by folder position.- site_patient_id: str
- site_abbreviation: str
- age_in_days: int
- event_details: PatientEventDetails
- sources: tuple[SourceLocation, ...]
Canonical function assessment values shared by ETL stages.
- class acmad_uploader.domain.function_assessment.Gmfcs(*values)
Bases:
StrEnumGross Motor Function Classification System levels.
- LEVEL_I = 'I'
- LEVEL_II = 'II'
- LEVEL_III = 'III'
- LEVEL_IV = 'IV'
- LEVEL_V = 'V'
- NOT_SPECIFIED = 'not specified'
- class acmad_uploader.domain.function_assessment.FunctionalMobilityScale(*values)
Bases:
StrEnumFunctional Mobility Scale rating, used at 5/50/500 metre distances.
- N = 'N'
- C = 'C'
- ONE = '1'
- TWO = '2'
- THREE = '3'
- FOUR = '4'
- FIVE = '5'
- SIX = '6'
- class acmad_uploader.domain.function_assessment.FunctionalAmbulationClassification(*values)
Bases:
StrEnumFunctional Ambulation Classification (FAC) level.
- ZERO = '0'
- ONE = '1'
- TWO = '2'
- THREE = '3'
- FOUR = '4'
- FIVE = '5'
- class acmad_uploader.domain.function_assessment.FunctionAssessmentRecord(site_patient_id, age_in_days, gmfcs, fms_5, fms_50, fms_500, fac, source)
Bases:
objectValidated function assessment independent of its source and destination.
- site_patient_id: str
- age_in_days: int
- fms_5: FunctionalMobilityScale | None
- fms_50: FunctionalMobilityScale | None
- fms_500: FunctionalMobilityScale | None
- fac: FunctionalAmbulationClassification | None
- source: SourceLocation
Canonical mocap session values shared by ETL stages.
- class acmad_uploader.domain.mocap_data.SessionCondition(*values)
Bases:
StrEnumFootwear/aid condition of the mocap session.
- BAREFOOT = 'barefoot'
- AFO = 'AFO'
- SHOES = 'shoes'
- PROSTHETIC = 'prosthetic'
- OTHER = 'other'
- class acmad_uploader.domain.mocap_data.GaitAid(*values)
Bases:
StrEnumGait aid used during the mocap session.
- UNASSISTED = 'unassisted'
- HAND_HELD = 'hand held'
- ANTERIOR_WALKER = 'anterior walker'
- POSTERIOR_WALKER = 'posterior walker'
- STICKS = 'sticks'
- CRUTCHES = 'crutches'
- OTHER = 'other'
- class acmad_uploader.domain.mocap_data.ConditionDetail(*values)
Bases:
StrEnumDetailed per-side condition (e.g. orthosis/prosthetic type).
- BAREFOOT = 'barefoot'
- SOLID_AFO = 'solid_AFO'
- HINGED_AFO = 'hinged_AFO'
- GRAFO = 'GRAFO'
- ENERGY_RESTORING_AFO = 'energy_restoring_AFO'
- KAFO = 'KAFO'
- SHOE_WITH_RAISE = 'shoe_with_raise'
- IN_SHOE_ORTHOSIS = 'in_shoe_orthosis'
- PROSTHETIC = 'prosthetic'
- OTHER = 'other'
- class acmad_uploader.domain.mocap_data.DesiredSpeed(*values)
Bases:
StrEnumRequested walking speed for the trial.
The API stores this hyphenated (
self-selected); the workbook spells it with a space (self selected) — the transformer maps between them.- SELF_SELECTED = 'self-selected'
- SLOW = 'slow'
- FAST = 'fast'
- NOT_APPLICABLE = 'not applicable'
- class acmad_uploader.domain.mocap_data.MocapDataRecord(site_patient_id, age_in_days, session_condition, gait_aid, left_condition_detail, right_condition_detail, desired_speed, source)
Bases:
objectValidated mocap session independent of its source and destination.
trial_name/trial_activity/trial_side(per-trial detail) have no source inmocap.xlsxat all — those come from the separate C3D processing pipeline (MocapTrial, out of scope for this ETL), so this record only carries the session-level fields the workbook does have.left_condition_detail/right_condition_detailare consistently left blank across real sample data (matching the data dictionary, which doesn’t mark them required) even for non-barefoot conditions, so they are optional here.- site_patient_id: str
- age_in_days: int
- session_condition: SessionCondition
- left_condition_detail: ConditionDetail | None
- right_condition_detail: ConditionDetail | None
- desired_speed: DesiredSpeed | None
- source: SourceLocation
Canonical biomechanics artifact values shared by ETL stages.
- class acmad_uploader.domain.biomechanics_artifact.ArtifactRole(*values)
Bases:
StrEnumKind of biomechanics file, matching the destination’s own role choices.
Only
normalised_kinematics_csv/normalised_kinetics_csv/spatiotemporal_csvare “derived” — the destination parses these three intoOpenSimKinematics/OpenSimKinetics/OpenSimSpatiotemporalMetricsserver-side and requires anOpenSimProcessingRunto attach them to. Every other role is a plain file upload with no further processing.- RAW_C3D = 'raw_c3d'
- DEIDENTIFIED_C3D = 'deidentified_c3d'
- TRC = 'trc'
- GRF_MOT = 'grf_mot'
- IK_MOT = 'ik_mot'
- ID_STO = 'id_sto'
- OSIM_MODEL = 'osim_model'
- SCALE_SETTINGS = 'scale_settings'
- MESH_STL = 'mesh_stl'
- MESH_VTP = 'mesh_vtp'
- NORMALISED_KINEMATICS_CSV = 'normalised_kinematics_csv'
- NORMALISED_KINETICS_CSV = 'normalised_kinetics_csv'
- SPATIOTEMPORAL_CSV = 'spatiotemporal_csv'
- MODEL_FIT_AUXILIARY = 'model_fit_auxiliary'
- UPLOADED_PACKAGE = 'uploaded_package'
- OTHER = 'other'
- class acmad_uploader.domain.biomechanics_artifact.BiomechanicsArtifactRecord(site_patient_id, age_in_days, session_condition, gait_aid, left_condition_detail, right_condition_detail, file_path, original_path, filename, role, extension, content_type, size_bytes, sha256)
Bases:
objectOne raw or derived biomechanics file belonging to a mocap session.
original_path(relative to the session’s ownmocap_<condition>folder) together with the resolvedMocapDatarow is the destination’s own natural key (unique_together = (mocap_data, original_path)) — no client-side matching needed, unlikeMocapDataitself. The session-identifying fields mirrorMocapDataRecord’s own natural key, needed to resolve the owningMocapDatarow viaMocapDataLookup.- site_patient_id: str
- age_in_days: int
- session_condition: SessionCondition
- left_condition_detail: ConditionDetail | None
- right_condition_detail: ConditionDetail | None
- file_path: Path
- original_path: str
- filename: str
- role: ArtifactRole
- extension: str
- content_type: str
- size_bytes: int
- sha256: str
Canonical physical examination values shared by ETL stages.
- class acmad_uploader.domain.physical_examination.AbdominalStrength(*values)
Bases:
StrEnumDegree of trunk flexion graded during abdominal strength testing.
- HEAD = 'head'
- HEAD_SHOULDERS = 'head_shoulders'
- HEAD_SHOULDER_BLADES = 'head_shoulder_blades'
- class acmad_uploader.domain.physical_examination.Side(*values)
Bases:
StrEnumBody side a physical exam detail row was measured on.
- LEFT = 'left'
- RIGHT = 'right'
- class acmad_uploader.domain.physical_examination.OxfordStrength(*values)
Bases:
StrEnumOxford manual muscle testing (MMT) grade, 0 (none) to 5 (max resistance).
- ZERO = '0'
- ONE = '1'
- TWO = '2'
- THREE = '3'
- FOUR = '4'
- FIVE = '5'
- class acmad_uploader.domain.physical_examination.SelectivityScale(*values)
Bases:
StrEnumWhether a muscle group’s movement can be selectively isolated.
- CANNOT_ISOLATE = '0'
- CAN_ISOLATE = '1'
- class acmad_uploader.domain.physical_examination.SelectiveMotorControl(*values)
Bases:
StrEnumSelective motor control grade for dorsiflexion, 0 (none) to 4 (isolated).
- ZERO = '0'
- ONE = '1'
- TWO = '2'
- THREE = '3'
- FOUR = '4'
- class acmad_uploader.domain.physical_examination.ConfusionTest(*values)
Bases:
StrEnumResult of confusion testing for ankle dorsiflexion substitution.
- POSITIVE_INVERTED = 'positive_inverted'
- POSITIVE_NEUTRAL = 'positive_neutral'
- POSITIVE_EVERTED = 'positive_everted'
- NEGATIVE = 'negative'
- class acmad_uploader.domain.physical_examination.ToneScale(*values)
Bases:
StrEnumScale used for a tone measurement — shared across both sides.
- DUNCAN_ELY = 'DE'
- MODIFIED_TARDIEU = 'MTS'
- MODIFIED_ASHWORTH = 'MAS'
- AUSTRALIAN_SPASTICITY = 'ASAS'
- class acmad_uploader.domain.physical_examination.Clonus(*values)
Bases:
StrEnumSeverity of clonus observed.
- NONE = 'none'
- MILD = 'mild'
- MODERATE = 'moderate'
- SEVERE = 'severe'
- class acmad_uploader.domain.physical_examination.HindfootSagittal(*values)
Bases:
StrEnumHindfoot sagittal plane alignment.
- MODERATE_SEVERE_CALCANEUS = 'moderate_severe_calcaneus'
- MILD_CALCANEUS = 'mild_calcaneus'
- NORMAL = 'normal'
- MILD_EQUINUS = 'mild_equinus'
- MODERATE_SEVERE_EQUINUS = 'moderate_severe_equinus'
- class acmad_uploader.domain.physical_examination.HindfootCoronal(*values)
Bases:
StrEnumHindfoot coronal plane alignment.
- MODERATE_SEVERE_VARUS = 'moderate_severe_varus'
- MILD_VARUS = 'mild_varus'
- NORMAL = 'normal'
- MILD_VALGUS = 'mild_valgus'
- MODERATE_SEVERE_VALGUS = 'moderate_severe_valgus'
- class acmad_uploader.domain.physical_examination.MidfootTransverse(*values)
Bases:
StrEnumMidfoot transverse plane alignment.
- MODERATE_SEVERE_CAVUS = 'moderate_severe_cavus'
- MILD_CAVUS = 'mild_cavus'
- NORMAL = 'normal'
- MILD_PLANUS = 'mild_planus'
- MODERATE_SEVERE_PLANUS = 'moderate_severe_planus'
- class acmad_uploader.domain.physical_examination.ForefootHorizontal(*values)
Bases:
StrEnumForefoot horizontal plane alignment.
- MODERATE_SEVERE_ADDUCTUS = 'moderate_severe_adductus'
- MILD_ADDUCTUS = 'mild_adductus'
- NORMAL = 'normal'
- MILD_ABDUCTUS = 'mild_abductus'
- MODERATE_SEVERE_ABDUCTUS = 'moderate_severe_abductus'
- class acmad_uploader.domain.physical_examination.AnthropometricsRecord(height_mm, mass_kg, asis_distance_mm)
Bases:
objectNon-sided anthropometric measurements for one physical examination.
- height_mm: float | None
- mass_kg: float | None
- asis_distance_mm: float | None
- class acmad_uploader.domain.physical_examination.AnthropometricSideRecord(side, leg_length_mm, troc_asis_distance_mm, knee_width_mm, ankle_width_mm, orthosis_ankle_width_mm, orthosis_knee_width_mm, shoe_sole_delta_mm)
Bases:
objectSided anthropometric measurements, incl. orthosis/shoe modifications.
- leg_length_mm: float | None
- troc_asis_distance_mm: float | None
- knee_width_mm: float | None
- ankle_width_mm: float | None
- orthosis_ankle_width_mm: float | None
- orthosis_knee_width_mm: float | None
- shoe_sole_delta_mm: float | None
- class acmad_uploader.domain.physical_examination.RangeOfMotionRecord(side, psoas_length, hip_adductor_ext_length, hip_adductor_flex_length, hamstring_mod_popliteal_length, hamstring_popliteal_length, hamstring_spasticity, knee_ext_range, soleus_length, soleus_spasticity, gastroc_length, gastroc_spasticity, plantarflex_range, knee_flex_range, hip_rot_int_range, hip_rot_ext_range, tpat, bimalleolar, thigh_heel, foot_thigh)
Bases:
objectSided joint range-of-motion and muscle length measurements, in degrees.
The backend also has a
*_is_wnl(within normal limits) flag paired with every measurement, but no workbook field maps to it — left unset.- psoas_length: float | None
- hip_adductor_ext_length: float | None
- hip_adductor_flex_length: float | None
- hamstring_mod_popliteal_length: float | None
- hamstring_popliteal_length: float | None
- hamstring_spasticity: float | None
- knee_ext_range: float | None
- soleus_length: float | None
- soleus_spasticity: float | None
- gastroc_length: float | None
- gastroc_spasticity: float | None
- plantarflex_range: float | None
- knee_flex_range: float | None
- hip_rot_int_range: float | None
- hip_rot_ext_range: float | None
- tpat: float | None
- bimalleolar: float | None
- thigh_heel: float | None
- foot_thigh: float | None
- class acmad_uploader.domain.physical_examination.StrengthRecord(side, hip_extensors_strength_knee_90, hip_extensors_selectivity_knee_90, hip_extensors_strength_knee_0, hip_extensors_selectivity_knee_0, hip_flexors_strength_knee_90, hip_flexors_selectivity_knee_90, hip_flexors_strength_knee_0, hip_flexors_selectivity_knee_0, hip_abductors_strength, hip_abductors_selectivity, knee_flexors_strength, knee_flexors_selectivity, knee_extensors_strength, knee_extensors_selectivity, plantarflexors_strength, plantarflexors_selectivity, dorsiflexors_strength_knee_0, dorsiflexors_selectivity_knee_0, dorsiflexors_strength_knee_90, dorsiflexors_selectivity_knee_90, ankle_invertors_strength, ankle_invertors_selectivity, ankle_evertors_strength, ankle_evertors_selectivity, quadriceps_lag, selective_motor_control, confusion_testing)
Bases:
objectSided manual muscle strength/selectivity testing.
- hip_extensors_strength_knee_90: OxfordStrength | None
- hip_extensors_selectivity_knee_90: SelectivityScale | None
- hip_extensors_strength_knee_0: OxfordStrength | None
- hip_extensors_selectivity_knee_0: SelectivityScale | None
- hip_flexors_strength_knee_90: OxfordStrength | None
- hip_flexors_selectivity_knee_90: SelectivityScale | None
- hip_flexors_strength_knee_0: OxfordStrength | None
- hip_flexors_selectivity_knee_0: SelectivityScale | None
- hip_abductors_strength: OxfordStrength | None
- hip_abductors_selectivity: SelectivityScale | None
- knee_flexors_strength: OxfordStrength | None
- knee_flexors_selectivity: SelectivityScale | None
- knee_extensors_strength: OxfordStrength | None
- knee_extensors_selectivity: SelectivityScale | None
- plantarflexors_strength: OxfordStrength | None
- plantarflexors_selectivity: SelectivityScale | None
- dorsiflexors_strength_knee_0: OxfordStrength | None
- dorsiflexors_selectivity_knee_0: SelectivityScale | None
- dorsiflexors_strength_knee_90: OxfordStrength | None
- dorsiflexors_selectivity_knee_90: SelectivityScale | None
- ankle_invertors_strength: OxfordStrength | None
- ankle_invertors_selectivity: SelectivityScale | None
- ankle_evertors_strength: OxfordStrength | None
- ankle_evertors_selectivity: SelectivityScale | None
- quadriceps_lag: float | None
- selective_motor_control: SelectiveMotorControl | None
- confusion_testing: ConfusionTest | None
- class acmad_uploader.domain.physical_examination.ToneValue(scale, value)
Bases:
objectA tone measurement and the scale it was recorded against.
The scale is shared between both sides in the source workbook (one scale column, two per-side value columns), but the destination stores it once per side-keyed
Tonerow, so it’s carried alongside each side’s own value here rather than hoisted ontoPhysicalExaminationRecord.- value: str | None
- class acmad_uploader.domain.physical_examination.ToneRecord(side, rectus_tone_slow, rectus_tone_fast, hip_ext_tone, hip_flex_tone, hip_add_tone, hip_introt_tone, hip_extrot_tone, knee_flexor_tone, knee_extensor_tone, soleus_tone, gastroc_tone, tib_post_tone, clonus)
Bases:
objectSided muscle tone assessment across multiple scales.
- class acmad_uploader.domain.physical_examination.FootStructureRecord(side, hindfoot_sagittal, hindfoot_coronal, midfoot_transverse, forefoot_horizontal)
Bases:
objectSided foot structure assessment across three planes.
- hindfoot_sagittal: HindfootSagittal | None
- hindfoot_coronal: HindfootCoronal | None
- midfoot_transverse: MidfootTransverse | None
- forefoot_horizontal: ForefootHorizontal | None
- class acmad_uploader.domain.physical_examination.PhysicalExaminationRecord(site_patient_id, age_in_days, abdominal_strength, anthropometrics, anthropometric_sides, range_of_motion, strength, tone, foot_structure, source)
Bases:
objectOne physical examination and its non-sided and sided detail rows.
gait_assessment(1:1) is the natural key, resolved from(site_patient_id, age_in_days)the same way FunctionAssessment and MocapData resolve their owning gait assessment. Each side-keyed tuple holds exactly one left and one right entry, matching the destination’sunique_together = (physical_examination, side)on each detail model.- site_patient_id: str
- age_in_days: int
- abdominal_strength: AbdominalStrength | None
- anthropometrics: AnthropometricsRecord
- anthropometric_sides: tuple[AnthropometricSideRecord, ...]
- range_of_motion: tuple[RangeOfMotionRecord, ...]
- strength: tuple[StrengthRecord, ...]
- tone: tuple[ToneRecord, ...]
- foot_structure: tuple[FootStructureRecord, ...]
- source: SourceLocation
Canonical PROMs (patient-reported outcome measure) values shared by ETL stages.
- class acmad_uploader.domain.proms.Respondent(*values)
Bases:
StrEnumWhich respondent completed a dual-respondent questionnaire slot.
Workbook slot
_1is always the “other” respondent (parent for GOAL/OFAQ/PODCI, proxy for MGaitEfficiency/Walk12); slot_2is always self-report — confirmed with the user, not a data-entry duplicate. The literal destination string differs per model ("parent"vs"proxy"), so each adapter maps this to its own model’scompleted_bychoice value.- SELF_REPORT = 'self_report'
- OTHER = 'other'
- class acmad_uploader.domain.proms.FaqRecord(function_score, activity_score)
Bases:
objectFunctional Assessment Questionnaire response.
Single row, no respondent split.
- function_score: int | None
- activity_score: int | None
- class acmad_uploader.domain.proms.OfaqRecord(respondent, version, physical, school_play, emotional, shoe)
Bases:
objectOxford Foot and Ankle Questionnaire response for one respondent.
- respondent: Respondent
- version: str | None
- physical: int
- school_play: int
- emotional: int
- shoe: int
- class acmad_uploader.domain.proms.PodciRecord(respondent, version, upper_extremity, transfer_mobility, physical_functioning, pain_comfort, happiness, global_functioning)
Bases:
objectPaediatric Outcomes Data Collection Instrument response for one respondent.
- respondent: Respondent
- version: str | None
- upper_extremity: int
- transfer_mobility: int
- physical_functioning: int
- pain_comfort: int
- happiness: int
- global_functioning: int
- class acmad_uploader.domain.proms.MGaitEfficiencyRecord(respondent, version, score)
Bases:
objectModified Gait Efficiency Scale response for one respondent.
- respondent: Respondent
- version: str | None
- score: int
- class acmad_uploader.domain.proms.Walk12Record(respondent, version, score)
Bases:
objectWalk-12 response for one respondent.
- respondent: Respondent
- version: str | None
- score: int
- class acmad_uploader.domain.proms.GoalAssessmentRecord(respondent, version, items, domain_scores)
Bases:
objectGOAL questionnaire response for one respondent.
itemsanddomain_scoresare keyed by the destinationGoalAssessmentmodel’s own field names (e.g."adli_1_difficulty","global_score") — a dict rather than ~57 explicit dataclass fields, mirroring the backend’s own declarativeGOAL_ITEM_FIELD_SPECS/GOAL_SCORE_FIELD_SPECStables (models/goal.py), which generate the model’s fields the same way rather than hand-declaring each one. Only populated items are included; a question’s absent metrics are simply not keys in the mapping.- respondent: Respondent
- version: str | None
- items: Mapping[str, int]
- domain_scores: Mapping[str, float]
- class acmad_uploader.domain.proms.PromsRecord(site_patient_id, age_in_days, faq, ofaq, podci, mgait_efficiency, walk12, goal_assessment, source)
Bases:
objectEvery PROMs family response recorded for one gait assessment.
gait_assessment(1:1) is the natural key for the parentPROMsrow, resolved from(site_patient_id, age_in_days). Each child questionnaire is optional/repeatable per its own destination shape:faqis a single 1:1 row (or absent); the dual-respondent questionnaires (ofaq/podci/mgait_efficiency/walk12/goal_assessment) each carry 0-2 entries, one per respondent slot actually present in the workbook.- site_patient_id: str
- age_in_days: int
- ofaq: tuple[OfaqRecord, ...]
- podci: tuple[PodciRecord, ...]
- mgait_efficiency: tuple[MGaitEfficiencyRecord, ...]
- walk12: tuple[Walk12Record, ...]
- goal_assessment: tuple[GoalAssessmentRecord, ...]
- source: SourceLocation
Canonical surgery/intervention episode values shared by ETL stages.
- class acmad_uploader.domain.surgery.SurgeryLaterality(*values)
Bases:
StrEnumLaterality of one surgical procedure.
- LEFT = 'left'
- RIGHT = 'right'
- BILATERAL = 'bilateral'
- NOT_SPECIFIED = 'not specified'
- NOT_APPLICABLE = 'not applicable'
- class acmad_uploader.domain.surgery.SurgicalProcedureRecord(procedure_index, laterality, surgery_type, surgery_region, surgery_intervention, surgery_intervention_detail, source)
Bases:
objectOne intervention performed during a surgery episode.
surgery_type/surgery_region/surgery_intervention/surgery_intervention_detailare submitted as raw text and matched server-side against admin-editableSurgicalInterventionDefinitionreference data — the ETL never resolves or sends a definition itself, the same pattern asDiagnosis.definition.procedure_indexis the numbered workbook slot (surg_laterality_<procedure_index>etc.) and is the destination’s natural key alongside its owning surgery (SurgicalProcedure.procedure_index, unique per surgery).- procedure_index: int
- laterality: SurgeryLaterality
- surgery_type: str
- surgery_region: str
- surgery_intervention: str
- surgery_intervention_detail: str | None
- source: SourceLocation
- class acmad_uploader.domain.surgery.SurgeryRecord(site_patient_id, site_abbreviation, age_in_days, hospital_abbreviation, event_details, procedures, sources)
Bases:
objectOne surgery/intervention episode and every procedure performed in it.
age_in_daystogether withsite_patient_idis the natural key: every numbered procedure slot found across contributingsurgery.xlsxworkbooks for the same day is aggregated into one episode, mirroring howGaitAssessmentRecordjoins its own contributing workbooks.- site_patient_id: str
- site_abbreviation: str
- age_in_days: int
- hospital_abbreviation: str | None
- event_details: PatientEventDetails
- procedures: tuple[SurgicalProcedureRecord, ...]
- sources: tuple[SourceLocation, ...]