Commit d641a71591ea1defb285fdd7d6be7f10c66db928
1 parent
d209eef9
Exists in
master
and in
68 other branches
ADD: A method to calculate window width and window level.
FIX: Using other mapper to raycasting
Showing
1 changed file
with
70 additions
and
21 deletions
Show diff stats
invesalius/data/volume.py
... | ... | @@ -20,6 +20,7 @@ import plistlib |
20 | 20 | import os |
21 | 21 | |
22 | 22 | import vtk |
23 | +import wx | |
23 | 24 | import wx.lib.pubsub as ps |
24 | 25 | |
25 | 26 | from project import Project |
... | ... | @@ -42,6 +43,8 @@ class Volume(): |
42 | 43 | def __init__(self): |
43 | 44 | self.config = None |
44 | 45 | self.exist = None |
46 | + self.color_transfer = None | |
47 | + self.opacity_transfer_func = None | |
45 | 48 | |
46 | 49 | self.__bind_events() |
47 | 50 | |
... | ... | @@ -51,7 +54,10 @@ class Volume(): |
51 | 54 | 'Show raycasting volume') |
52 | 55 | ps.Publisher().subscribe(self.OnHideVolume, |
53 | 56 | 'Hide raycasting volume') |
54 | - | |
57 | + ps.Publisher().subscribe(self.SetRaycastPreset, | |
58 | + 'Set raycasting preset') | |
59 | + ps.Publisher().subscribe(self.SetWWWL, | |
60 | + 'Set raycasting wwwl') | |
55 | 61 | |
56 | 62 | def OnLoadVolume(self, pubsub_evt): |
57 | 63 | label = pubsub_evt.data |
... | ... | @@ -65,24 +71,62 @@ class Volume(): |
65 | 71 | path = os.path.join("..", "presets", "raycasting", |
66 | 72 | label+".plist") |
67 | 73 | self.config = plistlib.readPlist(path) |
68 | - | |
74 | + print path | |
75 | + | |
69 | 76 | def OnHideVolume(self, pubsub_evt): |
70 | 77 | self.volume.SetVisibility(0) |
71 | 78 | ps.Publisher().sendMessage('Render volume viewer') |
72 | - | |
79 | + | |
73 | 80 | def OnShowVolume(self, pubsub_evt): |
74 | - if self.exist: | |
81 | + if self.exist: | |
75 | 82 | self.volume.SetVisibility(1) |
76 | 83 | ps.Publisher().sendMessage('Render volume viewer') |
77 | 84 | else: |
78 | 85 | self.LoadConfig(None) |
79 | 86 | self.LoadVolume() |
80 | 87 | self.exist = 1 |
81 | - | |
82 | - | |
88 | + | |
89 | + def SetRaycastPreset(self, pubsub_evt): | |
90 | + self.LoadConfig(pubsub_evt.data) | |
91 | + self.Create16bColorTable(self.scale) | |
92 | + self.CreateOpacityTable(self.scale) | |
93 | + | |
94 | + def SetWWWL(self, pubsub_evt): | |
95 | + ww, wl, n = pubsub_evt.data | |
96 | + print "Setting ww, wl", ww, wl | |
97 | + curve = self.config['16bitClutCurves'][n] | |
98 | + | |
99 | + p1 = curve[0] | |
100 | + p2 = curve[-1] | |
101 | + half = (p2['x'] - p1['x']) / 2.0 | |
102 | + middle = p1['x'] + half | |
103 | + | |
104 | + shiftWL = wl - middle | |
105 | + shiftWW = p1['x'] + shiftWL - (wl - 0.5 * ww) | |
106 | + | |
107 | + factor = 1.0 | |
108 | + for n,i in enumerate(curve): | |
109 | + factor = abs(i['x'] - middle) / half | |
110 | + if factor < 0: | |
111 | + factor = 0 | |
112 | + i['x'] += shiftWL | |
113 | + if n < len(curve)/2.0: | |
114 | + i['x'] -= shiftWW * factor | |
115 | + else: | |
116 | + i['x'] += shiftWW * factor | |
117 | + | |
118 | + self.CreateOpacityTable(self.scale) | |
119 | + print curve | |
120 | + ps.Publisher().sendMessage('Render volume viewer', None) | |
121 | + | |
122 | + | |
83 | 123 | #*************** |
84 | 124 | def Create16bColorTable(self, scale): |
85 | - color_transfer = vtk.vtkColorTransferFunction() | |
125 | + if self.color_transfer: | |
126 | + color_transfer = self.color_transfer | |
127 | + else: | |
128 | + color_transfer = vtk.vtkColorTransferFunction() | |
129 | + color_transfer.RemoveAllPoints() | |
86 | 130 | curve_table = self.config['16bitClutCurves'] |
87 | 131 | color_table = self.config['16bitClutColors'] |
88 | 132 | colors = [] |
... | ... | @@ -97,7 +141,7 @@ class Volume(): |
97 | 141 | color_transfer.AddRGBPoint( |
98 | 142 | self.TranslateScale(scale, gray_level), |
99 | 143 | r, g, b) |
100 | - return color_transfer | |
144 | + self.color_transfer = color_transfer | |
101 | 145 | |
102 | 146 | def Create8bColorTable(self): |
103 | 147 | color_transfer = vtk.vtkColorTransferFunction() |
... | ... | @@ -112,7 +156,11 @@ class Volume(): |
112 | 156 | return color_transfer |
113 | 157 | |
114 | 158 | def CreateOpacityTable(self, scale): |
115 | - opacity_transfer_func = vtk.vtkPiecewiseFunction() | |
159 | + if self.opacity_transfer_func: | |
160 | + opacity_transfer_func = self.opacity_transfer_func | |
161 | + else: | |
162 | + opacity_transfer_func = vtk.vtkPiecewiseFunction() | |
163 | + opacity_transfer_func.RemoveAllPoints() | |
116 | 164 | curve_table = self.config['16bitClutCurves'] |
117 | 165 | opacities = [] |
118 | 166 | |
... | ... | @@ -125,6 +173,8 @@ class Volume(): |
125 | 173 | k1 = 0.0 |
126 | 174 | k2 = 1.0 |
127 | 175 | |
176 | + opacity_transfer_func.AddSegment(0, 0, 2**16-1, 0) | |
177 | + | |
128 | 178 | for i, l in enumerate(curve_table): |
129 | 179 | for j, lopacity in enumerate(l): |
130 | 180 | gray_level = lopacity['x'] |
... | ... | @@ -137,7 +187,7 @@ class Volume(): |
137 | 187 | opacities.append((gray_level, opacity)) |
138 | 188 | opacity_transfer_func.AddPoint( |
139 | 189 | self.TranslateScale(scale, gray_level), opacity) |
140 | - return opacity_transfer_func | |
190 | + self.opacity_transfer_func = opacity_transfer_func | |
141 | 191 | |
142 | 192 | def Create8bOpacityTable(self): |
143 | 193 | opacity_transfer_func = vtk.vtkPiecewiseFunction() |
... | ... | @@ -211,6 +261,7 @@ class Volume(): |
211 | 261 | |
212 | 262 | |
213 | 263 | scale = image.GetScalarRange() |
264 | + self.scale = scale | |
214 | 265 | |
215 | 266 | cast = vtk.vtkImageShiftScale() |
216 | 267 | cast.SetInput(image) |
... | ... | @@ -219,8 +270,8 @@ class Volume(): |
219 | 270 | #cast.SetScale(2**16-1) |
220 | 271 | cast.SetOutputScalarTypeToUnsignedShort() |
221 | 272 | #scale = image.GetScalarRange() |
222 | - color_transfer = self.Create16bColorTable(scale) | |
223 | - opacity_transfer_func = self.CreateOpacityTable(scale) | |
273 | + self.Create16bColorTable(scale) | |
274 | + self.CreateOpacityTable(scale) | |
224 | 275 | cast.Update() |
225 | 276 | image2 = cast |
226 | 277 | else: |
... | ... | @@ -246,17 +297,17 @@ class Volume(): |
246 | 297 | gradientEstimator = vtk.vtkFiniteDifferenceGradientEstimator() |
247 | 298 | gradientEstimator.SetGradientMagnitudeScale(1) |
248 | 299 | |
249 | - volume_mapper = vtk.vtkVolumeRayCastMapper() | |
300 | + volume_mapper = vtk.vtkFixedPointVolumeRayCastMapper() | |
250 | 301 | #volume_mapper.AutoAdjustSampleDistancesOff() |
251 | 302 | volume_mapper.SetInput(image2.GetOutput()) |
252 | - volume_mapper.SetVolumeRayCastFunction(composite_function) | |
253 | - volume_mapper.SetGradientEstimator(gradientEstimator) | |
303 | + #volume_mapper.SetVolumeRayCastFunction(composite_function) | |
304 | + #volume_mapper.SetGradientEstimator(gradientEstimator) | |
254 | 305 | volume_mapper.IntermixIntersectingGeometryOn() |
255 | 306 | |
256 | 307 | #Cut Plane |
257 | 308 | CutPlane(image2.GetOutput(), volume_mapper) |
258 | 309 | |
259 | - self.color_transfer = color_transfer | |
310 | + #self.color_transfer = color_transfer | |
260 | 311 | |
261 | 312 | volume_properties = vtk.vtkVolumeProperty() |
262 | 313 | #volume_properties.IndependentComponentsOn() |
... | ... | @@ -270,10 +321,10 @@ class Volume(): |
270 | 321 | volume_properties.SetSpecularPower(44.0) |
271 | 322 | |
272 | 323 | volume_properties.SetInterpolationTypeToLinear() |
273 | - volume_properties.SetColor(color_transfer) | |
324 | + volume_properties.SetColor(self.color_transfer) | |
274 | 325 | |
275 | 326 | try: |
276 | - volume_properties.SetScalarOpacity(opacity_transfer_func) | |
327 | + volume_properties.SetScalarOpacity(self.opacity_transfer_func) | |
277 | 328 | except NameError: |
278 | 329 | pass |
279 | 330 | |
... | ... | @@ -382,6 +433,4 @@ class CutPlane: |
382 | 433 | self.plane.SetNormal(self.normal) |
383 | 434 | self.plane.SetOrigin(self.origin) |
384 | 435 | ps.Publisher().sendMessage('Render volume viewer', None) |
385 | - | |
386 | - | |
387 | - | |
388 | 436 | \ No newline at end of file |
437 | + | ... | ... |