import_cals() - Read the cal pulses from a crw file, construct their average, and return the appropriate scaling parameter for the data. Usage: >> [pulseamps,cal_itemnum,firstpulse,lastpulse,runningsum,tme,prewind,postwind,use_crw_chanlabels]=import_cals(Results,cal_blfORbdf_file,rm_chans) Required Inputs: Results = the input parser "p.Results" variable from crw2set. The fields of Results used in this function are: Results.cal_crwfile Results.cal_logfile Results.presam Results.cprecis Results.decimat cal_blfORbdf_file = bdf or blf file for the crw file from which the calibration pulses will be taken rm_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: []) NOTE: All file names should be strings and should include the file's path unless the file is the current working directory. Outputs: pulseamps = matrix of amplitudes of each cal pulse (in A/D units, NOT in uV) relative to the prepulse baseline. Matrix dimensions are number of channels X number of pulses. Used by trm_raw2nrm.m to normalize EEG. cal_itemnum = vector of logitems for the cal pulses that were actually loaded. Needed later to keep track of which pulses were actually used to norm EEG (i.e., the ones that were loaded and not trimmed). use_crw_chanlabels = cell array of strings indicating the names of the channels whose calibration pulse amplitude was estimated (some channels might not be processed if rm_chans argument is used) Outputs for plotting cal diagnostics via trm_raw2nrm.m: firstpulse = 2D matrix of the first cal pulse at all channels lastpulse = 2D matrix of the last cal pulse at all channels prewind = Beginning and end of pre-pulse baseline window (in msec) used for measuring pulse amplitude postwind = Beginning and end of post-pulse baseline window (in msec) used for measuring pulse amplitude runningsum = 2D matrix of the mean of all pulses tme = vector of peri-stimulus times (in msec) corresponding to each time point of data Notes: -Function assumes that cal pulses are all assigned to a single bin Author: David Groppe (based on code written by Tom Urbach), Kutaslab, 8/2009
0001 function [pulseamps,cal_itemnum,firstpulse,lastpulse,runningsum,tme,prewind,postwind,use_crw_chanlabels]=import_cals(Results,cal_blfORbdf_file,rm_chans) 0002 % import_cals() - Read the cal pulses from a crw file, construct their 0003 % average, and return the appropriate scaling parameter for the data. 0004 % 0005 % Usage: 0006 % >> 0007 % [pulseamps,cal_itemnum,firstpulse,lastpulse,runningsum,tme,prewind,postwind,use_crw_chanlabels]=import_cals(Results,cal_blfORbdf_file,rm_chans) 0008 % 0009 % Required Inputs: 0010 % Results = the input parser "p.Results" variable from crw2set. The fields of Results 0011 % used in this function are: 0012 % Results.cal_crwfile 0013 % Results.cal_logfile 0014 % Results.presam 0015 % Results.cprecis 0016 % Results.decimat 0017 % 0018 % cal_blfORbdf_file = bdf or blf file for the crw file from which the 0019 % calibration pulses will be taken 0020 % 0021 % rm_chans = string or cell array specifying the names of any 0022 % channels that should not be imported to set file 0023 % (e.g., a horizontal eye montage). (default: []) 0024 % 0025 % NOTE: All file names should be strings and should include the 0026 % file's path unless the file is the current working directory. 0027 % 0028 % 0029 % Outputs: 0030 % pulseamps = matrix of amplitudes of each cal pulse (in A/D units, NOT in uV) 0031 % relative to the prepulse baseline. Matrix dimensions are 0032 % number of channels X number of pulses. Used by trm_raw2nrm.m to 0033 % normalize EEG. 0034 % cal_itemnum = vector of logitems for the cal pulses that were actually 0035 % loaded. Needed later to keep track of which pulses were actually used 0036 % to norm EEG (i.e., the ones that were loaded and not trimmed). 0037 % use_crw_chanlabels = cell array of strings indicating the names of the 0038 % channels whose calibration pulse amplitude was estimated (some channels 0039 % might not be processed if rm_chans argument is used) 0040 % 0041 % 0042 % Outputs for plotting cal diagnostics via trm_raw2nrm.m: 0043 % firstpulse = 2D matrix of the first cal pulse at all channels 0044 % lastpulse = 2D matrix of the last cal pulse at all channels 0045 % prewind = Beginning and end of pre-pulse baseline window (in msec) 0046 % used for measuring pulse amplitude 0047 % postwind = Beginning and end of post-pulse baseline window (in msec) 0048 % used for measuring pulse amplitude 0049 % runningsum = 2D matrix of the mean of all pulses 0050 % tme = vector of peri-stimulus times (in msec) corresponding to 0051 % each time point of data 0052 % 0053 % Notes: 0054 % -Function assumes that cal pulses are all assigned to a single bin 0055 % 0056 % Author: 0057 % David Groppe (based on code written by Tom Urbach), 0058 % Kutaslab, 8/2009 0059 % 0060 0061 %%%%%%%%%%%%%%%% REVISION LOG %%%%%%%%%%%%%%%%% 0062 % 0063 % 08/21/09 Function is more memory efficient (only stores cal pulse amplitude, 0064 % not entire pulse) -DG 0065 % 0066 % 09/15/09 Added rm_chans option. -DG 0067 0068 global VERBLEVEL 0069 0070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0071 % I. OPEN CAL PULSE CRW FILE USING ERPIO() & GET EXP INFO AND RECORDING PARAMETERS 0072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0073 fid_crw=erpio('openraw',Results.cal_crwfile,Results.cal_logfile,Results.presam,Results.cprecis,Results.decimat); 0074 if (erpio('get_errno') == 0), 0075 VerbReport(sprintf('Opening cal pulse crw file %s went OK', Results.cal_crwfile), 2, VERBLEVEL); 0076 else 0077 error(erpio('get_errstr')); 0078 end; 0079 0080 % Get experiment info and recording parameters 0081 VerbReport('Getting cal pulse crw file header information.', 3, VERBLEVEL); 0082 0083 %Note: these aren't necessary, but worth reporting 0084 expdesc = erpio('get_hdrvar', fid_crw, 'expdesc', 0); 0085 subdesc = erpio('get_hdrvar', fid_crw, 'subdesc', 0); 0086 VerbReport(sprintf('Cal crw File Exp Desc: %s',expdesc), 3, VERBLEVEL); 0087 VerbReport(sprintf('Cal crw File Sub Desc: %s',subdesc), 3, VERBLEVEL); 0088 0089 %Necessary 0090 nchans = erpio('get_hdrvar', fid_crw, 'chans',0); 0091 crw_chanlabels=cell(1,nchans); 0092 for a=1:nchans, 0093 crw_chanlabels{a}=erpio('get_hdrvar',fid_crw,'chndesc',a-1); 0094 % "a-1" because indexing starts at 0 0095 end 0096 tpts = 256* Results.cprecis; 0097 srate=100000/erpio('get_hdrvar',fid_crw,'clktick','junk'); 0098 0099 % Figure out which channels to use 0100 use_chans=1:nchans; 0101 use_crw_chanlabels=cell(1,1); 0102 use_chan_ct=0; 0103 if ~isempty(rm_chans), 0104 for a=1:nchans, 0105 for b=1:length(rm_chans), 0106 if strcmpi(crw_chanlabels{a},rm_chans{b}), 0107 use_chans(a)=-1; 0108 break; %break b loop 0109 end 0110 end 0111 if use_chans(a)>0 0112 use_chan_ct=use_chan_ct+1; 0113 use_crw_chanlabels{use_chan_ct}=crw_chanlabels{a}; 0114 end 0115 end 0116 use_chans=use_chans(find(use_chans>0)); 0117 else 0118 use_crw_chanlabels=crw_chanlabels; 0119 end 0120 nchans=length(use_chans); 0121 0122 0123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0124 % II. IMPORT BLF FILE INFORMATION 0125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0126 [blf_info, bin_LongDesc, blffile, blf_evnum]=import_blf(cal_blfORbdf_file,Results.cal_logfile, ... 0127 srate,[]); 0128 0129 %Remove unnecessary vars 0130 clear blf_info bin_LongDesc 0131 0132 %blf_evnum is necessary for screening out any events in the logfile 0133 %that were not caught by the blf file 0134 0135 0136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0137 % III. IMPORT LOG INFO FROM ASCII VERSION OF CAL_LOGFILE 0138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0139 VerbReport(' ',1,VERBLEVEL); 0140 %Create temporary ascii version of Results.cal_logfile 0141 VerbReport(sprintf('Creating temporary ascii version of cal_logfile %s',Results.cal_logfile),1,VERBLEVEL); 0142 %remove temp_cal.asci if it exists 0143 asci_cmnd='rm -f temp_cal.asci'; 0144 unix(asci_cmnd); 0145 asci_cmnd=sprintf('log2asci %s temp_cal.asci -d %d',Results.cal_logfile,srate); 0146 [s, w]=unix(asci_cmnd); 0147 if s~=0, 0148 disp('Could not create ascii version of cal_logfile using log2asci.'); 0149 error('According to log2asci: %s',w); 0150 end 0151 asciilogfile='temp_cal.asci'; 0152 VerbReport(sprintf('Getting log information from %s', asciilogfile), 1, VERBLEVEL); 0153 0154 0155 % Load log information ... 0156 enum = []; ecode = []; ccode = []; flag =[]; tick = []; sec =[]; deltaT = []; 0157 %check to find out how ascii version of log file was created 0158 fid_ascii=fopen(asciilogfile,'r'); 0159 lyne=fgetl(fid_ascii); %read in first line 0160 for dumb_loop=1:13, 0161 lyne=fgetl(fid_ascii); %read in headerlines 0162 end 0163 if strcmpi(lyne(length(lyne)-4:end),'Delta') %file was generated with sampling rate 0164 fclose(fid_ascii); 0165 [enum, ecode, ccode, flag, tick, sec, deltaT]=textread(asciilogfile,['%d' ... 0166 ' %d %d %d %d %f %f'],'headerlines',14); 0167 else 0168 err_str=sprintf('ERROR: ASCII version of cal_logfile %s was not generated with sampling rate.\n', ... 0169 asciilogfile); 0170 error([err_str 'Please correct.']); 0171 end 0172 log_file_info = [enum, ecode, ccode, flag, sec]; 0173 0174 %Select only cal_logfile information for events that are listed in the 0175 %blf file 0176 log_info=zeros(size(blf_evnum,1),5); %preallocate memory 0177 ct=0; 0178 for blf_ev=blf_evnum, 0179 ct=ct+1; 0180 log_info(ct,:) = log_file_info(find(enum==blf_ev),:); 0181 end 0182 0183 %If a temp ascii version of cal_logfile was created, delete it 0184 if ~isempty(asci_cmnd) 0185 VerbReport(sprintf('Removing temporary ascii version of cal_logfile.'),1,VERBLEVEL); 0186 asci_cmnd='rm -f temp_cal.asci'; 0187 [s, w]=unix(asci_cmnd); 0188 if s~=0, 0189 disp('Could not remove ascii version of cal_logfile: temp_cal.asci.'); 0190 error('According to rm: %s',w); 0191 end 0192 end 0193 0194 0195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0196 % IV. READ CAL PULSES ... 0197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 0198 VerbReport(sprintf('\nGetting epochs from %s', Results.cal_crwfile), 1, VERBLEVEL); 0199 0200 % NAB NUMBER OF EPOCHS THE BLF FILE KNOWS ABOUT 0201 nep = size(log_info,1); 0202 0203 % INITIALIZE DATA AND INFO ARRAYS W/ MAX POSSIBLE EPOCHS THO 0204 % MAY BE FEWER IF EEG DATA READ FAILURES ... 0205 nom_cal_size = sum(log_info(:,3)==0); 0206 0207 %Assumes calibration condition code is 0 0208 VerbReport('Assuming Condition Code 0=calibration pulses.',1,VERBLEVEL); 0209 VerbReport(sprintf('%d total calibration pulses from cal crw file',nom_cal_size), 1, VERBLEVEL); 0210 0211 0212 %Initialize pulse variables 0213 runningsum=zeros(nchans,tpts); 0214 pulseamps=zeros(nchans,nom_cal_size); 0215 cal_itemnum=zeros(1,nom_cal_size); 0216 0217 % Find pre and post pulse time windows for measuring pulse amplitude 0218 %peristimulus time of each time point in milliseconds 0219 tme=1000*((1:256*Results.cprecis)-1)/srate; 0220 tme=tme-Results.presam; 0221 [dummy, low_cntr_samp]=min(abs(Results.low_cursor-tme)); 0222 [dummy, hi_cntr_samp]=min(abs(Results.hi_cursor-tme)); 0223 0224 %Pre-Pulse time window (in samples) 0225 lo_start_samp = low_cntr_samp-floor(Results.cal_npts/2); 0226 lo_stop_samp = low_cntr_samp+floor(Results.cal_npts/2); 0227 prewind=[tme(lo_start_samp) tme(lo_stop_samp)]; 0228 0229 %Post-Pulse time window (in samples) 0230 hi_start_samp = hi_cntr_samp-floor(Results.cal_npts/2); 0231 hi_stop_samp = hi_cntr_samp+floor(Results.cal_npts/2); 0232 postwind=[tme(hi_start_samp) tme(hi_stop_samp)]; 0233 0234 %Count # of calibration epochs actually loaded 0235 calcnt = 0; 0236 for i=1:nep 0237 0238 % ATTEMPT TO NAB EPOCH ... ERPIO RETURNS EMPTY ARRAY IF IT DOESN'T WORK 0239 currdat = zeros(nchans,tpts); 0240 currdat = erpio('evread', fid_crw, log_info(i, 1)); 0241 0242 % BRANCH ON CONDITION CODE FOR CALS VS. ALL OTHER EVENTS 0243 if (log_info(i,3)==0), 0244 if isempty(currdat) 0245 % DON'T LOAD ANY THING IF THERE IS NO DATA BUT CONTINUE 0246 msg=sprintf(['erpio: Can not read data at log item %d.\n' ... 0247 'Log item should be a calibration pulse.'],log_info(i,1)); 0248 watchit(msg); 0249 else 0250 %get rid of data from channels that are to be ignored 0251 currdat=currdat(use_chans,:); 0252 0253 calcnt = calcnt+1; 0254 %record logitem number of pulse 0255 cal_itemnum(calcnt)=log_info(i,1); 0256 lastpulse=currdat; 0257 %remove pre-pulse baseline 0258 lastpulse=rmbase(lastpulse,tpts,lo_start_samp:lo_stop_samp); 0259 if calcnt==1, 0260 firstpulse=lastpulse; 0261 end 0262 runningsum=runningsum+lastpulse; 0263 %get pulse amp 0264 pulseamps(:,calcnt)=mean(lastpulse(:,hi_start_samp:hi_stop_samp),2); 0265 VerbReport(sprintf('Loading cal %d/%d event (blf event %d/%d)', ... 0266 calcnt,nom_cal_size,i,nep),3,VERBLEVEL); 0267 end 0268 elseif (log_info(i,3)<0) 0269 error('Unexplained negative condition code at log item %d.', i); 0270 end 0271 end 0272 erpio('close', fid_crw) 0273 0274 0275 % Trim end of preallocated array to size of sucessful pulse reads 0276 pulseamps=pulseamps(:,1:calcnt); 0277 cal_itemnum=cal_itemnum(1:calcnt); 0278 %turn sum into mean 0279 runningsum=runningsum/calcnt; 0280 0281 VerbReport('', 1, VERBLEVEL); 0282 VerbReport(sprintf('Done loading cal pulses from %s\n',Results.cal_crwfile), 3, VERBLEVEL); 0283 %remove temp mkp files in case they exist 0284 if strcmpi(blffile,'temp.blf'), 0285 VerbReport('Removing temporary files: temp.rt, temp.blf', 2, VERBLEVEL); 0286 unix('rm -f temp.blf'); 0287 unix('rm -f temp.rt'); 0288 end 0289 VerbReport('', 1, VERBLEVEL); 0290