├── .gitignore
├── Instructions.html
├── README.md
├── html
├── Instructions.md
├── optimizexgui_bestx.jpg
├── optimizexgui_csv.jpg
├── optimizexgui_gui_contrastnum.jpg
├── optimizexgui_gui_contrastspec.jpg
├── optimizexgui_gui_main.jpg
├── optimizexgui_main_contrasts.jpg
├── optimizexgui_main_labeled.jpg
└── optimizexgui_output.jpg
├── optimizeXGUI.m
└── unused
└── testcarryorder.m
/.gitignore:
--------------------------------------------------------------------------------
1 | design_params*mat
2 | .DS_Store
3 | .DS_Store?
4 | ._*
5 | .Spotlight-V100
6 | .Trashes
7 | ehthumbs.db*
8 | Thumbs.db
9 | design_params*
10 | best_designs*
11 | unused/
12 | index*md
--------------------------------------------------------------------------------
/Instructions.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
325 |
OptimizeXGUI Instructions
326 |
Here you'll learn to use a program called OptimizeXGUI.m to optimize a complex, randomized event-related design that contains multiple event types (i.e., conditions). This software is specifically designed for optimizing the detection of specific linear contrasts of interest (i.e., activation differences). Most importantly, it (hopefully) will be easy for you to use, leaving you with no excuse for not optimizing your design for your next event-related study. In addition, you should check out Tor Wager'sDesign Optimization software,which is more powerful than this software but requires more MATLAB experience and time to be able to use effectively.
327 |
To get started, go ahead and run the program in a MATLAB command window:
328 |
329 | optimizeXGUI;
330 |
You should now see the main input dialogue:
331 |

332 |
Feel free to create your own unique design by modifying the inputs. Or, you can just use the "default" values to proceed on to the next step, which is to tell the software which contrasts you care most about:
333 |

334 |
That's it! The software will do the rest of the work, some of which you can see in the MATLAB command window:
335 |

336 |
Once it finishes, you should see a figure pop up showing you the most efficient design matrix:
337 |

338 |
In addition, you should see a new folder in the directory in which you ran the program. Inside that directory are .csv files (and .txt files, which can be read a bit easier back into MATLAB) like this:
339 |

