Difference between revisions of "NAMIC Wiki:DTI:DICOM for DWI and DTI"

From NAMIC Wiki
Jump to: navigation, search
Tag: 2017 source edit
 
(29 intermediate revisions by 7 users not shown)
Line 13: Line 13:
 
  0018 9117 SQ 1 MR Diffusion Sequence
 
  0018 9117 SQ 1 MR Diffusion Sequence
 
  0018 9147 CS 1 Diffusion Anisotropy Type
 
  0018 9147 CS 1 Diffusion Anisotropy Type
 +
0018 9602 FD 1 DiffusionBValueXX
 +
0018 9603 FD 1 DiffusionBValueXY
 +
0018 9604 FD 1 DiffusionBValueXZ
 +
0018 9605 FD 1 DiffusionBValueYY
 +
0018 9606 FD 1 DiffusionBValueYZ
 +
0018 9607 FD 1 DiffusionBValueZZ
  
 
These are defined in [ftp://medical.nema.org/medical/dicom/final/sup49_ft.pdf Supplement 49]. In particular see section C.8.12.5.9 "MR Diffusion Macro" on pages 94 and 95.
 
These are defined in [ftp://medical.nema.org/medical/dicom/final/sup49_ft.pdf Supplement 49]. In particular see section C.8.12.5.9 "MR Diffusion Macro" on pages 94 and 95.
Line 21: Line 27:
  
 
* The definition of "Diffusion Gradient Orientation" implies that the measurement frame is exactly the identity transform.
 
* The definition of "Diffusion Gradient Orientation" implies that the measurement frame is exactly the identity transform.
* There appears to be no means of recording the full B-matrix when it is known. This is not an issue for any NAMIC datasets, but can arise in small-bore imaging.
+
* While one can encode the B-matrix, it is [https://github.com/rordenlab/dcm2niix/issues/265 underspecified to store the polarity of the b-vector]. This makes it insufficient for tools like [https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/eddy#eddy_--_a_tool_for_correcting_eddy_currents_and_movements_in_diffusion_data FSL's eddy] which leverage the fact that polar opposite b-vectors should have identical true signal yet differ due to eddy currents (and therefore artifacts can be modeled and removed).
  
== Private vendor: GE ==
+
=== Private vendor: Canon ===
 +
 
 +
For Canon (né Toshiba) scanners saving classic 2D DICOM images, the gradient direction is stored in the text-based image comments fields. For older systems, the DiffusionBValue (0018,9087) tag may be omitted for images where the b-value is equal to zero. Be aware that the gradient direction stored in the comment field may not take into account the phase encoding polarity, so it may not be accurate. Example data illustrating this problem is [https://github.com/neurolabusc/dcm_qa_canon available]. For this reason, one should concern using a tool like GradFlipTest to determine the gradient direction. A sample for this type of data might be:
 +
 
 +
* (0018,9087) FD 1500                            #  8, 1 DiffusionBValue
 +
* (0020,4000) LT [b=1500(0.445,0.000,0.895)]    #  26, 1 ImageComments
 +
 
 +
When Canon scanners save data as enhanced DICOM, public tags (0018,9087; 0018,9089) are used. [https://github.com/neurolabusc/dcm_qa_canon Exemplars] suggest that gradient direction is specified correctly regardless of phase encoding polarity.
 +
* (0018,9087) FD 1500                                    #  8, 1 DiffusionBValue
 +
* (0018,9089) FD 0.29387456178665161\-0.95365142822265625\-0.064700603485107422 #  24, 3 DiffusionGradientOrientation
 +
 
 +
=== Private vendor: GE ===
  
 
For GE scanners, Signa Excite 12.0 and later, the following tags are reserved for diffusion weighted images:
 
For GE scanners, Signa Excite 12.0 and later, the following tags are reserved for diffusion weighted images:
  
* (0019,10e0) : # DTI diffusion directions (release 10.0 & above)
+
* (0019,10e0) : # DTI diffusion directions (release 10.0 & above)
* (0019,10df) : # DTI diffusion directions (release 9.0 & below)
+
* (0019,10df) : # DTI diffusion directions (release 9.0 & below)
* (0019,10d9) : Concatenated SAT {# DTI Diffusion Dir., release 9.0 & below}
+
* (0019,10d9) : Concatenated SAT {# DTI Diffusion Dir., release 9.0 & below}
* (0021,105A) : diffusion direction
+
* (0021,105A) : diffusion direction
* (0043,1039) : Slop_int_6... slop_int_9: (in the GEMS_PARM_01 block)
+
* (0043,1039) : Slop_int_6... slop_int_9: (in the GEMS_PARM_01 block)
 
** 6: b_value
 
** 6: b_value
 
** 7: private imaging options 2
 
** 7: private imaging options 2
Line 69: Line 86:
 
  (0019,10bd) DS [-0.420008]
 
  (0019,10bd) DS [-0.420008]
  
== Private vendor: Siemens ==
+
these directions are in the image (rather than scanner bore) frame of reference. The interpretation depends on the Phase Encoding direction (0018,1312). If 0018,1312 is "COL" than 0019,10bb refers to the image columns (i), 0019,10bc refers to the image rows (j) and 0019,10bd refers to the slices (k). If 0018,1312 is "ROW" than 0019,10bb refers to the image rows (j), 0019,10bc refers to the image columns (i) and 0019,10bd refers to the slices (k). There are two caveats: first this assumes that your slices are stacked in spatially ascending order (head to foot for axial acquisitions) regardless of the order that they were saved to disk (which appears to vary depending on how the user plans the scan). Second, you need to adjust the polarity of these directions to match the expectations of the software used for fitting.
 +
 
 +
Be aware that the b_value stored in tag 0043,1039 may be masked. For example, consider [https://github.com/nikadon/cc-dcm2bids-wrapper/tree/master/dicom-qa-examples/ge-mr750-dwi-b-vals#table series 16] from this archive. This series has images with b_values of both 750 and 1500, but the DICOM tag stores b_values of 1000001500 and 1000000750, as shown in the DICOM dump from image 24 (below). Therefore, if you use 0043,1039 to determine b_value, you should use the modulus of a large number like 100,000.
 +
 
 +
(0043,1039) IS [1000001500\8\0\0]
 +
 
 +
=== Private vendor: Siemens ===
 +
 
 +
Siemens software is reported by Series, Generation, Major Version and Minor Version. Therefore, 'VB17' data was created on a V-series, B-generation, version 1.7. Historically, all Siemens systems were V-series (Trio, Skyra, Prisma, etc), so people might just say data was from 'B17'.
 +
 
 +
For Siemens V-series systems from the B-generation onward (around 2005), the most reliable way to read diffusion gradients is from the [https://nipy.org/nibabel/dicom/siemens_csa.html CSA header]. Specially, for the 'DiffusionGradientDirection' and 'B_value' tags.
 +
 
 +
For the X-series (e.g. Vida and Sola, XA10 and XA11) systems will use the recommended public tags (described above) when exporting as enhanced DICOM. Therefore, the relevant DICOM data for Siemens X-series might look like this:
 +
 
 +
(0019,100c) IS [10]                                              # 2,1 B_value
 +
(0019,100d) CS [BMATRIX ]                                        # 8,1 DiffusionDirectionality
 +
(0019,100e) FD -0.57735\0.57735\0.57735                          # 24,3 DiffusionGradientDirection
 +
(0019,1027) FD 3\-3\-3\3\3\3                                      # 48,6 B_matrix
 +
 
 +
=== Private vendor: Siemens (Historical) ===
 +
 +
The data below is useful for older Siemens equipment (software ~2005 or earlier).
  
 
A Siemens DICOM Conformance Statement is available at
 
A Siemens DICOM Conformance Statement is available at
Line 99: Line 137:
 
Credits: Jan Klein <klein AT mevis DOT de>
 
Credits: Jan Klein <klein AT mevis DOT de>
  
Another solution is simply to download GDCM 2.x application (gdcmdump) and type:
+
==== Update ====
 
 
$ gdcmdump --csa input.dcm
 
 
 
Output should look like:
 
 
 
<pre>
 
(0029,0010)siemens csa header
 
Image shadow data (0029,xx10)
 
 
 
0 - 'EchoLinePosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '192    '
 
1 - 'EchoColumnPosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '128    '
 
2 - 'EchoPartitionPosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '16      '
 
3 - 'UsedChannelMask' VM 1, VR UL, SyngoDT 9, NoOfItems 6, Data '255    '
 
4 - 'Actual3DImaPartNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
5 - 'ICE_Dims' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'X_1_1_1_1_1_1_1_1_1_1_1_136'
 
6 - 'B_value' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
7 - 'Filter1' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
8 - 'Filter2' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
9 - 'ProtocolSliceNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0      '
 
10 - 'RealDwellTime' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '7500    '
 
11 - 'PixelFile' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data
 
12 - 'PixelFileName' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data
 
13 - 'SliceMeasurementDuration' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '73375.00000000'
 
14 - 'SequenceMask' VM 1, VR UL, SyngoDT 9, NoOfItems 6, Data '0      '
 
15 - 'AcquisitionMatrixText' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data '256*256'
 
16 - 'MeasuredFourierLines' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0      '
 
17 - 'FlowEncodingDirection' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
18 - 'FlowVenc' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data
 
19 - 'PhaseEncodingDirectionPositive' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '1      '
 
20 - 'NumberOfImagesInMosaic' VM 1, VR US, SyngoDT 10, NoOfItems 0, Data
 
21 - 'DiffusionGradientDirection' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data
 
22 - 'ImageGroup' VM 1, VR US, SyngoDT 10, NoOfItems 0, Data
 
23 - 'SliceNormalVector' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data
 
24 - 'DiffusionDirectionality' VM 1, VR CS, SyngoDT 16, NoOfItems 0, Data
 
25 - 'TimeAfterStart' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000'
 
26 - 'FlipAngle' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
27 - 'SequenceName' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data
 
28 - 'RepetitionTime' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
29 - 'EchoTime' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
30 - 'NumberOfAverages' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
31 - 'VoxelThickness' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
32 - 'VoxelPhaseFOV' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
33 - 'VoxelReadoutFOV' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
34 - 'VoxelPositionSag' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
35 - 'VoxelPositionCor' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
36 - 'VoxelPositionTra' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
37 - 'VoxelNormalSag' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
38 - 'VoxelNormalCor' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
39 - 'VoxelNormalTra' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
40 - 'VoxelInPlaneRot' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
41 - 'ImagePositionPatient' VM 3, VR DS, SyngoDT 3, NoOfItems 0, Data
 
42 - 'ImageOrientationPatient' VM 6, VR DS, SyngoDT 3, NoOfItems 0, Data
 
43 - 'PixelSpacing' VM 2, VR DS, SyngoDT 3, NoOfItems 0, Data
 
44 - 'SliceLocation' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
45 - 'SliceThickness' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
46 - 'SpectrumTextRegionLabel' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data
 
47 - 'Comp_Algorithm' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
48 - 'Comp_Blended' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
49 - 'Comp_ManualAdjusted' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
50 - 'Comp_AutoParam' VM 1, VR LT, SyngoDT 20, NoOfItems 0, Data
 
51 - 'Comp_AdjustedParam' VM 1, VR LT, SyngoDT 20, NoOfItems 0, Data
 
52 - 'Comp_JobID' VM 1, VR LT, SyngoDT 20, NoOfItems 0, Data
 
53 - 'FMRIStimulInfo' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data
 
54 - 'FlowEncodingDirectionString' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data
 
55 - 'RepetitionTimeEffective' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data
 
56 - 'CsiImagePositionPatient' VM 3, VR DS, SyngoDT 3, NoOfItems 0, Data
 
57 - 'CsiImageOrientationPatient' VM 6, VR DS, SyngoDT 3, NoOfItems 0, Data
 
...
 
</pre>
 
 
 
Ref:
 
* http://gdcm.sourceforge.net/wiki/index.php/GDCM_Release_2.0
 
 
 
=== Update ===
 
  
 
<br /> As far as the latest MR scanner software (2006) version is concerned, a solution for the access of the following Diffusion attributes was provided:
 
<br /> As far as the latest MR scanner software (2006) version is concerned, a solution for the access of the following Diffusion attributes was provided:
Line 188: Line 152:
 
That does not solve your problem with the older datasets and unfortunately there is no easy way to access diffusion information there as it is really only stored in the Siemens shadow part.
 
That does not solve your problem with the older datasets and unfortunately there is no easy way to access diffusion information there as it is really only stored in the Siemens shadow part.
  
Credits: Stefan Huwer
+
==== Update September 2010 ====
  
=== User Note ===
+
Via email, Matthew Brett reported the following information and links which are posted here with his permission.
  
Don't use the gradient-directions from the DICOM header from VB13 systems, it commonly contains errors; read the b-matrix instead and use that to compute the gradient-directions. In fact, this is also what Siemens does but they compute the gradient-vectors in an error-prone way. They do (in Matlab syntax):
+
<pre>
 +
...if you do this:
  
% BMtx = [bxx bxy bxz byy byz bzz]
+
P= spm_get(Inf,'*','Selct some files')
GradVec = BMtx([1:3])/sqrt(BVal*BMtx([1]));
+
hdr=spm_dicom_headers(P)
 +
hdr{1}.CSAImageHeaderInfo(22).item(1).val
 +
hdr{1}.CSAImageHeaderInfo(22).item(2).val
 +
hdr{1}.CSAImageHeaderInfo(22).item(3).val
  
This gives errors for bxx values of zero and close to one (bxx is an integer); NB this *does* happen! So instead read the b-matrix and do:
+
from http://www.na-mic.org/Wiki/index.php/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI#Private_vendor:_Siemens
  
[Y I] = max(BMtx([1 4 6]));      % Avoid using a zero cross-term (credits to Phil Cook)
+
- then the resulting q-like vectors can be rather far off, for reasons
switch I
+
that I now can't remember, but I believe Guy investigated.
    case 1
 
        BSign = sign(BMtx(1:3));      % Assume bx is positive
 
    case 2
 
        BSign = sign(BMtx([2 4 5]));  % Assume by is positive
 
    case 3
 
        BSign = sign(BMtx([3 5 6]));  % Assume bz is positive
 
end
 
GradVec = BSign .* sqrt(BMtx([1 4 6])/BVal);
 
  
In this way, the vectors may point exactly in the opposite direction (sign flip), but this is usually of no importance.
+
In SPM, hdr{1}.CSAImageHeaderInfo is the SPM reading of the Siemens
 +
private header.  We read this in:
  
Furthermore, the stored values may differ from the official values due to the fact that
+
http://github.com/matthew-brett/nibabel/blob/master/nibabel/nicom/csareader.py
# the directions are calculated from the b-matrix and not directly written to the header. Rounding errors, as well as sign flips may occur in this case.
 
# the b-matrix takes also the diffusion effect of imaging and spoiling gradients into account. This leads to deviations from the originally specified orientations.
 
# the vectors are expressed in the patient coordinate system (Sag/Cor/Tra), not in Slice/Read/Phase, following the DICOM convention.
 
  
Credits: Marcel Zwiers
+
in the 'read' function.
  
=== Reference ===
+
What SPM calls hdr{1}.CSAImageHeaderInfo(22) has the label
 +
'DiffusionGradientDirection', and is what looks like the q-vector.
 +
However, it can be rather far off, and, in particular, is often rather
 +
far from a unit vector.
 +
 
 +
Guy recovered from this by using the correctly specified 'B_matrix'
 +
field of the same private header.  I think this is:
 +
 
 +
hdr{1}.CSAImageHeaderInfo(78)
 +
 
 +
in SPM-speak, and is arranged as (0-based matrix indices into B matrix)
 +
 
 +
(0,0), (0, 1), (0,2), (1, 1), (1, 2), (2, 2)
 +
 
 +
where the B matrix is symmetric.  See 'get_b_matrix' in
 +
 
 +
http://github.com/matthew-brett/nibabel/blob/master/nibabel/nicom/csareader.py
 +
 
 +
We (this is obviously optional) rotate to voxel orientation (rather
 +
than DICOM orientation).
 +
 
 +
We (this is also optional) (credit Ian Nimmo-Smith) resolve to the
 +
nearest positive semi-definite matrix using Niethammer's and C-Fs
 +
tensor algorithm - see 'nearest_pos_semi_def' in:
 +
 
 +
http://github.com/matthew-brett/nibabel/blob/master/nibabel/nicom/dwiparams.py
 +
 
 +
Finally, we extract the best estimate of q from the resulting B
 +
matrix, using eigenvalue decomposition - see 'B2q' in the dwiparams -
 +
this is the main part of Guy's algorithm, and Ian N-S code.
 +
 
 +
But I think you're asking - can I put that on the NAMIC page?
 +
 
 +
I'm hoping that Guy or Ian or Eleftherios will jump in and tell me
 +
where I am wrong or explain further...
 +
 
 +
</pre>
 +
 
 +
This bug may or may not be related (now fixed): http://www.na-mic.org/Bug/view.php?id=978
 +
 
 +
==== Reference ====
  
 
* http://www.mmrrcc.upenn.edu/CAMRIS/cfn/
 
* http://www.mmrrcc.upenn.edu/CAMRIS/cfn/
Line 227: Line 225:
 
* http://www.mmrrcc.upenn.edu/CAMRIS/cfn/dicomhdr.html
 
* http://www.mmrrcc.upenn.edu/CAMRIS/cfn/dicomhdr.html
  
== Private vendor: Philips ==
+
=== Private vendor: Philips ===
  
Philips uses the following tags for diffusion weighted images
+
Be aware that Philips will store derived diffusion images (e.g. isotropic images) in the same series as the raw data. Derived images will disrupt processing. Further, one will be able to generate better derived images after processing (e.g. de-Gibbs, de-noise, eddy correction). Therefore, one typically wants to identify and discard these derived images.
 +
 
 +
Many Philips images use the following private tags for diffusion weighted images
 +
 
 +
* (2001,1003) FL : Diffusion B-Factor
 +
* (2001,1004) CS : Diffusion Direction
 +
*  (2005,10B0) FL :  Diffusion Direction RL
 +
*  (2005,10B1) FL :  Diffusion Direction AP
 +
*  (2005,10B2) FL : Diffusion Direction FH
 +
 
 +
Note that the [http://incenter.medical.philips.com/doclib/enc/fetch/2000/4504/577242/577256/588723/5144873/5144488/5144982/DICOM_Conformance_Statement_Ingenia_R4.1.pdf%3fnodeid%3d8124182%26vernum%3d-2 possible values for 2001,1004] are P (PreparationDirection), M (MeasurementDirection), S (Selection Direction),O(Oblique Direction), I (Isotropic). Since both the raw B=0 images and derived isotropic use the value "I" this tag is insufficient to discriminate raw images from derived images. For Philips scans, B=0 set all tags 2001,1003; 2005,10B0; 2005,10B1 and 2005,10B2  to zero, while derived images use the corresponding b-value (e.g. 2001,1003 = 1000) but set also set 2001,10B0; 2005,10B1; 2005,10B2 to zero. Raw B-weighted images have a positive value in 2001,1003 and at least one of the gradient directions 2001,10B0; 2005,10B1; 2005,10B2 will be non-zero.
 +
 
 +
Some Philips images use the recommended public tags described above (for example classic DICOM images from 2012 where 0002,0013 lists Philips MR 26.2 as well as 2018-vintage Philips MR 53.0). Philips enhanced DICOMs also use these public tags.
  
* (2001,1003) : B_value;
 
* (2001,1004) : Diffusion direction.
 
  
 
Complete DICOM conformance statements for
 
Complete DICOM conformance statements for
Line 244: Line 252:
 
are available here http://www.medical.philips.com/main/company/connectivity/mri/
 
are available here http://www.medical.philips.com/main/company/connectivity/mri/
  
=== DTI Table Gradient ===
+
=== Private vendor: Toshiba ===
 +
 
 +
The Toshiba Titan 3T (console software V2.30*R005) uses a standard DICOM attribute for b-value:
 +
* (0018,9087) : Diffusion b-value (for instances with a non-zero b-value).
 +
NOTE: this attribute is missing for those instances with a b-value of zero.
 +
 
 +
Gradients can be found in a private tag as follows:
 +
* (0029, 1001) : Private Sequence
 +
* >(0029, 1090): Private Byte Data
 +
When the byte data is reversed and the nybble-pairs are swapped, this becomes a DICOM sequence object (with 6 items). The 5th item contains a number of standard DICOM attributes including:
 +
* >>(0018,9087) : Diffusion b-value (which matches the above)
 +
* >>(0018,9089) : Diffusion Gradient Orientation. This is the diffusion direction and will be [0, 0, 0] for the b-value of zero instances.
 +
 
 +
Sample code for the byte data adjustment:
 +
<pre>
 +
private static byte[] adjustToshibaBytes( byte[] input ) {
 +
    int len = input.length;
 +
    byte[] output = new byte[ len ];
 +
    for( int i = 0; i < len; i++ )
 +
    {
 +
      output[ i ] = (byte)((input[ len - i - 1 ] & 0x0F) + (input[ len - i - 1 ] & 0xF0));
 +
    }
 +
    return output;
 +
}
 +
</pre>
 +
 
 +
 
 +
=== Private vendor: UIH ===
 +
 
 +
United Imaging Healthcare ("UIH") MRI scanners generate a number of [https://github.com/rordenlab/dcm2niix/tree/master/UIH private tags]. For Diffusion imaging, the crucial ones are the b-value and gradient direction.
  
OVERVIEW:
 
 
This applet computes the gradient table
 
for DTI data acquired on Philips MRI
 
scanners with low, medium, and high
 
directional resolution.
 
 
The imaging parameters and DTI options
 
listed can affect the gradient table.
 
e.g.directions from a gradient overplus
 
= yes table need to be adjusted for the
 
slice angulation (i.e. oblique slices)
 
specific to each DTI study
 
 
The output is appropriate for DTIstudio.
 
I hope this applet is useful, but please
 
use it at your own risk. Matlab code with
 
more functionality is available on my
 
webpage
 
  
* http://godzilla.kennedykrieger.org/%7Ejfarrell/OTHERphilips/GUI.html
+
(0065,1009) FD 929.75018313375267                      #  8, 1 B_value
 +
(0065,1037) FD 0.219573072677\0.9618\0.1632            #  24, 3 DiffusionDirectionality
  
 
== DICOM for estimated diffusion tensors ==
 
== DICOM for estimated diffusion tensors ==
Line 286: Line 305:
 
  structure.
 
  structure.
  
== Discussion on DICOM newsgroup ==
+
== Validation Datasets ==
  
http://groups.google.com/group/comp.protocols.dicom/browse_frm/thread/3d292d9c506b1cbf For cross reference:
+
Sample datasets are available for most manufacturers that provide concrete examples for their storage of diffusion information:
  
+
* [https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Diffusion_Tensor_Imaging dcm2niix NITRC page includes GE, Philips and Siemens DICOMs]
Hi Mathieu
+
* [https://github.com/neurolabusc/dcm_qa_canon_enh Canon Classic DICOMs]
+
* [https://github.com/neurolabusc/dcm_qa_canon_enh Canon Enhanced DICOMs]
Thanks for the very interesting links.
+
* [https://github.com/neurolabusc/dcm_qa_philips Philips DICOMs]
+
* [https://osf.io/brvak/ Siemens Mosaic DICOMs]
The proposed standard way to address this problem is with
+
* [https://github.com/neurolabusc/dcm_qa_uih UIH DICOMs]
the Enhanced MR IOD, which explicitly addresses the
+
 
attributes for encoding diffusion directionality and B-Value.
+
== Related Links ==
+
 
There will likely be no extensions of the existing MR IOD to
+
[http://www.na-mic.org/Wiki/index.php/NAMIC_Tools_Suite_for_DTI_analysis 2010 Project week: NAMIC tools for DTI analysis ]
address this concern, since by policy, we obviously want
+
 
folks to use the new IOD.
+
[http://www.na-mic.org/Wiki/index.php/Projects:DicomToNrrdForDTI DicomToNrrdForDTI Notes]
+
 
It would not surprise me if in the interim, vendors started
+
[http://www.na-mic.org/Wiki/index.php/DTI:Acquisition Randy's DTI Acquisition notes]
to send some of the new Sup 49 attributes in old IOD
+
 
instances, but there will almost certainly be no official move
+
== Python psuedocode ==
to standardize this, and we would certainly not consider
+
 
adding a non-Sup 49 based mechanism.
+
```python
+
 
If the Sup 49 mechanisms are not sufficient (e.g. for
+
def get_bvalue(dicom_header_info) -> str:
tensors), then we need to discuss what the gaps are
+
    """
and how to fill them.
+
    Extract bvalue from pydicom information
+
    `dicom_header_info = dicom.read_file(dicom_file_name, stop_before_pixels=True)`
We would not, by the way, ever "encapsulate" the NRRD
+
    :param dicom_header_info: A pydicom object
header, but it would nice if there was a clear mapping between
+
    :return: a string representing the BValue
the DICOM Sup 49 attributes and the relevant NRRD
+
    """
attributes, though these are probably obvious.
+
    # bvalue tags from private fields provided by https://www.nmr.mgh.harvard.edu/~greve/dicom-unpack
+
    private_tags_map = {
David
+
        "Standard": (0x0018, 0x9087),
+
        "UHI": (0x0065, 0x1009),
Mathieu Malaterre wrote:
+
        "GE": (0x0043, 0x1039),
> Hello again,
+
        "Siemens": (0x0019, 0x100C),
>
+
        "Siemens_historical": (0x0029, 0x1010), # NOT SUPPORTED
>    I am currently involved in a group which is working extensively with
+
        "Siemens_old": (0x0019, 0x000C),
> DWI data (diffusion-weighted image). Their acquisition data is coming
+
        "Philips": (0x2001, 0x1003)
  > in the form of DICOM files. Unfortunately they are currently facing two
+
        # "Toshiba" : # Uses (0x0018, 0x9087) standard
> problems:
+
    }
> 1. Each vendors stores the gradient directions differently (if at all!)
+
    for k, v in private_tags_map.items():
> 2. Even if you have the directions, you don't have the measurement
+
        if v in dicom_header_info:
> frame(*). As far as I understand the DICOM specification, there is
+
            # This decoding of bvalues follows the NAMIC conventions defined at
> currently no way to store this type of information.
+
            # https://www.na-mic.org/wiki/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI
>
+
            dicom_element = dicom_header_info[v]
>    For issue #1 I am currently gathering information about the major
+
            if k == "GE":
> vendors so that I can add extraction code into gdcm. This would provide
+
                large_number_modulo_for_GE = 100000
> a function to extract the gradient directions and make invisible to
+
                value = dicom_element.value[0] % large_number_modulo_for_GE
> user the different way vendors use to store this information. For more
+
            elif dicom_element.VR == "OB":
> information see the Wiki at:
+
                value = dicom_element.value.decode("utf-8")
> http://www.na-mic.org/Wiki/index.php/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI
+
            else:
>
+
                value = dicom_element.value
>    For issue #2, -again correct me if I am wrong- but I could not find
+
            print(f"Found BValue at {v} for {k}, {value} of type {dicom_element.VR}")
> anything that could represent this measurement frame. Therefore the
+
            return str(value)
> solution we are using is to use an intermediate file format called
+
    return "-1234"
> NRRD, see for instance:
+
```
> http://wiki.na-mic.org/Wiki/index.php/NAMIC_Wiki:DTI:Nrrd_format
 
>    Ideally this information should be accessible from a particular
 
> DICOM tag. Can we request an extension of the DICOM standard to allow
 
> us to store this information directly in the DICOM file, which would
 
> greatly simplify the process (avoiding the intermediate NRRD file
 
> format step).
 
>
 
> Regards,
 
> Mathieu
 
> (*)
 
> "measurement frame": relationship between the coordinate frame in which
 
> the gradient coefficients are expressed, and the physical coordinate
 
> frame in which image orientation is defined
 

Latest revision as of 03:23, 20 December 2022

Home < NAMIC Wiki:DTI:DICOM for DWI and DTI

This page should serve as a place where information about DICOM and DWI/DTI data can be maintained. With time, this information could be used as part of automated solutions for learning all the necessary DWI-related information from a DICOM series. A collection of tools for DICOM is here.

As long DICOM support for DWI information is vendor-specific and/or non-conformant with the info here, the Nrrd format provides a means of recording the DWI-specific information once it is known.

DICOM for DWI

The recommended tags to use in DICOM are as follows:

0018 9075 CS 1 Diffusion Directionality
0018 9076 SQ 1 Diffusion Gradient Direction Sequence
0018 9087 FD 1 Diffusion b-value
0018 9089 FD 3 Diffusion Gradient Orientation
0018 9117 SQ 1 MR Diffusion Sequence
0018 9147 CS 1 Diffusion Anisotropy Type
0018 9602 FD 1 DiffusionBValueXX
0018 9603 FD 1 DiffusionBValueXY
0018 9604 FD 1 DiffusionBValueXZ
0018 9605 FD 1 DiffusionBValueYY
0018 9606 FD 1 DiffusionBValueYZ
0018 9607 FD 1 DiffusionBValueZZ

These are defined in Supplement 49. In particular see section C.8.12.5.9 "MR Diffusion Macro" on pages 94 and 95.

The tags are also referenced in http://medical.nema.org/dicom/2004/04_06PU.PDF (see pages 28-29) as well as in some Working Group Minutes (see pages 155-156).

Two points of interest relative to the NRRD format:

  • The definition of "Diffusion Gradient Orientation" implies that the measurement frame is exactly the identity transform.
  • While one can encode the B-matrix, it is underspecified to store the polarity of the b-vector. This makes it insufficient for tools like FSL's eddy which leverage the fact that polar opposite b-vectors should have identical true signal yet differ due to eddy currents (and therefore artifacts can be modeled and removed).

Private vendor: Canon

For Canon (né Toshiba) scanners saving classic 2D DICOM images, the gradient direction is stored in the text-based image comments fields. For older systems, the DiffusionBValue (0018,9087) tag may be omitted for images where the b-value is equal to zero. Be aware that the gradient direction stored in the comment field may not take into account the phase encoding polarity, so it may not be accurate. Example data illustrating this problem is available. For this reason, one should concern using a tool like GradFlipTest to determine the gradient direction. A sample for this type of data might be:

  • (0018,9087) FD 1500 # 8, 1 DiffusionBValue
  • (0020,4000) LT [b=1500(0.445,0.000,0.895)] # 26, 1 ImageComments

When Canon scanners save data as enhanced DICOM, public tags (0018,9087; 0018,9089) are used. Exemplars suggest that gradient direction is specified correctly regardless of phase encoding polarity.

  • (0018,9087) FD 1500 # 8, 1 DiffusionBValue
  • (0018,9089) FD 0.29387456178665161\-0.95365142822265625\-0.064700603485107422 # 24, 3 DiffusionGradientOrientation

Private vendor: GE

For GE scanners, Signa Excite 12.0 and later, the following tags are reserved for diffusion weighted images:

  • (0019,10e0) : # DTI diffusion directions (release 10.0 & above)
  • (0019,10df) : # DTI diffusion directions (release 9.0 & below)
  • (0019,10d9) : Concatenated SAT {# DTI Diffusion Dir., release 9.0 & below}
  • (0021,105A) : diffusion direction
  • (0043,1039) : Slop_int_6... slop_int_9: (in the GEMS_PARM_01 block)
    • 6: b_value
    • 7: private imaging options 2
    • 8: ihtagging
    • 9: ihtagspc

This information can be found in http://www.gehealthcare.com/usen/interoperability/dicom/docs/5162373r1.pdf

Unfortunately the Dartmouth DWI data (from a GE Signa scanner) does not conform to this (nor do they use the nominally standard 0x0018 tags), as can be seen by running:

dcdump S4.100 | & grep \(0x0019,0x10

which includes:

(0x0019,0x10d9) DS Concatenated SAT      VR=<DS>   VL=<0x0008>  <0.000000>
(0x0019,0x10df) DS User Data     VR=<DS>   VL=<0x0008>  <0.000000>
(0x0019,0x10e0) DS User Data     VR=<DS>   VL=<0x0008>  <0.000000>

so all of the tags which are supposed to store # gradient directions store the value 0! In addition, there is:

(0x0021,0x105a) SL Integer Slop          VR=<SL>   VL=<0x0004>  [0x00000000]

so the supposed representation of diffusion-direction is also empty. The Dartmouth data has the following tags describing the scanner and software version:

(0008,1090) LO [GENESIS_SIGNA]
(0018,1020) LO [09]

In GE DWI images (software version 12.0)

(0008,1090) LO [SIGNA EXCITE]
(0018,1020) LO [12\LX\MR Software release:12.0_M4_0520.a]

diffusion directions are stored under the following tags:

(0019,10bb) DS [0.430617]
(0019,10bc) DS [-0.804161]
(0019,10bd) DS [-0.420008]

these directions are in the image (rather than scanner bore) frame of reference. The interpretation depends on the Phase Encoding direction (0018,1312). If 0018,1312 is "COL" than 0019,10bb refers to the image columns (i), 0019,10bc refers to the image rows (j) and 0019,10bd refers to the slices (k). If 0018,1312 is "ROW" than 0019,10bb refers to the image rows (j), 0019,10bc refers to the image columns (i) and 0019,10bd refers to the slices (k). There are two caveats: first this assumes that your slices are stacked in spatially ascending order (head to foot for axial acquisitions) regardless of the order that they were saved to disk (which appears to vary depending on how the user plans the scan). Second, you need to adjust the polarity of these directions to match the expectations of the software used for fitting.

Be aware that the b_value stored in tag 0043,1039 may be masked. For example, consider series 16 from this archive. This series has images with b_values of both 750 and 1500, but the DICOM tag stores b_values of 1000001500 and 1000000750, as shown in the DICOM dump from image 24 (below). Therefore, if you use 0043,1039 to determine b_value, you should use the modulus of a large number like 100,000.

(0043,1039) IS [1000001500\8\0\0]

Private vendor: Siemens

Siemens software is reported by Series, Generation, Major Version and Minor Version. Therefore, 'VB17' data was created on a V-series, B-generation, version 1.7. Historically, all Siemens systems were V-series (Trio, Skyra, Prisma, etc), so people might just say data was from 'B17'.

For Siemens V-series systems from the B-generation onward (around 2005), the most reliable way to read diffusion gradients is from the CSA header. Specially, for the 'DiffusionGradientDirection' and 'B_value' tags.

For the X-series (e.g. Vida and Sola, XA10 and XA11) systems will use the recommended public tags (described above) when exporting as enhanced DICOM. Therefore, the relevant DICOM data for Siemens X-series might look like this:

(0019,100c) IS [10]                                               # 2,1 B_value
(0019,100d) CS [BMATRIX ]                                         # 8,1 DiffusionDirectionality
(0019,100e) FD -0.57735\0.57735\0.57735                           # 24,3 DiffusionGradientDirection
(0019,1027) FD 3\-3\-3\3\3\3                                      # 48,6 B_matrix

Private vendor: Siemens (Historical)

The data below is useful for older Siemens equipment (software ~2005 or earlier).

A Siemens DICOM Conformance Statement is available at

http://www.medical.siemens.com/siemens/en_INT/rg_marcom_FBAs/files/brochures/DICOM/mr/dcs_trio.pdf

No diffusion related tags specified.

David Tuch has stated (in email from December 21, 2005):

The diffusion gradient information and coordinate frame are not provided
in the DICOM hdr for the MGH diffusion sequences.

Tag 0029,1010 may include all necessary information

If you have installed spm (and Matlab), the following spm-File extracts the gradient info:


P= spm_get(Inf,'*','Selct some files')
hdr=spm_dicom_headers(P)
hdr{1}.CSAImageHeaderInfo(22).item(1).val
hdr{1}.CSAImageHeaderInfo(22).item(2).val
hdr{1}.CSAImageHeaderInfo(22).item(3).val

look for "spm_dicom_headers.m" (google or on your hard disk), this spm File shows you how to decode the tag data.

It is easy to write a C or C++ program that does the same, if you have the spm_dicom_headers.m

Credits: Jan Klein <klein AT mevis DOT de>

Update


As far as the latest MR scanner software (2006) version is concerned, a solution for the access of the following Diffusion attributes was provided:

0019;000A;SIEMENS MR HEADER  ;NumberOfImagesInMosaic          ;1;US;1
0019;000B;SIEMENS MR HEADER  ;SliceMeasurementDuration        ;1;DS;1
0019;000C;SIEMENS MR HEADER  ;B_value                         ;1;IS;1
0019;000D;SIEMENS MR HEADER  ;DiffusionDirectionality         ;1;CS;1
0019;000E;SIEMENS MR HEADER  ;DiffusionGradientDirection      ;1;FD;3
0019;000F;SIEMENS MR HEADER  ;GradientMode                    ;1;SH;1
0019;0027;SIEMENS MR HEADER  ;B_matrix                        ;1;FD;6
0019;0028;SIEMENS MR HEADER  ;BandwidthPerPixelPhaseEncode    ;1;FD;1

That does not solve your problem with the older datasets and unfortunately there is no easy way to access diffusion information there as it is really only stored in the Siemens shadow part.

Update September 2010

Via email, Matthew Brett reported the following information and links which are posted here with his permission.

...if you do this:

P= spm_get(Inf,'*','Selct some files')
hdr=spm_dicom_headers(P)
hdr{1}.CSAImageHeaderInfo(22).item(1).val
hdr{1}.CSAImageHeaderInfo(22).item(2).val
hdr{1}.CSAImageHeaderInfo(22).item(3).val

from http://www.na-mic.org/Wiki/index.php/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI#Private_vendor:_Siemens

- then the resulting q-like vectors can be rather far off, for reasons
that I now can't remember, but I believe Guy investigated.

In SPM, hdr{1}.CSAImageHeaderInfo is the SPM reading of the Siemens
private header.   We read this in:

http://github.com/matthew-brett/nibabel/blob/master/nibabel/nicom/csareader.py

in the 'read' function.

What SPM calls hdr{1}.CSAImageHeaderInfo(22) has the label
'DiffusionGradientDirection', and is what looks like the q-vector.
However, it can be rather far off, and, in particular, is often rather
far from a unit vector.

Guy recovered from this by using the correctly specified 'B_matrix'
field of the same private header.  I think this is:

hdr{1}.CSAImageHeaderInfo(78)

in SPM-speak, and is arranged as (0-based matrix indices into B matrix)

(0,0), (0, 1), (0,2), (1, 1), (1, 2), (2, 2)

where the B matrix is symmetric.   See 'get_b_matrix' in

http://github.com/matthew-brett/nibabel/blob/master/nibabel/nicom/csareader.py

We (this is obviously optional) rotate to voxel orientation (rather
than DICOM orientation).

We (this is also optional) (credit Ian Nimmo-Smith) resolve to the
nearest positive semi-definite matrix using Niethammer's and C-Fs
tensor algorithm - see 'nearest_pos_semi_def' in:

http://github.com/matthew-brett/nibabel/blob/master/nibabel/nicom/dwiparams.py

Finally, we extract the best estimate of q from the resulting B
matrix, using eigenvalue decomposition - see 'B2q' in the dwiparams -
this is the main part of Guy's algorithm, and Ian N-S code.

But I think you're asking - can I put that on the NAMIC page?

I'm hoping that Guy or Ian or Eleftherios will jump in and tell me
where I am wrong or explain further...

This bug may or may not be related (now fixed): http://www.na-mic.org/Bug/view.php?id=978

Reference

in particular:

Private vendor: Philips

Be aware that Philips will store derived diffusion images (e.g. isotropic images) in the same series as the raw data. Derived images will disrupt processing. Further, one will be able to generate better derived images after processing (e.g. de-Gibbs, de-noise, eddy correction). Therefore, one typically wants to identify and discard these derived images.

Many Philips images use the following private tags for diffusion weighted images

  • (2001,1003) FL : Diffusion B-Factor
  • (2001,1004) CS : Diffusion Direction
  • (2005,10B0) FL : Diffusion Direction RL
  • (2005,10B1) FL : Diffusion Direction AP
  • (2005,10B2) FL : Diffusion Direction FH

Note that the possible values for 2001,1004 are P (PreparationDirection), M (MeasurementDirection), S (Selection Direction),O(Oblique Direction), I (Isotropic). Since both the raw B=0 images and derived isotropic use the value "I" this tag is insufficient to discriminate raw images from derived images. For Philips scans, B=0 set all tags 2001,1003; 2005,10B0; 2005,10B1 and 2005,10B2 to zero, while derived images use the corresponding b-value (e.g. 2001,1003 = 1000) but set also set 2001,10B0; 2005,10B1; 2005,10B2 to zero. Raw B-weighted images have a positive value in 2001,1003 and at least one of the gradient directions 2001,10B0; 2005,10B1; 2005,10B2 will be non-zero.

Some Philips images use the recommended public tags described above (for example classic DICOM images from 2012 where 0002,0013 lists Philips MR 26.2 as well as 2018-vintage Philips MR 53.0). Philips enhanced DICOMs also use these public tags.


Complete DICOM conformance statements for

  • Intera
  • Achieva
  • Panorama
  • Gyroscan
  • Infinion / Eclipse

are available here http://www.medical.philips.com/main/company/connectivity/mri/

Private vendor: Toshiba

The Toshiba Titan 3T (console software V2.30*R005) uses a standard DICOM attribute for b-value:

  • (0018,9087) : Diffusion b-value (for instances with a non-zero b-value).

NOTE: this attribute is missing for those instances with a b-value of zero.

Gradients can be found in a private tag as follows:

  • (0029, 1001) : Private Sequence
  • >(0029, 1090): Private Byte Data

When the byte data is reversed and the nybble-pairs are swapped, this becomes a DICOM sequence object (with 6 items). The 5th item contains a number of standard DICOM attributes including:

  • >>(0018,9087) : Diffusion b-value (which matches the above)
  • >>(0018,9089) : Diffusion Gradient Orientation. This is the diffusion direction and will be [0, 0, 0] for the b-value of zero instances.

Sample code for the byte data adjustment:

private static byte[] adjustToshibaBytes( byte[] input ) {
    int len = input.length;
    byte[] output = new byte[ len ];
    for( int i = 0; i < len; i++ )
    {
       output[ i ] = (byte)((input[ len - i - 1 ] & 0x0F) + (input[ len - i - 1 ] & 0xF0));
    }
    return output;
}


Private vendor: UIH

United Imaging Healthcare ("UIH") MRI scanners generate a number of private tags. For Diffusion imaging, the crucial ones are the b-value and gradient direction.


(0065,1009) FD 929.75018313375267                       #   8, 1 B_value
(0065,1037) FD 0.219573072677\0.9618\0.1632             #  24, 3 DiffusionDirectionality

DICOM for estimated diffusion tensors

There is no specification right now in DICOM to support Tensor. Only a supplement:

Supp 63 Parts 3,4,5,6,16,17 Multi-dimensional Interchange Object

The discussion would then be (D. Clunie quote):


Indeed, even if one were to try to standardize in DICOM the encoding
of the entire diffusion tensor, there would no doubt be considerable
debate as to whether to do that as 6 (or 9) planes of an "image", since
there is such a matrix at each spatial location ("pixel"), or as
a special case of the proposed Sup 63 object; the former would keep
image-oriented tools and software happier, the latter would require
implementing a new mechanism and navigating through a more general
structure.

Validation Datasets

Sample datasets are available for most manufacturers that provide concrete examples for their storage of diffusion information:

Related Links

2010 Project week: NAMIC tools for DTI analysis

DicomToNrrdForDTI Notes

Randy's DTI Acquisition notes

Python psuedocode

```python

def get_bvalue(dicom_header_info) -> str:

   """
   Extract bvalue from pydicom information 
   `dicom_header_info = dicom.read_file(dicom_file_name, stop_before_pixels=True)`
   :param dicom_header_info: A pydicom object
   :return: a string representing the BValue
   """
   # bvalue tags from private fields provided by https://www.nmr.mgh.harvard.edu/~greve/dicom-unpack
   private_tags_map = {
       "Standard": (0x0018, 0x9087),
       "UHI": (0x0065, 0x1009),
       "GE": (0x0043, 0x1039),
       "Siemens": (0x0019, 0x100C),
       "Siemens_historical": (0x0029, 0x1010),  # NOT SUPPORTED
       "Siemens_old": (0x0019, 0x000C),
       "Philips": (0x2001, 0x1003)
       # "Toshiba" : # Uses (0x0018, 0x9087) standard
   }
   for k, v in private_tags_map.items():
       if v in dicom_header_info:
           # This decoding of bvalues follows the NAMIC conventions defined at
           # https://www.na-mic.org/wiki/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI
           dicom_element = dicom_header_info[v]
           if k == "GE":
               large_number_modulo_for_GE = 100000
               value = dicom_element.value[0] % large_number_modulo_for_GE
           elif dicom_element.VR == "OB":
               value = dicom_element.value.decode("utf-8")
           else:
               value = dicom_element.value
           print(f"Found BValue at {v} for {k}, {value} of type {dicom_element.VR}")
           return str(value)
   return "-1234"

```