123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- %detect putative dentate spikes, extract their features and voltage profiles
- %2021 Dino Dvorak, New York University, neuraldino@gmail.com
- %Dentate spikes and external control of hippocampal function,
- %Cell Reports, Volume 36, Issue 5, 2021,109497,ISSN 2211-1247,
- %https://doi.org/10.1016/j.celrep.2021.109497
- clear; close all; clc;
- eegFS = 2000; %sample rate
- %input LFP file (channels x samples)
- fnEEG = '2016_09_30_PP12_334_PRETRAIN_BASE_eeg.mat';
- %DG channel (found using initial visual inspection)
- chDG = 24;
- %directories
- drMAT = 'MAT_EEG/'; %LFPs
- drOUT = 'DS/'; %OUTPUT
- %create filter for detection
- %pass-band 5-100Hz, 4Hz transition band, 40Hz attenuation
- [b, gd] = getFIRbandpass( 5,100,4,40,eegFS );
- chAround = 5; %+/- channels around for DS profile
- winBA = [60 20]; %search window for maxima before/after in samples (-60..-20samples or +20..+60 samples)
- thMin = []; %smallest threshold to accept (saves data)
- %features
- labelsFeat = {'sample','promZ','peakZ','peakRaw','promZbefore','promZafter',... %1..6
- 'peakZbefore','peakZafter','minZbefore','minZafter',...%7..10
- 'wDG','wBA','w50','tB','tA','tminB','tminA','acc','speed','max10_30before','max10_30after'}; %11..21
- %load LFP
- load([drMAT fnEEG]);
- eegData = double(eegData);
- Nchannels = size(eegData,1);
- %DG electrode
- eegDG = eegData(chDG,:);
- %filter 2-100Hz
- chST = chDG - chAround;
- chED = chDG + chAround;
- if chED > Nchannels; chED = Nchannels; end;
- if chST < 1; chST = 1; end;
- channelsProfiles = chST:chED;
- chDGk = find(channelsProfiles == chDG);
- eegF = filter(b,1,eegData(chST:chED,:),[],2);
- eegF = cat(2,eegF(:,gd+1:end),zeros(size(eegF,1),gd));
- %DG channel
- eegFDG = eegF(chDGk,:);
- %DG - maxima and minima (extract width,prominence)
- [MaxesDG,kMaxesDG,wDG,pDG] = findpeaks(eegFDG);
- [~,kMinsDG] = findpeaks(1.01*max(eegFDG) - eegFDG);
- %for each maxima in DG
- feat = nan(length(kMaxesDG),23);
- for i = 10:length(kMaxesDG)-10 %skip first couple of minima for before/after min-max computations
- s = kMaxesDG(i); %sample
- pDGi = pDG(i); %prominence of peak in z-score signal
- wDGi = wDG(i)/eegFS*1000; %width of peak in z-score signal
- pDGB = pDG(i-1); %prominence of peak before in z-score signal
- pDGA = pDG(i+1); %prominence of peak after in z-score signal
- tDGB = (s - kMaxesDG(i-1))/eegFS*1000; %mseconds to maxima before
- tDGA = (kMaxesDG(i+1) - s)/eegFS*1000; %mseconds to maxima after
- mDG = MaxesDG(i); %max value in z-scored filtered signal
- acci = nan; %acceleration
- mDGB = MaxesDG(i-1); %preceding maxima in z-scored filtered signal
- mDGA = MaxesDG(i+1); %following maxima in z-scored filtered signal
- %indexes preceeding and following minima
- kB = kMinsDG(kMinsDG < s);
- kA = kMinsDG(kMinsDG > s);
- if isempty(kB) || isempty(kA); continue; end;
- kB = kB(end);
- kA = kA(1);
- %time to minima before
- tmB = (s - kB)/eegFS*1000; %mseconds to minima before
- tmA = (kA - s)/eegFS*1000; %mseconds to minima after
- %maxima in raw signal
- mr = max(eegDG(s-10:s+10));
- %peak to to minima before and after
- mB = eegFDG(kB);
- mA = eegFDG(kA);
- %speed
- spi = nan;
- %width between minima
- wBA = (kA-kB)/eegFS*1000;
- %width 50%
- w50 = nan;
- k50B = nan;
- k50A = nan;
- if mB > mA %before higher
- level = (mDG + mB)/2;
- else %after higher
- level = (mDG + mA)/2;
- end
- x = eegFDG(kB:kA);
- %cut before maxima
- k = find(x(1:end-1) <= level & x(2:end) > level);
- if ~isempty(k)
- k50B = k(1);
- end
- %cut after maxima
- k = find(x(1:end-1) >= level & x(2:end) < level);
- if ~isempty(k)
- k50A = k(end);
- end
- if ~isnan(k50B) && ~isnan(k50A)
- w50 = (k50A-k50B)/eegFS*1000;
- end
- %winBA = [60 20];
- %maxima before
- x = eegFDG(s-winBA(1):s-winBA(2));
- maxB = max(x);
- %maxima after
- x = eegFDG(s+winBA(2):s+winBA(1));
- maxA = max(x);
- %minima in raw before
- mrB = min(eegDG(kB-10:kB+10));
- %minima in raw after
- mrA = min(eegDG(kA-10:kA+10));
- feat(i,1) = s; %sample max sDG
- feat(i,2) = pDGi; %prominence of peak in z-score signal
- feat(i,3) = mDG; %max value in z-scored filtered signal
- feat(i,4) = mr; %maxima in raw
- feat(i,5) = pDGB; %prominence of peak before in z-score signal
- feat(i,6) = pDGA; %prominence of peak after in z-score signal
- feat(i,7) = mDGB; %preceding maxima in z-scored filtered signal
- feat(i,8) = mDGA; %following maxima in z-scored filtered signal
- feat(i,9) = mB; %minima preceding peak in z-score signal
- feat(i,10) = mA; %minima following peak in z-score signal
- feat(i,11) = wDGi; %width of peak in z-score signal
- feat(i,12) = wBA; %width between minima
- feat(i,13) = w50; %width 50%
- feat(i,14) = tDGB; %mseconds to maxima before
- feat(i,15) = tDGA; %mseconds to maxima after
- feat(i,16) = tmB; %mseconds to minima before
- feat(i,17) = tmA; %mseconds to minima after
- feat(i,18) = acci; %acceleration
- feat(i,19) = spi; %speed
- feat(i,20) = maxB; %maxima 30-10ms before
- feat(i,21) = maxA; %maxima 10-30ms after
- feat(i,22) = mrB; %minima in raw before
- feat(i,23) = mrA; %minima in raw after
- end
- %remove nans
- knan = ~isnan(feat(:,1));
- feat = feat(knan,:);
- %apply thMin
- if ~isempty(thMin)
- k = feat(:,3) > thMin;
- %d = feat(:,3) - feat(:,9); %dist peak to minima before
- %k = d > 2;
- feat = feat(k,:);
- end
- %extract profiles around maxima
- s = feat(:,1); %samples;
- profilesDS = eegF(:,s);
- %save putative DS events
- save([drOUT fnEEG],'feat','chDG','profilesDS','channelsProfiles','labelsFeat');
-
- %plot output
- figure;
- subplot(1,2,1);
- plot(mean(profilesDS,2),1:size(profilesDS,1))
- title('Volrage DS profile');
- subplot(1,2,2);
- histogram(feat(:,11));
- title('Event width');
-
|