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 94 self.encoding = ""
95 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 304 def GetAcquisitionDate(self):
98 305 """
99 306 Return string containing the acquisition date using the
... ... @@ -177,52 +384,6 @@ class Parser():
177 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 387 def GetImageWindowLevel(self, preset=WL_PRESET, multiple=WL_MULT):
227 388 """
228 389 Return image window center / level (related to brightness).
... ... @@ -377,33 +538,6 @@ class Parser():
377 538 return [eval(value) for value in data.split('\\')]
378 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 541 def GetPatientWeight(self):
408 542 """
409 543 Return patient's weight as a float value (kilograms).
... ... @@ -1022,40 +1156,8 @@ class Parser():
1022 1156 if (res[1]):
1023 1157 return int(res[1])
1024 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 1161 def GetPatientBirthDate(self):
1060 1162 """
1061 1163 Return string containing the patient's birth date using the
... ... @@ -1186,43 +1288,6 @@ class Parser():
1186 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 1291 def GetEquipmentXRayTubeCurrent(self):
1227 1292 """
1228 1293 Return float value associated to the X-ray tube current
... ... @@ -1446,26 +1511,7 @@ class Parser():
1446 1511 return str(res[1])
1447 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 1515 def GetSeriesDescription(self):
1470 1516 """
1471 1517 Return a string with a description of the series.
... ... @@ -1494,43 +1540,6 @@ class Parser():
1494 1540 return self.__format_time(date)
1495 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 1543 def GetAcquisitionTime(self):
1535 1544 """
1536 1545 Return the acquisition time.
... ...