Keep the pipeline. Change the target.
A DICOM dataset describes imaging in DICOM terms. A FHIR ImagingStudy describes an imaging study in the resource model an application may already use for healthcare integrations. EASI JS’s built-in mapper connects those models for FHIR R4 4.0.1.
The source and parser are the same as our first example. Change the target to toFHIRImagingStudy() and provide the references your application already knows. This example remains entirely offline.
import EASI from '@xinonix/easi-js';
const metadata = {
'00080016': { vr: 'UI', Value: ['1.2.840.10008.5.1.4.1.1.7'] },
'00080018': { vr: 'UI', Value: ['2.25.123.1.1'] },
'00080050': { vr: 'SH', Value: ['SYNTHETIC-ACCESSION'] },
'00080060': { vr: 'CS', Value: ['OT'] },
'00100020': { vr: 'LO', Value: ['SYNTHETIC-PATIENT'] },
'0020000D': { vr: 'UI', Value: ['2.25.123'] },
'0020000E': { vr: 'UI', Value: ['2.25.123.1'] }
};
const source = new TextEncoder().encode(JSON.stringify(metadata));
const result = await EASI.pipelineBuilder()
.fromByteStream()
.ofDicomMetadata()
.toFHIRImagingStudy({
profile: 'full',
status: 'available',
subject: { reference: 'Patient/example' },
identifierSystems: {
accession: 'https://example.org/accessions'
},
endpoints: {
study: 'Endpoint/dicomweb',
series: 'Endpoint/dicomweb'
}
})
.build()
.process({ source });
console.log(JSON.stringify(result.first(), null, 2));Save it as imaging-study.mjs and run node imaging-study.mjs. The complete output includes a DICOM UID identifier, one series, and one instance. These selected fields show the resource’s overall shape:
{
"resourceType": "ImagingStudy",
"status": "available",
"subject": { "reference": "Patient/example" },
"numberOfSeries": 1,
"numberOfInstances": 1
}The model serializes with JSON.stringify() or toJSON(). Its series use FHIR’s singular series[].instance[] property, and its subject is a Reference.
EASI JS 1.0.0 uses class names for FHIR’s resourceType. With Vite 8 or Astro 7, set build.rolldownOptions.output.keepNames to true (inside vite for Astro). Other bundlers need their equivalent setting. Check that the built application still produces "resourceType": "ImagingStudy". See Rolldown’s name-preservation option.
Your application supplies the identity context.
Patient/example and Endpoint/dicomweb are illustrative references to existing FHIR resources. Replace them with references resolved by your application. The mapper creates an ImagingStudy in memory; it does not match patients, create server-side Patient or Endpoint records, or submit the resource to a FHIR server.
Put a DICOMweb retrieval URL in the Endpoint resource’s address. An ImagingStudy’s endpoint field references that resource; placing a WADO URL directly in that field does not model the relationship correctly.
Providing subject selects external-reference mode unless you explicitly override it. The default, when no subject is supplied, creates a contained Patient and references it as #patient. Decide which model fits your receiving system.
Identifier namespaces are equally deliberate. identifierSystems.accession supplies an absolute URI for your accession-number namespace. StudyInstanceUID uses urn:dicom:uid, while identifierSystems.study applies to the separate DICOM StudyID attribute.
A query summary and an instance collection tell different stories.
| Profile | Required imaging fields | How counts work |
|---|---|---|
full | Study UID, series UID, instance UID, SOP Class UID, and a modality | Counts the unique instances actually represented in this process call |
study-summary | Study UID | Uses the source’s declared series and instance counts when present |
Both profiles require a subject. A study-level search response often lacks series and instance fields, so use the summary profile for that input. Here is a standalone synthetic summary with two declared series and eighteen declared instances:
import EASI from '@xinonix/easi-js';
const metadata = {
'0020000D': { vr: 'UI', Value: ['2.25.123'] },
'00080061': { vr: 'CS', Value: ['CT'] },
'00201206': { vr: 'IS', Value: [2] },
'00201208': { vr: 'IS', Value: [18] }
};
const result = await EASI.pipelineBuilder()
.fromByteStream()
.ofDicomMetadata()
.toFHIRImagingStudy({
profile: 'study-summary',
subject: { reference: 'Patient/example' }
})
.build()
.process({
source: new TextEncoder().encode(JSON.stringify(metadata))
});
console.log(JSON.stringify(result.first(), null, 2));Run node study-summary.mjs. The output contains numberOfSeries: 2 and numberOfInstances: 18, without a series list. Missing declared summary counts are omitted rather than guessed.
A full resource built from five retrieved instances may represent only part of a larger PACS study. Its observed count is five; it does not establish that the archive holds only five instances.
Know the boundary of one mapping operation.
Within one process() call, metadata records group by StudyInstanceUID. Series and instances group by their UIDs, and duplicate records enrich existing entries without increasing counts. Interleaved studies stay separate. A later call begins a fresh aggregation.
The mapper rejects documented identity conflicts, missing required fields, invalid supplied dates or numbers, and conflicting summary counts. That helps surface inconsistent input where it occurs. It is a bounded ImagingStudy mapper; receiving-server implementation guides and terminology rules may impose additional requirements.
Pixel data is not included in an ImagingStudy. Native-text mapping supports ASCII, UTF-8, and Latin-1, with explicit failures for unsupported character-set declarations. DICOM JSON and XML supply already-decoded Unicode text.
Read the full mapping guide for supported fields, reference templates, computed mappings, conflict handling, and validation scope.
Connect the pipeline to an archive
Use Node.js DIMSE to query a PACS and map its study summaries through the same target.