Commit 8e34d14af082b07bcfa681133fac291bb5b89a27

Authored by Paulo Henrique Junqueira Amorim
1 parent 6a79ee28

FIX: DICOM (to be attached) reconstruction is flattened. FIX #167

invesalius/data/imagedata_utils.py
... ... @@ -159,7 +159,13 @@ def BuildEditedImage(imagedata, points):
159 159 imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour)
160 160 imagedata.Update()
161 161  
162   - return imagedata
  162 + gauss = vtk.vtkImageGaussianSmooth()
  163 + gauss.SetInput(imagedata)
  164 + gauss.SetRadiusFactor(0.8)
  165 + gauss.Update()
  166 +
  167 + return gauss.GetOutput()
  168 +
163 169  
164 170 def Export(imagedata, filename, bin=False):
165 171 writer = vtk.vtkXMLImageDataWriter()
... ... @@ -214,9 +220,10 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf):
214 220 voi.Update()
215 221 return voi.GetOutput()
216 222  
217   -def CreateImageData(filelist, zspacing, size, bits):
  223 +def CreateImageData(filelist, zspacing, xyspacing,size,
  224 + bits, use_dcmspacing):
218 225 message = _("Generating multiplanar visualization...")
219   -
  226 +
220 227 if not const.VTK_WARNING:
221 228 log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt')
222 229 fow = vtk.vtkFileOutputWindow()
... ... @@ -250,7 +257,12 @@ def CreateImageData(filelist, zspacing, size, bits):
250 257 # The zpacing is a DicomGroup property, so we need to set it
251 258 imagedata = vtk.vtkImageData()
252 259 imagedata.DeepCopy(reader.GetOutput())
253   - spacing = imagedata.GetSpacing()
  260 + if (use_dcmspacing):
  261 + spacing = xyspacing
  262 + spacing[2] = zspacing
  263 + else:
  264 + spacing = imagedata.GetSpacing()
  265 +
254 266 imagedata.SetSpacing(spacing[0], spacing[1], zspacing)
255 267 else:
256 268  
... ... @@ -283,7 +295,12 @@ def CreateImageData(filelist, zspacing, size, bits):
283 295 # The zpacing is a DicomGroup property, so we need to set it
284 296 imagedata = vtk.vtkImageData()
285 297 imagedata.DeepCopy(appender.GetOutput())
286   - spacing = imagedata.GetSpacing()
  298 +
  299 + if (use_dcmspacing):
  300 + spacing = xyspacing
  301 + spacing[2] = zspacing
  302 + else:
  303 + spacing = imagedata.GetSpacing()
287 304  
288 305 imagedata.SetSpacing(spacing[0], spacing[1], zspacing)
289 306  
... ... @@ -305,7 +322,7 @@ class ImageCreator:
305 322  
306 323 def CreateImageData(self, filelist, zspacing, size, bits):
307 324 message = _("Generating multiplanar visualization...")
308   -
  325 +
309 326 if not const.VTK_WARNING:
310 327 log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt')
311 328 fow = vtk.vtkFileOutputWindow()
... ...
invesalius/reader/dicom.py
... ... @@ -93,7 +93,7 @@ class Parser():
93 93 self.filename = ""
94 94 self.encoding = ""
95 95 self.vtkgdcm_reader = vtkgdcm.vtkGDCMImageReader()
96   -
  96 +
97 97 def GetAcquisitionDate(self):
98 98 """
99 99 Return string containing the acquisition date using the
... ... @@ -141,7 +141,7 @@ class Parser():
141 141 value = 0
142 142 return value
143 143 return ""
144   -
  144 +
145 145 def GetAcquisitionTime(self):
146 146 """
147 147 Return string containing the acquisition time using the
... ... @@ -194,18 +194,18 @@ class Parser():
194 194  
195 195 # used to parse DICOM files - similar to vtkDICOMParser
196 196 gdcm_reader = gdcm.ImageReader()
197   -
  197 +
198 198 gdcm_reader.SetFileName(filename)
199   -
  199 +
200 200 # if DICOM file is null vtkGDCMImageReader raises vtk
201 201 # exception
202 202 if not gdcm_reader.Read():
203 203 return False
204   -
  204 +
