Skip to content

Commit 251cd81

Browse files
committed
RF/NF: Implemented alpha keword to Brain and allowing the cortex keyword to accept colors (curv keyword deprecated)
1 parent 445172d commit 251cd81

File tree

2 files changed

+126
-80
lines changed

2 files changed

+126
-80
lines changed

surfer/tests/test_viz.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,22 @@ def test_brains():
7373
# testing backend breaks when passing in a figure, so we use 'auto' here
7474
# (shouldn't affect usability, but it makes testing more annoying)
7575
mlab.options.backend = 'auto'
76-
surfs = ['inflated', 'white']
77-
hemis = ['lh', 'rh']
78-
curvs = [True, False]
79-
titles = [None, 'Hello']
80-
cortices = ["low_contrast", ("Reds", 0, 1, False)]
81-
sizes = [500, (400, 300)]
82-
backgrounds = ["white", "blue"]
83-
foregrounds = ["black", "white"]
84-
figs = [None, mlab.figure()]
85-
subj_dirs = [None, subj_dir]
86-
for surf, hemi, curv, title, cort, s, bg, fg, fig, sd \
87-
in zip(surfs, hemis, curvs, titles, cortices, sizes,
88-
backgrounds, foregrounds, figs, subj_dirs):
89-
brain = Brain(subject_id, hemi, surf, curv, title,
90-
cort, s, bg, fg, fig, sd)
76+
surfs = ['inflated', 'white', 'white']
77+
hemis = ['lh', 'rh', 'both']
78+
titles = [None, 'Hello', 'Good bye!']
79+
cortices = ["low_contrast", ("Reds", 0, 1, False), 'hotpink']
80+
sizes = [500, (400, 300), (300, 300)]
81+
backgrounds = ["white", "blue", "black"]
82+
foregrounds = ["black", "white", "0.75"]
83+
figs = [None, mlab.figure(), None]
84+
subj_dirs = [None, subj_dir, subj_dir]
85+
alphas = [1.0, 0.5, 0.25]
86+
for surf, hemi, title, cort, s, bg, fg, fig, sd, alpha \
87+
in zip(surfs, hemis, titles, cortices, sizes,
88+
backgrounds, foregrounds, figs, subj_dirs, alphas):
89+
brain = Brain(subject_id, hemi, surf, title=title, cortex=cort,
90+
alpha=alpha, size=s, background=bg, foreground=fg,
91+
figure=fig, subj_dir=sd)
9192
brain.close()
9293
assert_raises(ValueError, Brain, subject_id, 'lh', 'inflated',
9394
subjects_dir='')

surfer/viz.py

