Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SIEMENS MOSAIC: SliceNormalVector (CSA)

420 views
Skip to first unread message

Mathieu Malaterre

unread,
Jul 13, 2017, 9:58:22 AM7/13/17
to
Hi there,

Does anyone knows what is going on with one of the internal information stored in CSA header for a SIEMENS MOSAIC instance: SliceNormalVector ?

There are references on the web that this 3D vector indicate that the order of the slices may be in opposite order:

* https://github.com/neurodebian/spm12/blob/master/spm_dicom_convert.m

[...]
% Maybe flip the image depending on SliceNormalVector from 0029,1010
%-------------------------------------------------------------------
SliceNormalVector = read_SliceNormalVector(hdr{i});
if det([reshape(hdr{i}.ImageOrientationPatient,[3 2]) SliceNormalVector(:)])<0;
volume = volume(:,:,end:-1:1);
mat = mat*[eye(3) [0 0 -(dim(3)-1)]'; 0 0 0 1];
end;
[...]

However when I load one particular instance, here is what I see:

$ gdcmdump --csa mosaic.dcm | grep SliceNormalVector
23 - 'SliceNormalVector' VM 3, VR FD, SyngoDT 4, NoOfItems 6, Data '0.00000000'\'0.00000000'\'-1.00000000'

Which is indeed in opposite direction as one would have expected from the normal vector to the Direction Cosines:

$ gdcmdump mosaic.dcm | grep Orientation
(0020,0037) DS [1.0\0.0\0.0\0.0\1.0\0.0 ] # 24,6 Image Orientation (Patient)

In this case the normal is obviously: (0,0,1).

So at this point, it would make sense to reorder the slices from the 2D frame in opposite order. But if one inspect more of the SIEMENS CSA ASCCONV attributes, one can see the following:

$ gdcmdump --csa mosaic.dcm | grep sSliceArray.asSlice | grep sPosition
sSliceArray.asSlice[0].sPosition.dSag = -9.322033898
sSliceArray.asSlice[0].sPosition.dCor = -35.59322034
sSliceArray.asSlice[0].sPosition.dTra = -91.54661017
sSliceArray.asSlice[1].sPosition.dSag = -9.322033898
sSliceArray.asSlice[1].sPosition.dCor = -35.59322034
sSliceArray.asSlice[1].sPosition.dTra = -89.04661017
[...snip...]
sSliceArray.asSlice[58].sPosition.dSag = -9.322033898
sSliceArray.asSlice[58].sPosition.dCor = -35.59322034
sSliceArray.asSlice[58].sPosition.dTra = 53.45338983
sSliceArray.asSlice[59].sPosition.dSag = -9.322033898
sSliceArray.asSlice[59].sPosition.dCor = -35.59322034
sSliceArray.asSlice[59].sPosition.dTra = 55.95338983

Clearly it seems as if the slices from the 2D frame are ordered in the correct normal direction: (0,0,1).

One can even check the normal associated with those slices:

$ gdcmdump --csa mosaic.dcm | grep sSliceArray.asSlice | grep sNormal
sSliceArray.asSlice[0].sNormal.dTra = 1
sSliceArray.asSlice[1].sNormal.dTra = 1
[...snip...]
sSliceArray.asSlice[58].sNormal.dTra = 1
sSliceArray.asSlice[59].sNormal.dTra = 1

So again the normal associated with the slices is (0,0,1).

In conclusion: what the heck is SliceNormalVector ? How does one traverse the slices stored in a 2D frame from a SIEMENS MOSAIC dataset ? What are the individual IOP and IPP of those individual slices (goal being of creating a true Enhanced MR Image Storage from an input MOSAIC SIEMENS instance) ?

Thanks much !

Just for completeness the Image Position (Patient) for this instance is:

$ gdcmdump mosaic.dcm | grep Position
(0020,0032) DS [-969.32203388214\-995.59321975708\55.953388214111 ] # 50,3 Image Position (Patient)

René-paul Debroize

unread,
Jul 27, 2017, 4:01:26 PM7/27/17
to
Hi Matthieu,

I don't have any good answers to your questions, but i have a Siemens mosaic where the slices inside a 2D mosaic frame are stored in descending order instead of ascending.

you can check for the csa field ProtocolSliceNumber, it should be greater than one. (see: the last message in https://github.com/rordenlab/dcm2niix/issues/40)

For that dataset I have indeed a weird SliceNormalVector:

>> gdcmdump -C IM-0010-0020.dcm | grep -i slicenormalvector
>> 23 - 'SliceNormalVector' VM 3, VR FD, SyngoDT 4, NoOfItems 6, Data '0.01570726'\'-0.05755664'\'-0.99821867'

Opposed to mosaic series where the order of the slices inside a 2D mosaic frame is the usual one (ascending).

In breif: you'll probably have to flip along the Z axis the volume you will extract from the 2D mosaic frame. Another way to check that seems to be the ProtocolSlicenumber csa field beeing greater than 1.

About IPP:

>>> The SPM DICOM conversion code has a comment saying that mosaic DICOM imagqes have an incorrect ImagePositionPatient field. The ImagePositionPatient field usually gives the t vector. The comments imply that Siemens has derived ImagePositionPatient from the (correct) position of the center of the first slice (once the mosaic has been unpacked), but has then adjusted the vector to point to the top left voxel, where the slice size used for this adjustment is the size of the mosaic, before it has been unpacked.

see(http://nipy.org/nibabel/dicom/dicom_mosaic.html)



Mathieu Malaterre

unread,
Jul 28, 2017, 4:08:03 AM7/28/17
to
Hi René-paul,

In the end I simply gave up on SliceNormalVector, I failed to understand how to interpret it.

As mentioned in my earlier post, 'gdcmtar' is now simply relying on the value sPosition/sNormal to order the sub-frames of the MOSAIC 2D frame, I find it much more reliable (also interpretation is straighforward).

Since you have access to the DataSet from Hans Johnson, you may want to verify that gdcmtar output is compatible with dcm2niix output (that would be terrific!).

Usage:

$ gdcmtar --mosaic -i MOSAIC.dcm -o mosaic --pattern %03d.dcm

Make sure to use gdcmtar --version >= 2.8.2.

Thanks.

Mathieu Malaterre

unread,
Jul 28, 2017, 4:10:07 AM7/28/17
to
Answering myself, here is what I choose to implement in gdcmtar:

* https://sourceforge.net/p/gdcm/mailman/message/35951046/

[...]
So I decided to revert the changes I introduced in 2.8.1. Please do
NOT use 2.8.1 in production, as it may read the slices from a 2D
MOSAIC SIEMENS instance in the wrong order.

Instead directly update to 2.8.2, it is compatible in behavior with
2.8.0 and earlier. I've introduced some extra options in gdcmtar
during generation, by default I am not transmitting private tags.
You'll need to use --mosaic-private to preserve the unsafe behavior
from 2.8.0.

I believe I misinterpreted the meaning of SliceNormalVector as defined
in SIEMENS CSA header. Until a clear documentation is produced, I will
be using directly the sPosition and sNormal as found within the
MrProtocol header to order the slices.

For later references:

* https://groups.google.com/d/msg/comp.protocols.dicom/hKNsgnjS1vs/nXSdO6m0BgAJ
* https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=spm;ede5f8bf.1707
(Subject: spm_dicom_convert: Handline of SliceVectorNormal)
* http://nipy.org/nibabel/dicom/dicom_mosaic.html

Cheers.
[...]

René-paul Debroize

unread,
Jul 31, 2017, 10:44:05 AM7/31/17
to
Hi Mathieu,

I don't have access to Hans Johnson data.however I did have some Siemens Mosaic data acquired in descending order.

I tested gdcmtar with gdcm 2.8.2 on this data, it doesn't work, the volume is flipped along the Z axis.

cror...@gmail.com

unread,
Oct 21, 2017, 4:58:46 PM10/21/17
to
My web page provides sample images with reversed image numbering, describes how to generate them and also demonstrates that they reflect how the images are saved to disk but not how they are acquired: http://www.mccauslandcenter.sc.edu/crnl/tools/stc

Specifically, images axial images acquired with ASCENDING or INTERLEAVED are acquired in the order F>>H regardless of this setting (and presumably DESCENDING are acquired H>>F regardless of this setting). I concur with the Siemens article I cite "Do not use the mode H>>F because this complicates the numbering". However, ProtocolSliceNumber does allow you to detect this setting.

Mathieu Malaterre

unread,
May 18, 2018, 4:21:55 AM5/18/18
to
I've re-reverted my change. Thanks to Chris Rorden (dcm2nii) for his help. The correct information is located here:

* http://www.mccauslandcenter.sc.edu/crnl/tools/stc

sPosition and sNormal should not be used directly. One need to use SliceNormalVector (and/or ProtocolSliceNumber for QA).
0 new messages