Skip to content

Commit 2429271

Browse files
committed
Merge pull request #53 from Eric89GXL/multi-view-rebase
ENH: Use multiple views simultaneously
2 parents 98ba09a + 5fad8c9 commit 2429271

26 files changed

+2182
-1225
lines changed

CHANGES

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
PySurfer Changes
22
================
33

4+
Version 0.4
5+
-------------
6+
7+
Enhancements
8+
~~~~~~~~~~~~
9+
10+
- Display data from both hemispheres simultaneously
11+
- Display multiple views simultaneously
12+
- Toggling Mayavi toolbars
13+
- Use nibabel for IO functions
14+
415
Version 0.3.1
516
-------------
617

bin/pysurfer

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,16 @@ if __name__ == '__main__':
2424
# boot up mlab/IPython
2525
if len(sys.argv) > 3:
2626
subjects_dir = os.environ['SUBJECTS_DIR']
27-
surf_file = os.path.join(subjects_dir,
28-
"%s/surf/%s.%s" % tuple(sys.argv[1:4]))
29-
if not os.path.exists(surf_file):
30-
sys.exit("ERROR: Could not find %s" % surf_file)
27+
if sys.argv[2] in ['both', 'split']:
28+
hemi_checks = ['lh', 'rh']
29+
else:
30+
hemi_checks = [sys.argv[2]]
31+
for h in hemi_checks:
32+
surf_file = os.path.join(subjects_dir,
33+
"%s/surf/%s.%s" % (sys.argv[1], h,
34+
sys.argv[3]))
35+
if not os.path.exists(surf_file):
36+
sys.exit("ERROR: Could not find %s" % surf_file)
3137

3238
if not is_ipython:
3339
# Parse the args so that --help exits back to the shell
@@ -62,10 +68,11 @@ if __name__ == '__main__':
6268
argdict = args.__dict__
6369
config_opts = dict([(k, v) for k, v in argdict.items()
6470
if k in confkeys and v])
71+
views = args.views
6572

6673
# Load up the figure and underlying brain object
6774
b = Brain(args.subject_id, args.hemi, args.surf, args.curv,
68-
args.title, config_opts=config_opts)
75+
args.title, views=views, config_opts=config_opts)
6976

7077
# Maybe load some morphometry
7178
if args.morphometry is not None:

doc/_static/split_view.png

115 KB
Loading

doc/conf.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545

4646
# General information about the project.
4747
project = u'PySurfer'
48-
copyright = u'2011-2012, Michael Waskom, Alexandre Gramfort, Scott Burns, Martin Luessi'
48+
copyright = (u'2011-2013, Michael Waskom, Alexandre Gramfort, Scott Burns, '
49+
'Martin Luessi, Eric Larson')
4950

5051
# Generate the plots for the gallery
5152
plot_gallery = True
@@ -222,5 +223,5 @@
222223
# (source start file, name, description, authors, manual section).
223224
man_pages = [
224225
('index', 'pysurfer', u'PySurfer Documentation',
225-
[u'Michael Waskom, Alexandre Gramfort, Scott Burns'], 1)
226+
[u'Michael Waskom, Alexandre Gramfort, Scott Burns, Eric Larson'], 1)
226227
]

doc/documentation/config_file.rst

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ There are several aspects of how PySurfer looks and behaves that you may
77
wish to customize but do not want to have to alter every time you
88
instantiate a Brain object or use the command-line interface. To
99
facilitate this, PySurfer allows you to set certain options with a
10-
standard Python config file.
10+
standard Python config file.
1111

1212
When a new Brain object is created (either in a script or via the
1313
command-line), it can read configuration options from one of two places:
@@ -27,9 +27,14 @@ Visual
2727

2828
*size*
2929
How large the sides of the display window should be (measured in
30-
pixels.) The window is always square, so just give one value, and
31-
it will be used for the height and width. (Possible values: any
32-
positive number.)
30+
pixels.) When using this option, the window will be square, and
31+
"size" it will be used for the height and width. (Possible values:
32+
any positive number.)
33+
34+
*width* and *height*
35+
The size of the window. This is an alternative to size, allowing
36+
the width and height to be set independently. (Possible values:
37+
any positive number.)
3338

3439
*default_view*
3540
Which view should be shown at the beginning of a visualization
@@ -49,3 +54,8 @@ Overlay
4954
provided when calling the :meth:`Brain.add_overlay` method.
5055
(Possible values: any float, ``robust_max``, ``actual_max``.)
5156

57+
Options
58+
-------
59+
*logging_level*
60+
Amount of verbosity to use in outputting status messages.
61+
(Possible values: ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR``.)

doc/documentation/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ Documentation
77

88
./command_line
99
./custom_viz
10+
./split_brain
1011
./config_file
1112

