Commit d4fcee3bc7ba924cd2335565bfd310b07ade0b0d

Authored by Paulo Henrique Junqueira Amorim
1 parent 2c2993a8

ENH: Optimized memory in DICOM importation window

invesalius/gui/dicom_preview_panel.py
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 22
23 #TODO: To create a beautiful API 23 #TODO: To create a beautiful API
24 import time 24 import time
  25 +import tempfile
25 26
26 import wx 27 import wx
27 import vtk 28 import vtk
@@ -34,6 +35,8 @@ from reader import dicom_reader @@ -34,6 +35,8 @@ from reader import dicom_reader
34 import data.vtk_utils as vtku 35 import data.vtk_utils as vtku
35 import utils 36 import utils
36 import vtkgdcm 37 import vtkgdcm
  38 +
  39 +
37 NROWS = 3 40 NROWS = 3
38 NCOLS = 6 41 NCOLS = 6
39 NUM_PREVIEWS = NCOLS*NROWS 42 NUM_PREVIEWS = NCOLS*NROWS
@@ -102,31 +105,18 @@ class DicomInfo(object): @@ -102,31 +105,18 @@ class DicomInfo(object):
102 self.subtitle = subtitle 105 self.subtitle = subtitle
103 self._preview = None 106 self._preview = None
104 self.selected = False 107 self.selected = False
  108 + self.filename = ""
105 109
106 @property 110 @property
107 def preview(self): 111 def preview(self):
108 - rdicom = vtkgdcm.vtkGDCMImageReader()  
109 - if self._preview:  
110 - return self._preview  
111 - else:  
112 - rdicom.SetFileName(self.dicom.image.file)  
113 - rdicom.Update()  
114 -  
115 - colorer = vtk.vtkImageMapToWindowLevelColors()  
116 - colorer.SetInput(rdicom.GetOutput())  
117 - colorer.SetWindow(float(self.dicom.image.window))  
118 - colorer.SetLevel(float(self.dicom.image.level))  
119 - colorer.SetOutputFormatToRGB()  
120 - colorer.Update()  
121 -  
122 - width, height, z = colorer.GetOutput().GetDimensions()  
123 -  
124 - r = colorer.GetOutput().GetPointData().GetScalars()  
125 - ni = numpy_support.vtk_to_numpy(r)  
126 - self.img = wx.ImageFromBuffer(width, height, ni)  
127 - self._preview = self.img.Mirror(False)  
128 - return self._preview  
129 - 112 +
  113 + if not self._preview:
  114 + bmp = wx.Bitmap(self.dicom.image.thumbnail_path, wx.BITMAP_TYPE_PNG)
  115 + self._preview = bmp.ConvertToImage()
  116 + return self._preview
  117 +
  118 + def release_thumbnail(self):
  119 + self._preview = None
130 120
131 class DicomPaintPanel(wx.Panel): 121 class DicomPaintPanel(wx.Panel):
132 def __init__(self, parent): 122 def __init__(self, parent):
@@ -238,6 +228,9 @@ class Preview(wx.Panel): @@ -238,6 +228,9 @@ class Preview(wx.Panel):
238 """ 228 """
239 Set a dicom to preview. 229 Set a dicom to preview.
240 """ 230 """
  231 + if self.dicom_info:
  232 + self.dicom_info.release_thumbnail()
  233 +
241 self.dicom_info = dicom_info 234 self.dicom_info = dicom_info
242 self.SetTitle(dicom_info.title) 235 self.SetTitle(dicom_info.title)
243 self.SetSubtitle(dicom_info.subtitle) 236 self.SetSubtitle(dicom_info.subtitle)
@@ -409,7 +402,6 @@ class DicomPreviewSeries(wx.Panel): @@ -409,7 +402,6 @@ class DicomPreviewSeries(wx.Panel):
409 def _display_previews(self): 402 def _display_previews(self):
410 initial = self.displayed_position * NCOLS 403 initial = self.displayed_position * NCOLS
411 final = initial + NUM_PREVIEWS 404 final = initial + NUM_PREVIEWS
412 -  
413 if len(self.files) < final: 405 if len(self.files) < final:
414 for i in xrange(final-len(self.files)): 406 for i in xrange(final-len(self.files)):
415 try: 407 try:
@@ -557,7 +549,6 @@ class DicomPreviewSlice(wx.Panel): @@ -557,7 +549,6 @@ class DicomPreviewSlice(wx.Panel):
557 def _display_previews(self): 549 def _display_previews(self):
558 initial = self.displayed_position * NCOLS 550 initial = self.displayed_position * NCOLS
559 final = initial + NUM_PREVIEWS 551 final = initial + NUM_PREVIEWS
560 -  
561 if len(self.files) < final: 552 if len(self.files) < final:
562 for i in xrange(final-len(self.files)): 553 for i in xrange(final-len(self.files)):
563 try: 554 try:
invesalius/reader/dicom.py
@@ -139,9 +139,10 @@ class Parser(): @@ -139,9 +139,10 @@ class Parser():
139 # return None#self.vtkgdcm_reader.GetOutput() 139 # return None#self.vtkgdcm_reader.GetOutput()
140 140
141 141
142 - def SetDataImage(self, data_image, filename): 142 + def SetDataImage(self, data_image, filename, thumbnail_path):
143 self.data_image = data_image 143 self.data_image = data_image
144 self.filename = self.filepath = filename 144 self.filename = self.filepath = filename
  145 + self.thumbnail_path = thumbnail_path