205 205 vtkgdcm_reader = self.vtkgdcm_reader
206 206 vtkgdcm_reader.SetFileName(filename)
207 207 vtkgdcm_reader.Update()
208   -
  208 +
209 209 self.filename = filename
210 210 self.gdcm_reader = gdcm_reader
211 211 self.vtkgdcm_reader = vtkgdcm_reader
... ... @@ -278,7 +278,7 @@ class Parser():
278 278 # we choose only one. As this should be paired to "Window
279 279 # Width", it is set based on WL_PRESET
280 280 value_list = [float(value) for value in data.split('\\')]
281   -
  281 +
282 282 if multiple:
283 283 return str(value_list)
284 284 else:
... ... @@ -619,7 +619,7 @@ class Parser():
619 619 return data
620 620 return ""
621 621  
622   -
  622 +
623 623 def GetPhysicianReferringAddress(self):
624 624 """
625 625 Return string containing physician's address.
... ... @@ -730,7 +730,7 @@ class Parser():
730 730 if (data):
731 731 return data
732 732 return ""
733   -
  733 +
734 734 def GetStudyInstanceUID(self):
735 735 """
736 736 Return string containing Unique Identifier of the
... ... @@ -931,7 +931,7 @@ class Parser():
931 931 data = str(ds.GetDataElement(tag).GetValue())
932 932 if (data):
933 933 return data
934   -
  934 +
935 935 0x0008, 0x0081
936 936  
937 937 def GetInstitutionAddress(self):
... ... @@ -1399,7 +1399,7 @@ class Parser():
1399 1399 except TypeError:
1400 1400 type = orientation.GetType(direc_cosines)
1401 1401 label = orientation.GetLabel(type)
1402   -
  1402 +
1403 1403 if (label):
1404 1404 return label
1405 1405 else:
... ... @@ -1432,14 +1432,14 @@ class Parser():
1432 1432 if (date) and (date != 'None'):
1433 1433 return self.__format_time(date)
1434 1434 return ""
1435   -
  1435 +
1436 1436 def __format_time(self,value):
1437 1437 sp1 = value.split(".")
1438 1438 sp2 = value.split(":")
1439   -
  1439 +
1440 1440 if (len(sp1) == 2) and (len(sp2) == 3):
1441 1441 new_value = str(sp2[0]+sp2[1]+
1442   - str(int(float(sp2[2]))))
  1442 + str(int(float(sp2[2]))))
1443 1443 data = time.strptime(new_value, "%H%M%S")
1444 1444 elif (len(sp1) == 2):
1445 1445 data = time.gmtime(float(value))
... ... @@ -1448,14 +1448,14 @@ class Parser():
1448 1448 elif(len(sp2) > 1):
1449 1449 data = time.strptime(value, "%H:%M:%S")
1450 1450 else:
1451   - data = time.strptime(value, "%H%M%S")
  1451 + data = time.strptime(value, "%H%M%S")
1452 1452 return time.strftime("%H:%M:%S",data)
1453   -
  1453 +
1454 1454 def __format_date(self, value):
1455   -
  1455 +
1456 1456 sp1 = value.split(".")
1457 1457 try:
1458   -
  1458 +
1459 1459 if (len(sp1) > 1):
1460 1460 if (len(sp1[0]) <= 2):
1461 1461 data = time.strptime(value, "%D.%M.%Y")
... ... @@ -1466,10 +1466,10 @@ class Parser():
1466 1466 else:
1467 1467 data = time.strptime(value, "%Y%M%d")
1468 1468 return time.strftime("%d/%M/%Y",data)
1469   -
  1469 +
1470 1470 except(ValueError):
1471 1471 return ""
1472   -
  1472 +
1473 1473 def GetAcquisitionTime(self):
1474 1474 """
1475 1475 Return the acquisition time.
... ... @@ -1482,7 +1482,7 @@ class Parser():
1482 1482 if (data):
1483 1483 return self.__format_time(data)
1484 1484 return ""
1485   -
  1485 +
1486 1486 def GetSerieNumber(self):
1487 1487 """
1488 1488 Return the serie number
... ... @@ -1508,7 +1508,7 @@ class Parser():
1508 1508 if encoding != None:
1509 1509 #Problem with 0051 anonymized
1510 1510 if (encoding.split(":"))[0] == "Loaded":
1511   - return 'ISO_IR 100'
  1511 + return 'ISO_IR 100'
