Skip to content

Commit 5fcc624

Browse files
committed
Remove config_opts and references to config file in surfer.viz
The Brain object can now be directly configured with keyword argument, although `config_opts` is still caught and used for backwards compatability. This commit does not fully remove the config file code, and it has not updated the example scripts to remove config_opts, but the unit tests should pass.
1 parent 4e0165b commit 5fcc624

File tree

2 files changed

+87
-97
lines changed

2 files changed

+87
-97
lines changed

surfer/tests/test_viz.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
subject_id = 'fsaverage'
1919
std_args = [subject_id, 'lh', 'inflated']
2020
data_dir = pjoin(op.dirname(__file__), '..', '..', 'examples', 'example_data')
21-
small_brain = dict(size=100)
2221

2322
overlay_fname = pjoin(data_dir, 'lh.sig.nii.gz')
2423

@@ -52,11 +51,11 @@ def test_image():
5251

5352
mlab.options.backend = 'auto'
5453
subject_id, _, surf = std_args
55-
brain = Brain(subject_id, 'both', surf=surf, config_opts=small_brain)
54+
brain = Brain(subject_id, 'both', surf=surf, size=100)
5655
brain.add_overlay(overlay_fname, hemi='lh', min=5, max=20, sign="pos")
5756
brain.save_imageset(tmp_name, ['med', 'lat'], 'jpg')
5857

