One of the reasons why you may want to use NeuroElf is for visualization. And while the online browsing capability is certainly helpful in identifying good visualizations, it can then be very tedious to create an entire series of them (e.g. for different subjects, etc.) by using the GUI directly. Hence I tried to make most of the steps you can perform via the mouse or keyboard scriptable.
Importantly, once the GUI is loaded, pretty much all functions are available by performing a call of the form:
neuroelf_gui('sub_function', 'argument1', [2, 3, 4], {'a', 'b'});
And as a more practical example, let's introduce the screenshot function:
neuroelf_gui('help', 'screenshot')
which returns the help text associated with this function:
ne_screenshot - create a screenshot file FORMAT: ne_screenshot(SRC, EVT, [, object [, filename [, hq]]]) Input fields: SRC, EVT Matlab handle callback inputs (discarded) object can be empty, 0 (main fig), or figure/axes handle filename optional filename (otherwise requested) hq high-quality flag (set to 'high-q' for oversampling) No output fields. Example: neuroelf_gui('screenshot', 'BS123456', 'screenshot_1234.png', 'high-q'); creates the file 'screenshot_1234.png' with high-quality oversampling from satellite window with ID 'BS123456'
Importantly, an “undocked” window is assigned an 8-character long token, which can then be used to address this window from the command line. To script an entire (and useful) function, I would assume the following steps must be performed (with some of them being optional):
I'll write up another page about this, but briefly put, to see if a file is loaded, the easiest way I can think of would be a try/catch construction:
% store filename in a variable, % which can be constructed from arguments to a function! objectfilename = '/Users/Jochen/Documents/interesting_stats.vmp'; objectfiletype = 'vmp'; % access to the loaded objects via the xff constructor x = xff; % then attempt to access this file try object = x.Document(objectfilename); catch try object = xff(objectfilename); if ~isxff(object, objectfiletype) error('INVALID_XFF_FILE'); end catch error('script:error', 'File %s not readable.', objectfilename); end end
And once the object is available, it can easily be added to the GUI (and made the current object) using
object.Browse;
There are several options, but in general, you would probably want to achieve at the very least the objectives of loading up all the surfaces you need, match the corresponding surface maps (to each of them, if you want to display multiple surfaces), and finally select the surface(s) you want to display together with a preferred view (angle, etc.).
The call that makes an object current also allows to specify which map (or volume) is to be shown in the viewer:
vmp.Browse(map_number);
In addition, the selection (click into the maps list) issues a call that can be scripted as well:
neuroelf_gui('setcstatmap', map_number); % for VMPs or surface_object.Browse; % make surface_object the current object neuroelf_gui('setcsrfstatmap', map_number); % select SMPs -- requires matching number of vertices
To generate a scenery, multiple surfaces (or DTI fiber tracts) can be combined in a view. The function call for this is
neuroelf_gui('sceneryselect', {surface_object1, surface_object2}); % for the main viewer window or neuroelf_gui('sceneryselect', {surface_object1, surface_object2}, 'BS123456'); % for the satellite with ID BS123456
Sometimes it is also important to be able to change surface properties (e.g. transparency or surface-specific translation values). For this, you can use
neuroelf_gui('setsceneprops', surface_object1, {[0, 0, 0], [0 0 0], [1], [.5], 'f'});
Whereas the elements in the cell array are (in order):
If the surface is displayed in an external window, it is important to re-select the scenery afterwards (as the surface object itself does only carry a reference to the MATLAB patch UI object in the main viewer):
neuroelf_gui('setsceneprops', surface_object1, {[0, 0, 0], [0 0 0], [1], [.5], 'f'}); neuroelf_gui('sceneryselect', {surface_object1, surface_object2}, 'BS123456');
While the main viewer has several advantages when it comes to manipulating objects (e.g. smoothing surfaces, etc.), the biggest shortcoming is the fact that the axes object in MATLAB isn't the only visible portion of the figure, which makes it difficult to take a screenshot of the surface viewer alone.
For this purpose, the current view (slicing, surface, or rendering) can be “undocked” into a separate window using
[hSat, tags, iSat] = neuroelf_gui('undock');
The iSat variable then contains the 8-character token (window ID) that can be used to further address this window
And the first thing that may be of interest is to resize this undocked view
neuroelf_gui('satresize', iSat, [width, height]);
Another thing you may want to do is setting the background color:
neuroelf_gui('satsetcolor', iSat, [red, green, blue]);
whereas each of red, green, and blue are 0-255 coded RGB values (so use [255, 255, 255] for white).
Naturally, it is important to be able to control what is being shown (from what angle and overall zoom, etc.). For this, use the function “setsurfpos”:
neuroelf_gui('setsurfpos', iSat, {azi, zen, trans, zoom, timeindex});
The angles (azi and zen) are given in degrees (not radians), the translation must be 1×3 double, although the first element will be discarded (no translation in X direction, where X is left/right along the brain axis). The zoom must be within .2 and 5, and the timeindex can be used for morph effects and color changes (e.g. for a surface-space sampled whole-brain time course average).
Finally, to take a screenshot (save an image of the surface to disk), use
neuroelf_gui('screenshot', iSat, image_filename, 'high-q');
Whereas the image_filename can of course be a sprintf(…) expression within a loop. The “high-q” flag instructs the function to use oversampling (which really is only useful for surface windows, though).
So, an entire script could look like this:
% files to load/display lh_srf = '/Users/Jochen/Documents/demo/lh.srf'; rh_srf = '/Users/Jochen/Documents/demo/rh.srf'; % VMP (will be sampled on surfaces) stast_vmp = '/Users/Jochen/Documents/demo/stats.vmp'; % load objects (without loading again) x = xff; try lh = x.Document(lh_srf); catch lh = xff(lh_srf); end try rh = x.Document(rh_srf); catch rh = xff(rh_srf); end try vmp = x.Document(stats_vmp); catch vmp = xff(stats_vmp); end % adding all to viewer vmp.Browse; lh.Browse; rh.Browse; % set in scenery neuroelf_gui('sceneryselect', {lh, rh}); % then sample the stats [lhsmp, rhsmp] = neuroelf_gui('vmp_createsmp'); % undock the window [hSat, tags, iSat] = neuroelf_gui('undock'); % resize satellite neuroelf_gui('satresize', iSat, [1080, 720]); % set color (to white) neuroelf_gui('satsetcolor', iSat, [255, 255, 255]); % loop over a rotation (create movie frames) mfc = 1; for fc = [90:360, 1:90] % set position neuroelf_gui('setsurfpos', iSat, {fc, 15, [0, 0, 0], 1, 0}); % screenshot neuroelf_gui('screenshot', iSat, sprintf('movieframe%03d.png', mfc), 'high-q'); % increase counter mfc = mfc + 1; end % delete satellite neuroelf_gui('closesatwindow', iSat); % unload created objects rhsmp.ClearObject; lhsmp.ClearObject;