0001 function data = prt_cfg_design
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 covar = cfg_files;
0014 covar.tag = 'covar';
0015 covar.name = 'Covariates';
0016 covar.help = {['Select a .mat file containing '...
0017 'your covariates (i.e. any other data/information '...
0018 'you would like to include in your design). This file '...
0019 'should contain a variable ''R'' with a matrix of '...
0020 'covariates. On covariate per image is expected.']};
0021 covar.val{1} = {''};
0022 covar.filter = 'mat';
0023 covar.ufilter = '.*';
0024 covar.num = [0 1];
0025
0026
0027
0028
0029 rt_subj = cfg_entry;
0030 rt_subj.tag = 'rt_subj';
0031 rt_subj.name = 'Regression targets (per scans)';
0032 rt_subj.help = {['Enter one regression target per scan. '...
0033 'or enter the name of a variable. '...
0034 ' This variable should be a vector '...
0035 '[Nscans x 1], where Nscans is the number of '...
0036 'scans/images.']};
0037 rt_subj.strtype = 'e';
0038 rt_subj.val = {[]};
0039 rt_subj.num = [Inf 0];
0040
0041
0042
0043
0044 rt_trial = cfg_entry;
0045 rt_trial.tag = 'rt_trial';
0046 rt_trial.name = 'Regression targets (trials)';
0047 rt_trial.help = {['Enter one regression target per trial. '...
0048 'This vector should have the following dimensions: '...
0049 '[Ntrials x 1], where Ntrials is the number of trials.']
0050 };
0051 rt_trial.strtype = 'e';
0052 rt_trial.val = {[]};
0053 rt_trial.num = [Inf 0];
0054
0055
0056
0057
0058 TR = cfg_entry;
0059 TR.tag = 'TR';
0060 TR.name = 'Interscan interval';
0061 TR.help = {'Specify interscan interval (TR). The units should be seconds.'};
0062 TR.strtype = 'e';
0063 TR.num = [Inf 1];
0064
0065
0066
0067
0068 unit = cfg_menu;
0069 unit.tag = 'unit';
0070 unit.name = 'Units for design';
0071 unit.help = {['The onsets of events or blocks can be specified in '...
0072 'either scans or seconds.']};
0073 unit.labels = {
0074 'Scans'
0075 'Seconds'
0076 }';
0077 unit.values = {0 1};
0078 unit.val = {1};
0079
0080
0081
0082
0083 review = cfg_menu;
0084 review.tag = 'review';
0085 review.name = 'Review';
0086 review.help = {['Choose ''Yes'' if you would like to review your '...
0087 'data and design in a separate window.']};
0088 review.labels = {
0089 'No'
0090 'Yes'
0091 }';
0092 review.values = {0 1};
0093 review.val = {0};
0094
0095
0096
0097
0098 hrfover = cfg_entry;
0099 hrfover.tag = 'hrfover';
0100 hrfover.name = 'HRF overlap';
0101 hrfover.help = {['If using fMRI data please specify the width of the '...
0102 'hemodynamic response function (HRF). This will be '...
0103 'used to calculate the overlap between events. '...
0104 'Leave as 0 for other modalities (other than fMRI).']};
0105 hrfover.strtype = 'e';
0106 hrfover.num = [1 1];
0107 hrfover.def = @(val)prt_get_defaults('datad.hrfw', val{:});
0108
0109
0110
0111
0112 hrfdel = cfg_entry;
0113 hrfdel.tag = 'hrfdel';
0114 hrfdel.name = 'HRF delay';
0115 hrfdel.help = {['If using fMRI data please specify the delay of the '...
0116 'hemodynamic response function (HRF). This will be '...
0117 'used to calculate the overlap between events. Leave '...
0118 'as 0 for other modalities (other than fMRI).']};
0119 hrfdel.strtype = 'e';
0120 hrfdel.num = [1 1];
0121 hrfdel.def = @(val)prt_get_defaults('datad.hrfd', val{:});
0122
0123
0124
0125
0126 fmri_des = cfg_branch;
0127 fmri_des.tag = 'fmri_des';
0128 fmri_des.name = 'fMRI_Des';
0129 fmri_des.val = {hrfover, hrfdel};
0130 fmri_des.help = {'fMRI design specific parameters, HRF overlap and delay.'};
0131
0132
0133
0134
0135 mod_name = cfg_entry;
0136 mod_name.tag = 'mod_name';
0137 mod_name.name = 'Name';
0138 mod_name.help = {['Name of modality. Example: ''BOLD''. The names '...
0139 'should be consistent accross subjects/groups '...
0140 'and the same names specified in the masks.']};
0141 mod_name.strtype = 's';
0142 mod_name.num = [1 Inf];
0143
0144
0145
0146
0147 scans = cfg_files;
0148 scans.tag = 'scans';
0149 scans.name = 'Scans';
0150 scans.help = {['Select scans (images) for this modality. They must '...
0151 'all have the same image dimensions, orientation, '...
0152 'voxel size etc.']};
0153 scans.filter = 'image';
0154 scans.ufilter = '.*';
0155 scans.num = [1 Inf];
0156
0157
0158
0159
0160 subjects = cfg_files;
0161 subjects.tag = 'subjects';
0162 subjects.name = 'Files';
0163 subjects.help = {['Select scans (images) for this modality. They must '...
0164 'all have the same image dimensions, orientation, '...
0165 'voxel size etc.']};
0166 subjects.filter = 'image';
0167 subjects.num = [0 Inf];
0168
0169
0170
0171
0172 modality = cfg_branch;
0173 modality.tag = 'modality';
0174 modality.name = 'Modality';
0175 modality.val = {mod_name, subjects, rt_subj, covar };
0176 modality.help = {'Specify modality, such as name and data.'};
0177
0178
0179
0180
0181 images = cfg_repeat;
0182 images.tag = 'images';
0183 images.name = 'Scans';
0184 images.values = {modality };
0185 images.help = {['Depending on the type of data at hand, you may have many images (scans) '...
0186 'per subject, such as a fMRI time series, or you may have many '...
0187 'subjects with only one or a small number of images (scans) per subject, '...
0188 'such as PET images. ',...
0189 'Select this option if you have many subjects per modality to spatially ',...
0190 'normalise, but there is one or a small number of scans for '...
0191 'each subject. This is a faster option with less information to specify '...
0192 'than the ''select by subjects'' option. Both options create the same '...
0193 '''PRT.mat'' but ''select by scans'' is optimised for modalities '...
0194 'with no design.']};
0195
0196
0197
0198
0199 fmask = cfg_files;
0200 fmask.tag = 'fmask';
0201 fmask.name = 'File';
0202 fmask.filter = 'image';
0203 fmask.ufilter = '.*';
0204 fmask.num = [1 1];
0205 fmask.help = {['Select one first-level mask (image) for each modality. ',...
0206 'This mask is used to optimise the prepare data step. ',...
0207 'In ''specify model'' there is an option to enter a ',...
0208 'second-level mask, which might be used to select only ',...
0209 'a few areas of the brain for subsequent analyses.']};
0210
0211
0212
0213 mask = cfg_branch;
0214 mask.tag = 'mask';
0215 mask.name = 'Modality';
0216 mask.help = {['Specify name of modality and file for each mask. ',...
0217 'The name should be consistent with the names chosen ',...
0218 'for the modalities (subjects/scans).']};
0219 mask.val = {mod_name, fmask };
0220
0221
0222
0223
0224 masks = cfg_repeat;
0225 masks.tag = 'masks';
0226 masks.name = 'Masks';
0227 masks.help = {['Select first-level (pre-processing) mask for each ',...
0228 'modality. The name of the modalities should be the same ',...
0229 'as the ones entered for subjects/scans.']};
0230 masks.num = [1 Inf];
0231 masks.values = {mask };
0232
0233
0234
0235
0236 load_SPM = cfg_files;
0237 load_SPM.tag = 'load_SPM';
0238 load_SPM.name = 'Load SPM.mat';
0239 load_SPM.help = {['Load design from SPM.mat (if you have previously '...
0240 'specified the experimental design with SPM).']};
0241 load_SPM.filter = '^SPM\.mat$';
0242 load_SPM.num = [1 1];
0243
0244
0245
0246
0247 cond_name = cfg_entry;
0248 cond_name.tag = 'cond_name';
0249 cond_name.name = 'Name';
0250 cond_name.help = {'Name of condition (alphanumeric strings only).'};
0251 cond_name.strtype = 's';
0252 cond_name.num = [1 Inf];
0253
0254
0255
0256
0257 onsets = cfg_entry;
0258 onsets.tag = 'onsets';
0259 onsets.name = 'Onsets';
0260 onsets.help = {'Specify a vector of onset times for this condition type. '};
0261 onsets.strtype = 'e';
0262 onsets.num = [Inf 1];
0263
0264
0265
0266
0267 durations = cfg_entry;
0268 durations.tag = 'durations';
0269 durations.name = 'Durations';
0270 durations.help = {['Specify the event durations. Epoch and '...
0271 'event-related responses are modeled in exactly '...
0272 'the same way but by specifying their different '...
0273 'durations. Events are specified with a duration '...
0274 'of 0. If you enter a single number for the '...
0275 'durations it will be assumed that all trials '...
0276 'conform to this duration. If you have multiple '...
0277 'different durations, then the number must match '...
0278 'the number of onset times.']};
0279 durations.strtype = 'e';
0280 durations.num = [Inf 1];
0281
0282
0283
0284
0285 conds = cfg_branch;
0286 conds.tag = 'conds';
0287 conds.name = 'Condition';
0288 conds.help = {'Specify condition: name, onsets and duration.'};
0289 conds.val = {cond_name, onsets, durations};
0290
0291
0292
0293
0294 conditions = cfg_repeat;
0295 conditions.tag = 'conditions';
0296 conditions.name = 'Conditions';
0297 conditions.help = {['Specify conditions. You are allowed to combine '...
0298 'both event- and epoch-related responses in '...
0299 'the same model and/or regressor. Any number of '...
0300 'condition (event or epoch) types can be '...
0301 'specified. Epoch and event-related responses '...
0302 'are modeled in exactly the same way by '...
0303 'specifying their onsets [in terms of onset '...
0304 'times] and their durations. Events are specified '...
0305 'with a duration of 0. If you enter a single '...
0306 'number for the durations it will be assumed that '...
0307 'all trials conform to this duration.For factorial '...
0308 'designs, one can later associate these experimental '...
0309 'conditions with the appropriate levels of experimental '...
0310 'factors.']};
0311 conditions.values = {conds};
0312
0313
0314
0315
0316 multi_conds = cfg_files;
0317 multi_conds.tag = 'multi_conds';
0318 multi_conds.name = 'Multiple conditions';
0319 multi_conds.val{1} = {''};
0320 multi_conds.help = {
0321 'Select the *.mat file containing details of your multiple experimental conditions. '
0322 ''
0323 'If you have multiple conditions then entering the details a condition at a time is very inefficient. This option can be used to load all the required information in one go. You will first need to create a *.mat file containing the relevant information. '
0324 ''
0325 'This *.mat file must include the following cell arrays (each 1 x n): names, onsets and durations. eg. names=cell(1,5), onsets=cell(1,5), durations=cell(1,5), then names{2}=''SSent-DSpeak'', onsets{2}=[3 5 19 222], durations{2}=[0 0 0 0], contain the required details of the second condition. These cell arrays may be made available by your stimulus delivery program, eg. COGENT. The duration vectors can contain a single entry if the durations are identical for all events.'
0326 ''
0327 'Time and Parametric effects can also be included. For time modulation include a cell array (1 x n) called tmod. It should have a have a single number in each cell. Unused cells may contain either a 0 or be left empty. The number specifies the order of time modulation from 0 = No Time Modulation to 6 = 6th Order Time Modulation. eg. tmod{3} = 1, modulates the 3rd condition by a linear time effect.'
0328 ''
0329 'For parametric modulation include a structure array, which is up to 1 x n in size, called pmod. n must be less than or equal to the number of cells in the names/onsets/durations cell arrays. The structure array pmod must have the fields: name, param and poly. Each of these fields is in turn a cell array to allow the inclusion of one or more parametric effects per column of the design. The field name must be a cell array containing strings. The field param is a cell array containing a vector of parameters. Remember each parameter must be the same length as its corresponding onsets vector. The field poly is a cell array (for consistency) with each cell containing a single number specifying the order of the polynomial expansion from 1 to 6.'
0330 ''
0331 'Note that each condition is assigned its corresponding entry in the structure array (condition 1 parametric modulators are in pmod(1), condition 2 parametric modulators are in pmod(2), etc. Within a condition multiple parametric modulators are accessed via each fields cell arrays. So for condition 1, parametric modulator 1 would be defined in pmod(1).name{1}, pmod(1).param{1}, and pmod(1).poly{1}. A second parametric modulator for condition 1 would be defined as pmod(1).name{2}, pmod(1).param{2} and pmod(1).poly{2}. If there was also a parametric modulator for condition 2, then remember the first modulator for that condition is in cell array 1: pmod(2).name{1}, pmod(2).param{1}, and pmod(2).poly{1}. If some, but not all conditions are parametrically modulated, then the non-modulated indices in the pmod structure can be left blank. For example, if conditions 1 and 3 but not condition 2 are modulated, then specify pmod(1) and pmod(3). Similarly, if conditions 1 and 2 are modulated but there are 3 conditions overall, it is only necessary for pmod to be a 1 x 2 structure array.'
0332 ''
0333 'EXAMPLE:'
0334 'Make an empty pmod structure: '
0335 ' pmod = struct(''name'',{''''},''param'',{},''poly'',{});'
0336 'Specify one parametric regressor for the first condition: '
0337 ' pmod(1).name{1} = ''regressor1'';'
0338 ' pmod(1).param{1} = [1 2 4 5 6];'
0339 ' pmod(1).poly{1} = 1;'
0340 'Specify 2 parametric regressors for the second condition: '
0341 ' pmod(2).name{1} = ''regressor2-1'';'
0342 ' pmod(2).param{1} = [1 3 5 7]; '
0343 ' pmod(2).poly{1} = 1;'
0344 ' pmod(2).name{2} = ''regressor2-2'';'
0345 ' pmod(2).param{2} = [2 4 6 8 10];'
0346 ' pmod(2).poly{2} = 1;'
0347 ''
0348 'The parametric modulator should be mean corrected if appropriate. Unused structure entries should have all fields left empty.'
0349 }';
0350 multi_conds.filter = 'mat';
0351 multi_conds.ufilter = '.*';
0352 multi_conds.num = [0 1];
0353
0354
0355
0356
0357 new_design = cfg_branch;
0358 new_design.tag = 'new_design';
0359 new_design.name = 'Specify design';
0360 new_design.help = {'Specify design: scans (data), onsets and durations.'};
0361 new_design.val = {unit conditions multi_conds};
0362
0363
0364
0365
0366 no_design = cfg_const;
0367 no_design.tag = 'no_design';
0368 no_design.name = 'No design';
0369 no_design.val = {0};
0370 no_design.help = {['Do not specify design. This option can be used '...
0371 'for modalities (e.g. structural scans) that do not '...
0372 'have an experimental design.']};
0373
0374
0375
0376
0377 design = cfg_choice;
0378 design.tag = 'design';
0379 design.name = 'Data & Design';
0380 design.help = {'Specify data and design.'};
0381 design.values = {load_SPM, new_design, no_design };
0382 design.val = {load_SPM };
0383
0384
0385
0386
0387 subject = cfg_branch;
0388 subject.tag = 'subject';
0389 subject.name = 'Modality';
0390 subject.val = {mod_name, TR, scans, design };
0391 subject.help = {'Add new modality.'};
0392
0393
0394
0395
0396 gr_name = cfg_entry;
0397 gr_name.tag = 'gr_name';
0398 gr_name.name = 'Name';
0399 gr_name.help = {'Name of the group. Example: ''Controls''.'};
0400 gr_name.strtype = 's';
0401 gr_name.num = [1 Inf];
0402
0403
0404
0405
0406 ind_subj = cfg_repeat;
0407 ind_subj.tag = 'ind_subj';
0408 ind_subj.name = 'Subject';
0409 ind_subj.help = {'Add new modality for this subject.'};
0410 ind_subj.values = {subject };
0411
0412
0413
0414
0415 subjs = cfg_repeat;
0416 subjs.tag = 'subjs';
0417 subjs.name = 'Subjects';
0418 subjs.help = {'Add subjects/scans.'};
0419 subjs.values = {ind_subj };
0420
0421
0422
0423
0424 select = cfg_choice;
0425 select.tag = 'select';
0426 select.name = 'Select by';
0427 select.values = {subjs, images};
0428 select.help = {...
0429 ['Depending on the type of data at hand, you may have many images (scans) '...
0430 'per subject, such as a fMRI time series, or you may have many '...
0431 'subjects with only one or a small number of images (scans) per subject '...
0432 ', such as PET images. If you have many scans per subject select the '...
0433 'option ''subjects''. If you have one scan for many subjects select '...
0434 'the option ''scans''.']};
0435
0436
0437
0438
0439 group = cfg_branch;
0440 group.tag = 'group';
0441 group.name = 'Group';
0442 group.help = {'Specify data and design for the group.'};
0443 group.val = {gr_name, select };
0444
0445
0446
0447
0448 groups = cfg_repeat;
0449 groups.tag = 'groups';
0450 groups.name = 'Groups';
0451 groups.help = {['Add data and design for one group. Click ''new'' '...
0452 'or ''repeat'' to add another group.']};
0453 groups.num = [1 Inf];
0454 groups.values = {group };
0455
0456
0457
0458
0459 dir_name = cfg_files;
0460 dir_name.tag = 'dir_name';
0461 dir_name.name = 'Directory';
0462 dir_name.help = {['Select a directory where the PRT.mat file '...
0463 'containing the specified design and data matrix '...
0464 'will be written.']};
0465 dir_name.filter = 'dir';
0466 dir_name.ufilter = '.*';
0467 dir_name.num = [1 1];
0468
0469
0470
0471
0472 data = cfg_exbranch;
0473 data.tag = 'data';
0474 data.name = 'Data & Design';
0475 data.val = {dir_name groups masks fmri_des review};
0476 data.help = {'Specify the data and design for each group (minimum one group).'};
0477 data.prog = @prt_run_design;
0478 data.vout = @vout_data;
0479 data.check = @check_data;
0480
0481
0482
0483
0484 function cdep = vout_data(job)
0485
0486
0487 cdep(1) = cfg_dep;
0488 cdep(1).sname = 'PRT.mat file';
0489 cdep(1).src_output = substruct('.','files');
0490 cdep(1).tgt_spec = cfg_findspec({{'filter','mat','strtype','e'}});
0491 ngroup = length(job.group);
0492 for g = 1:ngroup
0493 cdep(1+g) = cfg_dep;
0494 cdep(1+g).sname = sprintf('Group#%d name',g);
0495 cdep(1+g).src_output = substruct('.',sprintf('gr_name%d',g));
0496 cdep(1+g).tgt_spec = cfg_findspec({{'strtype','s'}});
0497 end
0498 nmod = length(job.mask);
0499 for m = 1:nmod
0500 cdep(1+ngroup+m) = cfg_dep;
0501 cdep(1+ngroup+m).sname = sprintf('Mod#%d name',m);
0502 cdep(1+ngroup+m).src_output = substruct('.',sprintf('mod_name%d',m));
0503 cdep(1+ngroup+m).tgt_spec = cfg_findspec({{'strtype','s'}});
0504 end
0505
0506
0507
0508
0509 function t = check_data(data)
0510
0511 t = {};
0512 if isfield(data,'group')
0513 if isfield(data,'mask')
0514
0515
0516 Ngroup = numel(data.group);
0517 subj_mod = {}; gr_mod = cell(1,Ngroup); Ngr_mod = zeros(1,Ngroup);
0518 for gg = 1:numel(data.group)
0519 c_smod = 0;
0520 if isfield(data.group(gg).select,'subject')
0521 Nsubj = numel(data.group(gg).select.subject);
0522 for ss = 1:Nsubj
0523 if ~isempty(data.group(gg).select.subject{ss})
0524 for mm = 1:numel(data.group(gg).select.subject{ss})
0525 c_smod = c_smod+1;
0526 subj_mod{c_smod,gg} = ...
0527 data.group(gg).select.subject{ss}(mm).mod_name;
0528 end
0529 end
0530 end
0531 gr_mod{:,gg} = unique(subj_mod(1:Nsubj,gg));
0532 elseif isfield(data.group(gg).select,'modality')
0533 Nmod = numel(data.group(gg).select.modality);
0534 for mm = 1:Nmod
0535 c_smod = c_smod+1;
0536 subj_mod{c_smod,gg} = data.group(gg).select.modality(mm).mod_name;
0537 end
0538 gr_mod{:,gg} = unique(subj_mod(:,gg));
0539 end
0540 Ngr_mod(gg) = numel(gr_mod{:,gg});
0541 end
0542
0543 Nmask = numel(data.mask);
0544 mask_mod = cell(1,Nmask);
0545 for mk = 1:Nmask
0546 mask_mod{mk} = data.mask(mk).mod_name;
0547 end
0548
0549 if Ngroup>1
0550 if any(diff(Ngr_mod))
0551 t = {'Different number of modalities across groups!'};
0552 warndlg(t,'Group modality name');
0553 return
0554 end
0555 end
0556
0557
0558
0559
0560 if numel(unique(mask_mod))~=Nmask
0561 t = {'Masks'' name not unique!'};
0562 warndlg(t,'Masks modality name');
0563 return
0564 end
0565 ok = zeros(Nmask,1);
0566 for mk=1:Nmask
0567 if any(strcmp(mask_mod{mk},subj_mod(:)))
0568 ok(mk) = 1;
0569 end
0570 end
0571 if ~all(ok)
0572 t{1} = 'Some masks name don''t match any subj/img modality!';
0573 warndlg(t,'Masks and data modality name');
0574 return
0575 end
0576 smods = subj_mod(:);
0577 smods = smods(~cellfun(@isempty,smods));
0578 usubj_mod = unique(smods);
0579 Nsubj_mod = numel(usubj_mod);
0580 ok = zeros(Nsubj_mod,1);
0581 for sm = 1:Nsubj_mod
0582 if any(strcmp(usubj_mod{sm},mask_mod))
0583 ok(sm) = 1;
0584 end
0585 end
0586 if ~all(ok)
0587 t{1} = 'Some subj/img modality! don''t match any masks name';
0588 warndlg(t,'Masks and data modality name');
0589 return
0590 end
0591
0592 end
0593 end
0594 return;
0595