Commit ef8b84edbfe331b67c8d7fb1c7ca3e1ed0512575

Authored by Paulo Henrique Junqueira Amorim
1 parent 96833c49

ENH: Replaced the way it reads some data, changed of vtkgdcm to gdcm reader DICOM tags.

Showing 1 changed file with 210 additions and 201 deletions   Show diff stats
invesalius/reader/dicom.py
@@ -94,6 +94,213 @@ class Parser(): @@ -94,6 +94,213 @@ class Parser():
94 self.encoding = "" 94 self.encoding = ""
95 self.vtkgdcm_reader = vtkgdcm.vtkGDCMImageReader() 95 self.vtkgdcm_reader = vtkgdcm.vtkGDCMImageReader()
96 96
  97 + def SetFileName(self, filename):
  98 + """
  99 + Set file name to be parsed given its filename (this should
  100 + include the full path of the file of interest).
  101 +
  102 + Return True/False if file could be read.
  103 + """
  104 + import os.path as path
  105 +
  106 +
  107 + filename = path.abspath(filename)
  108 +
  109 + if (sys.platform == 'win32'):
  110 + filename = filename.encode('latin-1')
  111 +
  112 + if path.isfile(filename):
  113 + # Several information can be acquired from DICOM using
  114 + # vtkgdcm.vtkGDCMImageReader.GetMedicalImageProperties()
  115 + # but some tags (such as spacing) can only be achieved
  116 + # with gdcm.ImageReader()
  117 + # used to parse DICOM files - similar to vtkDICOMParser
  118 + gdcm_reader = gdcm.ImageReader()
  119 + #filename = filename.encode('utf-8')
  120 +
  121 + gdcm_reader.SetFileName(filename)
  122 +
  123 + # if DICOM file is null vtkGDCMImageReader raises vtk
  124 + # exception
  125 + if not gdcm_reader.Read():
  126 + return False
  127 +
  128 + vtkgdcm_reader = self.vtkgdcm_reader
  129 + vtkgdcm_reader.SetFileName(filename)
  130 + vtkgdcm_reader.Update()
  131 +
  132 + self.filename = filename
  133 + self.gdcm_reader = gdcm_reader
  134 + self.vtkgdcm_reader = vtkgdcm_reader
  135 + return True
  136 +
  137 + return False
  138 +
  139 + def GetImageData(self):
  140 + return self.vtkgdcm_reader.GetOutput()
  141 +
  142 + def __format_time(self,value):
  143 + sp1 = value.split(".")
  144 + sp2 = value.split(":")
  145 +
  146 + if (len(sp1) == 2) and (len(sp2) == 3):
  147 + new_value = str(sp2[0]+sp2[1]+
  148 + str(int(float(sp2[2]))))
  149 + data = time.strptime(new_value, "%H%M%S")
  150 + elif (len(sp1) == 2):
  151 + data = time.gmtime(float(value))
  152 + elif (len(sp1) > 2):
  153 + data = time.strptime(value, "%H.%M.%S")
  154 + elif(len(sp2) > 1):
  155 + data = time.strptime(value, "%H:%M:%S")
  156 + else:
  157 + data = time.strptime(value, "%H%M%S")
  158 + return time.strftime("%H:%M:%S",data)
  159 +
  160 + def __format_date(self, value):
  161 +
  162 + sp1 = value.split(".")
  163 + try:
  164 +
  165 + if (len(sp1) > 1):
  166 + if (len(sp1[0]) <= 2):
  167 + data = time.strptime(value, "%D.%M.%Y")
  168 + else:
  169 + data = time.strptime(value, "%Y.%M.%d")
  170 + elif(len(value.split("//")) > 1):
  171 + data = time.strptime(value, "%D/%M/%Y")
  172 + else:
  173 + data = time.strptime(value, "%Y%M%d")
  174 + return time.strftime("%d/%M/%Y",data)
  175 +
  176 + except(ValueError):
  177 + return ""
  178 +
  179 + def GetImageOrientationLabel(self):
  180 + """
  181 + Return Label regarding the orientation of
  182 + an image. (AXIAL, SAGITTAL, CORONAL,
  183 + OBLIQUE or UNKNOWN)
  184 + """
  185 + img = self.gdcm_reader.GetImage()
  186 + direc_cosines = img.GetDirectionCosines()
  187 + orientation = gdcm.Orientation()
  188 + try:
  189 + type = orientation.GetType(tuple(direc_cosines))
  190 + except TypeError:
  191 + type = orientation.GetType(direc_cosines)
  192 + label = orientation.GetLabel(type)
  193 +
  194 + if (label):
  195 + return label
  196 + else:
  197 + return ""
  198 +
  199 + def GetDimensionX(self):
  200 + """
  201 + Return integer associated to X dimension. This is related
  202 + to the number of columns on the image.
  203 + Return "" if not defined.
  204 + """
  205 + tag = gdcm.Tag(0x0028, 0x0011)
  206 + ds = self.gdcm_reader.GetFile().GetDataSet()
  207 + sf = gdcm.StringFilter()
  208 + sf.SetFile(self.gdcm_reader.GetFile())
  209 + data = sf.ToStringPair(tag)[1]
  210 +
  211 + if (data):
  212 + return int(str(data))
  213 + return ""
  214 +
  215 +
  216 + def GetDimensionY(self):
  217 + """
  218 + Return integer associated to Y dimension. This is related
  219 + to the number of rows on the image.
  220 + Return "" if not defined.
  221 + """
  222 + tag = gdcm.Tag(0x0028, 0x0010)
  223 + ds = self.gdcm_reader.GetFile().GetDataSet()
  224 + sf = gdcm.StringFilter()
  225 + sf.SetFile(self.gdcm_reader.GetFile())
  226 + data = sf.ToStringPair(tag)[1]
  227 +
  228 + if (data):
  229 + return int(str(data))
  230 + return ""
  231 +
  232 +
  233 + def GetDimensionZ(self):
  234 + """
  235 + Return float value associated to Z dimension.
  236 + Return "" if not defined.
  237 + """
  238 + data = self.vtkgdcm_reader.GetOutput()\
  239 + .GetDimensions()[2]
  240 + if (data):
  241 + return float(data)
  242 + return ""
  243 +
  244 + def GetImageDataType(self):
  245 + """
  246 + Return image's pixel representation data type (string). This
  247 + might be:
  248 + - Float64
  249 + - Int8
  250 + - Int16
  251 + - Int32
  252 + - UInt16
  253 + Return "" otherwise.
  254 + """
  255 + repres = self._GetPixelRepresentation()
  256 +
  257 + bits = self._GetBitsAllocated()
  258 +
  259 + if not bits:
  260 + answer = ""
  261 + else:
  262 + answer = "UInt16"
  263 +
  264 + if bits == 8:
  265 + answer = "Int8"
  266 + elif bits == 16:
  267 + if repres:
  268 + answer = "Int16"
  269 + elif bits == 32:
  270 + answer = "Int32"
  271 + elif bits == 64:
  272 + answer = "Float64"
  273 +
  274 + return answer
  275 +
  276 + def GetImagePixelSpacingY(self):
  277 + """
  278 + Return spacing between adjacent pixels considerating y axis
  279 + (height). Values are usually floating point and represent mm.
  280 + Return "" if field is not defined.
  281 +
  282 + DICOM standard tag (0x0028, 0x0030) was used.
  283 + """
  284 + spacing = self.GetPixelSpacing()
  285 + if spacing:
  286 + return spacing[1]
  287 + return ""
  288 +
  289 + def GetImagePixelSpacingX(self):
  290 + """
  291 + Return spacing between adjacent pixels considerating x axis
  292 + (width). Values are usually floating point and represent mm.
  293 + Return "" if field is not defined.
  294 +
  295 + DICOM standard tag (0x0028, 0x0030) was used.
  296 + """
  297 +
  298 + spacing = self.GetPixelSpacing()
  299 + if spacing:
  300 + return spacing[0]
  301 + return ""
  302 +
  303 +
