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 function GND=erplab2GND(gui_infiles_or_tmplt,varargin)
0120
0121 p=inputParser;
0122 p.addRequired('gui_infiles_or_tmplt',@(x) ischar(x) || iscell(x));
0123 p.addParamValue('locfile',[],@ischar);
0124 p.addParamValue('sub_ids',[],@isnumeric);
0125 p.addParamValue('bsln',[],@(x) isnumeric(x) && length(x)==2);
0126 p.addParamValue('exp_name','An Experiment',@ischar);
0127 p.addParamValue('use_bins',[],@isnumeric);
0128 p.addParamValue('exclude_chans',[],@(x) ischar(x) || iscell(x));
0129 p.addParamValue('include_chans',[],@(x) ischar(x) || iscell(x));
0130 p.addParamValue('out_fname',[],@ischar);
0131 p.addParamValue('verblevel',[],@(x) isnumeric(x) && (length(x)==1));
0132 p.parse(gui_infiles_or_tmplt,varargin{:});
0133
0134
0135 global VERBLEVEL;
0136
0137 if isempty(p.Results.verblevel),
0138 if isempty(VERBLEVEL),
0139 VERBLEVEL=2;
0140 end
0141 else
0142 VERBLEVEL=p.Results.verblevel;
0143 end
0144
0145
0146
0147
0148 if ~isempty(p.Results.include_chans) && ~isempty(p.Results.exclude_chans)
0149 error('You cannot use BOTH ''include_chans'' and ''exclude_chans'' options.');
0150 end
0151 if ischar(p.Results.exclude_chans),
0152 exclude_chans{1}=p.Results.exclude_chans;
0153 elseif isempty(p.Results.exclude_chans)
0154 exclude_chans=[];
0155 else
0156 exclude_chans=p.Results.exclude_chans;
0157 end
0158 if ischar(p.Results.include_chans),
0159 include_chans{1}=p.Results.include_chans;
0160 elseif isempty(p.Results.include_chans)
0161 include_chans=[];
0162 else
0163 include_chans=p.Results.include_chans;
0164 end
0165
0166
0167
0168 if strcmpi(gui_infiles_or_tmplt,'GUI'),
0169 loading=1;
0170 infiles=[];
0171 while loading,
0172 [neofname, inpath]=uigetfile({'*.erp','*.erp files'; ...
0173 '*.*','All Files (*.*)'},'ERPLAB erp Files to Import','MultiSelect','on');
0174 if ischar(neofname),
0175 clear infname;
0176 infname{1}=neofname;
0177 else
0178 infname=neofname;
0179 end
0180 if ~inpath,
0181 if isempty(infiles),
0182 fprintf('File selection cancelled. Aborting erplab2GND.\n');
0183 GND=[];
0184 return;
0185 else
0186 loading=0;
0187 end
0188 else
0189 if isempty(infiles),
0190 infiles=cell(1,length(infname));
0191 for a=1:length(infname),
0192 infiles{a}=[inpath infname{a}];
0193 end
0194 else
0195 n_files=length(infiles);
0196 ct=0;
0197 for a=(n_files+1):(n_files+length(infname)),
0198 ct=ct+1;
0199 infiles{a}=[inpath infname{ct}];
0200 end
0201 end
0202
0203 resp=questdlg('Do you want to load more files?',...
0204 'OUTPUT','Yes','No','Yes');
0205 if strcmpi(resp,'No'),
0206 loading=0;
0207 end
0208 end
0209 end
0210 elseif iscell(p.Results.gui_infiles_or_tmplt)
0211 infiles=p.Results.gui_infiles_or_tmplt;
0212 else
0213 if isempty(p.Results.sub_ids)
0214 error('If gui_infiles_or_tmplt is a string filename template, you must specify the subject numbers with the argument ''sub_ids''.');
0215 elseif ~ismember('#',p.Results.gui_infiles_or_tmplt),
0216 error('The filename template %s needs to contain a # to indicate where the subject numbers go (e.g., odbl#.nrm).', ...
0217 p.Results.gui_infiles_or_tmplt);
0218 else
0219 lb_id=find(p.Results.gui_infiles_or_tmplt=='#');
0220 prefix=p.Results.gui_infiles_or_tmplt(1:(lb_id(1)-1));
0221 postfix=p.Results.gui_infiles_or_tmplt((lb_id(1)+1):end);
0222 n_infiles=length(p.Results.sub_ids);
0223 infiles=cell(1,n_infiles);
0224 for s=1:n_infiles,
0225 no_pad=[prefix num2str(p.Results.sub_ids(s)) postfix];
0226 if p.Results.sub_ids(s)<10,
0227 padded=[prefix num2str(p.Results.sub_ids(s),'%.2d') postfix];
0228 if ismac || isunix
0229
0230 [sP wP]=unix(['ls ' padded]);
0231 [sNP wNP]=unix(['ls ' no_pad]);
0232 if ~sP
0233 if ~sNP,
0234 error('You have a file named %s and one named %s. I don''t know which one to load!\n', ...
0235 padded,no_pad);
0236 else
0237 infiles{s}=padded;
0238 end
0239 else
0240 infiles{s}=no_pad;
0241 end
0242 else
0243
0244 infiles{s}=no_pad;
0245 end
0246 else
0247 infiles{s}=no_pad;
0248 end
0249 end
0250 end
0251 end
0252
0253
0254 infiles=unique(infiles);
0255 n_infiles=length(infiles);
0256
0257
0258
0259 ERP=load_erplab(infiles{1});
0260
0261 [n_ERP_chans, n_pts, n_ERP_bins]=size(ERP.bindata);
0262 if ~isempty(exclude_chans),
0263 use_chans=zeros(1,n_ERP_chans);
0264 ex_ct=0;
0265 for a=1:n_ERP_chans,
0266 if ~ismember_ci(ERP.chanlocs(a).labels,exclude_chans)
0267 use_chans(a)=1;
0268 else
0269 ex_ct=ex_ct+1;
0270 ex_labels{ex_ct}=ERP.chanlocs(a).labels;
0271 end
0272 end
0273 n_chans=sum(use_chans);
0274 use_chans=find(use_chans==1);
0275
0276 if VERBLEVEL>1,
0277 missed=setdiff_ci(exclude_chans,ex_labels);
0278 n_missed=length(missed);
0279 if n_missed,
0280 if n_missed==1,
0281 msg=sprintf('I attempted to exclude the following channel, but it was not found:');
0282 else
0283 msg=sprintf('I attempted to exclude the following channels, but they were not found:');
0284 end
0285 for a=1:n_missed,
0286 msg=[msg ' ' missed{a}];
0287 end
0288 watchit(msg);
0289 end
0290 end
0291 elseif ~isempty(include_chans),
0292 use_chans=zeros(1,n_ERP_chans);
0293 in_ct=0;
0294 for a=1:n_ERP_chans,
0295 if ismember_ci(ERP.chanlocs(a).labels,include_chans)
0296 use_chans(a)=1;
0297 in_ct=in_ct+1;
0298 in_labels{in_ct}=ERP.chanlocs(a).labels;
0299 end
0300 end
0301 n_chans=sum(use_chans);
0302 use_chans=find(use_chans==1);
0303
0304 if VERBLEVEL>1,
0305 missed=setdiff_ci(include_chans,in_labels);
0306 n_missed=length(missed);
0307 if n_missed,
0308 if n_missed==1,
0309 msg=sprintf('I attempted to include the following channel, but it was not found:');
0310 else
0311 msg=sprintf('I attempted to include the following channels, but they were not found:');
0312 end
0313 for a=1:n_missed,
0314 msg=[msg ' ' missed{a}];
0315 end
0316 watchit(msg);
0317 end
0318 end
0319 else
0320 n_chans=n_ERP_chans;
0321 use_chans=1:n_chans;
0322 end
0323
0324
0325 if isempty(p.Results.use_bins),
0326 use_bins=1:n_ERP_bins;
0327 n_bins=n_ERP_bins;
0328 else
0329
0330 if min(p.Results.use_bins)<1,
0331 error('You cannot request to import bins with indices less than 1 (e.g., "Bin -1").');
0332 elseif length(unique(p.Results.use_bins)) ~= length(p.Results.use_bins)
0333 error('You cannot request to import duplicate bins\n');
0334 elseif max(p.Results.use_bins)>n_ERP_bins,
0335 error('File %s only has %d bins, but you''ve requested to import Bin %d.\n', ...
0336 infiles{1},n_ERP_bins,max(p.Results.use_bins));
0337 end
0338 use_bins=p.Results.use_bins;
0339 n_bins=length(use_bins);
0340 end
0341
0342 GND.exp_desc=p.Results.exp_name;
0343 GND.filename=[];
0344 GND.filepath=[];
0345 GND.saved='no';
0346 GND.grands=zeros(n_chans,n_pts,n_bins)*NaN;
0347 GND.grands_stder=GND.grands;
0348 GND.grands_t=GND.grands;
0349 GND.sub_ct=zeros(1,n_bins);
0350 GND.chanlocs=ERP.chanlocs(use_chans);
0351 GND.bin_info=[];
0352
0353 for b=1:n_bins,
0354 GND.bin_info(b).bindesc=ERP.bindescr{use_bins(b)};
0355 GND.bin_info(b).condcode=1;
0356 end
0357
0358
0359 GND.condesc{1}='Experiment (not cal pulses)';
0360
0361 GND.time_pts=ERP.times;
0362 if isempty(p.Results.bsln)
0363
0364 GND.bsln_wind(1)=ERP.times(1);
0365 ids=find(ERP.times<0);
0366 if isempty(ids)
0367 GND.bsln_wind(2)=ERP.times(1);
0368 else
0369 GND.bsln_wind(2)=ERP.times(max(ids));
0370 end
0371 else
0372 GND.bsln_wind=p.Results.bsln;
0373 end
0374 GND.odelay=[];
0375 GND.srate=ERP.srate;
0376 GND.indiv_fnames=infiles;
0377 if isempty(ERP.subject),
0378 if VERBLEVEL,
0379 fprintf('ERP file, %s, does not have a subject name. I will use the filename as the subject''s name.\n', ...
0380 infiles{1});
0381 end
0382 GND.indiv_subnames{1}=infiles{1};
0383 else
0384 GND.indiv_subnames{1}=ERP.subject;
0385 end
0386 GND.indiv_traits=[];
0387 GND.indiv_bin_ct=zeros(n_infiles,n_bins);
0388 GND.indiv_bin_raw_ct=zeros(n_infiles,n_bins);
0389 GND.indiv_erps=zeros(n_chans,n_pts,n_bins,n_infiles);
0390 GND.indiv_art_ics=[];
0391 GND.cals=[];
0392 GND.history=[];
0393 GND.t_tests=[];
0394
0395
0396 sub_ct=1;
0397 for filenum=1:n_infiles,
0398
0399 if filenum>1,
0400 if VERBLEVEL,
0401 fprintf('\n\n');
0402 end
0403 ERP=load_erplab(infiles{filenum});
0404
0405
0406 if isempty(ERP.subject),
0407 if VERBLEVEL,
0408 fprintf('ERP file, %s, does not have a subject name. I will use the filename as the subject''s name.\n', ...
0409 infiles{filenum});
0410 end
0411 sub_name=infiles{filenum};
0412 else
0413 sub_name=ERP.subject;
0414 end
0415 ur_sub_id=0;
0416 for old_sub=1:sub_ct,
0417 if strcmpi(GND.indiv_subnames{old_sub},sub_name),
0418 ur_sub_id=old_sub;
0419 if VERBLEVEL
0420 fprintf('erp file, %s, will be appended to data already loaded from Subject %s.\n', ...
0421 infiles{filenum},GND.indiv_subnames{old_sub});
0422 end
0423 break;
0424 end
0425 end
0426 if ~ur_sub_id,
0427 sub_ct=sub_ct+1;
0428 sub=sub_ct;
0429 GND.indiv_subnames{sub}=sub_name;
0430 else
0431 sub=ur_sub_id;
0432 end
0433
0434 [n_ERP_chans2, n_pts2, n_ERP_bins2]=size(ERP.bindata);
0435
0436
0437 if ~isempty(exclude_chans),
0438 use_chans=zeros(1,n_ERP_chans2);
0439 ex_ct=0;
0440 for a=1:n_ERP_chans2,
0441 if ~ismember_ci(ERP.chanlocs(a).labels,exclude_chans)
0442 use_chans(a)=1;
0443 else
0444 ex_ct=ex_ct+1;
0445 ex_labels{ex_ct}=ERP.chanlocs(a).labels;
0446 end
0447 end
0448 n_chans2=sum(use_chans);
0449 use_chans=find(use_chans==1);
0450
0451 if VERBLEVEL>1,
0452 missed=setdiff_ci(exclude_chans,ex_labels);
0453 n_missed=length(missed);
0454 if n_missed,
0455 if n_missed==1,
0456 msg=sprintf('I attempted to exclude the following channel, but it was not found:');
0457 else
0458 msg=sprintf('I attempted to exclude the following channels, but they were not found:');
0459 end
0460 for a=1:n_missed,
0461 msg=[msg ' ' missed{a}];
0462 end
0463 watchit(msg);
0464 end
0465 end
0466 elseif ~isempty(include_chans),
0467 use_chans=zeros(1,n_ERP_chans2);
0468 in_ct=0;
0469 for a=1:n_ERP_chans2,
0470 if ismember_ci(ERP.chanlocs(a).labels,include_chans)
0471 use_chans(a)=1;
0472 in_ct=in_ct+1;
0473 in_labels{in_ct}=ERP.chanlocs(a).labels;
0474 end
0475 end
0476 n_chans2=sum(use_chans);
0477 use_chans=find(use_chans==1);
0478
0479 if VERBLEVEL>1,
0480 missed=setdiff_ci(include_chans,in_labels);
0481 n_missed=length(missed);
0482 if n_missed,
0483 if n_missed==1,
0484 msg=sprintf('I attempted to include the following channel, but it was not found:');
0485 else
0486 msg=sprintf('I attempted to include the following channels, but they were not found:');
0487 end
0488 for a=1:n_missed,
0489 msg=[msg ' ' missed{a}];
0490 end
0491 watchit(msg);
0492 end
0493 end
0494
0495 else
0496 n_chans2=n_ERP_chans2;
0497 use_chans=1:n_chans2;
0498 end
0499
0500
0501 if ERP.srate~=GND.srate,
0502 error('File %s has a different sampling rate than file %s.\n', ...
0503 infiles{1},infiles{filenum});
0504 end
0505 if n_chans2~=n_chans,
0506 error('File %s has a different number of channels to import than file %s.\n', ...
0507 infiles{1},infiles{filenum});
0508 end
0509 if n_pts2~=n_pts,
0510 error('File %s has a different number of time points than file %s.\n', ...
0511 infiles{1},infiles{filenum});
0512 end
0513 if ~min(ERP.times==GND.time_pts),
0514 error('The epochs in file %s begin and end at different times than file %s.\n', ...
0515 infiles{1},infiles{filenum});
0516 end
0517 if isempty(p.Results.use_bins),
0518 if n_ERP_bins2~=n_bins,
0519 error('File %s has a different number of bins than file %s.\n', ...
0520 infiles{1},infiles{filenum});
0521 end
0522 else
0523 if max(p.Results.use_bins)>n_ERP_bins2,
0524 error('File %s only has %d bins, but you''ve requested to import Bin %d.\n', ...
0525 infiles{filenum},n_ERP_bins2,max(p.Results.use_bins));
0526 end
0527 end
0528
0529 bin_ct=0;
0530 for b=use_bins,
0531 bin_ct=bin_ct+1;
0532 if ~strcmpi(GND.bin_info(bin_ct).bindesc,ERP.bindescr{b}),
0533 error('The #%d imported bin in file %s is different than that of file %s.\n', ...
0534 b,infiles{1},infiles{filenum});
0535 end
0536 end
0537 try
0538 [fs1, fs2, er]=comp_struct_quiet(GND.chanlocs,ERP.chanlocs(use_chans));
0539 catch
0540 error('File %s''s imported channel location information differs from that of file %s.\n', ...
0541 infiles{1},infiles{filenum});
0542 end
0543 if ~isempty(er),
0544 error('File %s''s imported channel location information differs from that of file %s.\n', ...
0545 infiles{1},infiles{filenum});
0546 end
0547 else
0548 sub=sub_ct;
0549 end
0550
0551
0552
0553 GND.indiv_art_ics{filenum}=NaN;
0554
0555
0556 if ~isempty(GND.bsln_wind),
0557 bsln_pts(1)=find_tpt(GND.bsln_wind(1),ERP.times);
0558 bsln_pts(2)=find_tpt(GND.bsln_wind(2),ERP.times);
0559 if VERBLEVEL>=2,
0560 fprintf('Baselining data by removing mean EEG between %d and %d ms (time points %d and %d).\n', ...
0561 GND.bsln_wind(1),GND.bsln_wind(2),bsln_pts(1),bsln_pts(2));
0562 end
0563
0564 [temp_chans temp_tpts temp_bins]=size(ERP.bindata);
0565 ERP.bindata=rmbase(ERP.bindata,temp_tpts,bsln_pts(1):bsln_pts(2));
0566 ERP.bindata=reshape(ERP.bindata,temp_chans,temp_tpts,temp_bins);
0567 end
0568
0569
0570 GND.indiv_erps(:,:,:,sub)=ERP.bindata(use_chans,:,use_bins);
0571 GND.indiv_bin_raw_ct(sub,:)=ERP.ntrials.accepted(use_bins)+ERP.ntrials.rejected(use_bins);
0572 GND.indiv_bin_ct(sub,:)=ERP.ntrials.accepted(use_bins);
0573 end
0574
0575
0576
0577
0578 GND.indiv_bin_ct=GND.indiv_bin_ct(1:sub_ct,:);
0579 GND.indiv_bin_raw_ct=GND.indiv_bin_raw_ct(1:sub_ct,:);
0580 GND.indiv_erps=GND.indiv_erps(:,:,:,1:sub_ct);
0581
0582
0583
0584 for sub=1:sub_ct,
0585 if VERBLEVEL>1
0586 fprintf('\nTrials per bin for Subject %s:\n',GND.indiv_subnames{sub});
0587 end
0588 for b=1:n_bins,
0589 bin_ct=GND.indiv_bin_ct(sub,b);
0590 if bin_ct,
0591 if VERBLEVEL>1,
0592 fprintf('Bin %d (%s): %d trials\n',b,GND.bin_info(b).bindesc,bin_ct);
0593 end
0594 GND.sub_ct(b)=GND.sub_ct(b)+1;
0595 else
0596 watchit(sprintf('Subject %s has no epochs that fall into bin %d.',GND.indiv_subnames{sub},b));
0597 GND.indiv_erps(:,:,b,sub)=GND.indiv_erps(:,:,b,sub)*NaN;
0598 end
0599 end
0600 end
0601
0602
0603 if VERBLEVEL>1,
0604 fprintf('\n\n');
0605 end
0606 GND=baselineGND(GND,GND.bsln_wind);
0607
0608
0609
0610 if isempty(p.Results.out_fname),
0611
0612 [jname, jpath]=uiputfile({'*.GND','*.GND files'; ...
0613 '*','All files'},'Save GND variable as:','untitled.GND');
0614 if ~jpath,
0615 fprintf('Output filename selection cancelled. GND variable NOT saved to disk.\n');
0616 else
0617
0618 isW=isWriteable([jpath jname]);
0619 if isW,
0620 GND=save_matmk(GND,jname,jpath,1);
0621 else
0622 fprintf('GND file could not be saved, but should still exist in MATLAB workspace.');
0623 end
0624 end
0625 elseif ~strcmpi(p.Results.out_fname,'no save'),
0626 [jpath, jname]=pathNname(p.Results.out_fname);
0627
0628 if ~ismember('.',jname),
0629 jname=[jname '.GND'];
0630 end
0631 GND=save_matmk(GND,jname,jpath);
0632 end
0633
0634
0635 function isW = isWriteable(inFile)
0636
0637
0638
0639
0640
0641
0642 isW = 0;
0643 [fid, message] = fopen(inFile,'a+');
0644 if (fid ~= -1)
0645 isW = 1;
0646 fclose(fid);
0647 else
0648 fprintf('Error opening %s: %s\n', inFile, message);
0649 end
0650
0651 function ERP=load_erplab(filename)
0652
0653
0654
0655
0656
0657
0658 load(filename,'-MAT');
0659 if ~exist('ERP','var'),
0660 error('File %s does not contain a variable named "ERP".',filename);
0661 end
0662 if ~isfield(ERP,'bindescr')
0663 error('The "ERP" variable in file %s does not appear to have been produced by ERPLAB.',filename);
0664 end
0665
0666 function yesno=ismember_ci(str,str_array)
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 yesno=0;
0679 n_str=length(str_array);
0680
0681 for a=1:n_str,
0682 if strcmpi(str,str_array{a})
0683 yesno=1;
0684 break;
0685 end
0686 end
0687
0688 function dif_str=setdiff_ci(superset,subset)
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700 n_super=length(superset);
0701 n_sub=length(subset);
0702 dif_ct=0;
0703 dif_str=[];
0704 for a=1:n_super,
0705 found=0;
0706 for b=1:n_sub,
0707 if strcmpi(superset{a},subset{b}),
0708 found=1;
0709 break
0710 end
0711 end
0712 if ~found,
0713 dif_ct=dif_ct+1;
0714 dif_str{dif_ct}=superset{a};
0715 end
0716 end