doc/documentation/split_brain.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
.. _split_brain:
2+
3+
Working with a split-screen brain
4+
=================================
5+
6+
The split-screen view can be activated by using the argument ``hemi='split'``.
7+
Using this option will put views of the left hemisphere in consecutive
8+
vertical frames on the left, and views of the right hemisphere in
9+
consecutive vertical frames on the right. For example, running the following::
10+
11+
brain = Brain('fsaverage', 'split', 'inflated', views=['lat', 'med'])
12+
13+
Will produce a window with two columns (hemispheres) and two rows (the
14+
lateral and medial views, respectively), shown below.
15+
16+
.. image:: ../../_static/split_view.png
17+
18+
Adding and displaying data
19+
--------------------------
20+
21+
Data can be added to either hemisphere using the same functions that are
22+
normally used, e.g. ``add_data``, ``add_overlay``, ``add_morphometry``.
23+
The objects are automatically shown on all views of the brain. When
24+
calling these functions, the ``hemi`` keyword argument can be set to
25+
``hemi='lh'`` or ``hemi='rh'`` to specify the hemisphere to plot to.
26+
In some instances (e.g., ``add_morphometry``), if no keyword argument
27+
is provided, PySurfer will attempt to load data or both hemispheres
28+
automtically.
29+
30+
Note that the ``show_view`` method accepts arguments for the ``row`` and
31+
``col`` values, which allow the user to control which ``Brain`` panel
32+
gets the updated view.
33+
34+
Caveats
35+
-------
36+
The multi-view support is available thanks to the capabilities of the
37+
TraitsUI framework. However, due to some limitations in the implementation
38+
of TraitsUI, there is no guarantee that a set of scripted commands will
39+
result in a painted window when the user may think it will. For
40+
example, making a series of calls to ``brain.add_label()`` followed by
41+
``brain.save_image('out.png')`` may result in some or all of the labels
42+
being absent from the saved ``out.png``. While we have implemented some
43+
workarounds to help prevent this occurrance, we cannot guarantee it will
44+
work. Thus we recommend that for critical non-interactive plotting (e.g.,
45+
if scripting figure generation for a paper) only a single view is used
46+
with ``hemi`` set to ``'lh'``, ``'rh'``, or ``'both'``. This will use a single,
47+
pure Mayavi window, thereby bypassing TraisUI entirely -- this helps
48+
guarantee that drawing commands result in updated visual display.

doc/index.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ MRI and MEG data.
1010

1111
PySurfer offers both a command-line interface designed to broadly
1212
replicate Freesurfer's Tksurfer program as well as a Python library
13-
for writing scripts to efficiently explore complex datasets.
13+
for writing scripts to efficiently explore complex datasets.
1414

1515
Contents
1616
--------
1717

1818
.. toctree::
1919
:maxdepth: 2
20-
20+
2121
install
2222
examples/index.rst
2323
documentation/index.rst
@@ -33,6 +33,8 @@ Scott Burns, Harvard Med. School MGH Martinos Center
3333

3434
Martin Luessi, Harvard Med. School MGH Martinos Center
3535

36+
Eric Larson, University of Washington ILABS
37+
3638
License
3739
-------
3840

doc/sphinxext/gen_rst.py

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -148,66 +148,51 @@ def generate_file_rst(fname, target_dir, src_dir, plot_gallery):
148148
this_template = rst_template
149149
last_dir = os.path.split(src_dir)[-1]
150150
# to avoid leading . in file names
151-
if last_dir == '.': last_dir = ''
152-
else: last_dir += '_'
153-
short_fname = last_dir + fname
151+
if last_dir == '.':
152+
last_dir = ''
153+
else:
154+
last_dir += '_'
155+
short_fname = last_dir + fname
154156
src_file = os.path.join(src_dir, fname)
155157
example_file = os.path.join(target_dir, fname)
156158
shutil.copyfile(src_file, example_file)
157159
if plot_gallery and fname.startswith('plot'):
158160
# generate the plot as png image if file name
159161
# starts with plot and if it is more recent than an
160162
# existing image.
161-
if not os.path.exists(
162-
os.path.join(target_dir, 'images')):
163+
if not os.path.exists(os.path.join(target_dir, 'images')):
163164
os.makedirs(os.path.join(target_dir, 'images'))
164165
image_file = os.path.join(target_dir, 'images', image_name)
165166
if (not os.path.exists(image_file) or
166-
os.stat(image_file).st_mtime <=
167-
os.stat(src_file).st_mtime):
167+
os.stat(image_file).st_mtime <= os.stat(src_file).st_mtime):
168168
print 'plotting %s' % fname
169169
import matplotlib.pyplot as plt
170170
plt.close('all')
171171
try:
172-
try:
173-
from mayavi import mlab
174-
except ImportError:
175-
from enthought.mayavi import mlab
176-
mlab.close(all=True)
177-
except:
178-
pass
179-
180-
try:
181-
execfile(example_file, {'pl' : plt})
182-
facecolor = plt.gcf().get_facecolor() # hack to keep black bg
172+
brain = None
173+
global plt
174+
global brain
175+
execfile(example_file, globals())
176+
facecolor = plt.gcf().get_facecolor() # hack to keep black bg
183177
if facecolor == (0.0, 0.0, 0.0, 1.0):
184178
plt.savefig(image_file, facecolor='black')
185179
else:
186180
plt.savefig(image_file)
187181

188-
try:
189-
try:
190-
from mayavi import mlab
191-
except ImportError:
192-
from enthought.mayavi import mlab
193-
194-
e = mlab.get_engine()
195-
if len(e.scenes) > 0:
196-
mlab.savefig(image_file, size=(400, 400))
197-
except:
198-
pass
182+
brain.save_image(image_file)
183+
brain.close()
199184

200185
except:
201-
print 80*'_'
186+
print 80 * '_'
202187
print '%s is not compiling:' % fname
203188
traceback.print_exc()
204-
print 80*'_'
189+
print 80 * '_'
205190
this_template = plot_rst_template
206191

207192
docstring, short_desc, end_row = extract_docstring(example_file)
208193

209-
f = open(os.path.join(target_dir, fname[:-2] + 'rst'),'w')
210-
f.write( this_template % locals())
194+
f = open(os.path.join(target_dir, fname[:-2] + 'rst'), 'w')
195+
f.write(this_template % locals())
211196
f.flush()
212197

213198

doc/surfer.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
[visual]
2+
width=600
3+
height=600
24
background=black
35
cortex=classic
46
default_view=lateral

0 commit comments

Comments
 (0)