/usr/share/pyshared/tvtk/util/ctf.py is in mayavi2 4.1.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | """Color transfer function related code.
"""
# Author: Prabhu Ramachandran <prabhu@aero.iitb.ac.in>
# Copyright (c) 2006-2009, Enthought, Inc.
# License: BSD Style.
# Enthought library imports.
from traits.api import List
from tvtk.api import tvtk
##########################################################################
# Color transfer function related utility code from MayaVi1.
##########################################################################
def _err_msg(obj, cls_name):
return '%s %s does not have either a "nodes" attribute or a '\
'"get_node_value" method'%(cls_name, str(obj))
def save_ctfs(volume_property):
"""Given a `tvtk.VolumeProperty` it saves the state of the RGB and
opacity CTF to a dictionary and returns that.
The 'rgb' key stores a list of (x, r, g, b) and the 'alpha' a list
of (x, a) values.
"""
vp = volume_property
ctf = vp.rgb_transfer_function
otf = vp.get_scalar_opacity()
s1, s2 = ctf.range
# The RGB values.
nc = ctf.size
rgb = []
if hasattr(ctf, 'nodes'):
for i in range(nc):
x = ctf.nodes[i]
r, g, b = ctf.get_color(x)
rgb.append([x, r, g, b])
elif hasattr(ctf, 'get_node_value'):
val = [0]*6
for i in range(nc):
ctf.get_node_value(i, val)
rgb.append(val[:4])
else:
raise TypeError, _err_msg(ctf, 'ColorTransferFunction')
# The Alpha values.
na = otf.size
a = []
if hasattr(otf, 'nodes'):
for i in range(na):
x = otf.nodes[i]
val = otf.get_value(x)
a.append([x, val])
elif hasattr(otf, 'get_node_value'):
val = [0]*4
for i in range(na):
otf.get_node_value(i, val)
a.append(val[:2])
else:
raise TypeError, _err_msg(otf, 'PiecewiseFunction')
return {'range': (s1, s2), 'rgb':rgb, 'alpha':a}
def load_ctfs(saved_data, volume_property):
""" Given the saved data produced via `save_ctfs`, this sets the
state of the passed volume_property appropriately.
It returns the new color transfer function and piecewise function.
"""
rgb = saved_data['rgb']
a = saved_data['alpha']
# The new_ctf/otf shenanigans are necessary because if the ctf/otf
# go out of scope we loose the node information. This is because
# the tvtk object is really a dynamically generated wrapper.
# First do the RGB values ...
new_ctf = True
ctf = volume_property.rgb_transfer_function
if isinstance(ctf, ColorTransferFunction):
new_ctf = False
ctf.remove_all_points()
else:
ctf = ColorTransferFunction()
nc = len(rgb)
for i in range(nc):
ctf.add_rgb_point(rgb[i][0], *(rgb[i][1:]))
if new_ctf:
volume_property.set_color(ctf)
try:
ctf.range = saved_data['range']
except Exception:
# VTK versions < 5.2 don't seem to need this.
pass
# and then the alpha values.
na = len(a)
new_otf = True
otf = volume_property.get_scalar_opacity()
if isinstance(otf, PiecewiseFunction):
new_otf = False
otf.remove_all_points()
else:
otf = PiecewiseFunction()
for i in range(na):
otf.add_point(a[i][0], a[i][1])
if new_otf:
volume_property.set_scalar_opacity(otf)
return ctf, otf
def rescale_ctfs(volume_property, new_range):
""" Given the volume_property with a new_range for the data while
using the same transfer functions, this function rescales the
CTF's so that everything works OK.
It returns the CTF and OTF.
"""
ctf = volume_property.rgb_transfer_function
otf = volume_property.get_scalar_opacity()
old_range = ctf.range
def _rescale_value(x, old, new):
nx = (x - old[0])/(old[1] - old[0])
return new[0] + nx*(new[1] - new[0])
if new_range[0] != old_range[0] and new_range[1] != old_range[1]:
s_d = save_ctfs(volume_property)
# Set the new range making sure that they are in the right order.
s1, s2 = new_range
if s1 > s2:
s_d['range'] = (s2, s1)
else:
s_d['range'] = (s1, s2)
# Rescale the RGB values.
rgb = s_d['rgb']
for v in rgb:
v[0] = _rescale_value(v[0], old_range, new_range)
# Rescale the alpha values.
alpha = s_d['alpha']
for v in alpha:
v[0] = _rescale_value(v[0], old_range, new_range)
# Now load the rescaled values.
ctf, otf = load_ctfs(s_d, volume_property)
return ctf, otf
def set_lut(lut, volume_property):
"""Given a `tvtk.LookupTable` and a `tvtk.VolumeProperty` it saves
the state of the RGB and opacity CTF from the volume property to
the LUT. The number of colors to use is obtained from the LUT and
not the CTF.
"""
vp = volume_property
ctf = vp.rgb_transfer_function
otf = vp.get_scalar_opacity()
s1, s2 = ctf.range
nc = lut.number_of_colors
ds = float(s2-s1)/(nc - 1)
for i in range(nc):
r, g, b = ctf.get_color(s1 + i*ds)
a = otf.get_value(s1 + i*ds)
lut.set_table_value(i, r, g, b, a)
def set_ctf_from_lut(lut, volume_property):
"""Given a `tvtk.LookupTable` and a `tvtk.VolumeProperty` it loads
the state of the RGB and opacity CTF from the lookup table to the
CTF. The CTF range is obtained from the volume property and the
number of colors to use is obtained from the LUT.
"""
vp = volume_property
ctf = vp.rgb_transfer_function
s1, s2 = ctf.range
nc = lut.number_of_colors
ds = float(s2-s1)/(nc - 1)
ctf = ColorTransferFunction()
otf = PiecewiseFunction()
for i in range(nc):
v = s1 + i*ds
r, g, b, a = lut.get_table_value(i)
ctf.add_rgb_point(v, r, g, b)
otf.add_point(v, a)
volume_property.set_color(ctf)
volume_property.set_scalar_opacity(otf)
##########################################################################
# `ColorTransferFunction` class.
##########################################################################
class ColorTransferFunction(tvtk.ColorTransferFunction):
"""Overrides a few important methods that allow us to glean node
information. This is useful in cases where the super class does
not have methods to get the nodes.
"""
# Stores the nodes used by the CTF. Note that this is not a
# proper trait and modifying this will not change the underlying
# VTK object.
nodes = List
def add_rgb_point(self, *args):
"""V.add_rgb_point(float, float, float, float) -> int
V.add_rgb_point(float, float, float, float, float, float) -> int
Add/Remove a point to/from the function defined in RGB or HSV
Return the index of the point (0 based), or -1 on error.
Wrapper around parent class functionality to store node
information.
"""
ret = super(ColorTransferFunction, self).add_rgb_point(*args)
self.nodes.append(args[0])
self.nodes.sort()
return ret
def add_hsv_point(self, *args):
"""V.add_hsv_point(float, float, float, float) -> int
V.add_hsv_point(float, float, float, float, float, float) -> int
Add/Remove a point to/from the function defined in RGB or HSV
Return the index of the point (0 based), or -1 on error.
Wrapper around parent class functionality to store node
information.
"""
ret = super(ColorTransferFunction, self).add_hsv_point(*args)
self.nodes.append(args[0])
self.nodes.sort()
return ret
def remove_all_points(self):
"""Remove all the points.
"""
super(ColorTransferFunction, self).remove_all_points()
self.nodes = []
##########################################################################
# `PiecewiseFunction` class.
##########################################################################
class PiecewiseFunction(tvtk.PiecewiseFunction):
"""Overrides a few important methods that allow us to glean node
information. This is useful in cases where the super class does
not have methods to get the nodes.
"""
# Stores the nodes used by the function. Note that this is not a
# proper trait and modifying this will not change the underlying
# VTK object.
nodes = List
def initialize(self):
"""V.initialize()
Clears out the current function. A newly created
PiecewiseFunction is alreay initialized, so there is no need
to call this method which in turn simply calls
remove_all_points()
"""
super(PiecewiseFunction, self).initialize()
self.nodes = []
def add_point(self, x, val):
"""V.add_point(float, float) -> int
V.add_point(float, float, float, float) -> int
Add/Remove points to/from the function. If a duplicate point
is added then the function value is changed at that location.
Return the index of the point (0 based), or -1 on error.
"""
ret = super(PiecewiseFunction, self).add_point(x, val)
self.nodes.append(x)
self.nodes.sort()
return ret
def remove_point(self, x):
"""V.remove_point(float) -> int
Add/Remove points to/from the function. If a duplicate point
is added then the function value is changed at that location.
Return the index of the point (0 based), or -1 on error.
"""
ret = super(PiecewiseFunction, self).remove_point(x)
self.nodes.remove(x)
self.nodes.sort()
return ret
def remove_all_points(self):
"""Remove all the points.
"""
super(PiecewiseFunction, self).remove_all_points()
self.nodes = []
|