Commit afdb3ce1763e0e37fb385d31236baefa4de23fcd

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent 9a7e323e
Exists in master

Open Multiframe dicom (#133)

* Loading multiframe dicom using the import gui

* Showing multiframe thumbnails

* Showing the thumbnail in the slice viewer from preview

* Set slide to the number of slices or numberofframes
invesalius/control.py
@@ -404,8 +404,9 @@ class Controller(): @@ -404,8 +404,9 @@ class Controller():
404 Publisher.sendMessage('Begin busy cursor') 404 Publisher.sendMessage('Begin busy cursor')
405 else: 405 else:
406 #Is None if user canceled the load 406 #Is None if user canceled the load
407 - self.progress_dialog.Close()  
408 - self.progress_dialog = None 407 + if self.progress_dialog is not None:
  408 + self.progress_dialog.Close()
  409 + self.progress_dialog = None
409 410
410 def OnLoadImportPanel(self, evt): 411 def OnLoadImportPanel(self, evt):
411 patient_series = evt.data 412 patient_series = evt.data
@@ -795,47 +796,53 @@ class Controller(): @@ -795,47 +796,53 @@ class Controller():
795 xyspacing = dicom.image.spacing 796 xyspacing = dicom.image.spacing
796 orientation = dicom.image.orientation_label 797 orientation = dicom.image.orientation_label
797 798
  799 + wl = float(dicom.image.level)
  800 + ww = float(dicom.image.window)
  801 +
798 if sop_class_uid == '1.2.840.10008.5.1.4.1.1.7': #Secondary Capture Image Storage 802 if sop_class_uid == '1.2.840.10008.5.1.4.1.1.7': #Secondary Capture Image Storage
799 use_dcmspacing = 1 803 use_dcmspacing = 1
800 else: 804 else:
801 use_dcmspacing = 0 805 use_dcmspacing = 0
802 806
803 imagedata = None 807 imagedata = None
804 -  
805 - sx, sy = size  
806 - n_slices = len(filelist)  
807 - resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8)  
808 -  
809 - if resolution_percentage < 1.0 and gui:  
810 - re_dialog = dialog.ResizeImageDialog()  
811 - re_dialog.SetValue(int(resolution_percentage*100))  
812 - re_dialog_value = re_dialog.ShowModal()  
813 - re_dialog.Close()  
814 -  
815 - if re_dialog_value == wx.ID_OK:  
816 - percentage = re_dialog.GetValue()  
817 - resolution_percentage = percentage / 100.0  
818 - else:  
819 - return  
820 808
821 - xyspacing = xyspacing[0] / resolution_percentage, xyspacing[1] / resolution_percentage  
822 -  
823 -  
824 - wl = float(dicom.image.level)  
825 - ww = float(dicom.image.window)  
826 - self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size,  
827 - orientation, resolution_percentage) 809 + if dicom.image.number_of_frames == 1:
  810 + sx, sy = size
  811 + n_slices = len(filelist)
  812 + resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8)
  813 +
  814 + if resolution_percentage < 1.0 and gui:
  815 + re_dialog = dialog.ResizeImageDialog()
  816 + re_dialog.SetValue(int(resolution_percentage*100))
  817 + re_dialog_value = re_dialog.ShowModal()
  818 + re_dialog.Close()
  819 +
  820 + if re_dialog_value == wx.ID_OK:
  821 + percentage = re_dialog.GetValue()
  822 + resolution_percentage = percentage / 100.0
  823 + else:
  824 + return
  825 +
  826 + xyspacing = xyspacing[0] / resolution_percentage, xyspacing[1] / resolution_percentage
  827 +
  828 + self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size,
  829 + orientation, resolution_percentage)
  830 +
  831 + print xyspacing, zspacing
  832 + if orientation == 'AXIAL':
  833 + spacing = xyspacing[0], xyspacing[1], zspacing
  834 + elif orientation == 'CORONAL':
  835 + spacing = xyspacing[0], zspacing, xyspacing[1]
  836 + elif orientation == 'SAGITTAL':
  837 + spacing = zspacing, xyspacing[1], xyspacing[0]
  838 + else:
  839 + self.matrix, spacing, scalar_range, self.filename = image_utils.dcmmf2memmap(filelist[0], orientation)
