Commit 1ea696b9fda53711b471a12973e666ae1e2e89d1

Authored by tfmoraes
1 parent ceaf535c

Using weakref reduce memory consumption in volume rendering

invesalius/control.py
@@ -599,7 +599,6 @@ class Controller(): @@ -599,7 +599,6 @@ class Controller():
599 else: 599 else:
600 prj.Project().raycasting_preset = 0 600 prj.Project().raycasting_preset = 0
601 Publisher.sendMessage('Update raycasting preset') 601 Publisher.sendMessage('Update raycasting preset')
602 - Publisher.sendMessage("Hide raycasting volume")  
603 602
604 def SaveRaycastingPreset(self, pubsub_evt): 603 def SaveRaycastingPreset(self, pubsub_evt):
605 preset_name = pubsub_evt.data 604 preset_name = pubsub_evt.data
invesalius/data/viewer_volume.py
@@ -110,11 +110,14 @@ class Viewer(wx.Panel): @@ -110,11 +110,14 @@ class Viewer(wx.Panel):
110 self.repositioned_coronal_plan = 0 110 self.repositioned_coronal_plan = 0
111 self.added_actor = 0 111 self.added_actor = 0
112 112
  113 + self._to_show_ball = 0
  114 +
113 def __bind_events(self): 115 def __bind_events(self):
114 Publisher.subscribe(self.LoadActor, 116 Publisher.subscribe(self.LoadActor,
115 'Load surface actor into viewer') 117 'Load surface actor into viewer')
116 Publisher.subscribe(self.RemoveActor, 118 Publisher.subscribe(self.RemoveActor,
117 'Remove surface actor from viewer') 119 'Remove surface actor from viewer')
  120 + Publisher.subscribe(self.OnShowSurface, 'Show surface')
