Get Dicom image position into a sequence - dicom

A simple question as i am developing a java application based on dcm4che ...
I want to calculate/find the "position" of a dicom image into its sequence (series). By position i mean to find if this image is first, second etc. in its series. More specifically i would like to calculate/find:
Number of slices into a Sequence
Position of each slice (dicom image) into the Sequence
For the first question i know i can use tag 0020,1002 (however it is not always populated) ... For the second one?

If you are dealing with volumetric image series, best way to order your series is to use the Image Position (Patient) (0020, 0032). This is a required Type 1 tag (should always have value) and it is part of the image plane module. It will contain the X, Y and Z values coordinates representing the upper left corner of the image in mm. If the slices are parallel to each other, only one value should change between the slices.
Please note that the Slice Location (0020, 1041) is an optional (Type 3) element and it may not exist in the DICOM file.

We use the InstanceNumber tag (0x0020, 0x0013) as our first choice for the slice position. If there is no InstanceNumber, or if they are all the same, then we use the SliceLocation tag (0x0020, 0x1041). If neither tag is available, then we give up.
We check the InstanceNumber tag such that the Max(InstanceNumber) - Min(InstanceNumber) + 1 is equal to the number of slices we have in the sequence (just in case some manufacturers start counting at 0 or 1, or even some other number). We check the SliceLocation the same way.
This max - min + 1 is then the number of slices in the sequence (substitute for tag ImagesInAcquisition 0x0020, 0x1002).
Without the ImagesInAcquisition tag, we have no way of knowing in advance how many slices to expect...

I would argue that if the slice location is available, use that. It will be more consistent with the image acquisition. If it is not available, then you'll have to use or compute from the image position (patient) attribute. Part 3 section C.7.6.2.1 has details on these attributes.
The main issue comes when you have a series that is oblique. If you just use the z-value of the image position (patient), it may not change by the slice thickenss/spacing between slices attributes, while the slice location typically will. That can cause confusion to end users.

Related

Dicom protocol and CT scan and sorting according to z position of axial slices?

I have a CT scan of the chest where I can't seem to figure out how to determine how to sort the aixal slices such that the first slices are the ones closet to the head.
The scan has the following dicom parameters:
Patient Position Attribute (0018,5100): FFS (Feet First Supine)
Image Position (Patient) (0020,0032): -174-184-15 (one slice)
Image Orientation (Patient)(0020,0037): 1\0\0\0\1\0
The most cranial slice (anatomically, closet to the head) has z position 13 and the most caudal (lower) -188.
However, when the Patient Position is FFS shouldn't the slice with the lowest z position (e.g. -188) be the one being the one most cranially (anatomically, i.e. closet to the head) located?
Can anyone enlighten me?
Kind regards
DICOM very clearly defines, that the x-axis has to go from the patients right to the left, the y-axis has to go from front to back, and the z-axis has to go from foot to head.
So the lower z-position of -188 has to be closer to the feet than the higher position of 13. You should always rely on this.
Patient Position Attribute is rather some informational annotation. If you do all the math yourself, then you can ignore it.
If a viewer does not do the math (there are a lot of them) and just loads the images and shows them sored by ImageNumber, then the Position Attribute is the info to annotate, if the image with ImageNumber 1 is the one closer to the head or the one closer to the feet. Meaning: when the patient went throught the ct scanner, which one was the first imate aquisitioned: the one of the head or of the feet.

What direction do the DICOM instance numbers grow along?