828 840
829 self.Slice = sl.Slice() 841 self.Slice = sl.Slice()
830 self.Slice.matrix = self.matrix 842 self.Slice.matrix = self.matrix
831 self.Slice.matrix_filename = self.filename 843 self.Slice.matrix_filename = self.filename
832 844
833 - if orientation == 'AXIAL':  
834 - self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing  
835 - elif orientation == 'CORONAL':  
836 - self.Slice.spacing = xyspacing[0], zspacing, xyspacing[1]  
837 - elif orientation == 'SAGITTAL':  
838 - self.Slice.spacing = zspacing, xyspacing[1], xyspacing[0] 845 + self.Slice.spacing = spacing
839 846
840 # 1(a): Fix gantry tilt, if any 847 # 1(a): Fix gantry tilt, if any
841 tilt_value = dicom.acquisition.tilt 848 tilt_value = dicom.acquisition.tilt
invesalius/data/imagedata_utils.py
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 19
20 import math 20 import math
21 import os 21 import os
  22 +import sys
22 import tempfile 23 import tempfile
23 24
24 import gdcm 25 import gdcm
@@ -35,6 +36,16 @@ from invesalius.data import vtk_utils as vtk_utils @@ -35,6 +36,16 @@ from invesalius.data import vtk_utils as vtk_utils
35 import invesalius.reader.bitmap_reader as bitmap_reader 36 import invesalius.reader.bitmap_reader as bitmap_reader
36 import invesalius.utils as utils 37 import invesalius.utils as utils
37 import invesalius.data.converters as converters 38 import invesalius.data.converters as converters
  39 +
  40 +if sys.platform == 'win32':
  41 + try:
  42 + import win32api
  43 + _has_win32api = True
  44 + except ImportError:
  45 + _has_win32api = False
  46 +else:
  47 + _has_win32api = False
  48 +
38 # TODO: Test cases which are originally in sagittal/coronal orientation 49 # TODO: Test cases which are originally in sagittal/coronal orientation
39 # and have gantry 50 # and have gantry
40 51
@@ -246,11 +257,79 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf): @@ -246,11 +257,79 @@ def ExtractVOI(imagedata,xi,xf,yi,yf,zi,zf):
246 """ 257 """
247 voi = vtk.vtkExtractVOI() 258 voi = vtk.vtkExtractVOI()
248 voi.SetVOI(xi,xf,yi,yf,zi,zf) 259 voi.SetVOI(xi,xf,yi,yf,zi,zf)
249 - voi.SetInput(imagedata) 260 + voi.SetInputData(imagedata)
250 voi.SetSampleRate(1, 1, 1) 261 voi.SetSampleRate(1, 1, 1)
251 voi.Update() 262 voi.Update()
252 return voi.GetOutput() 263 return voi.GetOutput()
253 264
  265 +
  266 +def create_dicom_thumbnails(filename, window=None, level=None):
  267 + rvtk = vtkgdcm.vtkGDCMImageReader()
  268 + rvtk.SetFileName(filename)
  269 + rvtk.Update()
  270 +
  271 + img = rvtk.GetOutput()
  272 + if window is None or level is None:
  273 + _min, _max = img.GetScalarRange()
  274 + window = _max - _min
  275 + level = _min + window / 2
  276 +
  277 + dx, dy, dz = img.GetDimensions()
  278 +
  279 + if dz > 1:
  280 + thumbnail_paths = []
  281 + for i in xrange(dz):
  282 + img_slice = ExtractVOI(img, 0, dx-1, 0, dy-1, i, i+1)
  283 +
  284 + colorer = vtk.vtkImageMapToWindowLevelColors()
  285 + colorer.SetInputData(img_slice)
  286 + colorer.SetWindow(window)
  287 + colorer.SetLevel(level)
  288 + colorer.SetOutputFormatToRGB()
  289 + colorer.Update()
  290 +
  291 + resample = vtk.vtkImageResample()
  292 + resample.SetInputData(colorer.GetOutput())
  293 + resample.SetAxisMagnificationFactor ( 0, 0.25 )
  294 + resample.SetAxisMagnificationFactor ( 1, 0.25 )
  295 + resample.SetAxisMagnificationFactor ( 2, 1 )
  296 + resample.Update()
  297 +
  298 + thumbnail_path = tempfile.mktemp()
  299 +
  300 + write_png = vtk.vtkPNGWriter()
  301 + write_png.SetInputData(resample.GetOutput())
  302 + write_png.SetFileName(thumbnail_path)
  303 + write_png.Write()
  304 +
  305 + thumbnail_paths.append(thumbnail_path)
  306 +
  307 + return thumbnail_paths
  308 + else:
  309 + colorer = vtk.vtkImageMapToWindowLevelColors()
  310 + colorer.SetInputData(img)
  311 + colorer.SetWindow(window)
  312 + colorer.SetLevel(level)
  313 + colorer.SetOutputFormatToRGB()
  314 + colorer.Update()
  315 +
  316 + resample = vtk.vtkImageResample()
  317 + resample.SetInputData(colorer.GetOutput())
  318 + resample.SetAxisMagnificationFactor ( 0, 0.25 )
  319 + resample.SetAxisMagnificationFactor ( 1, 0.25 )
  320 + resample.SetAxisMagnificationFactor ( 2, 1 )
  321 + resample.Update()
  322 +
  323 + thumbnail_path = tempfile.mktemp()
  324 +
  325 + write_png = vtk.vtkPNGWriter()
  326 + write_png.SetInputData(resample.GetOutput())
  327 + write_png.SetFileName(thumbnail_path)
  328 + write_png.Write()
  329 +
  330 + return thumbnail_path
  331 +
  332 +
