Radiology transactionhandbook
Every radiology study is the product of two conversations running in parallel: HL7 carries the identity and the intent, DICOM carries the pixels and the acknowledgement. Almost every ticket you will ever work is a break at one of the seams between them. This guide walks the whole chain in order, with the roles, field names and status codes you need to prove where it broke.
Jump to a section
- Who talks to whom
- Timeline: register → read
- Order-to-image lifecycle
- HL7 structure & MLLP
- Senders, receivers, acks
- ADT
- ORM / OMI
- ORU
- DICOM model, UIDs, VRs
- SCU and SCP roles
- Association negotiation
- DIMSE services
- Query / Retrieve
- MWL, MPPS, commitment
- DICOMweb RS services
- Tag reference
- Transfer syntaxes
- HL7 → DICOM mapping
- Ports, time, bandwidth
- Troubleshooting playbook
- Status & reject codes
- Identity repair & IOCM
- Security & audit
- Self-check
-
HIS / EMRRegisters the patient, owns the MRNHL7 SENDER→ ADT^A04/A08
-
RIS / Order FillerSchedules, mints the accessionHL7 RECEIVER + SENDER→ ORM^O01
-
Interface engineTranslates, routes, re-maps codesHL7 BOTH→ ORM^O01
-
Worklist providerServes the scheduled stepMWL SCP→ C-FIND
-
ModalityPulls demographics, acquires, sendsMWL/STORE SCU→ C-STORE
-
PACS / VNAArchives, commits, serves priorsSTORE/Q-R SCP→ C-MOVE
-
Reading & reportDiagnosis returns as text, not pixelsQ-R SCU → HL7 SENDER→ ORU^R01
01 · System map
Who talks to whom
Before you can debug a transaction you have to know which box is authoritative for the field that is wrong, and which end of the connection initiates. Ownership disputes cause more broken studies than networking does.
| Actor | IHE role | Authoritative for | HL7 role | DICOM role |
|---|---|---|---|---|
| HIS / EMR | ADT / Patient Registration | MRN, legal name, DOB, sex, encounter number | Sender (ADT) | — |
| CPOE | Order Placer | Placer order number, indication, priority | Sender (ORM) | — |
| RIS | Order Filler / DSS | Accession, procedure code, schedule, exam status | Both | MWL SCP, MPPS SCP |
| Interface engine | — | Nothing — but rewrites everything | Both | — (some do DICOM routing) |
| Modality | Acquisition Modality | Study/Series/SOP UIDs, acquisition parameters | — | MWL SCU, Storage SCU, MPPS SCU, Commit SCU |
| PACS | Image Manager / Archive | Storage of record, query results, availability | Receiver (ADT/ORM/ORU) | Storage SCP, Q/R SCP, Commit SCP, and Storage SCU when forwarding |
| VNA | Image Archive | Long-term retention, cross-department objects | Receiver | Storage SCP, Q/R SCP, DICOMweb origin server |
| Diagnostic workstation | Image Display | Presentation states, key images, measurements | — (often reads RIS worklist) | Q/R SCU, Storage SCU (GSPS/KO), Storage SCP for C-MOVE returns |
| Routing / broker | Importer / Gateway | Nothing; transforms in flight | Sometimes | Storage SCP inbound + Storage SCU outbound |
| AI / CAD | Evidence Creator | Its own findings objects | — | Storage SCP in, Storage SCU out; increasingly UPS-RS + STOW-RS |
| Dictation / speech | Report Creator | Report text and status | Sender (ORU) | — (may store SR) |
| Zero-footprint viewer | Image Display | — | — | DICOMweb user agent (QIDO + WADO) |
| Dose registry | Dose Information Reporter | CTDIvol, DLP, exposure index | — | Storage SCP for RDSR |
The three keys that hold the chain together
Ninety percent of reconciliation failures are a mismatch in one of these. Learn them cold.
- PID-3 (0010,0020) Patient ID / MRN — joins images to the person. Break it and you get an orphan patient record.
- OBR-18 (0008,0050) Accession Number — joins images to the order and to the report. Break it and the study arrives but never matches the report.
- ZDS-1 (0020,000D) Study Instance UID — the globally unique handle for the study. Break it and you get duplicate or split studies.
02 · Infographic 2
One exam, end to end, on the clock
A routine outpatient CT abdomen/pelvis, traced from the moment the order is placed to the moment the signed report lands in the chart. Every arrow is a real transaction. Watch which system initiates each one — the roles swap more often than people expect.
-
Day −611:03A clinician decides to imageReferring physician · in the EMR
The indication is entered — flank pain, rule out calculus. Clinical decision support may score the order here. Nothing has crossed an interface yet.
-
Day −611:05Order is transmittedCPOE → RIS · sender → receiver over MLLP
An
ORM^O01withORC-1 = NWcarries the placer order number, the procedure code and the indication. The RIS acks withMSA-1 = AA. If it acksAE, the order silently never exists. -
Day −611:06RIS schedules it and mints the identifiersRIS → PACS, MWL provider · fan-out through the interface engine
This is the single most consequential moment in the chain. The RIS assigns the accession number, a filler order number, the room and the time slot, and generates the Study Instance UID that everything downstream will key on. It ships as
ORM^O01withORC-1 = SCand aZDSsegment. PACS creates a pre-registered, image-less study. -
Day −102:14Priors are prefetched overnightPACS SCU → VNA SCP
A rule fires off tomorrow's schedule: find this patient's previous abdominal imaging and pull it to fast storage. PACS runs a
C-FINDat STUDY level on the MRN, then aC-MOVEfor the matches. Here PACS is the client — the same box that will be a server twenty minutes into the exam. -
Day 009:58Patient arrives and is registeredHIS → RIS, PACS ·
ADT^A04Demographics are confirmed at the desk. If the name was misspelled at booking, the correction rides in now as
ADT^A08and must reach PACS, or the images will carry the old spelling forever. -
10:02Exam status flips to "arrived"RIS → PACS ·
ORM^O01,ORC-1 = SCA status-only update. A receiver that mistakes
SCforNWcreates a duplicate worklist entry right here, and a tech will eventually pick the wrong one. -
10:26Technologist queries the worklistCT scanner SCU → MWL provider SCP
A
C-FINDagainst the Modality Worklist Information Model, filtered on this scanner's AE title, today's date and modalityCT. The tech selects the patient rather than typing them — which is the entire reason the previous six steps exist. -
10:31Acquisition beginsCT scanner SCU → RIS / PACS SCP
MPPS N-CREATEwith statusIN PROGRESS. The room is now visibly live to schedulers and radiologists, and PACS learns what to expect. -
10:33 – 10:47Images are pushed as they reconstructCT scanner SCU → PACS SCP
One association carries hundreds of
C-STOREoperations — axial soft tissue, axial bone, coronal and sagittal reformats, each its own series. Every instance gets a status back; a single0xA700here means the archive is out of room. -
10:49Exam is marked completeCT scanner SCU → RIS / PACS SCP
MPPS N-SET, statusCOMPLETED, carrying the list of series and instances actually produced. PACS compares expected against received and can now flag an under-delivered study instead of quietly presenting a partial exam. -
10:50Storage commitment — and the roles invertScanner SCU → PACS SCP, then PACS → scanner on a new association
The scanner sends
N-ACTION: "do you take permanent responsibility for these instances?" PACS answers later withN-EVENT-REPORT— and to do that it opens its own connection back to the scanner. Only after event type 1 (all committed) may the console purge locally. -
10:51PACS forwards to the VNA and the dose registryPACS SCU → VNA SCP · scanner → dose registry
The archive of record now becomes a client. Separately the scanner sends a Radiation Dose SR to the dose registry, which is a Storage SCP that accepts exactly one SOP class.
-
10:53AI triage takes a lookRouter SCU → algorithm SCP, results back as SCU
A routing rule matched on
(0018,0015) Body Part Examinedand modality. The algorithm returns a secondary capture or SR and, if positive, escalates the study's priority on the reading worklist. Newer deployments do this with UPS-RS work items and STOW-RS instead of DIMSE. -
14:02Radiologist opens the studyWorkstation SCU → PACS SCP · or WADO-RS over HTTPS
A
C-FINDpopulates the study list, aC-MOVEorWADO-RSretrieves pixels, and the hanging protocol lays out current beside prior — driven almost entirely by(0008,103E) Series Description. Note that onC-MOVEthe workstation must also be a Storage SCP to receive what it asked for. -
14:22Report is signed and distributedDictation → RIS → EMR, PACS ·
ORU^R01The interpretation travels as a stack of
OBXsegments withOBR-25 = F, keyed on the same accession number issued at 11:06 six days earlier. If those two strings differ by so much as a leading zero, the loop never closes. -
14:23The referring clinician sees the resultEMR inbox · critical findings escalate by phone, not by interface
Total elapsed time from order to result: six days, three hours. Total time the images were actually in motion: about fourteen minutes. Everything else is scheduling, queueing and human availability — which is worth remembering when someone blames the network.
HL7 messages
One order, one schedule, one registration, one status update, one report — plus acknowledgements for each. Any one of them failing silently stops the chain.
DICOM operations
Overwhelmingly C-STOREs, on a handful of associations. The negotiation happens once; the transfer happens 1,240 times.
Role reversals
PACS acts as SCU for prefetch and forwarding, SCP for storage and query. The workstation is an SCU that must also listen as an SCP.
03 · IHE Scheduled Workflow
The same chain, as IHE names it
The timeline above is the story; this is the specification. When a vendor claims "SWF.b compliance," these are the transactions they are claiming to implement, and these numbers are what you cite in an RFP or an integration statement.
| Txn | Name | From → To | Protocol | Initiator role |
|---|---|---|---|---|
| RAD-1 | Patient Registration | ADT → Order Placer / Filler | HL7 ADT | Sender |
| RAD-2 | Placer Order Management | Order Placer → Order Filler | HL7 ORM | Sender |
| RAD-3 | Filler Order Management | Order Filler → Order Placer | HL7 ORM | Sender |
| RAD-4 | Procedure Scheduled | Order Filler → Image Manager | HL7 ORM + ZDS | Sender |
| RAD-5 | Query Modality Worklist | Modality → DSS/Order Filler | DICOM C-FIND | Modality is SCU |
| RAD-6 | Modality PS In Progress | Modality → Image Mgr / Order Filler | DICOM N-CREATE | Modality is SCU |
| RAD-7 | Modality PS Completed | Modality → Image Mgr / Order Filler | DICOM N-SET | Modality is SCU |
| RAD-8 | Modality Images Stored | Modality → Image Archive | DICOM C-STORE | Modality is SCU |
| RAD-10 | Storage Commitment | Modality ↔ Image Manager | DICOM N-ACTION / N-EVENT-REPORT | Both directions |
| RAD-11 | Image Availability Query | Order Filler → Image Manager | DICOM C-FIND | Order Filler is SCU |
| RAD-12 | Patient Update | ADT → Order Filler / Image Mgr | HL7 ADT | Sender |
| RAD-13 | Procedure Update | Order Filler → Image Manager | HL7 ORM | Sender |
| RAD-14 | Query Images | Image Display → Image Archive | DICOM C-FIND | Display is SCU |
| RAD-16 | Retrieve Images | Image Display ← Image Archive | DICOM C-MOVE | Display is SCU, then SCP to receive |
| RAD-28 | Structured Report Export | Evidence Creator → Image Manager | DICOM C-STORE | Creator is SCU |
When the order comes second
Trauma and STAT cases acquire first and register later, so the study lands unmatched under a temporary identity. IHE's fix-up profile is PIR. Practically: the RIS sends the real order, then an update or merge, and PACS re-keys the study onto the correct MRN, accession and Study UID. Make sure your unidentified-patient naming convention is unique per day, or two simultaneous traumas will collide into one patient record.
HL7 version 2 — identity, intent and result
Everything in this part is delimited text over a raw TCP socket. HL7 tells the imaging chain who the patient is, what was asked for, and what the answer was. It never carries a pixel.
04 · Encoding and transport
Message structure and MLLP
HL7 v2 has no schema enforcement at the wire level. That is why interfaces drift, why every site's build is slightly different, and why you will spend real time counting pipes.
The hierarchy
A message is a series of segments, one per line, terminated by carriage return (\r, 0x0D — not LF, and not CRLF). Each segment begins with a three-character name and divides into fields, which divide into components, which divide into subcomponents. Fields can also repeat.
MSH|^~\&|... | field separator MSH-1 — literally the 4th character of the message ^ component separator DOE^JOHN^Q → family^given^middle ~ repetition separator one field, multiple values \ escape character & subcomponent separator Escape sequences you will meet inside text fields: \F\ literal | \S\ literal ^ \T\ literal & \R\ literal ~ \E\ literal \ \.br\ line break ◄ the one that mangles reports \X0D\ hex-escaped character \H\ \N\ start / end highlighting
MSH-9 is the ninth token counted that way. Off-by-one here is the single most common mapping error in the industry.Reading a segment grammar
HL7 specifications and vendor interface documents describe message structure with a compact notation. You need to be able to read it in a conformance conversation:
| Notation | Meaning | Example |
|---|---|---|
| SEG | Required, once | MSH |
| [SEG] | Optional | [PV1] |
| {SEG} | Required, repeats | {OBX} |
| [{SEG}] | Optional, repeats | [{NTE}] |
| R / RE / O / C / X | Field usage: required · required-but-may-be-empty · optional · conditional · not supported | Column in every vendor spec |
| Z-segments | Locally defined, begin with Z. Never standard, always negotiated | ZDS carries Study Instance UID |
HL7 data types you will actually parse
| Type | Name | Components you care about |
|---|---|---|
| CX | Extended composite ID | ID ^ ^ ^ AssigningAuthority ^ IdentifierTypeCode — this is PID-3. Component 5 is how you find the MR repetition |
| XPN | Extended person name | Family ^ Given ^ Middle ^ Suffix ^ Prefix ^ Degree ^ NameTypeCode — component 7 L = legal |
| XCN | Extended composite ID + name | ID ^ Family ^ Given ^ Middle ^ Suffix ^ Prefix ^ Degree — used for every physician field |
| CE / CWE | Coded element | Identifier ^ Text ^ CodingSystem — OBR-4 procedure codes. CWE replaces CE in 2.5+ |
| TS / DTM | Timestamp | YYYYMMDDHHMMSS[.S][+/-ZZZZ]. Truncation to 8 chars is legal, which is why dates arrive with and without times |
| HD | Hierarchic designator | NamespaceID ^ UniversalID ^ UniversalIDType — sending/receiving facility, assigning authority |
| EI | Entity identifier | EntityIdentifier ^ NamespaceID ^ UniversalID ^ UniversalIDType — order numbers |
| TQ | Timing / quantity | OBR-27. Component 4 = start datetime, component 6 = priority |
| XAD / XTN | Address / telecom | Rarely mapped into DICOM, frequently required by the EMR |
Transport: MLLP
HL7 v2 rides on Minimal Lower Layer Protocol — a plain, usually long-lived TCP connection with framing bytes around each message, because the protocol carries no length header of its own.
<VT> 0x0B ...HL7 message, segments separated by 0x0D... 0x1C <FS> 0x0D <CR> └ start block └ end block └ carriage return Typical exchange on one socket: Sender Receiver │ TCP connect (kept open for hours) │ │ ─────────────────────────────────────► │ │ 0x0B MSH|…ORM^O01… 0x1C 0x0D │ │ ─────────────────────────────────────► │ │ 0x0B MSH|…ACK…MSA|AA|MSG00187 0x1C 0x0D │ ◄───────────────────────────────────── │ │ next message only after the ack │
hl7 or tcp.port == 2575 and read the raw bytes — the 0x0B / 0x1C pair is visible immediately. MLLP has no TLS of its own; wrap it in a tunnel or use MLLPS on a dedicated port.05 · Roles and reliability
Senders, receivers, acknowledgements and queues
HL7's role model is much simpler than DICOM's — there is an initiator and a responder, and that is all. What is not simple is what happens when the responder says no, or says nothing.
The two roles
- Sending application (MSH-3 / MSH-4) opens the TCP connection, frames the message, and waits for an acknowledgement before sending the next one.
- Receiving application (MSH-5 / MSH-6) listens on a port, parses, processes, and returns an
ACK.
Unlike DICOM, the direction of the TCP connection and the direction of the data are always the same. This is why HL7 crosses firewalls more easily than C-MOVE does.
Where the simplicity ends
Most real systems are both sender and receiver, on different ports, often over different connections in each direction. A RIS receives ADT on 2575 and sends ORM out on 6661. Firewall rules must be written per channel, per direction — a single "allow HL7" rule between two hosts is a sign nobody mapped the flows.
Acknowledgement modes
MSH-15 (accept ack type) and MSH-16 (application ack type) choose between two modes. Leave both empty and you get original mode: one ack, meaning "received and processed."
| MSA-1 | Mode | Meaning | What you do about it |
|---|---|---|---|
| AA | Original | Application Accept | Nothing. Message consumed. |
| AE | Original | Application Error | Content problem — unknown procedure code, unparseable date, missing required field. Read MSA-3 and any ERR segment. The sender will usually not retry, so this message is lost unless someone reprocesses it. |
| AR | Original | Application Reject | The receiver cannot process at all — service down, wrong version, unknown facility. The sender should retry. |
| CA | Enhanced | Commit Accept | "I received it and framed it correctly." Not "I processed it." A second, application-level ack follows. |
| CE / CR | Enhanced | Commit Error / Reject | Failed at the transport or parse layer |
The silent-failure pattern worth memorising
An AE looks like a successful exchange at the network layer: connection fine, ack returned, no alarm. But the order does not exist downstream. Techs discover it at the scanner when the worklist is empty, hours later. Alert on AE and AR counts, not just on queue depth and connection state. A healthy-looking interface that has returned four hundred AEs overnight is an outage.
Queueing, retries and ordering
- Order matters. An
A08demographic update applied before theA04that created the patient produces a mess. Interface engines preserve order per channel; parallel channels for the same patient stream do not. - Retry policy should be bounded and alerting. An unbounded retry against a receiver returning
AEwill loop forever without anyone noticing. - Queue depth is your leading indicator. Baseline it during a normal Monday morning so you know what abnormal looks like.
- Replay capability is essential. When PACS is down for four hours, you need to reprocess the held messages in order, and you need to know exactly which ones were consumed before the outage.
- Duplicate suppression — a sender that never got an ack will resend. Receivers should be idempotent on MSH-10.
What to demand in an interface specification
- Which trigger events are sent, and which are not
- Field-level table: segment, sequence, data type, usage (R/RE/O/C/X), and an example value
- Exactly where the accession number lives, byte for byte
- Acknowledgement mode and behaviour on error
- Character set declared in MSH-18 and actually emitted
- Behaviour on cancel, reschedule, merge and correction — not just on the happy path
06 · Admit, Discharge, Transfer
ADT — the identity feed
ADT is not about beds, as far as imaging is concerned. It is the feed that keeps the patient identity in PACS identical to the identity in the medical record. Subscribe to too few events and demographics rot; subscribe to too many and you flood the archive with encounter noise.
| Event | Trigger | Why PACS cares |
|---|---|---|
| A01 | Admit inpatient | Creates the encounter; PV1-19 visit number links inpatient exams |
| A02 | Transfer | Location change — matters if prefetch or worklists key on ward |
| A03 | Discharge | Common trigger for archiving, dose reporting, releasing prefetched priors |
| A04 | Register outpatient | The dominant event in imaging. Most outpatient radiology patients are registered, never admitted |
| A05 | Pre-admit | Lets you prefetch priors before the patient arrives |
| A08 | Update patient information | The workhorse correction. Spelling, DOB, sex. If PACS ignores A08 you edit demographics by hand forever |
| A11 | Cancel admit | Registration made in error |
| A12 / A13 | Cancel transfer / cancel discharge | Reverses A02 / A03 |
| A18 | Merge patient information | Older merge event; still seen in 2.3 interfaces |
| A40 | Merge patient — identifier list | The modern merge. MRG-1 carries the incorrect MRN, PID-3 the surviving one. PACS must move every study |
| A41 / A42 / A45 | Merge account / visit, move visit | Encounter-level merges; relevant only if you key on visit number |
| A47 | Change patient identifier list | The MRN itself is renumbered — rare and painful |
| A31 | Update person information | Demographic update outside an encounter; some HIS send this instead of A08 |
| A28 / A29 | Add / delete person information | Person-level rather than encounter-level records |
An A08 in the wild
MSH|^~\&|EPIC|MERCY|PACS|RAD|20260811093000||ADT^A08^ADT_A01|MSG00042|P|2.5.1||||||UNICODE UTF-8 EVN|A08|20260811092955|||OPERATOR123 PID|1||10045522^^^MERCY^MR~999887777^^^USA^SS||RIVERA^MARIA^L^^^^L||19710304|F|||88 ELM ST^^AUSTIN^TX^78701||^PRN^PH^^^512^5550142|||M||ACC88231 PV1|1|O|RAD^CT^01||||1234^CHEN^WEI^^^^MD|5678^PARK^SUNG^^^^MD||RAD|||||||||V20260811-0093
ID^^^assigningAuthority^typeCode. Select the repetition where the type is MR — never blindly the first, or the day someone adds an SSN repeat in front, you will key studies on a social security number.
PID-5.7 = L marks the legal name; alias repeats may follow.
PV1-2 patient class: I inpatient, O outpatient, E emergency, P preadmit, R recurring, B obstetrics.
MSH-18 declares the character set — here UTF-8, which must be translated into DICOM's (0008,0005) as ISO_IR 192.
A merge, dissected
MSH|^~\&|EPIC|MERCY|PACS|RAD|20260811110000||ADT^A40^ADT_A39|MSG00551|P|2.5.1 EVN|A40|20260811105958 PID|1||10045522^^^MERCY^MR||RIVERA^MARIA^L||19710304|F ◄ SURVIVING identity MRG|10099814^^^MERCY^MR ◄ identity to be RETIRED
MRG-1 must move to PID-3. In DICOM terms that means rewriting (0010,0020) and usually (0010,0010) on every object, updating the archive database, and invalidating every downstream copy — VNA, EMR viewer cache, dose registry, XDS-I registry, teaching file, any burned CD.Two things to verify before you trust your merge handling
- Does PACS forward the change downstream, or does the VNA still hold the pre-merge MRN? Test with a real merge in a non-production pair and query the VNA afterwards.
- Does the modality's local cache, the CD-burner queue, or the AI vendor's copy still hold the old identity? Anything you cannot update, you must be able to enumerate.
07 · Order message
ORM^O01 and its successor OMI^O23
This is the message that becomes a worklist entry. Every field the technologist does not have to type comes from here, and every field mapped wrong here becomes a manual correction later.
MSH|^~\&|RIS|MERCY|PACS|RAD|20260805110600||ORM^O01|MSG00187|P|2.3.1 PID|1||10045522^^^MERCY^MR||RIVERA^MARIA^L||19710304|F PV1|1|O|RAD^CT^01||||1234^CHEN^WEI^^^^MD|5678^PARK^SUNG^^^^MD ORC|SC|PL8891234|FL5567890||SC||^^^20260811103000^^R||20260805110600|||1234^CHEN^WEI^^^^MD|RAD^CT^01 OBR|1|PL8891234|FL5567890|CT7150^CT ABDOMEN PELVIS W CONTRAST^C4|||20260811103000||||||Flank pain, r/o stone|||1234^CHEN^WEI^^^^MD||ACC20260811-0417|RP-88231|||||CT|SC||^^^20260811103000^^R|||WALK|R10.9^Abdominal pain^I10|||||20260811103000 ZDS|1.2.840.113619.2.55.3.604688119.868.1754912700.417^100^Application^DICOM
Field by field
| HL7 | Field | Example | Notes |
|---|---|---|---|
| ORC-1 | Order control | NW | The verb of the message — table below |
| ORC-2 / OBR-2 | Placer order number | PL8891234 | Assigned by the ordering system → (0040,2016) |
| ORC-3 / OBR-3 | Filler order number | FL5567890 | Assigned by the RIS → (0040,2017). Some vendors put the accession here instead of OBR-18 |
| ORC-5 | Order status | SC | SC scheduled · IP in progress · CM complete · CA cancelled · DC discontinued |
| ORC-9 | Date/time of transaction | 20260805110600 | When the order event happened, not when the exam is |
| ORC-12 / OBR-16 | Ordering provider | 1234^CHEN^WEI | → Requesting Physician (0032,1032); referring goes to (0008,0090) |
| ORC-13 | Enterer's location | RAD^CT^01 | Sometimes the only clue to the ordering department |
| OBR-4 | Universal service ID | CT7150^CT ABD PELV W^C4 | Procedure code. Drives hanging protocols, body-part mapping, prefetch. Component 3 is the coding system (C4 = CPT-4, or a local scheme) |
| OBR-7 | Observation date/time | 20260811103000 | Exam date/time — becomes SPS start when OBR-27/36 are absent |
| OBR-13 | Relevant clinical info | Flank pain, r/o stone | Reason for study — radiologists genuinely need this on the worklist |
| OBR-15 | Specimen source | — | Lab field; occasionally abused to carry contrast or laterality |
| OBR-18 | Placer field 1 | ACC20260811-0417 | Accession number by convention → (0008,0050). Not guaranteed — confirm per interface |
| OBR-19 | Placer field 2 | RP-88231 | Frequently the requested procedure ID (0040,1001) |
| OBR-20 / 21 | Filler field 1 / 2 | — | Vendor-specific; sometimes the scheduled procedure step ID |
| OBR-24 | Diagnostic serv sect ID | CT | → Modality (0008,0060). Often needs translation (RAD→CR, NUC→NM) |
| OBR-25 | Result status | SC | On an order, still scheduled |
| OBR-27 | Quantity / timing | ^^^20260811103000^^R | Component 4 = start datetime, component 6 = priority (S STAT, A ASAP, R routine, P preop, C callback) |
| OBR-30 | Transportation mode | WALK / PORT / CART | Drives portable workflow and room assignment |
| OBR-31 | Reason for study | R10.9^Abdominal pain^I10 | Coded indication; feeds decision support and appropriateness reporting |
| OBR-34 | Technician | — | |
| OBR-36 | Scheduled date/time | 20260811103000 | Where some RIS put the schedule instead of OBR-27 |
| OBR-44 | Procedure code | 74177^CT ABD PELV W^C4 | In 2.5.1 the CPT commonly moves here from OBR-4 |
| ZDS-1 | Study Instance UID | 1.2.840.113619… | Non-standard segment, blessed by IHE Radiology |
Order control codes you must handle
| ORC-1 | Meaning | Correct receiver behaviour |
|---|---|---|
| NW | New order | Create the worklist entry and the pre-registered study |
| SC | Status changed | Update in place — do not create a second entry |
| XO | Change order | Modify the existing order (procedure, time, room). Match on accession, then update |
| CA | Cancel order | Remove from worklist. If images already exist, flag for review rather than delete |
| DC | Discontinue | Exam partially done then stopped — keep what arrived |
| OC | Order cancelled (filler confirms) | Acknowledgement of a cancel; usually no action |
| CM | Order completed | Often the trigger to expect no further images |
| SN / NA | Send / number assigned | Filler reporting the number it assigned to a placer's order |
| RO | Replacement order | Supersedes a previous order — must not leave the original on the worklist |
OMI^O23 — the modern imaging order
HL7 2.5.1 deprecates ORM^O01 and splits it into OMG^O19 (general clinical order) and OMI^O23 (imaging order). OMI is worth pushing for on new interfaces because it removes the two ugliest hacks in radiology integration.
MSH|^~\&|RIS|MERCY|PACS|RAD|20260805110600||OMI^O23^OMI_O23|MSG00188|P|2.5.1 PID|1||10045522^^^MERCY^MR||RIVERA^MARIA^L||19710304|F ORC|SC|PL8891234|FL5567890||SC OBR|1|PL8891234|FL5567890|CT7150^CT ABDOMEN PELVIS W CONTRAST^C4 IPC|ACC20260811-0417|RP-88231|1.2.840.113619.2.55.3.604688119.868.1754912700.417|SPS-88231-1|CT|CTAP_C^CT Abd Pelvis w contrast^LOCAL|CT_SCANNER_01|RAD^CT^01|CT01_AE
One order, several procedure steps
"CT chest/abdomen/pelvis" may be one Requested Procedure that becomes one Study Instance UID, or three, depending on how your RIS models it. Decide deliberately: one study with several series is far easier for radiologists to read and for hanging protocols to lay out than three studies that must be manually linked. Whatever you choose, the modality must produce a Study Instance UID matching what the RIS pre-registered — otherwise PACS holds a second, unmatched study.
08 · Result message
ORU^R01 — the report comes home
ORU carries the radiologist's interpretation back to the RIS, the EMR, and often to PACS so the report can be displayed beside the images. It is keyed on the accession number that went out on the order — which is why accession discipline matters more than any other single mapping decision.
MSH|^~\&|POWERSCRIBE|MERCY|EPIC|MERCY|20260811142200||ORU^R01|MSG00931|P|2.3.1 PID|1||10045522^^^MERCY^MR||RIVERA^MARIA^L||19710304|F ORC|RE|PL8891234|FL5567890 OBR|1|PL8891234|FL5567890|CT7150^CT ABDOMEN PELVIS W CONTRAST^C4|||20260811103000|||||||||ACC20260811-0417||||||CT|F|||||||9911^OKAFOR^ADA^^^^MD OBX|1|TX|TECHNIQUE||Axial images through the abdomen and pelvis after IV contrast.||||||F OBX|2|TX|COMPARISON||CT abdomen 14 March 2024.||||||F OBX|3|TX|FINDINGS||A 4 mm nonobstructing calculus is present in the left||||||F OBX|4|TX|FINDINGS||renal lower pole. No hydronephrosis. Appendix normal.||||||F OBX|5|TX|IMPRESSION||1. Small nonobstructing left renal calculus.||||||F OBX|6|TX|IMPRESSION||2. No acute intra-abdominal process.||||||F
\.br\. If reports arrive in PACS as an unreadable wall of text, that escape sequence is almost always the culprit.| Field | Name | Values that matter |
|---|---|---|
| OBR-22 | Results report / status change datetime | The timestamp your turnaround dashboards should use |
| OBR-25 | Result status | O ordered · I in progress · S scheduled · P preliminary · R entered not verified · F final · C corrected · X cannot be obtained |
| OBR-32 | Principal result interpreter | The signing radiologist — drives credit, RVU reporting and peer review |
| OBR-33 / 35 | Assistant interpreter / transcriptionist | Resident or fellow attribution in teaching settings |
| OBX-2 | Value type | TX free text · FT formatted · ST string · NM numeric · CE coded · ED encapsulated (embedded PDF) · RP reference pointer (URL to the report) |
| OBX-3 | Observation identifier | Section label — FINDINGS, IMPRESSION, TECHNIQUE, COMPARISON. Sometimes LOINC coded |
| OBX-5 | Observation value | The actual text line |
| OBX-11 | Observation result status | P preliminary · F final · C correction · X cannot obtain · D deleted |
| OBX-14 | Date/time of observation | When observed, not when sent |
| NTE | Notes and comments | Addenda and critical-result communication notes often land here |
Getting the report into PACS
Three patterns, in ascending order of fidelity:
- HL7 ORU into the PACS database — shown in a text pane. Simple, universal, no DICOM object created, does not travel with the study.
- Encapsulated PDF …1.1.104.1 — the report becomes a real DICOM object inside the study. Travels on CD and to the VNA.
- DICOM Structured Report — Basic Text SR, or Enhanced/Comprehensive SR for measurement-bearing reports. Machine-readable, but only worth the effort if something downstream parses it.
Other objects created at read time
- GSPS — Grayscale Softcopy Presentation State …1.1.11.1. Window/level, zoom, annotations and shutters, stored separately from the pixels.
- KOS — Key Object Selection …1.1.88.59. "These are the key images." Also the manifest object in XDS-I.
- RDSR — Radiation Dose SR …1.1.67. Feeds the dose registry.
- SEG / RTSTRUCT — segmentations from AI or planning tools.
DICOM — pixels, objects and negotiated conversations
DICOM is both a file format and a network protocol, and the network half is far more negotiated than most people expect. Nothing moves until two nodes agree on who they are, which object types they will exchange, in which encoding, and which of them is playing which role.
09 · PS3.3 / PS3.5
The data model, UIDs and value representations
A DICOM object is a flat list of attributes that encodes a four-level hierarchy. Understanding that the hierarchy exists only because certain UIDs agree with each other is what makes split studies, duplicate series and orphaned instances comprehensible.
PATIENT (0010,0020) Patient ID — not a UID; a local identifier. This is why merges are hard. │ └─ STUDY (0020,000D) Study Instance UID — one exam. Ideally minted by the RIS. │ (0008,0050) Accession Number — the RIS/HL7 handle for the same thing. │ └─ SERIES (0020,000E) Series Instance UID — one acquisition or reconstruction. │ (0008,0060) Modality — fixed per series, not per study. │ (0020,0052) Frame of Reference UID — spatial link between series. │ └─ INSTANCE (0008,0018) SOP Instance UID — one image / object. Unique forever. (0008,0016) SOP Class UID — what kind of object it is.
Terminology that trips people up
| Term | What it actually means |
|---|---|
| IOD — Information Object Definition | The blueprint for a type of object: which modules and attributes a CT Image must contain. Defined in PS3.3 |
| Module | A named group of related attributes (Patient module, General Study module, Image Pixel module) reused across IODs |
| Attribute type | 1 required, non-empty · 1C conditionally required, non-empty · 2 required, may be empty · 2C conditionally required, may be empty · 3 optional |
| SOP Class — Service-Object Pair | An IOD plus the services allowed on it. "CT Image Storage" = the CT Image IOD + the Storage service |
| SOP Instance | One actual object conforming to a SOP Class |
| Abstract syntax | The SOP Class UID, as named during association negotiation |
| Transfer syntax | The encoding rules — byte order, explicit/implicit VR, compression |
| Presentation context | One abstract syntax paired with one or more proposed transfer syntaxes. The unit of negotiation |
| Composite vs normalized | Composite objects describe real-world things assembled from many entities (images) and use C-services. Normalized objects describe one entity (MPPS, Storage Commitment, Print) and use N-services |
| Conformance Statement | The vendor document listing every SOP class supported, in which role, with which transfer syntaxes. Ask for it before purchase, not after go-live |
UIDs
A UID is a dotted-decimal string, maximum 64 characters, globally unique and permanent. It begins with an organizational root registered to a vendor or institution, followed by locally generated suffixes.
1.2.840.10008.…is the DICOM Standard's own root — every standard SOP Class, transfer syntax and information model lives under it. Never generate your own UID under this root.1.2.840.113619.…,1.3.12.2.1107.…,1.3.6.1.4.1.…are vendor and enterprise roots. If your organisation generates UIDs (anonymisation, routers, AI pipelines), obtain a registered root rather than inventing one.- Legal characters are digits and dots only. No leading zeros within a component, no trailing dot. Padded to even length with a NULL byte, not a space.
The rule people break
If you change the pixel data, you must issue a new SOP Instance UID. If you change the meaning of the study — different patient, different exam — you generally need new Study and Series UIDs too. Re-using a SOP Instance UID for different content means two archives can hold different images under the same identifier and never detect the conflict. Anonymisation tools that "keep the UIDs to make matching easier" create exactly this trap.
Value representations
| VR | Name | Max length | Notes and traps |
|---|---|---|---|
| AE | Application Entity | 16 | AE titles. Case-sensitive; trailing spaces not significant |
| AS | Age String | 4 | nnnD/W/M/Y, e.g. 045Y |
| AT | Attribute Tag | 4 | A tag used as a value, e.g. in de-identification lists |
| CS | Code String | 16 | Uppercase, digits, space, underscore only |
| DA | Date | 8 | YYYYMMDD. No separators, no time |
| DS | Decimal String | 16 | Numbers stored as text — beware locale commas |
| DT | Date Time | 26 | YYYYMMDDHHMMSS.FFFFFF&ZZXX |
| FL / FD | Float / Double | 4 / 8 | True binary floats |
| IS | Integer String | 12 | Also text. Leading zeros are legal and cause string-compare bugs |
| LO | Long String | 64 | Descriptions, institution names |
| LT | Long Text | 10240 | May contain line breaks |
| OB / OW / OF | Other Byte / Word / Float | — | Pixel data and binary blobs |
| PN | Person Name | 64 per group | Family^Given^Middle^Prefix^Suffix, up to three groups separated by = for alphabetic, ideographic, phonetic |
| SH | Short String | 16 | Accession number lives here. Truncation risk |
| SQ | Sequence | — | A nested list of datasets. Worklist and MPPS are built almost entirely from these |
| ST | Short Text | 1024 | |
| TM | Time | 16 | HHMMSS.FFFFFF |
| UI | Unique Identifier | 64 | NULL-padded to even length |
| UL / US / SL / SS | Integers | 4 / 2 / 4 / 2 | True binary integers |
| UN | Unknown | — | What you get when a private tag survives a transcoding that lost its dictionary |
| UR | URI / URL | — | Used by DICOMweb-aware objects |
| UT | Unlimited Text | 232−2 | Report bodies in SR objects |
SOP Classes you will meet
| Object | SOP Class UID |
|---|---|
| Verification (DICOM echo) | 1.2.840.10008.1.1 |
| CR Image Storage | 1.2.840.10008.5.1.4.1.1.1 |
| Digital X-Ray — For Presentation | 1.2.840.10008.5.1.4.1.1.1.1 |
| Digital X-Ray — For Processing | 1.2.840.10008.5.1.4.1.1.1.1.1 |
| Digital Mammography X-Ray — For Presentation | 1.2.840.10008.5.1.4.1.1.1.2 |
| CT Image Storage | 1.2.840.10008.5.1.4.1.1.2 |
| Enhanced CT Image Storage | 1.2.840.10008.5.1.4.1.1.2.1 |
| Ultrasound Multi-frame Image Storage | 1.2.840.10008.5.1.4.1.1.3.1 |
| MR Image Storage | 1.2.840.10008.5.1.4.1.1.4 |
| Enhanced MR Image Storage | 1.2.840.10008.5.1.4.1.1.4.1 |
| Ultrasound Image Storage | 1.2.840.10008.5.1.4.1.1.6.1 |
| Secondary Capture Image Storage | 1.2.840.10008.5.1.4.1.1.7 |
| Grayscale Softcopy Presentation State | 1.2.840.10008.5.1.4.1.1.11.1 |
| X-Ray Angiographic Image Storage | 1.2.840.10008.5.1.4.1.1.12.1 |
| Breast Tomosynthesis Image Storage | 1.2.840.10008.5.1.4.1.1.13.1.3 |
| Nuclear Medicine Image Storage | 1.2.840.10008.5.1.4.1.1.20 |
| Radiation Dose SR | 1.2.840.10008.5.1.4.1.1.67 |
| Basic Text SR | 1.2.840.10008.5.1.4.1.1.88.11 |
| Key Object Selection Document | 1.2.840.10008.5.1.4.1.1.88.59 |
| Encapsulated PDF Storage | 1.2.840.10008.5.1.4.1.1.104.1 |
| PET Image Storage | 1.2.840.10008.5.1.4.1.1.128 |
| Segmentation Storage | 1.2.840.10008.5.1.4.1.1.66.4 |
| Modality Worklist Information Model — FIND | 1.2.840.10008.5.1.4.31 |
| Study Root Q/R — FIND / MOVE / GET | 1.2.840.10008.5.1.4.1.2.2.1 / .2 / .3 |
| Patient Root Q/R — FIND / MOVE / GET | 1.2.840.10008.5.1.4.1.2.1.1 / .2 / .3 |
| Storage Commitment Push Model | 1.2.840.10008.1.20.1 |
| Modality Performed Procedure Step | 1.2.840.10008.3.1.2.3.3 |
| Unified Procedure Step — Push | 1.2.840.10008.5.1.4.34.6.1 |
10 · The role model
SCU and SCP — who asks, who answers
These two acronyms cause more confusion in PACS administration than anything else in DICOM, because people try to attach them to boxes. They attach to services, and a single box plays both roles within the same hour — sometimes within the same association.
Service Class User — SCU
The client. The SCU invokes an operation: it asks for something to be stored, queried, retrieved, created or updated. It issues the request and waits for a status back.
Think: "I am the one with a request."
Service Class Provider — SCP
The server. The SCP performs the operation and returns a status. It listens on a TCP port, maintains an allow-list of AE titles, and is the one whose logs actually explain a failure.
Think: "I am the one who has to do the work."
Three rules that resolve most confusion
- Roles are per service, not per system. A PACS is a Storage SCP when receiving from a scanner and a Storage SCU when forwarding to the VNA. Ask "SCU of what?"
- Only an SCP needs a listening port and an AE allow-list. If a device is purely an SCU it needs no inbound firewall rule at all. This is exactly why C-MOVE surprises people — it forces the requester to also be an SCP.
- By default the association requester is the SCU and the acceptor is the SCP, for every presentation context proposed. Changing that requires explicit SCP/SCU Role Selection negotiation, which is what makes C-GET work.
Role assignment by service
| Service | SCU (asks) | SCP (answers) | Notes |
|---|---|---|---|
| Verification (C-ECHO) | Whoever is testing | Whoever is being tested | Every SCP must support it. Your first diagnostic in any ticket |
| Storage (C-STORE) | Modality, router, workstation sending GSPS, AI node returning results, PACS forwarding to VNA | PACS, VNA, dose registry, AI node receiving work, workstation receiving a C-MOVE | The most common service by volume. Direction of data = direction of the request |
| Modality Worklist (C-FIND) | Modality | RIS or worklist broker | Never reversed. The scanner always asks |
| Query/Retrieve — FIND | Workstation, PACS prefetch engine, RIS availability check | PACS, VNA | Metadata only, no pixels |
| Query/Retrieve — MOVE | Workstation or PACS requesting | Archive holding the images | The archive then becomes a Storage SCU to a third AE, which must be a Storage SCP |
| Query/Retrieve — GET | Workstation | Archive | Images return on the same association — the requester must accept the Storage role via role negotiation |
| MPPS (N-CREATE / N-SET) | Modality | RIS and/or PACS | Both may be configured as destinations |
| Storage Commitment (N-ACTION) | Modality (or PACS committing to VNA) | Archive | Request direction |
| Storage Commitment (N-EVENT-REPORT) | Archive | Modality | Roles invert. The archive opens a new association back. The modality must be reachable and listening |
| Print (N-CREATE / N-ACTION) | Workstation or modality | DICOM printer / print server | Legacy but still present in some departments |
| UPS (Unified Procedure Step) | Whoever creates or claims a work item | The worklist manager | Push, Pull, Watch and Event SOP classes each define roles separately |
Role negotiation, and why C-GET exists
Inside the association request, each presentation context can carry an SCP/SCU Role Selection item declaring that the requester also wishes to act as SCP for that abstract syntax. This is the mechanism that lets a single association carry a request in one direction and objects in the other.
C-MOVE — two associations, one inbound to the requester Workstation Archive Workstation (Q/R MOVE SCU) (Q/R MOVE SCP) (Storage SCP) │ 1. C-MOVE-RQ dest = WS_AE01 │ │ │ ────────────────────────────────► │ │ │ │ 2. new association │ │ │ ─────────────────────────► │ │ │ C-STORE × n │ │ │ (archive = Storage SCU) │ │ 3. C-MOVE-RSP sub-op counts │ │ │ ◄──────────────────────────────── │ │ Requires: archive knows WS_AE01 → IP:port, and firewall permits archive → workstation. C-GET — one association, no inbound connection Workstation Archive (Q/R GET SCU, Storage SCP) (Q/R GET SCP, Storage SCU) │ A-ASSOCIATE-RQ │ │ ctx: Study Root GET │ │ ctx: CT Image Storage │ │ + Role Selection: SCP=1 │ ◄ "I will also receive" │ ────────────────────────────────► │ │ C-GET-RQ │ │ ────────────────────────────────► │ │ C-STORE-RQ × n (same assoc) │ │ ◄──────────────────────────────── │ │ C-GET-RSP │ │ ◄──────────────────────────────── │ Requires: nothing inbound. Works through NAT and one-way firewall rules.
What this means when you configure a device
| If the device is… | It needs… | Common misconfiguration |
|---|---|---|
| Storage SCU only (simple modality) | Destination AE title, IP, port. No inbound rule | Wrong called AE title → rejection reason 7 |
| Storage SCP (archive, AI node) | Listening port, AE allow-list entry for every sender, accepted SOP classes and transfer syntaxes | New sender not added to the allow-list → rejection reason 3 |
| Q/R SCU using C-MOVE | To also run a Storage SCP listener, and to be registered on the archive as a move destination | Registered with the wrong port, or not registered at all → query works, retrieve never arrives |
| MWL SCU (modality) | Worklist provider address plus the query filter that matches how the RIS populates the SPS | Station AE title mismatch → empty worklist on one scanner only |
| Commitment SCU (modality) | To be reachable inbound for the N-EVENT-REPORT | Commitment never returns; techs delete on faith or never delete at all |
| Both (router, PACS, VNA) | Two sets of everything, documented separately by direction | One firewall rule written for "DICOM between A and B" that covers only one direction |
11 · PS3.7 / PS3.8
Association negotiation, in detail
Most "network" faults in DICOM are really failed negotiations. The upper-layer protocol is verbose about why it said no — you simply have to know where to look.
SCU SCP │ TCP connect to host:11112 │ │ ───────────────────────────────────────────────────► │ │ │ │ A-ASSOCIATE-RQ (PDU type 01) │ │ Calling AE Title : CT_SCANNER_01 │ who I am │ Called AE Title : PACS_ARCHIVE │ who I think you are │ Application Ctx : 1.2.840.10008.3.1.1.1 │ always this value │ Presentation Ctx 1 (id 1, odd) │ │ Abstract syntax: CT Image Storage │ │ Transfer syntax: Explicit VR LE │ │ JPEG 2000 Lossless │ │ Implicit VR LE │ │ Presentation Ctx 2 (id 3) │ │ Abstract syntax: Enhanced CT Image Storage │ │ User Information │ │ Max PDU length : 16384 │ raise on fast links │ Implementation Class UID / Version Name │ names the software │ Async operations window (optional) │ │ SCP/SCU Role Selection (optional) │ needed for C-GET │ ───────────────────────────────────────────────────► │ │ │ │ A-ASSOCIATE-AC (PDU type 02) │ │ Ctx 1: result 0 ACCEPTED — Explicit VR LE │ SCP picks exactly ONE │ Ctx 3: result 3 REJECTED — abstract syntax not supported │ ◄─────────────────────────────────────────────────── │ │ │ │ P-DATA-TF (PDU type 04): C-STORE-RQ + dataset │ │ ───────────────────────────────────────────────────► │ │ P-DATA-TF: C-STORE-RSP status 0x0000 │ │ ◄─────────────────────────────────────────────────── │ │ … repeated for every instance … │ │ │ │ A-RELEASE-RQ (05) / A-RELEASE-RP (06) │ │ ◄──────────────────────────────────────────────────► │ Alternatives to A-ASSOCIATE-AC: A-ASSOCIATE-RJ (03) — refused before any data moved A-ABORT (07) — either side tears it down mid-conversation
Presentation context result codes
| Result | Meaning | What to do |
|---|---|---|
| 0 | Acceptance | Nothing — note which transfer syntax was chosen |
| 1 | User rejection | The receiving application declined. Usually a policy or licensing limit |
| 2 | No reason (provider rejection) | Check the SCP log; the detail is there |
| 3 | Abstract syntax not supported | Configure that SOP class on the archive. The most common cause of missing series after an upgrade |
| 4 | Transfer syntaxes not supported | The SCP does not speak any encoding the SCU proposed. Add the syntax, or make the SCU transcode |
Three things every DICOM node needs
Identity
Max 16 characters, case-sensitive. Both ends must have each other's AE title configured. Adopt a naming convention and never reuse a retired one — old entries in an archive's allow-list are a security finding.
Address
Static IP or a reserved DHCP lease. Use DNS names only if you are certain every device resolves them; many modalities cache forever or ignore DNS entirely.
Capability
Which SOP classes and transfer syntaxes each side supports, in which role. Published in the vendor's DICOM Conformance Statement.
Tuning knobs that matter on real links
- Max PDU length — 16 KB is a conservative default. Raising it to 64–128 KB materially improves throughput on high-latency links by reducing round trips.
- Asynchronous operations window — allows multiple outstanding operations on one association instead of strict request/response lockstep. Supported unevenly; test rather than assume.
- Simultaneous associations — bulk migrations and busy archives need this raised, but each one costs memory on the SCP. Coordinate the number with the vendor.
- Association idle timeout — too short and long reconstructions get torn down mid-study; too long and dead sockets accumulate.
12 · DIMSE
The DIMSE services, one by one
DIMSE — DICOM Message Service Element — is the set of operations carried inside an association. C-services act on composite objects (images, made of many real-world entities). N-services act on normalized objects (a procedure step, a commitment request, a print job).
| Service | Type | SCU → SCP | What it does | Where you see it |
|---|---|---|---|---|
| C-ECHO | Composite | Tester → tested node | Verification. "Are you alive and will you talk to me?" | The first test in every ticket |
| C-STORE | Composite | Sender → receiver | Push one composite instance; one request and one status per object | Modality → PACS; PACS → VNA; router → AI |
| C-FIND | Composite | Querier → archive | Query. Returns matching attributes as a series of pending responses, then a final status. Never pixels | Worklist, Q/R, prefetch, availability checks |
| C-MOVE | Composite | Requester → archive | "Send these instances to AE X." The archive opens a second association to X and becomes a Storage SCU | Workstation retrieving priors |
| C-GET | Composite | Requester → archive | Retrieve over the same association; requires role negotiation | Firewalled and NAT'd links |
| C-CANCEL | Composite | Requester → archive | Abort an in-flight FIND, MOVE or GET | User closes a slow query |
| N-CREATE | Normalized | Modality → RIS/PACS | Create a managed object instance | MPPS "in progress", print job |
| N-SET | Normalized | Modality → RIS/PACS | Update a managed object | MPPS "completed" |
| N-GET | Normalized | Requester → provider | Read attributes of a managed object | Printer status, UPS work item |
| N-ACTION | Normalized | Modality → archive | Request an action on an object | Storage commitment request; print |
| N-EVENT-REPORT | Normalized | Archive → modality | Asynchronous notification, on a new association | Storage commitment result; UPS state change |
| N-DELETE | Normalized | Requester → provider | Delete a managed object | Print session cleanup |
C-STORE in practice
- One association typically carries an entire study — the negotiation cost is paid once, then hundreds of store operations follow.
- Each instance gets its own status. A study can be partially stored, which is why comparing instance counts on both ends is a real diagnostic step and not paranoia.
- The SCP may coerce attributes on receipt — rewriting patient name or accession to match its own records — and signals this with status
0xB000. Coercion rules are a common source of "PACS shows a different name than the scanner." - A Storage SCP that accepts an object is asserting only that it received it, not that it will keep it. That assertion is Storage Commitment's job.
C-FIND in practice
- The SCU sends one dataset containing matching keys (populated = filter) and return keys (empty = "send me this attribute").
- The SCP replies with a stream of
0xFF00pending responses, one per match, then a single0x0000success. - An empty result set is a successful query returning zero matches — it is not an error, which is why "the worklist is empty" produces no error anywhere in the logs.
13 · Query/Retrieve
Query models and matching rules
Q/R has two information models and a small matching grammar. Knowing both lets you reproduce any user-reported query problem from a command line in about thirty seconds.
| Level | Unique key required | Typical return keys |
|---|---|---|
| PATIENT | (0010,0020) Patient ID | Name, DOB, sex, number of related studies |
| STUDY | (0020,000D) Study Instance UID | Study date/time, accession, description, modalities in study, number of series |
| SERIES | (0020,000E) Series Instance UID | Modality, series number, description, number of instances |
| IMAGE | (0008,0018) SOP Instance UID | Instance number, SOP class |
| Matching type | Syntax | Example |
|---|---|---|
| Single value | Exact string | PatientID=10045522 |
| Universal | Zero-length value | StudyDescription= → "return this attribute for every match" |
| Wildcard | * any run, ? one character | PatientName=RIVERA* |
| Range | lo-hi on dates and times | StudyDate=20260101-20260131, StudyDate=-20260101 |
| List of UIDs | Backslash separated | ModalitiesInStudy=CT\MR |
| Sequence matching | Nested dataset inside an SQ | How you filter a worklist by ScheduledProcedureStepSequence[0].Modality |
Relational versus hierarchical queries
A hierarchical query requires the unique key of every level above the one you are querying — to list series you must supply the Study Instance UID. A relational query lets you skip levels, for example asking for all series with a given description across the whole archive. Relational support is optional and often disabled for performance. If a workstation's search behaves differently against two archives, this is usually why.
14 · Workflow services
Worklist, MPPS and storage commitment
These three services separate a functioning department from one that runs on typed names and hope. They are also the three most commonly left unconfigured after a go-live.
Modality Worklist
SCU the modality SCP the RIS or a worklist broker. A C-FIND against the Modality Worklist Information Model: the modality sends a query with a few keys populated and the rest empty; the SCP returns one dataset per matching Scheduled Procedure Step.
(0010,0010) PN Patient's Name RIVERA^MARIA^L (0010,0020) LO Patient ID 10045522 (0010,0030) DA Patient's Birth Date 19710304 (0010,0040) CS Patient's Sex F (0010,1030) DS Patient's Weight 68 ◄ required for PET SUV (0008,0050) SH Accession Number ACC20260811-0417 (0020,000D) UI Study Instance UID 1.2.840.113619.2.55.3… (0032,1032) PN Requesting Physician CHEN^WEI (0032,1060) LO Requested Procedure Descr. CT ABDOMEN PELVIS W CONTRAST (0040,1001) SH Requested Procedure ID RP-88231 (0040,1003) SH Requested Procedure Priority ROUTINE (0038,0300) LO Current Patient Location RAD-OPD (0040,0100) SQ Scheduled Procedure Step Sequence └ (0008,0060) CS Modality CT ◄ modality filters on this (0040,0001) AE Scheduled Station AE Title CT_SCANNER_01 ◄ and on this (0040,0002) DA SPS Start Date 20260811 ◄ and on this (0040,0003) TM SPS Start Time 103000 (0040,0006) PN Scheduled Performing Phys. OKAFOR^ADA (0040,0007) LO SPS Description CT ABD/PELV W (0040,0009) SH Scheduled Procedure Step ID SPS-88231-1 (0040,0010) SH Scheduled Station Name CT01 (0040,0011) SH SPS Location RADIOLOGY-B (0040,0008) SQ Scheduled Protocol Code Sequence
RAD instead of CT, or with a typo in the station AE title, is present in the database and invisible on the scanner. Query it yourself with findscu -W and no filters to prove the record exists, then add filters one at a time until it disappears.Modality Performed Procedure Step
SCU the modality SCP the RIS, PACS, or both. MPPS turns imaging into a status-tracked workflow: N-CREATE opens the step, N-SET closes it.
| Tag | Attribute | Notes |
|---|---|---|
| (0040,0252) | Performed Procedure Step Status | IN PROGRESS → COMPLETED or DISCONTINUED. Never goes backwards |
| (0040,0253) | Performed Procedure Step ID | Modality-assigned handle for the step |
| (0040,0244)/(0040,0245) | PPS Start Date / Time | Real acquisition start — the basis of honest room-utilisation reporting |
| (0040,0250)/(0040,0251) | PPS End Date / Time | |
| (0040,0254) | PPS Description | |
| (0040,0260) | Performed Protocol Code Sequence | What was actually done, versus what was ordered |
| (0040,0270) | Scheduled Step Attributes Sequence | Carries Study Instance UID, accession and requested procedure ID back — this is how the RIS correlates performed to scheduled |
| (0040,0340) | Performed Series Sequence | The series and referenced instances actually produced |
| (0040,0281) | PPS Discontinuation Reason Code Seq | Why an exam was abandoned — patient could not tolerate, equipment failure |
Storage Commitment
The safety interlock before anyone deletes anything from a modality — and the clearest example of roles inverting mid-transaction.
- Modality (SCU) sends
N-ACTIONto the archive (SCP) with a Transaction UID (0008,1195) and a Referenced SOP Sequence (0008,1199) listing every instance. - The archive returns an immediate acknowledgement of the request — this is not yet a commitment.
- Later, the archive (now SCU) opens a new association back to the modality and sends
N-EVENT-REPORT. Event Type ID 1 = all instances committed. Event Type ID 2 = some failed, listed in (0008,1198) with a reason in (0008,1197). - Only now may the modality purge its local copy.
The commitment gotcha
Because the result arrives on an association the archive initiates, this has the same firewall shape as C-MOVE. If commitment "never comes back," check that the archive can reach the modality's listening port and that the modality's AE title is registered on the archive as a commitment destination. Some implementations return the report on the original association instead — check the Conformance Statement rather than assuming.
15 · PS3.18
DICOMweb — QIDO-RS, WADO-RS, STOW-RS, UPS-RS
DICOMweb does what DIMSE does, over REST on port 443. It exists because zero-footprint viewers, mobile apps, cloud archives and AI services cannot practically be C-MOVE destinations. The role vocabulary changes too: instead of SCU and SCP, PS3.18 speaks of the user agent (the client making the request) and the origin server (the service holding the data).
| Service | Expands to | DIMSE equivalent | User agent | Origin server |
|---|---|---|---|---|
| QIDO-RS | Query based on ID for DICOM Objects | C-FIND | Viewer, AI service, index builder | PACS, VNA, cloud archive |
| WADO-RS | Web Access to DICOM Objects — RESTful | C-MOVE / C-GET | Viewer | Archive |
| STOW-RS | Store Over the Web | C-STORE | Uploader, AI result writer, image-share portal | Archive |
| UPS-RS | Unified Procedure Step — RESTful | MWL + MPPS combined | Worker claiming a task | Worklist manager |
| WADO-URI | The original single-object URL service | — | Legacy viewers | Archive |
QIDO-RS — querying
GET /studies?PatientID=10045522&includefield=00081030&limit=25
GET /studies?StudyDate=20260101-20260131&ModalitiesInStudy=CT
GET /studies/{studyUID}/series?Modality=CT
GET /studies/{studyUID}/series/{seriesUID}/instances
Accept: application/dicom+json ◄ the default and the one to use
Accept: multipart/related; type="application/dicom+xml"
Query parameters:
{attribute}={value} matching key, by keyword or by hex tag
includefield= extra attributes to return; includefield=all for everything
fuzzymatching=true name matching leniency, if supported
limit= / offset= paging — always page large result sets
Response 200 OK — array of JSON objects keyed by tag:
[{ "0020000D": { "vr":"UI", "Value":["1.2.840.113619…"] },
"00080050": { "vr":"SH", "Value":["ACC20260811-0417"] },
"00100010": { "vr":"PN", "Value":[{"Alphabetic":"RIVERA^MARIA^L"}] } }]
Response 204 No Content — zero matches. Not an error, same trap as C-FIND
Value array. Person names are objects with Alphabetic, Ideographic and Phonetic members, mirroring DICOM's three PN component groups.WADO-RS — retrieving
GET /studies/{studyUID} whole study, multipart
GET /studies/{studyUID}/series/{seriesUID}
GET /studies/{studyUID}/series/{seriesUID}/instances/{sopUID}
GET /studies/{studyUID}/series/{seriesUID}/instances/{sopUID}/frames/1,2,3
GET /studies/{studyUID}/metadata attributes, no pixel data
GET /studies/{studyUID}/series/{seriesUID}/rendered?viewport=512,512&window=40,400
GET /studies/{studyUID}/thumbnail
GET /{bulkdataURI} large values referenced from metadata
Accept headers select what comes back:
multipart/related; type="application/dicom" Part 10 objects
multipart/related; type="application/octet-stream" raw frames
multipart/related; type="image/jpeg" compressed frames
application/dicom+json metadata
image/jpeg, image/png rendered
transfer-syntax parameter to request a specific encoding
Status codes:
200 OK complete
206 Partial some instances could not be returned
404 Not Found no such study/series/instance
406 Not Acceptable the archive cannot produce the media type you asked for
/metadata plus bulk data URIs lets a client build a study list and load pixels lazily.STOW-RS — storing
POST /studies store instances, any study POST /studies/{studyUID} constrain to one study; mismatches are rejected Content-Type: multipart/related; type="application/dicom"; boundary=… — one part per SOP Instance — Or metadata plus bulk data: Content-Type: multipart/related; type="application/dicom+json" Response 200 — a DICOM JSON dataset containing: (0008,1199) ReferencedSOPSequence — instances accepted (0008,1198) FailedSOPSequence — instances rejected, with (0008,1197) FailureReason — e.g. 0xC000 cannot understand, 0xA700 out of resources, 0x0110 processing failure Response 202 Accepted — partial success. Read the response body, do not assume Response 409 Conflict — the instances contradict the target study
202 is where uploads quietly lose objects. Treat any STOW integration that does not parse FailedSOPSequence as unverified, because it will report success while dropping instances.UPS-RS — the modern worklist
Unified Procedure Step generalises MWL and MPPS into a single work-item model with a lifecycle: SCHEDULED → IN PROGRESS → COMPLETED or CANCELED. A worker claims a work item with a transaction UID, so two AI nodes cannot process the same study twice.
POST /workitems create a work item
GET /workitems?ProcedureStepState=SCHEDULED search
PUT /workitems/{uid}/state claim / change state (needs transaction UID)
POST /workitems/{uid}/cancelrequest request cancellation
POST /workitems/{uid}/subscribers/{aetitle} subscribe to notifications
Where DICOMweb wins
- Traverses proxies, NAT and TLS-inspecting firewalls like any other web traffic
- Standard authentication — OAuth 2.0 bearer tokens, mutual TLS — instead of AE-title allow-lists
- Retrieve a single frame instead of an entire series
- Cacheable at the proxy or CDN layer for priors
- Every developer already has tooling:
curl, browser dev tools, standard HTTP logging
Where it doesn't
- Modalities overwhelmingly still speak DIMSE only — you will run both for years
- Per-request HTTP overhead is real on very large studies without proper multipart handling and connection reuse
- Vendor implementations vary in which query parameters,
includefieldoptions and media types they honour - An AE-title allow-list is a crude control, but it is a control; a REST endpoint without proper authorisation is an open archive on the internet
17 · Encoding
Transfer syntaxes and compression
The transfer syntax is the encoding contract for a dataset: byte order, whether the VR is written explicitly, and how pixel data is compressed. Negotiation failures and "the image is corrupt" reports usually trace back here.
| UID | Transfer syntax | Use |
|---|---|---|
| 1.2.840.10008.1.2 | Implicit VR Little Endian | The default. Every SCP must support it. VR is not on the wire — private tags degrade to UN |
| 1.2.840.10008.1.2.1 | Explicit VR Little Endian | Safe, universal, uncompressed. What you use when you want nothing to go wrong |
| 1.2.840.10008.1.2.1.99 | Deflated Explicit VR LE | Whole dataset zlib-deflated — helps on slow WAN links |
| 1.2.840.10008.1.2.2 | Explicit VR Big Endian retired | Legacy. Encountering it means something very old is on your network |
| 1.2.840.10008.1.2.4.50 | JPEG Baseline (Process 1) | 8-bit lossy. Ultrasound, visible light, screenshots |
| 1.2.840.10008.1.2.4.51 | JPEG Extended (Process 2 & 4) | 12-bit lossy |
| 1.2.840.10008.1.2.4.57 | JPEG Lossless (Process 14) | Older lossless |
| 1.2.840.10008.1.2.4.70 | JPEG Lossless, First-Order Prediction (14 SV1) | The traditional lossless workhorse — widely supported |
| 1.2.840.10008.1.2.4.80 | JPEG-LS Lossless | Better ratio than .70, less universal |
| 1.2.840.10008.1.2.4.81 | JPEG-LS Near-Lossless | |
| 1.2.840.10008.1.2.4.90 | JPEG 2000 Lossless Only | Modern lossless standard. Best ratio of the common lossless options |
| 1.2.840.10008.1.2.4.91 | JPEG 2000 (lossy allowed) | Lossy — must set (0028,2110) to 01 |
| 1.2.840.10008.1.2.4.100 | MPEG2 Main Profile @ Main Level | Cine |
| 1.2.840.10008.1.2.4.102 | MPEG-4 AVC/H.264 High Profile 4.1 | Cine, endoscopy, ultrasound video |
| 1.2.840.10008.1.2.5 | RLE Lossless | Simple run-length; poor ratios, trivially implemented |
Setting a compression policy
- Diagnostic primary read: lossless only, unless your regulator and your radiologists have both signed off on a specific ratio per modality.
- Mammography: most jurisdictions require lossless for primary interpretation. Check local rules before touching this.
- Clinical review, mobile, EMR viewer: lossy is generally acceptable — label it in the viewer so nobody reads from it.
- Decompress before AI: some algorithms are validated on uncompressed data only.
The negotiation trap
If your archive advertises only Implicit VR LE and a modality sends JPEG 2000, the association still succeeds — the SCP accepts the presentation context with the transfer syntax it chose, and the SCU must either transcode or abandon that context. Some modalities transcode silently (fine), some drop the series (not fine). Verify by comparing instance counts on both ends after a test study, not by watching the association open.
Integration, infrastructure and operations
Where the two protocols meet, where the packets actually travel, and what you do at two in the morning when a study is on the wrong patient.
18 · HL7 → DICOM
The seam: order fields to worklist attributes
This table is the crossing point between the two halves of this guide. Print it. When a study lands with a wrong field, you walk this table backwards — from the DICOM tag, to the HL7 field, to the system that owns it.
| HL7 source | DICOM tag | Attribute | Failure mode when mismapped |
|---|---|---|---|
| PID-5 | (0010,0010) | Patient's Name | Both use ^, but DICOM PN has five components in a strict order. Prefix/suffix collisions produce "SMITH^JOHN^^MD^" oddities |
| PID-3 | (0010,0020) | Patient ID | Wrong CX repetition selected → studies filed under an SSN or a visit number |
| PID-3.4 | (0010,0021) | Issuer of Patient ID | Omitted in multi-facility environments → MRN collisions between sites |
| PID-7 | (0010,0030) | Patient's Birth Date | HL7 may send YYYYMMDDHHMM; DICOM DA is exactly 8 characters → truncation or rejection |
| PID-8 | (0010,0040) | Patient's Sex | DICOM accepts M, F, O only. U, N, X and blank must be translated |
| MSH-18 | (0008,0005) | Specific Character Set | UTF-8 in HL7 must become ISO_IR 192 in DICOM, or accented names mangle |
| OBR-18 (or IPC-1) | (0008,0050) | Accession Number | SH, 16 characters. Longer accessions get silently truncated and never match the report |
| ZDS-1 (or IPC-3) | (0020,000D) | Study Instance UID | Not passed through → modality generates its own → PACS holds two studies for one exam |
| OBR-19 (or IPC-2) | (0040,1001) | Requested Procedure ID | Missing → MPPS and worklist cannot be correlated |
| — (IPC-4) | (0040,0009) | Scheduled Procedure Step ID | Missing → the RIS cannot match the performed step to the scheduled one |
| OBR-4 | (0032,1060) | Requested Procedure Description | Free-text description drifts from the code; hanging protocols break |
| OBR-4.1 | (0032,1064) | Requested Procedure Code Sequence | Sending description without the code makes downstream analytics impossible |
| OBR-24 (or IPC-5) | (0008,0060) | Modality (in the SPS) | Must be a DICOM-defined value. RAD, XRAY, SCAN are not; the modality filters on this and gets nothing back |
| OBR-27.4 / OBR-7 / OBR-36 | (0040,0002)/(0040,0003) | SPS Start Date / Time | Timezone or format drift → the exam is scheduled yesterday and vanishes from the worklist |
| Config (or IPC-6) | (0040,0001) | Scheduled Station AE Title | The room-to-AE-title table. Wrong here and the exam appears on the wrong scanner's worklist |
| Config (or IPC-7) | (0040,0010) | Scheduled Station Name | Human-readable room label; techs filter on it |
| OBR-27.6 | (0040,1003) | Requested Procedure Priority | STAT exams that arrive as ROUTINE do not get read first |
| ORC-12 / OBR-16 | (0032,1032) | Requesting Physician | Confused with Referring (0008,0090) — different people in many workflows |
| PV1-8 | (0008,0090) | Referring Physician's Name | Report routing goes to the wrong inbox |
| OBR-13 | (0040,1002) | Reason for the Requested Procedure | Dropped → radiologist reads without the indication |
| ORC-2 / OBR-2 | (0040,2016) | Placer Order Number | Order reconciliation across systems fails |
| ORC-3 / OBR-3 | (0040,2017) | Filler Order Number | Same |
| PV1-19 | (0038,0010) | Admission ID | Inpatient correlation lost |
| PV1-3 | (0038,0300) | Current Patient Location | Drives portable-exam routing and prefetch |
| OBX (height/weight) | (0010,1020)/(0010,1030) | Patient's Size / Weight | Missing weight makes PET SUV uncomputable and skews dose modelling |
19 · Infrastructure
Ports, time, bandwidth and storage
Imaging is the largest data flow in most hospitals and the least tolerant of clock drift. These are the infrastructure facts you will be asked for in a change-control meeting.
| Port | Protocol | Role that needs it open inbound |
|---|---|---|
| 104/tcp | DICOM (well-known) | Any SCP. Below 1024, so needs privilege on Unix — one reason many systems avoid it |
| 11112/tcp | DICOM (registered) | The modern default for DIMSE listeners |
| 2761/tcp | DICOM ISCL | Legacy secure transport |
| 2762/tcp | DICOM TLS | Registered port for TLS-secured DIMSE |
| 2575/tcp | HL7 MLLP | The HL7 receiver. 6661, 6000 and 5000-range are also common in the wild |
| 443/tcp | DICOMweb, FHIR, viewers | The DICOMweb origin server |
| 80/8080/tcp | DICOMweb, admin UIs | Should not carry PHI unencrypted |
| 123/udp | NTP | Everything. Non-negotiable |
| 53/udp | DNS | Some modalities cache forever, or ignore DNS entirely |
| 514 / 6514 | Syslog / TLS syslog | ATNA audit repository |
Time synchronisation
Every device must take time from the same NTP source. IHE makes this a profile in its own right — CT (Consistent Time) — recommending synchronisation within one second of the community time source.
- Clock drift breaks MWL date filters — an exam scheduled "today" disappears from a scanner that thinks it is yesterday.
- It makes MPPS-derived turnaround times meaningless and occasionally negative.
- It corrupts audit trails to the point of being useless in an investigation.
- Studies sort wrongly in the reading worklist, so priors look like current exams.
Bandwidth and storage planning
| Modality | Typical study size | Comment |
|---|---|---|
| CR / DX | 10 – 40 MB | Few large images |
| Mammography 2D | 80 – 250 MB | Four high-resolution views |
| Digital breast tomosynthesis | 1 – 3 GB | The single biggest capacity shock most departments encounter |
| CT routine | 100 – 500 MB | Thin-slice and multi-phase go much higher |
| CT angio / thin slice | 1 – 4 GB | Thousands of instances |
| MR | 50 – 400 MB | Many series, small images |
| Ultrasound with cine | 20 – 500 MB | Video clips dominate |
| NM / PET-CT | 100 MB – 1.5 GB | PET plus its CT |
| XA / cardiac cine | 300 MB – 2 GB |
Transfer time, quickly
1 Gbps ≈ 125 MB/s theoretical, realistically 70–100 MB/s. A 500 MB CT is roughly 5–7 seconds on gigabit, 50–60 seconds on 100 Mbps, and 7 minutes on a 10 Mbps site link. Size the WAN for peak simultaneous studies, not the daily average.
Annual storage, quickly
studies/year × average MB/study × copies. 120,000 studies at 250 MB average with two copies is about 60 TB per year before compression and before the tomosynthesis line item. Study size inflates faster than volume does.
Network hygiene that pays off
- Separate the imaging VLAN from general clinical traffic; QoS-mark DICOM if the WAN is contended.
- Static addressing or reserved DHCP for every modality. AE-title-to-IP tables do not follow a lease renewal.
- Watch MTU on tunnels. Large PDUs plus a reduced-MTU VPN and blocked ICMP produces the classic "small studies transfer, big studies hang" — path MTU discovery is silently failing.
- Raise the max PDU size and allow more simultaneous associations for bulk migration.
- Test the failover path before you need it — including whether the DR archive uses a different AE title, because every modality would then need reconfiguring.
20 · Operations
Troubleshooting playbook
Work the chain in order. Establish which hop last saw the study, then prove the next hop rejected it rather than never receiving it. Almost every ticket resolves in one of the rows below.
| Symptom | Most likely cause | First thing to check |
|---|---|---|
| Worklist empty on one scanner | Scheduled Station AE Title mismatch, or a modality value that is not a DICOM code | Run findscu -W yourself with no filters — if the record is there, the modality's query filter is wrong |
| Worklist empty on all scanners | HL7 order feed stopped, or the MWL SCP service is down | Interface engine queue depth and last-message timestamp; then C-ECHO the MWL SCP |
| Study in PACS with no patient name | Tech typed the patient manually or used an emergency entry | (0008,1010) Station Name to identify the room; reconcile via PIR and retrain |
| Study arrives, report never attaches | Accession mismatch — leading zeros, truncation past 16 characters, or case | Compare (0008,0050) against OBR-18 byte for byte |
| Two studies for one exam | Modality generated its own Study Instance UID instead of using the scheduled one | Whether the worklist actually returned (0020,000D) and whether the modality honours it |
| Some series missing | SOP class not accepted, or presentation context rejected with result 3 or 4 | The SCP's association log: which contexts were accepted. Compare instance counts on both ends |
| Modality can't send at all | AE title mismatch, or the SCU is not in the SCP's allow-list | C-ECHO first. If echo works and store fails, it is contexts, not connectivity |
| Query works, retrieve never arrives | C-MOVE destination AE not registered on the archive, or the inbound port is blocked | The archive's move-destination table, then tcpdump on the workstation's listening port |
| Storage commitment never returns | Archive cannot open an association back to the modality | Firewall archive → modality, and the modality's AE registration on the archive |
| Images stuck "in progress" forever | MPPS N-SET COMPLETED never sent | Whether MPPS is configured at all on that modality; discontinued exams also need a status |
| Big studies fail, small ones work | Path MTU discovery over a tunnel, or an idle timeout mid-transfer | Test progressively larger payloads; check whether ICMP is blocked on the path |
| Accented names arrive as garbage | (0008,0005) missing or wrong | What MSH-18 declares versus what the interface writes into DICOM |
| Exams appear on the wrong day | Clock drift or timezone mismatch | NTP sync on every device in the chain |
| Interface engine queue growing | Downstream returning AE/AR, or not acking at all | MSA-1 values in the ack log, correlated on MSH-10 |
| STOW-RS upload "succeeds" but objects are missing | HTTP 202 with a populated FailedSOPSequence | Parse the response body, not just the status code |
| Priors don't prefetch | Rule keyed on a field the order didn't populate — body part, procedure code | The prefetch rule's match criteria against a real recent order |
Command-line toolkit
Two open-source toolkits cover nearly everything: DCMTK and dcm4che. Learn these and you can prove where any DICOM problem lives.
# 1. Is the node alive and will it accept my AE title? (you = SCU) echoscu -v -aec PACS_ARCHIVE -aet MY_TEST_AE 10.20.30.40 11112 # 2. What is on the worklist, unfiltered? (you = MWL SCU) findscu -v -W -k "ScheduledProcedureStepSequence[0].Modality=CT" \ -aec MWL_SCP -aet MY_TEST_AE 10.20.30.41 11112 # 3. Query the archive for a patient's studies (you = Q/R SCU) findscu -S -k QueryRetrieveLevel=STUDY -k PatientID=10045522 \ -k StudyInstanceUID= -k StudyDate= -k AccessionNumber= \ -aec PACS_ARCHIVE -aet MY_TEST_AE 10.20.30.40 11112 # 4. Send a test object and watch the negotiation (you = Storage SCU) storescu -v -aec PACS_ARCHIVE -aet MY_TEST_AE 10.20.30.40 11112 test.dcm # 5. Become a Storage SCP so a C-MOVE has somewhere to land storescp -v -aet MY_TEST_AE 11113 movescu -S -k QueryRetrieveLevel=STUDY -k StudyInstanceUID=1.2.840… \ --move MY_TEST_AE -aec PACS_ARCHIVE -aet MY_TEST_AE 10.20.30.40 11112 # 6. Read the header of a file, including private tags dcmdump +P 0010 test.dcm dcmdump test.dcm | grep -i accession # 7. Exercise DICOMweb without a viewer curl -H "Accept: application/dicom+json" \ "https://vna.example.org/dicomweb/studies?PatientID=10045522&includefield=all" # 8. Capture the conversation for the vendor tcpdump -i any -s 0 -w dicom.pcap host 10.20.30.40 and port 11112 Wireshark display filters: dcm | hl7 | tcp.port == 2575
21 · PS3.7 Annex C
Status codes and rejection reasons
DIMSE responses carry a two-byte status. Vendors log it in hex with no explanation. This table converts it into an action.
| Status | Meaning | What it usually is in practice |
|---|---|---|
| 0x0000 | Success | Accepted and stored |
| 0xFF00 / 0xFF01 | Pending | Normal during C-FIND — one response per match, then a final 0x0000 |
| 0xFE00 | Cancel | The SCU asked to stop |
| 0xB000 | Warning — sub-operations complete, one or more failures | C-MOVE partially delivered, or attributes coerced on C-STORE. Find out which instances failed |
| 0xB006 | Warning — elements discarded | Stored, but the archive threw attributes away (often private tags) |
| 0xB007 | Warning — data set does not match SOP class | Accepted with reservations; the object is malformed somewhere |
| 0xA700 – 0xA7FF | Refused — out of resources | Archive is full, out of memory, or throttling. Very often literally disk space |
| 0xA900 – 0xA9FF | Error — data set does not match SOP class | The object claims to be one thing and is encoded as another |
| 0xC000 – 0xCFFF | Error — cannot understand | Catch-all parse failure. Malformed or truncated object, or unsupported private encoding |
| 0x0110 | Processing failure | Generic server-side error — go to the SCP's own log |
| 0x0111 | Duplicate SOP Instance | Re-sent something already stored. Usually harmless, sometimes a retry loop |
| 0x0112 | No such object instance | Retrieve for something that isn't there |
| 0x0117 | Invalid object instance | Malformed UID |
| 0x0122 | SOP class not supported | Configure the SOP class on the archive. The classic post-upgrade failure |
| 0x0124 | Not authorized | AE title known but not permitted for this operation |
| 0x0210 | Duplicate invocation | Message ID reused on one association |
| 0x0211 | Unrecognized operation | Service not supported on that context |
Association rejection (A-ASSOCIATE-RJ)
| Reason | Text | Fix |
|---|---|---|
| 1 | No reason given | Check the SCP log — the real reason is there |
| 2 | Application context name not supported | Rare; a non-conformant implementation |
| 3 | Calling AE title not recognised | Add the SCU's AE title to the SCP's allow-list. Watch case and trailing spaces |
| 7 | Called AE title not recognised | The SCU is using the wrong AE title for the server. Fix it on the sender |
| source 1 | DICOM UL service-user | The application rejected you — configuration |
| source 2/3 | DICOM UL service-provider | Protocol or transport level — version mismatch, temporary congestion, local limit exceeded |
22 · Data integrity
Identity repair, merges and IOCM
Studies attached to the wrong patient are the highest-severity defect a PACS administrator handles. Have a documented procedure before you need one, and never fix these quietly.
Wrong patient on a study
- Stop the bleeding — remove the study from the reading worklist so it cannot be interpreted under the wrong identity.
- Correct it in the owning system first (RIS/HIS), then let the interface drive the change if PACS supports it.
- If you must edit in PACS, use the vendor's supported reconciliation tool — not a raw database edit — so the change is audited and propagated.
- Push the correction downstream: VNA, EMR image link, dose registry, AI or research copies, any CD already burned.
- Log it. Misfiled images are usually a reportable event under your organisation's patient-safety policy.
IOCM — Imaging Object Change Management
The IHE profile that makes deletions and corrections propagate. Instead of quietly deleting objects, the archive issues a Key Object Selection document with a title such as Rejected for Quality Reasons, Rejected for Patient Safety Reasons or Incorrect Modality Worklist Entry Selected. Downstream systems consume that document and hide or remove the objects themselves.
Without IOCM, a study you deleted from PACS still lives in the VNA, the EMR viewer cache and the teaching file — and will resurface.
Duplicates and near-duplicates
- Duplicate MRN — the same human registered twice. Resolved with an HL7
A40merge driven from the master patient index, not from PACS. - Split study — one exam that landed as two Study Instance UIDs. Fixed by re-keying one set of objects onto the surviving Study UID, then rebuilding the series list.
- Reused accession — a RIS that recycles accession numbers annually will silently attach this year's report to last year's images. Verify your accession scheme is unique in time, not just within a year.
- Character-set drift — the same patient stored twice because one system sent
MÜLLERand anotherMULLER. Fix the character set, then merge.
Before you accept a new interface into production
- Send a patient with an accented name, an apostrophe and a hyphenated surname.
- Send an accession at the 16-character limit and one that exceeds it.
- Send an order, then
XOit to a new time and room, thenCAit. - Send an
A08that changes the name and confirm images already in PACS update. - Send an
A40merge and confirm every study moved, including in the VNA. - Run one exam end to end without anyone typing a demographic field.
23 · Risk
Security, audit and de-identification
DICOM was designed for a trusted network that no longer exists. Every imaging object is PHI, and modalities are frequently unpatched appliances running an operating system nobody will let you touch.
Transport
DIMSE is plaintext by default, and an AE title is an identifier, not an authentication credential — anyone who can reach the port and guess the title is in. Use DICOM TLS where both ends support it, DICOMweb over HTTPS where they don't, and network segmentation everywhere.
Audit — ATNA
The IHE profile pairing node authentication with an audit trail. Systems emit structured audit messages to a central repository over TLS syslog. Combined with Consistent Time, this is what makes "who viewed this patient's images" an answerable question.
De-identification
PS3.15 Annex E defines confidentiality profiles. Removing (0010,0010) and (0010,0020) is not sufficient — PHI hides in Study and Series Description, Patient Comments, private tags, and burned into the pixels on ultrasound and secondary capture.
Media and export
CD/DVD export follows the PDI profile. Any export path — burner, portal upload, cloud AI vendor, image-exchange service — needs the same access control and audit as the archive. Export is where PHI leaves your control.
Modality-specific realities
- Many scanners run end-of-life operating systems the vendor will not permit you to patch. Compensate with VLAN isolation and strict allow-lists, and document the risk acceptance formally.
- Default vendor service accounts and shared passwords are common. Inventory them.
- Remote service access — the vendor's tunnel into your scanner — should be on-demand and logged, not always-on.
- Backups of the archive are as sensitive as the archive. Encrypt them, and test restores rather than backups.
24 · Self-check
Test yourself
If you can answer these without looking, you can hold your own in an incident call.
In a C-MOVE, name every role each of the three systems plays.
The workstation is the Query/Retrieve MOVE SCU — it issues the request — and must simultaneously be a Storage SCP, because the images arrive on a connection someone else initiates. The archive is the Q/R MOVE SCP for the request and then becomes a Storage SCU when it opens a second association to deliver the objects. If the destination happens to be a third machine, that machine is the Storage SCP and never speaks to the workstation at all.
Why does C-GET work through NAT when C-MOVE does not?
C-GET returns the objects on the same association the requester opened, so no inbound connection is ever needed. It achieves this through SCP/SCU Role Selection negotiation: the requester declares in the association request that it will also act as Storage SCP for the relevant abstract syntaxes. C-MOVE instead has the archive open a fresh association to the destination AE, which requires an inbound firewall rule and a routable address — neither of which survives NAT.
A tech reports one CT scanner's worklist is empty while the other CT works. Where do you look first?
Scheduled Station AE Title (0040,0001) and the modality's own query filter. The order is almost certainly present — prove it by running findscu -W with no filters, then add the scanner's filters one at a time until the record disappears. Also check that scanner's clock: a device a day behind queries for the wrong SPS start date and finds nothing.
Images arrive but the report never attaches. Name the three fields you compare, in order.
Accession Number first: (0008,0050) versus OBR-18, checking truncation past 16 characters, leading zeros and case. Then Patient ID: (0010,0020) versus PID-3, confirming the right CX repetition was taken. Then Study Instance UID (0020,000D) versus ZDS-1 or IPC-3, in case the study was created twice.
What does a presentation context result of 4 mean, and how is it different from 3?
Result 4 is "transfer syntaxes not supported" — the SCP recognises the SOP class but speaks none of the encodings offered, so add the transfer syntax or make the sender transcode. Result 3 is "abstract syntax not supported" — the SCP does not handle that SOP class at all, which is what you see when a modality upgrade introduces Enhanced CT or tomosynthesis objects the archive was never configured to accept.
What does 0xA700 mean, and what do you check?
Refused — out of resources. In practice this is nearly always the archive being out of disk space, out of memory, or deliberately throttling. Check free space on the storage tier first, then the archive's service logs. It is a server-side condition, so retrying from the modality will not help.
Which DICOMweb service replaces which DIMSE service, and what are the two role names?
QIDO-RS replaces C-FIND, WADO-RS replaces C-MOVE and C-GET, STOW-RS replaces C-STORE, and UPS-RS replaces MWL plus MPPS. PS3.18 calls the client the user agent and the service the origin server — the HTTP equivalents of SCU and SCP. The practical advantage is that all traffic is client-initiated over 443, so there is no C-MOVE-style inbound connection to permit.
A STOW-RS upload returns HTTP 202. Is that success?
No — 202 means partial. The response body is a DICOM JSON dataset containing (0008,1199) ReferencedSOPSequence for what was accepted and (0008,1198) FailedSOPSequence with a (0008,1197) failure reason for what was not. An integration that checks only the status code will report success while silently dropping instances.
An interface treats ORC-1 = XO as NW. What breaks, and when do you notice?
Every rescheduled exam creates a second worklist entry instead of updating the first. You notice days later, when a technologist selects the stale entry and the study is filed against the wrong scheduled step — wrong room, wrong time, sometimes a wrong accession. Test it during validation by rescheduling an order and confirming exactly one worklist entry survives.
Storage commitment never comes back from the archive. What is the shape of the problem?
The same shape as C-MOVE. The modality sent N-ACTION as SCU, but the result arrives via N-EVENT-REPORT on an association the archive initiates back to the modality. So check that the archive can reach the modality's listening port, and that the modality's AE title is registered on the archive as a commitment destination. Until it returns event type 1, nobody should be deleting from the console.
Why can a lossy-compressed image never be made lossless again, and what records this?
Lossy compression discards information permanently; transcoding to a lossless syntax afterwards preserves only the already-degraded data. (0028,2110) is set to 01 and must stay 01 for the life of the object, with the ratio in (0028,2112) and the method in (0028,2114). Any system that clears this flag on transcode is producing objects that lie about their own provenance.
Big studies hang on the WAN while small ones transfer fine. Hypothesis?
Path MTU discovery failing across a tunnel. The VPN reduces the effective MTU, large DICOM PDUs need fragmentation, and ICMP "fragmentation needed" is filtered somewhere, so the sender never learns to reduce packet size. Small transfers fit inside the working MTU and succeed. Test with progressively larger payloads, verify ICMP type 3 code 4 is permitted, and consider lowering the MSS or the negotiated max PDU size.