Getting DICOM structure contours as array in Python - dicom
So if I have an image (CT, MRI, etc.) or even a dose from radiation therapy I can pull out the dose or image values into an array through:
import dicom
ds = dicom.read_file("dicom_file.dcm")
print ds.pixel_array
This is pretty straightforward, and gives me the ability to manipulate images/doses as I want. However, often you also have a structure file that includes different contoured structures that you can then see in an image viewer or something like that. Again, pretty straightforward.
My problem is that I would also like these individual structures as an array as well. And if I run the same code I just get TypeError: No pixel data found in this dataset.
I'm guessing that structure DICOM files are not "made" the same way as dose/images DICOM files.
So is there a solution to this that I haven't been able to find ? I have also looked at the dicompyler_core package, but from what I could see there wasn't any way to "just" get out the different structures into arrays.
The SOP Class UID of the DICOM file in question is RT Structure Set Storage.
Here is an interactive session illustrating the data layout using the rtstruct.dcm file included with pydicom:
>>> import dicom
>>> ds = dicom.read_file("rtstruct.dcm", force=True)
>>> ds.dir("contour")
['ROIContourSequence']
>>> ctrs = ds.ROIContourSequence
>>> ctrs[0]
(3006, 002a) ROI Display Color IS: ['220', '160', '120']
(3006, 0040) Contour Sequence 3 item(s) ----
(3006, 0042) Contour Geometric Type CS: 'CLOSED_PLANAR'
(3006, 0046) Number of Contour Points IS: '5'
(3006, 0048) Contour Number IS: '1'
(3006, 0050) Contour Data DS: ['-200.0', '150.0', '-20
0.0', '-200.0', '-150.0', '-200.0', '200.0', '-150.0', '-200.0', '200.0', '150.0
', '-200.0', '-200.0', '150.0', '-200.0']
---------
(3006, 0042) Contour Geometric Type CS: 'CLOSED_PLANAR'
(3006, 0046) Number of Contour Points IS: '6'
(3006, 0048) Contour Number IS: '2'
(3006, 0050) Contour Data DS: ['200.0', '-0.0', '-190.
0', '200.0', '-150.0', '-190.0', '-200.0', '-150.0', '-190.0', '-200.0', '150.0'
, '-190.0', '200.0', '150.0', '-190.0', '200.0', '-0.0', '-190.0']
---------
(3006, 0042) Contour Geometric Type CS: 'CLOSED_PLANAR'
(3006, 0046) Number of Contour Points IS: '6'
(3006, 0048) Contour Number IS: '3'
(3006, 0050) Contour Data DS: ['200.0', '-0.0', '-180.
0', '200.0', '-150.0', '-180.0', '-200.0', '-150.0', '-180.0', '-200.0', '150.0'
, '-180.0', '200.0', '150.0', '-180.0', '200.0', '-0.0', '-180.0']
---------
(3006, 0084) Referenced ROI Number IS: '1'
The data is stored (in this case, as is usual) as a set of coordinates for each plane. To get the data for one contour, for one plane, you could use
>>> ctrs[0].ContourSequence[0].ContourData
['-200.0', '150.0', '-200.0', '-200.0', '-150.0', '-200.0', '200.0', '-150.0', '
-200.0', '200.0', '150.0', '-200.0', '-200.0', '150.0', '-200.0']
These are triplets of (x, y, z) coordinates one after the other.
You can find out more information about each contour (name, etc) in the StructureSetROISequence sequence, for the index given by Referenced ROI Number.
You could get a complete array for all of these by looping through each dataset in the ContourSequence for that particular contour and appending them together into one array.
Related
is there a way for xarray DataArray to handle variable length arrays
Essentially trying to represent scatter plots with different number of points in traces for example 3 traces y1,y2,y3 that represent 'y=f(x,z)' but x are not all the same size. Question is how to represent s as an xarray DataArray. My attempts are resulting in errors 'different number of dimensions on data and dims: 0 vs 3' Note the length of x1 and x2 are not the same in the example below n_traces=3 x1=np.arange (-2,4,1);x2=np.arange(0.5,2,0.5);x3=x2*1.1 y1=x1*2;y2=np.power(x2,1.5)-3;y3=y2*.9 z=[0.5,1,2] s=tuple(x1) s=((tuple(x1),tuple(y1)),(tuple(x2),tuple(y2)),(tuple(x3),tuple(y3)))
What is the full Optical Density representation range of shades of gray in a Dicom CT image?
For normal images the range of shades of gray is from 0 to 256, what is it for Dicom CT monochrome images?
Techically, I agree with Amit Joshi. But especially for CT images you will usually find a grayscale range expressed in Hounsfield Units. These range from -1000 to +4000. By applying a linear transformation of the pixel data as specified by the attributes Rescale Intercept (0028,1052) and Rescale Slope (0028,1053), pixel data as described by Amit Joshi's anwer are mapped to that range. To this range, the windowing (VOI LUT) funtion is applied. [EDIT] A little explanation on Hounsfield units (HU)... HU are valid for CT images only. A range of HU corresponds to a particular type of tissue or depicted structures, e.g. -1000 -> air 0 -> fat 10-40 -> kidney and so on. So in CT images, pixel values found in the file are usually mapped to HU using Rescale Slope and -Intercept. Whether or not the this is the case is indicated by the attribute Rescale Type (0028,1054). HUs are not only used for measuring grayvalues and deducing tissue type from the median value but also for windowing. In CT, you refer to "bone window", "tissue window" etc. So the relevant part of the DICOM Grayscale Standard Display Function (GSDF, see PS3.14) is: interpret the pixel values according to their type description (signed/unsigned, bpp) map the pixel values to HU using Rescale Slope and -Intercept apply windowing to HU, i.e. map the range of the HU defined by the window to the display range (usually 256 grayscales)
I am not sure about Optical Density Representation. Shades of gray can be calculated by 2^Bits Stored. For CT images, Bits Stored may be 10 to 16 depending on manufacturer and other factors. Considering value 16, shades are 65536. For unsigned image: - Start value: 0 End value: 65536 For signed image: - Start value: -32768 End value: 32768 CT images are generally signed. In signed images, 0 is center and range is split half negative values and half positive values.
How to generate vector arrows that conforms to a raster slope layer?
I would like to generate vector arrows that conform to the topography/slope of a raster dataset of a river catchment area. I have created a Fishnet grid of points in ArcGIS and I would like to create a single arrow for each point of a set length that will follow the shape of the slope i.e. follow the path of least resistance, the line will follow progressively small numbers in a 3 x 3 grid. I think I can generate the vector arrows using vector plot. Is it possible to achieve the lines conforming to the raster? UPDATE: I have ~200,000 lines that I generated from a grid of points. I am going to turn these into a raster using R and set it to the same resolution as my slope raster. Any ideas on how to layer the raster lines on the slope so I can get the lines to follow the lowest values of the slope?
This is for display/mapping purposes only? Use a DEM or TIN and display your arrow lines in ArcScene. EDIT: given your update about your data and software not working- Try this: 1) Make a raster surface covering the extent of your data with a cell size of 100m (or smaller or larger if that doesn't suit) 2) Convert that raster to a polygon layer e.g. 'area_grid100m' 3) Do a spatial join and assign all points a polygon cell id from one of the unique id fields in 'area_grid100m' 4) Use Summarize to get the mean lat/long of the start points and mean lat/long of the end points for each polygon. Summarize on the polygon id field and get select mean for both the lat and long fields 5) Add summary table to ArcMap, right click and select Display XY Data (set X Field as longitude and y Field as latitude). Right right the result and select Data > Export Data to make it permanent. You will now have two points per 'area_grid100m' cell. 5) Recreate your lines using this new file, which will give you one line per cell If the res is not small enough, make the 'area_grid' cells smaller.
Gnuplot: plot with circles of a defined radius
I know on gnuplot you can plot some data with circles as the plot points: plot 'data.txt' using 1:2 ls 1 with circles How do I then set the size of the circles? I want to plot several sets of data but with different size circles for each data set.
If you have a third column in your data, the third column specifies the size of the circles. In your case, you could have the third column have the same value for all the points in each data set. For example: plot '-' with circles 1 1 0.2 e will plot a circle at (1,1) with radius 0.2. Note that the radius is in the same units as the data. (The special file name '-' lets you input data directly; typing 'e' ends the input. Type help special at the gnuplot console for more info.) You can look here for more ideas of how to use circles.
I used: plot "file" using 1:2:($2*0+10) with circles This will fake a the third column specifying the sizes - it is probably possible to write it simpler, but this worked for me.
drawing a circle around many points with different radius
I can draw a circle around a given point (x,y) with a command like flowing (here for example point is at (X=5,Y=7) and the circle have a radius R=2.73): set object 1 circle at 5,7 size first 2.73 fc rgb "navy" Now, if I have many points (in a txt file where each line is "x y") and I want to draw a circle around each point with different specified radius. Should I repeat the command "set object i circle at Xi,Yi size first Ri fc rgb "navy"" for each point i ?!
It looks like you may want to use the with circles option. If you have a data file with three columns (x y radius), the following command will plot circles with radii from the file at each point: plot 'datafile' u 1:2:3 with circles http://gnuplot.sourceforge.net/demo/circles.html
You can create a loop in gnuplot for multiple circles. do for[k=1:20]{ set object k circle front at k*3,0 size 1 fillcolor rgb "black" lw 1 } This will create 20 circles at x points (3,6,9...) of radius 1. Please keep in mind to set the object count with the loop variable too ("object k").