Commit aa9d1fe9629f689902ff165d734c3b7a6607b4f7
1 parent
291b78c3
Exists in
master
and in
68 other branches
ADD: The histogram in the clut raycasting widget
Showing
3 changed files
with
49 additions
and
19 deletions
Show diff stats
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) |