1512 1512 else:
1513 1513 return encoding
1514 1514 return 'ISO_IR 100'
... ... @@ -1544,7 +1544,7 @@ class DicomWriter:
1544 1544 """
1545 1545  
1546 1546 def __init__(self):
1547   -
  1547 +
1548 1548 self.reader = ""
1549 1549 self.anony = gdcm.Anonymizer()
1550 1550 self.path = ""
... ... @@ -1555,13 +1555,13 @@ class DicomWriter:
1555 1555 def SetFileName(self, path):
1556 1556 """
1557 1557 Set Dicom File Name
1558   - """
  1558 + """
1559 1559 self.path = path
1560 1560  
1561 1561 self.reader.SetFileName(path)
1562   -
  1562 +
1563 1563 if (self.reader.Read()):
1564   -
  1564 +
1565 1565 self.anony.SetFile(self.reader.GetFile())
1566 1566  
1567 1567  
... ... @@ -1571,11 +1571,11 @@ class DicomWriter:
1571 1571 Input vtkImageData
1572 1572 """
1573 1573 self.img_data = img_data
1574   -
1575   -
  1574 +
  1575 +
1576 1576 def __CreateNewDicom(self, img_data):
1577 1577 """
1578   - Create New Dicom File, input is
  1578 + Create New Dicom File, input is
1579 1579 a vtkImageData
1580 1580 """
1581 1581 new_dicom = self.new_dicom
... ... @@ -1583,13 +1583,13 @@ class DicomWriter:
1583 1583 new_dicom.SetInput(img_data)
1584 1584 new_dicom.Write()
1585 1585  
1586   -
  1586 +
1587 1587 def SaveIsNew(self, img_data):
1588 1588 """
1589   - Write Changes in Dicom file or Create
  1589 + Write Changes in Dicom file or Create