254 def CreateImageData(filelist, zspacing, xyspacing,size, 333 def CreateImageData(filelist, zspacing, xyspacing,size,
255 bits, use_dcmspacing): 334 bits, use_dcmspacing):
256 message = _("Generating multiplanar visualization...") 335 message = _("Generating multiplanar visualization...")
@@ -587,6 +666,29 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage): @@ -587,6 +666,29 @@ def dcm2memmap(files, slice_size, orientation, resolution_percentage):
587 return matrix, scalar_range, temp_file 666 return matrix, scalar_range, temp_file
588 667
589 668
  669 +def dcmmf2memmap(dcm_file, orientation):
  670 + r = vtkgdcm.vtkGDCMImageReader()
  671 + r.SetFileName(dcm_file)
  672 + r.Update()
  673 +
  674 + temp_file = tempfile.mktemp()
  675 +
  676 + o = r.GetOutput()
  677 + x, y, z = o.GetDimensions()
  678 + spacing = o.GetSpacing()
  679 +
  680 + matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=(z, y, x))
  681 +
  682 + d = numpy_support.vtk_to_numpy(o.GetPointData().GetScalars())
  683 + d.shape = z, y, x
  684 + matrix[:] = d
  685 + matrix.flush()
  686 +
  687 + scalar_range = matrix.min(), matrix.max()
  688 +
  689 + return matrix, spacing, scalar_range, temp_file
  690 +
  691 +
