MRD Model
The Magnetic Resonance Data (MRD) format is a vendor neutral standard for describing data from MR acquisitions and reconstructions.
MRD version 2 and above uses Yardl to generate stream-oriented SDKs implementing the standard. MRD streaming formats are described here.
The Model Definitions below are described using the Yardl language, and can be found in the model/
subdirectory of the MRD repository. Click to expand the full model file in each component section below.
MRD Protocol
The MRD Protocol describes an MRD stream or file, which contains:
- The MRD header containing general metadata describing the acquisition, including MR system details and k-space sampling.
- A sequence of MRD datatypes that may be one of:
- Raw k-space data, stored as individual readout acquisitions.
- Image data, stored as sets of 2D or 3D arrays.
- Waveforms, storing physiological data such as electrocardiograms, pulse oximetry, or external triggering sources.
- Intermediate data, commonly used in MR image reconstruction pipelines.
Click to view MRD Protocol definitions
# Union of all primary types that can be streamed in the MRD Protocol
StreamItem:
- Acquisition
- WaveformUint32
- ImageUint16
- ImageInt16
- ImageUint32
- ImageInt32
- ImageFloat
- ImageDouble
- ImageComplexFloat
- ImageComplexDouble
- AcquisitionBucket
- ReconData
- ArrayComplexFloat
- ImageArray
# The MRD Protocol
Mrd: !protocol
sequence:
header: Header?
data: !stream
items: StreamItem
# Protocol for serializing a noise covariance matrix
MrdNoiseCovariance: !protocol
sequence:
noiseCovariance: NoiseCovariance
MRD Header
The MRD Header contains general metadata describing the acquisition, including MR system details and k-space sampling.
The header contains a small set of mandatory parameters common to all MR acquisitions, but is extensible to parameters for specialized acquisitions such as b-values, venc, magnetization preparation durations, etc.
The most critical elements for image reconstruction are contained in the encoding
field of the header, which describes the encoded spaced as well as the target reconstructed space. This section allows reconstruction software to determine matrix sizes, oversampling factors, partial Fourier, etc. An experiment can have multiple encoding spaces and it is possible to indicate on each acquired data readout, which encoding space the data belongs to (see the encodingSpaceRef
field in MRD Acquisition).
Click to view MRD Header definitions
PatientGender: !enum
values:
- m
- f
- o
SubjectInformationType: !record
fields:
patientName: string?
patientWeightKg: float?
patientHeightM: float?
patientID: string?
patientBirthdate: date?
patientGender: PatientGender?
StudyInformationType: !record
fields:
studyDate: date?
studyTime: time?
studyID: string?
accessionNumber: long?
referringPhysicianName: string?
studyDescription: string?
studyInstanceUID: string?
bodyPartExamined: string?
PatientPosition: !enum
values:
- hFP
- hFS
- hFDR
- hFDL
- fFP
- fFS
- fFDR
- fFDL
ThreeDimensionalFloat: !record
fields:
x: float
y: float
z: float
MeasurementDependencyType: !record
fields:
dependencyType: string
measurementID: string
ReferencedImageSequenceType: !record
fields:
referencedSOPInstanceUID: string*
MeasurementInformationType: !record
fields:
measurementID: string?
seriesDate: date?
seriesTime: time?
patientPosition: PatientPosition
relativeTablePosition: ThreeDimensionalFloat?
initialSeriesNumber: long?
protocolName: string?
sequenceName: string?
seriesDescription: string?
measurementDependency: MeasurementDependencyType*
seriesInstanceUIDRoot: string?
frameOfReferenceUID: string?
referencedImageSequence: ReferencedImageSequenceType?
CoilLabelType: !record
fields:
coilNumber: uint
coilName: string
AcquisitionSystemInformationType: !record
fields:
systemVendor: string?
systemModel: string?
systemFieldStrengthT: float?
relativeReceiverNoiseBandwidth: float?
receiverChannels: uint?
coilLabel: CoilLabelType*
institutionName: string?
stationName: string?
deviceID: string?
deviceSerialNumber: string?
ExperimentalConditionsType: !record
fields:
h1resonanceFrequencyHz: long
MatrixSizeType: !record
fields:
x: uint
y: uint
z: uint
FieldOfViewMm: !record
fields:
x: float
y: float
z: float
EncodingSpaceType: !record
fields:
matrixSize: MatrixSizeType
fieldOfViewMm: FieldOfViewMm
LimitType: !record
fields:
minimum: uint
maximum: uint
center: uint
EncodingLimitsType: !record
fields:
kspaceEncodingStep0: LimitType?
kspaceEncodingStep1: LimitType?
kspaceEncodingStep2: LimitType?
average: LimitType?
slice: LimitType?
contrast: LimitType?
phase: LimitType?
repetition: LimitType?
set: LimitType?
segment: LimitType?
user0: LimitType?
user1: LimitType?
user2: LimitType?
user3: LimitType?
user4: LimitType?
user5: LimitType?
user6: LimitType?
user7: LimitType?
Trajectory: !enum
values:
- cartesian
- epi
- radial
- goldenangle
- spiral
- other
UserParameterLongType: !record
fields:
name: string
value: long
UserParameterDoubleType: !record
fields:
name: string
value: double
UserParameterStringType: !record
fields:
name: string
value: string
TrajectoryDescriptionType: !record
fields:
identifier: string
userParameterLong: UserParameterLongType*
userParameterDouble: UserParameterDoubleType*
userParameterString: UserParameterStringType*
comment: string?
AccelerationFactorType: !record
fields:
kspaceEncodingStep1: uint
kspaceEncodingStep2: uint
CalibrationMode: !enum
values:
- noacceleration
- embedded
- interleaved
- separate
- external
- other
InterleavingDimension: !enum
values:
- phase
- repetition
- contrast
- average
- other
MultibandSpacingType: !record
fields:
dZ: float*
Calibration: !enum
values:
- separable2D
- full3D
- other
MultibandType: !record
fields:
spacing: MultibandSpacingType*
deltaKz: float
multibandFactor: uint
calibration: Calibration
calibrationEncoding: uint64
ParallelImagingType: !record
fields:
accelerationFactor: AccelerationFactorType
calibrationMode: CalibrationMode?
interleavingDimension: InterleavingDimension?
multiband: MultibandType?
EncodingType: !record
fields:
encodedSpace: EncodingSpaceType
reconSpace: EncodingSpaceType
encodingLimits: EncodingLimitsType
trajectory: Trajectory
trajectoryDescription: TrajectoryDescriptionType?
parallelImaging: ParallelImagingType?
echoTrainLength: long?
DiffusionDimension: !enum
values:
- average
- contrast
- phase
- repetition
- set
- segment
- user0
- user1
- user2
- user3
- user4
- user5
- user6
- user7
GradientDirectionType: !record
fields:
rl: float
ap: float
fh: float
DiffusionType: !record
fields:
gradientDirection: GradientDirectionType
bvalue: float
SequenceParametersType: !record
fields:
tR: float*
tE: float*
tI: float*
flipAngleDeg: float*
sequenceType: string?
echoSpacing: float*
diffusionDimension: DiffusionDimension?
diffusion: DiffusionType*
diffusionScheme: string?
UserParameterBase64Type: !record
fields:
name: string
value: string
UserParametersType: !record
fields:
userParameterLong: UserParameterLongType*
userParameterDouble: UserParameterDoubleType*
userParameterString: UserParameterStringType*
userParameterBase64: UserParameterBase64Type*
WaveformType: !enum
values:
- ecg
- pulse
- respiratory
- trigger
- gradientwaveform
- other
WaveformInformationType: !record
fields:
waveformName: string
waveformType: WaveformType
userParameters: UserParametersType
Header: !record
fields:
version: long?
subjectInformation: SubjectInformationType?
studyInformation: StudyInformationType?
measurementInformation: MeasurementInformationType?
acquisitionSystemInformation: AcquisitionSystemInformationType?
experimentalConditions: ExperimentalConditionsType
encoding: EncodingType*
sequenceParameters: SequenceParametersType?
userParameters: UserParametersType?
waveformInformation: WaveformInformationType*
MRD Acquisition
Raw k-space data is stored as individual readout Acquisitions. Each readout contains the complex raw data for all channels, a fixed header for metadata including encoding loop counters, and optionally corresponding k-space trajectory information.
Acquisition data is stored as a complex float array with dimensions [coils, samples]
.
k-space trajectory information is optionally included with each readout as a float array with dimensions [basis, samples]
.
Click to view MRD Acquisition definitions
AcquisitionFlags: !flags
base: uint64
values:
firstInEncodeStep1: 0x1
lastInEncodeStep1: 0x2
firstInEncodeStep2: 0x4
lastInEncodeStep2: 0x8
firstInAverage: 0x10
lastInAverage: 0x20
firstInSlice: 0x40
lastInSlice: 0x80
firstInContrast: 0x100
lastInContrast: 0x200
firstInPhase: 0x400
lastInPhase: 0x800
firstInRepetition: 0x1000
lastInRepetition: 0x2000
firstInSet: 0x4000
lastInSet: 0x8000
firstInSegment: 0x10000
lastInSegment: 0x20000
isNoiseMeasurement: 0x40000
isParallelCalibration: 0x80000
isParallelCalibrationAndImaging: 0x100000
isReverse: 0x200000
isNavigationData: 0x400000
isPhasecorrData: 0x800000
lastInMeasurement: 0x1000000
isHpfeedbackData: 0x2000000
isDummyscanData: 0x4000000
isRtfeedbackData: 0x8000000
isSurfacecoilcorrectionscanData: 0x10000000
isPhaseStabilizationReference: 0x20000000
isPhaseStabilization: 0x40000000
EncodingCounters: !record
fields:
# Phase encoding line
kspaceEncodeStep1: uint?
# Partition encoding
kspaceEncodeStep2: uint?
# Signal average
average: uint?
# Slice number (multi-slice 2D)
slice: uint?
# Echo number in multi-echo
contrast: uint?
# Cardiac phase
phase: uint?
# Counter in repeated/dynamic acquisitions
repetition: uint?
# Sets of different preparation, e.g. flow encoding, diffusion weighting
set: uint?
# Counter for segmented acquisitions
segment: uint?
# User-defined counters
user: uint*
AcquisitionData: !array
items: complexfloat
dimensions:
coils:
samples:
TrajectoryData: !array
items: float
dimensions:
basis:
samples:
AcquisitionHeader: !record
fields:
# A bit mask of common attributes applicable to individual acquisition
flags: AcquisitionFlags
# Encoding loop counters
idx: EncodingCounters
# Unique ID corresponding to the readout
measurementUid: uint
# Zero-indexed incrementing counter for readouts
scanCounter: uint?
# Clock time stamp (e.g. milliseconds since midnight)
acquisitionTimeStamp: uint?
# Time stamps relative to physiological triggering
physiologyTimeStamp: uint*
# Channel numbers
channelOrder: uint*
# Number of readout samples to be discarded at the beginning
# (e.g. if the ADC is active during gradient events)
discardPre: uint?
# Number of readout samples to be discarded at the end
# (e.g. if the ADC is active during gradient events)
discardPost: uint?
# Index of the readout sample corresponing to k-space center (zero indexed)
centerSample: uint?
# Indexed reference to the encoding spaces enumerated in the MRD Header
encodingSpaceRef: uint?
# Readout bandwidth, as time between samples in microseconds
sampleTimeUs: float?
# Center of the excited volume, in LPS coordinates relative to isocenter in millimeters
position: float[3]
# Directional cosine of readout/frequency encoding
readDir: float[3]
# Directional cosine of phase encoding (2D)
phaseDir: float[3]
# Directional cosine of slice normal, i.e. cross-product of read_dir and phase_dir
sliceDir: float[3]
# Offset position of the patient table, in LPS coordinates
patientTablePosition: float[3]
# User-defined integer parameters
userInt: int*
# User-defined float parameters
userFloat: float*
Acquisition: !record
fields:
# Acquisition header
head: AcquisitionHeader
# Raw k-space samples array
data: AcquisitionData
# Trajectory array
trajectory: TrajectoryData
computedFields:
coils: size(data, "coils")
samples: size(data, "samples")
activeChannels: size(head.channelOrder)
trajectoryDimensions: size(trajectory, "basis")
trajectorySamples: size(trajectory, "samples")
MRD Image
Image data is stored as either sets of 2D or 3D arrays with a fixed Image header of common properties and metadata. Images can be organized into series of common types and multi-channel data is supported for non-coil-combined images.
Image data is organized as a 4-D array of the chosen image data type with dimensions [channel, z, y, x]
.
Click to view MRD Image definitions
ImageFlags: !flags
base: uint64
values:
isNavigationData: 0x1
firstInAverage: 0x10
lastInAverage: 0x20
firstInSlice: 0x40
lastInSlice: 0x80
firstInContrast: 0x100
lastInContrast: 0x200
firstInPhase: 0x400
lastInPhase: 0x800
firstInRepetition: 0x1000
lastInRepetition: 0x2000
firstInSet: 0x4000
lastInSet: 0x8000
ImageType: !enum
values:
magnitude: 1
phase: 2
real: 3
imag: 4
complex: 5
ImageData<Y>: !array
items: Y
dimensions:
channel:
z:
y:
x:
ImageHeader: !record
fields:
# A bit mask of common attributes applicable to individual images
flags: ImageFlags
# Unique ID corresponding to the image
measurementUid: uint
# Physical size (in mm) in each of the 3 dimensions in the image
fieldOfView: float[3]
# Center of the excited volume, in LPS coordinates relative to isocenter in millimeters
position: float[3]
# Directional cosine of readout/frequency encoding
colDir: float[3]
# Directional cosine of phase encoding (2D)
lineDir: float[3]
# Directional cosine of 3D phase encoding direction
sliceDir: float[3]
# Offset position of the patient table, in LPS coordinates
patientTablePosition: float[3]
# Signal average
average: uint?
# Slice number (multi-slice 2D)
slice: uint?
# Echo number in multi-echo
contrast: uint?
# Cardiac phase
phase: uint?
# Counter in repeated/dynamic acquisitions
repetition: uint?
# Sets of different preparation, e.g. flow encoding, diffusion weighting
set: uint?
# Clock time stamp (e.g. milliseconds since midnight)
acquisitionTimeStamp: uint?
# Time stamps relative to physiological triggering, e.g. ECG, pulse oximetry, respiratory
physiologyTimeStamp: uint*
# Interpretation type of the image
imageType: ImageType
# Image index number within a series of images, corresponding to DICOM InstanceNumber (0020,0013)
imageIndex: uint?
# Series index, used to separate images into different series, corresponding to DICOM SeriesNumber (0020,0011)
imageSeriesIndex: uint?
# User-defined int parameters
userInt: int*
# User-defined float parameters
userFloat: float*
ImageMetaValue: [string, long, double]
ImageMeta: string->ImageMetaValue*
Image<T>: !record
fields:
# Image header
head: ImageHeader
# Image data array
data: ImageData<T>
# Meta attributes
meta: ImageMeta
computedFields:
channels: size(data, "channel")
slices: size(data, "z")
rows: size(data, "y")
cols: size(data, "x")
ImageUint16: Image<uint16>
ImageInt16: Image<int16>
ImageUint32: Image<uint>
ImageInt32: Image<int>
ImageFloat: Image<float>
ImageDouble: Image<double>
ImageComplexFloat: Image<complexfloat>
ImageComplexDouble: Image<complexdouble>
# Union of all MRD Image types
AnyImage:
- ImageUint16
- ImageInt16
- ImageUint32
- ImageInt32
- ImageFloat
- ImageDouble
- ImageComplexFloat
- ImageComplexDouble
MRD Waveform
Physiological data such as electrocardiograms, pulse oximetry, or external triggering sources are stored as individual waveforms along with a fixed Waveform header for metadata.
The waveformId
field in the Waveform
record describes the type of physiological data stored. For custom Waveform IDs, corresponding WaveformInformation
entries should be added to the MRD header to describe the data interpretation.
Waveform data is streamed as an uint32
array with dimensions [channels, samples]
.
Click to view MRD Waveform definitions
WaveformSamples<T>: !array
items: T
dimensions:
- channels
- samples
Waveform<T>: !record
fields:
# Bit field of flags. Currently unused
flags: uint64
# Unique ID for this measurement
measurementUid: uint
# Number of the acquisition after this waveform
scanCounter: uint
# Starting timestamp of this waveform
timeStamp: uint
# Time between samples in microseconds
sampleTimeUs: float
# ID matching the waveform in the MRD header
waveformId: uint
# Waveform sample array
data: WaveformSamples<T>
computedFields:
channels: size(data, "channels")
numberOfSamples: size(data, "samples")
WaveformUint32: Waveform<uint32>
MRD Intermediate Types
MRD includes definitions for intermediate data types commonly used in MR image reconstruction, including Acquisitions
"bucketed" by encoding parameters, buffered k-space data, arrays of Images
, and dynamic multi-dimensional arrays.
Click to view MRD Intermediate definitions
NoiseCovariance: !record
fields:
# Comes from Header.acquisitionSystemInformation.coilLabel
coilLabels: CoilLabelType*
# Comes from Header.acquisitionSystemInformation.relativeReceiverNoiseBandwidth
receiverNoiseBandwidth: float
# Comes from Acquisition.sampleTimeUs
noiseDwellTimeUs: float
# Number of samples used to compute matrix
sampleCount: size
# Noise covariance matrix with dimensions [coil, coil]
matrix: complexfloat[,]
AcquisitionBucket: !record
fields:
data: Acquisition*
ref: Acquisition*
datastats: EncodingLimitsType*
refstats: EncodingLimitsType*
waveforms: WaveformUint32*
# Sampled range along E0, E1, E2 (for asymmetric echo and partial fourier)
SamplingLimits: !record
fields:
kspaceEncodingStep0: LimitType
kspaceEncodingStep1: LimitType
kspaceEncodingStep2: LimitType
SamplingDescription: !record
fields:
encodedFOV: FieldOfViewMm
reconFOV: FieldOfViewMm
encodedMatrix: MatrixSizeType
reconMatrix: MatrixSizeType
samplingLimits: SamplingLimits
ReconBuffer: !record
fields:
# Buffered Acquisition data
data: complexfloat[loc, s, n, chan, e2, e1, e0]
# Buffered Trajectory data
trajectory: float[loc, s, n, e2, e1, basis, samples]
# Buffered Density weights
density: float[loc, s, n, e2, e1, e0]?
# Buffered AcquisitionHeaders
headers: AcquisitionHeader[loc, s, n, e2, e1]
# Sampling details for these Acquisitions
sampling: SamplingDescription
ReconAssembly: !record
fields:
data: ReconBuffer
ref: ReconBuffer?
ReconData: !record
fields:
buffers: ReconAssembly*
ImageArray: !record
fields:
data: complexfloat[loc, s, n, channel, z, y, x]
headers: ImageHeader[loc, s, n]
meta: ImageMeta[loc, s, n]
waveforms: WaveformUint32*
Array<T>: !array
items: T
ArrayComplexFloat: Array<complexfloat>