118 Publisher.subscribe(self.UpdateRender, 121 Publisher.subscribe(self.UpdateRender,
119 'Render volume viewer') 122 'Render volume viewer')
120 Publisher.subscribe(self.ChangeBackgroundColour, 123 Publisher.subscribe(self.ChangeBackgroundColour,
@@ -225,22 +228,35 @@ class Viewer(wx.Panel): @@ -225,22 +228,35 @@ class Viewer(wx.Panel):
225 self.ball_actor.SetProperty(p) 228 self.ball_actor.SetProperty(p)
226 229
227 def ActivateBallReference(self, pubsub_evt): 230 def ActivateBallReference(self, pubsub_evt):
228 - if not self.ball_reference:  
229 - self.CreateBallReference()  
230 - self.ren.AddActor(self.ball_actor) 231 + if self._to_show_ball:
  232 + if not self.ball_reference:
  233 + self.CreateBallReference()
  234 + self.ren.AddActor(self.ball_actor)
231 235
232 def DeactivateBallReference(self, pubsub_evt): 236 def DeactivateBallReference(self, pubsub_evt):
233 if self.ball_reference: 237 if self.ball_reference:
234 self.ren.RemoveActor(self.ball_actor) 238 self.ren.RemoveActor(self.ball_actor)
235 239
  240 + def OnShowSurface(self, pubsub_evt):
  241 + index, value = pubsub_evt.data
  242 + if value:
  243 + self._to_show_ball += 1
  244 + else:
  245 + self._to_show_ball -= 1
  246 + print "to show ball", self._to_show_ball
  247 +
236 def SetBallReferencePosition(self, pubsub_evt): 248 def SetBallReferencePosition(self, pubsub_evt):
237 x, y, z = pubsub_evt.data 249 x, y, z = pubsub_evt.data
238 self.ball_reference.SetCenter(x, y, z) 250 self.ball_reference.SetCenter(x, y, z)
239 251
240 def SetBallReferencePositionBasedOnBound(self, pubsub_evt): 252 def SetBallReferencePositionBasedOnBound(self, pubsub_evt):
241 - coord = pubsub_evt.data  
242 - x, y, z = bases.FlipX(coord)  
243 - self.ball_reference.SetCenter(x, y, z) 253 + if self._to_show_ball:
  254 + self.ActivateBallReference(None)
  255 + coord = pubsub_evt.data
  256 + x, y, z = bases.FlipX(coord)
  257 + self.ball_reference.SetCenter(x, y, z)
  258 + else:
  259 + self.DeactivateBallReference(None)
244 260
245 def OnStartSeed(self, pubsub_evt): 261 def OnStartSeed(self, pubsub_evt):
246 index = pubsub_evt.data 262 index = pubsub_evt.data
@@ -321,6 +337,7 @@ class Viewer(wx.Panel): @@ -321,6 +337,7 @@ class Viewer(wx.Panel):
321 if (volumes.GetNumberOfItems()): 337 if (volumes.GetNumberOfItems()):
322 self.ren.RemoveVolume(volumes.GetLastProp()) 338 self.ren.RemoveVolume(volumes.GetLastProp())
323 self.interactor.Render() 339 self.interactor.Render()
  340 + self._to_show_ball -= 1
324 341
325 def RemoveActors(self, pubsub_evt): 342 def RemoveActors(self, pubsub_evt):
326 "Remove a list of actors" 343 "Remove a list of actors"
@@ -605,12 +622,16 @@ class Viewer(wx.Panel): @@ -605,12 +622,16 @@ class Viewer(wx.Panel):
605 622
606 def OnShowRaycasting(self, pubsub_evt): 623 def OnShowRaycasting(self, pubsub_evt):
607 self.raycasting_volume = True 624 self.raycasting_volume = True
  625 + self._to_show_ball += 1
  626 + print "to show ball", self._to_show_ball
608 if self.on_wl: 627 if self.on_wl:
609 self.text.Show() 628 self.text.Show()
610 629
611 def OnHideRaycasting(self, pubsub_evt): 630 def OnHideRaycasting(self, pubsub_evt):
612 self.raycasting_volume = False 631 self.raycasting_volume = False
613 self.text.Hide() 632 self.text.Hide()
  633 + self._to_show_ball -= 1
  634 + print "to show ball", self._to_show_ball
614 635
615 def OnSize(self, evt): 636 def OnSize(self, evt):
616 self.UpdateRender() 637 self.UpdateRender()
@@ -639,6 +660,8 @@ class Viewer(wx.Panel): @@ -639,6 +660,8 @@ class Viewer(wx.Panel):
639 660
640 #self.ShowOrientationCube() 661 #self.ShowOrientationCube()
641 self.interactor.Render() 662 self.interactor.Render()
  663 + self._to_show_ball += 1
  664 + print "to show ball", self._to_show_ball
642 665
643 def RemoveActor(self, pubsub_evt): 666 def RemoveActor(self, pubsub_evt):
644 utils.debug("RemoveActor") 667 utils.debug("RemoveActor")
@@ -646,6 +669,8 @@ class Viewer(wx.Panel): @@ -646,6 +669,8 @@ class Viewer(wx.Panel):
646 ren = self.ren 669 ren = self.ren
647 ren.RemoveActor(actor) 670 ren.RemoveActor(actor)
648 self.interactor.Render() 671 self.interactor.Render()
  672 + #self._to_show_ball -= 1
  673 + #print "to show ball", self._to_show_ball
649 674
650 def RemoveAllActor(self, pubsub_evt): 675 def RemoveAllActor(self, pubsub_evt):
651 utils.debug("RemoveAllActor") 676 utils.debug("RemoveAllActor")
@@ -658,6 +683,8 @@ class Viewer(wx.Panel): @@ -658,6 +683,8 @@ class Viewer(wx.Panel):
658 683
659 def LoadVolume(self, pubsub_evt): 684 def LoadVolume(self, pubsub_evt):
660 self.raycasting_volume = True 685 self.raycasting_volume = True
  686 + #self._to_show_ball += 1
  687 + #print "to show ball", self._to_show_ball
661 688
662 volume = pubsub_evt.data[0] 689 volume = pubsub_evt.data[0]
663 colour = pubsub_evt.data[1] 690 colour = pubsub_evt.data[1]
@@ -685,7 +712,10 @@ class Viewer(wx.Panel): @@ -685,7 +712,10 @@ class Viewer(wx.Panel):
685 712
686 def UnloadVolume(self, pubsub_evt): 713 def UnloadVolume(self, pubsub_evt):
687 volume = pubsub_evt.data 714 volume = pubsub_evt.data
  715 + self._to_show_ball -= 1
688 self.ren.RemoveVolume(volume) 716 self.ren.RemoveVolume(volume)
  717 + del volume
  718 + print "to show ball", self._to_show_ball
689 719
690 def OnSetViewAngle(self, evt_pubsub): 720 def OnSetViewAngle(self, evt_pubsub):
691 view = evt_pubsub.data 721 view = evt_pubsub.data
@@ -824,6 +854,9 @@ class Viewer(wx.Panel): @@ -824,6 +854,9 @@ class Viewer(wx.Panel):
824 self.SetViewAngle(const.VOL_ISO) 854 self.SetViewAngle(const.VOL_ISO)
825 self.repositioned_coronal_plan = 1 855 self.repositioned_coronal_plan = 1
826 856
  857 + def _verify_necessity_ball_ref(self):
  858 + pass
  859 +
827 860
828 861
829 862
invesalius/data/volume.py
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
19 import plistlib 19 import plistlib
20 import os 20 import os
  21 +import weakref
21 22
22 import numpy 23 import numpy
23 import vtk 24 import vtk
@@ -173,12 +174,30 @@ class Volume(): @@ -173,12 +174,30 @@ class Volume():
173 #Publisher.sendMessage('Render volume viewer') 174 #Publisher.sendMessage('Render volume viewer')
174 else: 175 else:
175 self.LoadVolume() 176 self.LoadVolume()
176 - self.CalculateHistogram() 177 + #self.CalculateHistogram()
177 self.exist = 1 178 self.exist = 1
178 179
179 colour = self.GetBackgroundColour() 180 colour = self.GetBackgroundColour()
180 Publisher.sendMessage('Change volume viewer background colour', colour) 181 Publisher.sendMessage('Change volume viewer background colour', colour)
181 Publisher.sendMessage('Change volume viewer gui colour', colour) 182 Publisher.sendMessage('Change volume viewer gui colour', colour)
  183 + else:
  184 + Publisher.sendMessage('Unload volume', self.volume)
  185 + del self.image
  186 + del self.imagedata
  187 + del self.final_imagedata
  188 + del self.volume
  189 + del self.color_transfer
  190 + del self.opacity_transfer_func
  191 + del self.volume_properties
  192 + del self.volume_mapper
  193 + self.volume = None
  194 + self.exist = False
  195 + self.loaded_image = False
  196 + self.image = None
  197 + self.final_imagedata = None
  198 + self.opacity_transfer_func = None
  199 + self.color_transfer = None
  200 + Publisher.sendMessage('Render volume viewer')
182 201
183 def OnFlipVolume(self, pubsub_evt): 202 def OnFlipVolume(self, pubsub_evt):
184 print "Flipping Volume" 203 print "Flipping Volume"
@@ -198,7 +217,6 @@ class Volume(): @@ -198,7 +217,6 @@ class Volume():
198 self.Create8bColorTable(self.scale) 217 self.Create8bColorTable(self.scale)
199 self.Create8bOpacityTable(self.scale) 218 self.Create8bOpacityTable(self.scale)
200 219
201 -  
202 def __load_preset(self): 220 def __load_preset(self):
203 # Update colour table 221 # Update colour table
204 self.__update_colour_table() 222 self.__update_colour_table()
@@ -212,7 +230,6 @@ class Volume(): @@ -212,7 +230,6 @@ class Volume():
212 self.SetShading() 230 self.SetShading()
213 self.SetTypeRaycasting() 231 self.SetTypeRaycasting()
214 232
215 -  
216 def OnSetCurve(self, pubsub_evt): 233 def OnSetCurve(self, pubsub_evt):
217 self.curve = pubsub_evt.data 234 self.curve = pubsub_evt.data
218 self.CalculateWWWL() 235 self.CalculateWWWL()
@@ -469,9 +486,16 @@ class Volume(): @@ -469,9 +486,16 @@ class Volume():
469 convolve = vtk.vtkImageConvolve() 486 convolve = vtk.vtkImageConvolve()
470 convolve.SetInput(imagedata) 487 convolve.SetInput(imagedata)
471 convolve.SetKernel5x5([i/60.0 for i in Kernels[filter]]) 488 convolve.SetKernel5x5([i/60.0 for i in Kernels[filter]])
472 - convolve.AddObserver("ProgressEvent", lambda obj,evt:  
473 - update_progress(convolve, "Rendering...")) 489 + convolve.ReleaseDataFlagOn()
  490 +
  491 + convolve_ref = weakref.ref(convolve)
  492 +
  493 + convolve_ref().AddObserver("ProgressEvent", lambda obj,evt:
  494 + update_progress(convolve_ref(), "Rendering..."))
  495 + convolve.Update()
  496 + del imagedata
474 imagedata = convolve.GetOutput() 497 imagedata = convolve.GetOutput()
  498 + del convolve
475 #convolve.GetOutput().ReleaseDataFlagOn() 499 #convolve.GetOutput().ReleaseDataFlagOn()
476 return imagedata 500 return imagedata
477 501
@@ -509,12 +533,13 @@ class Volume(): @@ -509,12 +533,13 @@ class Volume():
509 flip.SetInput(image) 533 flip.SetInput(image)
510 flip.SetFilteredAxis(1) 534 flip.SetFilteredAxis(1)
511 flip.FlipAboutOriginOn() 535 flip.FlipAboutOriginOn()
512 - flip.AddObserver("ProgressEvent", lambda obj,evt:  
513 - update_progress(flip, "Rendering...")) 536 + flip.ReleaseDataFlagOn()
  537 +
  538 + flip_ref = weakref.ref(flip)
  539 + flip_ref().AddObserver("ProgressEvent", lambda obj,evt:
  540 + update_progress(flip_ref(), "Rendering..."))
514 flip.Update() 541 flip.Update()
515 image = flip.GetOutput() 542 image = flip.GetOutput()
516 - #else:  
517 - #update_progress= vtk_utils.ShowProgress(1 + number_filters)  
518 543
519 scale = image.GetScalarRange() 544 scale = image.GetScalarRange()
520 self.scale = scale 545 self.scale = scale
@@ -523,10 +548,13 @@ class Volume(): @@ -523,10 +548,13 @@ class Volume():
523 cast.SetInput(image) 548 cast.SetInput(image)
524 cast.SetShift(abs(scale[0])) 549 cast.SetShift(abs(scale[0]))
525 cast.SetOutputScalarTypeToUnsignedShort() 550 cast.SetOutputScalarTypeToUnsignedShort()
526 - cast.AddObserver("ProgressEvent", lambda obj,evt:  
527 - update_progress(cast, "Rendering...")) 551 + cast.ReleaseDataFlagOn()
  552 + cast_ref = weakref.ref(cast)
  553 + cast_ref().AddObserver("ProgressEvent", lambda obj,evt:
  554 + update_progress(cast_ref(), "Rendering..."))
528 cast.Update() 555 cast.Update()
529 image2 = cast 556 image2 = cast
  557 +
530 self.imagedata = image2 558 self.imagedata = image2
531 if self.config['advancedCLUT']: 559 if self.config['advancedCLUT']:
532 self.Create16bColorTable(scale) 560 self.Create16bColorTable(scale)
@@ -606,6 +634,8 @@ class Volume(): @@ -606,6 +634,8 @@ class Volume():
606 634
607 Publisher.sendMessage('Load volume into viewer', 635 Publisher.sendMessage('Load volume into viewer',
608 (volume, colour, (self.ww, self.wl))) 636 (volume, colour, (self.ww, self.wl)))
  637 + del flip
  638 + del cast
609 639
610 def OnEnableTool(self, pubsub_evt): 640 def OnEnableTool(self, pubsub_evt):
611 tool_name, enable = pubsub_evt.data 641 tool_name, enable = pubsub_evt.data
@@ -630,6 +660,7 @@ class Volume(): @@ -630,6 +660,7 @@ class Volume():
630 accumulate.SetInput(image) 660 accumulate.SetInput(image)
631 accumulate.SetComponentExtent(0, r -1, 0, 0, 0, 0) 661 accumulate.SetComponentExtent(0, r -1, 0, 0, 0, 0)
632 accumulate.SetComponentOrigin(image.GetScalarRange()[0], 0, 0) 662 accumulate.SetComponentOrigin(image.GetScalarRange()[0], 0, 0)
  663 + accumulate.ReleaseDataFlagOn()
633 accumulate.Update() 664 accumulate.Update()
634 n_image = numpy_support.vtk_to_numpy(accumulate.GetOutput().GetPointData().GetScalars()) 665 n_image = numpy_support.vtk_to_numpy(accumulate.GetOutput().GetPointData().GetScalars())
635 Publisher.sendMessage('Load histogram', (n_image, 666 Publisher.sendMessage('Load histogram', (n_image,