590 def img2memmap(group): 692 def img2memmap(group):
591 """ 693 """
592 From a nibabel image data creates a memmap file in the temp folder and 694 From a nibabel image data creates a memmap file in the temp folder and
invesalius/data/vtk_utils.py
@@ -52,6 +52,8 @@ def ShowProgress(number_of_filters = 1, @@ -52,6 +52,8 @@ def ShowProgress(number_of_filters = 1,
52 52
53 # when the pipeline is larger than 1, we have to consider this object 53 # when the pipeline is larger than 1, we have to consider this object
54 # percentage 54 # percentage
  55 + if number_of_filters < 1:
  56 + number_of_filters = 1
55 ratio = (100.0 / number_of_filters) 57 ratio = (100.0 / number_of_filters)
56 58
57 def UpdateProgress(obj, label=""): 59 def UpdateProgress(obj, label=""):
invesalius/gui/dicom_preview_panel.py
@@ -115,7 +115,7 @@ class DicomInfo(object): @@ -115,7 +115,7 @@ class DicomInfo(object):
115 """ 115 """
116 Keep the informations and the image used by preview. 116 Keep the informations and the image used by preview.
117 """ 117 """
118 - def __init__(self, id, dicom, title, subtitle): 118 + def __init__(self, id, dicom, title, subtitle, n=0):
119 self.id = id 119 self.id = id
120 self.dicom = dicom 120 self.dicom = dicom
121 self.title = title 121 self.title = title
@@ -123,12 +123,15 @@ class DicomInfo(object): @@ -123,12 +123,15 @@ class DicomInfo(object):
123 self._preview = None 123 self._preview = None
124 self.selected = False 124 self.selected = False
125 self.filename = "" 125 self.filename = ""
  126 + self._slice = n
126 127
127 @property 128 @property
128 def preview(self): 129 def preview(self):
129 -  
130 if not self._preview: 130 if not self._preview:
131 - bmp = wx.Bitmap(self.dicom.image.thumbnail_path, wx.BITMAP_TYPE_PNG) 131 + if isinstance(self.dicom.image.thumbnail_path, list):
  132 + bmp = wx.Bitmap(self.dicom.image.thumbnail_path[self._slice], wx.BITMAP_TYPE_PNG)
  133 + else:
  134 + bmp = wx.Bitmap(self.dicom.image.thumbnail_path, wx.BITMAP_TYPE_PNG)
132 self._preview = bmp.ConvertToImage() 135 self._preview = bmp.ConvertToImage()
133 return self._preview 136 return self._preview
134 137
@@ -539,11 +542,22 @@ class DicomPreviewSlice(wx.Panel): @@ -539,11 +542,22 @@ class DicomPreviewSlice(wx.Panel):
539 dicom_files = group.GetHandSortedList() 542 dicom_files = group.GetHandSortedList()
540 n = 0 543 n = 0
541 for dicom in dicom_files: 544 for dicom in dicom_files:
542 - info = DicomInfo(n, dicom,  
543 - _("Image %d") % (dicom.image.number),  
544 - "%.2f" % (dicom.image.position[2]))  
545 - self.files.append(info)  
546 - n+=1 545 + if isinstance(dicom.image.thumbnail_path, list):
  546 + _slice = 0
  547 + for thumbnail in dicom.image.thumbnail_path:
  548 + print thumbnail
  549 + info = DicomInfo(n, dicom,
  550 + _("Image %d") % (n),
  551 + "%.2f" % (dicom.image.position[2]), _slice)
  552 + self.files.append(info)
  553 + n+=1
  554 + _slice += 1
  555 + else:
  556 + info = DicomInfo(n, dicom,
  557 + _("Image %d") % (dicom.image.number),
  558 + "%.2f" % (dicom.image.position[2]))
  559 + self.files.append(info)
  560 + n+=1
547 561
548 scroll_range = len(self.files)/NCOLS 562 scroll_range = len(self.files)/NCOLS
549 if scroll_range * NCOLS < len(self.files): 563 if scroll_range * NCOLS < len(self.files):
@@ -560,12 +574,23 @@ class DicomPreviewSlice(wx.Panel): @@ -560,12 +574,23 @@ class DicomPreviewSlice(wx.Panel):
560 dicom_files = group.GetHandSortedList() 574 dicom_files = group.GetHandSortedList()
561 n = 0 575 n = 0
562 for dicom in dicom_files: 576 for dicom in dicom_files:
563 - info = DicomInfo(n, dicom,  
564 - _("Image %d") % (dicom.image.number),  
565 - "%.2f" % (dicom.image.position[2]),  
566 - )  
567 - self.files.append(info)  
568 - n+=1 577 + if isinstance(dicom.image.thumbnail_path, list):
  578 + _slice = 0
  579 + for thumbnail in dicom.image.thumbnail_path:
  580 + print thumbnail
  581 + info = DicomInfo(n, dicom,
  582 + _("Image %d") % int(n),
  583 + "%.2f" % (dicom.image.position[2]), _slice)
  584 + self.files.append(info)
  585 + n+=1
  586 + _slice += 1
  587 + else:
  588 + info = DicomInfo(n, dicom,
  589 + _("Image %d") % int(dicom.image.number),
  590 + "%.2f" % (dicom.image.position[2]),
  591 + )
  592 + self.files.append(info)
  593 + n+=1
569 594
570 scroll_range = len(self.files)/NCOLS 595 scroll_range = len(self.files)/NCOLS
571 if scroll_range * NCOLS < len(self.files): 596 if scroll_range * NCOLS < len(self.files):
@@ -803,14 +828,20 @@ class SingleImagePreview(wx.Panel): @@ -803,14 +828,20 @@ class SingleImagePreview(wx.Panel):
803 def SetDicomGroup(self, group): 828 def SetDicomGroup(self, group):
804 self.dicom_list = group.GetHandSortedList() 829 self.dicom_list = group.GetHandSortedList()
805 self.current_index = 0 830 self.current_index = 0
806 - self.nimages = len(self.dicom_list) 831 + if len(self.dicom_list) > 1:
  832 + self.nimages = len(self.dicom_list)
  833 + else:
  834 + self.nimages = self.dicom_list[0].image.number_of_frames
807 # GUI 835 # GUI
808 self.slider.SetMax(self.nimages-1) 836 self.slider.SetMax(self.nimages-1)
809 self.slider.SetValue(0) 837 self.slider.SetValue(0)
810 self.ShowSlice() 838 self.ShowSlice()
811 839
812 def ShowSlice(self, index = 0): 840 def ShowSlice(self, index = 0):
813 - dicom = self.dicom_list[index] 841 + try:
  842 + dicom = self.dicom_list[index]
  843 + except IndexError:
  844 + dicom = self.dicom_list[0]
814 845
815 # UPDATE GUI 846 # UPDATE GUI
816 ## Text related to size 847 ## Text related to size
@@ -845,28 +876,41 @@ class SingleImagePreview(wx.Panel): @@ -845,28 +876,41 @@ class SingleImagePreview(wx.Panel):
845 dicom.acquisition.time) 876 dicom.acquisition.time)
846 self.text_acquisition.SetValue(value) 877 self.text_acquisition.SetValue(value)
847 878
848 - rdicom = vtkgdcm.vtkGDCMImageReader()  
849 - if _has_win32api:  
850 - rdicom.SetFileName(win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE)) 879 + if isinstance(dicom.image.thumbnail_path, list):
  880 + reader = vtk.vtkPNGReader()
  881 + if _has_win32api:
  882 + reader.SetFileName(win32api.GetShortPathName(dicom.image.thumbnail_path[index]).encode(const.FS_ENCODE))
  883 + else:
  884 + reader.SetFileName(dicom.image.thumbnail_path[index])
  885 + reader.Update()
  886 +
  887 + image = reader.GetOutput()
  888 +
