crw2set() - Create and save to disk an EEGLAB set file from a Kutaslab crw, log, and associated files. EEGLAB must be started before running this function. Usage: >> crw2set(crwfile,logfile,blfORbdf_file,setfile,locfile,varargin) Required Inputs: crwfile = name of Kutaslab crw file logfile = name of Kutaslab log file blfORbdf_file = name of Kutaslab blf of bdf file setfile = name of EEGLAB set file that will be created NOTE: All file names should be strings and should include the file's path unless the file is in the current working directory. Optional Inputs: locfile = name of EEGLAB channel locations file. If not provided, crw2set will try to automatically generate electrode coordinates from channel names. cprecis = channel precision. The number of time points extracted for each event is 256*cprecis. (default: 1) decimat = decimation factor (default: 1) presam = length of prestimulus baseline in msec (default: 100) rtfile = cdbl produced reaction time file. If blfORbdf_file is a bdf file, a new rtfile will be generated from that bdf file and this rtfile will be ignored. (default: []) arffile = name of Kutaslab artifact rejection file. If you specify an arffile, any existing artifact flags in logfile will be ignored and arffile will be used to create a new temporary set of log file flags.(default: []) garv_flags = a string that indicates what you want done with EEG epochs flagged as artifact-polluted by an arffile. Options are: 'ignore arf' - Import all epochs (default) 'reject nonblink artifacts' - Do not import epochs polluted by nonblink artifacts 'reject blink artifacts' -Do not import epochs polluted by blink artifacts 'reject all artifacts' - Do not import epochs polluted by any artifacts verblevel = an integer specifiying the amount of information you want this function to provide about what it is doing during runtime. Options are: 0 - quiet, only show errors, warnings, and EEGLAB reports 1 - stuff anyone should probably know 2 - stuff you should know the first time you start working with a data set (default value) 3 - stuff that might help you debug (show all reports) event_infofile = name of a text file or a cell array of text file names containing NUMERIC information about experimental events (e.g., participant accuracy, successful post-experiment recall). The first row of this file should be a header row consisting of names for each column. The name of a column can NOT contain white space (e.g., 'sbjct accuracy' is NOT ok, but 'sbjct_accuracy' would be fine) nor can it contain parenthesis (e.g., 'sbjct(accuracy)' won't work). (default: []) code_infofile = name of a text file or a cell array of text file names containing NUMERIC information about classes of experimental events (e.g., a word's frequency of use, word concreteness, an image's emotional valence). The first row of this file should be a header row consisting of names for each column. The name of a column can NOT contain white space (e.g., 'emotion valence' is NOT ok, but 'emotion_valence' would be fine) nor can it contain parenthesis (e.g., 'emotion(valence)' won't work). (default: []) sbjct_infofile = name of a text file or a cell array of text file names containing NUMERIC information about subjects in the experiment (e.g., age, working memory span). The first row of this file should be a header row consisting of names for each column. The name of a column can NOT contain white space (e.g., 'sbjct age' is NOT ok, but 'sbjct_age' would be fine) nor can it contain parenthesis (e.g., 'sbjct(age)' won't work). Note, this option must be used with the 'sbject_id' option described below. (default: []) sbjct_id = string or number that identifies the subject who produced the data in crwfile. This ID should in appear in the first column of 'sbjct_infofile' (see above). (default: []) exclude_chans = string or cell array specifying the names of any channels that should not be imported to set file (e.g., a horizontal eye montage). (default: []) rm_blocking = 'yes' or 'no'. If 'yes', epochs that show evidence of amplifier blocking (i.e., several consecutive time points with nearly the exact same voltage) will NOT be imported. This is useful if ICA will be used to correct for EEG artifacts, since ICA cannot correct for amplifier blocking. block_plot_opt = [0 | 1] If 1, any epochs believed to exhibit blocking will be plot for visual verification. (default: 1) rm_bsln_mn = two element vector specifiying baseline time window in msec (e.g., [-100 0]). The mean EEG in this baseline window will be removed from each epoch at each channel. reref_bimast = 'yes' or 'no'. If 'yes,' re-references data to mean of both mastoids. Assumes data are recorded using a mastoid reference and that the other mastoid channel is labelled 'A1' or 'A2'. (default: 'no') reref_ignore = string or cell array specifying the names of any channels that should not be re-referenced (e.g., a horizontal eye montage). This argument has no effect if reref_bimast is set to 'no'. (default: []) Calibration Parameter Optional Inputs: cal_npts = number of time points to include in pre and post pulse calibration windows (default: 10) low_cursor = center of pre-pulse baseline window in msec (default: -50) hi_cursor = center of post-pulse baseline window in msec (default: 50) cal_amp = cal pulse amplitude in microvolts (default: 10) cal_polarity = 1 for positive, -1 for negative (default: 1) trm_pcnt = percentage of extreme cal pulses to discard (0 to 99). This protects against outliers. (default: 5) cal_plot_opt = 1 to plot pre and post calibration diagnostics. 0 to suppress these plots. (default: 1) cal_crwfile = an alternative crw file from which to extract cal pulses. If used any cal pulses in crwfile will be ignored. Note, the order of the channels in cal_crwfile need to be exactly the same as those in EEG crwfile. (default: []) cal_logfile = the logfile for cal_crwfile (default: []) cal_blfORbdf_file = the blf or bdf file for cal_crwfile (default: blfORbdf_file) Outputs: The function writes a set file to disk and the EEGLAB global variable EEG is overwritten to store the new data set. Also, some temporary files are written to the current working directory and deleted. Global Variables: VERBLEVEL = matlabMK level of verbosity (i.e., tells functions how much to report about what they're doing during runtime) set by the optional function argument 'verblevel' SUBJECT = temporary struct that stores EEG data and cal pulses and some related info EEG, ALLEEG = EEGLAB global variables Example: >> crwfile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.crw'; >> logfile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.log'; >> blfORbdf_file='/homes/dgroppe/SANDBOX/PRSENT/prsent.bdf'; >> setfile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.set'; >> arffile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.arf'; >> locfile='/homes/dgroppe/SANDBOX/LOCS/mk31.loc'; >> code_infofile='/homes/dgroppe/SANDBOX/PRSENT/tone_durations.txt'; >> sbjct_infofile='/homes/dgroppe/SANDBOX/PRSENT/prsent_sbjctages.txt'; >> crw2set(crwfile,logfile,blfORbdf_file,setfile,'presam',100, ... 'rm_bsln_mn',[-100 0],'reref_bimast','yes','cprecis',1,'code_infofile', ... code_infofile,'sbjct_infofile',sbjct_infofile,'sbjct_id','prsent41', ... 'arffile',arffile); Notes: -Setfile is the only given file that is modified by this function (e.g., blfORbdf_file, logfile, etc... will not be changed). -Currently, the EEGLAB GUI will report the reference from individual channels (taken from EEG.chanlocs). Thus if different channels have different references, the GUI's description won't be accurate. -Function assumes that cal pulses are all assigned to a single bin -Unix program avg is what adds artifact flags to logfile Author: David Groppe (based on code written by Tom Urbach & Ming Lo), Kutaslab, 8/2009
0001 function crw2set(crwfile,logfile,blfORbdf_file,setfile,varargin) 0002 % crw2set() - Create and save to disk an EEGLAB set file from a 0003 % Kutaslab crw, log, and associated files. EEGLAB must 0004 % be started before running this function. 0005 % 0006 % Usage: 0007 % >> crw2set(crwfile,logfile,blfORbdf_file,setfile,locfile,varargin) 0008 % 0009 % Required Inputs: 0010 % crwfile = name of Kutaslab crw file 0011 % logfile = name of Kutaslab log file 0012 % blfORbdf_file = name of Kutaslab blf of bdf file 0013 % setfile = name of EEGLAB set file that will be created 0014 % 0015 % NOTE: All file names should be strings and should include the 0016 % file's path unless the file is in the current working directory. 0017 % 0018 % 0019 % Optional Inputs: 0020 % locfile = name of EEGLAB channel locations file. If not 0021 % provided, crw2set will try to automatically generate 0022 % electrode coordinates from channel names. 0023 % cprecis = channel precision. The number of time points 0024 % extracted for each event is 256*cprecis. (default: 1) 0025 % decimat = decimation factor (default: 1) 0026 % presam = length of prestimulus baseline in msec (default: 100) 0027 % rtfile = cdbl produced reaction time file. If blfORbdf_file is 0028 % a bdf file, a new rtfile will be generated from that 0029 % bdf file and this rtfile will be ignored. (default: []) 0030 % arffile = name of Kutaslab artifact rejection file. If you 0031 % specify an arffile, any existing artifact flags in logfile will 0032 % be ignored and arffile will be used to create a new temporary 0033 % set of log file flags.(default: []) 0034 % garv_flags = a string that indicates what you want done with 0035 % EEG epochs flagged as artifact-polluted by an 0036 % arffile. Options are: 0037 % 'ignore arf' - Import all epochs (default) 0038 % 'reject nonblink artifacts' - Do not import epochs polluted 0039 % by nonblink artifacts 0040 % 'reject blink artifacts' -Do not import epochs 0041 % polluted by blink artifacts 0042 % 'reject all artifacts' - Do not import epochs polluted by 0043 % any artifacts 0044 % 0045 % verblevel = an integer specifiying the amount of information you want 0046 % this function to provide about what it is doing during runtime. 0047 % Options are: 0048 % 0 - quiet, only show errors, warnings, and EEGLAB reports 0049 % 1 - stuff anyone should probably know 0050 % 2 - stuff you should know the first time you start working 0051 % with a data set (default value) 0052 % 3 - stuff that might help you debug (show all reports) 0053 % event_infofile = name of a text file or a cell array of text file names 0054 % containing NUMERIC information about experimental events 0055 % (e.g., participant accuracy, successful 0056 % post-experiment recall). The first row of this file 0057 % should be a header row consisting of names for each 0058 % column. The name of a column can NOT contain white 0059 % space (e.g., 'sbjct accuracy' is NOT ok, but 0060 % 'sbjct_accuracy' would be fine) nor can it contain 0061 % parenthesis (e.g., 'sbjct(accuracy)' won't work). 0062 % (default: []) 0063 % code_infofile = name of a text file or a cell array of text file names 0064 % containing NUMERIC information about classes of 0065 % experimental events (e.g., a word's frequency of use, 0066 % word concreteness, an image's emotional valence). The 0067 % first row of this file should be a header row consisting 0068 % of names for each column. The name of a column can NOT 0069 % contain white space (e.g., 'emotion valence' is NOT ok, 0070 % but 'emotion_valence' would be fine) nor can it contain 0071 % parenthesis (e.g., 'emotion(valence)' won't work). 0072 % (default: []) 0073 % sbjct_infofile = name of a text file or a cell array of text file names 0074 % containing NUMERIC information about subjects 0075 % in the experiment (e.g., age, working memory span). The 0076 % first row of this file should be a header row consisting 0077 % of names for each column. The name of a column can NOT 0078 % contain white space (e.g., 'sbjct age' is NOT ok, but 0079 % 'sbjct_age' would be fine) nor can it contain 0080 % parenthesis (e.g., 'sbjct(age)' won't work). 0081 % Note, this option must be used with the 'sbject_id' 0082 % option described below. (default: []) 0083 % sbjct_id = string or number that identifies the subject who 0084 % produced the data in crwfile. This ID should in 0085 % appear in the first column of 'sbjct_infofile' (see 0086 % above). (default: []) 0087 % exclude_chans = string or cell array specifying the names of any 0088 % channels that should not be imported to set file 0089 % (e.g., a horizontal eye montage). (default: []) 0090 % rm_blocking = 'yes' or 'no'. If 'yes', epochs that show evidence of 0091 % amplifier blocking (i.e., several consecutive time points 0092 % with nearly the exact same voltage) will NOT be imported. 0093 % This is useful if ICA will be used to correct for EEG 0094 % artifacts, since ICA cannot correct for amplifier 0095 % blocking. 0096 % block_plot_opt = [0 | 1] If 1, any epochs believed to exhibit blocking 0097 % will be plot for visual verification. (default: 1) 0098 % rm_bsln_mn = two element vector specifiying baseline time window in 0099 % msec (e.g., [-100 0]). The mean EEG in this baseline 0100 % window will be removed from each epoch at each channel. 0101 % reref_bimast = 'yes' or 'no'. If 'yes,' re-references data to mean of 0102 % both mastoids. Assumes data are recorded using a mastoid 0103 % reference and that the other mastoid channel is labelled 0104 % 'A1' or 'A2'. (default: 'no') 0105 % reref_ignore = string or cell array specifying the names of any 0106 % channels that should not be re-referenced (e.g., a horizontal 0107 % eye montage). This argument has no effect if reref_bimast 0108 % is set to 'no'. (default: []) 0109 % 0110 % Calibration Parameter Optional Inputs: 0111 % cal_npts = number of time points to include in pre and post 0112 % pulse calibration windows (default: 10) 0113 % low_cursor = center of pre-pulse baseline window in msec (default: -50) 0114 % hi_cursor = center of post-pulse baseline window in msec 0115 % (default: 50) 0116 % cal_amp = cal pulse amplitude in microvolts (default: 10) 0117 % cal_polarity = 1 for positive, -1 for negative (default: 1) 0118 % trm_pcnt = percentage of extreme cal pulses to discard (0 to 99). 0119 % This protects against outliers. (default: 5) 0120 % cal_plot_opt = 1 to plot pre and post calibration diagnostics. 0 to 0121 % suppress these plots. (default: 1) 0122 % cal_crwfile = an alternative crw file from which to extract 0123 % cal pulses. If used any cal pulses in crwfile 0124 % will be ignored. Note, the order of the channels 0125 % in cal_crwfile need to be exactly the same as those 0126 % in EEG crwfile. (default: []) 0127 % cal_logfile = the logfile for cal_crwfile (default: []) 0128 % cal_blfORbdf_file = the blf or bdf file for cal_crwfile (default: blfORbdf_file) 0129 % 0130 % 0131 % Outputs: 0132 % The function writes a set file to disk and the EEGLAB global 0133 % variable EEG is overwritten to store the new data set. Also, 0134 % some temporary files are written to the current working 0135 % directory and deleted. 0136 % 0137 % 0138 % Global Variables: 0139 % VERBLEVEL = matlabMK level of verbosity (i.e., tells functions 0140 % how much to report about what they're doing during 0141 % runtime) set by the optional function argument 'verblevel' 0142 % 0143 % SUBJECT = temporary struct that stores EEG data and cal 0144 % pulses and some related info 0145 % 0146 % EEG, ALLEEG = EEGLAB global variables 0147 % 0148 % 0149 % Example: 0150 % >> crwfile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.crw'; 0151 % >> logfile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.log'; 0152 % >> blfORbdf_file='/homes/dgroppe/SANDBOX/PRSENT/prsent.bdf'; 0153 % >> setfile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.set'; 0154 % >> arffile='/homes/dgroppe/SANDBOX/PRSENT/prsent41.arf'; 0155 % >> locfile='/homes/dgroppe/SANDBOX/LOCS/mk31.loc'; 0156 % >> code_infofile='/homes/dgroppe/SANDBOX/PRSENT/tone_durations.txt'; 0157 % >> sbjct_infofile='/homes/dgroppe/SANDBOX/PRSENT/prsent_sbjctages.txt'; 0158 % >> crw2set(crwfile,logfile,blfORbdf_file,setfile,'presam',100, ... 0159 % 'rm_bsln_mn',[-100 0],'reref_bimast','yes','cprecis',1,'code_infofile', ... 0160 % code_infofile,'sbjct_infofile',sbjct_infofile,'sbjct_id','prsent41', ... 0161 % 'arffile',arffile); 0162 % 0163 % 0164 % Notes: 0165 % -Setfile is the only given file that is modified by this function (e.g., 0166 % blfORbdf_file, logfile, etc... will not be changed). 0167 % 0168 % -Currently, the EEGLAB GUI will report the reference from individual channels 0169 % (taken from EEG.chanlocs). Thus if different channels have different references, 0170 % the GUI's description won't be accurate. 0171 % 0172 % -Function assumes that cal pulses are all assigned to a single bin 0173 % 0174 % -Unix program avg is what adds artifact flags to logfile 0175 % 0176 % Author: 0177 % David Groppe (based on code written by Tom Urbach & Ming Lo), 0178 % Kutaslab, 8/2009 0179 % 0180 0181 %%%%%%%%%%%%%%%% FUNCTION OUTLINE %%%%%%%%%%%%%%%%% 0182 % I. IF ALT CAL PULSE CRW FILE SPECIFIED, GET THOSE CAL PULSES FIRST 0183 % II. OPEN CRW FILE USING ERPIO() & GET EXP INFO AND RECORDING PARAMETERS 0184 % III. IMPORT BLF FILE INFORMATION 0185 % IV. IF ARF FILE SPECIFIED, FLAG ARTIFACTS IN LOG FILE 0186 % V. IMPORT LOG INFO FROM ASCII VERSION OF LOGFILE 0187 % VI. COMBINE LOG & BIN INFORMATION 0188 % VII. LOAD INFORMATION ABOUT CLASSES OF EVENTS FROM TEXT FILE(S) [OPTIONAL] 0189 % VIII. LOAD INFORMATION ABOUT PARTICIPANT FROM TEXT FILE(S) [OPTIONAL] 0190 % IX. LOAD INFORMATION ABOUT LOG EVENTS FROM TEXT FILE(S) [OPTIONAL] 0191 % X. IMPORT CDBL PRODUCED REACTION TIME INFORMATION [OPTIONAL] 0192 % XI. IMPORT EEG AND CALIBRATION PULSES 0193 % XII. NORMALIZE CAL PULSES AND DATA 0194 % XIII. CREATE EEGLAB SET FILE AND SAVE TO DISK 0195 % XIV. RE-REFERENCE TO BIMASTOID REF [OPTIONAL] 0196 % XV. REMOVE BASELINE MEAN FROM EEG [OPTIONAL] 0197 % XVI. SAVE SET AND CLEANUP 0198 0199 0200 %%%%%%%%%%%%%%%% REVISION LOG %%%%%%%%%%%%%%%%% 0201 % 0202 % 08/11/09 Function no longer requires eeglab GUI -DG 0203 % 0204 % 08/19/09 cal_blfORbdf_file option added -Padmapriya Kandhadai 0205 % 0206 % 08/18/09 (1) RTs loaded as EEG.rmsec and EEG.rtbins fieldnames to permit 0207 % multiple RTs per epoch. (2) If erpio read error, reports if event was a 0208 % cal pulse or not. (3) Reports the number of trials found per bin, the 0209 % number of artifact flagged trials/bin, and the number of loaded trials/bin. -DG 0210 % 0211 % 08/21/09 (1) EEG calibration made more memory efficient, (2) Code tidied 0212 % (3) locfile channel labels checked against crw channel labels/number of chans -DG 0213 % 0214 % 09/02/09 Sampling rate now read from crw file instead of passed as 0215 % function argument -DG 0216 % 0217 % 09/04/09 Added rm_chans option. -DG 0218 % 0219 % 09/15/09 Extended rm_chans option to optional cal pulse crw/log file. 0220 % There is also a check to make sure that the channel names in the cal 0221 % pulse crw file match those of the EEG crw file. Channels names need to 0222 % be in the exact same order for both files. -DG 0223 % 0224 % 10/06/09 Added sbjct_infofile and sbjct_id options. -DG 0225 % 0226 % 11/19/09 Added call to import_cal_erps so that cal pulse ERPs will be 0227 % stored with EEGLAB data set 0228 % 0229 % 11/23/09 Consolidated all cal pulse information into a single field in 0230 % the EEGLAB set file. I also added the field cond_desc, which contains 0231 % string descriptors of each condition code (save for zero, which is 0232 % assumed to be calibration pulses) 0233 % 0234 % 12/14/09 Modified Section IV so that arf flags are still loaded even if 0235 % they are not used to reject polluted trials. 0236 % 0237 % 12/22/09 "rm_blocking" option added (modifies section XIII) 0238 % 0239 % 2/5/10 made minor changes to text reports about number of calibration and 0240 % non-calibration pulse epoch imported. Input option 'asciilogfile' 0241 % removed. 0242 % 0243 % 2/10/10 'block_plot_opt' option added. Epochs with blocking now removed 0244 % via pop_rejepoch. 0245 % 0246 % 11/2/10 EEG.binccodes field added to keep track of which condition code 0247 % a bin belongs to 0248 % 0249 % 6/6/11 Renamed 'rm_chans' option to 'exclude_chans'. Now locfile is an 0250 % optional input arugment. If not specified, channel location information 0251 % will be automatically generated. 0252 % 0253 0254 % POSSIBLE FUTURE DEVELOPMENT 0255 % - If need be, the function could be made much more memory efficient. 0256 % Currently, two copies of the EEG data are held in memory. First it is 0257 % loaded into the global variable SUBJECT.DATA.data and calibrated. Then 0258 % it is imported into the global EEGLAB variable EEG. With a bit of work 0259 % you should be able to load the data directly into the EEG variable, 0260 % though this would require filling out the rest of the EEG variable 0261 % ourselves (i.e., we couldn't use pop_importepoch). 0262 % 0263 % - Do people ever use arf files for cal pulses? Right now arf 0264 % files are not considered during calibration 0265 % 0266 % - Add epochdescription field to EEG struct? Right now there's 0267 % just an event description and bin description field 0268 % 0269 % - Add warning if baseline, arffile or cal pulse parameters are beyond epoch time 0270 % limits? 0271 % 0272 % - Make it possible to add strings to epoch information (e.g., the word 0273 % someone gave in reponse to a question) 0274 0275 global VERBLEVEL 0276 global SUBJECT 0277 0278 %EEGLAB global variables: 0279 global EEG 0280 global ALLEEG 0281 0282 %Input Parser 0283 p=inputParser; 0284 %Note: the order of the required arguments needs to match precisely their 0285 %order in the function definition (which is also the order used by p.parse 0286 %below) 0287 p.addRequired('crwfile',@ischar); 0288 p.addRequired('logfile',@ischar); 0289 p.addRequired('blfORbdf_file',@ischar); 0290 p.addRequired('setfile',@ischar); 0291 p.addParamValue('locfile',[],@ischar); 0292 p.addParamValue('presam',100,@(x) x>0); 0293 p.addParamValue('arffile',[],@ischar); 0294 p.addParamValue('cprecis',1,@(x) x>0 & mod(x,1)==0); 0295 p.addParamValue('decimat',1,@(x) x>0 & mod(x,1)==0); 0296 p.addParamValue('verblevel',2,@(x) x>=0); 0297 p.addParamValue('rtfile',[],@ischar); 0298 p.addParamValue('event_infofile',[],@(x) ischar(x) | iscell(x)); 0299 p.addParamValue('code_infofile',[],@(x) ischar(x) | iscell(x)); 0300 p.addParamValue('sbjct_infofile',[],@(x) ischar(x) | iscell(x)); 0301 p.addParamValue('sbjct_id',[],@(x) ischar(x) | isnumeric(x)); 0302 p.addParamValue('cal_plot_opt',1,@(x) x==0 | x==1); %plot cal pulses 0303 p.addParamValue('cal_npts',10,@(x) x>0 & mod(x,1)==0); %number of time 0304 p.addParamValue('block_plot_opt',1,@(x) x==0 | x==1); %plot sweeps with amplifier blocking 0305 %points to include in cal window 0306 p.addParamValue('low_cursor',-50,@(x) x<0); %center of pre-pulse 0307 %baseline window (in msec) 0308 p.addParamValue('hi_cursor',50,@(x) x>0); %center of post-pulse 0309 %baseline window (in msec) 0310 p.addParamValue('cal_amp',10,@isnumeric); %cal pulse amplitude 0311 %(in microvolts) 0312 p.addParamValue('cal_polarity',1,@(x) x==1 | x==-1); %cal pulse polarity 0313 p.addParamValue('trm_pcnt',5,@(x) x>=0 & x<100); 0314 p.addParamValue('garv_flags','ignore arf',@(x) iscell(x) | ischar(x)); 0315 p.addParamValue('reref_bimast','no',@(x) strcmpi('yes',x) | strcmpi('no',x) ); 0316 p.addParamValue('rm_blocking','no',@(x) strcmpi('yes',x) | strcmpi('no',x) ); 0317 p.addParamValue('reref_ignore',[],@(x) ischar(x) | iscell(x)); 0318 p.addParamValue('exclude_chans',[],@(x) ischar(x) | iscell(x)); 0319 %remove mean EEG in given time window (in msec) from each epoch 0320 p.addParamValue('rm_bsln_mn',[],@(x) isnumeric(x) & (length(x)==2)); 0321 p.addParamValue('cal_crwfile',[],@ischar); 0322 p.addParamValue('cal_logfile',[],@ischar); 0323 p.addParamValue('cal_blfORbdf_file',[],@ischar); 0324 0325 p.parse(crwfile,logfile,blfORbdf_file,setfile,varargin{:}); 0326 0327 VERBLEVEL=p.Results.verblevel; 0328 0329 %Show settings of all arguments 0330 if VERBLEVEL>0 0331 fprintf('crw2set argument values:\n'); 0332 disp(p.Results); 0333 end 0334 0335 if iscell(p.Results.garv_flags) 0336 garv_flags=p.Results.garv_flags{1}; 0337 for a=2:length(p.Results.garv_flags), 0338 garv_flags=[garv_flags ' ' p.Results.garv_flags{a}]; 0339 end 0340 else 0341 garv_flags=p.Results.garv_flags; 0342 end 0343 %?? fix one day so that eval.m can call crw2set? 0344 %if ~strcmpi('ignore arf',garv_flag) && ... 0345 % ~strcmpi('reject nonblink artifacts') && ... 0346 % ~strcmpi('reject blink artifacts') && ... 0347 % ~strcmpi('reject all artifacts'), 0348 % error('%s is not a valid value for argument "garv_flag",garv_flag); 0349 %end 0350 0351 0352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0353 % O. MANAGE CHANNEL LOCATION INFORMATION 0354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0355 0356 %convert p.Results.exclude_chans to a cell array if it is not already 0357 if isempty(p.Results.exclude_chans), 0358 exclude_chans=[]; 0359 elseif iscell(p.Results.exclude_chans), 0360 exclude_chans=p.Results.exclude_chans; 0361 else 0362 exclude_chans{1}=p.Results.exclude_chans; 0363 end 0364 if isempty(p.Results.locfile) 0365 %The values of the following parameters shouldn't make a difference. 0366 %They are just needed to make it possible to open the crw file so that the 0367 %channel labels can be imported. 0368 use_chanlocs=chanlocs_from_crw(crwfile,logfile,p.Results.presam, ... 0369 p.Results.cprecis,p.Results.decimat,exclude_chans,[]); 0370 else 0371 use_chanlocs=p.Results.locfile; 0372 end 0373 0374 0375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0376 % I. IF ALT CAL PULSE CRW FILE SPECIFIED, GET THOSE CAL PULSES FIRST 0377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0378 alt_cal_files=0; 0379 if ~isempty(p.Results.cal_crwfile) && ~isempty(p.Results.cal_logfile) 0380 if isempty(p.Results.cal_blfORbdf_file), %default is to use same blf/bdf file for EEG and cal crw files 0381 cal_blfORbdf_file=p.Results.blfORbdf_file; %unfortunately you can't write to p.Results 0382 else 0383 cal_blfORbdf_file=p.Results.cal_blfORbdf_file; 0384 end 0385 VerbReport(['Getting cal pulses and EEG from separate crw' ... 0386 ' files.'],2,VERBLEVEL); 0387 VerbReport(sprintf('Getting cal pulses first from %s, %s, and %s.', ... 0388 p.Results.cal_crwfile,p.Results.cal_logfile,cal_blfORbdf_file),2,VERBLEVEL); 0389 [pulseamps,cal_itemnum,firstpulse,lastpulse,runningsum,tme,prewind,postwind,cal_chanlabels]= ... 0390 import_cals(p.Results,cal_blfORbdf_file,exclude_chans); 0391 alt_cal_files=1; 0392 calcnt=length(cal_itemnum); 0393 elseif ~isempty(p.Results.cal_crwfile) || ~isempty(p.Results.cal_logfile) 0394 error(['You need to specify a cal_crwfile AND a cal_logfile to get' ... 0395 ' cal pulses and EEG from separate crw files.']); 0396 end 0397 0398 0399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0400 % II. OPEN CRW FILE USING ERPIO() & GET EXP INFO AND RECORDING PARAMETERS 0401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0402 fid_crw=erpio('openraw',crwfile,logfile,p.Results.presam,p.Results.cprecis,p.Results.decimat); 0403 if (erpio('get_errno') == 0), 0404 VerbReport(sprintf('Opening crw file %s went OK', crwfile), 3, VERBLEVEL); 0405 else 0406 error(erpio('get_errstr')); 0407 end; 0408 0409 % Get experiment info and recording parameters 0410 VerbReport('Getting header information', 3, VERBLEVEL); 0411 SUBJECT.PARAMS.expdesc = erpio('get_hdrvar', fid_crw, 'expdesc', 0); 0412 SUBJECT.PARAMS.subdesc = erpio('get_hdrvar', fid_crw, 'subdesc', 0); 0413 srate=100000/erpio('get_hdrvar',fid_crw,'clktick','junk'); 0414 nchans = erpio('get_hdrvar', fid_crw, 'chans',0); 0415 crw_chanlabels=cell(1,nchans); 0416 for a=1:nchans, 0417 crw_chanlabels{a}=erpio('get_hdrvar',fid_crw,'chndesc',a-1); 0418 % "a-1" because indexing starts at 0 0419 end 0420 tpts = 256*p.Results.cprecis; 0421 0422 % Figure out which channels to use 0423 use_chans=1:nchans; 0424 use_crw_chanlabels=cell(1,1); 0425 use_chan_ct=0; 0426 if ~isempty(exclude_chans), 0427 for a=1:nchans, 0428 for b=1:length(exclude_chans), 0429 if strcmpi(crw_chanlabels{a},exclude_chans{b}), 0430 use_chans(a)=-1; 0431 break; %break b loop 0432 end 0433 end 0434 if use_chans(a)>0 0435 use_chan_ct=use_chan_ct+1; 0436 use_crw_chanlabels{use_chan_ct}=crw_chanlabels{a}; 0437 end 0438 end 0439 use_chans=use_chans(find(use_chans>0)); 0440 else 0441 use_crw_chanlabels=crw_chanlabels; 0442 end 0443 nchans=length(use_chans); 0444 0445 %if cal pulses were taken from another crw file, make sure channel names 0446 %match 0447 if exist('cal_chanlabels','var'), 0448 nchans_cal=length(cal_chanlabels); 0449 if nchans~=nchans_cal, 0450 error('Calibration pulse crw file and EEG crw file have different numbers of channels.'); 0451 else 0452 %Note, I assume that channels are listed in the same order in both 0453 %cal and EEG crw files 0454 for a=1:nchans, 0455 if ~strcmpi(use_crw_chanlabels{a},cal_chanlabels{a}), 0456 error('Channel #%d (%s) in cal pulse crw file does not match channel #%d (%s) in EEG crw file.', ... 0457 a,use_crw_chanlabels{a},a,cal_chanlabels{a}); 0458 end 0459 end 0460 end 0461 end 0462 0463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0464 % III. IMPORT BLF FILE INFORMATION 0465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0466 [blf_info, bin_LongDesc, blffile, blf_evnum, rtfile, cal_bin, cond_LongDesc, bin_CondCode]=import_blf(blfORbdf_file, ... 0467 logfile,srate,p.Results.rtfile); 0468 num_bins=size(blf_info,2); 0469 0470 0471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0472 % IV. IF ARF FILE SPECIFIED, FLAG ARTIFACTS IN LOG FILE 0473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0474 logfile=p.Results.logfile; %use user specified logfile by default 0475 if ~isempty(p.Results.arffile) 0476 logfile=flag_art(logfile,p.Results.arffile,crwfile,blffile,p.Results.presam,p.Results.cprecis); 0477 end 0478 0479 0480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0481 % V. IMPORT LOG INFO FROM ASCII VERSION OF LOGFILE 0482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0483 VerbReport(' ',1,VERBLEVEL); 0484 % If ascii version of logfile not specified or if new log file created with artifact flags, 0485 % create temporary ascii file 0486 0487 VerbReport(sprintf('Creating temporary ascii version of logfile %s',logfile),1,VERBLEVEL); 0488 %remove temp.asci if it exists 0489 asci_cmnd='rm -f temp.asci'; 0490 unix(asci_cmnd); 0491 asci_cmnd=sprintf('log2asci %s temp.asci -d %d',logfile,srate); 0492 [s, w]=unix(asci_cmnd); 0493 if s~=0, 0494 disp('Could not create ascii version of logfile using log2asci.'); 0495 error('According to log2asci: %s',w); 0496 end 0497 asciilogfile='temp.asci'; 0498 tempascii=1; 0499 VerbReport(sprintf('Getting log information from %s', asciilogfile), 1, VERBLEVEL); 0500 0501 %import log information for events caught by blf file 0502 ep_info=import_log(asciilogfile,blf_evnum); 0503 0504 %If a temp ascii version of logfile was created, delete it 0505 if tempascii, 0506 VerbReport(sprintf('Removing temporary ascii version of logfile.'),1,VERBLEVEL); 0507 asci_cmnd='rm -f temp.asci'; 0508 [s, w]=unix(asci_cmnd); 0509 if s~=0, 0510 disp('Could not remove ascii version of logfile: temp.asci.'); 0511 error('According to rm: %s',w); 0512 end 0513 end 0514 0515 % Build epoch information descriptions for later ... 0516 log_LongDesc = {'Log Item Number', 'Event Code', 'Condition Code', 'Log Flag (40=nonblink art; 60=blink art)','TIME'}; 0517 0518 0519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0520 % VI. COMBINE LOG & BIN INFORMATION 0521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0522 VerbReport(sprintf('Combining Log and Bin Information.'), 3, VERBLEVEL); 0523 EventTableColNames = {'logitmnum', 'evcode', 'ccode','logflag', 'logtime'}; 0524 %name_ct=length(EventTableColNames); 0525 0526 if ~isempty(cal_bin), %remove cal pulse bin 0527 blf_info=blf_info(:,setdiff(1:size(blf_info,2),cal_bin+1)); %typically cal bin will be 0 0528 else 0529 BinColNames=cell(1,num_bins); 0530 end 0531 0532 loop_ct=0; 0533 for b=0:num_bins-1, 0534 if b~=cal_bin, 0535 loop_ct=loop_ct+1; 0536 %BinColNames{length(BinColNames)+1} = sprintf('bin%d',b); 0537 BinColNames{loop_ct} = sprintf('bin%d',b); 0538 end 0539 end 0540 0541 % Number of events included in blf file 0542 nep = size(ep_info,1); 0543 0544 0545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0546 % VII. LOAD INFORMATION ABOUT CLASSES OF EVENTS FROM TEXT FILE(S) [OPTIONAL] 0547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0548 if ~isempty(p.Results.code_infofile) 0549 VerbReport(' ',1, VERBLEVEL); 0550 if iscell(p.Results.code_infofile) 0551 n_file=length(p.Results.code_infofile); 0552 for dd=1:n_file, %code_infofile is cell array of text file names 0553 [new_info, info_names]=add_code_info(p.Results.code_infofile{dd},ep_info(:,2)); %second column of 0554 %ep_info is stim/response codes 0555 ep_info=[ep_info new_info]; 0556 for dg=1:length(info_names), 0557 EventTableColNames{length(EventTableColNames)+1}= ... 0558 info_names{dg}; 0559 log_LongDesc{length(log_LongDesc)+1}=info_names{dg}; 0560 end 0561 end 0562 else %presumably code_infofile is just a string name of a text file 0563 [new_info, info_names]=add_code_info(p.Results.code_infofile,ep_info(:,2)); %second column of 0564 %ep_info is stim/response codes 0565 ep_info=[ep_info new_info]; 0566 for dg=1:length(info_names), 0567 EventTableColNames{length(EventTableColNames)+1}= ... 0568 info_names{dg}; 0569 log_LongDesc{length(log_LongDesc)+1}=info_names{dg}; 0570 end 0571 end 0572 end 0573 clear n_file new_info info_names 0574 0575 0576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0577 % VIII. LOAD INFORMATION ABOUT PARTICIPANT FROM TEXT FILE(S) [OPTIONAL] 0578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0579 if ~isempty(p.Results.sbjct_infofile) 0580 if isempty(p.Results.sbjct_id) 0581 error('To use the option ''sbjct_infofile'' you also have to specify the ID of the subject via the option ''sbjct_id''.'); 0582 end 0583 if isnumeric(p.Results.sbjct_id), 0584 sbjct_id=num2str(p.Results.sbjct_id); 0585 else 0586 sbjct_id=p.Results.sbjct_id; 0587 end 0588 VerbReport(' ',1, VERBLEVEL); 0589 n_ep=size(ep_info,1); 0590 if iscell(p.Results.sbjct_infofile) 0591 n_file=length(p.Results.sbjct_infofile); 0592 for dd=1:n_file, %sbjct_infofile is cell array of text file names 0593 [new_info, info_names]=add_sbjct_info(p.Results.sbjct_infofile{dd},sbjct_id); 0594 new_info=repmat(new_info,n_ep,1); 0595 ep_info=[ep_info new_info]; 0596 for dg=1:length(info_names), 0597 EventTableColNames{length(EventTableColNames)+1}= ... 0598 info_names{dg}; 0599 log_LongDesc{length(log_LongDesc)+1}=info_names{dg}; 0600 end 0601 end 0602 else %presumably sbjct_infofile is just a string name of a text file 0603 [new_info, info_names]=add_sbjct_info(p.Results.sbjct_infofile,sbjct_id); 0604 new_info=repmat(new_info,n_ep,1); 0605 ep_info=[ep_info new_info]; 0606 for dg=1:length(info_names), 0607 EventTableColNames{length(EventTableColNames)+1}= ... 0608 info_names{dg}; 0609 log_LongDesc{length(log_LongDesc)+1}=info_names{dg}; 0610 end 0611 end 0612 end 0613 clear n_file new_info info_names n_ep 0614 0615 0616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0617 % IX. LOAD INFORMATION ABOUT LOG EVENTS FROM TEXT FILE(S) [OPTIONAL] 0618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0619 if ~isempty(p.Results.event_infofile) 0620 VerbReport(' ',1, VERBLEVEL); 0621 if iscell(p.Results.event_infofile) 0622 n_file=length(p.Results.event_infofile); 0623 for dd=1:n_file, %event_infofile is cell array of text file names 0624 [new_info, info_names]=add_ev_info(p.Results.event_infofile{dd},blf_evnum); %blf_evnum is log item numbers 0625 ep_info=[ep_info new_info]; 0626 for dg=1:length(info_names), 0627 EventTableColNames{length(EventTableColNames)+1}= ... 0628 info_names{dg}; 0629 log_LongDesc{length(log_LongDesc)+1}=info_names{dg}; 0630 end 0631 end 0632 else %presumably event_infofile is just a string name of a text file 0633 [new_info, info_names]=add_ev_info(p.Results.event_infofile, ... 0634 blf_evnum); %blf_evnum is log item numbers 0635 ep_info=[ep_info new_info]; 0636 for dg=1:length(info_names), 0637 EventTableColNames{length(EventTableColNames)+1}= ... 0638 info_names{dg}; 0639 log_LongDesc{length(log_LongDesc)+1}=info_names{dg}; 0640 end 0641 end 0642 end 0643 clear n_file new_info info_names 0644 0645 0646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0647 % X. IMPORT CDBL PRODUCED REACTION TIME INFORMATION [OPTIONAL] 0648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0649 %Grab RTs from specified rtfile or from temporarily generated rtfile 0650 rtvector=[]; %marker for whether or not RTs will be imported to EEG.event 0651 rtmsec=[]; %marker for whether or not RTs will be imported to EEG.rtmsec & EEG.rtbins 0652 if ~isempty(rtfile), 0653 non_calpulse_eps=find(ep_info(:,3)>0); 0654 [rtmsec, rtbins, rtvector]=import_rts(rtfile,blf_evnum(non_calpulse_eps)); 0655 if ~isempty(rtvector) 0656 %add RTs to other epoch info 0657 ep_info=[ep_info zeros(size(ep_info,1),1)]; 0658 ep_info(non_calpulse_eps,end)=rtvector; 0659 0660 EventTableColNames{length(EventTableColNames)+1} = 'rtmsec'; 0661 rt_LongDesc = {'Reaction Time in Milliseconds'}; 0662 end 0663 end 0664 0665 0666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0667 % XI. IMPORT EEG AND CALIBRATION PULSES 0668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0669 VerbReport(sprintf('\nGetting epochs from %s', crwfile), 1, VERBLEVEL); 0670 % Initialize data and info arrays w/ max possible epochs, though 0671 % there may be fewer epochs due to artifact rejection or data read failures 0672 nom_data_size = sum(ep_info(:,3)>0); 0673 if ~alt_cal_files, 0674 nom_cal_size = sum(ep_info(:,3)==0); %Assumes calibration condition code is 0 0675 VerbReport('Assuming Condition Code 0=calibration pulses.',1,VERBLEVEL); 0676 VerbReport(sprintf('%d total calibration pulses (according to log & blf file)',nom_cal_size), ... 0677 1, VERBLEVEL); 0678 %Initialize pulse variables 0679 runningsum=zeros(nchans,tpts); 0680 pulseamps=zeros(nchans,nom_cal_size); 0681 cal_itemnum=zeros(1,nom_cal_size); 0682 calcnt=0; %count number of pulses actually loaded 0683 0684 % Find pre and post pulse time windows for measuring pulse amplitude 0685 %peristimulus time of each time point in milliseconds 0686 tme=1000*((1:256*p.Results.cprecis)-1)/srate; 0687 tme=tme-p.Results.presam; 0688 [dummy, low_cntr_samp]=min(abs(p.Results.low_cursor-tme)); 0689 [dummy, hi_cntr_samp]=min(abs(p.Results.hi_cursor-tme)); 0690 0691 %Pre-Pulse time window (in samples) 0692 lo_start_samp = low_cntr_samp-floor(p.Results.cal_npts/2); 0693 lo_stop_samp = low_cntr_samp+floor(p.Results.cal_npts/2); 0694 prewind=[tme(lo_start_samp) tme(lo_stop_samp)]; 0695 0696 %Post-Pulse time window (in samples) 0697 hi_start_samp = hi_cntr_samp-floor(p.Results.cal_npts/2); 0698 hi_stop_samp = hi_cntr_samp+floor(p.Results.cal_npts/2); 0699 postwind=[tme(hi_start_samp) tme(hi_stop_samp)]; 0700 end 0701 0702 %Pre-allocate memory for EEG 0703 VerbReport(sprintf('%d total NON-calibration pulse epochs (according to log & blf file)',nom_data_size), 1, VERBLEVEL); 0704 SUBJECT.DATA.data=zeros(nchans,tpts,nom_data_size); 0705 use_ep=zeros(1,nom_data_size); 0706 datacnt = 0; %count number of EEG trials actually loaded 0707 0708 %Figure out how to deal with artifact flags from arf file 0709 if strcmpi(garv_flags,'ignore arf'), 0710 flg_opt=0; 0711 VerbReport('Importing all epochs regardless of arf file flags.',1,VERBLEVEL); 0712 elseif strcmpi(garv_flags,'reject nonblink artifacts'), 0713 flg_opt=1; 0714 VerbReport('Importing all epochs save for those flagged as nonblink artifacts by arf file.',1,VERBLEVEL); 0715 elseif strcmpi(garv_flags,'reject blink artifacts'), 0716 flg_opt=2; 0717 VerbReport('Importing all epochs save for those flagged as blink artifacts by arf file.',1,VERBLEVEL); 0718 elseif strcmpi(garv_flags,'reject all artifacts'), 0719 flg_opt=3; 0720 VerbReport('Importing all epochs save for those flagged as artifacts (both blinks and nonblinks) by arf file.',1,VERBLEVEL); 0721 else 0722 error('Argument "garv_flags" is set to %s.\nThis is invalid.',p.Results.garv_flags); 0723 end 0724 0725 bin_ct=zeros(length(bin_LongDesc),3); 0726 %1st col=total # of trials 0727 %2nd col=# of artifact flagged trials 0728 %3rd col=# of loaded trials (this will equal the first col if artifact flags are ignored) 0729 0730 for i=1:nep, %loop through all blf events (including cal pulses) 0731 % ATTEMPT TO NAB EPOCH ... ERPIO RETURNS EMPTY ARRAY IF IT DOESN'T WORK 0732 currdat = erpio('evread', fid_crw, ep_info(i, 1)); 0733 0734 % If data didn't load, show a warning and continue 0735 if isempty(currdat) 0736 if (ep_info(i,3)==0) 0737 msg=sprintf(['erpio: Can not read data at log item %d.\n' ... 0738 'Log item should be a calibration pulse.'],ep_info(i,1)); 0739 else 0740 msg=sprintf(['erpio: Can not read data at log item %d.\n' ... 0741 'Log item should be an experimental event.'],ep_info(i,1)); 0742 end 0743 watchit(msg); 0744 else 0745 %get rid of data from channels that are to be ignored 0746 currdat=currdat(use_chans,:); 0747 0748 % BRANCH ON CONDITION CODE FOR CALS V. EXPERIMENTAL EVENTS 0749 if (ep_info(i,3)==0) 0750 if ~alt_cal_files, 0751 calcnt = calcnt+1; 0752 %record logitem number of pulse 0753 cal_itemnum(calcnt)=ep_info(i,1); 0754 0755 lastpulse=currdat; 0756 %remove pre-pulse baseline 0757 lastpulse=rmbase(lastpulse,tpts,lo_start_samp:lo_stop_samp); 0758 if calcnt==1, 0759 firstpulse=lastpulse; 0760 end 0761 runningsum=runningsum+lastpulse; 0762 %get pulse amp 0763 pulseamps(:,calcnt)=mean(lastpulse(:,hi_start_samp:hi_stop_samp),2); 0764 VerbReport(sprintf('Loading cal %d/%d event (blf event %d/%d)', ... 0765 calcnt,nom_cal_size,i,nep),3,VERBLEVEL); 0766 end 0767 elseif (ep_info(i,3)>0) 0768 % BRANCH ON DROP OPTION HERE ... THESE ARE THE CONDITIONS SUFFICIENT FOR 0769 % ADDING THE DATA TO THE ARRAY ... 0770 % 'none' -> flg_opt = 0; 0771 % 'nonblinks' -> flg_opt = 1; 0772 % 'blinks' -> flg_opt = 2; 0773 % 'all' -> flg_opt = 3; 0774 % 0775 % FLAG 32/40 == REGULAR ARTIFACT, FLAG 48/60 = BLINK DEPENDING 0776 % WHERE THE ASCII VERSION CAME FROM LOGCAT2/LOG2ASCI 0777 0778 % Convert logcat2 flags to log2asci flags 0779 if ep_info(i,4)==48 0780 ep_info(i,4)=60; 0781 elseif ep_info(i,4)==32 0782 ep_info(i,4)=40; 0783 end 0784 0785 in_bins=find(blf_info(i,:)==1); 0786 bin_ct(in_bins,1)=bin_ct(in_bins,1)+1; 0787 0788 if ( (flg_opt == 0) || ... 0789 (flg_opt == 1 && ep_info(i,4) ~= 40) || ... 0790 (flg_opt == 2 && ep_info(i,4) ~= 60) || ... 0791 (flg_opt == 3 && ep_info(i,4) ~= 40 && ep_info(i,4) ~= 60)) 0792 datacnt = datacnt+1; 0793 SUBJECT.DATA.data(:,:,datacnt) = currdat; 0794 use_ep(datacnt)=i; %keep track of which rows of ep_info we need 0795 VerbReport(sprintf('Loading data %d/%d event (blf event %d/%d)', ... 0796 datacnt, nom_data_size, i, nep),3,VERBLEVEL); 0797 bin_ct(in_bins,3)=bin_ct(in_bins,3)+1; 0798 else 0799 bin_ct(in_bins,2)=bin_ct(in_bins,2)+1; 0800 end 0801 else 0802 error('Unexplained negative condition code at log item %d.',i); 0803 end 0804 end 0805 end 0806 erpio('close', fid_crw) 0807 0808 % Trim end of preallocated array to size of sucessful data reads 0809 SUBJECT.DATA.data = SUBJECT.DATA.data(:,:,1:datacnt); 0810 %Cull rows of ep_info corresponding to cal pulses and epochs of data 0811 %that were not used due to artifact flags or erpio errors 0812 %NOTE: matrix transposition 0813 ep_info = ep_info(use_ep(1:datacnt),:)'; 0814 %do same thing for RTs 0815 if ~isempty(rtmsec), 0816 rtmsecUSED=cell(1,length(rtmsec)); 0817 rtbinsUSED=cell(1,length(rtbins)); 0818 for rtloop=1:datacnt, 0819 rtmsecUSED{rtloop}=rtmsec{use_ep(rtloop)}; 0820 rtbinsUSED{rtloop}=rtbins{use_ep(rtloop)}; 0821 end 0822 else 0823 rtmsecUSED=[]; %to indicate RTs have not been loaded 0824 end 0825 clear rtmsec rtbins 0826 0827 % Trim end of preallocated array to size of sucessful pulse reads 0828 if ~alt_cal_files, 0829 pulseamps=pulseamps(:,1:calcnt); 0830 cal_itemnum=cal_itemnum(1:calcnt); 0831 %turn sum into mean 0832 runningsum=runningsum/calcnt; 0833 end 0834 0835 %Report # of trials in each bin 0836 if VERBLEVEL>1, 0837 fprintf('# of cal pulses actually loaded: %d\n',calcnt); 0838 fprintf('BIN\t\tTOTAL TRIALS\tARTIFACT TRIALS\t\tLOADED TRIALS\n'); 0839 for binloop=1:size(bin_ct,1), 0840 if binloop<10 0841 fprintf('Bin %d: \t\t%d\t\t%d\t\t\t%d\n',binloop,bin_ct(binloop,1), ... 0842 bin_ct(binloop,2), bin_ct(binloop,3)); 0843 elseif binloop<100 0844 fprintf('Bin %d: \t\t%d\t\t%d\t\t\t%d\n',binloop,bin_ct(binloop,1), ... 0845 bin_ct(binloop,2), bin_ct(binloop,3)); 0846 else 0847 fprintf('Bin %d:\t\t%d\t\t%d\t\t\t%d\n',binloop,bin_ct(binloop,1), ... 0848 bin_ct(binloop,2), bin_ct(binloop,3)); 0849 end 0850 end 0851 end 0852 0853 %Consolidate descriptions of ep_info rows (formally columns); 0854 if ~isempty(rtvector) 0855 LongDesc = [log_LongDesc rt_LongDesc]; 0856 else 0857 LongDesc = log_LongDesc; 0858 end 0859 0860 % Use this to look up ep_info row (formally columns) decriptors 0861 % after EEGLAB sorts them alphabetically 0862 LongDescHash = [EventTableColNames', LongDesc']; 0863 0864 VerbReport('', 1, VERBLEVEL); 0865 VerbReport('Done loading raw data into Matlab', 3, VERBLEVEL); VerbReport('', 1, VERBLEVEL); 0866 0867 0868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0869 % XII. NORMALIZE CAL PULSES AND DATA 0870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0871 [usedcal_ids, scale_factor]=trm_raw2nrm(firstpulse,lastpulse,pulseamps,runningsum,tme,p.Results,prewind,postwind); 0872 0873 %get the logitem numbers of the cal pulses that were actually used 0874 usedcal_itemnum=zeros(size(usedcal_ids)); 0875 for a=1:nchans, 0876 usedcal_itemnum(a,:)=cal_itemnum(usedcal_ids(a,:)); 0877 end 0878 npulse_psbl=length(cal_itemnum); 0879 npulse_used=length(usedcal_ids); 0880 0881 if ~alt_cal_files, 0882 cal_erps=import_cal_erps(p.Results,crwfile,logfile,blfORbdf_file,exclude_chans,usedcal_itemnum,scale_factor); 0883 else 0884 %Note: earlier code has already checked to make sure that the channels 0885 %and their order are compatible across the data crw and calpulse crw 0886 %files 0887 cal_erps=import_cal_erps(p.Results,p.Results.cal_crwfile,p.Results.cal_logfile, ... 0888 p.Results.cal_blfORbdf_file,exclude_chans,usedcal_itemnum,scale_factor); 0889 end 0890 0891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0892 % XIII. CREATE EEGLAB SET FILE AND SAVE TO DISK 0893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0894 %separate set filename from its path for eeglab 0895 [setfilepath, setfilename]=pathNname(setfile); 0896 EEG = pop_importdata( 'dataformat', 'array', 'data', SUBJECT.DATA.data, ... 0897 'setname', setfilename(1:(length(setfilename)-4)), ... 0898 'srate',srate, ... 0899 'subject', SUBJECT.PARAMS.subdesc, ... 0900 'nbchan', nchans, ... 0901 'comments', SUBJECT.PARAMS.expdesc, ... 0902 'pnts',tpts, ... 0903 'xmin',-(p.Results.presam/1000), ... 0904 'chanlocs', use_chanlocs); 0905 EEG = eeg_checkset( EEG ); 0906 EEG.ref='not specified'; 0907 EEG.rawtrials_per_bin=sum(blf_info); 0908 0909 %Check to make sure locfile channel labels agree with crw channel labels 0910 match=1; 0911 if length(EEG.chanlocs)~=length(use_crw_chanlabels), 0912 match=0; 0913 else 0914 for a=1:length(EEG.chanlocs), 0915 if ~strcmpi(EEG.chanlocs(a).labels,use_crw_chanlabels{a}), 0916 match=0; 0917 end 0918 end 0919 end 0920 if ~match, 0921 if isempty(p.Results.locfile) 0922 error('Automatically generated electrode coordinates do not match %s channel names. Try using ''locfile'' input option.', ... 0923 crwfile); 0924 else 0925 error('EEGLAB locfile %s does not match %s channel names',p.Results.locfile,crwfile); 0926 end 0927 end 0928 0929 %GROPPE NOTE: This first way of importing epochs into EEGLAB creates 0930 %events for each reaction time event. I don't think this is a good 0931 %way of keeping track of RTs because of potential bugs. 0932 %Specifically, I believe an RT will not be tagged to an event if 0933 %it happens after the end of an epoch (e.g., 1.1 seconds postimulus 0934 %and the epoch only goes until .9 seconds poststimulus). Also, I 0935 %belive multiple RTs can be tagged to an event if more than one RT 0936 %occurs within the epoch time window. However, I'm keeping this 0937 %code in so that we can easily revert back to it in case I'm wrong. 0938 % 0939 %if ~isempty(rtvector) 0940 % EEG = pop_importepoch(EEG,ep_info,EventTableColNames, 'latencyfields', {'rtval'}, 'timeunit', 1e-3); 0941 %else 0942 EEG = pop_importepoch(EEG,ep_info,EventTableColNames); 0943 %end 0944 0945 %remove existing EEG.epoch.eventtype field so that we can replace it with 0946 %cell arrays. This enables more than one type (e.g., bin) per epoch. 0947 EEG.epoch=rmfield(EEG.epoch,'eventtype'); 0948 0949 %remove these because we don't use them 0950 EEG.epoch=rmfield(EEG.epoch,'eventduration'); 0951 EEG.event=rmfield(EEG.event,'duration'); 0952 0953 %add new Kutaslab fields 0954 EEG.bindesc=bin_LongDesc; 0955 EEG.binccodes=bin_CondCode; 0956 EEG.condesc=cond_LongDesc; 0957 EEG.crw2set_params=p.Results(1); %store arguments to crw2set with the set file it creates 0958 EEG.cal_info.erps=cal_erps; 0959 EEG.cal_info.usedcal_itemnum=usedcal_itemnum; 0960 EEG.cal_info.npulse_psbl=npulse_psbl; 0961 EEG.cal_info.npulse_used=npulse_used; 0962 0963 %create new EEG.epoch.eventtype with a type for each bin 0964 n_ev=length(EEG.event); 0965 ev_ct=n_ev; 0966 for ep_loop=1:n_ev, 0967 EEG.epoch(ep_loop).eventurevent=EEG.epoch(ep_loop).event; 0968 blf_info_id=find(blf_evnum==EEG.event(ep_loop).logitmnum); 0969 types_ct=1; 0970 types=cell(1,sum(blf_info(blf_info_id,:))); 0971 for bin_col=find(blf_info(blf_info_id,:)), 0972 types{types_ct}=BinColNames{bin_col}; 0973 types_ct=types_ct+1; 0974 ev_ct=ev_ct+1; 0975 EEG.event(ev_ct)=EEG.event(ep_loop); 0976 EEG.event(ev_ct).type=BinColNames{bin_col}; 0977 end 0978 EEG.epoch(ep_loop).eventtype=types; 0979 end 0980 0981 0982 % SINCE EEGLAB ASCII-SORTS EVENT COLUMNS WE HAVE TO LOOKUP THE CORRECT FIELD NAMES ... UGH. 0983 currFields = fieldnames(EEG.event); 0984 n_names=length(EventTableColNames); 0985 % LOAD USER DEFINED DESCRIPTIONS ... NO NEED TO RELOAD OR CHECK FIRST 0986 % FOUR INITIAL EEGLAB DEFAULTS SO START COUNTING WITH 5 0987 % ONE FINAL EEGLAB DEFAULT SO STOP COUNTING 1 EARLY 0988 for f = 4:(length(currFields)-1) 0989 match=0; 0990 for h = 1:n_names, 0991 % fprintf('curr key: %s val: %s target: %s\n', dataset{1}.DATA.LongDescHash{h,1}, dataset{1}.DATA.LongDescHash{h,2}, currFields{f}); 0992 if (strcmp(LongDescHash{h,1}, currFields{f})) 0993 EEG.eventdescription{f} = LongDescHash{h,2}; 0994 match=1; 0995 break; %break out of h loop 0996 end 0997 end 0998 %error check to make currFields element has found a match 0999 if ~match, 1000 error('Can not find long text description for event %s.\n',currFields{f}); 1001 end 1002 end 1003 %Final EEGLAB default urevent (Note this isn't last just due to alphabetical order. It should always be last.) 1004 EEG.eventdescription{f+1} = 'Original .set File Event Index'; 1005 1006 %?? need to sort this alphabetically and there's no urevent 1007 %%EEG.epochdescription=EEG.eventdescription; 1008 1009 %If reaction times have been loaded add them 1010 if ~isempty(rtmsecUSED), 1011 EEG.rtmsec=rtmsecUSED; 1012 EEG.rtbins=rtbinsUSED; 1013 end 1014 1015 % Detect and remove epochs polluted by amplifier blocking (if requested) 1016 if strcmpi(p.Results.rm_blocking,'yes'), 1017 %flag epochs with blocking 1018 [blocked, blk_chans]=mxflat(EEG.data,.12,10); 1019 1020 %plot blocked channels 1021 if p.Results.block_plot_opt, 1022 for a=1:length(blocked), 1023 figure; 1024 plot1erpBW(squeeze(EEG.data(blk_chans(a),:,blocked(a))), ... 1025 [EEG.times(1) EEG.times(end)],EEG.srate); 1026 h=title(sprintf('Trial %d (Channel %s) appears to exhibit amp blocking.\nThis trial will NOT be imported.', ... 1027 blocked(a),EEG.chanlocs(blk_chans(a)).labels)); 1028 set(h,'fontsize',12); 1029 end; 1030 end 1031 VerbReport(sprintf('%d trials appear to exhibit amplifier blocking and will no be imported.', ... 1032 length(unique(blocked))),2,VERBLEVEL); 1033 1034 %remove trials with blocking 1035 EEG=pop_rejepoch(EEG,blocked,0); 1036 if 0, %old code 1037 use_epochs=setdiff(1:EEG.trials,blocked); 1038 EEG.trials=length(use_epochs); 1039 EEG.data=EEG.data(:,:,use_epochs); 1040 EEG.urevent=EEG.urevent(use_epochs); 1041 EEG.epoch=EEG.epoch(use_epochs); 1042 n_block_free=length(use_epochs); 1043 if ~isempty(rtmsecUSED), 1044 % If reaction times have been loaded, remove trials with blocking 1045 orig_rtbins=EEG.rtbins; 1046 orig_rtmsec=EEG.rtmsec; 1047 % Erase existing RT information and overwrite it. There may be a 1048 %faster way to do this. 1049 EEG.rtbins=cell(1,n_block_free); 1050 EEG.rtmsec=cell(1,n_block_free); 1051 for a=1:n_block_free, 1052 EEG.rtbins{a}=orig_rtbins{use_epochs(a)}; 1053 EEG.rtmsec{a}=orig_rtmsec{use_epochs(a)}; 1054 end 1055 end 1056 1057 % There may be a way to speed this process up (e.g., by removing trials 1058 % with blocking before creating the EEG variable) 1059 n_ev=length(EEG.event); 1060 use_ev=zeros(1,n_ev); 1061 for a=1:n_ev, 1062 if ~ismember(EEG.event(a).epoch,blocked), 1063 use_ev(a)=1; 1064 end 1065 end 1066 EEG.event=EEG.event(find(use_ev==1)); 1067 1068 %Note: EEG.rawtrials_per_bin contains counts of the numbers of trials 1069 %in the crw file, regardless of whether or not they are imported. Thus 1070 %this field of EEG does not need to be modified. 1071 end 1072 end 1073 1074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1075 % XIV. RE-REFERENCE TO BIMASTOID REF [OPTIONAL] 1076 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1077 if strcmpi(p.Results.reref_bimast,'yes') 1078 %find mastoid electrode 1079 mastoid_id=[]; 1080 VerbReport(' ',1,VERBLEVEL); 1081 VerbReport('Looking for channel labeled A1 or A2.',2,VERBLEVEL); 1082 for dg=1:length(EEG.chanlocs), 1083 if strcmpi(EEG.chanlocs(dg).labels,'A2') || strcmpi(EEG.chanlocs(dg).labels,'A1') 1084 mastoid_id=dg; 1085 VerbReport(sprintf('Found mastoid electrode: Channel %d, %s', ... 1086 dg,EEG.chanlocs(dg).labels), 1, VERBLEVEL); 1087 break; 1088 end 1089 end 1090 if isempty(mastoid_id) 1091 watchit(sprintf(['Could not find mastoid electrode labeled "A1"' ... 1092 ' or "A2".\nRe-reference aborted. Data were' ... 1093 ' not modified.'])); 1094 else 1095 %find any electrodes that shouldn't be re-referenced (e.g., horizontal 1096 % eye montage) 1097 if isempty(p.Results.reref_ignore) 1098 ignore=[]; 1099 VerbReport(['I assume all electrodes were' ... 1100 ' recorded referenced to the other mastoid.'],1,VERBLEVEL); 1101 else 1102 if ischar(p.Results.reref_ignore) 1103 ignore{1}=p.Results.reref_ignore; 1104 else 1105 ignore=p.Results.reref_ignore; 1106 end 1107 VerbReport(sprintf(['I assume all electrodes were' ... 1108 ' recorded referenced to the other mastoid save for the' ... 1109 ' %d that I was told to ignore (via the "reref_ignore" option).'],length(ignore)),1,VERBLEVEL); 1110 end 1111 reref_bimastoidEEG(mastoid_id,ignore); 1112 end 1113 VerbReport(' ',1,VERBLEVEL); 1114 end 1115 1116 1117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1118 % XV. REMOVE BASELINE MEAN FROM EEG [OPTIONAL] 1119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1120 %p.addParamValue('rm_bsln_mn',[],@(x) isnumeric(x) & (length(x)==2)); 1121 if ~isempty(p.Results.rm_bsln_mn) 1122 strt=p.Results.rm_bsln_mn(1); 1123 stp=p.Results.rm_bsln_mn(2); 1124 if stp<strt, 1125 watchit(sprintf(['Beginning of baseline window, %.0f ms, is' ... 1126 ' later than end of window, %.0f ms.\n' ... 1127 'Not baselining EEG data.'],strt,stp)); 1128 elseif strt>EEG.times(end) 1129 watchit(sprintf(['Problem with baseline window of %.0f ms to %.0f ms.\n', ... 1130 'The beginning of the window is after the end of' ... 1131 ' the epoch, %.0f ms.\nNot baselining EEG data.'], ... 1132 strt,stp,EEG.times(end))); 1133 elseif stp<EEG.times(1) 1134 watchit(sprintf(['Problem with baseline window of %.0f ms to %.0f ms.\n', ... 1135 'The end of the window is before the beginning' ... 1136 ' of the epoch, %.0f ms.\nNot baselining EEG ' ... 1137 'data.'],strt,stp,EEG.times(1))); 1138 else 1139 pt1=find(EEG.times>=strt); 1140 pt1=pt1(1); 1141 pt2=find(EEG.times<=stp); 1142 pt2=pt2(end); 1143 VerbReport(sprintf('Removing baseline mean EEG between %d and %d ms', ... 1144 EEG.times(pt1),EEG.times(pt2)),1,VERBLEVEL); 1145 VerbReport(sprintf('(i.e., between time points %d and %d).', ... 1146 pt1,pt2),1,VERBLEVEL); 1147 sz=size(EEG.data); 1148 EEG.data=rmbase(EEG.data,sz(2),pt1:pt2); 1149 EEG.data=reshape(EEG.data,sz(1),sz(2),sz(3)); 1150 end 1151 end 1152 1153 1154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1155 % XVI. SAVE SET AND CLEANUP 1156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1157 EEG=eeg_checkset(EEG); 1158 [ALLEEG EEG ALLEEGid] = eeg_store(ALLEEG, EEG, 1); 1159 %[ALLEEG EEG ALLEEGid] = eeg_store(ALLEEG, EEG, CURRENTSET); 1160 %[ALLEEG EEG ALLEEGid] = eeg_store(ALLEEG, EEG); %use eeg_store without CURRENTSET 1161 %to keep adding new data sets into memory without deleting already 1162 %loaded sets 1163 1164 EEG = pop_saveset( EEG, 'filename', setfilename, 'filepath', setfilepath); 1165 1166 %call eeg_store one more time to set: 1167 %ALLEEG(ALLEEGid).filename=setfilename; 1168 %ALLEEG(ALLEEGid).filepath=setfilepath; 1169 [ALLEEG EEG] = eeg_store(ALLEEG, EEG, ALLEEGid); 1170 %eeglab redraw; 1171 1172 %CLEAN-UP 1173 clear global SUBJECT 1174 %remove temp mkp files in case they exist 1175 if strcmpi(logfile,'temp.log'), 1176 VerbReport('Removing temporary logfile: temp.log', 2, VERBLEVEL); 1177 unix('rm -f temp.log'); 1178 end 1179 if strcmpi(blffile,'temp.blf'), 1180 VerbReport('Removing temporary files: temp.rt, temp.blf', 2, VERBLEVEL); 1181 unix('rm -f temp.blf'); 1182 unix('rm -f temp.rt'); 1183 end 1184 1185 function plot1erpBW(erp1,times,srate,ylims) 1186 %function plot1erpBW(erp1,times,srate,ylims) 1187 % 1188 % Plots an erp onsame axis using dashed and dotted lines (for 1189 % Times in ms (just beginning and end time points) 1190 1191 hold on; 1192 set(gca,'box','on'); 1193 h=plot([times(1):round(1000/srate):times(2)],erp1,'k'); 1194 set(h,'linewidth',2); 1195 plot(times,[0 0],'k'); 1196 if nargin<4, 1197 v=axis; 1198 ylims=v(3:4); 1199 end 1200 plot([0 0],ylims,'k'); 1201 axis([times ylims]); 1202 %replot ERP so that it is on top of axes 1203 h=plot([times(1):round(1000/srate):times(2)],erp1,'k'); 1204 set(h,'linewidth',2); 1205 [dummy id]=min(abs(ylims)); 1206 mn=ylims(id); 1207 if mn, 1208 %making tick marks this way includes 0 uV 1209 y_step=round(abs(mn/2)); 1210 else 1211 %0 uV is one of the y-axis limits, make about 8 tick marks instead 1212 mx=max(abs(ylims)); 1213 y_step=round(mx/8); 1214 end 1215 set(gca,'ytick',[ylims(1):y_step:ylims(2)],'ydir','reverse'); 1216 1217 h=xlabel('Time (ms)'); 1218 set(h,'fontsize',12); 1219 h=ylabel('\muV'); 1220 set(h,'fontsize',12); 1221 1222 1223 function [blocked, chan]=mxflat(data,max_vertical,max_length) 1224 %function [blocking, chan]=mxflat(data,max_vertical,max_length) 1225 % 1226 %mxflat returns epochs that appear to contain amplifier blocking 1227 % 1228 %Inputs: 1229 %data: a 3-D array of EEG data (channel,time,epoch) 1230 % 1231 %max_vertical: if two consecutive points differ by this value or more, then 1232 %they are assumed not to be part of a segment of amplifier 1233 %blocking. A good value for this is .2 microvolts. 1234 % 1235 %max_length: if more than max_length consecutive points do not 1236 %differ by more than max_verticle from the initial consecutive 1237 %point, the epoch is assumed to contaminated by blocking. A good 1238 %value for this is 10 time points. 1239 % 1240 %Output: 1241 %blocked: a 1-D binary array. A "1" in the nth position of the 1242 %array indicates that the nth epoch contains blocking 1243 % 1244 %chan: a 1-D integer array. Lists the channel in which blocking 1245 %was detected for each epoch specified by "blocked" 1246 % 1247 1248 s=size(data); 1249 if length(s)~=3 1250 disp('Data should be 3 dimensional'); 1251 return 1252 end 1253 1254 nepochs=s(3); 1255 blocking=zeros(1,nepochs); 1256 chan=[]; 1257 blocked=[]; 1258 for a=1:nepochs, %number of epochs 1259 for c=1:s(1) %number of channels 1260 mn=data(c,1,a); 1261 len=1; 1262 for b=2:s(2) %number of points/epoch 1263 %fprintf('%d time %d len\n',b,len); 1264 if (abs(data(c,b,a)-mn)>max_vertical) 1265 len=1; 1266 mn=data(c,b,a); 1267 else 1268 len=len+1; 1269 end 1270 1271 if len>max_length 1272 blocking(a)=1; 1273 chan=[chan c]; 1274 blocked=[blocked a]; 1275 break; 1276 end 1277 end 1278 if blocking(a) 1279 break; 1280 end 1281 end 1282 end