145 146
146 def __format_time(self,value): 147 def __format_time(self,value):
147 sp1 = value.split(".") 148 sp1 = value.split(".")
@@ -1931,6 +1932,7 @@ class Image(object): @@ -1931,6 +1932,7 @@ class Image(object):
1931 self.size = (parser.GetDimensionX(), parser.GetDimensionY()) 1932 self.size = (parser.GetDimensionX(), parser.GetDimensionY())
1932 #self.imagedata = parser.GetImageData() 1933 #self.imagedata = parser.GetImageData()
1933 self.bits_allocad = parser._GetBitsAllocated() 1934 self.bits_allocad = parser._GetBitsAllocated()
  1935 + self.thumbnail_path = parser.thumbnail_path
1934 1936
1935 if (parser.GetImageThickness()): 1937 if (parser.GetImageThickness()):
1936 try: 1938 try:
invesalius/reader/dicom_reader.py
@@ -19,10 +19,12 @@ @@ -19,10 +19,12 @@
19 import os 19 import os
20 import Queue 20 import Queue
21 import threading 21 import threading
  22 +import tempfile
22 23
23 from multiprocessing import cpu_count 24 from multiprocessing import cpu_count
24 25
25 import vtk 26 import vtk
  27 +import vtkgdcm
26 import gdcm 28 import gdcm
27 import wx.lib.pubsub as ps 29 import wx.lib.pubsub as ps
28 30
@@ -106,9 +108,8 @@ class LoadDicom(threading.Thread): @@ -106,9 +108,8 @@ class LoadDicom(threading.Thread):
106 reader.SetFileName(str(filepath)) 108 reader.SetFileName(str(filepath))
107 109
108 if (reader.Read()): 110 if (reader.Read()):
109 -  
110 file = reader.GetFile() 111 file = reader.GetFile()
111 - 112 +
112 # Retrieve data set 113 # Retrieve data set
113 dataSet = file.GetDataSet() 114 dataSet = file.GetDataSet()
114 115
@@ -173,6 +174,41 @@ class LoadDicom(threading.Thread): @@ -173,6 +174,41 @@ class LoadDicom(threading.Thread):
173 data_dict[group][field] = "Invalid Character" 174 data_dict[group][field] = "Invalid Character"
174 175
175 176
  177 +
  178 + # -------------- To Create DICOM Thumbnail -----------
  179 + rvtk = vtkgdcm.vtkGDCMImageReader()
  180 + rvtk.SetFileName(str(filepath))
  181 + rvtk.Update()
  182 +
  183 + try:
  184 + data = data_dict['0028']['1050']
  185 + level = [float(value) for value in data.split('\\')][0]
  186 + data = data_dict['0028']['1051']
  187 + window = [float(value) for value in data.split('\\')][0]
  188 + except(KeyError):
  189 + level = 300.0
  190 + window = 2000.0
  191 +
  192 + colorer = vtk.vtkImageMapToWindowLevelColors()
  193 + colorer.SetInput(rvtk.GetOutput())
  194 + colorer.SetWindow(float(window))
  195 + colorer.SetLevel(float(level))
  196 + colorer.SetOutputFormatToRGB()
  197 + colorer.Update()
  198 +
  199 + resample = vtk.vtkImageResample()
  200 + resample.SetInput(colorer.GetOutput())
  201 + resample.SetAxisMagnificationFactor ( 0, 0.25 )
  202 + resample.SetAxisMagnificationFactor ( 1, 0.25 )
  203 + resample.SetAxisMagnificationFactor ( 2, 1 )
  204 + resample.Update()
  205 +
  206 + thumbnail_path = tempfile.mktemp()
  207 +
  208 + write_png = vtk.vtkPNGWriter()
  209 + write_png.SetInput(resample.GetOutput())
  210 + write_png.SetFileName(thumbnail_path)
  211 + write_png.Write()
176 212
177 # ---------- Refactory -------------------------------------- 213 # ---------- Refactory --------------------------------------
178 data_dict['invesalius'] = {'orientation_label' : GetImageOrientationLabel(str(filepath))} 214 data_dict['invesalius'] = {'orientation_label' : GetImageOrientationLabel(str(filepath))}
@@ -190,7 +226,7 @@ class LoadDicom(threading.Thread): @@ -190,7 +226,7 @@ class LoadDicom(threading.Thread):
190 226
191 if not(is_dicom_dir): 227 if not(is_dicom_dir):
192 parser = dicom.Parser() 228 parser = dicom.Parser()
193 - parser.SetDataImage(dict_file[filepath], filepath) 229 + parser.SetDataImage(dict_file[filepath], filepath, thumbnail_path)
194 230
195 dcm = dicom.Dicom() 231 dcm = dicom.Dicom()
196 self.l.acquire() 232 self.l.acquire()