97 def GetAcquisitionDate(self): 304 def GetAcquisitionDate(self):
98 """ 305 """
99 Return string containing the acquisition date using the 306 Return string containing the acquisition date using the
@@ -177,52 +384,6 @@ class Parser(): @@ -177,52 +384,6 @@ class Parser():
177 return "" 384 return ""
178 385
179 386
180 -  
181 - def SetFileName(self, filename):  
182 - """  
183 - Set file name to be parsed given its filename (this should  
184 - include the full path of the file of interest).  
185 -  
186 - Return True/False if file could be read.  
187 - """  
188 - import os.path as path  
189 -  
190 -  
191 - filename = path.abspath(filename)  
192 -  
193 - if (sys.platform == 'win32'):  
194 - filename = filename.encode('latin-1')  
195 -  
196 - if path.isfile(filename):  
197 - # Several information can be acquired from DICOM using  
198 - # vtkgdcm.vtkGDCMImageReader.GetMedicalImageProperties()  
199 - # but some tags (such as spacing) can only be achieved  
200 - # with gdcm.ImageReader()  
201 - # used to parse DICOM files - similar to vtkDICOMParser  
202 - gdcm_reader = gdcm.ImageReader()  
203 - #filename = filename.encode('utf-8')  
204 -  
205 - gdcm_reader.SetFileName(filename)  
206 -  
207 - # if DICOM file is null vtkGDCMImageReader raises vtk  
208 - # exception  
209 - if not gdcm_reader.Read():  
210 - return False  
211 -  
212 - vtkgdcm_reader = self.vtkgdcm_reader  
213 - vtkgdcm_reader.SetFileName(filename)  
214 - vtkgdcm_reader.Update()  
215 -  
216 - self.filename = filename  
217 - self.gdcm_reader = gdcm_reader  
218 - self.vtkgdcm_reader = vtkgdcm_reader  
219 - return True  
220 -  
221 - return False  
222 -  
223 - def GetImageData(self):  
224 - return self.vtkgdcm_reader.GetOutput()  
225 -  
226 def GetImageWindowLevel(self, preset=WL_PRESET, multiple=WL_MULT): 387 def GetImageWindowLevel(self, preset=WL_PRESET, multiple=WL_MULT):
227 """ 388 """
228 Return image window center / level (related to brightness). 389 Return image window center / level (related to brightness).
@@ -377,33 +538,6 @@ class Parser(): @@ -377,33 +538,6 @@ class Parser():
377 return [eval(value) for value in data.split('\\')] 538 return [eval(value) for value in data.split('\\')]
378 return "" 539 return ""
379 540
380 - def GetImagePixelSpacingY(self):  
381 - """  
382 - Return spacing between adjacent pixels considerating y axis  
383 - (height). Values are usually floating point and represent mm.  
384 - Return "" if field is not defined.  
385 -  
386 - DICOM standard tag (0x0028, 0x0030) was used.  
387 - """  
388 - spacing = self.GetPixelSpacing()  
389 - if spacing:  
390 - return spacing[1]  
391 - return ""  
392 -  
393 - def GetImagePixelSpacingX(self):  
394 - """  
395 - Return spacing between adjacent pixels considerating x axis  
396 - (width). Values are usually floating point and represent mm.  
397 - Return "" if field is not defined.  
398 -  
399 - DICOM standard tag (0x0028, 0x0030) was used.  
400 - """  
401 -  
402 - spacing = self.GetPixelSpacing()  
403 - if spacing:  
404 - return spacing[0]  
405 - return ""  
406 -  
407 def GetPatientWeight(self): 541 def GetPatientWeight(self):
408 """ 542 """
409 Return patient's weight as a float value (kilograms). 543 Return patient's weight as a float value (kilograms).
@@ -1022,40 +1156,8 @@ class Parser(): @@ -1022,40 +1156,8 @@ class Parser():
1022 if (res[1]): 1156 if (res[1]):
1023 return int(res[1]) 1157 return int(res[1])
1024 return "" 1158 return ""
1025 -  
1026 - def GetImageDataType(self):  
1027 - """  
1028 - Return image's pixel representation data type (string). This  
1029 - might be:  
1030 - - Float64  
1031 - - Int8  
1032 - - Int16  
1033 - - Int32  
1034 - - UInt16  
1035 - Return "" otherwise.  
1036 - """  
1037 - repres = self._GetPixelRepresentation()  
1038 -  
1039 - bits = self._GetBitsAllocated()  
1040 -  
1041 - if not bits:  
1042 - answer = ""  
1043 - else:  
1044 - answer = "UInt16"  
1045 -  
1046 - if bits == 8:  
1047 - answer = "Int8"  
1048 - elif bits == 16:  
1049 - if repres:  
1050 - answer = "Int16"  
1051 - elif bits == 32:  
1052 - answer = "Int32"  
1053 - elif bits == 64:  
1054 - answer = "Float64"  
1055 -  
1056 - return answer  
1057 -  
1058 - 1159 +
  1160 +
