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?)
Related
I am currently working on some radiotherapy plan generation and I am trying to retrieve the beam source position from a DICOM RTPLAN file and point it on a related CT-Scan 3D image.
With the RTPLAN, I am able to access the isocenter position of each beam but this is in patient coordinates and I am note quite sure how to find the coordinates in the basis that is used by the 3D CT-Scan image.
I have access to the attributes ImagePosition and ImageOrientation of the DICOM of the CT. Moreover, the CT DICOM-like file (it is in practice a json regrouping some DICOM information) and the RTPLAN share the same FrameOfReference (Does it mean that they share the Patient coordinate system ?).
What does ImagePosition truely indicates ? As well as I can understand I think this is the position of the point (0, 0, 0) of the CT-3DImage in the Patient Coordinates. I am also a bit confused about the ImageOrientation attribute.
As you can read in this answer here, the ImagePosition attribute gives you the x, y, and z coordinates of the upper left hand corner of the image, in mm, i.e. the coordinates of the center of the upper left pixel of the image.
For your convenience I copy-paste below a table from the DICOM Documentation Part 3 (page 561).
Regarding the ImageOrientation attribute, as described in the documentation, gives you the direction cosines of the first row and the first column with respect to the patient. To understand better this attribute take a look at the very useful website, DICOM is Easy, by Roni Zaharia. In one of his images (below), you can clearly see that when the attribute is not equal to 1\0\0\0\1\0, then the coordinate system of the image is not align with the coordinate system of the patient. To align them, you have to use the direction cosines provided by the attribute and apply a rotation (take a look at the transformation matrix at page 562 of the aforementioned DICOM documentation).
I want to write a program with 'geometry automata'. I'd like it to be a companion to a book on artistic designs. There will be different units, like the 'four petal unit' and 'six petal unit' shown below, and users and choose rulesets to draw unique patterns onto the units:
I don't know what the best data structure to use for this project is. I also don't know if similar things have been done and if so, using what packages or languages. I'm willing to learn anything.
All I know right now is 2D arrays to represent a grid of units. I'm also having trouble mathematically partitioning the 'subunits'. I can see myself just overlapping a bunch of unit circle formulas and shrinking the x/y domains (cartesian system). I can also see myself representing the curve from one unit to another (radians).
Any help would be appreciated.
Thanks!!
I can't guarantee that this is the most efficient solution, but it is a solution so should get you started.
It seems that a graph (vertices with edges) is a natural way to encode this grid. Each node has 4 or 6 neighbours (the number of neighbours matches the number of petals). Each node has 8 or 12 edges, two for each neighbour.
Each vertex has an (x,y) co-ordinate, for example the first row in in the left image, starting from the left is at location (1,0), the next node to its right is (3,0). The first node on the second row is (0,1). This can let you make sure they get plotted correctly, but otherwise the co-ordinate doesn't have much to do with it.
The trouble comes from having two different edges to each neighbour, each aligned with a different circle. You could identify them with the centres of their circles, or you could just call one "upper" and the other "lower".
This structure lets you follow edges easily, and can be stored sparsely if necessary in a hash set (keyed by co-ordinate), or linked list.
Data structure:
The vertices can naturally be stored as a 2-dimensional array (row, column), with the special characteristic that every second column has a horizontal offset.
Each vertex has a set of possible connections to those vertices to its right (upper-right, right, or lower right). The set of possible connections depends on the grid. Whether a connection should be displayed as a thin or a thick line can be represented as a single bit, so all possible connections for the vertex could be packed into a single byte (more compact than a boolean array). For your 4-petal variant, only 4 bits need storing; for the 6-petal variant you need to store 6 bits.
That means your data structure should be a 2-dimensional array of bytes.
Package:
Anything you like that allows drawing and mouse/touch interaction. Drawing the connections is pretty straightforward; you could either draw arcs with SVG or you could even use a set of PNG sprites for different connection bit-patterns (the sprites having partial transparency so as not to obscure other connections).
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)
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.
I have a basic question for the DICOM protocol.
I know how I can calculate the orientation labels of every slice of a DICOM image (A,P,L,R,H,F). But when I got for example an Axial slices with numbers from 0001 to 0024 I need to know if the slice order is from Head to Feet or from Feet to Head.
How can I calculate that ?
Patient Position (0018, 5100) will tell you if the patient was scanned head-first supine, feet-first prone, head-first prone, etc. Instance Number (0020, 0013), also commonly known as slice number, contains no information about spatial location and isn't even guaranteed to be unique. Slice Location (0020, 1041) is useful, if it exists, but you can't count on it always existing because it's a Type 3 (optional) attribute. To have a robust solution, you need to use Image Position Patient (0020, 0032) together with Image Orientation Patient (0020, 0037) and Patient Position (0018, 5100) to properly order the slices in space. Image Position Patient gives you a vector from the origin to the center of the first transmitted pixel of the image. Image Orientation Patient gives you vectors for the orientation of the rows and columns of the image in space. Patient Position tells you how the patient was placed on the table relative to the coordinate system.
The origin of the patient coordinate system is arbitrary, and selected by the imaging modality. I assume that the modality is free to choose a different origin for each series of images, but the origin is fixed for a given series.
If you wish to annotate images when displayed with notations such as (L) or (R) to indicate which side of the 2D image is considered the patient's left or right side, you need the Patient Position (0018, 5100) Attribute from the General Series module.
This attribute contains the position of the patient relative to the imaging equipment space.Valid values are:
1.Head First-Prone
2.Head First-Supine
3.Head First-Decubitus Right
4.Head First-Decubitus Left
5.Feet First-Decubitus Left
6.Feet First-Decubitus Right
7.Feet First-Prone
8.Feet First-Supine.
Definitions:
Head First means the patient was laying on the imaging couch with the head facing the imaging device first.
Feet first means the patient was laying on the imaging couch with the feet facing the imaging device first.
Prone means the patient is laying on his/her stomach. (Patient's face being positioned in a downwards (gravity) direction.)
Supine means the patient is laying on his/her back. (Patient's face being in an upwards direction.)
Decubitus Right means the patient is laying with his/her right side in a downwards direction.
Decubitus Left means the patient is laying with his/her left side in a downwards direction.
NOTE -- Patient Position (0018, 5100) is a type 1 required attribute for both the CT and MR modalities. This attribute is VERY IMPORTANT for accurately interpreting the patient's orientation.
You do not need to consider the patient position tag to label dicom images orientations when presented on screen. You only need the image orientation patient. Since that's the orientation of the image in the (patient) reference coordinate system.
So, for example you will get different values for IOP from a CT scanner if the patient is prone or supine.