Skip to content

Specimen Profile

Canonical../StructureDefinition/nexus-emr-core-specimen
Statusdraft (experimental) · 1.26.0
BaseSpecimen (constraint)
SourceFSH · JSON

Nexus EMR profile for Specimen -- the physical sample a lab result was produced from. Currently a pass-through type: the platform resolves ServiceRequest.specimen references and traverses into Specimen from DiagnosticReport, but reads none of its own fields. First pass; the heritage-EMR reconciliation is unresolved.

TypedFhir API / Pydantic schema

The typed accessor surface Specimen exposes for Specimen — generated from this IG's compiled profile; each typed accessor has a validating raw-FHIR twin (xRaw) where marked. The three ports are parity-enforced.

The AI-facing shape: from typed_fhir.facade.generated.schemas import SpecimenSchemamodel_json_schema() is a structured-output / tool definition; instantiating validates an extraction. Generated source.

class SpecimenSchema(BaseModel):
    """AI-facing shape of the Specimen profile: the facade's typed accessor
    surface (curated + salient fields) as a pydantic model. `model_json_schema()` is a
    structured-output / tool schema; instantiating validates an extraction."""

    model_config = ConfigDict(extra="forbid")

    accession_identifier: dict | None = Field(
        None,
        description=(
            "The performing lab's accession number. The identifier assigned by the laboratory "
            "that processed the specimen. This is the value that correlates a result back to the "
            "physical sample at the lab, and that reveals when several results derive from a "
            "single draw. It is also what a human reads off a requisition when phoning the lab, "
            "which makes it the identifier most often needed and most often missing. ⚠ HERITAGE "
            "EMR SITUATION -- UNRESOLVED. This is the one specimen field heritage EMRs reliably "
            "DO carry, because it rides in the inbound HL7 v2 lab message. But it arrives without "
            "a governed system URI: the accession is scoped to the performing lab and is not "
            "unique across labs, so two labs can legitimately issue the same accession string. "
            "The IG does not yet define how to namespace it per performing lab, so "
            "`accessionIdentifier.system` is currently unconstrained and inbound values may "
            "collide. Treat an accession as unique only WITHIN a known performing organization "
            "until this is resolved. Note: Do not merge with `identifier` -- an accession is "
            "lab-scoped and is not a substitute for a specimen identifier. See the definition for "
            "the unresolved cross-lab namespacing gap. Specimen.accessionIdentifier — 0..1"
        ),
    )
    status: Literal["available", "entered-in-error", "unavailable", "unsatisfactory"] | None = Field(
        None,
        description=(
            "available | unavailable | unsatisfactory | entered-in-error. The availability of the "
            "specimen. Note: `unsatisfactory` is clinically meaningful -- a rejected sample means "
            "the test was NOT performed, and a consumer treating the linked result as pending "
            "rather than failed will wait forever. 0..1 in R4, so absence must be tolerated and "
            "must NOT be read as `available`. Heritage-EMR-derived specimens usually carry no "
            "status at all. Specimen.status — 0..1"
        ),
    )
    type: Concept | None = Field(
        None,
        description=(
            "The kind of sample (blood, urine, swab, ...). The kind of material that forms the "
            "specimen. Note: ⚠ FIRST PASS -- no binding. The SNOMED specimen hierarchy is large "
            "and no agreed subset exists for this EMR. Readers MUST tolerate text-only. "
            "Heritage-EMR data typically supplies at most a free-text specimen-source string from "
            "the HL7 v2 OBR segment, so text-only is the expected shape, not the exception. Where "
            "this code was mapped from a source system's own vocabulary, carry the raw coding "
            "alongside the mapped one, flagged `userSelected = true`. See [Carrying the raw "
            "code](../guide/patterns/raw-codes.md). Specimen.type — 0..1"
        ),
    )
    subject: Reference | None = Field(
        None,
        description=(
            "The patient the sample came from. The patient the specimen was collected from. 0..1 "
            "in R4 (a specimen can be environmental or device-derived) and left optional here. "
            "Anything appearing in a patient chart MUST carry it. ⚠ HERITAGE EMR SITUATION -- "
            "UNRESOLVED. Where a Specimen is synthesized during lab ingest, the patient link is "
            "inferred from the enclosing DiagnosticReport rather than carried by the source "
            "message. That inference is only as good as the report's own patient matching, so a "
            "mis-matched report propagates its error into the specimen silently. Whether "
            "ingest-synthesized specimens should assert `subject` at all -- versus leaving it "
            "absent and letting consumers reach the patient through `DiagnosticReport.subject` -- "
            "is unresolved. Specimen.subject — 0..1"
        ),
    )
    received_time: FuzzyDate | None = Field(
        None,
        description=(
            "When the lab received the sample. Time when specimen was received for processing or "
            "testing. Specimen.receivedTime — 0..1"
        ),
    )
    request: Reference | None = Field(
        None,
        description=(
            "The order this sample was collected for. Details concerning a service request that "
            "required a specimen to be collected. Note: The inverse of `ServiceRequest.specimen`, "
            "which the eReferral reference resolver rewrites when relaying a message bundle. Per "
            "the logical-reference model these MAY be identifier-only. Specimen.request — 0..*"
        ),
    )
    collection: dict | None = Field(
        None,
        description=(
            "How and when the sample was collected. Details concerning the specimen collection. "
            "Specimen.collection — 0..1"
        ),
    )
    condition: Concept | None = Field(
        None,
        description=(
            "State of the specimen. A mode or state of being that describes the nature of the "
            "specimen. Note: Specimen condition is an observation made about the specimen. It's a "
            "point-in-time assessment. It can be used to assess its quality or appropriateness "
            "for a specific test. Specimen.condition — 0..*. codes (extensible): AUT | CFU | CLOT "
            "| CON | COOL | FROZ | HEM | LIVE | …"
        ),
    )
    date: FuzzyDate | None = Field(
        None,
        description=(
            "When the sample was collected. Time when specimen was collected from subject - the "
            "physiologically relevant time. Note: THE effective date for this profile, preferred "
            "over receivedTime. A choice of dateTime or Period in R4 -- handle both. Heritage-EMR "
            "lab messages often carry only the received/report time, in which case this is absent "
            "and the effective date falls through to `receivedTime`. Salient field — "
            "collection.collectedDateTime | collection.collectedPeriod.start | receivedTime"
        ),
    )