By direction I mean for example from a patient's head to bottom or from his bottom to head. The CHEST CT scans I have seen so far indicates that Instance Number 1 slice is usually the first one down from the upper part of the body but I don't know whether this is part of the standard or there are some other tags that I should inspect into to determine.
There is no rule in DICOM that requires the Instance Number to be related to the slice position in a particular way. The link of Bartloimiej shows that there is a rule how the slice coordinates defined by Image Position Patient (0020,0027) and Image Orientation Patient (0020, 0037) are related to directions in the patient's body (head, feet, etc.)
So if you want to apply spatial ordering, these attributes are what you want to use. Slice Location (0020,1041) will not help you as well:
C.7.6.2.1.2 [...] This information is relative to an unspecified implementation specific reference point.
For original (i.e. Image Type (0008,0008) is ORIGINAL\PRIMARY...) CT slices, it is quite safe to assume that some growth in the Z-Direction is always present in a volumetric dataset. But for MRI or for reconstructed CT-slices (MPR), you may find datasets in which slices are parallel to the xz or yz plane. If your application is supposed to handle such images, make sure to avoid division by zero...
Yes, the standard defines it. DICOM PS3.3, part C.7.6.2:
The direction of the axes is defined fully by the patient's orientation.
If Anatomical Orientation Type (0010,2210) is absent or has a value of BIPED, the x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient.
There is also a tag (0020,0037), Image Orientation (Patient), which relates actual position of the patient to the global coordinate frame. In trunk CT it is almost always 1 0 0 0 1 0 (no rotation) and you don't need to deal with it. Otherwise, see comments under the link above.
You are correct. The chest CT series are sorted from head to feet. The slice closest to the head should have the lowest Instance Number.
I don't know if this is defined by the DICOM standard or not, but I have seen a lot of DICOM images and the convention is this:
AXIAL - sorted by Z axis high to low (head to feet)
CORONAL - sorted by Y axis high to low (back to front)
SAGITTAL - sorted by X axis low to high (right to left)
Notice in all cases, the first slice in the series will be farthest from the observer.
If you need to generate Instance Number, you should sort the images by the dot product of Image Position Patient and (1,-1,-1) from low to high. In the rare degenerate case (all dot products are the same), I don't know. Pick another direction to sort, but probably (0,-1,-1) would be a good choice.
EDIT: I just discussed this with a friend who is more experienced. He said it varies. Some departments prefer back to front order, some prefer front to back. Also some DICOM viewers will give users the choice of how the slices are sorted (by Instance Number, Slice Location, IPP, Content Time, etc)

How to deal with arbitrary size for Laplacian Pyramid?

