This is a simple example to illustrate how to write your own custom 'analysis' code and functions to integrate with mrTools-4.5. The function writes an animated gif file that shows the mean or median fMRI/EPI data over time in false color, superimposed on your inplane anatomies. Not particularly life-changing, but quite useful for (0) learning how to get started coding, (1) inspecting whether you inplane anatomies and EPI data are aligned (2) how bad distortions of the EPI data is compared to nondistorted anatomy and (3) impressing your audience with moving false-color images if they like that kind of thing.
Things you will need: most recent mrTools-4.5 install. svn update if you are not sure. The OSX command line tool gifmerge for turning individual gif images into animated gif. If you have FSL installed on your machine, you should have it. Try which gifmerge or gifmerge at the Terminal prompt. It's also handy to have the imagemagick convert tools http://www.imagemagick.org/script/binary-releases.php#macosx available.
matlab gif-writing is a pain)
Usual pre-amble with some comments on how to use the function. You can save the function anywhere on your matlab path. Its only input is the mrLoadRet view. So to use the function, the user will have to keep hold of it:
v = newView; mrSliceExportTest( v )
Open a new file called mrSliceExport in your editor and start adding to the file:
% mrSliceExportTest - output series of images across all slices % % usage: [ ] = mrSliceExportTest( v ) % by: denis schluppeck % date: 2007-11-22 % $Id: mrSliceExportTest.m,v 1.1 2008/01/25 17:12:20 ds1 Exp $: % inputs: v % outputs: % % purpose: export merged images of EPI data and underlying anatomy to an animated gif % % e.g: v = mrLoadRet; mrSliceExport( v ); % function [ ]=mrSliceExportTest( v ) % make sure user supplies input if nargin < 1 help mrSliceExportTest return end % get access to mrTools global variables mrGlobals
We assume that the user has been good and installed the imagemagick tools for converting images and the gifmerge program. Also he/she should have calculated the timeSeriesStats for the current scan/group. If not, the code just warns and returns:
% check that the the timeSeriesStats have been calculated analysisdir = sprintf('%s/timeSeriesStats',viewGet(v,'datadir')); if ~exist(analysisdir, 'dir') mrWarnDlg('(mrSliceExportTest) You need to calculate timeSeriesStats first') return end % check that gifmerge and /usr/local/convert are installed for imageconversion [status,result]=system('which convert'); if status == 0 % unix success mrDisp(sprintf('(mrSliceExportTest) imagemagick "convert" found: %s', result)); else mrWarnDlg('(mrSliceExportTest) You need to install imagemagick first...'); return end [status,result]=system('which gifmerge'); if status == 0 % unix success mrDisp(sprintf('(mrSliceExportTest) "gifmerge" found: %s', result)); else mrWarnDlg('(mrSliceExportTest) you need to install gifmerge first...'); return end
The next lines of code just load in the data from the analysis performed previously. For good measure read in the anatomy image again; this also lets the user specify another anatomy image (maybe the volume anatomy):
% load in timeSeriesStatistics v = loadAnalysis(v, 'timeSeriesStats', analysisdir); % load anatomy v = loadAnat(v);
By changing the type of analysis you are loading in, you can obviously change the overlay. You could use similar code to superimpose e.g. functional maps on very high resolution anatomies by loading the corresponding files.
This bit of code illustrates the power of the viewGet command - basically anything that you might ever want to query is accessible by the viewGet/viewSet commands. To see what's available for reading/writing type viewGet (or viewSet) at the matlab prompt and you will get a nicely formatted list of all the parameters. The code switches to the median view (which is the 2nd entry in the cell array of statistical maps), and gets various paramters. We then get the medianData and calculate its 5 and 95 percentiles to give the colormap a smaller range to display.
% the timeSeriesStats data contains several statistics; #2 is the median. % let's grab that. v = viewSet(v, 'curoverlay', 2); viewNum = viewGet(v,'viewnum'); curGroup = viewGet(v,'curgroup'); curScan = viewGet(v,'curscan'); curOverlay = viewGet(v,'currentoverlay'); % set the range of displayed median values to 5 and 95 percentile medianData = viewGet(v,'overlaydata',curScan, curOverlay); robustRange = prctile(medianData(medianData>0), [5 95]); % clip can handle n-d data, use nanclip to set values to nan (instead of cmin,max) robustMedianData = nanclip(medianData, robustRange(1), robustRange(2));
Next set the display range used by the mrLoadRet GUI and the alpha transparency…
v = viewSet(v,'overlaymin', robustRange(1)); v = viewSet(v,'overlaymax', robustRange(2)); % for alpha transparency, have to go via mlrGuiSet -- is this bad? mlrGuiSet(v,'alpha', 0.5);
Get info on how many slices we need to process. Next create a temporary directory, which we will clean up again later.
% loop over slices and get images nSlices = viewGet(v,'nslices'); % clear a variable img = ; % make a temporary folder called '.tmptif' tmpdir = sprintf('%s/.tmptif',viewGet(v,'datadir')); % ignore warnings about directory already existing! warning('off','MATLAB:MKDIR:DirectoryExists'); mkdir(tmpdir); warning('on','MATLAB:MKDIR:DirectoryExists');
Loop over slices, display, grab image, write to tiff and convert in place to gif (using the OSX command line tool).
for ii = 1:nSlices mlrGuiSet(v, 'slice', ii); refreshMLRDisplay(viewNum); disp(sprintf('..rendering slice %d to %s..',ii, tmpdir)); img(:,:,1:3,ii) = refreshMLRDisplay(viewNum); mglWaitSecs(0.1); % let the GUI catch up fname = sprintf('%sim%02d.tif', tmpdir,ii); imwrite(img(:,:,1:3,ii), fname , 'tif'); % convert to gif right here. % could increase imagesize by adding an option % convertcmd = sprintf('convert %s -resize 200% %s ' ,fname , strrep(fname, '.tif','.gif')); convertcmd = sprintf('convert %s %s', fname, strrep(fname, '.tif', '.gif')); system(convertcmd); end
The unix tool gifmerge glues all of the gif frames together with some options: frame time 50, means 0.5s, -l0 means loop forever.
% gifmerge - merge all the gif images together. animgifname = sprintf('%s/animatedGif.gif', viewGet(v,'datadir')); mrDisp(sprintf('(mrSliceExport) writing animated gif to %s',animgifname)) system(sprintf('gifmerge -50 -l0 %s/*.gif > %s', tmpdir, animgifname ));
If you haven't used the Mac OSX command open yet, learn about it with man open in the Terminal. It's really useful for opening image files up in preview, text files in TextEdit, etc. (it's actually smart about filetypes, but we need to help it out here and point it to Safari browser).
% open in safari... mrDisp(sprintf('(mrSliceExport) opening up in Safari.app')) system(sprintf('open -a Safari %s', animgifname));
% clean up. mrDisp(sprintf('(mrSliceExport) cleaning up temporary directoryn')) system(sprintf('rm -r %s', tmpdir )); return;