851 else: 889 else:
852 - rdicom.SetFileName(dicom.image.file)  
853 - rdicom.Update()  
854 -  
855 - # ADJUST CONTRAST  
856 - window_level = dicom.image.level  
857 - window_width = dicom.image.window  
858 - colorer = vtk.vtkImageMapToWindowLevelColors()  
859 - colorer.SetInputConnection(rdicom.GetOutputPort())  
860 - colorer.SetWindow(float(window_width))  
861 - colorer.SetLevel(float(window_level))  
862 - colorer.Update() 890 + rdicom = vtkgdcm.vtkGDCMImageReader()
  891 + if _has_win32api:
  892 + rdicom.SetFileName(win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE))
  893 + else:
  894 + rdicom.SetFileName(dicom.image.file)
  895 + rdicom.Update()
  896 +
  897 + # ADJUST CONTRAST
  898 + window_level = dicom.image.level
  899 + window_width = dicom.image.window
  900 + colorer = vtk.vtkImageMapToWindowLevelColors()
  901 + colorer.SetInputConnection(rdicom.GetOutputPort())
  902 + colorer.SetWindow(float(window_width))
  903 + colorer.SetLevel(float(window_level))
  904 + colorer.Update()
  905 +
  906 + image = colorer.GetOutput()
863 907
864 if self.actor is None: 908 if self.actor is None:
865 self.actor = vtk.vtkImageActor() 909 self.actor = vtk.vtkImageActor()
866 self.renderer.AddActor(self.actor) 910 self.renderer.AddActor(self.actor)
867 911
868 # PLOT IMAGE INTO VIEWER 912 # PLOT IMAGE INTO VIEWER
869 - self.actor.SetInputData(colorer.GetOutput()) 913 + self.actor.SetInputData(image)
870 self.renderer.ResetCamera() 914 self.renderer.ResetCamera()
871 self.interactor.Render() 915 self.interactor.Render()
872 916
invesalius/reader/dicom.py
@@ -1154,8 +1154,20 @@ class Parser(): @@ -1154,8 +1154,20 @@ class Parser():
1154 if (data): 1154 if (data):
1155 return int(data) 1155 return int(data)
1156 return "" 1156 return ""
1157 -  
1158 - 1157 +
  1158 + def GetNumberOfFrames(self):
  1159 + """
  1160 + Number of frames in a multi-frame image.
  1161 +
  1162 + DICOM standard tag (0x0028, 0x0008) was used.
  1163 + """
  1164 + try:
  1165 + data = self.data_image[str(0x028)][str(0x0008)]
  1166 + except KeyError:
  1167 + return 1
  1168 + return int(data)
  1169 +
  1170 +