Recently I had much fun with the Laplacian Pyramid algorithm (http://persci.mit.edu/pub_pdfs/pyramid83.pdf). But one big problem is that the original paper is limited to 2^m+1*2^n+1 images. My question is: What is the best way to deal with arbitrary w*h instead? I can think of a couple of options:
Up sample the input to the next 2^m+1,2^n+1 up front
Pad even lines. How exactly? Wouldn't it shift the signal?
Shift even lines by half a sample? Wouldn't it loose half a sample?
Does anybody have experience with this? What is the most practical and efficient approach? Also any pointers to papers dealing with this would be very welcome.
One approach is to create an image with a width and height equal to the next 2^m+1,2^n+1, but instead of up-sampling the image to fill the expanded dimensions, just place it in the top-left corner and fill the empty space to the right and below with a constant value (the average value for the image is a good choice for this). Then encode in the normal way, storing the original image dimensions along with the pyramid. When decoding, decode and then crop to the original size.
This won't introduce any visual artifacts or degradation because you aren't stretching or offsetting the image in any way.
Because the empty space to the right and below the original image is a constant value, the high-pass bands at each level in the image pyramid will be all zero in this area. So if you are using a compression scheme like run length encoding to store each level this will be automatically taken care off and these areas will be compressed to almost nothing. If not then you can simply store the top-left (potentially non-zero) area of each level and then fill out the rest with zeros when decoding.
You could find the min and max x and y bounding rectangle of the non-zero values for each level and store this along with the level, cropped to include only non-zero values. The decoder could also be optimized so that areas of the image that are going to be cropped away are not actually decoded in the first place, by only processing the top-left of each level.
Here's an illustration of the technique:
Instead of just filling the lower-right area with a flat color, you could fill it with horizontally and vertically mirrored copies of the image to the right and below, and a copy mirrored in both directions to the bottom-right, like this:
This will avoid the discontinuities of the first technique, although there will be a discontinuity in dx (e.g. if the value was gradually increasing from left to right it will suddenly be decreasing). Choosing a mirror that keeps dx constant and ddx zero will avoid this second-order discontinuity by linearly extrapolating the values.
Another technique, which is similar to what some JPEG encoders do to pad out an image to a whole number of MCU blocks, is to take the last pixel value of each row and repeat it, and likewise for columns, with the bottom-right-most pixel of the image used to fill the bottom-right area:
This last technique could easily be modified to extrapolate the gradient of values or even the gradient of gradients instead of just repeating the same value for the remainder of the row or column.

How to calculate space between dicom slices for MPR?

Due to showing MPR view based on Dicoms. I've made a 3D array from series of dicom files. And I show it from Coronal and Sagittal sides.
My 3D array includes:
- z = count of dicoms
- c = column value for every dicoms
- r = Row value for every dicoms
But I have a problem. When there is some space between slices, image is made by this way doesn't show a correct view. Because I can not think of simulation distance between them!
I don't know how to calculate space between slices? I want to add extra space between slices. for example, If space between slices is 4. I have to add 4 time z inner slices.
I hope to arrive my mean.
Image Position (Patient) and Image Orientation (Patient) are the two only attributes you should ever used when computing distance between slices. For more details see here or here. For an actual implementation see here, this implementation also does take into account Frame Of Reference UID, as well as Gantry/Detector Tilt.
This question is the question #1 asked on comp.protocols.dicom.
Please see ImageJ bug
I believe the answer from #Matt is erroneous, let me clarify a few things here.
No: 'DICOM does not have an attribute called Spacing Between Slices'. That is very wrong (technically it does not even mean anything).
DICOM defines IODs which define the set of required attributes available in an SOP Class Instance. Let's consider two very common cases: CT Image Storage (legacy) and MR Image Storage (legacy). So we need to compare the set of attributes in between:
CT Image IOD Modules
MR Image IOD Modules
Now let's say we want to check that MR Image Storage support Spacing Between Slices, it is easy to jump to:
MR Image Module Attributes
However it is much harder to find this attribute for CT Image Storage: simply because this attribute does not exist (per standard). So the only time you would find such attribute would be within an extended SOP Class (some vendors may decide that Spacing Between Slices attribute make sense within their extended SOP Class Instance).
Mixing in the same answer both Spacing Between Slices and Slice Thickness (0018,0050) is very confusing for new users.
I agree that Slice Thickness is perfectly defined in the standard for both CT Image Storage and MR Image Storage since they both include Image Plane Module Attributes, however let's not exchange one for the other.
I found a nice summary of Slice Thickness vs Spacing Between Slices here (if you scroll to the section, you can even play the small demo) :
CT Physics: CT Reconstruction and Helical CT
In step and shoot CT the Slice Thickness and Spacing Between Slices are identical so there is no big issue here. However for helical CT those values are not the same and can vary in any direction (they are independent).
[…] Slice Thickness is determined by the detector width and pitch,
while reconstruction interval (=Spacing Between Slices) can be chosen
arbitrarily. […]
In conclusion to compute (safely!) the Spacing Between Slices (= Reconstruction Interval), it is much safer to use Image Orientation (Patient) and Image Position (Patient) since they are available in either MR Image Storage or CT Image Storage instances.
DICOM has an attribute called Spacing Between Slices (0018, 0088) that gives the distance between two adjacent slices (perpendicular to the image plane) and it also has an attribute called Slice Thickness (0018, 0050) that gives the thickness of the imaged slice (the image plane exists at the center of the slice, with half of the volume above the plane and half below). Image Position (Patient) (0020, 0032) and Image Orientation (Patient) (0020, 0037) are also useful attributes for computing spatial relationships between slices.
For a more detailed explanation, see section C.7.6.2 of part 3 of the DICOM standard. (p. 409)
WARNING: Please be aware that different vendors use the same dicom tags for addressing different things. For instance, the attribute Spacing Between Slices (0018, 0088) means two different things depending on the vendor. See this table to have a guide, and this thread for an explanation.
As discussed in the previous answers, it is not straightforward how to calculate space between DICOM slices. Let's phrase the question differently: How to store DICOM slices in a 3D volume, i.e. a list of equally spaced slices for rendering (guess you want to upload into a 3D texture).
This is because the actual position that a CT slice is captured might not be identical to the position selected by the radiologist. A dataset might have been configured to capture 1 mm slices, but the CT returns slices at position 0.0 mm, 0.997 mm, 2.010 mm, ...
If you use an attribute such as Spacing Between Slices to calculate the size of the 3D volume, you will obtain subtle rounding errors easily. Don't go there.
Rather it is essential to use Image Position (Patient) (0020, 0032) and then perform an optimization to figure our how the slices could be fit into an grid.
Typical problems in practice to consider:
Missing slices (interpolate? Gap?)
Out of step slices (hardware defect? data defect?)

PlayN: GroupLayer.add( layer) seems to ignore layer's depth attribute

Suppose I have 4 layer, A,B,C,D with layer.depth() of 1, 4, 2, 3.
when I add the those layer to parent, by using groupLayer.add(layer), the index (ala, depth,) of them added seems to ignore the 'depth()' attribute and the result is according only to the order when I add them.
Not sure if it's a implementation bug or I have the wrong usage semantic.
I'm not sure this is your problem but it's definitely mine right now.
I'm pretty certain layer depth only obeys the depth value within a group.
If you nest groups (like for parts of a character), I think the layer(s) in higher level groups will always be drawn above the layer(s) in lower level groups.
I'm running into this issue now when trying to create a puppet-like character with lots of image layers arranged in a group layer hierarchy of body parts.
The torso needs to be at the top of the transformation hierarchy but some layers need to be drawn on top of the torso as well. Currently, I don't think you can do this with a single group layer hierarchy with image layers as children.
GroupLayer.add(layer, depth) has been deprecated. Instead you should use Layer.setDepth.

Resources