DICOM Connector Hierarchy Mapping Guide
Introduction
This document explains how the DICOM Connector maps DICOM data structures to the Flywheel hierarchy.
Both DICOM and Flywheel use a 3-level hierarchy for organizing medical imaging data:
| Level | DICOM | Flywheel |
|---|---|---|
| Level 1 | Patient | Subject |
| Level 2 | Study | Session |
| Level 3 | Series | Acquisition |
While the hierarchies align conceptually, they use different identification approaches:
- DICOM: Uses globally unique identifiers (UIDs) to identify objects
PatientIDfor patientsStudyInstanceUIDfor studiesSeriesInstanceUIDfor series
- Flywheel: Uses human-readable labels to identify containers
subject.labelfor subjectssession.labelfor sessionsacquisition.labelfor acquisitions
The DICOM Connector's mapping challenge is deriving appropriate Flywheel labels from DICOM metadata, since DICOM UIDs are not suitable for human-readable labels.
For information about metadata processing mechanics, see the Metadata Extraction Guide. For advanced configuration options, see the Advanced Configuration Guide.
Default Field Mappings
The following table shows standard mappings from DICOM tags to Flywheel fields:
| Flywheel Field | DICOM Tag | Notes |
|---|---|---|
group._id | Routing field (e.g., PatientComments) | Based on routing string parsing |
project.label | Routing field (e.g., PatientComments) | Based on routing string parsing |
subject.label | Routing field (e.g., PatientComments) | Based on routing string parsing |
subject.firstname | PatientName | See name parsing rules |
subject.lastname | PatientName | See name parsing rules |
session.uid | StudyInstanceUID | |
session.label | Configured routing field (e.g., PatientComments) or header mapping (e.g., StudyDescription by default) | Can be based on routing string parsing or directly mapped from other DICOM headers. |
session.operator | OperatorsName | |
session.timestamp | StudyDate / StudyTime | See timestamp parsing |
acquisition.uid | SeriesInstanceUID | See UID processing rules |
acquisition.label | SeriesDescription | |
acquisition.timestamp | AcquisitionDate / AcquisitionTime | See timestamp parsing |
Site-Specific Configurations
These are default mappings. Individual sites may use different DICOM tags for Flywheel fields. Consult your Site Administrator for site-specific mappings.
Key Label Mappings
Subject Level:
subject.label←PatientID(notPatientName)- Subject identification uses the DICOM patient identifier
Session Level:
session.label←StudyDescription- Session identification uses the study description text, not
StudyInstanceUID
Acquisition Level:
acquisition.label←SeriesDescription- Acquisition identification uses the series description text, not
SeriesInstanceUID
Multiple DICOM Series to One Flywheel Acquisition
Because Flywheel uses SeriesDescription (not SeriesInstanceUID) for acquisition.label, multiple DICOM series with the same description become a single Flywheel acquisition.
Common Scenarios:
- Localizer Scans: Some modalities create separate series for each plane (axial, sagittal, coronal) with identical descriptions
- Multi-Echo Sequences: Multiple echoes may be stored as separate series with the same description
- Dynamic Series: Time-series acquisitions may be split into multiple series
Example:
Whether this grouping is appropriate depends on your use case. Some customers prefer all related series grouped together; others require separation.
SeriesInstanceUID Processing
To address cases where UIDs need to influence Flywheel organization, the Connector applies special processing to SeriesInstanceUID:
Derived Series Handling
DICOMs with ImageType values DERIVED\SECONDARY\SCREEN SAVE or DERIVED\SECONDARY\VXTL STATE receive a "decremented" UID:
- Original:
SeriesInstanceUID=4.5.6 - Processed:
acquisition.uid=4.5.5
This groups derived series with their source series in Flywheel.
AcquisitionNumber Suffix
For non-Siemens manufacturers, when AcquisitionNumber > 1, the UID is suffixed with _{AcquisitionNumber}:
| SeriesInstanceUID | ImageType | Manufacturer | AcquisitionNumber | acquisition.uid |
|---|---|---|---|---|
| 1.2.3.4 | ORIGINAL... | (any) | (any) | 1.2.3.4 |
| 1.2.3.4 | DERIVED... | (any) | (any) | 1.2.3.3 |
| 1.2.3.4 | (any) | SIEMENS | 2 | 1.2.3.4 |
| 1.2.3.4 | (any) | GE | 2 | 1.2.3.4_2 |
| 1.2.3.4 | (any) | GE | 1 | 1.2.3.4 |
This separates multi-part acquisitions into distinct Flywheel acquisitions.
Container Creation Rules
Understanding how containers are created helps predict where data will appear:
- Groups: Desired group should be manually created in advance.
Unknowngroup is automatically created if desired group does not exist or if mapping string is missing or cannot be parsed.
- Projects: Created based on routing string.
- Ideally, the desired project is manually created in advance with the preferred settings. Otherwise, the DICOM connector will create it with default settings.
Unsortedproject is created if mapping string is missing or cannot be parsed.
- Subjects: Created based on routing string or derived from DICOM metadata (e.g.,
PatientID) - Sessions: Created based on routing string or derived from DICOM metadata (e.g.,
StudyDescription) - Acquisitions: Always created for each unique
SeriesDescription
Routing String Processing
Format Specification
Valid routing strings follow this format:
Processing Rules
The Connector parses routing strings according to these rules:
| Routing String Pattern | Result | Notes |
|---|---|---|
fw://group/project/subject/session | Complete routing | Ideal case - all containers specified |
fw://group/project/subject | Partial routing | Session name derived from StudyDescription |
fw://group/project | Group + Project only | Subject and session from DICOM metadata |
fw://group | Group only | Data goes to Unsorted Project |
| Invalid format or missing | Default routing | Data goes to Unknown Group |
Container Resolution Logic
The DICOM Connector uses two decision processes to determine where data is placed in Flywheel:
Routing String Parsing:
The following flowchart shows how routing strings are parsed to determine target containers:
flowchart TD
start([Routing String Input]) --> parse{Parse Routing String}
parse -->|"fw://group/project/subject/session"| complete[Complete Routing Specified]
parse -->|"fw://group/project/subject"| partial_subject[Partial Routing]
parse -->|"fw://group/project"| partial_project[Group + Project Only]
parse -->|"fw://group"| group_only[Group Only]
parse -->|Invalid or missing| invalid[Invalid/Missing]
complete --> result_complete[Group, Project, Subject, Session all specified]
partial_subject --> session_fallback[Derive Session from StudyDescription]
session_fallback --> result_partial_subject[Specified Group, Project, Subject + Derived Session]
partial_project --> subject_fallback[Derive Subject from PatientID]
subject_fallback --> session_fallback2[Derive Session from StudyDescription]
session_fallback2 --> result_partial_project[Specified Group, Project + Derived Subject, Session]
group_only --> unsorted_project["Use 'Unsorted' Project"]
unsorted_project --> subject_fallback2[Derive Subject from PatientID]
subject_fallback2 --> session_fallback3[Derive Session from StudyDescription]
session_fallback3 --> result_group_only[Specified Group + Default Project + Derived Subject, Session]
invalid --> unknown_group["Use 'Unknown' Group"]
unknown_group --> unsorted_project2["Use 'Unsorted' Project"]
unsorted_project2 --> subject_fallback3[Derive Subject from PatientID]
subject_fallback3 --> session_fallback4[Derive Session from StudyDescription]
session_fallback4 --> result_invalid[Default Group, Project + Derived Subject, Session]
result_complete --> next[Proceed to Upload Decision]
result_partial_subject --> next
result_partial_project --> next
result_group_only --> next
result_invalid --> next
style start fill:#e8f5e9
style parse fill:#fff9c4
style complete fill:#fff
style partial_subject fill:#fff
style partial_project fill:#fff
style group_only fill:#fff
style invalid fill:#fff
style result_complete fill:#e3f2fd
style result_partial_subject fill:#e3f2fd
style result_partial_project fill:#e3f2fd
style result_group_only fill:#e3f2fd
style result_invalid fill:#e3f2fd
style next fill:#e8f5e9 Upload Decision Logic:
After resolving container labels, the Connector determines whether to update existing containers or create new ones:
flowchart TD
start([Upload Ready]) --> session_check{Session UID exists in Flywheel?}
session_check -->|Yes| acq_check{Acquisition UID exists in session?}
session_check -->|No| group_check{Group ID exists? - Fuzzy Match}
acq_check -->|Yes| uid_placement[UID Placement: Update existing acquisition]
acq_check -->|No| uid_placement_new[UID Placement - New Acq: Create acquisition in existing session]
group_check -->|Yes| project_check{Project Label exists in group?}
group_check -->|No| unknown_placement[Unknown Placement: Create in Unknown Group, Unsorted Project]
project_check -->|Yes| new_session[New Placement - Session: Create new session in existing project]
project_check -->|No| unsorted_placement[Unsorted Placement: Create in existing group, Unsorted Project]
uid_placement --> complete([Upload Complete])
uid_placement_new --> complete
new_session --> complete
unsorted_placement --> complete
unknown_placement --> complete
style start fill:#e8f5e9
style session_check fill:#fff9c4
style acq_check fill:#fff9c4
style group_check fill:#fff9c4
style project_check fill:#fff9c4
style uid_placement fill:#e1f5fe
style uid_placement_new fill:#fff9c4
style new_session fill:#c8e6c9
style unsorted_placement fill:#ffe0b2
style unknown_placement fill:#ffccbc
style complete fill:#e8f5e9 Flywheel Container Hierarchy
The DICOM Connector places data in the Flywheel hierarchy:
Complete Mapping Example
| DICOM Field | DICOM Value | Flywheel Field | Flywheel Value |
|---|---|---|---|
PatientComments | fw://neurology/parkinsons/sub-001 | group.id | neurology |
PatientComments | fw://neurology/parkinsons/sub-001 | project.label | parkinsons |
PatientComments | fw://neurology/parkinsons/sub-001 | subject.label | sub-001 |
PatientComments | fw://neurology/parkinsons/sub-001 | session.label | ses-baseline |
PatientName | doe^john | subject.firstname | John |
PatientName | doe^john | subject.lastname | Doe |
StudyInstanceUID | 1.2.3.4.5 | session.uid | 1.2.3.4.5 |
StudyDescription | Baseline Assessment | session.label | Baseline Assessment |
OperatorsName | tech^smith | session.operator | tech^smith |
StudyDate | 20241201 | session.timestamp | 2024-12-01T14:30:00+00:00 |
StudyTime | 143000 | ||
SeriesInstanceUID | 1.2.3.4.5.6 | acquisition.uid | 1.2.3.4.5.6 |
SeriesDescription | T1w MPRAGE | acquisition.label | T1w MPRAGE |
AcquisitionDate | 20241201 | acquisition.timestamp | 2024-12-01T14:35:00+00:00 |
AcquisitionTime | 143500 |
When Custom Configuration Is Needed
The default mappings work for many scenarios, but custom configuration may be needed when:
- Series Descriptions Are Not Unique: Multiple unrelated series share the same description
- Series Grouping Is Incorrect: Related series should be grouped but have different descriptions, or vice versa
- Labels Are Not Meaningful: Default DICOM fields do not provide useful labels for your workflow
- Routing Information Is Missing: Standard DICOM fields do not contain group/project information
Custom configuration options are documented in the Advanced Configuration Guide.
Related Resources
- Flywheel Hierarchy Concept - Understanding Flywheel's organizational structure
- Metadata Extraction Guide - Metadata processing mechanics
- Advanced Configuration Guide - Custom metadata extraction and configuration
- DICOM Connector Overview - Feature overview and key concepts
- Admin Guide - Ongoing management and operations
- User Guide - Scanner operator instructions