What an observation is

An observation is one finding, seen or explicitly excluded, on one exam. The deck frames it as “what + where + attributes”: a finding tag, an anatomic location, and lesion characteristics, carrying presence indicators, change from prior, and measurements, in “a universal structure across systems.”1

Two of those three parts point at the semantic foundation. The “what” is a finding model identifier. The “where” is a RadLex identifier. Only the “how” is local to the observation, and even there each attribute and each chosen value carry codes from the finding model’s own definition.

A negative observation is an observation. Absence is recorded the same way presence is, with a presence attribute whose value is absent, because a radiologist stating “no fracture” has actively looked and not found. That commitment is what makes the Imaging Problem List able to distinguish a finding nobody checked for from one that was checked for and ruled out.

The concrete form today

There is no standalone Observation record. An observation is one entry in the findings array of an Exam Finding List.2

FieldTypeRequiredWhat it carries
observationIdstringyesidentity within this list. Repeat instances get separate identifiers.
findingCodeOIFM_[A-Z]{3,4}_[0-9]{6}yesthe OIFM identifier of the finding model
findingDescriptionstringyesthe finding model’s display name
attributes[]arrayyesone entry per characterized attribute; see below
anatomicLocation{locationId, locationDisplay}optional, development branch onlya RadLex identifier from the anatomic-locations package, omitted when the finding is not anatomically localizable3
reportTextstringoptionalthe verbatim span of the report the observation came from

Each entry in attributes[] carries four fields: attributeCode, an OIFMA_[A-Z]{3,4}_[0-9]{6} identifier; attributeDescription, its display name; attributeValueCode, the attribute code plus a dot suffix; and attributeValueDescription.

{
  "observationId": "acromioclavicular_degenerative_changes_1",
  "findingCode": "OIFM_GMTS_025663",
  "findingDescription": "degenerative joint changes",
  "attributes": [
    {
      "attributeCode": "OIFMA_GMTS_265084",
      "attributeDescription": "presence",
      "attributeValueCode": "OIFMA_GMTS_265084.1",
      "attributeValueDescription": "present"
    }
  ],
  "anatomicLocation": {
    "locationId": "RID42239",
    "locationDisplay": "left acromioclavicular joint"
  },
  "reportText": "Mild degenerative changes of the acromioclavicular joint with joint space narrowing and small osteophytes."
}

That record is the first finding of a left shoulder radiograph in the sample data.4 A full list in context is in the Exam Finding List example.

Presence and the dot codes

Presence is the attribute every observation carries. Its values in the sample data are present, absent, and indeterminate.

Value codes are positional, not semantic: a value code is the attribute identifier plus a dot and the value’s zero-based position in the finding model’s value list. Consuming code in the extraction repository documents the standard ordering as “.1 = present, .0 = absent.”3 That ordering holds for the large majority of published finding models but not all of them, so a consumer that hard-codes .1 as present is wrong for the minority that order their values differently. The presence glossary entry records the counts and the conflict.

Repeat instances

“The same finding type may appear multiple times in one exam (e.g., multiple kidney stones). Each instance gets a separate entry with its own observationId.”2 Count is therefore expressed by the number of observations, not by a count attribute, at the Exam Finding List level. The problem list re-collapses them: several observations of one finding from one exam display as a single dated row.

The extraction-time observation

The extraction platform on the development branch has its own Pydantic model for a finding as language models produce it, before any code assignment. It is a different object from the Exam Finding List entry and is worth reading as the pre-coding form of the same thing.5

ModelFields
Findingfinding_name, presence, location, attributes[], report_text, source_section, coding
FindingLocationbody_region, specific_anatomy, laterality
FindingAttributekey, value
ExtractedReportFindingsexam_info, findings[], non_finding_text[]

Three differences from the coded form matter.

The presence vocabulary is wider. presence is a Literal["present", "absent", "indeterminate", "possible"], and the design note explains the fourth value: “‘possible’ covers hedged language like ‘raising the possibility of’, ‘suggestive of’, ‘cannot exclude’.”56 There is no possible in the finding model presence value set, so the extra value has no coded counterpart and must be resolved before an Exam Finding List entry can be written.

Location is free text, not a code. FindingLocation carries a constrained body_region, a free-text specific_anatomy, and a laterality. Turning that into a locationId is the job of the separate post-extraction coding pass, governed by the anatomic location assignment rules.

Attributes are loose key-value pairs. FindingAttribute is a key and a value as strings, with standard keys named in the model docstring: size, acuity, change from prior, severity, count, and morphology.5 Those are not OIFMA codes and carry no value codes.

The model is also where coding results land. A FindingCodingBundle on each finding records the chosen OIFM identifier, the method used (fast-path, llm, or unresolved), a reason when unresolved, and the candidate codes that were considered. The pipeline that produces it is described in finding and location coding.

The mapping from the extraction model to the Exam Finding List entry is therefore not a rename. It is a coding step:

Extraction fieldExam Finding List fieldHow
finding_namefindingCode, findingDescriptionfinding coding against the finding model corpus
presencean attributes[] entryresolve to the finding model’s presence attribute and dot-suffixed value code
locationanatomicLocationlocation coding against the anatomic-locations index
attributes[]remaining attributes[] entriesno automated mapping is documented
report_textreportTextcarried through verbatim

The FHIR precedent

The 2024 reference implementation modelled an observation as a FHIR Observation directly. Its docstring states “the Observation class is the model for FHIR Observation objects,” and the class carries resourceType, code, status, subject, bodySite as a CodeableConcept, derivedFrom as references, and component as a discriminated union of codeable-concept, string, integer, and boolean variants keyed on the FHIR value[x] naming convention.7

The lung cancer screening samples show the same shape with real codes. A finding observation’s code is a CDE set identifier under https://radelement.org, each component code is a CDE element identifier, and each component’s valueCodeableConcept gives the chosen value code.8 In those samples status is what separates a machine-produced finding from a radiologist-confirmed one: preliminary for the AI observation, final for the radiologist’s, with no change to the resource type. That distinction is the closest thing in the project’s history to a provenance marker on an observation, and it is what the Exam Finding List specification asks for when it says “each Observation should include some kind of provenance marker.” See FHIR mapping.

What is missing

There is no Observation model, no JSON Schema, and no standalone record. Issue 1 in the extraction repository states the gap and the intended shape: Pydantic models for Observation, with a possible “Extracted Observation” subtype, alongside the Exam Finding List and Imaging Problem List, with “extensive annotation to generate JSON schemas” and camelCase aliases on export against snake_case attributes internally.9 The issue is open and unclaimed by any current plan. The Extracted Observation subtype it floats is exactly the distinction described above, between what a language model produced and what has been coded.

Footnotes

  1. “Open Imaging Data Model 2026 Status Update”, January 2026 ↩

  2. imaging-problem-list domain model notes, main branch ↩ ↩2

  3. imaging-problem-list domain model notes, dev branch ↩ ↩2

  4. An Exam Finding List with anatomic locations, dev branch ↩

  5. Extraction Pydantic models, dev branch ↩ ↩2 ↩3

  6. Initial extraction plan, dev branch ↩

  7. Observation model, OpenImagingDataModel.py ↩

  8. An AI-produced finding Observation, FHIRSamples ↩

  9. imaging-problem-list issue 1, “Create System of Data Models” ↩