Commit aa9d1fe9629f689902ff165d734c3b7a6607b4f7

Authored by tfmoraes
1 parent 291b78c3

ADD: The histogram in the clut raycasting widget

invesalius/data/volume.py
@@ -19,14 +19,17 @@ @@ -19,14 +19,17 @@
19 import plistlib 19 import plistlib
20 import os 20 import os
21 21
  22 +import numpy
22 import vtk 23 import vtk
23 import wx 24 import wx
24 import wx.lib.pubsub as ps 25 import wx.lib.pubsub as ps
25 26
26 import constants as const 27 import constants as const
27 -from data import vtk_utils  
28 import project as prj 28 import project as prj
29 29
  30 +from data import vtk_utils
  31 +from vtk.util import numpy_support
  32 +
30 Kernels = { 33 Kernels = {
31 "Basic Smooth 5x5" : [1.0, 1.0, 1.0, 1.0, 1.0, 34 "Basic Smooth 5x5" : [1.0, 1.0, 1.0, 1.0, 1.0,
32 1.0, 4.0, 4.0, 4.0, 1.0, 35 1.0, 4.0, 4.0, 4.0, 1.0,
@@ -128,6 +131,7 @@ class Volume(): @@ -128,6 +131,7 @@ class Volume():
128 #ps.Publisher().sendMessage('Render volume viewer') 131 #ps.Publisher().sendMessage('Render volume viewer')
129 else: 132 else:
130 self.LoadVolume() 133 self.LoadVolume()
  134 + self.CalculateHistogram()
131 self.exist = 1 135 self.exist = 1
132 136
133 if (self.plane and self.plane_on): 137 if (self.plane and self.plane_on):
@@ -173,7 +177,7 @@ class Volume(): @@ -173,7 +177,7 @@ class Volume():
173 ww = self.ww + diff_ww 177 ww = self.ww + diff_ww
174 wl = self.wl + diff_wl 178 wl = self.wl + diff_wl
175 ps.Publisher().sendMessage('Set volume window and level text', 179 ps.Publisher().sendMessage('Set volume window and level text',
176 - (ww, wl)) 180 + (ww, wl))
177 self.SetWWWL(ww, wl) 181 self.SetWWWL(ww, wl)
178 self.ww = ww 182 self.ww = ww
179 self.wl = wl 183 self.wl = wl
@@ -184,7 +188,6 @@ class Volume(): @@ -184,7 +188,6 @@ class Volume():
184 self.SetWWWL(ww,wl) 188 self.SetWWWL(ww,wl)
185 189
186 def SetWWWL(self, ww, wl): 190 def SetWWWL(self, ww, wl):
187 -  
188 if self.config['advancedCLUT']: 191 if self.config['advancedCLUT']:
189 try: 192 try:
190 curve = self.config['16bitClutCurves'][self.curve] 193 curve = self.config['16bitClutCurves'][self.curve]
@@ -233,7 +236,6 @@ class Volume(): @@ -233,7 +236,6 @@ class Volume():
233 def Refresh(self, pubsub_evt): 236 def Refresh(self, pubsub_evt):
234 self.__update_colour_table() 237 self.__update_colour_table()
235 238
236 -#***************  
237 def Create16bColorTable(self, scale): 239 def Create16bColorTable(self, scale):
238 if self.color_transfer: 240 if self.color_transfer:
239 color_transfer = self.color_transfer 241 color_transfer = self.color_transfer
@@ -530,6 +532,18 @@ class Volume(): @@ -530,6 +532,18 @@ class Volume():
530 self.plane = CutPlane(self.final_imagedata, 532 self.plane = CutPlane(self.final_imagedata,
531 self.volume_mapper) 533 self.volume_mapper)
532 534
  535 + def CalculateHistogram(self):
  536 + proj = prj.Project()
  537 + image = proj.imagedata
  538 + r = image.GetScalarRange()[1] - image.GetScalarRange()[0]
  539 + accumulate = vtk.vtkImageAccumulate()
  540 + accumulate.SetInput(image)
  541 + accumulate.SetComponentExtent(0, r -1, 0, 0, 0, 0)
  542 + accumulate.SetComponentOrigin(image.GetScalarRange()[0], 0, 0)
  543 + accumulate.Update()
  544 + n_image = numpy_support.vtk_to_numpy(accumulate.GetOutput().GetPointData().GetScalars())
  545 + ps.Publisher().sendMessage('Load histogram', (n_image,
  546 + image.GetScalarRange()))
533 547
534 def TranslateScale(self, scale, value): 548 def TranslateScale(self, scale, value):
535 #if value < 0: 549 #if value < 0:
invesalius/gui/default_viewers.py
@@ -237,8 +237,10 @@ class VolumeInteraction(wx.Panel): @@ -237,8 +237,10 @@ class VolumeInteraction(wx.Panel):
237 'Hide raycasting widget') 237 'Hide raycasting widget')
238 ps.Publisher().subscribe(self.OnSetRaycastPreset, 238 ps.Publisher().subscribe(self.OnSetRaycastPreset,
239 'Update raycasting preset') 239 'Update raycasting preset')
240 - ps.Publisher().subscribe( self.RefreshPoints, 240 + ps.Publisher().subscribe(self.RefreshPoints,
241 'Refresh raycasting widget points') 241 'Refresh raycasting widget points')
  242 + ps.Publisher().subscribe(self.LoadHistogram,
  243 + 'Load histogram')
242 244
243 def __update_curve_wwwl_text(self, curve): 245 def __update_curve_wwwl_text(self, curve):
244 ww, wl = self.clut_raycasting.GetCurveWWWl(curve) 246 ww, wl = self.clut_raycasting.GetCurveWWWl(curve)
@@ -283,6 +285,12 @@ class VolumeInteraction(wx.Panel): @@ -283,6 +285,12 @@ class VolumeInteraction(wx.Panel):
283 p.Hide() 285 p.Hide()
284 self.aui_manager.Update() 286 self.aui_manager.Update()
285 287
  288 + def LoadHistogram(self, pubsub_evt):
  289 + histogram = pubsub_evt.data[0]
  290 + init, end = pubsub_evt.data[1]
  291 + self.clut_raycasting.SetRange((init, end))
  292 + self.clut_raycasting.SetHistogramArray(histogram, (init, end))
  293 +
286 def RefreshPoints(self, pubsub_evt): 294 def RefreshPoints(self, pubsub_evt):
287 self.clut_raycasting.CalculatePixelPoints() 295 self.clut_raycasting.CalculatePixelPoints()
288 self.clut_raycasting.Refresh() 296 self.clut_raycasting.Refresh()
invesalius/gui/widgets/clut_raycasting.py
@@ -51,6 +51,12 @@ class Curve(object): @@ -51,6 +51,12 @@ class Curve(object):
51 self.wl = self.nodes[0].graylevel + self.ww / 2.0 51 self.wl = self.nodes[0].graylevel + self.ww / 2.0
52 52
53 53
  54 +class Histogram(object):
  55 + def __init__(self):
  56 + self.init = -1024
  57 + self.end = 2000
  58 +
  59 +
54 class CLUTRaycastingWidget(wx.Panel): 60 class CLUTRaycastingWidget(wx.Panel):
55 """ 61 """
56 This class represents the frame where images is showed 62 This class represents the frame where images is showed
@@ -68,6 +74,7 @@ class CLUTRaycastingWidget(wx.Panel): @@ -68,6 +74,7 @@ class CLUTRaycastingWidget(wx.Panel):
68 self.curves = [] 74 self.curves = []
69 self.init = -1024 75 self.init = -1024
70 self.end = 2000 76 self.end = 2000
  77 + self.Histogram = Histogram()
71 self.padding = 5 78 self.padding = 5
72 self.previous_wl = 0 79 self.previous_wl = 0
73 self.to_render = False 80 self.to_render = False
@@ -484,14 +491,14 @@ class CLUTRaycastingWidget(wx.Panel): @@ -484,14 +491,14 @@ class CLUTRaycastingWidget(wx.Panel):
484 ctx.set_line_width(HISTOGRAM_LINE_WIDTH) 491 ctx.set_line_width(HISTOGRAM_LINE_WIDTH)
485 for x,y in self.histogram_pixel_points: 492 for x,y in self.histogram_pixel_points:
486 ctx.line_to(x,y) 493 ctx.line_to(x,y)
487 - ctx.line_to(x, height)  
488 - ctx.line_to(0, height) 494 + ctx.set_source_rgb(*HISTOGRAM_LINE_COLOUR)
  495 + ctx.stroke_preserve()
  496 + ctx.line_to(x, height + self.padding)
  497 + ctx.line_to(self.HounsfieldToPixel(self.Histogram.init), height + self.padding)
489 x,y = self.histogram_pixel_points[0] 498 x,y = self.histogram_pixel_points[0]
490 ctx.line_to(x, y) 499 ctx.line_to(x, y)
491 ctx.set_source_rgb(*HISTOGRAM_FILL_COLOUR) 500 ctx.set_source_rgb(*HISTOGRAM_FILL_COLOUR)
492 - ctx.fill_preserve()  
493 - ctx.set_source_rgb(*HISTOGRAM_LINE_COLOUR)  
494 - ctx.stroke() 501 + ctx.fill()
495 502
496 def _draw_selection_curve(self, ctx, height): 503 def _draw_selection_curve(self, ctx, height):
497 for curve in self.curves: 504 for curve in self.curves:
@@ -520,24 +527,23 @@ class CLUTRaycastingWidget(wx.Panel): @@ -520,24 +527,23 @@ class CLUTRaycastingWidget(wx.Panel):
520 self._draw_selected_point_text(ctx) 527 self._draw_selected_point_text(ctx)
521 528
522 def _build_histogram(self): 529 def _build_histogram(self):
523 - width, height= self.GetVirtualSizeTuple() 530 + width, height = self.GetVirtualSizeTuple()
524 width -= self.padding 531 width -= self.padding
525 - height -= self.padding 532 + height -= (self.padding * 2)
  533 + x_init = self.Histogram.init
  534 + x_end = self.Histogram.end
526 y_init = 0 535 y_init = 0
527 y_end = math.log(max(self.histogram_array)) 536 y_end = math.log(max(self.histogram_array))
528 - print y_end  
529 - proportion_x = width * 1.0 / (self.end - self.init) 537 + proportion_x = width * 1.0 / (x_end - x_init)
530 proportion_y = height * 1.0 / (y_end - y_init) 538 proportion_y = height * 1.0 / (y_end - y_init)
531 - print ":) ", y_end, proportion_y  
532 self.histogram_pixel_points = [] 539 self.histogram_pixel_points = []
533 for i in xrange(len(self.histogram_array)): 540 for i in xrange(len(self.histogram_array)):
534 if self.histogram_array[i]: 541 if self.histogram_array[i]:
535 y = math.log(self.histogram_array[i]) 542 y = math.log(self.histogram_array[i])
536 else: 543 else:
537 y = 0 544 y = 0
538 - x = self.init+ i  
539 - x = (x + abs(self.init)) * proportion_x  
540 - y = height - y * proportion_y 545 + x = self.HounsfieldToPixel(x_init + i)
  546 + y = height - y * proportion_y + self.padding
541 self.histogram_pixel_points.append((x, y)) 547 self.histogram_pixel_points.append((x, y))
542 548
543 def __sort_pixel_points(self): 549 def __sort_pixel_points(self):
@@ -627,8 +633,10 @@ class CLUTRaycastingWidget(wx.Panel): @@ -627,8 +633,10 @@ class CLUTRaycastingWidget(wx.Panel):
627 self.to_draw_points = 0 633 self.to_draw_points = 0
628 self.Refresh() 634 self.Refresh()
629 635
630 - def SetHistrogramArray(self, h_array): 636 + def SetHistogramArray(self, h_array, range):
631 self.histogram_array = h_array 637 self.histogram_array = h_array
  638 + self.Histogram.init = range[0]
  639 + self.Histogram.end = range[1]
632 640
633 def GetCurveWWWl(self, curve): 641 def GetCurveWWWl(self, curve):
634 return (self.curves[curve].ww, self.curves[curve].wl) 642 return (self.curves[curve].ww, self.curves[curve].wl)