0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 function [outdata,outsort,outtrials] = erpimages(data1,data2,sortvar1,sortvar2,chan1,chan2,varargin)
0197
0198
0199
0200
0201 p=inputParser;
0202
0203
0204
0205 p.addRequired('data1',@isnumeric);
0206 p.addRequired('data2',@isnumeric);
0207 p.addRequired('sortvar1',@isnumeric);
0208 p.addRequired('sortvar2',@isnumeric);
0209 p.addRequired('chan1',@ischar);
0210 p.addRequired('chan2',@ischar);
0211 p.addParamValue('stdev',1/7,@(x) isnumeric(x) && (x>=0));
0212 p.addParamValue('times',[],@isnumeric);
0213 p.addParamValue('decfactor',0,@isnumeric);
0214 p.addParamValue('title',[],@ischar);
0215 p.addParamValue('img1_title','Img1',@(x) ischar(x) || isempty(x));
0216 p.addParamValue('img2_title','Img2',@(x) ischar(x) || isempty(x));
0217 p.addParamValue('cbarlimits',[],@(x) (isnumeric(x) && (length(x)==2)) || isempty(x));
0218 p.addParamValue('cbartitle','\muV',@ischar);
0219 p.addParamValue('yimglabel','Trials',@ischar);
0220 p.addParamValue('yimgticks',[],@isnumeric);
0221 p.addParamValue('timelimits',[],@(x) (isnumeric(x) && (length(x)==2)) || isempty(x));
0222 p.addParamValue('erplimits',[],@(x) (isnumeric(x) && (length(x)==2)) || isempty(x));
0223 p.addParamValue('erpdiflimits',[],@(x) (isnumeric(x) && (length(x)==2)) || isempty(x));
0224 p.addParamValue('sortvarlimits',[],@(x) (isnumeric(x) && (length(x)==2)) || isempty(x));
0225 p.addParamValue('yerplabel','ERP (\muV)',@ischar);
0226 p.addParamValue('erpgrid','on',@(x) strcmpi(x,'on') || strcmpi(x,'off'));
0227 p.addParamValue('topos','on',@(x) strcmpi(x,'on') || strcmpi(x,'off'));
0228 p.addParamValue('chanlocs1',[],@isstruct);
0229 p.addParamValue('chanlocs2',[],@isstruct);
0230 p.addParamValue('renorm','off',@ischar);
0231 p.addParamValue('rmerp','off',@(x) strcmpi(x,'on') || strcmpi(x,'off'));
0232 p.addParamValue('showsortvar','on',@(x) strcmpi(x,'on') || strcmpi(x,'off'));
0233 p.addParamValue('srate',[],@(x) isnumeric(x) && (length(x)==1) && (x>0));
0234 p.addParamValue('marktimes',[],@isnumeric);
0235 p.addParamValue('marktrials',[],@isnumeric);
0236 p.addParamValue('baseline',[],@(x) (isnumeric(x) && (length(x)==2)) || isempty(x));
0237 p.addParamValue('filt',[],@(x) (isnumeric(x) && (length(x)==2)) || isempty(x));
0238
0239 p.parse(data1,data2,sortvar1,sortvar2,chan1,chan2,varargin{:});
0240
0241
0242
0243
0244
0245
0246 if size(data1,1)~=size(data2,1),
0247 error('data1 and data2 need to have the same number of time points.');
0248 else
0249 ntrials1=size(data1,2);
0250 ntpts=size(data1,1);
0251 ntrials2=size(data2,2);
0252 mn_ntrials=min([ntrials1 ntrials2]);
0253 not_nan_trials1=find(~isnan(sortvar1));
0254 not_nan_trials2=find(~isnan(sortvar2));
0255 if length(not_nan_trials1)==length(not_nan_trials2),
0256 if ~unique(data1(:,not_nan_trials1)-data2(:,not_nan_trials2))
0257 error('The two datasets you''re trying to contrast are exactly the same.');
0258 end
0259 end
0260 end
0261
0262
0263
0264 if length(sortvar1)~=ntrials1,
0265 error('sortvar1 and data1 have to have the same number of trials.');
0266 end
0267 if length(sortvar2)~=ntrials2,
0268 error('sortvar2 and data2 have to have the same number of trials.');
0269 end
0270
0271
0272
0273 if isempty(p.Results.times)
0274 times = 1:ntpts;
0275 xlab='Time Points';
0276 else
0277 times=p.Results.times;
0278 if length(times)~=ntpts,
0279 error('The number time points in ''times'', %d, does not equal the number of time points in the data. %d.',length(times),ntpts)
0280 end
0281 xlab='Time (msec)';
0282 end
0283 if isempty(p.Results.timelimits)
0284 timelimits = [min(times) max(times)];
0285 else
0286 timelimits = p.Results.timelimits;
0287 if (timelimits(2)<timelimits(1)),
0288 error('First element of ''timelimits'' needs to be less than or equal to the second element.');
0289 end
0290
0291 mn_time=min(times);
0292 if timelimits(1)<mn_time,
0293 watchit(sprintf('''timelimits'' extends before each trial''s earliest time point %d.',mn_time));
0294 fprintf('Setting earliest time limit to %d msec.\n',mn_time);
0295 timelimits(1)=mn_time;
0296
0297
0298 if timelimits(2)<mn_time,
0299 timelimits(2)=min(setdiff(times,mn_time));
0300 fprintf('Setting latest time limit to %d msec.\n',timelimits(2));
0301 end
0302 end
0303
0304 mx_time=max(times);
0305 if timelimits(2)>mx_time,
0306 watchit(sprintf('''timelimits'' extends after each trial''s latest time point %d.',mx_time));
0307 fprintf('Setting latest time limit to %d msec.\n',mx_time);
0308 timelimits(2)=mx_time;
0309
0310
0311 if timelimits(1)>mx_time,
0312 timelimits(1)=max(setdiff(times,mx_time));
0313 fprintf('Setting earliest time limit to %d msec.\n',timelimits(1));
0314 end
0315 end
0316 end
0317 if ~isempty(p.Results.erplimits),
0318 if p.Results.erplimits(1)>=p.Results.erplimits(2),
0319 error('First element of ''erplimits'' needs to be less than the second element.');
0320 end
0321 end
0322 if ~isempty(p.Results.erpdiflimits),
0323 if p.Results.erpdiflimits(1)>=p.Results.erpdiflimits(2),
0324 error('First element of ''erpdiflimits'' needs to be less than the second element.');
0325 end
0326 end
0327
0328
0329 if p.Results.decfactor > mn_ntrials
0330 fprintf('Setting variable decfactor to max %d.\n',mn_ntrials)
0331 decfactor = mn_ntrials;
0332 else
0333 decfactor = p.Results.decfactor;
0334 end
0335
0336
0337 if strcmpi(p.Results.topos,'on') && isempty(p.Results.chanlocs1),
0338 error('If ''topos'' is set to ''on'', you need to provide ''chanlocs'' (i.e., channel locations) as well.');
0339 end
0340 if isempty(p.Results.chanlocs2),
0341 chanlocs2=p.Results.chanlocs1;
0342 else
0343 chanlocs2=p.Results.chanlocs2;
0344 end
0345 topomap1=0;
0346 for a=1:length(p.Results.chanlocs1),
0347 if strcmpi(strtok(chan1),strtok(p.Results.chanlocs1(a).labels))
0348 topomap1=a;
0349 break;
0350 end
0351 end
0352 topomap2=0;
0353 for a=1:length(chanlocs2),
0354 if strcmpi(strtok(chan2),strtok(chanlocs2(a).labels))
0355 topomap2=a;
0356 break;
0357 end
0358 end
0359
0360
0361
0362 img_ytick_lab=p.Results.yimgticks;
0363 verttimes=p.Results.marktimes;
0364 horzepochs=p.Results.marktrials;
0365 aligntime=NaN;
0366 percentiles=[];
0367
0368
0369 YES = 1;
0370 NO = 0;
0371
0372 curfig = gcf;
0373 BACKCOLOR = [0.8 0.8 0.8];
0374 try, icadefs; catch, end;
0375
0376
0377
0378
0379 SORTWIDTH = 2.5;
0380 ZEROWIDTH = 3.0;
0381 VERTWIDTH = 2.5;
0382 HORZWIDTH = 2.1;
0383 SIGNIFWIDTH = 1.9;
0384 DOTSTYLE = 'k--';
0385 LINESTYLE = '-';
0386 LABELFONT = 10;
0387 TITLEFONT = 12;
0388 FIG_TITLEFONT = 16;
0389 TICKFONT = 10;
0390
0391 PLOT_HEIGHT = 0.2;
0392 YGAP = 0.03;
0393 YEXPAND = 1.3;
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 if any(isnan(sortvar1))
0405 nantrials = find(isnan(sortvar1));
0406 fprintf('Removing data1 %d trials with NaN sortvar1 values.\n', length(nantrials));
0407 data1(:,nantrials) = [];
0408 sortvar1(nantrials) = [];
0409 ntrials1 = length(sortvar1);
0410 if ~ntrials1,
0411 error('No trials with legal values for sortvar1');
0412 end
0413 end
0414
0415
0416
0417 if any(isnan(sortvar2))
0418 nantrials = find(isnan(sortvar2));
0419 fprintf('Removing data2 %d trials with NaN sortvar2 values.\n', length(nantrials));
0420 data2(:,nantrials) = [];
0421 sortvar2(nantrials) = [];
0422 ntrials2 = length(sortvar2);
0423 if ~ntrials2,
0424 error('No trials with legal values for sortvar2');
0425 end
0426 end
0427
0428
0429 cmn_vals=intersect(sortvar1,sortvar2);
0430 if isempty(cmn_vals),
0431 error('The two sets of data have no common values of the sorting variable. You cannot compare them.');
0432 end
0433 cmn_data1=zeros(ntpts,mn_ntrials)*NaN;
0434 cmn_data2=zeros(ntpts,mn_ntrials)*NaN;
0435 sortedvar=zeros(mn_ntrials)*NaN;
0436 n_ties=0;
0437 dist_ties=zeros(1,length(cmn_vals));
0438
0439 cmn_ct=0;
0440 dist_ct=0;
0441 for rept_loop=cmn_vals,
0442 ids1=find(sortvar1==rept_loop);
0443 ids2=find(sortvar2==rept_loop);
0444 n_ids1=length(ids1);
0445 n_ids2=length(ids2);
0446 mn_ids=min([n_ids1 n_ids2]);
0447 mx_ids=max([n_ids1 n_ids2]);
0448 dist_ct=dist_ct+1;
0449 if mx_ids>1,
0450 avg1=mean(data1(:,ids1),2);
0451 cmn_data1(:,cmn_ct+1:mn_ids+cmn_ct)=repmat(avg1,1,mn_ids);
0452 avg2=mean(data2(:,ids2),2);
0453 cmn_data2(:,cmn_ct+1:mn_ids+cmn_ct)=repmat(avg2,1,mn_ids);
0454 sortedvar(cmn_ct+1:mn_ids+cmn_ct)=rept_loop;
0455 n_ties=n_ties+mn_ids;
0456 cmn_ct=cmn_ct+mn_ids;
0457 dist_ties(dist_ct)=mn_ids;
0458 else
0459 cmn_ct=cmn_ct+1;
0460 cmn_data1(:,cmn_ct)=data1(:,ids1);
0461 cmn_data2(:,cmn_ct)=data2(:,ids2);
0462 sortedvar(cmn_ct)=rept_loop;
0463 end
0464 end
0465
0466
0467 cmn_data1=cmn_data1(:,1:cmn_ct);
0468 cmn_data2=cmn_data2(:,1:cmn_ct);
0469 sortedvar=sortedvar(1:cmn_ct);
0470 fprintf('%.2f%c of the used trials (i.e., %d out of %d) have the same sortvar value as at least one other trial.\n', ...
0471 (n_ties/cmn_ct)*100,37,n_ties,cmn_ct);
0472 fprintf('Distribution of number ties per unique value of sortvar:\n');
0473 fprintf('Min: %d, 25th ptile: %d, Median: %d, 75th ptile: %d, Max: %d\n',min(dist_ties),prctile(dist_ties,25), ...
0474 median(dist_ties),prctile(dist_ties,75),max(dist_ties));
0475 fprintf('Trials with tied sorting values will be replaced by their mean.\n\n');
0476 sortidx=1:cmn_ct;
0477
0478
0479
0480
0481 switch lower(p.Results.renorm)
0482 case 'on',
0483 fprintf('\nSorting variable renormalized.\n\n');
0484 sortedvar = (sortedvar-min(sortedvar)) / (max(sortedvar) - min(sortedvar)) * ...
0485 0.5 * (max(times) - min(times)) + min(times) + 0.4*(max(times) - min(times));
0486 case 'off',;
0487 otherwise,
0488 locx = findstr('x', lower(p.Results.renorm));
0489 if length(locx) ~= 1, error('erpimage2chan: unrecognized renormalizing formula'); end;
0490 try
0491 eval( [ 'sortedvar =' p.Results.renorm(1:locx-1) 'sortedvar' p.Results.renorm(locx+1:end) ';'] );
0492 catch
0493 error('Invalid sorting variable renormalization formula.');
0494 end
0495 end;
0496
0497
0498
0499
0500
0501 stdev=p.Results.stdev;
0502 if stdev==0,
0503 stdev=1/7;
0504 end
0505 wt_wind=exp(-0.5*([-3*stdev:3*stdev]/stdev).^2)';
0506 wt_wind=wt_wind/sum(wt_wind);
0507 avewidth=length(wt_wind);
0508
0509 if avewidth==0,
0510 wt_wind=1;
0511 avewidth=1;
0512 watchit('Moving average smoothing window is smaller than a time point. No smoothing will be done.');
0513 elseif avewidth > cmn_ct,
0514 watchit('Moving average window is too big for this number of trials (i.e., ''stdev'' is too big).\n');
0515
0516 stdev=floor((cmn_ct-1)/6);
0517 fprintf('\nTrying a Gaussian window with stdev of %d trials.\n',stdev);
0518 wt_wind=exp(-0.5*([-3*stdev:3*stdev]/stdev).^2)';
0519 wt_wind=wt_wind/sum(wt_wind);
0520 avewidth=length(wt_wind);
0521
0522
0523 if avewidth==0,
0524 wt_wind=1;
0525 avewidth=1;
0526 fprintf('Attempt failed. Moving average smoothing window is smaller than a time point. No smoothing will be done.\n');
0527 elseif avewidth > cmn_ct,
0528 fprintf('Attempt failed. Try picking a new stdev by hand. Currently, no smoothing will be done.\n');
0529 wt_wind=1;
0530 avewidth=1;
0531 end
0532 end
0533
0534
0535 if avewidth > 1 || decfactor > 1
0536 fprintf('\nSmoothing the sorting variable using a window width of %g epochs ',avewidth);
0537 fprintf('\n and a decimation factor of %g\n',decfactor);
0538 [outsort,outtrials] = movav(sortedvar,1:cmn_ct,avewidth,decfactor,[],[],wt_wind);
0539
0540 for index=1:length(percentiles)
0541 outpercent{index} = compute_percentile( sortedvar, percentiles(index), outtrials, avewidth);
0542 end;
0543 else
0544 outtrials = 1:cmn_ct;
0545 outsort = sortedvar;
0546 end
0547
0548
0549
0550
0551 if ~isempty(p.Results.yimglabel) && ~strcmpi(p.Results.yimglabel,'Trials')
0552 mn=min(outsort);
0553 mx=max(outsort);
0554 ord=orderofmag(mx-mn);
0555 rng_rnd=round([mn mx]/ord)*ord;
0556 if isempty(img_ytick_lab)
0557 img_ytick_lab=[rng_rnd(1):ord:rng_rnd(2)];
0558 in_range=find((img_ytick_lab>=mn) & (img_ytick_lab<=mx));
0559 img_ytick_lab=img_ytick_lab(in_range);
0560 else
0561 img_ytick_lab=unique(img_ytick_lab);
0562 in_range=find((img_ytick_lab>=mn) & (img_ytick_lab<=mx));
0563 if length(img_ytick_lab)~=length(in_range),
0564 fprintf('\n***Warning***\n');
0565 fprintf('''img_trialax_ticks'' exceed smoothed sorting variable values. Max/min values are %f/%f.\n\n',mn,mx);
0566 img_ytick_lab=img_ytick_lab(in_range);
0567 end
0568 end
0569 n_tick=length(img_ytick_lab);
0570 img_ytick=zeros(1,n_tick);
0571 for tickloop=1:n_tick,
0572 img_ytick(tickloop)=find_crspnd_pt(img_ytick_lab(tickloop),outsort,outtrials);
0573 end
0574 end
0575
0576
0577
0578
0579
0580
0581 erps=zeros(3,ntpts);
0582 mindat=zeros(1,3);
0583 maxdat=mindat;
0584
0585 for eimloop=1:3,
0586 switch eimloop
0587 case 1
0588 data=cmn_data1;
0589 case 2
0590 data=cmn_data2;
0591 case 3
0592 data=cmn_data1-cmn_data2;
0593 end
0594
0595
0596
0597
0598 nans = find(isnan(data));
0599 if ~isempty(nans)
0600 if eimloop==1,
0601 error('Some values of ''data1'' are NaN (i.e., not a number). There''s been some error in data processing (e.g., division by 0).');
0602 elseif eimloop==2,
0603 error('Some values of ''data2'' are NaN (i.e., not a number). There''s been some error in data processing (e.g., division by 0).');
0604 end
0605 end
0606
0607
0608
0609
0610
0611 if ~isempty(p.Results.filt),
0612
0613 if isempty(p.Results.srate),
0614 watchit('To use the ''filt'' option you need to specify the sampling rate with the ''srate'' parameter.');
0615 fprintf('Not filtering data.\n\n');
0616 else
0617 if length(p.Results.filt)~=2,
0618 error('''filt'' parameter argument should be a two element vector.');
0619 elseif max(p.Results.filt)>(p.Results.srate/2),
0620 error('''filt'' parameters need to be less than or equal to sampling rate/2 (i.e., %f).',p.Results.srate/2);
0621 elseif (p.Results.filt(2)==(p.Results.srate/2)) && (p.Results.filt(1)==0),
0622 error('If second element of ''filt'' parameter is srate/2, then the first element must be greater than 0.');
0623 elseif abs(p.Results.filt(2))<=abs(p.Results.filt(1)),
0624 error('Second element of ''filt'' parameters must be greater than first in absolute value.');
0625 elseif (p.Results.filt(1)<0) || (p.Results.filt(2)<0),
0626 if (p.Results.filt(1)>=0) || (p.Results.filt(2)>=0),
0627 error('BOTH parameters of ''filt'' need to be greater than or equal to zero OR need to be negative.');
0628 end
0629 if min(p.Results.filt)<=(-p.Results.srate/2),
0630 error('''filt'' parameters need to be greater than sampling rate/2 (i.e., -%f) when creating a stop band.',p.Results.srate/2);
0631 end
0632 end
0633
0634 msg=sprintf('\nFiltering data with 3rd order Butterworth filter: ');
0635 if (p.Results.filt(1)==0),
0636
0637 [B A]=butter(3,p.Results.filt(2)*2/p.Results.srate,'low');
0638 msg=[msg sprintf('lowpass at %.0f Hz\n',p.Results.filt(2))];
0639 elseif (p.Results.filt(2)==(p.Results.srate/2)),
0640
0641 [B A]=butter(3,p.Results.filt(1)*2/p.Results.srate,'high');
0642 msg=[msg sprintf('highpass at %.0f Hz\n',p.Results.filt(1))];
0643 elseif (p.Results.filt(1)<0)
0644
0645 [B A]=butter(3,-p.Results.filt*2/p.Results.srate,'stop');
0646 msg=[msg sprintf('stopband from %.0f to %.0f Hz\n',-p.Results.filt(1),-p.Results.filt(2))];
0647 else
0648
0649 [B A]=butter(3,p.Results.filt*2/p.Results.srate);
0650 msg=[msg sprintf('bandpass from %.0f to %.0f Hz\n',p.Results.filt(1),p.Results.filt(2))];
0651 end
0652 for trial=1:cmn_ct,
0653 data(:,trial)=filtfilt(B,A,data(:,trial));
0654 end
0655 if isempty(p.Results.baseline)
0656 msg=[msg sprintf('Note, you might want to re-baseline the data using the ''baseline'' option.\n\n')];
0657 end
0658 if eimloop==1,
0659 disp(msg);
0660 end
0661 end
0662 end
0663
0664
0665 if ~isempty(p.Results.baseline),
0666
0667 if p.Results.baseline(2)<p.Results.baseline(1),
0668 error('First element of ''baseline'' argument needs to be less than or equal to second argument.');
0669 elseif p.Results.baseline(2)<times(1),
0670 error('Second element of ''baseline'' argument needs to be greater than or equal to epoch start time %.1f.',times(1));
0671 elseif p.Results.baseline(1)>times(end),
0672 error('First element of ''baseline'' argument needs to be less than or equal to epoch end time %.1f.',times(end));
0673 end
0674
0675
0676 if p.Results.baseline(1)<times(1),
0677 strt_pt=1;
0678 else
0679 strt_pt=find_crspnd_pt(p.Results.baseline(1),times,1:ntpts);
0680 strt_pt=ceil(strt_pt);
0681 end
0682 if p.Results.baseline(end)>times(end),
0683 end_pt=length(times);
0684 else
0685 end_pt=find_crspnd_pt(p.Results.baseline(2),times,1:ntpts);
0686 end_pt=floor(end_pt);
0687 end
0688 if eimloop==1,
0689 fprintf('\nRemoving pre-stimulus mean baseline from %.1f to %.1f msec.\n\n',times(strt_pt),times(end_pt));
0690 end
0691 bsln_mn=mean(data(strt_pt:end_pt,:),1);
0692 data=data-repmat(bsln_mn,ntpts,1);
0693 end
0694
0695 if isempty(p.Results.sortvarlimits),
0696 erps(eimloop,:)=mean(data');
0697 end
0698
0699
0700
0701
0702 if strcmpi(p.Results.rmerp, 'on')
0703 data = data - repmat(nan_mean(data')', [1 size(data,2)]);
0704 end;
0705
0706
0707
0708
0709
0710 if avewidth > 1 || decfactor > 1
0711 if eimloop==1,
0712 fprintf('Smoothing the sorted epochs with a %g-epoch moving window.',...
0713 avewidth);
0714 fprintf('\n');
0715 fprintf(' and a decimation factor of %g\n',decfactor);
0716 end
0717
0718 [data,outtrials] = movav(data,1:cmn_ct,avewidth,decfactor,[],[],wt_wind);
0719
0720 [outsort,outtrials] = movav(sortedvar,1:cmn_ct,avewidth,decfactor,[],[],wt_wind);
0721
0722 for index=1:length(percentiles)
0723 outpercent{index} = compute_percentile( sortedvar, percentiles(index), outtrials, avewidth);
0724 end;
0725 if eimloop==1,
0726 fprintf('Output data will be %d ntpts by %d smoothed trials.\n',...
0727 ntpts,length(outtrials));
0728 fprintf('Outtrials: %3.2f to %4.2f\n',min(outtrials),max(outtrials));
0729 end
0730 else
0731 outtrials = 1:cmn_ct;
0732 outsort = sortedvar;
0733 end
0734 outdata(:,:,eimloop)=data;
0735 mindat(eimloop) = min(min(data));
0736 maxdat(eimloop) = max(max(data));
0737
0738 end
0739
0740
0741
0742
0743 if ~isempty(p.Results.cbarlimits)
0744 img_min = p.Results.cbarlimits(1);
0745 img_max = p.Results.cbarlimits(2);
0746 if img_min>img_max,
0747 watchit('First element of ''cbarlimits'' needs to be less than the second element.');
0748 img_min = min(min(data));
0749 img_max = max(max(data));
0750 img_max = max(abs([img_min img_max]));
0751 img_min = -img_max;
0752 fprintf('The color scale imits will be the symmetric abs. data range -> [%g,%g].\n', img_min, img_max);
0753 else
0754 fprintf('Using the specified caxis range of [%g,%g].\n', img_min, img_max);
0755 end
0756 img_mxDIF=max(abs([mindat(3) maxdat(3)]));
0757 fprintf('The color scale limits for the difference between erpimages will be the symmetric abs. data range -> [%g,%g].\n', -img_mxDIF, img_mxDIF);
0758 else
0759 img_max=max(abs([mindat(1:2) maxdat(1:2)]));
0760 img_min=-img_max;
0761 fprintf('The cbarlimits for individual erpimages will be the symmetric abs. data range -> [%g,%g].\n', img_min, img_max);
0762 img_mxDIF=max(abs([mindat(3) maxdat(3)]));
0763 fprintf('The cbarlimits for the difference between erpimages will be the symmetric abs. data range -> [%g,%g].\n', -img_mxDIF, img_mxDIF);
0764 end
0765
0766
0767
0768
0769
0770
0771 fprintf('Data will be plotted between %g and %g ms.\n',timelimits(1),timelimits(2));
0772
0773 for eimloop=1:3,
0774
0775
0776 switch (eimloop),
0777 case 1
0778 img_pos1=[.09 .53 .35 .35];
0779 img_ax=axes('position',img_pos1);
0780 imagesc(times,outtrials,outdata(:,:,eimloop)',[img_min img_max]);
0781 case 2
0782 img_pos2=[.54 .53 .35 .35];
0783 img_ax=axes('position',img_pos2);
0784 imagesc(times,outtrials,outdata(:,:,eimloop)',[img_min img_max]);
0785 case 3
0786 img_pos3=[.09 .09 .35 .35];
0787 img_ax=axes('position',img_pos3);
0788 imagesc(times,outtrials,outdata(:,:,eimloop)',[-img_mxDIF,img_mxDIF]);
0789 end
0790 set(gca,'Ydir','normal');
0791 axis([timelimits(1) timelimits(2) ...
0792 min(outtrials) max(outtrials)]);
0793 hold on
0794 drawnow
0795
0796
0797 if eimloop~=2,
0798 l=ylabel(p.Results.yimglabel);
0799 set(l,'FontSize',LABELFONT);
0800 if ~isempty(p.Results.yimgticks) || (~isempty(p.Results.yimglabel) && ~strcmpi(p.Results.yimglabel,'Trials')),
0801 set(gca,'ytick',img_ytick,'yticklabel',img_ytick_lab);
0802 end
0803 elseif ~isempty(p.Results.yimglabel) && ~strcmpi(p.Results.yimglabel,'Trials'),
0804 set(gca,'ytick',img_ytick,'yticklabel',[]);
0805 end
0806
0807
0808
0809 if ~isempty(verttimes)
0810 if (size(verttimes,1) ~= 1) && (size(verttimes,2) == 1) && (size(verttimes,1) ~= cmn_ct)
0811 verttimes = verttimes';
0812 end
0813 if (size(verttimes,1) ~= 1) && (size(verttimes,1) ~= cmn_ct)
0814 fprintf('\nerpimage2chan(): vert arg matrix must have 1 or %d rows\n',cmn_ct);
0815 return
0816 end;
0817
0818 if size(verttimes,1) == 1
0819 fprintf('Plotting %d lines at times: ',size(verttimes,2));
0820 else
0821 fprintf('Plotting %d traces starting at times: ',size(verttimes,2));
0822 end
0823 for vt = verttimes
0824 fprintf('%g ',vt(1));
0825 if length(vt)==1
0826 mydotstyle = DOTSTYLE;
0827 if exist('auxcolors') && (length(verttimes) == length(auxcolors))
0828 mydotstyle = auxcolors{find(verttimes == vt)};
0829 end
0830 figure(curfig);plot([vt vt],[0 max(outtrials)],mydotstyle,'Linewidth',VERTWIDTH);
0831 elseif length(vt)==cmn_ct
0832 [outvt,ix] = movav(vt,1:cmn_ct,avewidth,decfactor,[],[],wt_wind);
0833 figure(curfig);plot(outvt,outtrials,DOTSTYLE,'Linewidth',VERTWIDTH);
0834 end
0835 end
0836 fprintf('\n');
0837 end
0838
0839
0840
0841
0842 if ~isempty(horzepochs)
0843 if size(horzepochs,1) > 1 && size(horzepochs,1) > 1
0844 watchit('Argument ''marktrials'' must be a vector. Ignoring ''marktrials''.');
0845 else
0846 if ~isempty(p.Results.yimglabel) && ~strcmpi(p.Results.yimglabel,'Trials'),
0847
0848 mx=max(outsort);
0849 mn=min(outsort);
0850 fprintf('Plotting %d lines at epochs corresponding to sorting variable values: ',length(horzepochs));
0851 for he = horzepochs
0852 fprintf('%g ',he);
0853
0854
0855 if (he>mn) && (he<mx)
0856 he_ep=find_crspnd_pt(he,outsort,outtrials);
0857 figure(curfig);plot([timelimits(1) timelimits(2)],[he_ep he_ep],LINESTYLE,'Linewidth',HORZWIDTH);
0858 end
0859 end
0860
0861 else
0862 fprintf('Plotting %d lines at epochs: ',length(horzepochs));
0863 for he = horzepochs
0864 fprintf('%g ',he);
0865
0866 figure(curfig);plot([timelimits(1) timelimits(2)],[he he],LINESTYLE,'Linewidth',HORZWIDTH);
0867 end
0868 end
0869 fprintf('\n');
0870 end
0871 end
0872 set(gca,'FontSize',TICKFONT)
0873 hold on;
0874
0875
0876
0877
0878
0879 if times(1) <= 0 & times(ntpts) >= 0
0880 figure(curfig);plot([0 0],[min(outtrials) max(outtrials)],...
0881 'k','Linewidth',ZEROWIDTH);
0882 end
0883
0884 if ( min(outsort) < timelimits(1) ...
0885 |max(outsort) > timelimits(2))
0886 ur_outsort = outsort;
0887 fprintf('Not all sortvar values within time vector limits: \n')
0888 fprintf(' outliers will be shown at nearest limit.\n');
0889 i = find(outsort< timelimits(1));
0890 outsort(i) = timelimits(1);
0891 i = find(outsort> timelimits(2));
0892 outsort(i) = timelimits(2);
0893 end
0894
0895
0896 switch (eimloop),
0897 case 1
0898 l=title(p.Results.img1_title);
0899 set(l,'FontSize',TITLEFONT,'fontweight','bold');
0900 case 2
0901 l=title(p.Results.img2_title);
0902 set(l,'FontSize',TITLEFONT,'fontweight','bold');
0903 case 3
0904 l=title([p.Results.img1_title '-' p.Results.img2_title]);
0905 set(l,'FontSize',TITLEFONT,'fontweight','bold');
0906 end
0907
0908 set(gca,'Box','off');
0909 set(gca,'Fontsize',TICKFONT);
0910 set(gca,'color',BACKCOLOR);
0911 if eimloop==3,
0912 figure(curfig);l=xlabel(xlab);
0913 set(l,'Fontsize',LABELFONT);
0914 else
0915 set(gca,'xticklabel',[]);
0916 end
0917
0918
0919
0920
0921
0922 if strcmpi(p.Results.showsortvar,'off')
0923 fprintf('Not overplotting sorted sortvar on data.\n');
0924 elseif isnan(aligntime)
0925 hold on;
0926 figure(curfig);plot(outsort,outtrials,'k','LineWidth',SORTWIDTH);
0927 drawnow
0928 end
0929
0930
0931
0932
0933 axcopy(gcf);
0934
0935
0936
0937
0938
0939
0940
0941 if ~isempty(p.Results.sortvarlimits)
0942 sortvarlimits=p.Results.sortvarlimits;
0943 v=axis;
0944 img_mn=find_crspnd_pt(sortvarlimits(1),outsort,outtrials);
0945 if isempty(img_mn),
0946 img_mn=1;
0947 sortvarlimits(1)=outsort(1);
0948 end
0949 img_mx=find_crspnd_pt(sortvarlimits(2),outsort,outtrials);
0950 if isempty(img_mx),
0951 img_mx=length(outsort);
0952 sortvarlimits(2)=outsort(img_mx);
0953 end
0954 axis([v(1:2) img_mn img_mx]);
0955 id1=find(sortvar>=sortvarlimits(1));
0956 id2=find(sortvar<=sortvarlimits(2));
0957 id=intersect(id1,id2);
0958 fprintf('%d epochs fall within sortvar limits.\n',length(id));
0959 erps(eimloop,:)=mean(outdata(:,round(img_mn):round(img_mx),eimloop),2)';
0960 end
0961
0962
0963
0964
0965 if (eimloop>1)
0966 pos=get(img_ax,'Position');
0967 axcb=axes('Position',...
0968 [pos(1)+.97*pos(3)+0.02 pos(2) ...
0969 0.03 pos(4)]);
0970 if eimloop==3,
0971 figure(curfig);cbar(axcb,0,[-img_mxDIF,img_mxDIF]);
0972 else
0973 figure(curfig);cbar(axcb,0,[img_min img_max]);
0974 end
0975 title(p.Results.cbartitle);
0976 set(axcb,'fontsize',TICKFONT,'xtick',[]);
0977 end
0978
0979 end
0980 warning on;
0981
0982
0983
0984
0985
0986 if strcmpi(p.Results.topos,'on'),
0987 axes('Position',[img_pos1(1) img_pos1(2)+.99*img_pos1(4) ...
0988 .1 .1]);
0989 fprintf('Plotting topo maps to show electrode location.\n');
0990 eloc_info.plotrad = [];
0991 try
0992 topoplot(topomap1,p.Results.chanlocs1,'electrodes','off', ...
0993 'style', 'blank', 'emarkersize1chan', 10, 'chaninfo', eloc_info);
0994 catch
0995 fprintf('topoplot() plotting failed.\n');
0996 end;
0997 axis('square');
0998
0999 axes('Position',[img_pos2(1) img_pos2(2)+.99*img_pos2(4) .1 .1]);
1000 try
1001 topoplot(topomap2,chanlocs2,'electrodes','off', ...
1002 'style', 'blank', 'emarkersize1chan',10,'emarkercolor1chan','b', 'chaninfo', eloc_info);
1003 catch
1004 fprintf('topoplot() plotting failed.\n');
1005 end;
1006 axis('square');
1007 end
1008
1009
1010
1011
1012
1013 if ~strcmpi(p.Results.rmerp,'on'),
1014 ERPWIDTH=1;
1015
1016
1017 if isempty(p.Results.erplimits)
1018 fac = 10;
1019 maxerp = 0;
1020 while maxerp == 0
1021 maxerp = round(fac*YEXPAND*max(max(erps(1:2,:))))/fac;
1022 fac = 10*fac;
1023 end
1024 maxerp=max(maxerp);
1025
1026 fac = 1;
1027 minerp = 0;
1028 while minerp == 0
1029 minerp = round(fac*YEXPAND*min(min(erps(1:2,:))))/fac;
1030 fac = 10*fac;
1031 end
1032 minerp=min(minerp);
1033 else
1034 minerp=p.Results.erplimits(1);
1035 maxerp=p.Results.erplimits(2);
1036 end
1037 limit = [timelimits minerp maxerp];
1038 erpAX=axes('position',[.54 .31 .35 .15]);
1039 fprintf('Plotting the ERPs\n');
1040 plot1trace(erpAX,times,erps(1:2,:),limit,[],[],[],p.Results.erpgrid,{'r','b'});
1041 erp_limits=axis;
1042 axis([timelimits erp_limits(3:4)]);
1043 set(gca,'xticklabel',[],'yaxislocation','right','Fontsize',TICKFONT);
1044 ylabel(p.Results.yerplabel);
1045 l=title(['{\color{red}' p.Results.img1_title ' \color{blue}' p.Results.img2_title '}']);
1046 set(l,'fontsize',TITLEFONT);
1047 axcopy(gcf);
1048
1049
1050 if isempty(p.Results.erpdiflimits)
1051 fac = 10;
1052 maxdif = 0;
1053 while maxdif == 0
1054 maxdif = round(fac*YEXPAND*max(max(erps(3,:))))/fac;
1055 fac = 10*fac;
1056 end
1057 maxdif=max(maxdif);
1058
1059 fac = 1;
1060 mindif = 0;
1061 while mindif == 0
1062 mindif = round(fac*YEXPAND*min(min(erps(3,:))))/fac;
1063 fac = 10*fac;
1064 end
1065 mindif=min(mindif);
1066 else
1067 mindif=p.Results.erpdiflimits(1);
1068 maxdif=p.Results.erpdiflimits(2);
1069 end
1070 limit = [timelimits mindif maxdif];
1071
1072
1073 purple=[148 0 211]/255;
1074 difAX=axes('position',[.54 .09 .35 .15]);
1075 plot1trace(difAX,times,erps(3,:),limit,[],[],[],p.Results.erpgrid,{purple});
1076 dif_limits=axis;
1077 axis([timelimits dif_limits(3:4)]);
1078 xlabel(xlab);
1079 ylabel(p.Results.yerplabel);
1080 set(gca,'yaxislocation','right','Fontsize',TICKFONT);
1081 l=title(['\color[rgb]{.58 0 .828}' p.Results.img1_title '-' p.Results.img2_title ]);
1082 set(l,'fontsize',TITLEFONT);
1083 axcopy(gcf);
1084 if ~exist('YDIR')
1085 error('Default YDIR not read from ''icadefs.m''');
1086 end
1087 if YDIR == 1
1088 set(erpAX,'ydir','normal');
1089 set(difAX,'ydir','normal');
1090 else
1091 set(erpAX,'ydir','reverse');
1092 set(difAX,'ydir','reverse');
1093 end
1094
1095
1096 if ~isempty(verttimes)
1097 if size(verttimes,1) == cmn_ct
1098 vts=sort(verttimes);
1099 vts = vts(ceil(cmn_ct/2),:);
1100 else
1101 vts = verttimes(:)';
1102 end
1103 for vt = vts
1104 if isnan(aligntime)
1105 mydotstyle = DOTSTYLE;
1106 if exist('auxcolors') & ...
1107 length(verttimes) == length(verttimesColors)
1108 mydotstyle = verttimesColors{find(verttimes == vt)};
1109 end
1110 axes(erpAX);plot([vt vt],erp_limits(3:4),mydotstyle,'Linewidth',ERPWIDTH);
1111 axes(difAX);plot([vt vt],dif_limits(3:4),mydotstyle,'Linewidth',ERPWIDTH);
1112 else
1113 axes(erpAX);plot(repmat(median(aligntime+vt-outsort),1,2),erp_limits(3:4),...
1114 DOTSTYLE,'LineWidth',ERPWIDTH);
1115 axes(difAX);plot(repmat(median(aligntime+vt-outsort),1,2),dif_limits(3:4),...
1116 DOTSTYLE,'LineWidth',ERPWIDTH);
1117 end
1118 end
1119 end
1120 end
1121
1122
1123 if ~isempty(p.Results.title),
1124 fig_title=textsc(p.Results.title,'title');
1125 set(fig_title,'fontsize',FIG_TITLEFONT,'fontweight','bold');
1126 end
1127
1128 return
1129
1130
1131
1132
1133
1134 function [plot_handle] = plot1trace(ax,times,trace,axlimits,signif,stdev,winlocs,erp_grid,erp_colors)
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 FILLCOLOR = [.66 .76 1];
1145 WINFILLCOLOR = [.88 .92 1];
1146 ERPDATAWIDTH = 1;
1147 ERPZEROWIDTH = 1;
1148 axes(ax);
1149
1150 if ~isempty(winlocs)
1151 for k=1:size(winlocs,1)
1152 winloc = winlocs(k,:);
1153 fillwinx = [winloc winloc(end:-1:1)];
1154 hannwin = makehanning(length(winloc));
1155 hannwin = hannwin./max(hannwin);
1156 hannwin = hannwin(:)';
1157 if ~isempty(axlimits) & sum(isnan(axlimits))==0
1158
1159 fillwiny = [hannwin*axlimits(3) hannwin*axlimits(4)];
1160 else
1161
1162 fillwiny = [hannwin*2*min(trace) hannwin*2*max(trace)];
1163 end
1164 fillwh = fill(fillwinx,fillwiny, WINFILLCOLOR); hold on
1165 set(fillwh,'edgecolor',WINFILLCOLOR-[.00 .00 0]);
1166 end
1167 end
1168 if ~isempty(signif);
1169 filltimes = [times times(end:-1:1)];
1170 if size(signif,1) ~=2 | size(signif,2) ~= length(times)
1171 fprintf('plot1trace(): signif array must be size (2,ntpts)\n')
1172 return
1173 end
1174 fillsignif = [signif(1,:) signif(2,end:-1:1)];
1175 fillh = fill(filltimes,fillsignif, FILLCOLOR); hold on
1176 set(fillh,'edgecolor',FILLCOLOR-[.02 .02 0]);
1177
1178
1179 end
1180 if ~isempty(stdev)
1181 [st1] = plot(times,trace+stdev, 'r--','LineWidth',1); hold on
1182 [st2] = plot(times,trace-stdev, 'r--','LineWidth',1); hold on
1183 end
1184
1185
1186 plot_handle=zeros(1,size(trace,1));
1187 for traceloop=1:size(trace,1),
1188 [plot_handle(traceloop)] = plot(times,trace(traceloop,:),'LineWidth',ERPDATAWIDTH, ...
1189 'color',erp_colors{traceloop}); hold on
1190 end
1191
1192 if ~isempty(axlimits) && sum(isnan(axlimits))==0
1193 if axlimits(2)>axlimits(1) && axlimits(4)>axlimits(3)
1194 axis([axlimits(1:2) 1.1*axlimits(3:4)])
1195 end
1196 l1=line([axlimits(1:2)],[0 0], 'Color','k',...
1197 'linewidth',ERPZEROWIDTH);
1198 timebar=0;
1199 l2=line([1 1]*timebar,axlimits(3:4)*1.1,'Color','k',...
1200 'linewidth',ERPZEROWIDTH);
1201
1202
1203 shrunk_ylimits=axlimits(3:4)*.8;
1204 ystep=(shrunk_ylimits(2)-shrunk_ylimits(1))/4;
1205 if ystep>1,
1206 ystep=round(ystep);
1207 else
1208 ord=orderofmag(ystep);
1209 ystep=round(ystep/ord)*ord;
1210 end
1211
1212 if (sign(shrunk_ylimits(2))*sign(shrunk_ylimits(1)))==1,
1213 erp_yticks=shrunk_ylimits(1):ystep:shrunk_ylimits(2);
1214 else
1215
1216
1217 erp_yticks=0:ystep:axlimits(4);
1218 erp_yticks=[erp_yticks [0:-ystep:axlimits(3)]];
1219 end
1220 if strcmpi(erp_grid,'on')
1221 set(gca,'ytick',unique(erp_yticks),'ygrid','on');
1222 else
1223 set(gca,'ytick',unique(erp_yticks));
1224 end
1225 end
1226
1227
1228
1229 kids=get(gca,'children')';
1230 for hndl_loop=plot_handle,
1231 id=find(kids==hndl_loop);
1232 kids(id)=[];
1233 kids=[hndl_loop kids];
1234 end
1235 set(gca,'children',kids');
1236 plot_handle=[plot_handle l1 l2];
1237
1238
1239
1240
1241
1242
1243
1244
1245 function [out, outalpha] = nan_mean(in,alpha)
1246 NBOOT = 500;
1247
1248 intrials = size(in,1);
1249 inframes = size(in,2);
1250 nans = find(isnan(in));
1251 in(nans) = 0;
1252 sums = sum(in);
1253 nonnans = ones(size(in));
1254 nonnans(nans) = 0;
1255 nonnans = sum(nonnans);
1256 nononnans = find(nonnans==0);
1257 nonnans(nononnans) = 1;
1258 out = sum(in)./nonnans;
1259 outalpha = [];
1260 if nargin>1
1261 if NBOOT < round(3/alpha)
1262 NBOOT = round(3/alpha);
1263 end
1264 fprintf('Computing %d bootstrap ERP values... ',NBOOT);
1265 booterps = zeros(NBOOT,inframes);
1266 for n=1:NBOOT
1267 signs = sign(randn(1,intrials)'-0.5);
1268 booterps(n,:) = sum(repmat(signs,1,inframes).*in)./nonnans;
1269 if ~rem(n,50)
1270 fprintf('%d ',n);
1271 end
1272 end
1273 fprintf('\n');
1274 booterps = sort(abs(booterps));
1275 alpha = 1+floor(2*alpha*NBOOT);
1276 outalpha = booterps(end+1-alpha,:);
1277 end
1278 out(nononnans) = NaN;
1279
1280
1281
1282
1283 function outpercent = compute_percentile(sortvar, percent, outtrials, winsize);
1284 ntrials = length(sortvar);
1285 outtrials=round(outtrials);
1286 sortvar = [ sortvar sortvar sortvar ];
1287 winvals = [round(-winsize/2):round(winsize/2)];
1288 outpercent = zeros(size(outtrials));
1289 for index = 1:length(outtrials)
1290 sortvarval = sortvar(outtrials(index)+ntrials+winvals);
1291 sortvarval = sort(sortvarval);
1292 outpercent(index) = sortvarval(round((length(winvals)-1)*percent)+1);
1293 end;
1294
1295
1296
1297
1298 function ord=orderofmag(val)
1299
1300
1301
1302
1303
1304
1305
1306 if val>=1
1307 ord=1;
1308 val=floor(val/10);
1309 while val>=1,
1310 ord=ord*10;
1311 val=floor(val/10);
1312 end
1313 return;
1314 else
1315 ord=1/10;
1316 val=val*10;
1317 while val<1,
1318 ord=ord/10;
1319 val=val*10;
1320 end
1321 return;
1322 end
1323
1324
1325
1326
1327 function y_pt=find_crspnd_pt(targ,vals,outtrials)
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346 abv=find(vals>=targ);
1347 if isempty(abv),
1348
1349 y_pt=[];
1350 return
1351 end
1352 abv=abv(1);
1353
1354
1355 blw=find(vals<=targ);
1356 if isempty(blw),
1357
1358 y_pt=[];
1359 return
1360 end
1361 blw=blw(end);
1362
1363 if (vals(abv)==vals(blw)),
1364
1365 ids=find(vals==targ);
1366 y_pt=median(outtrials(ids));
1367 else
1368
1369
1370
1371 B=regress([outtrials(abv) outtrials(blw)]',[ones(2,1) [vals(abv) vals(blw)]']);
1372
1373
1374 y_pt=[1 targ]*B;
1375
1376 end
1377 return
1378
1379
1380
1381 function watchit(msg)
1382
1383
1384
1385
1386
1387 disp(' ');
1388 disp('****************** Warning ******************');
1389 disp(msg);
1390 disp(' ');
1391 return;