1159 def GetPatientBirthDate(self): 1171 def GetPatientBirthDate(self):
1160 """ 1172 """
1161 Return string containing the patient's birth date using the 1173 Return string containing the patient's birth date using the
@@ -1498,11 +1510,11 @@ class Parser(): @@ -1498,11 +1510,11 @@ class Parser():
1498 try: 1510 try:
1499 data = self.data_image[str(0x0020)][str(0x0013)] 1511 data = self.data_image[str(0x0020)][str(0x0013)]
1500 except(KeyError): 1512 except(KeyError):
1501 - return "" 1513 + return 0
1502 1514
1503 if (data): 1515 if (data):
1504 return int(data) 1516 return int(data)
1505 - return "" 1517 + return 0
1506 1518
1507 def GetStudyDescription(self): 1519 def GetStudyDescription(self):
1508 """ 1520 """
@@ -1954,6 +1966,8 @@ class Image(object): @@ -1954,6 +1966,8 @@ class Image(object):
1954 self.bits_allocad = parser._GetBitsAllocated() 1966 self.bits_allocad = parser._GetBitsAllocated()
1955 self.thumbnail_path = parser.thumbnail_path 1967 self.thumbnail_path = parser.thumbnail_path
1956 1968
  1969 + self.number_of_frames = parser.GetNumberOfFrames()
  1970 +
1957 if (parser.GetImageThickness()): 1971 if (parser.GetImageThickness()):
1958 try: 1972 try:
1959 spacing.append(parser.GetImageThickness()) 1973 spacing.append(parser.GetImageThickness())
invesalius/reader/dicom_grouper.py
@@ -94,22 +94,22 @@ class DicomGroup: @@ -94,22 +94,22 @@ class DicomGroup:
94 if not self.dicom: 94 if not self.dicom:
95 self.dicom = dicom 95 self.dicom = dicom
96 96
97 - pos = tuple(dicom.image.position)  
98 - 97 + pos = tuple(dicom.image.position)
  98 +
99 #Case to test: \other\higroma 99 #Case to test: \other\higroma
100 - #condition created, if any dicom with the same 100 + #condition created, if any dicom with the same
101 #position, but 3D, leaving the same series. 101 #position, but 3D, leaving the same series.
102 if not "DERIVED" in dicom.image.type: 102 if not "DERIVED" in dicom.image.type:
103 #if any dicom with the same position 103 #if any dicom with the same position
104 if pos not in self.slices_dict.keys(): 104 if pos not in self.slices_dict.keys():
105 self.slices_dict[pos] = dicom 105 self.slices_dict[pos] = dicom
106 - self.nslices += 1 106 + self.nslices += dicom.image.number_of_frames
107 return True 107 return True
108 else: 108 else:
109 return False 109 return False
110 else: 110 else:
111 self.slices_dict[dicom.image.number] = dicom 111 self.slices_dict[dicom.image.number] = dicom
112 - self.nslices += 1 112 + self.nslices += dicom.image.number_of_frames
113 return True 113 return True
114 114
115 def GetList(self): 115 def GetList(self):
invesalius/reader/dicom_reader.py
@@ -36,6 +36,8 @@ import invesalius.session as session @@ -36,6 +36,8 @@ import invesalius.session as session
36 import glob 36 import glob
37 import invesalius.utils as utils 37 import invesalius.utils as utils
38 38
  39 +from invesalius.data import imagedata_utils
  40 +
