NHS North West Genomics
2.2.0 - ci-build
NHS North West Genomics - Local Development build (v2.2.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
NE&Y Management Information (ctDNA) - copies of ctDNA Laboratory Orders and Reports sent to North East and Yorkshire (NE&Y) Genomics for their own regional management information/portal, rather than NE&Y being the ordering or testing party.
NEYctDNA.csv and NorthEnglandctDNA100.csv, examples of the iGene CSV exportThis page documents copies of ctDNA laboratory orders and reports flowing to NE&Y for management information - not the clinical pathway itself. This section gives project staff and developers the clinical context behind those messages: why the test is ordered, what the data fields mean clinically, and why NE&Y receives order/report metadata rather than full clinical content.
NGTDTestCode on each order identifies one of two ctDNA panels from the NHS National Genomic Test Directory:
| Test Code | Cancer type | Panel | Clinical purpose |
|---|---|---|---|
| M4.14 | Non-small cell lung cancer (NSCLC) | Combined small-variant + structural-variant ctDNA NGS panel (EGFR, ALK, BRAF, KRAS, MET exon 14 skipping/CNV, ROS1, RET, NTRK1-3) | Identify an actionable driver mutation/fusion to select first-line targeted therapy - typically when tissue is unavailable or insufficient, or run alongside tissue NGS to reduce time-to-treatment. Also used at disease progression to detect acquired resistance mutations (e.g. EGFR T790M/C797S) and guide the next line of targeted therapy. |
| M3.13 | Breast cancer | ctDNA NGS panel (ESR1) | Detect acquired ESR1 resistance mutations in HR+/HER2- advanced breast cancer patients progressing on an aromatase inhibitor, to guide a switch to an ESR1-directed treatment (e.g. a fulvestrant-based regimen or an oral SERD). |
Both are blood-based ("liquid biopsy") tests: a plasma sample is used instead of, or alongside, a tumour tissue biopsy, because ctDNA shed by the tumour into the bloodstream can be sequenced non-invasively and turned around faster than a repeat tissue biopsy.
ORU_R01.)flowchart LR
A[Patient identified<br/>for ctDNA testing] --> B[Blood sample taken<br/>at NHS Trust]
B --> C[Order + specimen<br/>sent to NW Genomics]
C --> D[Diagnostic testing<br/>NW Genomics / iGene]
D --> E[Report returned<br/>to Trust]
E --> F[MDT treatment<br/>decision]
C -.->|"copy via RIE (O21)"| G[NE&Y Management<br/>Portal]
E -.->|"copy via RIE (R01, PDF removed)"| G
Steps 3 and 5 are where this IG's process attaches: iGene's daily CSV export is converted by the RIE into FHIR O21/R01 messages, and copies are routed to NE&Y. NE&Y Genomics is not the ordering clinician and plays no part in the step 6 treatment decision - it receives copies of the order and report purely for regional management information (test volumes, turnaround times, activity by Trust) via its Management Portal. This is why the RIE strips the PDF/clinical content before forwarding the report copy (R01): NE&Y needs to know that a test happened and when it was reported, not the clinical result itself.
NGTDTestCode/NGTDTestName (M4.14/M3.13) map to ServiceRequest.code in the O21 message - this identifies which panel was ordered, and is the field most likely to expand as new NGTD ctDNA panels are added to the Test Directory.ObservationResultStatus = F on a CSV row means the report has been finalised in iGene - this is what should trigger treating a LAB-3 ORU_R01/R01 copy as a completed test; anything not yet F is still in progress.SpecimenTakenDateTime, SpecimenReceivedDateTime, ObservationDateTime, ReportStatusDateTime) are what NE&Y's Management Portal uses to calculate turnaround time - their accuracy in the daily CSV export matters more for this management-information use case than it does for the Trust's own clinical use, where the report itself remains the authoritative record.presentedForm) from the R01 copy - that's an information governance requirement, not just a technical convenience.ORU_R01) is a logical interaction only at present - the RIE's conversion of that same report into the R01 copy for NE&Y is real, but in practice the Trust itself currently receives the report as a PDF via NHS.net secure email, not as an electronic HL7 v2 message. Don't assume the Trust-facing leg is already electronic when building against this flow.| IHE Actor | Role |
|---|---|
| Order Placer | NHS Trust (North East or Yorkshire) - sends the order and specimen, paper-based |
| Order Filler | NW Genomics (iGene) - clerks in the order and performs the diagnostic testing |
| Intermediary | Regional Integration Engine (RIE) - converts the daily CSV export into a FHIR Message O21, relays LAB-3/ORU_R01 on to the NHS Trust, converts that same report into a FHIR Message R01 (with clinical content/PDF removed), and routes copies of both the O21 and R01 to NE&Y via AWS SQS |
| Order Result Tracker | NE&Y Genomics / NE&Y Management Portal - receives copies of order and report messages for regional management visibility; not itself the ordering or testing party |
| Transaction | Description | Direction |
|---|---|---|
| Paper order (LAB-1 equivalent, no electronic transaction) | NHS Trust sends the order and specimen to NW Genomics on paper | NHS Trust → NW Genomics |
| Manual entry + daily CSV export | NW Genomics Specimen Management manually enters the order into iGene; a daily extraction job exports it as a CSV file | iGene → RIE |
| CSV → FHIR Message O21 (LAB-2) | RIE converts the CSV export into a FHIR Message O21 | RIE (internal) |
| FHIR Message O21 copy, via AWS SQS | RIE sends a copy of the O21 message to NE&Y for their Management Portal | RIE → NE&Y (AWS SQS) |
HL7 v2 ORU_R01 (LAB-3) |
NW Genomics sends the diagnostic report to the RIE | iGene → RIE |
HL7 v2 ORU_R01 (LAB-3) - logical interaction, not yet electronic |
RIE relays the diagnostic report on to the NHS Trust. In practice, at present, this leg is not an electronic transaction: the report reaches the Trust as a PDF sent via NHS.net secure email | RIE → NHS Trust |
| FHIR Message R01 copy (PDF/clinical content removed), via AWS SQS | RIE converts the same LAB-3 report into a FHIR Message R01, strips the PDF/clinical content, and sends a copy to NE&Y | RIE → NE&Y (AWS SQS) |
ORU_R01, LAB-3) is sent from NW Genomics to the RIE, which relays it on to the NHS Trust - this NHS Trust leg is currently a logical interaction only: in practice, the Trust receives the report as a PDF via NHS.net secure email, not as an electronic HL7 v2 message. The RIE also converts this same report into a FHIR Message R01, removing the clinical content (the PDF), and sends this copy to NE&Y via AWS SQS, again for processing into the NE&Y Management Portal.sequenceDiagram
participant Trust as NHS Trust<br/>(North East / Yorkshire)<br/>Order Placer
participant SpecMgmt as NW Genomics<br/>Specimen Management
participant iGene as iGene<br/>Order Filler
participant RIE as Regional Integration<br/>Engine (RIE)<br/>Intermediary
participant NEY as NE&Y Genomics<br/>Management Portal<br/>Order Result Tracker
note over Trust,NEY: Laboratory Order
Trust ->> SpecMgmt: Paper Order + Specimen<br/>(LAB-1 equivalent)
SpecMgmt ->> iGene: Manually entered
iGene ->> RIE: Daily CSV export
RIE ->> RIE: Convert CSV to<br/>FHIR Message O21 (LAB-2)
RIE ->> NEY: Copy of FHIR Message O21<br/>via AWS SQS
note over Trust,NEY: Diagnostic Testing
iGene ->> iGene: Diagnostic testing
note over Trust,NEY: Laboratory Report
iGene ->> RIE: Laboratory Report<br/>HL7 v2 ORU_R01 (LAB-3)
RIE -->> Trust: Laboratory Report<br/>HL7 v2 ORU_R01 (LAB-3)<br/>(logical - see note)
note right of Trust: Logical interaction only at present -<br/>in practice, PDF via NHS.net secure email
RIE ->> RIE: Wire-tapped conversion of LAB-3 to<br/>FHIR Message R01,<br/>remove PDF/clinical content
RIE ->> NEY: Copy of FHIR Message R01<br/>via AWS SQS
No distinct future-state changes are currently defined for this process.
presentedForm PDF attachmentIf you haven't worked with HL7 v2/FHIR Messaging "events" before: an event
message (Bundle.type = message) is a self-contained, standalone package,
not a delta or update against some shared state the receiver is assumed to
already hold. Its MessageHeader.eventCoding says what kind of event this is
(O21 = a laboratory order, R01 = a laboratory report), and
MessageHeader.focus points to the one resource that is the event (the
ServiceRequest for O21, the DiagnosticReport for R01). Everything else in
the Bundle exists to support that focus resource.
This matters here because the O21 and R01 for the same laboratory order are
sent as two separate, independent messages, at different times - the order
copy as soon as it's entered in iGene, the report copy once testing is
finalised, potentially days or weeks later. There is no FHIR Reference
spanning across the two Bundles, because event messages don't work that way -
each one has to stand on its own.
Why the R01 re-declares Patient and ServiceRequest instead of just
referencing them. In principle, since NE&Y already saw the order in the
earlier O21, the R01 could just carry a bare identifier rather than the
patient's name/DOB and the ServiceRequest's details all over again. HL7 v2
ORU_R01 (and its FHIR Messaging equivalent) doesn't work that way, because it
is explicitly designed to also support an unsolicited result - a
laboratory reporting a result for an order the receiving system never saw in
the first place. To support that case, every R01 has to be self-sufficient:
full Patient and order-identifying content, not just a thin reference.
In this NE&Y flow specifically, an unsolicited R01 should never actually
happen - the RIE always generates the O21 from the same underlying iGene
order before the R01 is ever produced - but the message shape is the same
either way, because it follows the general-purpose HL7 v2/FHIR Messaging
pattern, not a flow-specific shortcut.
How the two events are linked in practice. Because there's no cross-Bundle
FHIR reference, correlating the O21 and R01 for the same order is done by
matching business identifiers that both Bundles carry - primarily the
Placer/Filler Order Number on ServiceRequest.identifier (see the note under
Laboratory Report R01 Mapping on exactly
which identifier is present in the current example) and the patient's NHS
Number. This is a standard integration-engine pattern - correlate by business
identifier, not by FHIR reference - not something specific to this IG.
Why these particular identifiers. Medical Record
Number (aka Hospital Number),
Order Identifier's Placer Order
Number, and Hospital Provider Spell
Identifier (aka
Account Number) are all identifiers set by the ordering NHS Trust, not by
NW Genomics/iGene. That makes them the identifiers the Trust itself actually
recognises its own patient, order and report by - unlike the Filler-side
identifiers (FillerOrderNumber, TestAccessionIdentifier,
ReportIdentifier), which are iGene's own internal numbering and mean nothing
to the Trust.
How the report references the order and specimen. Inside the R01 Bundle
itself, DiagnosticReport.basedOn references the ServiceRequest included in
that same Bundle - a normal in-Bundle FHIR reference, since both resources are
present together. ServiceRequest.specimen, in turn, references a Specimen -
but as noted under Laboratory Report R01
Mapping below, the current worked example's
Specimen reference is dangling: the Specimen resource itself isn't one
of the R01 Bundle's entries, so it can't actually be resolved from the report
message alone, only from the earlier O21.
flowchart TB
subgraph O21["FHIR Message O21 - event: Laboratory Order"]
direction TB
MH1["MessageHeader<br/>eventCoding = O21"]
SR1["ServiceRequest<br/>identifier: Placer/Filler<br/>Order Number"]
P1["Patient"]
PR1["PractitionerRole"]
SP1["Specimen"]
MH1 -->|focus| SR1
SR1 -->|subject| P1
SR1 -->|specimen| SP1
SR1 -->|requester| PR1
end
subgraph R01["FHIR Message R01 - event: Laboratory Report"]
direction TB
MH2["MessageHeader<br/>eventCoding = R01"]
DR["DiagnosticReport<br/>(new)"]
SR2["ServiceRequest<br/>re-declared - same Placer/<br/>Filler Order Number"]
P2["Patient<br/>re-declared"]
PR2["PractitionerRole<br/>re-declared"]
SP2["Specimen<br/>referenced only - not<br/>included in this Bundle"]
MH2 -->|focus| DR
DR -->|basedOn| SR2
DR -->|subject| P2
SR2 -->|specimen, dangling| SP2
SR2 -->|requester| PR2
end
SR1 -.->|"linked by matching business<br/>identifiers - not a FHIR reference,<br/>these are separate messages"| SR2
style SP2 stroke-dasharray: 5 5
The daily iGene CSV export (step 3 of Current Process above) has the shape below - see NEYctDNA.csv for a full example file. This table covers only the columns that populate the FHIR Message O21 Laboratory Order - the same CSV's report/result columns instead populate the separate FHIR Message R01 Laboratory Report, covered in Laboratory Report R01 Mapping below. Many columns here reuse the same FHIR mapping as the equivalent iGene Work Order Export column, since this is the same underlying order data.
| CSV Column | Description | Type | FHIR Mapping |
|---|---|---|---|
PatientAccessionIdentifier |
iGene's internal patient accession number - see Patient Identifier | string | Patient.identifier (PatientIdentifier) |
NHSNumber |
Patient's NHS Number - see NHS Identifier | string | Patient.identifier (NHS Number) |
HospitalNumber |
Patient's hospital/medical record number - see Medical Record Number | string | Patient.identifier (MedicalRecordNumber) |
PatientFamilyName |
Patient's surname | string | Patient.name.family |
PatientGivenName |
Patient's first name | string | Patient.name.given |
DateOfBirth |
Patient's date of birth | date | Patient.birthDate |
AdministrativeSex |
Sex registered at birth | string | Patient.gender |
PostCode |
Patient's postcode | string | Patient.address.postalCode |
HospitalSpellIdentifier |
Identifier for the hospital spell/episode the order was placed under - see Hospital Provider Spell Identifier | string | ServiceRequest.encounter.identifier (HospitalProviderSpellIdentifier) |
OrderingProviderIdentifier |
Ordering clinician's professional identifier - see Practitioner Identifier | string | PractitionerRole.practitioner.identifier.value |
OrderingProviderName |
Ordering clinician's name | string | PractitionerRole.practitioner.display |
RequestingOrganisationCode |
Requesting Trust's ODS code - see Organisation Code | string | PractitionerRole.organization.identifier.value |
RequestingOrganisationName |
Requesting Trust's name | string | PractitionerRole.organization.display |
PlacerOrderNumber |
Order identifier assigned by the ordering Trust - see Order Identifier | string | ServiceRequest.identifier (OrderIdentifier, type=PLAC) |
FMIIdentifier |
Blank on every current example row - purpose not yet confirmed | string | ServiceRequest.identifier (TBD) |
FillerOrderNumber |
Order identifier assigned by iGene (the lab) - see Order Identifier | string | ServiceRequest.identifier (OrderIdentifier, type=FILL) |
OrderStatus |
Order's current status in iGene | string | ServiceRequest.status |
NGTDTestCode |
NHS England Genomic Test Directory test code | string | ServiceRequest.code |
NGTDTestName |
NHS England Genomic Test Directory test/package name | string | ServiceRequest.code.coding.display |
TestCode |
Local iGene short test code (e.g. ctDNA_M4) |
string | ServiceRequest.code.coding (second coding, local system TBD) |
TestAccessionIdentifier |
iGene's test-level accession number | string | ServiceRequest.identifier (system TBD) |
TestOrderDate |
Date/time the test was ordered | dateTime | ServiceRequest.authoredOn |
SpecimenTakenDateTime |
Date/time the specimen was taken from the patient | dateTime | Specimen.collection.collectedDateTime |
SpecimenReceivedDateTime |
Date/time the specimen was received in the lab | dateTime | Specimen.receivedTime |
SpecimenAccessionIdentifier |
Specimen's lab accession number - see Specimen Accession Number | string | Specimen.accessionIdentifier |
SpecimenTypeCode |
Coded specimen type (e.g. SAMPLE: BL) - normally SNOMED coded using the Specimen Type value set |
string | Specimen.type.coding.code |
SpecimenTypeDescription |
Specimen type, free text (e.g. Blood) | string | Specimen.type.coding.display |
FMIIdentifier, TestCode and TestAccessionIdentifier are not yet confirmed against
a published identifier system - see the Questionnaire's own item design notes for
detail.
Unlike the R01 message below, Specimen is fully included here:
ServiceRequest.specimen in the O21 worked example resolves to an actual
Specimen entry in the same Bundle, not just a dangling reference - so all
five Specimen-mapped columns above are resolvable from the O21 order message
alone. See the Laboratory Report R01 Mapping
note below for the contrasting case.
Unlike the O21 order above, the R01 Laboratory Report is actually based on an HL7 v2
ORU^R01 message, converted into a FHIR DiagnosticReport-led Bundle (see
Bundle-GenomicsReportMessage-ctDNA for the
worked example this table is grounded in - it carries MessageHeader, Patient,
DiagnosticReport, ServiceRequest and PractitionerRole, but not the Specimen
resource ServiceRequest.specimen references). The table below uses the same CSV
column names and descriptions as Laboratory Order O21
Mapping above, so the two tables can be read side by
side to see where each column lands depending on
which FHIR Message actually carries it.
| CSV Column | Description | Type | R01 FHIR Mapping |
|---|---|---|---|
NHSNumber |
Patient's NHS Number - see NHS Identifier | string | Patient.identifier (NHS Number) - also echoed on DiagnosticReport.subject.identifier/ServiceRequest.subject.identifier |
HospitalNumber |
Patient's hospital/medical record number - see Medical Record Number | string | Patient.identifier (MedicalRecordNumber) |
PatientFamilyName |
Patient's surname | string | Patient.name.family |
PatientGivenName |
Patient's first name | string | Patient.name.given |
DateOfBirth |
Patient's date of birth | date | Patient.birthDate |
AdministrativeSex |
Sex registered at birth | string | Patient.gender |
PostCode |
Patient's postcode | string | Patient.address.postalCode |
HospitalSpellIdentifier |
Identifier for the hospital spell/episode the order was placed under - see Hospital Provider Spell Identifier | string | ServiceRequest.encounter.identifier (HospitalProviderSpellIdentifier) (not populated in current example) |
OrderingProviderIdentifier |
Ordering clinician's professional identifier - see Practitioner Identifier | string | PractitionerRole.practitioner.identifier.value |
OrderingProviderName |
Ordering clinician's name | string | PractitionerRole.practitioner.display |
RequestingOrganisationCode |
Requesting Trust's ODS code - see Organisation Code | string | PractitionerRole.organization.identifier.value |
RequestingOrganisationName |
Requesting Trust's name | string | PractitionerRole.organization.display |
PlacerOrderNumber |
Order identifier assigned by the ordering Trust - see Order Identifier | string | ServiceRequest.identifier (OrderIdentifier, type=PLAC) (not present in current example - see note below) |
FillerOrderNumber |
Order identifier assigned by iGene (the lab) - see Order Identifier | string | ServiceRequest.identifier (OrderIdentifier, type=FILL), echoed on DiagnosticReport.basedOn (see note below) |
OrderStatus |
Order's current status in iGene | string | ServiceRequest.status |
ReportStatusDateTime |
Date/time the report status was last updated | dateTime | DiagnosticReport.issued (not yet populated in current example) |
ReportIdentifier |
Report's identifier, once issued - see Report Identifier | string | DiagnosticReport.identifier (ReportIdentifier) (see note below) |
NGTDTestCode |
NHS England Genomic Test Directory test code | string | DiagnosticReport.code.coding |
NGTDTestName |
NHS England Genomic Test Directory test/package name | string | DiagnosticReport.code.coding.display |
TestCode |
Local iGene short test code (e.g. ctDNA_M4) |
string | (not present in current example) |
TestAccessionIdentifier |
iGene's test-level accession number | string | (system TBD - see note below) |
TestOrderDate |
Date/time the test was ordered | dateTime | ServiceRequest.authoredOn (not yet populated in current example) |
ObservationResultStatus |
Result status (F = finalised) |
string | DiagnosticReport.status |
ObservationDateTime |
Date/time the result was observed/produced | dateTime | DiagnosticReport.effectiveDateTime |
ObservationIdentifierCode |
Code identifying which result/analyte this row represents Genomic Test Outcome Codes | string | DiagnosticReport.conclusionCode.coding.code (on the individual result Observation referenced from DiagnosticReport.result, not itself included in the example Bundle) |
ObservationIdentifierDescription |
Display name for the result/analyte code above | string | DiagnosticReport.conclusionCode.coding.display (as above) |
FillerOrderNumber (iGene's "R-Number") is not present in the underlying HL7 v2
ORU_R01 feed's ORC-4 (Placer Group Number) - so the FHIR mapping above cannot
currently be sourced from that field in the real v2 message and needs revisiting.SpecimenAccessionIdentifier (iGene's "S-Number") is not present in the
underlying HL7 v2 ORU_R01 feed's SPM-2 (Specimen ID) - the same problem as
above, for the specimen identifier.ObservationIdentifierCode is missing from the current feed. This is more
commonly known as the Genomics Test Outcome - see Genomic Test Outcome
Codes. It will map to
DiagnosticReport.conclusionCode in FHIR, and to an OBX segment in HL7 v2
ORU_R01 (with OBX-3 coded as a Genomic Test Outcome Code).| Example | Description |
|---|---|
| Bundle-GenomicsOrderMessage-ctDNA | FHIR Message O21 - the order copy sent to NE&Y |
| Bundle-GenomicsReportMessage-ctDNA | FHIR Message R01 - the report copy sent to NE&Y, with the PDF removed |
| NEYctDNA.csv | Example of the daily iGene CSV export |
| NorthEnglandctDNA100.csv | Further example of the daily iGene CSV export |
Includes:
Bundle from a row of Input/NEYctDNA.csvSee Developer Guides for the full notebook series.