340 |
For most applications, this should be all of the information you need to implement your experiment, and to do so in a manner that is optimal given the contrasts you care about. Of course, you might want to think about running the software for more than a minute if you do decide to use this for a study! There is no hard-and-fast rule for how long you do need to run it, but it wouldn't hurt (presumably) to run it overnight.
341 |
345 |
346 |
439 |
440 |
441 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # **THIS REPOSITORY IS NO LONGER ACTIVELY MAINTAINED - USE AT YOUR OWN RISK**
2 |
3 | ---
4 |
5 | # easy-optimize-x
6 | GUI-based MATLAB software for optimizing the design of fMRI tasks. See [Help Page](http://spunt.github.io/easy-optimize-x) for usage instructions.
7 |
8 | You can use the following DOI to cite use of this software: [](https://zenodo.org/badge/latestdoi/21612/spunt/easy-optimize-x)
9 |
10 | ### to do
11 | * add m-sequencing for trial counterbalancing
12 | * look into improving GA (possibly with turboGA.m from MATLAB File Exchange)
13 |
--------------------------------------------------------------------------------
/html/Instructions.md:
--------------------------------------------------------------------------------
1 | # Instructions
2 |
3 | ## About ##
4 | Here you'll learn to use a program called OptimizeXGUI.m to optimize a complex, randomized event-related design that contains multiple event types (i.e., conditions). This software is specifically designed for optimizing the detection of specific linear contrasts of interest (i.e., activation differences). Most importantly, it (hopefully) will be easy for you to use, leaving you with no excuse for not optimizing your design for your next event-related study. In addition, you should check out Tor Wager's [Design Optimization software](http://wagerlab.colorado.edu/tools), which is more powerful than this software but requires more MATLAB experience and time to be able to use effectively.
5 |
6 | ## Launching *optimizeXGUI*
7 | To get started, go ahead and run the program in a MATLAB command window (make sure you're in the right directory):
8 | ```
9 | >> optimizeXGUI
10 | ```
11 | You should now see the main input dialogue:
12 |
13 | 
14 |
15 | Feel free to create your own unique design by modifying the inputs. Or, you can just use the "default" values to proceed on to the next step, which is to tell the software which contrasts you care most about:
16 |
17 | 
18 |
19 | That's it! The software will do the rest of the work, some of which you can see in the MATLAB command window:
20 |
21 | 
22 |
23 | Once it finishes, you should see a figure pop up showing you the most efficient design matrix:
24 |
25 | 
26 |
27 | In addition, you should see a new folder in the directory in which you ran the program. Inside that directory are .csv files (and .txt files, which can be read a bit easier back into MATLAB) like this:
28 |
29 | 
30 |
31 | For most applications, this should be all of the information you need to implement your experiment, and to do so in a manner that is optimal given the contrasts you care about. Of course, you might want to think about running the software for more than a minute if you do decide to use this for a study! There is no hard-and-fast rule for how long you do need to run it, but it wouldn't hurt (presumably) to run it overnight.
32 |
33 | ## Have Questions?
34 | Feel free to shoot me (Bob) an email at: bobspunt@gmail.com
--------------------------------------------------------------------------------
/html/optimizexgui_bestx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_bestx.jpg
--------------------------------------------------------------------------------
/html/optimizexgui_csv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_csv.jpg
--------------------------------------------------------------------------------
/html/optimizexgui_gui_contrastnum.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_gui_contrastnum.jpg
--------------------------------------------------------------------------------
/html/optimizexgui_gui_contrastspec.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_gui_contrastspec.jpg
--------------------------------------------------------------------------------
/html/optimizexgui_gui_main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_gui_main.jpg
--------------------------------------------------------------------------------
/html/optimizexgui_main_contrasts.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_main_contrasts.jpg
--------------------------------------------------------------------------------
/html/optimizexgui_main_labeled.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_main_labeled.jpg
--------------------------------------------------------------------------------
/html/optimizexgui_output.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spunt/easy-optimize-x/2c818675f61071356c3d7903eb3f7ab994991d04/html/optimizexgui_output.jpg
--------------------------------------------------------------------------------
/optimizeXGUI.m:
--------------------------------------------------------------------------------
1 | function optimizeXGUI(params)
2 | % OPTIMIZEXGUI
3 | %
4 | % USAGE: optimizeXGUI([params])
5 | %
6 | % Run this function at the command line to open the GUI. Once the design
7 | % search has ended, a time stamped folder will be created in the software
8 | % directory. In the folder, details regarding the most efficient designs
9 | % will be saved. This includes a .mat file with all of the design
10 | % information, as well as separate txt/csv files for the most efficient
11 | % designs. The text files will have 5 columns:
12 | %
13 | % column 1 -- trial #
14 | % column 2 -- condition
15 | % column 3 -- onsets (in secs)
16 | % column 4 -- trial duration (secs)
17 | % column 5 -- post-trial duration (secs)
18 | %
19 | %
20 | % The GUI was created using the MATLAB File Exchange contribution
21 | % "settingsdlg.m" (http://goo.gl/DFvcQ5), which is included as a
22 | % subfunction. Some of the code is lifted or adapted from software
23 | % developed by Russ Poldrack or Tor Wager.
24 |
25 | % Copyright 2014 Bob Spunt, Pasadena, California
26 | % California Institute of Technology, USA
27 | % Contact: bobspunt@gmail.com
28 | % Current Version: 20160104
29 | %
30 | if nargin==0
31 |
32 | params = getParams;
33 |
34 | elseif ~isstruct(params)
35 |
36 | if iscell(params), params = char(params); end
37 |
38 | try
39 | load(params)
40 | catch err
41 | error_handler(err);
42 | end
43 |
44 | end
45 |
46 | % =========================================================================
47 | % Run defineX.m
48 | % =========================================================================
49 | params = defineX(params);
50 |
51 | % =========================================================================
52 | % Run optimizeX.m
53 | % =========================================================================
54 | try
55 | optimizeX(params);
56 | delete(findall(0, 'Name','optimizeXGUI Progress'));
57 | catch err
58 | error_handler(err);
59 | delete(findall(0, 'Name','optimizeXGUI Progress'));
60 | end
61 |
62 | end
63 | % =========================================================================
64 | % *
65 | % * SUBFUNCTIONS (PRIMARY)
66 | % *
67 | % =========================================================================
68 | function params = getParams
69 |
70 | % =========================================================================
71 | % Request Major Settings from User
72 | % =========================================================================
73 | try
74 | % cbintervalstr = {'None', '1st/2nd Half (2)', 'Tertiles (3)', 'Quartiles (4)', 'Quintiles (5)' , 'Sextile (6)', 'Septile (7)', 'Octile (8)', 'Decile (10)', 'Hexadecile (16)'};
75 | % cbintervalnum = [1 2 3 4 5 6 7 8 10 16];
76 | % cbintervalstr = {'None', '1st/2nd Half (2)', 'Tertiles (3) [possibly slow]', 'Quartiles (4) [possibly very slow]'};
77 | % cbintervalnum = [1 2 3 4];
78 | % {'Interval Counterbalancing'; 'counterBalanceInterval'}, cbintervalstr, ...
79 |
80 |
81 | distOpt = {
82 | 'Rayleigh'
83 | 'Chisquare'
84 | 'Exponential'
85 | };
86 |
87 | [params, button] = settingsdlg(...
88 | 'title' , 'OptimizeX Settings', ...
89 | 'separator' , 'General Settings', ...
90 | {'TR (s)'; 'TR'}, 2, ...
91 | {'High-Pass Filter Cutoff (s)'; 'hpf'}, 100, ...'
92 | 'separator' , 'Task Settings', ...
93 | {'N Conditions';'nconds'} , 4, ...
94 | {'N Trials Per Condition';'trialsPerCond'} , '25 25 25 25', ...
95 | {'Maximum Block Size'; 'maxRep'} , 3, ...
96 | 'separator' , 'Timing (s)', ...
97 | {'Trial Duration'; 'trialDur'}, 2, ...
98 | {'Mean ISI';'meanISI'} , 3, ...
99 | {'Min ISI';'minISI'} , 2, ...
100 | {'Max ISI';'maxISI'} , 6, ...
101 | {'ISI Distribution'; 'distISI'} , distOpt, ...
102 | {'Time before first trial'; 'restBegin'}, 10, ...
103 | {'Time after last trial'; 'restEnd'}, 10, ...
104 | 'separator' , 'Optimization Settings', ...
105 | {'N Designs to Save'; 'keep'}, 5, ...
106 | {'N Generations to Run';'ngen'} , 100, ...
107 | {'N Designs Per Generation';'gensize'} , 500, ...
108 | {'Max Time to Run (minutes)';'maxtime'} , .5);
109 | catch err
110 | error_handler(err);
111 | end
112 | if strcmpi(button, 'cancel') || isempty(button), return; end % canceled
113 | % params.counterBalanceInterval = cbintervalnum(strcmpi(cbintervalstr, params.counterBalanceInterval));
114 | params.trialsPerCond = str2num(params.trialsPerCond);
115 | params.counterBalanceInterval = 0;
116 | if length(params.trialsPerCond)==1, params.trialsPerCond = repmat(params.trialsPerCond, 1, params.nconds);
117 | elseif length(params.trialsPerCond)~=params.nconds
118 | msg = sprintf('The number of entries in "N Trials Per Condition" does not match the number of conditions');
119 | headsup(msg, 'Invalid Input', 1);
120 | optimizeXGUI
121 | end
122 | if params.minISI > params.meanISI | params.maxISI < params.meanISI
123 | msg = sprintf('The ISI values you''ve specified look odd: Min ISI cannot be greater than the Mean ISI, and the Max ISI cannot be less than the Mean ISI');
124 | headsup(msg, 'Invalid Input', 1);
125 | optimizeXGUI
126 | end
127 |
128 | % =========================================================================
129 | % Contrast Specification and Weighting
130 | % =========================================================================
131 | [condata, button] = settingsdlg(...
132 | 'title' , 'Settings', ...
133 | {'How many contrasts of interest?';'ncontrast'} , 1);
134 | if strcmpi(button, 'cancel') || isempty(button), return; end
135 | vec = repmat('0 ', 1, params.nconds);
136 | all = [];
137 | for c = 1:condata.ncontrast
138 | tmp = [{{sprintf('Vector for Contrast %d', c); sprintf('con%d', c)}},
139 | {vec},
140 | {{sprintf('Weight for Contrast %d', c); sprintf('con%dw', c)}},
141 | {1}];
142 | all = [all; tmp];
143 | end
144 | [data2, button] = settingsdlg(...
145 | 'title', 'Contrast Specification', ...
146 | all{:});
147 | if strcmpi(button, 'cancel') || isempty(button), return; end
148 | con = struct2cell(data2);
149 | params.L = [];
150 | convec = con(1:2:end);
151 | conweight = con(2:2:end);
152 | params.L = [];
153 | params.conWeights = [];
154 | for c = 1:length(conweight)
155 | params.L = [params.L; str2num(convec{c})];
156 | params.conWeights(c) = conweight{c};
157 | end
158 |
159 | % =========================================================================
160 | % Save Design Parameters
161 | % =========================================================================
162 | [d, t] = get_timestamp;
163 | outfile = sprintf('design_params_%s_%s.mat', d, t);
164 | fprintf('\nParameters saved in %s\n', fullfile(pwd, outfile));
165 | save(fullfile(pwd, outfile), 'params');
166 |
167 | end
168 | function params = defineX(params)
169 |
170 | % Pulse Sequence Parameters
171 | params.nslices = 16; % number of time bins in each TR (SPM default = 16)
172 |
173 | % Derive Some Additional Parameters %
174 | params.ntrials=sum(params.trialsPerCond); % computes total number of trials
175 | params.scan_length=ceil((params.restBegin + params.restEnd + params.ntrials*(params.meanISI+params.trialDur))/params.TR); % computes total scan length (in TRs)
176 | params.TReff=params.TR/params.nslices; % computes effective TR
177 |
178 |
179 | %% Verify that valid order can be made with specified max reps %%
180 | fprintf('\nVerifying efficiency of creating valid trial orders with current parameters... ');
181 | tic; % start the timer
182 | order = [];
183 | for i = 1:params.nconds, order = [order; repmat(i, params.trialsPerCond(i), 1)]; end
184 | move_on = 0;
185 | maxtesttime = 5;
186 | while ~move_on
187 | tmp = order(randperm(params.ntrials));
188 | nchunk = getchunks(tmp);
189 | if ~any(nchunk>params.maxRep)
190 | move_on = 1;
191 | elseif toc>=maxtesttime
192 | fprintf('FAIL\n\n');
193 | error('Current parameters prevent efficient creation of valid trial orders. Try increasing Maximum Block Size parameter.');
194 | end
195 | end
196 | order = tmp;
197 | % if toc>=maxtime*60, break, end
198 | fprintf('SUCCESS\n');
199 |
200 | % Get ISI distribution %
201 | fprintf('\nCreating base distirbution of ISIs... ');
202 | minISI = params.minISI;
203 | maxISI = params.maxISI;
204 | meanISI = params.meanISI;
205 | TReff = params.TReff;
206 | mu = TReff:TReff:meanISI;
207 | jitSample = zeros(1000,length(mu));
208 | % try
209 | % for s = 1:length(mu), jitSample(:,s) = random(params.distISI, mu(s), 1000, 1); end
210 | % catch
211 | switch lower(params.distISI)
212 | % Thanks to Jeremy Purcell for this fix for older versions of MATLAB
213 | case 'rayleigh'
214 | for s = 1:length(mu), jitSample(:,s) = raylrnd(mu(s), 1000, 1); end
215 | case 'chisquare'
216 | for s = 1:length(mu), jitSample(:,s) = chi2rnd(mu(s), 1000, 1); end
217 | case 'exponential'
218 | for s = 1:length(mu), jitSample(:,s) = exprnd(mu(s), 1000, 1); end
219 | end
220 | % end
221 | jitSample(jitSample