|
| 1 | +%% CATEGORIZE TRIALS |
| 2 | +% This program performs the following operations: |
| 3 | +% 1. Opens each CNT file and converts it to Matlab using X_loadcnt |
| 4 | +% 2. Shows the user the lever responses versus time for each stimulus type |
| 5 | +% to determine attention. |
| 6 | +% 3. Epochs data for each electrode for vis-std and vis-odd stimuli (ignoring auditory) |
| 7 | +% 4. Saves to disk. |
| 8 | +% |
| 9 | +% Data are saved in the following format: |
| 10 | +% data = 2x2 cell array (attend vs. non-attend; IT vs. V4) |
| 11 | +% data{i,j} = structure with the following fields: |
| 12 | +% filename = full name of original file |
| 13 | +% epoch = peristimulus window in s |
| 14 | +% channels = channels from the original file |
| 15 | +% Hz = sampling rate in Hz |
| 16 | +% attend = whether or not the visual stimuli were being attended to |
| 17 | +% xaxis = simply epoch*Hz; the time points corresponding to the data |
| 18 | +% [std = visual standard epoched data, dimensions are channel | trial | time] -- optional |
| 19 | +% odd = visual oddball epoched data, dimensions are channel | trial | time |
| 20 | +% |
| 21 | +% Note that the trials in the data span multiple recording sessions. Part 2 |
| 22 | +% of this code is based on csdatachecks.m, while part 3 is based on |
| 23 | +% csdataepoch.m. |
| 24 | +% |
| 25 | +% Version: 2015sep19 |
| 26 | + |
| 27 | +%% 0. Housekeeping |
| 28 | + |
| 29 | +datadir='/home/cliffk/bill/data/juemo/raw/'; % Which directory to look for data in |
| 30 | +addpath(datadir) % So X_loadcnt() is available |
| 31 | +outfile='tmp.mat'; % Output filename |
| 32 | +dosave = 0; % Whether or not to save |
| 33 | +oldrate=2000; % Sampling rate in Hz |
| 34 | +epochstart=-0.2; % Start of epoch in s |
| 35 | +epochend=0.4; % End of epoch in s |
| 36 | +newrate=200; % New sampling rate in Hz |
| 37 | +channels=[30:43; 1:14]; % V4 and IT LFP channels |
| 38 | +data=cell(2,2); % Store output data |
| 39 | +v4vsit={'V4','IT'}; % The names of the two sites |
| 40 | + |
| 41 | +stimcount=zeros(2,2,2,length(channels)); % Number of stimuli; dimensions are: attend/ignore | IT/V4 | standard/oddball | channel |
| 42 | + |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +%% 1. Loading data |
| 47 | + |
| 48 | +allfiles=dir([datadir '*.cnt']); % Get all file names |
| 49 | +nfiles=length(allfiles); |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | +for Z=1:nfiles % Loop over files |
| 54 | + tic |
| 55 | + fprintf('\nLoading file %i of %i (%s)...\n',Z,nfiles,allfiles(Z).name) |
| 56 | + tmpdata=X_loadcnt(allfiles(Z).name); |
| 57 | + origdata=tmpdata.data'; % Pull out the interesting array and transpose it |
| 58 | + |
| 59 | + |
| 60 | + %% 2. Decide on whether trial block is attend-auditory or attend-visual |
| 61 | + xaxis=(0:length(origdata)-1)/oldrate; % Set up an x-axis to plot everything |
| 62 | + |
| 63 | + labels={'Auditory target (green: lever)','Visual target (green: lever)'}; |
| 64 | + levertimes=diff(origdata(:,61)); levertimes=find(levertimes>200)/oldrate; % Pull out lever times |
| 65 | + npulls=length(levertimes); % How many times the monkey pulled the lever |
| 66 | + audodd=diff(origdata(:,58)); audodd=find(audodd<-200)/oldrate; % Pull out auditory oddball stimuli |
| 67 | + visodd=diff(origdata(:,60)); visodd=find(visodd<-200)/oldrate; % Pull out visual oddball stimuli |
| 68 | + audpositive=0; |
| 69 | + vispositive=0; |
| 70 | + |
| 71 | + h=figure('position',[-200 500 2200 50]); hold on |
| 72 | + scatter(levertimes,2*ones(npulls,1),'k','filled') |
| 73 | + scatter(audodd,1*ones(size(audodd)),'g','filled') |
| 74 | + scatter(visodd,3*ones(size(visodd)),'b','filled') |
| 75 | + drawnow |
| 76 | + |
| 77 | + for i=1:length(levertimes) |
| 78 | + tmpaud=levertimes(i)-audodd; % Find the time difference between the lever press and the stimuli |
| 79 | + tmpvis=levertimes(i)-visodd; % Find the time difference between the lever press and the stimuli |
| 80 | + tmpaud=tmpaud(tmpaud>0.05 & tmpaud<1.2); % Give it between 100 ms and 1 s to respond |
| 81 | + tmpvis=tmpvis(tmpvis>0.05 & tmpvis<1.2); % Give it between 100 ms and 1 s to respond |
| 82 | + if isempty(tmpaud), tmpaud=Inf; end % Handle cases where no stimuli are available |
| 83 | + if isempty(tmpvis), tmpvis=Inf; end |
| 84 | + if min(tmpaud)<min(tmpvis) |
| 85 | + audpositive=audpositive+1; |
| 86 | + fprintf(' * %ith auditory response after %i ms\n',audpositive,round(min(tmpaud)*1000)) |
| 87 | + elseif min(tmpvis)<min(tmpaud) |
| 88 | + vispositive=vispositive+1; |
| 89 | + fprintf(' ** %ith visual response after %i ms\n',vispositive,round(min(tmpvis)*1000)) |
| 90 | + else |
| 91 | + disp(' *** No clear antecedent!') |
| 92 | + end |
| 93 | + end |
| 94 | + |
| 95 | + h=figure('position',[700 100 1000 500]); |
| 96 | + for i=1:2 |
| 97 | + subplot(2,1,i); hold on |
| 98 | + plot(xaxis,-origdata(:,56+i*2)) % Plot stimuli |
| 99 | + plot(xaxis,origdata(:,61),'g') % Plot lever response |
| 100 | + title(labels{i}) |
| 101 | + if i==2, xlabel('Time (s)'), end |
| 102 | + box on |
| 103 | + xlim([0,300]) |
| 104 | + end |
| 105 | +% drawnow; pause(5); close(h); drawnow |
| 106 | + |
| 107 | + if audpositive>2*vispositive % If monkey responds twice as frequently to auditory, assume that's what it is |
| 108 | + fprintf(' Monkey was responding to auditory (%i vs %i)\n',audpositive,vispositive) |
| 109 | + A=1; |
| 110 | + elseif vispositive>2*audpositive % If monkey responds twice as frequently to visual, assume that's what it is |
| 111 | + fprintf(' Monkey was responding to visual (%i vs %i)\n',audpositive,vispositive) |
| 112 | + A=2; |
| 113 | + else |
| 114 | + disp('Monkey was confused :(') |
| 115 | + A=input('Auditory (1) or visual (2)? '); % Whether auditory or visual stimuli are being attended to |
| 116 | +% close(h); drawnow % Close window when done |
| 117 | + end |
| 118 | + |
| 119 | + pause(2) |
| 120 | + close(h); drawnow |
| 121 | + |
| 122 | + |
| 123 | + |
| 124 | + for Q=1:2 % Loop over V4 vs. IT |
| 125 | + |
| 126 | + %% 3. Store additional information |
| 127 | + data{A,Q}.filename=[datadir allfiles(Z).name]; % Which file did the data come from originally? |
| 128 | + data{A,Q}.epoch=[epochstart epochend]; % How big is the window? |
| 129 | + data{A,Q}.channels=channels(Q,:); % Which channels to pull from the file? |
| 130 | + data{A,Q}.Hz=newrate; % What's the sampling rate in Hz? |
| 131 | + data{A,Q}.attend=A-1; % Which stimulus type is being attended to in this data |
| 132 | + data{A,Q}.area=v4vsit{Q}; % What area the data is from: V4 or IT |
| 133 | + |
| 134 | + %% 3. Split the data up into trials |
| 135 | + trialtypes={'std','odd'}; % Trial types -- auditory standard, auditory oddball, visual standard, visual oddball |
| 136 | + stimindices=[57 58]; % Which channels in the file correspond to stim data; [57 58] are auditory stimuli, [59 60] are visual |
| 137 | + ntypes=length(trialtypes); |
| 138 | + nchannels=length(channels); |
| 139 | + npts=ceil((epochend-epochstart)*newrate); % Number of points in each trial window |
| 140 | + newptsbefore=-epochstart*newrate; % How many points before the stimulus to use |
| 141 | + newptsafter=epochend*newrate; % How many points after the stimulus to use |
| 142 | + oldptsbefore=-epochstart*oldrate; |
| 143 | + oldptsafter=epochend*oldrate; |
| 144 | + data{A,Q}.xaxis=linspace(epochstart,epochend,npts); % For plotting -- store time information |
| 145 | + |
| 146 | + fprintf(' Splitting %i of %i into epochs...\n',Q,2) |
| 147 | + for i=1:ntypes % Loop over standards and oddballs |
| 148 | + fprintf(' Working on type %i of %i...\n',i,ntypes); |
| 149 | + % Get the stimulus times |
| 150 | + thisstim=origdata(:,stimindices(i)); % Pull out the stimuli |
| 151 | + totalpts=length(thisstim); % Total number of data points |
| 152 | + stimdiff=diff(thisstim); % Detect changes in the stimuli |
| 153 | + stimtimes=find(stimdiff<-200); % Changes are huge decreases (~-500) in the stim time series |
| 154 | + stimtimes=stimtimes(stimtimes>oldptsbefore & stimtimes<(totalpts-oldptsafter)); % Remove stimuli that are too close to the beginning or end of the recording |
| 155 | + nstims=length(stimtimes); % Number of stimuli |
| 156 | + |
| 157 | + % Set up the array to store results in |
| 158 | + if Z==1, data{A,Q}.(trialtypes{i})=zeros(nchannels,3000,npts); end % Set up array if not set up before, 3000 is arbitrary to make it big enough |
| 159 | + |
| 160 | + % Pull out the corresponding data |
| 161 | + for j=1:nchannels |
| 162 | + for k=1:nstims |
| 163 | + stimcount(A,Q,i,j)=stimcount(A,Q,i,j)+1; % Total number of stimuli -- sum over files (Z) and k but nothing else |
| 164 | + thisdata=origdata(stimtimes(k)-oldptsbefore:stimtimes(k)+oldptsafter+oldrate/newrate,channels(Q,j)); % Pull out the data; oldrate/newrate is to give one extra data point |
| 165 | + tmp=downsample(thisdata,oldrate,newrate); % Downsample to the desired rate |
| 166 | + data{A,Q}.(trialtypes{i})(j,stimcount(A,Q,i,j),:)=tmp; % Append to entire array |
| 167 | + end |
| 168 | + end |
| 169 | + end |
| 170 | + end |
| 171 | + toc |
| 172 | +end |
| 173 | + |
| 174 | +for A=1:2 |
| 175 | + for Q=1:2 |
| 176 | + for i=1:ntypes |
| 177 | + data{A,Q}.(trialtypes{i})=data{A,Q}.(trialtypes{i})(:,1:stimcount(A,Q,i,1),:); % Trim extra "rows" |
| 178 | + end |
| 179 | + end |
| 180 | +end |
| 181 | + |
| 182 | +if dosave |
| 183 | + fprintf('\nSaving data...\n') |
| 184 | + save(outfile,'data') % Save data |
| 185 | + disp('...done.') |
| 186 | +end |
| 187 | + |
| 188 | + |
| 189 | +disp('Done.') |
0 commit comments