1590 1590 New Dicom File
1591 1591 """
1592   -
  1592 +
1593 1593 self.__CreateNewDicom(img_data)
1594 1594  
1595 1595 #Is necessary to create and add
... ... @@ -1597,19 +1597,19 @@ class DicomWriter:
1597 1597 self.SetFileName(self.path)
1598 1598 self.anony.SetFile(self.reader.GetFile())
1599 1599  
1600   -
  1600 +
1601 1601 def Save(self):
1602 1602  
1603 1603 reader = self.reader
1604   -
  1604 +
1605 1605 writer = gdcm.Writer()
1606 1606 writer.SetFile(self.reader.GetFile())
1607 1607 writer.SetFileName(self.path)
1608   - writer.Write()
1609   -
  1608 + writer.Write()
  1609 +
1610 1610  
1611 1611 def SetPatientName(self, patient):
1612   - """
  1612 + """
1613 1613 Set Patient Name requeries string type
1614 1614 """
1615 1615 self.anony.Replace(gdcm.Tag(0x0010,0x0010), \
... ... @@ -1617,73 +1617,73 @@ class DicomWriter:
1617 1617  
1618 1618  
1619 1619 def SetImageThickness(self, thickness):
1620   - """
  1620 + """
1621 1621 Set thickness value requeries float type
1622 1622 """
1623 1623 self.anony.Replace(gdcm.Tag(0x0018,0x0050), \
1624 1624 str(thickness))
1625   -
1626   -
  1625 +
  1626 +
1627 1627 def SetImageSeriesNumber(self, number):
1628   - """
  1628 + """
1629 1629 Set Serie Number value requeries int type
1630 1630 """
1631 1631 self.anony.Replace(gdcm.Tag(0x0020,0x0011), \
1632 1632 str(number))
1633   -
1634   -
  1633 +
  1634 +
1635 1635 def SetImageNumber(self, number):
1636   - """
  1636 + """
1637 1637 Set image Number value requeries int type
1638 1638 """
1639 1639 self.anony.Replace(gdcm.Tag(0x0020,0x0013),
1640 1640 str(number))
1641   -
1642   -
  1641 +
  1642 +
1643 1643 def SetImageLocation(self, location):
1644   - """
  1644 + """
1645 1645 Set slice location value requeries float type
1646 1646 """
1647 1647 self.anony.Replace(gdcm.Tag(0x0020,0x1041),\
1648 1648 str(number))
1649   -
1650   -
  1649 +
  1650 +
1651 1651 def SetImagePosition(self, position):
1652   - """
1653   - Set slice position value requeries list
  1652 + """
  1653 + Set slice position value requeries list
1654 1654 with three values x, y and z
1655 1655 """
1656 1656 self.anony.Replace(gdcm.Tag(0x0020,0x0032), \
1657 1657 str(position[0]) + \
1658 1658 "\\" + str(position[1]) + \
1659 1659 "\\" + str(position[2]))
1660   -
1661   -
  1660 +
  1661 +
1662 1662 def SetAcquisitionModality(self, modality):
1663   - """
  1663 + """
1664 1664 Set modality study CT or RM
1665 1665 """
1666 1666 self.anony.Replace(gdcm.Tag(0x0008,0x0060), \
1667 1667 str(modality))
1668   -
1669   -
  1668 +
  1669 +
1670 1670 def SetPixelSpacing(self, spacing):
1671 1671 """
1672 1672 Set pixel spacing x and y
1673 1673 """
1674 1674 self.anony.Replace(gdcm.Tag(0x0028,0x0030), \
1675 1675 str(spacing))
1676   -
1677   -
  1676 +
  1677 +
1678 1678 def SetInstitutionName(self, institution):
1679 1679 """
1680 1680 Set institution name
1681 1681 """
1682 1682 self.anony.Replace(gdcm.Tag(0x0008, 0x0080), \
1683 1683 str(institution))
1684   -
1685 1684  
1686   -
  1685 +
  1686 +
1687 1687  
1688 1688  
1689 1689  
... ... @@ -1808,11 +1808,11 @@ class Patient(object):
1808 1808 self.name = parser.GetPatientName()
1809 1809 self.id = parser.GetPatientID()
1810 1810 self.age = parser.GetPatientAge()
1811   - self.birthdate = parser.GetPatientBirthDate()
  1811 + self.birthdate = parser.GetPatientBirthDate()
1812 1812 self.gender = parser.GetPatientGender()
1813 1813 self.physician = parser.GetPhysicianReferringName()
1814   -
1815   -
  1814 +
  1815 +
1816 1816 class Acquisition(object):
1817 1817  
1818 1818 def __init__(self):
... ... @@ -1832,7 +1832,8 @@ class Acquisition(object):
1832 1832 self.time = parser.GetAcquisitionTime()
1833 1833 self.protocol_name = parser.GetProtocolName()
1834 1834 self.serie_number = parser.GetSerieNumber()
1835   -
  1835 + self.sop_class_uid = parser.GetSOPClassUID()
  1836 +
1836 1837 class Image(object):
1837 1838  
1838 1839 def __init__(self):
... ... @@ -1841,11 +1842,11 @@ class Image(object):
1841 1842 def SetParser(self, parser):
1842 1843 self.level = parser.GetImageWindowLevel()
1843 1844 self.window = parser.GetImageWindowWidth()
1844   -
  1845 +
1845 1846 self.position = parser.GetImagePosition()
1846 1847 if not (self.position):
1847 1848 self.position = [1, 1, 1]
1848   -
  1849 +
1849 1850 self.number = parser.GetImageNumber()
1850 1851 self.spacing = spacing = parser.GetPixelSpacing()
1851 1852 self.orientation_label = parser.GetImageOrientationLabel()
... ... @@ -1855,18 +1856,18 @@ class Image(object):
1855 1856 self.size = (parser.GetDimensionX(), parser.GetDimensionY())
1856 1857 self.imagedata = parser.GetImageData()
1857 1858 self.bits_allocad = parser._GetBitsAllocated()
1858   -
  1859 +
1859 1860 if (parser.GetImageThickness()):
1860 1861 try:
1861 1862 spacing.append(parser.GetImageThickness())
1862 1863 except(AttributeError):
1863   - spacing = [1, 1, 1]
  1864 + spacing = [1, 1, 1]
1864 1865 else:
1865 1866 try:
1866 1867 spacing.append(1.5)
1867 1868 except(AttributeError):
1868 1869 spacing = [1, 1, 1]
1869   -
  1870 +
1870 1871 spacing[0] = round(spacing[0],2)
1871 1872 spacing[1] = round(spacing[1],2)
1872 1873 spacing[2] = round(spacing[2],2)
... ...