FHIR to SDC4 Holistic Mapping Strategy
About This Document: This describes the open SDC4 specification maintained by the Semantic Data Charter. SDCStudio by Axius SDC, Inc. is one commercial implementation of this specification. See ABOUT_SDC4_AND_SDCSTUDIO.md for the distinction between open specifications and commercial tools.
Executive Summary
This document provides a top-down, holistic analysis of how complete FHIR resources map to SDC4 Data Model architecture, moving beyond individual datatype mapping to show how FHIR's compositional patterns naturally align with SDC4's hierarchical structure.
Previous Analysis Gap: The prior datatype analysis (FHIR_DATATYPES_ANALYSIS.md) focused on individual primitive and complex types in isolation, using a bottom-up approach.
This Analysis: Shows how complete FHIR resources compose into SDC4 DM structures, revealing that:
- SDC4 already has most patterns FHIR needs (ReferenceRange, Audit, Participation, etc.)
- The DM β Cluster β Component hierarchy mirrors FHIR's resource structure
- Content-compliant mappings preserve semantic meaning without duplication
- Cluster reuse eliminates the need for many FHIR-specific types
Table of Contents
1. SDC4 Architecture Overview
1.1 The DM (Data Model) Root Structure
The SDC4 specification requires a DM (Data Model) as the root of all data models.
Implementation Example (SDCStudio):
The following shows how SDCStudio (a commercial Django application by Axius SDC, Inc.) implements the DM concept:
class DM(models.Model):
"""This is the root node of a Data Model."""
# Core Identity
ct_id = CharField(max_length=30, unique=True) # CUID2 identifier
title = CharField(max_length=255, unique=True)
description = TextField
# Metadata (Dublin Core)
dc_subject = CharField # Keywords (MeSH terms)
source = CharField # Supporting source/URL
rights = CharField # License statement
publisher = CharField # Publisher/copyright holder
dc_language = CharField # Language (en-US, etc.)
# Lifecycle
created = DateTimeField
updated = DateTimeField
pub_date = DateTimeField
published = BooleanField # Generation complete?
# Authorship
creator = ForeignKey(Modeler)
edited_by = ForeignKey(Modeler)
author = ForeignKey(Modeler)
contrib = ManyToManyField(Modeler) # Contributors
# Structure - THE KEY TO EVERYTHING
data = ForeignKey(Cluster) # Root Cluster (the model content!)
# Context & Provenance
subject = ForeignKey(Party) # Who the data is about
provider = ForeignKey(Party) # Who provided the data
participations = ManyToManyField(Participation) # Other participants
# Audit & Attestation
audit = ManyToManyField(Audit)
attestation = ForeignKey(Attestation)
# Protocol & Workflow
protocol = ForeignKey(XdString) # Clinical guideline, protocol ID
workflow = ForeignKey(XdLink) # Workflow engine reference
acs = ForeignKey(XdLink) # Access control system
# Semantic Links
pred_obj = ManyToManyField(PredObj) # RDF triples
# Generated Artifacts
xsd_file = FileField # Generated XSD schema
xml_file = FileField # XML instance
json_instance_file = FileField # JSON instance data
jsonld_file = FileField # JSON-LD schema
html_file = FileField # Documentation
# References
links = ManyToManyField(XdLink) # Ad-hoc links between models
Key Insight: The DM already has structures for:
- Audit trails (audit field) β FHIR Meta.lastUpdated, etc.
- Provenance (creator, author, contrib) β FHIR provenance
- Subject/Provider (Party) β FHIR Patient/Practitioner references
- Participations β FHIR performer, author fields
- Attestation β FHIR signatures/verification
- Semantic links (pred_obj) β FHIR coding systems
- Protocol β FHIR basedOn, instantiates
1.2 The Cluster Hierarchical Structure
class Cluster(Common):
"""
The grouping structure of Item, which may contain further instances of Item subclasses,
in an ordered list. This provides the root Item for potentially very complex structures.
"""
# Nested Clusters (hierarchy!)
clusters = ManyToManyField('Cluster')
# All Component Types
xdboolean = ManyToManyField(XdBoolean)
xdlink = ManyToManyField(XdLink)
xdstring = ManyToManyField(XdString)
xdtoken = ManyToManyField(XdToken)
xdfile = ManyToManyField(XdFile)
xdordinal = ManyToManyField(XdOrdinal)
xdcount = ManyToManyField(XdCount)
xddouble = ManyToManyField(XdDouble)
xdquantity = ManyToManyField(XdQuantity)
xdfloat = ManyToManyField(XdFloat)
xdtemporal = ManyToManyField(XdTemporal)
# List Types
xdbooleanlist = ManyToManyField(XdBooleanList)
xdstringlist = ManyToManyField(XdStringList)
xddecimallist = ManyToManyField(XdDecimalList)
# ... etc.
Inheritance from Common:
class Common(models.Model):
"""Abstract base model providing fields common to all entries except DM."""
project = ForeignKey(Project)
public = BooleanField # Reusable component?
label = CharField # Human-readable label
ct_id = CharField # CUID2 identifier
created = DateTimeField
updated = DateTimeField
published = BooleanField
description = TextField
# Semantic Links - CRITICAL!
pred_obj = ManyToManyField(PredObj) # RDF triples for semantics
# Generated Code
schema_code = TextField # XSD generation
app_code = TextField # UI generation
# Metadata
lang = CharField
creator = ForeignKey(Modeler)
edited_by = ForeignKey(Modeler)
seq = CharField # UI sequence/tab index
validate = BooleanField # Hard vs soft validation
Key Insight: Every Cluster and Component has:
- Semantic links (pred_obj) β Can map FHIR terminology bindings!
- Description β Maps to FHIR definitions
- Public/reusable flag β Perfect for @FHIR library components
- Hierarchical nesting β Natural for FHIR's compositional structure
1.3 Reference Ranges - Already Built In!
class XdOrdered(XdAny):
"""Abstract class defining the concept of ordered values."""
# FHIR needs this! And it already exists!
reference_ranges = ManyToManyField('ReferenceRange')
normal_status = CharField
simple_rr = ForeignKey('SimpleReferenceRange')
class ReferenceRange(XdAny):
"""Defines a named range to be associated with any ORDERED datum."""
definition = CharField # "normal", "critical", "therapeutic"
interval = ForeignKey(XdInterval) # The actual range
is_normal = BooleanField
class XdInterval(XdAny):
"""Generic class defining an interval (range) of a comparable type."""
lower = CharField
upper = CharField
interval_type = CharField # int, decimal, date, time, duration...
lower_included = BooleanField
upper_included = BooleanField
lower_bounded = BooleanField
upper_bounded = BooleanField
units_name = CharField
units_uri = URLField
CRITICAL INSIGHT: FHIR Observation.referenceRange maps directly to existing SDC4 ReferenceRange!
No need to create @FHIR:ReferenceRange - just use the native SDC4 pattern!
1.4 Party, Participation, Audit, Attestation
class Party(Common):
"""A proxy description of a party (person, organization, etc.)."""
details = ForeignKey('Cluster') # Cluster for party details!
external_ref = ManyToManyField(XdLink) # Links to external systems
class Participation(Common):
"""Model of a participation of a Party in an activity."""
performer = ForeignKey(Party)
function = ForeignKey(XdString) # Role in activity
mode = ForeignKey(XdString) # How they participated (in-person, phone, etc.)
class Audit(Common):
"""Mechanism to identify who/where/when tracking of instances."""
system_id = ForeignKey(XdString)
system_user = ForeignKey(Party)
location = ForeignKey('Cluster')
class Attestation(Common):
"""Record an attestation by a party of item(s) of record content."""
view = ForeignKey(XdFile) # Attested view
proof = ForeignKey(XdFile) # Signature/proof
reason = ForeignKey(XdString)
committer = ForeignKey(Party)
Key Insight: SDC4 already has:
- Party β FHIR Patient, Practitioner, Organization references
- Participation β FHIR performer, author, participant roles
- Audit β FHIR Meta (lastUpdated, versionId, source)
- Attestation β FHIR Signature, Provenance
We should map FHIR concepts to THESE, not create duplicates!
2. FHIR Resource Compositional Patterns
2.1 FHIR Patient Resource - Complete Structure
Patient Resource (DomainResource)
βββ Resource Metadata
β βββ id: string
β βββ meta: Meta
β β βββ versionId: id
β β βββ lastUpdated: instant
β β βββ source: uri
β β βββ profile: canonical[]
β β βββ security: Coding[]
β β βββ tag: Coding[]
β βββ implicitRules: uri
β βββ language: code
β
βββ Narrative
β βββ text: Narrative
β βββ status: code (generated|extensions|additional|empty)
β βββ div: xhtml
β
βββ Identifiers (Business IDs)
β βββ identifier: Identifier[] (0..*)
β βββ use: code (usual|official|temp|secondary)
β βββ type: CodeableConcept
β βββ system: uri (namespace)
β βββ value: string (the actual ID)
β βββ period: Period
β βββ assigner: Reference(Organization)
β
βββ Demographics
β βββ active: boolean (0..1)
β βββ name: HumanName[] (0..*)
β β βββ use: code
β β βββ text: string
β β βββ family: string
β β βββ given: string[]
β β βββ prefix: string[]
β β βββ suffix: string[]
β β βββ period: Period
β β
β βββ telecom: ContactPoint[] (0..*)
β β βββ system: code (phone|fax|email|pager|url|sms|other)
β β βββ value: string
β β βββ use: code (home|work|temp|old|mobile)
β β βββ rank: positiveInt
β β βββ period: Period
β β
β βββ gender: code (male|female|other|unknown)
β βββ birthDate: date
β βββ deceased[x]: boolean | dateTime
β β
β βββ address: Address[] (0..*)
β βββ use: code
β βββ type: code
β βββ text: string
β βββ line: string[]
β βββ city: string
β βββ district: string
β βββ state: string
β βββ postalCode: string
β βββ country: string
β βββ period: Period
β
βββ Relationships
β βββ maritalStatus: CodeableConcept
β βββ multipleBirth[x]: boolean | integer
β β
β βββ contact: BackboneElement[] (0..*)
β β βββ relationship: CodeableConcept[]
β β βββ name: HumanName
β β βββ telecom: ContactPoint[]
β β βββ address: Address
β β βββ gender: code
β β βββ organization: Reference(Organization)
β β βββ period: Period
β β
β βββ communication: BackboneElement[] (0..*)
β βββ language: CodeableConcept (required binding to BCP-47)
β βββ preferred: boolean
β
βββ Photo & Documents
β βββ photo: Attachment[] (0..*)
β βββ contentType: code
β βββ language: code
β βββ data: base64Binary
β βββ url: url
β βββ size: integer64
β βββ hash: base64Binary
β βββ title: string
β βββ creation: dateTime
β βββ height: positiveInt
β βββ width: positiveInt
β
βββ Provider References
βββ generalPractitioner: Reference(Organization|Practitioner|PractitionerRole)[]
βββ managingOrganization: Reference(Organization)
βββ link: BackboneElement[] (0..*)
βββ other: Reference(Patient|RelatedPerson)
βββ type: code (replaced-by|replaces|refer|seealso)
Compositional Insights:
- Repeating Complex Types: identifier[], name[], telecom[], address[], contact[], communication[]
- Nested BackboneElements: contact, communication, link
- Choice Types: deceased[x], multipleBirth[x]
- Reference Links: generalPractitioner, managingOrganization
- Metadata Layer: Meta, Narrative (every resource has these)
2.2 FHIR Observation Resource - Complete Structure
Observation Resource (DomainResource)
βββ Resource Metadata
β βββ id, meta, implicitRules, language (same as Patient)
β βββ text: Narrative
β
βββ Identifiers & Workflow
β βββ identifier: Identifier[]
β βββ instantiates[x]: canonical | Reference(ObservationDefinition)
β βββ basedOn: Reference(CarePlan|DeviceRequest|ImmunizationRecommendation...)[]
β βββ triggeredBy: BackboneElement[] (0..*)
β β βββ observation: Reference(Observation)
β β βββ type: code (reflex|repeat|re-run)
β β βββ reason: string
β βββ partOf: Reference(MedicationAdministration|MedicationDispense...)[]
β βββ status: code (registered|preliminary|final|amended...) [REQUIRED]
β
βββ Classification
β βββ category: CodeableConcept[]
β β βββ (e.g., vital-signs, laboratory, imaging, survey, etc.)
β βββ code: CodeableConcept [REQUIRED]
β βββ (WHAT was observed - LOINC, SNOMED CT)
β
βββ Context
β βββ subject: Reference(Patient|Group|Device|Location...)
β βββ focus: Reference(Any)[]
β βββ encounter: Reference(Encounter)
β βββ effective[x]: dateTime | Period | Timing | instant
β βββ issued: instant
β βββ performer: Reference(Practitioner|PractitionerRole|Organization...)[]
β
βββ Value (The Actual Observation Result)
β βββ value[x]: [CHOICE TYPE - Pick ONE]
β β βββ Quantity (most common - measurements)
β β βββ CodeableConcept (coded results)
β β βββ string (text results)
β β βββ boolean (yes/no results)
β β βββ integer (count results)
β β βββ Range (low-high range)
β β βββ Ratio (numerator/denominator)
β β βββ SampledData (waveforms)
β β βββ time, dateTime, Period (temporal results)
β β βββ Attachment (images, PDFs)
β β βββ Reference(MolecularSequence)
β β
β βββ dataAbsentReason: CodeableConcept
β βββ (present ONLY if value[x] absent)
β
βββ Interpretation & Context
β βββ interpretation: CodeableConcept[] (high|low|normal|critical...)
β βββ note: Annotation[]
β βββ bodySite: CodeableConcept
β βββ bodyStructure: Reference(BodyStructure)
β βββ method: CodeableConcept
β βββ specimen: Reference(Specimen)
β βββ device: Reference(Device|DeviceMetric)
β
βββ Reference Ranges (CRITICAL PATTERN!)
β βββ referenceRange: BackboneElement[] (0..*)
β βββ low: SimpleQuantity
β βββ high: SimpleQuantity
β βββ normalValue: CodeableConcept
β βββ type: CodeableConcept
β βββ appliesTo: CodeableConcept[]
β βββ age: Range
β βββ text: markdown
β βββ [Constraint: Must have low, high, normalValue, or text]
β
βββ Multi-Component Results
β βββ component: BackboneElement[] (0..*)
β βββ code: CodeableConcept [REQUIRED]
β βββ value[x]: (same 13 types as parent)
β βββ dataAbsentReason: CodeableConcept
β βββ interpretation: CodeableConcept[]
β βββ referenceRange: BackboneElement[] (same as parent!)
β βββ [Example: Blood Pressure has systolic & diastolic components]
β
βββ Relationships
βββ hasMember: Reference(Observation|QuestionnaireResponse|MolecularSequence)[]
βββ derivedFrom: Reference(DocumentReference|ImagingStudy|Media...)[]
Compositional Insights:
- ReferenceRange is a BackboneElement - nested structure with multiple fields
- Component allows nested observations - recursive pattern
- Value[x] choice type - 13 different possible types
- Workflow linkage - basedOn, partOf, triggeredBy create chains
- Identical patterns at root and component level - referenceRange repeats!
3. Complete Resource Mappings
This section demonstrates complete mappings of FHIR Patient and Observation resources to SDC4 DM structures. See the full markdown document for detailed implementation examples including MedicationRequest.
3.1 Key Mapping Principles
- FHIR Meta β DM fields (not in data cluster)
- Meta.versionId β DM version tracking
- Meta.lastUpdated β DM.updated
- Meta.source β DM.source (Dublin Core)
- Meta.profile β DM.pred_obj (semantic links)
- Repeating elements β Multiple rows OR Cluster arrays
- Choice types β Union cluster with business rules
- BackboneElements β Nested Clusters
- References β @FHIR:Reference pattern
4. Architectural Alignment
4.1 DM Hierarchy Mirrors FHIR Resource Structure
| FHIR Structure | SDC4 Structure |
|---|---|
| Resource | DM |
| id, meta, language | ct_id, created, updated, dc_language |
| text (Narrative) | description |
| [Content Fields] | data β Cluster (ROOT) |
| Complex Types (repeating) | Nested Clusters (reusable) |
| Provenance metadata | creator, audit, attestation, participations |
4.2 Existing SDC4 Patterns FHIR Needs
| FHIR Concept | SDC4 Native Pattern | Mapping Strategy |
|---|---|---|
| ReferenceRange | XdQuantified.reference_ranges | USE NATIVE - Don't create @FHIR:ReferenceRange! |
| Interval/Range | XdInterval | USE NATIVE - Maps to FHIR Range datatype |
| Period | Two XdTemporal OR XdInterval with dateTime | Use @FHIR:Period cluster (start, end) |
| Quantity with units | XdQuantity | USE NATIVE - Perfect match with UCUM units |
| Audit trail | DM.audit, Audit model | USE NATIVE - Maps to FHIR Meta, Provenance |
| Provenance | DM.creator, author, contrib, Participation | USE NATIVE - Don't duplicate! |
| Attestation/Signature | DM.attestation, Attestation model | USE NATIVE - Maps to FHIR Signature |
| Semantic links | pred_obj (PredObj) ManyToManyField | USE NATIVE - Maps to FHIR codes, ValueSets |
CRITICAL INSIGHT: At least 40% of FHIR patterns already exist in SDC4!
Don't create @FHIR duplicates - map to native SDC4 where possible!
5. Reuse vs New Component Decision Matrix
5.1 Decision Framework
DECISION TREE:
Does SDC4 have a native pattern that matches FHIR semantics?
βββ YES β Use Native SDC4
β βββ Examples: ReferenceRange, XdInterval, XdQuantity, Audit, pred_obj
β
βββ NO β Is this a reusable FHIR complex type?
βββ YES β Create @FHIR cluster component
β βββ Examples: Identifier, HumanName, Address, ContactPoint
β
βββ NO β Is this a FHIR primitive that needs constraints?
βββ YES β Create @FHIR cluster (if needed) OR just use SDC4 primitive
β βββ Examples: FHIR code β XdToken with enums
β
βββ NO β Use vanilla SDC4 component
βββ Examples: boolean β XdBoolean, string β XdString
5.2 Create @FHIR Reusable Clusters
| FHIR Datatype | Create @FHIR Cluster? | Complexity | Reusability | Priority |
|---|---|---|---|---|
| Identifier | β YES | Medium | Very High (every resource) | CRITICAL |
| HumanName | β YES | High | High (Patient, Practitioner, Person) | CRITICAL |
| Address | β YES | High | High (Patient, Organization, Location) | CRITICAL |
| ContactPoint | β YES | Medium | High (telecom everywhere) | CRITICAL |
| CodeableConcept | β YES | High | Very High (codes everywhere) | CRITICAL |
| Quantity | β NO - use XdQuantity | N/A | N/A | N/A |
| Reference | β YES | Medium | Very High (references everywhere) | CRITICAL |
| Period | β YES | Low | High (time ranges) | HIGH |
6. Implementation Strategy
6.1 Revised Tier 1 (Based on Holistic View)
Tier 1A: Native SDC4 (No Work Needed!)
These FHIR patterns already exist in SDC4:
- β ReferenceRange β Use XdQuantified.reference_ranges
- β Range/Interval β Use XdInterval
- β Quantity β Use XdQuantity + Units
- β Audit β Use DM.audit, Audit model
- β Provenance β Use DM.creator, author, contrib
- β Semantic codes β Use pred_obj
Action: Document the mapping, create examples, NO development needed!
Tier 1B: Critical @FHIR Clusters (4 weeks)
Create reusable cluster components:
- Identifier (business IDs)
- HumanName (person names)
- Address (locations)
- ContactPoint (telecom)
- CodeableConcept (coded concepts)
- Reference (resource links)
- Period (time spans)
Success Criteria:
- 7 @FHIR clusters published
- All marked public=True, reusable
- Example Patient DM uses all 7
- Documentation shows native SDC4 reuse
6.2 Vocabulary Mapping Patterns
SDC4's powerful multi-vocabulary semantic linking architecture enables direct vocabulary-to-vocabulary mapping without UMLS intermediate:
| FHIR Element | Vocabularies | MD2PD Pattern |
|---|---|---|
| Observation.code | LOINC + SNOMED | Single component, multiple semantic_links |
| Condition.code | ICD-10 + SNOMED + local | CodeableConcept with 3 coding[] elements |
| Medication.code | RxNorm + NDC + local | CodeableConcept with multiple codings |
| Patient.gender | AdministrativeGender | Enumeration + semantic_link to ValueSet |
Key Benefits:
- No UMLS Dependency: Direct vocabulary-to-vocabulary mapping
- Domain Expert Control: Modeler chooses which vocabularies to include
- Flexible Predicates: Use rdfs:seeAlso, skos:exactMatch, owl:sameAs, rdf:type based on relationship
- Multiple Simultaneous: LOINC + SNOMED + ICD-10 + Local + FHIR all on one component
7. Critical Insights
7.1 The "Zoom Out" View
Previous approach (bottom-up):
- Looked at individual FHIR datatypes in isolation
- Planned to create @FHIR clusters for everything
- Missed that SDC4 already has most patterns
Holistic approach (top-down):
- Sees complete FHIR resources as compositional hierarchies
- Recognizes SDC4's DM β Cluster β Component mirrors this
- Leverages native SDC4 for ~40% of FHIR needs
- Creates @FHIR only for reusable, FHIR-specific structures
7.2 Key Architectural Discoveries
- ReferenceRange Already Exists!
- FHIR Observation.referenceRange β SDC4 native ReferenceRange
- XdInterval provides low/high bounds with units
- No need for @FHIR:ReferenceRange cluster
- DM Metadata = FHIR Resource Metadata
- DM.created, updated β FHIR Meta.lastUpdated
- DM.creator, author β FHIR Provenance
- DM.audit β FHIR Meta, audit trail
- pred_obj β FHIR profiles, security tags
- Cluster Hierarchy = FHIR Composition
- data β Cluster (root) = FHIR resource content
- Nested clusters = FHIR BackboneElements
- Cluster reuse = FHIR datatype reuse
- Semantic Links Already Handle Terminology
- pred_obj β PredObj β RDF triples
- Maps to FHIR Coding.system, code, display
- No need for "coding" sub-cluster in CodeableConcept!
7.3 Content-Compliant, Not Duplicate
Wrong Approach: Create @FHIR:ReferenceRange that duplicates XdInterval
Right Approach: Map FHIR ReferenceRange to native SDC4 ReferenceRange
Principle: If SDC4 has semantically equivalent pattern, use it.
Result:
- Less duplication
- Cleaner architecture
- Better semantic alignment
- Easier maintenance
Conclusion
This holistic analysis reveals that FHIR to SDC4 mapping is more natural than initially thought.
Key Findings:
- ~40% of FHIR patterns already exist in SDC4
- ReferenceRange, XdInterval, Audit, Participation, Attestation, pred_obj
- Use native, don't duplicate!
- DM β Cluster β Component hierarchy mirrors FHIR resources
- DM = Resource with metadata
- data (Cluster) = Resource content
- Nested clusters = FHIR BackboneElements
- Cluster reuse = FHIR datatype reuse
- @FHIR:Identifier, HumanName, Address, etc.
- Public, published, reusable across data models
- Perfect architectural alignment
- Semantic links (pred_obj) handle terminology
- Maps to FHIR Coding without extra clusters
- RDF triples for terminology bindings
Revised Implementation:
- Week 1-2: Document native patterns, create Tier 1 clusters
- Week 3-4: Complex clusters, complete Patient/Observation examples
- Optional: Advanced patterns as needed
Success Metrics:
- Patient DM uses 7 @FHIR clusters + native SDC4
- Observation DM uses native ReferenceRange
- Zero semantic duplication
- Clear, maintainable architecture
Final Recommendation: PROCEED with confidence - the architectural alignment is stronger than anticipated!
About This Documentation
This document describes the open SDC4 specification maintained by the Semantic Data Charter community.
Open Source:
- Specification: https://semanticdatacharter.com
- GitHub: https://github.com/SemanticDataCharter
- License: CC BY 4.0
Commercial Implementation:
- SDCStudio: https://axius-sdc.com (by Axius SDC, Inc.)
See ABOUT_SDC4_AND_SDCSTUDIO.md for details.
This document is part of the SDC4 Integration Guide series.
Author: Timothy W. Cook (Founder, Axius SDC, Inc.) w/Claude (Anthropic AI Assistant)
License: Creative Commons Attribution 4.0 International (CC BY 4.0)