Lines changed: 110 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -294,17 +294,22 @@ class Brain(object):
294294
in different viewing panes.
295295
surf : geometry name
296296
freesurfer surface mesh name (ie 'white', 'inflated', etc.)
297-
curv : boolean
298-
if true, loads curv file and displays binary curvature
299-
(default: True)
300297
title : str
301298
title for the window
302-
cortex : str or tuple
303-
specifies how binarized curvature values are rendered.
304-
either the name of a preset PySurfer cortex colorscheme (one of
305-
'classic', 'bone', 'low_contrast', or 'high_contrast'), or the
306-
name of mayavi colormap, or a tuple with values (colormap, min,
307-
max, reverse, alpha) to fully specify the curvature colors.
299+
cortex : str, tuple, or dict
300+
Specifies if/how binarized curvature values are rendered. If
301+
binarized curvature values should be rendered it can be
302+
either the name of a preset PySurfer cortex colorscheme (one
303+
of 'classic' (default), 'bone', 'low_contrast', or
304+
'high_contrast'), the name of a mayavi colormap, a 4-tuple with
305+
values (colormap, min, max, reverse), or a dictionary with
306+
corresponding keys to fully specify the curvature colors. If a
307+
color is specified instead, the brain is rendered in that
308+
color without displaying the binarized curvature values. A
309+
setting of `None` produces a gray brain without binarized
310+
curvature.
311+
alpha : float in [0, 1]
312+
Alpha level to control opacity.
308313
size : float or pair of floats
309314
the size of the window, in pixels. can be one number to specify
310315
a square window, or the (width, height) of a rectangular window.
@@ -335,11 +340,11 @@ class Brain(object):
335340
List of the underlying brain instances.
336341
337342
"""
338-
def __init__(self, subject_id, hemi, surf, curv=True, title=None,
339-
cortex="classic", size=800, background="black",
343+
def __init__(self, subject_id, hemi, surf, title=None,
344+
cortex="classic", alpha=1.0, size=800, background="black",
340345
foreground="white", figure=None, subjects_dir=None,
341346
views=['lat'], offset=True, show_toolbar=False,
342-
offscreen=False, config_opts=None):
347+
offscreen=False, config_opts=None, curv=None):
343348

344349
# Keep backwards compatability
345350
if config_opts is not None:
@@ -356,6 +361,18 @@ def __init__(self, subject_id, hemi, surf, curv=True, title=None,
356361
width = config_opts.get("width", size)
357362
height = config_opts.get("height", size)
358363
size = (width, height)
364+
# Keep backwards compatability
365+
if curv is not None:
366+
msg = ("The `curv` keyword has been deprecated and will "
367+
"be removed in future versions. You should update your "
368+
"code and use the `cortex` keyword to specify how the "
369+
"brain surface is rendered. Setting `cortex` to `None` "
370+
"will reproduce the previous behavior when `curv` was "
371+
"set to `False`. To emulate the previous behavior for "
372+
"cases where `curv` was set to `True`, simply omit it.")
373+
warn(msg)
374+
if not curv:
375+
cortex = None
359376

360377
col_dict = dict(lh=1, rh=1, both=1, split=2)
361378
n_col = col_dict[hemi]
@@ -385,12 +402,13 @@ def __init__(self, subject_id, hemi, surf, curv=True, title=None,
385402
geo_hemis = ['rh']
386403
else:
387404
raise ValueError('bad hemi value')
405+
geo_kwargs, geo_reverse, geo_curv = self._get_geo_params(cortex, alpha)
388406
for h in geo_hemis:
389407
# Initialize a Surface object as the geometry
390408
geo = Surface(subject_id, h, surf, subjects_dir, offset)
391409
# Load in the geometry and (maybe) curvature
392410
geo.load_geometry()
393-
if curv:
411+
if geo_curv:
394412
geo.load_curvature()
395413
self.geo[h] = geo
396414

@@ -414,9 +432,9 @@ def __init__(self, subject_id, hemi, surf, curv=True, title=None,
414432
self._toggle_render(False)
415433

416434
# fill figures with brains
417-
kwargs = dict(surf=surf, curv=curv, title=None,
418-
cortex=cortex, subjects_dir=subjects_dir,
419-
bg_color=self._bg_color, offset=offset)
435+
kwargs = dict(surf=surf, geo_curv=geo_curv, geo_kwargs=geo_kwargs,
436+
geo_reverse=geo_reverse, subjects_dir=subjects_dir,
437+
bg_color=self._bg_color)
420438
brains = []
421439
brain_matrix = []
422440
for ri, view in enumerate(views):
@@ -492,6 +510,77 @@ def _set_window_properties(self, size, background, foreground):
492510
fg_color_rgb = colorConverter.to_rgb(foreground)
493511
self._fg_color = fg_color_rgb
494512

513+
def _get_geo_params(self, cortex, alpha=1.0):
514+
"""Return keyword arguments and other parameters for surface
515+
rendering.
516+
517+
Parameters
518+
----------
519+
cortex : {classic, high_contrast, low_contrast, bone, tuple}
520+
The name of one of the preset cortex styles, or a tuple
521+
with four entries as described in the return vales.
522+
alpha : float in [0, 1]
523+
Alpha level to control opacity.
524+
525+
Returns
526+
-------
527+
kwargs : dict
528+
Dictionary with keyword arguments to be used for surface
529+
rendering. For colormaps, keys are ['colormap', 'vmin',
530+
'vmax', 'alpha'] to specify the name, minimum, maximum,
531+
and alpha transparency of the colormap respectively. For
532+
colors, keys are ['color', 'alpha'] to specify the name
533+
and alpha transparency of the color respectively.
534+
reverse : boolean
535+
Boolean indicating whether a colormap should be
536+
reversed. Set to False if a color (rather than a colormap)
537+
is specified.
538+
curv : boolean
539+
Boolean indicating whether curv file is loaded and binary
540+
curvature is displayed.
541+
542+
"""
543+
colormap_map = dict(classic=(dict(colormap="Greys",
544+
vmin=-1, vmax=2,
545+
opacity=alpha), False, True),
546+
high_contrast=(dict(colormap="Greys",
547+
vmin=-.1, vmax=1.3,
548+
opacity=alpha), False, True),
549+
low_contrast=(dict(colormap="Greys",
550+
vmin=-5, vmax=5,
551+
opacity=alpha), False, True),
552+
bone=(dict(colormap="bone",
553+
vmin=-.2, vmax=2,
554+
opacity=alpha), True, True))
555+
if cortex in colormap_map:
556+
geo_params = colormap_map[cortex]
557+
elif cortex in lut_manager.lut_mode_list():
558+
geo_params = dict(colormap=cortex, vmin=-1, vmax=2,
559+
opacity=alpha), False, True
560+
elif isinstance(cortex, dict):
561+
geo_params = cortex, False, True
562+
if not geo_params[0].has_key('opacity'):
563+
geo_params[0]['opacity'] = alpha
564+
# check for None before checking len:
565+
elif cortex is None:
566+
geo_params = dict(color=(0.5, 0.5, 0.5),
567+
opacity=alpha), False, False
568+
# Test for 4-tuple specifying colormap parameters. Need to
569+
# avoid 4 letter strings and 4-tuples not specifying a
570+
# colormap name in the first position (color can be specified
571+
# as RGBA tuple, but the A value will be dropped by to_rgb()):
572+
elif (not isinstance(cortex, basestring)) and (len(cortex) == 4) and (
573+
isinstance(cortex[0], basestring)):
574+
geo_params = dict(colormap=cortex[0], vmin=cortex[1],
575+
vmax=cortex[2], opacity=alpha), cortex[3], True
576+
else:
577+
try:
578+
color = colorConverter.to_rgb(cortex)
579+
geo_params = dict(color=color, opacity=alpha), False, False
580+
except ValueError:
581+
geo_params = cortex, False, True
582+
return geo_params
583+
495584
def get_data_properties(self):
496585
""" Get properties of the data shown
497586
@@ -2341,8 +2430,8 @@ def animate(self, views, n_steps=180., fname=None, use_cache=False,
23412430

23422431
class _Hemisphere(object):
23432432
"""Object for visualizing one hemisphere with mlab"""
2344-
def __init__(self, subject_id, hemi, surf, figure, geo, curv, title,
2345-
cortex, subjects_dir, bg_color, offset, backend):
2433+
def __init__(self, subject_id, hemi, surf, figure, geo, geo_curv,
2434+
geo_kwargs, geo_reverse, subjects_dir, bg_color, backend):
23462435
if hemi not in ['lh', 'rh']:
23472436
raise ValueError('hemi must be either "lh" or "rh"')
23482437
# Set the identifying info
@@ -2357,16 +2446,12 @@ def __init__(self, subject_id, hemi, surf, figure, geo, curv, title,
23572446

23582447
# mlab pipeline mesh and surface for geomtery
23592448
self._geo = geo
2360-
if curv:
2449+
if geo_curv:
23612450
curv_data = self._geo.bin_curv
23622451
meshargs = dict(scalars=curv_data)
2363-
colormap, vmin, vmax, reverse, alpha = self._get_geo_colors(cortex)
2364-
kwargs = dict(colormap=colormap, vmin=vmin, vmax=vmax,
2365-
opacity=alpha)
23662452
else:
23672453
curv_data = None
23682454
meshargs = dict()
2369-
kwargs = dict(color=(.5, .5, .5))
23702455
meshargs['figure'] = self._f
23712456
x, y, z, f = self._geo.x, self._geo.y, self._geo.z, self._geo.faces
23722457
self._geo_mesh = mlab.pipeline.triangular_mesh_source(x, y, z, f,
@@ -2376,8 +2461,8 @@ def __init__(self, subject_id, hemi, surf, figure, geo, curv, title,
23762461
self._geo_mesh.data.cell_data.normals = None
23772462
self._geo_surf = mlab.pipeline.surface(self._geo_mesh,
23782463
figure=self._f, reset_zoom=True,
2379-
**kwargs)
2380-
if curv and reverse:
2464+
**geo_kwargs)
2465+
if geo_curv and geo_reverse:
23812466
curv_bar = mlab.scalarbar(self._geo_surf)
23822467
curv_bar.reverse_lut = True
23832468
curv_bar.visible = False
@@ -2654,46 +2739,6 @@ def _orient_lights(self):
26542739
for light in self._f.scene.light_manager.lights:
26552740
light.azimuth *= -1
26562741

2657-
def _get_geo_colors(self, cortex):
2658-
"""Return an mlab colormap name, vmin, vmax, and alpha for binary
2659-
curvature.
2660-
2661-
Parameters
2662-
----------
2663-
cortex : {classic, high_contrast, low_contrast, bone, tuple}
2664-
The name of one of the preset cortex styles, or a tuple
2665-
with five entries as described in the return vales.
2666-
2667-
Returns
2668-
-------
2669-
colormap : string
2670-
mlab colormap name
2671-
vmin : float
2672-
curv colormap minimum
2673-
vmax : float
2674-
curv colormap maximum
2675-
reverse : boolean
2676-
boolean indicating whether the colormap should be reversed
2677-
alpha : float in [0, 1]
2678-
alpha level to control opacity
2679-
2680-
"""
2681-
colormap_map = dict(classic=("Greys", -1, 2, False, 1.0),
2682-
high_contrast=("Greys", -.1, 1.3, False, 1.0),
2683-
low_contrast=("Greys", -5, 5, False, 1.0),
2684-
bone=("bone", -.2, 2, True, 1.0))
2685-
2686-
if cortex in colormap_map:
2687-
color_data = colormap_map[cortex]
2688-
elif cortex in lut_manager.lut_mode_list():
2689-
color_data = cortex, -1, 2, False, 1.0
2690-
else:
2691-
if len(cortex) == 4:
2692-
color_data = tuple(cortex) + (1.0, )
2693-
else:
2694-
color_data = cortex
2695-
return color_data
2696-
26972742
def _format_cbar_text(self, cbar):
26982743
bg_color = self._bg_color
26992744
if bg_color is None or sum(bg_color) < 2:

0 commit comments

Comments
 (0)