59-
brain = Brain(*std_args, config_opts=small_brain)
58+
brain = Brain(*std_args, size=100)
6059
brain.save_image(tmp_name)
6160
brain.save_montage(tmp_name, ['l', 'v', 'm'], orientation='v')
6261
brain.save_montage(tmp_name, ['l', 'v', 'm'], orientation='h')
@@ -76,12 +75,20 @@ def test_brains():
7675
hemis = ['lh', 'rh']
7776
curvs = [True, False]
7877
titles = [None, 'Hello']
79-
config_opts = [{}, dict(size=(800, 800))]
78+
cortices = ["low_contrast", ("Reds", 0, 1, False)]
79+
widths = [200, "w"]
80+
heights = [400, "h"]
81+
sizes = [None, 600]
82+
backgrounds = ["white", "blue"]
83+
foregrounds = ["black", "white"]
8084
figs = [None, mlab.figure()]
8185
subj_dirs = [None, subj_dir]
82-
for surf, hemi, curv, title, co, fig, sd \
83-
in zip(surfs, hemis, curvs, titles, config_opts, figs, subj_dirs):
84-
brain = Brain(subject_id, hemi, surf, curv, title, co, fig, sd)
86+
for surf, hemi, curv, title, cort, w, h, s, bg, fg, fig, sd \
87+
in zip(surfs, hemis, curvs, titles, cortices,
88+
widths, heights, sizes,
89+
backgrounds, foregrounds, figs, subj_dirs):
90+
brain = Brain(subject_id, hemi, surf, curv, title,
91+
cort, w, h, s, bg, fg, fig, sd)
8592
brain.close()
8693
assert_raises(ValueError, Brain, subject_id, 'lh', 'inflated',
8794
subjects_dir='')
@@ -287,7 +294,7 @@ def test_probabilistic_labels():
287294
"""
288295
mlab.options.backend = 'test'
289296
brain = Brain("fsaverage", "lh", "inflated",
290-
config_opts=dict(cortex="low_contrast"))
297+
cortex="low_contrast")
291298

292299
brain.add_label("BA1", color="darkblue")
293300

@@ -322,7 +329,7 @@ def test_animate():
322329
"""Test animation
323330
"""
324331
mlab.options.backend = 'auto'
325-
brain = Brain(*std_args, config_opts=small_brain)
332+
brain = Brain(*std_args, size=100)
326333
brain.add_morphometry('curv')
327334
tmp_name = mktemp() + '.avi'
328335
brain.animate(["m"] * 3, n_steps=2)

surfer/viz.py

Lines changed: 71 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212

1313
from mayavi import mlab
1414
from mayavi.tools.mlab_scene_model import MlabSceneModel
15+
from mayavi.core import lut_manager
1516
from mayavi.core.ui.api import SceneEditor
1617
from mayavi.core.ui.mayavi_scene import MayaviScene
1718
from traits.api import (HasTraits, Range, Int, Float,
1819
Bool, Enum, on_trait_change, Instance)
1920

2021
from . import utils, io
21-
from .config import config
2222
from .utils import (Surface, verbose, create_color_lut, _get_subjects_dir,
2323
string_types, assert_ffmpeg_is_available, ffmpeg)
2424

@@ -296,8 +296,18 @@ class Brain(object):
296296
(default: True)
297297
title : str
298298
title for the window
299-
config_opts : dict
300-
options to override visual options in config file
299+
cortex : str or tuple
300+
specifies how binarized curvature values are rendered.
301+
either the name of a preset PySurfer cortex colorscheme (one of
302+
'classic', 'bone', 'low_contrast', or 'high_contrast'), or the
303+
name of mayavi colormap, or a tuple with values (colormap, min,
304+
max, reverse) to fully specify the curvature colors.
305+
width, height : floats
306+
width and height (in pixels) of the display window
307+
size : float
308+
specify a square display window, overriding the width and height
309+
background, foreground : matplotlib colors
310+
color of the background and foreground of the display window
301311
figure : list of instances of mayavi.core.scene.Scene | None
302312
If None, a new window will be created with the appropriate
303313
views.
@@ -318,10 +328,28 @@ class Brain(object):
318328
----------
319329
brains : list
320330
List of the underlying brain instances.
331+
321332
"""
322333
def __init__(self, subject_id, hemi, surf, curv=True, title=None,
323-
config_opts={}, figure=None, subjects_dir=None,
324-
views=['lat'], show_toolbar=False, offscreen=False):
334+
cortex="classic", width=800, height=800, size=None,
335+
background="black", foreground="white", figure=None,
336+
subjects_dir=None, views=['lat'],
337+
show_toolbar=False, offscreen=False, config_opts=None):
338+
339+
# Keep backwards compatability
340+
if config_opts is not None:
341+
msg = ("The `config_opts` dict has been deprecated and will "
342+
"be removed in future versions. You should update your "
343+
"code and pass these options directly to the `Brain` "
344+
"constructor.")
345+
warn(msg)
346+
cortex = config_opts.get("cortex", cortex)
347+
width = config_opts.get("width", width)
348+
height = config_opts.get("height", height)
349+
size = config_opts.get("size", size)
350+
background = config_opts.get("background", background)
351+
foreground = config_opts.get("foreground", foreground)
352+
325353
col_dict = dict(lh=1, rh=1, both=1, split=2)
326354
n_col = col_dict[hemi]
327355
if hemi not in col_dict.keys():
@@ -360,7 +388,8 @@ def __init__(self, subject_id, hemi, surf, curv=True, title=None,
360388
self.geo[h] = geo
361389

362390
# deal with making figures
363-
self._set_window_properties(config_opts)
391+
self._set_window_properties(width, height, size,
392+
background, foreground)
364393
figures, _v = _make_viewer(figure, n_row, n_col, title,
365394
self._scene_size, offscreen)
366395
self._figures = figures
@@ -371,6 +400,7 @@ def __init__(self, subject_id, hemi, surf, curv=True, title=None,
371400
if f.scene is not None:
372401
f.scene.background = self._bg_color
373402
f.scene.foreground = self._fg_color
403+
374404
# force rendering so scene.lights exists
375405
_force_render(self._figures, self._window_backend)
376406
self.toggle_toolbars(show_toolbar)
@@ -379,7 +409,7 @@ def __init__(self, subject_id, hemi, surf, curv=True, title=None,
379409

380410
# fill figures with brains
381411
kwargs = dict(surf=surf, curv=curv, title=None,
382-
config_opts=config_opts, subjects_dir=subjects_dir,
412+
cortex=cortex, subjects_dir=subjects_dir,
383413
bg_color=self._bg_color, offset=offset)
384414
brains = []
385415
brain_matrix = []
@@ -441,39 +471,19 @@ def _toggle_render(self, state, views=None):
441471
_force_render(self._figures, self._window_backend)
442472
return views
443473

444-
def _set_window_properties(self, config_opts):
445-
"""Set window properties using config_opts"""
474+
def _set_window_properties(self, width, height, size,
475+
background, foreground):
476+
"""Set window properties that are used elsewhere."""
446477
# old option "size" sets both width and height
447-
if "size" in config_opts:
448-
width = config_opts["size"]
449-
height = width
450-
451-
if "width" in config_opts:
452-
width = config_opts["width"]
453-
else:
454-
width = config.getfloat("visual", "width")
455-
if 'height' in config_opts:
456-
height = config_opts['height']
457-
else:
458-
height = config.getfloat("visual", "height")
459-
self._scene_size = (height, width)
478+
if size is not None:
479+
width, height = size, size
480+
self._scene_size = height, width
460481

461-
try:
462-
bg_color_name = config_opts['background']
463-
except KeyError:
464-
bg_color_name = config.get("visual", "background")
465-
if bg_color_name is not None:
466-
bg_color_code = colorConverter.to_rgb(bg_color_name)
467-
else:
468-
bg_color_code = None
469-
self._bg_color = bg_color_code
482+
bg_color_rgb = colorConverter.to_rgb(background)
483+
self._bg_color = bg_color_rgb
470484

471-
try:
472-
fg_color_name = config_opts['foreground']
473-
except KeyError:
474-
fg_color_name = config.get("visual", "foreground")
475-
fg_color_code = colorConverter.to_rgb(fg_color_name)
476-
self._fg_color = fg_color_code
485+
fg_color_rgb = colorConverter.to_rgb(foreground)
486+
self._fg_color = fg_color_rgb
477487

478488
def get_data_properties(self):
479489
""" Get properties of the data shown
@@ -693,45 +703,24 @@ def _get_display_range(self, scalar_data, min, max, sign):
693703
else:
694704
range_data = np.abs(scalar_data)
695705

696-
# Get the min and max from among various places
697-
if min is None:
698-
try:
699-
min = config.getfloat("overlay", "min_thresh")
700-
except ValueError:
701-
min_str = config.get("overlay", "min_thresh")
702-
if min_str == "robust_min":
703-
min = stats.scoreatpercentile(range_data, 2)
704-
elif min_str == "actual_min":
705-
min = range_data.min()
706-
else:
707-
min = 2.0
708-
warn("The 'min_thresh' value in your config value must be "
709-
"a float, 'robust_min', or 'actual_min', but it is "
710-
"%s. I'm setting the overlay min to the config "
711-
"default of 2" % min)
706+
# Get a numeric value for the scalar minimum
707+
if min == "robust_min":
708+
min = stats.scoreatpercentile(range_data, 2)
709+
elif min == "actual_min":
710+
min = range_data.min()
712711

713-
if max is None:
714-
try:
715-
max = config.getfloat("overlay", "max_thresh")
716-
except ValueError:
717-
max_str = config.get("overlay", "max_thresh")
718-
if max_str == "robust_max":
719-
max = stats.scoreatpercentile(scalar_data, 98)
720-
elif max_str == "actual_max":
721-
max = range_data.max()
722-
else:
723-
max = stats.scoreatpercentile(range_data, 98)
724-
warn("The 'max_thresh' value in your config value must be "
725-
"a float, 'robust_min', or 'actual_min', but it is "
726-
"%s. I'm setting the overlay min to the config "
727-
"default of robust_max" % max)
712+
# Get a numeric value for the scalar maximum
713+
if max == "robust_max":
714+
max = stats.scoreatpercentile(scalar_data, 98)
715+
elif max == "actual_max":
716+
max = range_data.max()
728717

729718
return min, max
730719

731720
###########################################################################
732721
# ADDING DATA PLOTS
733-
def add_overlay(self, source, min=None, max=None, sign="abs", name=None,
734-
hemi=None):
722+
def add_overlay(self, source, min=2, max="robust_max", sign="abs",
723+
name=None, hemi=None):
735724
"""Add an overlay to the overlay dict from a file or array.
736725
737726
Parameters
@@ -2260,7 +2249,7 @@ def animate(self, views, n_steps=180., fname=None, use_cache=False,
22602249
class _Hemisphere(object):
22612250
"""Object for visualizing one hemisphere with mlab"""
22622251
def __init__(self, subject_id, hemi, surf, figure, geo, curv, title,
2263-
config_opts, subjects_dir, bg_color, offset, backend):
2252+
cortex, subjects_dir, bg_color, offset, backend):
22642253
if hemi not in ['lh', 'rh']:
22652254
raise ValueError('hemi must be either "lh" or "rh"')
22662255
# Set the identifying info
@@ -2278,7 +2267,7 @@ def __init__(self, subject_id, hemi, surf, figure, geo, curv, title,
22782267
if curv:
22792268
curv_data = self._geo.bin_curv
22802269
meshargs = dict(scalars=curv_data)
2281-
colormap, vmin, vmax, reverse = self._get_geo_colors(config_opts)
2270+
colormap, vmin, vmax, reverse = self._get_geo_colors(cortex)
22822271
kwargs = dict(colormap=colormap, vmin=vmin, vmax=vmax)
22832272
else:
22842273
curv_data = None
@@ -2568,13 +2557,14 @@ def _orient_lights(self):
25682557
for light in self._f.scene.light_manager.lights:
25692558
light.azimuth *= -1
25702559

2571-
def _get_geo_colors(self, config_opts):
2560+
def _get_geo_colors(self, cortex):
25722561
"""Return an mlab colormap name, vmin, and vmax for binary curvature.
25732562
25742563
Parameters
25752564
----------
2576-
config_opts : dict
2577-
dictionary of config file "visual" options
2565+
cortex : {classic, high_contrast, low_contrast, bone, tuple}
2566+
The name of one of the preset cortex styles, or a tuple
2567+
with four entries as described in the return vales.
25782568
25792569
Returns
25802570
-------
@@ -2593,19 +2583,12 @@ def _get_geo_colors(self, config_opts):
25932583
low_contrast=("Greys", -5, 5, False),
25942584
bone=("bone", -.2, 2, True))
25952585

2596-
try:
2597-
cortex_color = config_opts['cortex']
2598-
except KeyError:
2599-
cortex_color = config.get("visual", "cortex")
2600-
try:
2601-
color_data = colormap_map[cortex_color]
2602-
except KeyError:
2603-
warn(""
2604-
"The 'cortex' setting in your config file must be one of "
2605-
"'classic', 'high_contrast', 'low_contrast', or 'bone', "
2606-
"but your value is '%s'. I'm setting the cortex colormap "
2607-
"to the 'classic' setting." % cortex_color)
2608-
color_data = colormap_map['classic']
2586+
if cortex in colormap_map:
2587+
color_data = colormap_map[cortex]
2588+
elif cortex in lut_manager.lut_mode_list():
2589+
color_data = cortex, -1, 2, False
2590+
else:
2591+
color_data = cortex
26092592

26102593
return color_data
26112594

0 commit comments

Comments
 (0)