SimpleITK  1.2.4
DicomSeriesFromArray/DicomSeriesFromArray.py
1 #=========================================================================
2 #
3 # Copyright Insight Software Consortium
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0.txt
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17 #=========================================================================
18 
19 from __future__ import print_function
20 
21 import SimpleITK as sitk
22 
23 import sys, time, os
24 import numpy as np
25 
26 if len( sys.argv ) < 2:
27  print( "Usage: python " + __file__ + "<output_directory>" )
28  sys.exit ( 1 )
29 
30 def writeSlices(series_tag_values, new_img, i):
31  image_slice = new_img[:,:,i]
32 
33  # Tags shared by the series.
34  list(map(lambda tag_value: image_slice.SetMetaData(tag_value[0], tag_value[1]), series_tag_values))
35 
36  # Slice specific tags.
37  image_slice.SetMetaData("0008|0012", time.strftime("%Y%m%d")) # Instance Creation Date
38  image_slice.SetMetaData("0008|0013", time.strftime("%H%M%S")) # Instance Creation Time
39 
40  # Setting the type to CT preserves the slice location.
41  image_slice.SetMetaData("0008|0060", "CT") # set the type to CT so the thickness is carried over
42 
43  # (0020, 0032) image position patient determines the 3D spacing between slices.
44  image_slice.SetMetaData("0020|0032", '\\'.join(map(str,new_img.TransformIndexToPhysicalPoint((0,0,i))))) # Image Position (Patient)
45  image_slice.SetMetaData("0020,0013", str(i)) # Instance Number
46 
47  # Write to the output directory and add the extension dcm, to force writing in DICOM format.
48  writer.SetFileName(os.path.join(sys.argv[1],str(i)+'.dcm'))
49  writer.Execute(image_slice)
50 
51 # Create a new series from a numpy array
52 new_arr = np.random.uniform(-10, 10, size = (3,4,5)).astype(np.int16)
53 new_img = sitk.GetImageFromArray(new_arr)
54 new_img.SetSpacing([2.5,3.5,4.5])
55 
56 # Write the 3D image as a series
57 # IMPORTANT: There are many DICOM tags that need to be updated when you modify an
58 # original image. This is a delicate opration and requires knowlege of
59 # the DICOM standard. This example only modifies some. For a more complete
60 # list of tags that need to be modified see:
61 # http://gdcm.sourceforge.net/wiki/index.php/Writing_DICOM
62 # If it is critical for your work to generate valid DICOM files,
63 # It is recommended to use David Clunie's Dicom3tools to validate the files
64 # (http://www.dclunie.com/dicom3tools.html).
65 
66 writer = sitk.ImageFileWriter()
67 # Use the study/series/frame of reference information given in the meta-data
68 # dictionary and not the automatically generated information from the file IO
69 writer.KeepOriginalImageUIDOn()
70 
71 modification_time = time.strftime("%H%M%S")
72 modification_date = time.strftime("%Y%m%d")
73 
74 # Copy some of the tags and add the relevant tags indicating the change.
75 # For the series instance UID (0020|000e), each of the components is a number, cannot start
76 # with zero, and separated by a '.' We create a unique series ID using the date and time.
77 # tags of interest:
78 direction = new_img.GetDirection()
79 series_tag_values = [("0008|0031",modification_time), # Series Time
80  ("0008|0021",modification_date), # Series Date
81  ("0008|0008","DERIVED\\SECONDARY"), # Image Type
82  ("0020|000e", "1.2.826.0.1.3680043.2.1125."+modification_date+".1"+modification_time), # Series Instance UID
83  ("0020|0037", '\\'.join(map(str, (direction[0], direction[3], direction[6],# Image Orientation (Patient)
84  direction[1],direction[4],direction[7])))),
85  ("0008|103e", "Created-SimpleITK")] # Series Description
86 
87 # Write slices to output directory
88 list(map(lambda i: writeSlices(series_tag_values, new_img, i), range(new_img.GetDepth())))
89 
90 # Re-read the series
91 # Read the original series. First obtain the series file names using the
92 # image series reader.
93 data_directory = sys.argv[1]
94 series_IDs = sitk.ImageSeriesReader.GetGDCMSeriesIDs(data_directory)
95 if not series_IDs:
96  print("ERROR: given directory \""+data_directory+"\" does not contain a DICOM series.")
97  sys.exit(1)
98 series_file_names = sitk.ImageSeriesReader.GetGDCMSeriesFileNames(data_directory, series_IDs[0])
99 
100 series_reader = sitk.ImageSeriesReader()
101 series_reader.SetFileNames(series_file_names)
102 
103 # Configure the reader to load all of the DICOM tags (public+private):
104 # By default tags are not loaded (saves time).
105 # By default if tags are loaded, the private tags are not loaded.
106 # We explicitly configure the reader to load tags, including the
107 # private ones.
108 series_reader.LoadPrivateTagsOn()
109 image3D = series_reader.Execute()
110 print(image3D.GetSpacing(),'vs',new_img.GetSpacing())
111 sys.exit( 0 )