39 import plistlib 41 import plistlib
40 42
41 if sys.platform == 'win32': 43 if sys.platform == 'win32':
@@ -187,45 +189,22 @@ class LoadDicom: @@ -187,45 +189,22 @@ class LoadDicom:
187 189
188 190
189 # -------------- To Create DICOM Thumbnail ----------- 191 # -------------- To Create DICOM Thumbnail -----------
190 - rvtk = vtkgdcm.vtkGDCMImageReader()  
191 192
192 - if _has_win32api:  
193 - print 'dicom', win32api.GetShortPathName(self.filepath)  
194 - rvtk.SetFileName(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE))  
195 - else:  
196 - rvtk.SetFileName(self.filepath)  
197 - rvtk.Update()  
198 - 193 +
199 try: 194 try:
200 data = data_dict[str(0x028)][str(0x1050)] 195 data = data_dict[str(0x028)][str(0x1050)]
201 level = [float(value) for value in data.split('\\')][0] 196 level = [float(value) for value in data.split('\\')][0]
202 data = data_dict[str(0x028)][str(0x1051)] 197 data = data_dict[str(0x028)][str(0x1051)]
203 window = [float(value) for value in data.split('\\')][0] 198 window = [float(value) for value in data.split('\\')][0]
204 except(KeyError, ValueError): 199 except(KeyError, ValueError):
205 - level = 300.0  
206 - window = 2000.0  
207 -  
208 - colorer = vtk.vtkImageMapToWindowLevelColors()  
209 - colorer.SetInputConnection(rvtk.GetOutputPort())  
210 - colorer.SetWindow(float(window))  
211 - colorer.SetLevel(float(level))  
212 - colorer.SetOutputFormatToRGB()  
213 - colorer.Update()  
214 -  
215 - resample = vtk.vtkImageResample()  
216 - resample.SetInputConnection(colorer.GetOutputPort())  
217 - resample.SetAxisMagnificationFactor ( 0, 0.25 )  
218 - resample.SetAxisMagnificationFactor ( 1, 0.25 )  
219 - resample.SetAxisMagnificationFactor ( 2, 1 )  
220 - resample.Update()  
221 -  
222 - thumbnail_path = tempfile.mktemp()  
223 -  
224 - write_png = vtk.vtkPNGWriter()  
225 - write_png.SetInputConnection(resample.GetOutputPort())  
226 - write_png.SetFileName(thumbnail_path)  
227 - write_png.Write()  
228 - 200 + level = None
  201 + window = None
  202 +
  203 + if _has_win32api:
  204 + thumbnail_path = imagedata_utils.create_dicom_thumbnails(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE), window, level)
  205 + else:
  206 + thumbnail_path = imagedata_utils.create_dicom_thumbnails(self.filepath, window, level)
  207 +
229 #------ Verify the orientation -------------------------------- 208 #------ Verify the orientation --------------------------------
230 209
231 img = reader.GetImage() 210 img = reader.GetImage()
@@ -362,12 +341,14 @@ class ProgressDicomReader: @@ -362,12 +341,14 @@ class ProgressDicomReader:
362 341
363 y = yGetDicomGroups(path, recursive) 342 y = yGetDicomGroups(path, recursive)
364 for value_progress in y: 343 for value_progress in y:
  344 + print ">>>>", value_progress
365 if not self.running: 345 if not self.running:
366 break 346 break
367 if isinstance(value_progress, tuple): 347 if isinstance(value_progress, tuple):
368 self.UpdateLoadFileProgress(value_progress) 348 self.UpdateLoadFileProgress(value_progress)
369 else: 349 else:
370 self.EndLoadFile(value_progress) 350 self.EndLoadFile(value_progress)
  351 + self.UpdateLoadFileProgress(None)
371 352
372 #Is necessary in the case user cancel 353 #Is necessary in the case user cancel
373 #the load, ensure that dicomdialog is closed 354 #the load, ensure that dicomdialog is closed