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