Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
mrtools:scripting [2008/11/19 17:42]
justin
mrtools:scripting [2009/06/11 01:21] (current)
Line 1: Line 1:
 +
 +====== ​ Example function illustrating how to access data with viewGet/​viewSet ​ ======
 +
 +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  (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 funky moving false-color images (Tony Movshon'​s favourite!).
 +
 +**Things you will need:** most recent mrTools-4.5 install. **cvs 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.
 +
 +(Download the whole file here) //! uploads of non-media filetypes disabled !// .
 +
 +=====  Overview of code  =====
 +
 +  - function definition
 +  - checking that all directories and unix tools are available on users machine
 +  - loading in previous analysis (timeSeriesStats) and the anatomy
 +  - getting information about number of slices, range of data, etc. using **viewGet**
 +  - set range of overlay colors
 +  - step through slices, render each one, grab image, save to tiff and convert to gif (because matlab gif-writing is a pain)
 +  - glue all gif images together to make an animated gif
 +  - open the resulting image up in safari (which can display animated gifs dynamically)
 +  - clean up by removing temporary files
 +
 +=====  Implementation ​ =====
 +
 +====  1. Function definition ​ ====
 +
 +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:
 +
 +<code matlab>
 + v = mrLoadRet
 + ​mrSliceExport( v )
 +</​code>​
 +
 +Open a new file called **mrSliceExport** in your editor and start adding to the file:
 +
 +<code matlab>
 + % 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 [[| ]]=mrSliceExport( v )
 + 
 + % make sure user supplies input
 + if nargin < 1 
 +   help mrSliceExport
 +   ​return
 + end
 + 
 + % get access to mrTools global variables ​
 + ​mrGlobals
 +</​code>​
 +
 +====  2. Checking directories and unix tools are available ​ ====
 +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:
 +
 +<code matlab>
 + % check that the the timeSeriesStats have been calculated
 + ​analysisdir = [[viewGet(v,'​datadir'​)|'/​timeSeriesStats'​]];​
 + if ~exist(analysisdir,​ '​dir'​)
 +   ​mrWarnDlg('​(uhoh) 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('​imagemagick "​convert"​ found: %s', result)); ​
 + else
 +   ​mrWarnDlg('​(mrSliceExport) you need to install imagemagick first...'​);​
 +   ​return
 + end
 + 
 + ​[[status,​|result]]=system('​which gifmerge'​);​
 + if status == 0 % unix success
 +   ​mrDisp(sprintf('"​gifmerge"​ found: %s', result));
 + else
 +   ​mrWarnDlg('​(mrSliceExport) you need to install gifmerge first...'​);​
 +   ​return
 + end
 +</​code>​
 +
 +====  3. Loading in previous analysis (timeSeriesStats) and the anatomy ​ ====
 +
 +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):
 +
 +<code matlab>
 + % load in timeSeriesStatistics
 + v = loadAnalysis(v,​ '​timeSeriesStats',​ analysisdir);​
 + % load anatomy ​
 + v = loadAnat(v);​
 +</​code>​
 +
 +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.
 +
 +====  4. Getting information about number of slices, range of data, etc. using **viewGet** ​ ====
 +
 +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.
 +
 +<code matlab>
 + % 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));​
 +</​code>​
 +
 +====  5. Set range of overlay colors ​ ====
 +Next set the display range used by the mrLoadRet GUI and the alpha transparency...
 +
 +<code matlab>
 + 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);
 +</​code>​
 +
 +====  6. Step through slices, render each one, grab image, save to tiff and convert to gif (because matlab gif-writing is a pain)  ====
 +
 +Get info on how many slices we need to process. Next create a temporary directory, which we will clean up again later.
 +
 +<code matlab>
 + % loop over slices and get images
 + ​nSlices = viewGet(v,'​nslices'​);​
 + % clear a variable
 + img = [[]]; 
 + % make a temporary folder called '​.tmptif'​
 + ​tmpdir = [[viewGet(v,'​datadir'​)|'/​.tmptif'​ ]]; 
 + % ignore warnings about directory already existing!
 + ​warning('​off','​MATLAB:​MKDIR:​DirectoryExists'​); ​
 + ​mkdir(tmpdir);​
 + ​warning('​on','​MATLAB:​MKDIR:​DirectoryExists'​); ​
 +</​code>​
 +
 +Loop over slices, display, grab image, write to tiff and convert in place to gif (using the OSX command line tool).
 +
 +<code matlab>
 + 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 = [[tmpdir|'/'​ sprintf('​im%02d.tif',​ ii)]];
 +   ​imwrite(img(:,:,​1:​3,​ii),​ fname , '​tif'​);​
 +   % convert to gif right here.
 +   % could increase imagesize by adding an option
 +   % convertcmd = [['​convert|'​ fname ' -resize 200% ' strrep(fname,​ '​.tif',​ '​.gif'​)]];​
 +   ​convertcmd = [['​convert|'​ fname ' ' strrep(fname,​ '​.tif',​ '​.gif'​)]];​
 +   ​system(convertcmd);​
 + end
 +</​code>​
 +
 +====  7. Glue all gif images together to make an animated gif  ====
 +
 +The unix tool **gifmerge** glues all of the gif frames together with some options: frame time 50, means 0.5s, -l0 means loop forever.
 +
 +<code matlab>
 + % gifmerge - merge all the gif images together.
 + ​animgifname = [[|viewGet(v,'​datadir'​) '/​animatedGif.gif'​ ]];
 + ​mrDisp(sprintf('​(mrSliceExport) writing animated gif to %sn',​animgifname))
 + ​system([['​gifmerge|-50 -l0 ' tmpdir '/​*.gif > ' animgifname ]] );
 +</​code>​
 +
 +====  8. Open the resulting image up in safari (which can display animated gifs dynamically) ​ ====
 +
 +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).
 +
 +<code matlab>
 + % open in safari...
 + ​mrDisp(sprintf('​(mrSliceExport) opening up in Safari.appn'​))
 + ​system([['​open|-a Safari ' animgifname]]);​
 +</​code>​
 +
 +====  9. Finally clean up and return ​ ====
 +<code matlab>
 + % clean up.
 + ​mrDisp(sprintf('​(mrSliceExport) cleaning up temporary directoryn'​))
 + ​system([['​rm|-r ' tmpdir ]]);
 + ​return;​
 +</​code>​
 +
 +====  10. The final product ​ ====
 +
 +Looks different depending on what kind of color map, clip values, and alpha transparency you specify. Here a simple example:
 +
 +{{:​mrtools:​animatedgif.gif|}}
 +
 +--[[User:​Ds|Ds]] 10:43, 12 June 2008 (EDT)
 +