1059 def GetPatientBirthDate(self): 1161 def GetPatientBirthDate(self):
1060 """ 1162 """
1061 Return string containing the patient's birth date using the 1163 Return string containing the patient's birth date using the
@@ -1186,43 +1288,6 @@ class Parser(): @@ -1186,43 +1288,6 @@ class Parser():
1186 return "" 1288 return ""
1187 1289
1188 1290
1189 - def GetDimensionX(self):  
1190 - """  
1191 - Return integer associated to X dimension. This is related  
1192 - to the number of columns on the image.  
1193 - Return "" if not defined.  
1194 - """  
1195 -  
1196 - data = self.vtkgdcm_reader.GetOutput()\  
1197 - .GetDimensions()[0]  
1198 - if (data):  
1199 - return int(data)  
1200 - return ""  
1201 -  
1202 - def GetDimensionY(self):  
1203 - """  
1204 - Return integer associated to Y dimension. This is related  
1205 - to the number of rows on the image.  
1206 - Return "" if not defined.  
1207 - """  
1208 - data = self.vtkgdcm_reader.GetOutput()\  
1209 - .GetDimensions()[1]  
1210 - if (data):  
1211 - return int(data)  
1212 - return ""  
1213 -  
1214 - def GetDimensionZ(self):  
1215 - """  
1216 - Return float value associated to Z dimension.  
1217 - Return "" if not defined.  
1218 - """  
1219 - data = self.vtkgdcm_reader.GetOutput()\  
1220 - .GetDimensions()[2]  
1221 - if (data):  
1222 - return float(data)  
1223 - return ""  
1224 -  
1225 -  
1226 def GetEquipmentXRayTubeCurrent(self): 1291 def GetEquipmentXRayTubeCurrent(self):
1227 """ 1292 """
1228 Return float value associated to the X-ray tube current 1293 Return float value associated to the X-ray tube current
@@ -1446,26 +1511,7 @@ class Parser(): @@ -1446,26 +1511,7 @@ class Parser():
1446 return str(res[1]) 1511 return str(res[1])
1447 return "" 1512 return ""
1448 1513
1449 - def GetImageOrientationLabel(self):  
1450 - """  
1451 - Return Label regarding the orientation of  
1452 - an image. (AXIAL, SAGITTAL, CORONAL,  
1453 - OBLIQUE or UNKNOWN)  
1454 - """  
1455 - img = self.gdcm_reader.GetImage()  
1456 - direc_cosines = img.GetDirectionCosines()  
1457 - orientation = gdcm.Orientation()  
1458 - try:  
1459 - type = orientation.GetType(tuple(direc_cosines))  
1460 - except TypeError:  
1461 - type = orientation.GetType(direc_cosines)  
1462 - label = orientation.GetLabel(type)  
1463 -  
1464 - if (label):  
1465 - return label  
1466 - else:  
1467 - return ""  
1468 - 1514 +
1469 def GetSeriesDescription(self): 1515 def GetSeriesDescription(self):
1470 """ 1516 """
1471 Return a string with a description of the series. 1517 Return a string with a description of the series.
@@ -1494,43 +1540,6 @@ class Parser(): @@ -1494,43 +1540,6 @@ class Parser():
1494 return self.__format_time(date) 1540 return self.__format_time(date)
1495 return "" 1541 return ""
1496 1542
1497 - def __format_time(self,value):  
1498 - sp1 = value.split(".")  
1499 - sp2 = value.split(":")  
1500 -  
1501 - if (len(sp1) == 2) and (len(sp2) == 3):  
1502 - new_value = str(sp2[0]+sp2[1]+  
1503 - str(int(float(sp2[2]))))  
1504 - data = time.strptime(new_value, "%H%M%S")  
1505 - elif (len(sp1) == 2):  
1506 - data = time.gmtime(float(value))  
1507 - elif (len(sp1) > 2):  
1508 - data = time.strptime(value, "%H.%M.%S")  
1509 - elif(len(sp2) > 1):  
1510 - data = time.strptime(value, "%H:%M:%S")  
1511 - else:  
1512 - data = time.strptime(value, "%H%M%S")  
1513 - return time.strftime("%H:%M:%S",data)  
1514 -  
1515 - def __format_date(self, value):  
1516 -  
1517 - sp1 = value.split(".")  
1518 - try:  
1519 -  
1520 - if (len(sp1) > 1):  
1521 - if (len(sp1[0]) <= 2):  
1522 - data = time.strptime(value, "%D.%M.%Y")  
1523 - else:  
1524 - data = time.strptime(value, "%Y.%M.%d")  
1525 - elif(len(value.split("//")) > 1):  
1526 - data = time.strptime(value, "%D/%M/%Y")  
1527 - else:  
1528 - data = time.strptime(value, "%Y%M%d")  
1529 - return time.strftime("%d/%M/%Y",data)  
1530 -  
1531 - except(ValueError):  
1532 - return ""  
1533 -  
1534 def GetAcquisitionTime(self): 1543 def GetAcquisitionTime(self):
1535 """ 1544 """
1536 Return the acquisition time. 1545 Return the acquisition time.