OSCR

Transient gamma events delineate somatosensory modality in S1.

Code ↔ Paper

3 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 3 matches
  1. [1] § Results › Transient gamma events correlate with stimulus modality and nocifensive response ↔ spectralevents.py, lines 293–399 · score 0.76 · un normalized TFR, event frequency span, Event onset, suprathreshold regions, maximum power, spectral events
  2. [2] § Results › Transient gamma events correlate with stimulus modality and nocifensive response ↔ spectralevents_find.m, lines 282–404 · score 0.71 · un normalized TFR, Event onset, suprathreshold regions, maximum power, spectral events, magnitude
  3. [3] § STAR★Methods › Method details › Spectral event analysis ↔ spectralevents_find.m, lines 203–280 · score 0.68 · spectralEvents, event metrics, un normalized, Shin, frequency bands, peaks

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

MATLAB · 528 lines · 32 KB · BSD-3-Clause · 2 matches

  1. function specEv_struct = spectralevents_find(findMethod, eventBand, thrFOM, tVec, fVec, TFR, classLabels)
  2. % SPECTRALEVENTS_FIND Algorithm for finding and calculating spectral
  3. % events on a trial-by-trial basis of a single subject/session. Uses
  4. % one of three methods before further analyzing and organizing event
  5. % features:
  6. %
  7. % 1) (Primary event detection method in Shin et al. eLife 2017): Find
  8. % spectral events by first retrieving all local maxima in
  9. % un-normalized TFR using imregionalmax, then selecting suprathreshold
  10. % peaks within the frequency band of interest. This method allows for
  11. % multiple, overlapping events to occur in a given suprathreshold
  12. % region and does not guarantee the presence of within-band,
  13. % suprathreshold activity in any given trial will render an event.
  14. % 2) Find spectral events by first thresholding
  15. % entire normalize TFR (over all frequencies), then finding local
  16. % maxima. Discard those of lesser magnitude in each suprathreshold
  17. % region, respectively, s.t. only the greatest local maximum in each
  18. % region survives (when more than one local maxima in a region have
  19. % the same greatest value, their respective event timing, freq.
  20. % location, and boundaries at full-width half-max are calculated
  21. % separately and averaged). This method does not allow for overlapping
  22. % events to occur in a given suprathreshold region and does not
  23. % guarantee the presence of within-band, suprathreshold activity in
  24. % any given trial will render an event.
  25. % 3) Find spectral events by first thresholding
  26. % normalized TFR in frequency band of interest, then finding local
  27. % maxima. Discard those of lesser magnitude in each suprathreshold region,
  28. % respectively, s.t. only the greatest local maximum in each region
  29. % survives (when more than one local maxima in a region have the same
  30. % greatest value, their respective event timing, freq. location, and
  31. % boundaries at full-width half-max are calculated separately and
  32. % averaged). This method does not allow for overlapping events to occur in
  33. % a given suprathreshold region and ensures the presence of
  34. % within-band, suprathreshold activity in any given trial will render
  35. % an event.
  36. %
  37. % specEv_struct = SPECTRALEVENTS_FIND(findMethod,eventBand,thrFOM,tVec,fVec,TFR,classLabels)
  38. %
  39. % Inputs:
  40. % findMethod - integer value specifying which event-finding method to use
  41. % (1, 2, or 3). Note that the method specifies how much overlap
  42. % exists between events. Use 1 to replicate the method used in
  43. % et al. eLife 2017.
  44. % eventBand - range of frequencies ([Fmin_event Fmax_event]; Hz) over
  45. % which above-threshold spectral power events are classified.
  46. % thrFOM - factors of median threshold; positive real number used to
  47. % threshold local maxima and classify events (see Shin et al. eLife
  48. % 2017 for discussion concerning this value).
  49. % tVec - time vector (s) over which the time-frequency response (TFR) is
  50. % calcuated.
  51. % fVec - frequency vector (Hz) over which the time-frequency response
  52. % (TFR) is calcuated.
  53. % TFR - time-frequency response (TFR) (frequency-by-time-trial) for a
  54. % single subject/session.
  55. % classLabels - numeric or logical 1-row array of trial classification
  56. % labels; associates each trial of the given subject/session to an
  57. % experimental condition/outcome/state (e.g., hit or miss, detect or
  58. % non-detect, attend-to or attend away).
  59. %
  60. % Outputs:
  61. % specEv_struct - event feature structure with three main sub-structures:
  62. % TrialSummary (trial-level features), Events (individual event
  63. % characteristics), and IEI (inter-event intervals from all trials
  64. % and those associated with only a given class label).
  65. %
  66. % See also SPECTRALEVENTS, SPECTRALEVENTS_FIND, SPECTRALEVENTS_TS2TFR, SPECTRALEVENTS_VIS.
  67. % Initialize general data parameters
  68. eventBand_inds = fVec>=eventBand(1) & fVec<=eventBand(2); %Logical vector representing indices of freq vector within eventBand
  69. if size(eventBand_inds,1)~=length(eventBand_inds)
  70. eventBand_inds = eventBand_inds'; %Transpose so that the dimensions correspond with the frequency-domain dimension of the TFR
  71. end
  72. flength = size(TFR,1); %Number of elements in discrete frequency spectrum
  73. tlength = size(TFR,2); %Number of points in time
  74. numTrials = size(TFR,3); %Number of trials
  75. classes = unique(classLabels);
  76. medianpower = median(reshape(TFR, size(TFR,1), size(TFR,2)*size(TFR,3)), 2); %Median power at each frequency across all trials
  77. thr = thrFOM*medianpower; %Spectral event threshold for each frequency value
  78. % Validate consistency of parameter dimensions
  79. if flength~=length(fVec) || tlength~=length(tVec) || numTrials~=length(classLabels)
  80. error('Mismatch in input parameter dimensions!')
  81. end
  82. % Find events using the method-of-choice
  83. spectralEvents = []; %Array for storing event results
  84. switch findMethod
  85. case 1
  86. find_localmax_method_1;
  87. case 2
  88. find_localmax_method_2;
  89. case 3
  90. find_localmax_method_3;
  91. otherwise
  92. error('Unknown event-finding method.')
  93. end
  94. % Make sure this subject/session contains >1 events
  95. if isempty(spectralEvents)
  96. disp('Warning!! This subject/session contains no events!!')
  97. specEv_struct = struct('TrialSummary',[],'Events',[],'IEI',[]);
  98. return;
  99. end
  100. % Identify and organize event features
  101. % Matrix of event features: each row is an event
  102. % 11 column matrix with 1. trial index, 2. hit/miss, 3. maxima frequency, 4. lowerbound frequency, 5. upperbound frequency, 6. frequency span, ...
  103. % 7. maxima timing, 8. event onset timing, 9. event offset timing, 10. event duration, 11. maxima power, 12. maxima/median power
  104. spectralEvents_columnlabel={'trialind', 'classLabels', 'maximafreq', 'lowerboundFspan', 'upperboundFspan', 'Fspan', ...
  105. 'maximatiming', 'onsettiming', 'offsettiming', 'duration', 'maximapower', 'maximapowerFOM'};
  106. for rci=1:numel(spectralEvents_columnlabel)
  107. eventsind.(spectralEvents_columnlabel{rci})=rci;
  108. end
  109. trialSummary.classLabels = classLabels';
  110. trialSummary.meanpower = mean(squeeze(mean(TFR(eventBand_inds,:,:),2)) ./ repmat(medianpower(eventBand_inds),1,numTrials), 1)'; %Mean trial power normalized to frequency-specific median
  111. suprathrTFR = TFR>=repmat(thr,1,tlength,numTrials);
  112. trialSummary.coverage = squeeze(sum(sum(suprathrTFR(eventBand_inds,:,:),1),2)) *100 / (nnz(eventBand_inds)*tlength); %Calculated in percentage
  113. % Initialize column vectors
  114. trialSummary.eventnumber = nan(numTrials,1);
  115. trialSummary.meaneventpower = nan(numTrials,1);
  116. trialSummary.meaneventduration = nan(numTrials,1);
  117. trialSummary.meaneventFspan = nan(numTrials,1);
  118. trialSummary.mostrecenteventtiming = nan(numTrials,1);
  119. trialSummary.mostrecenteventpower = nan(numTrials,1);
  120. trialSummary.mostrecenteventduration = nan(numTrials,1);
  121. trialSummary.mostrecenteventFspan = nan(numTrials,1);
  122. % Iterate through trials
  123. for tri=1:numTrials
  124. trialSummary.eventnumber(tri)=nnz(spectralEvents(:,1)==tri);
  125. if nnz(spectralEvents(:,1)==tri)==0
  126. trialSummary.meaneventpower(tri) = 0; % traces2TFR always returns a positive value
  127. trialSummary.meaneventduration(tri) = 0;
  128. trialSummary.meaneventFspan(tri) = 0;
  129. trialSummary.mostrecenteventtiming(tri) = tVec(1)-mean(diff(tVec));
  130. trialSummary.mostrecenteventpower(tri) = 0;
  131. trialSummary.mostrecenteventduration(tri) = 0;
  132. trialSummary.mostrecenteventFspan(tri) = 0;
  133. else
  134. trialSummary.meaneventpower(tri) = mean(spectralEvents(spectralEvents(:,eventsind.trialind)==tri,eventsind.maximapowerFOM)); % traces2TFR always returns a positive value
  135. trialSummary.meaneventduration(tri) = mean(spectralEvents(spectralEvents(:,eventsind.trialind)==tri,eventsind.duration));
  136. trialSummary.meaneventFspan(tri) = mean(spectralEvents(spectralEvents(:,eventsind.trialind)==tri,eventsind.Fspan));
  137. trialSummary.mostrecenteventtiming(tri) = spectralEvents(find(spectralEvents(:,eventsind.trialind)==tri,1,'last'), eventsind.maximatiming);
  138. trialSummary.mostrecenteventpower(tri) = spectralEvents(find(spectralEvents(:,eventsind.trialind)==tri,1,'last'), eventsind.maximapowerFOM);
  139. trialSummary.mostrecenteventduration(tri) = spectralEvents(find(spectralEvents(:,eventsind.trialind)==tri,1,'last'), eventsind.duration);
  140. trialSummary.mostrecenteventFspan(tri) = spectralEvents(find(spectralEvents(:,eventsind.trialind)==tri,1,'last'), eventsind.Fspan);
  141. end
  142. end
  143. % Event dependent features (mean power, mean length, most recent timing):
  144. % need special treatment for zero event trials
  145. specialFeat.field = {'meaneventpower','meaneventduration','meaneventFspan','mostrecenteventtiming',...
  146. 'mostrecenteventpower','mostrecenteventduration','mostrecenteventFspan'};
  147. % Percent change from mean (PCM)
  148. trialSum_featNames = fieldnames(trialSummary);
  149. for feat_i=2:numel(trialSum_featNames)
  150. pcm_name = [trialSum_featNames{feat_i},'_pcm'];
  151. feature = trialSummary.(trialSum_featNames{feat_i});
  152. % Control for features that need special treatment
  153. validtrials = trialSummary.eventnumber>0 ; %Trials that do have events
  154. if ismember(trialSum_featNames{feat_i},specialFeat.field)
  155. trialSummary.(pcm_name) = 100 * (feature-mean(feature(validtrials))) ./ repmat(abs(mean(feature(validtrials))),numTrials,1);
  156. else
  157. trialSummary.(pcm_name) = 100 * (feature-mean(feature))./repmat(abs(mean(feature)),numTrials,1);
  158. end
  159. end
  160. % Inter-event interval (IEI)
  161. ieitemp=diff(spectralEvents(:,eventsind.maximatiming));
  162. sametrial=(diff(spectralEvents(:,eventsind.trialind))==0);
  163. IEI.IEI_all = ieitemp(sametrial);
  164. for cls_i=1:numel(classes)
  165. fieldName = ['IEI_',num2str(classes(cls_i))];
  166. iei_class=diff(spectralEvents(spectralEvents(:,eventsind.classLabels)==classes(cls_i),eventsind.maximatiming));
  167. sametrial_class=(diff(spectralEvents(spectralEvents(:,eventsind.classLabels)==classes(cls_i),eventsind.trialind)) == 0);
  168. IEI.(fieldName) = iei_class(sametrial_class);
  169. end
  170. % Assign output structure with 3 main branches: trial-level summary
  171. % (TrialSummary), trial-specific events (Events), and mean inter-event
  172. % interval across trials (IEI)
  173. specEv_struct.TrialSummary = struct('NumTrials',numTrials,'SpecialFeatures',specialFeat,'TrialSummary',trialSummary);
  174. specEv_struct.Events = struct('EventBand',eventBand,'ThrFOM',thrFOM,'MedianPower',medianpower,'Threshold',thr,'Events',struct(spectralEvents_columnlabel{1},spectralEvents(:,1),...
  175. spectralEvents_columnlabel{2},spectralEvents(:,2),spectralEvents_columnlabel{3},spectralEvents(:,3),spectralEvents_columnlabel{4},spectralEvents(:,4),...
  176. spectralEvents_columnlabel{5},spectralEvents(:,5),spectralEvents_columnlabel{6},spectralEvents(:,6),spectralEvents_columnlabel{7},spectralEvents(:,7),...
  177. spectralEvents_columnlabel{8},spectralEvents(:,8),spectralEvents_columnlabel{9},spectralEvents(:,9),spectralEvents_columnlabel{10},spectralEvents(:,10),...
  178. spectralEvents_columnlabel{11},spectralEvents(:,11),spectralEvents_columnlabel{12},spectralEvents(:,12)));
  179. specEv_struct.IEI = IEI;
  180. function find_localmax_method_1
  181. % 1st event-finding method (primary event detection method in Shin et
  182. % al. eLife 2017): Find spectral events by first retrieving all local
  183. % maxima in un-normalized TFR using imregionalmax, then selecting
  184. % suprathreshold peaks within the frequency band of interest. This
  185. % method allows for multiple, overlapping events to occur in a given
  186. % suprathreshold region and does not guarantee the presence of
  187. % within-band, suprathreshold activity in any given trial will render
  188. % an event.
  189. % spectralEvents: 12 column matrix for storing local max event metrics: trial
  190. % index, hit/miss, maxima frequency, lowerbound frequency, upperbound
  191. % frequency, frequency span, maxima timing, event onset timing, event
  192. % offset timing, event duration, maxima power, maxima/median power
  193. spectralEvents = [];
  194. % Finds_localmax: stores peak frequecy at each local max (columns) for each
  195. % trial (rows)
  196. Finds_localmax = [];
  197. % Retrieve all local maxima in TFR using imregionalmax
  198. for ti=1:numTrials
  199. [peakF,peakT] = find(imregionalmax(squeeze(TFR(:,:,ti)))); %Indices of max local power
  200. peakpower = TFR(find(imregionalmax(squeeze(TFR(:,:,ti))))+(ti-1)*flength*tlength); %Power values at local maxima (vector; compiles across frequencies and time)
  201. % Find local maxima lowerbound, upperbound, and full width at half max
  202. % for both frequency and time
  203. Ffwhm = NaN(numel(peakpower),3); %2D matrix for freq-dimension event metrics with columns containing lowerbound, upperbound, and fwhm, respectively
  204. Tfwhm = NaN(numel(peakpower),3); %2D matrix for time-dimension event metrics with columns containing lowerbound, upperbound, and fwhm, respectively
  205. for lmi=1:numel(peakpower)
  206. lmF_underthr = find(squeeze(TFR(:,peakT(lmi),ti) < peakpower(lmi)/2)); %Indices of TFR frequencies of < half max power at the time of a given local peak
  207. if ~isempty(find(lmF_underthr < peakF(lmi), 1)) && ~isempty(find(lmF_underthr > peakF(lmi), 1))
  208. Ffwhm(lmi,1) = fVec(lmF_underthr(find(lmF_underthr < peakF(lmi),1,'last'))+1);
  209. Ffwhm(lmi,2) = fVec(lmF_underthr(find(lmF_underthr > peakF(lmi),1,'first'))-1);
  210. Ffwhm(lmi,3) = Ffwhm(lmi,2)-Ffwhm(lmi,1)+ min(diff(fVec));
  211. elseif isempty(find(lmF_underthr < peakF(lmi),1)) && ~isempty(find(lmF_underthr > peakF(lmi),1))
  212. Ffwhm(lmi,1) = fVec(1);
  213. Ffwhm(lmi,2) = fVec(lmF_underthr(find(lmF_underthr > peakF(lmi),1,'first'))-1);
  214. Ffwhm(lmi,3) = 2*(Ffwhm(lmi,2)-fVec(peakF(lmi)))+ min(diff(fVec));
  215. elseif ~isempty(find(lmF_underthr < peakF(lmi),1)) && isempty(find(lmF_underthr > peakF(lmi),1))
  216. Ffwhm(lmi,1) = fVec(lmF_underthr(find(lmF_underthr < peakF(lmi),1,'last'))+1);
  217. Ffwhm(lmi,2) = fVec(end);
  218. Ffwhm(lmi,3) = 2*(fVec(peakF(lmi))-Ffwhm(lmi,1))+ min(diff(fVec));
  219. else
  220. Ffwhm(lmi,1) = fVec(1);
  221. Ffwhm(lmi,2) = fVec(end);
  222. Ffwhm(lmi,3) = 2*(fVec(end)-fVec(1)+min(diff(fVec)));
  223. end
  224. lmT_underthr = find(squeeze(TFR(peakF(lmi),:,ti) < peakpower(lmi)/2)); %Indices of TFR times of < half max power at the freq of a given local peak
  225. if ~isempty(find(lmT_underthr < peakT(lmi), 1)) && ~isempty(find(lmT_underthr > peakT(lmi), 1))
  226. Tfwhm(lmi,1) = tVec(lmT_underthr(find(lmT_underthr < peakT(lmi),1,'last'))+1);
  227. Tfwhm(lmi,2) = tVec(lmT_underthr(find(lmT_underthr > peakT(lmi),1,'first'))-1);
  228. Tfwhm(lmi,3) = Tfwhm(lmi,2)-Tfwhm(lmi,1)+ min(diff(tVec));
  229. elseif isempty(find(lmT_underthr < peakT(lmi),1)) && ~isempty(find(lmT_underthr > peakT(lmi),1))
  230. Tfwhm(lmi,1) = tVec(1);
  231. Tfwhm(lmi,2) = tVec(lmT_underthr(find(lmT_underthr > peakT(lmi),1,'first'))-1);
  232. Tfwhm(lmi,3) = 2*(Tfwhm(lmi,2)-tVec(peakT(lmi)))+ min(diff(tVec));
  233. elseif ~isempty(find(lmT_underthr < peakT(lmi),1)) && isempty(find(lmT_underthr > peakT(lmi),1))
  234. Tfwhm(lmi,1) = tVec(lmT_underthr(find(lmT_underthr < peakT(lmi),1,'last'))+1);
  235. Tfwhm(lmi,2) = tVec(end);
  236. Tfwhm(lmi,3) = 2*(tVec(peakT(lmi))-Tfwhm(lmi,1))+ min(diff(tVec));
  237. else
  238. Tfwhm(lmi,1) = tVec(1);
  239. Tfwhm(lmi,2) = tVec(end);
  240. Tfwhm(lmi,3) = 2*(tVec(end)-tVec(1)+min(diff(tVec)));
  241. end
  242. end
  243. % 12 column matrix with 1. trial index, 2. trial class, 3. maxima frequency, 4. lowerbound frequency, 5. upperbound frequency, 6. frequency span, ...
  244. % 7. maxima timing, 8. event onset timing, 9. event offset timing, 10. event duration, 11. maxima power, 12. maxima/median power, ...
  245. spectralEvents = [spectralEvents; ti*ones(size(peakF)) classLabels(ti)*ones(size(peakF)) fVec(peakF)' Ffwhm tVec(peakT)' Tfwhm peakpower peakpower./medianpower(peakF)];
  246. Finds_localmax = [Finds_localmax; peakF];
  247. end
  248. % Pick out maxima above threshold and within the frequency band of interest
  249. spectralEvents = spectralEvents((spectralEvents(:,3)>=eventBand(1) & spectralEvents(:,3)<=eventBand(2) & spectralEvents(:,11)>=thr(Finds_localmax)),:); %Select local maxima
  250. end
  251. function find_localmax_method_2
  252. % 2nd event-finding method: Find spectral events by first thresholding
  253. % entire normalize TFR (over all frequencies), then finding local
  254. % maxima. This method does not allow for overlapping events to occur in
  255. % a given suprathreshold region and does not guarantee the presence of
  256. % within-band, suprathreshold activity in any given trial will render
  257. % an event.
  258. % spectralEvents: 12 column matrix for storing local max event metrics: trial
  259. % index, hit/miss, maxima frequency, lowerbound frequency, upperbound
  260. % frequency, frequency span, maxima timing, event onset timing, event
  261. % offset timing, event duration, maxima power, maxima/median power
  262. spectralEvents = [];
  263. % Retrieve local maxima in normalized TFR using imregionalmax,
  264. % discard those of lesser (un-normalized) magnitude in each suprathreshold
  265. % region, respectively, and characterize event boundaries (at half max)
  266. for ti=1:numTrials
  267. TFR_ST = squeeze(TFR(:,:,ti))./medianpower; %Suprathreshold TFR: first isolate 2D TFR matrix and normalize
  268. TFR_ST(TFR_ST<thrFOM) = 0; %Set infrathreshold values to zero
  269. % Find all local maxima in suprathreshold TFR
  270. TFR_LM = TFR_ST.*imregionalmax(TFR_ST); %Threshold TFR at each respective local maximum
  271. numTotalPeaks = nnz(TFR_LM);
  272. % Escape this iteration when this trial contains no suprathreshold
  273. % local maxima
  274. if numTotalPeaks==0
  275. continue
  276. end
  277. % Find max peak in each respective suprathreshold region
  278. [~,regions,numReg,~] = bwboundaries(TFR_ST>=thrFOM); %Separate suprathreshold regions
  279. evPeakF = cell(1,numReg);
  280. evPeakT = cell(1,numReg);
  281. evPeakpower = nan(numReg,1);
  282. for reg_i=1:numReg
  283. region = zeros(size(TFR_ST)); %Initialize a blank image that will contain a single region
  284. region(regions==reg_i) = 1; %Set elements (pixels) in region to the value 1
  285. TFR_reg = TFR_LM.*region; %Regional local maxima
  286. [peakF_reg,peakT_reg] = find(TFR_reg); %Indices of regional local maxima
  287. peakpower_reg = TFR(find(TFR_reg)+(ti-1)*flength*tlength); %Power values at regional local maxima
  288. maxPeakpower = max(peakpower_reg);
  289. maxPeak_inds = find(peakpower_reg==maxPeakpower); %Indices of all instances where local maxima have the max peak power
  290. evPeakF{reg_i} = peakF_reg(maxPeak_inds); %Select TFR indices at max regional peak
  291. evPeakT{reg_i} = peakT_reg(maxPeak_inds); %Select TFR indices at max regional peak
  292. evPeakpower(reg_i) = maxPeakpower(1);
  293. end
  294. % Find local maxima lowerbound, upperbound, and full width at half max
  295. % for both frequency and time
  296. evBndsF = nan(numReg,3);
  297. evBndsT = nan(numReg,3);
  298. evPeakF_inds = nan(numReg,1);
  299. evPeakT_inds = nan(numReg,1);
  300. evPeakpower_norm = nan(numReg,1);
  301. for reg_i=1:numReg
  302. numRegPeaks = numel(evPeakF{reg_i});
  303. peakF = evPeakF{reg_i};
  304. peakT = evPeakT{reg_i};
  305. peakpower = evPeakpower(reg_i);
  306. Ffwhm = nan(numRegPeaks,3); %2D matrix for freq-dimension event metrics with columns containing lowerbound, upperbound, and fwhm, respectively
  307. Tfwhm = nan(numRegPeaks,3); %2D matrix for time-dimension event metrics with columns containing lowerbound, upperbound, and fwhm, respectively
  308. peakpower_norm = nan(numRegPeaks,1); %Vector for storing the normalized power at each regional peak
  309. for lmi=1:numRegPeaks
  310. lmF_underthr = find(squeeze(TFR(:,peakT(lmi),ti) < peakpower/2)); %Indices of TFR frequencies of < half max power at the time of a given local peak
  311. if ~isempty(find(lmF_underthr < peakF(lmi), 1)) && ~isempty(find(lmF_underthr > peakF(lmi), 1))
  312. Ffwhm(lmi,1) = fVec(lmF_underthr(find(lmF_underthr < peakF(lmi),1,'last'))+1);
  313. Ffwhm(lmi,2) = fVec(lmF_underthr(find(lmF_underthr > peakF(lmi),1,'first'))-1);
  314. Ffwhm(lmi,3) = Ffwhm(lmi,2)-Ffwhm(lmi,1)+ min(diff(fVec));
  315. elseif isempty(find(lmF_underthr < peakF(lmi),1)) && ~isempty(find(lmF_underthr > peakF(lmi),1))
  316. Ffwhm(lmi,1) = fVec(1);
  317. Ffwhm(lmi,2) = fVec(lmF_underthr(find(lmF_underthr > peakF(lmi),1,'first'))-1);
  318. Ffwhm(lmi,3) = 2*(Ffwhm(lmi,2)-fVec(peakF(lmi)))+ min(diff(fVec));
  319. elseif ~isempty(find(lmF_underthr < peakF(lmi),1)) && isempty(find(lmF_underthr > peakF(lmi),1))
  320. Ffwhm(lmi,1) = fVec(lmF_underthr(find(lmF_underthr < peakF(lmi),1,'last'))+1);
  321. Ffwhm(lmi,2) = fVec(end);
  322. Ffwhm(lmi,3) = 2*(fVec(peakF(lmi))-Ffwhm(lmi,1))+ min(diff(fVec));
  323. else
  324. Ffwhm(lmi,1) = fVec(1);
  325. Ffwhm(lmi,2) = fVec(end);
  326. Ffwhm(lmi,3) = 2*(fVec(end)-fVec(1)+min(diff(fVec)));
  327. end
  328. lmT_underthr = find(squeeze(TFR(peakF(lmi),:,ti) < peakpower/2)); %Indices of TFR times of < half max power at the freq of a given local peak
  329. if ~isempty(find(lmT_underthr < peakT(lmi), 1)) && ~isempty(find(lmT_underthr > peakT(lmi), 1))
  330. Tfwhm(lmi,1) = tVec(lmT_underthr(find(lmT_underthr < peakT(lmi),1,'last'))+1);
  331. Tfwhm(lmi,2) = tVec(lmT_underthr(find(lmT_underthr > peakT(lmi),1,'first'))-1);
  332. Tfwhm(lmi,3) = Tfwhm(lmi,2)-Tfwhm(lmi,1)+ min(diff(tVec));
  333. elseif isempty(find(lmT_underthr < peakT(lmi),1)) && ~isempty(find(lmT_underthr > peakT(lmi),1))
  334. Tfwhm(lmi,1) = tVec(1);
  335. Tfwhm(lmi,2) = tVec(lmT_underthr(find(lmT_underthr > peakT(lmi),1,'first'))-1);
  336. Tfwhm(lmi,3) = 2*(Tfwhm(lmi,2)-tVec(peakT(lmi)))+ min(diff(tVec));
  337. elseif ~isempty(find(lmT_underthr < peakT(lmi),1)) && isempty(find(lmT_underthr > peakT(lmi),1))
  338. Tfwhm(lmi,1) = tVec(lmT_underthr(find(lmT_underthr < peakT(lmi),1,'last'))+1);
  339. Tfwhm(lmi,2) = tVec(end);
  340. Tfwhm(lmi,3) = 2*(tVec(peakT(lmi))-Tfwhm(lmi,1))+ min(diff(tVec));
  341. else
  342. Tfwhm(lmi,1) = tVec(1);
  343. Tfwhm(lmi,2) = tVec(end);
  344. Tfwhm(lmi,3) = 2*(tVec(end)-tVec(1)+min(diff(tVec)));
  345. end
  346. peakpower_norm(lmi) = TFR_ST(peakF(lmi),peakT(lmi));
  347. end
  348. evBndsF(reg_i,:) = mean(Ffwhm,1);
  349. evBndsT(reg_i,:) = mean(Tfwhm,1);
  350. evPeakF_inds(reg_i) = round(mean(peakF));
  351. evPeakT_inds(reg_i) = round(mean(peakT));
  352. evPeakpower_norm(reg_i) = mean(peakpower_norm);
  353. end
  354. % 12 column matrix with 1. trial index, 2. trial class, 3. maxima frequency, 4. lowerbound frequency, 5. upperbound frequency, 6. frequency span, ...
  355. % 7. maxima timing, 8. event onset timing, 9. event offset timing, 10. event duration, 11. maxima power, 12. maxima/median power, ...
  356. spectralEvents = [spectralEvents; ti*ones(size(evPeakpower)) classLabels(ti)*ones(size(evPeakpower))...
  357. fVec(evPeakF_inds)' evBndsF tVec(evPeakT_inds)' evBndsT evPeakpower evPeakpower_norm];
  358. end
  359. % Pick out maxima within the frequency band of interest
  360. spectralEvents = spectralEvents((spectralEvents(:,3)>=eventBand(1) & spectralEvents(:,3)<=eventBand(2)),:); %Select local maxima
  361. end
  362. function find_localmax_method_3
  363. % 3rd event-finding method: Find spectral events by first thresholding
  364. % normalized TFR in frequency band of interest, then finding local
  365. % maxima. This method does not allow for overlapping events to occur in
  366. % a given suprathreshold region and ensures the presence of
  367. % within-band, suprathreshold activity in any given trial will render
  368. % an event.
  369. % spectralEvents: 12 column matrix for storing local max event metrics: trial
  370. % index, hit/miss, maxima frequency, lowerbound frequency, upperbound
  371. % frequency, frequency span, maxima timing, event onset timing, event
  372. % offset timing, event duration, maxima power, maxima/median power
  373. spectralEvents = [];
  374. % Retrieve local maxima in normalized TFR using imregionalmax,
  375. % discard those of lesser (un-normalized) magnitude in each suprathreshold
  376. % region, respectively, and characterize event boundaries (at half max)
  377. for ti=1:numTrials
  378. TFR_ST = squeeze(TFR(:,:,ti))./medianpower; %Suprathreshold TFR: first isolate 2D TFR matrix and normalize
  379. TFR_ST(TFR_ST<thrFOM) = 0; %Set infrathreshold values to zero
  380. TFR_ST = TFR_ST.*eventBand_inds; %Set out-of-band values to zero
  381. % Find all local maxima in suprathreshold TFR
  382. TFR_LM = TFR_ST.*imregionalmax(TFR_ST); %Threshold TFR at each respective local maximum
  383. numTotalPeaks = nnz(TFR_LM);
  384. % Escape this iteration when this trial contains no suprathreshold
  385. % local maxima
  386. if numTotalPeaks==0
  387. continue
  388. end
  389. % Find max peak in each respective suprathreshold region
  390. [~,regions,numReg,~] = bwboundaries(TFR_ST>=thrFOM); %Separate suprathreshold regions
  391. evPeakF = cell(1,numReg);
  392. evPeakT = cell(1,numReg);
  393. evPeakpower = nan(numReg,1);
  394. for reg_i=1:numReg
  395. region = zeros(size(TFR_ST)); %Initialize a blank image that will contain a single region
  396. region(regions==reg_i) = 1; %Set elements (pixels) in region to the value 1
  397. TFR_reg = TFR_LM.*region; %Regional local maxima
  398. [peakF_reg,peakT_reg] = find(TFR_reg); %Indices of regional local maxima
  399. peakpower_reg = TFR(find(TFR_reg)+(ti-1)*flength*tlength); %Power values at regional local maxima
  400. maxPeakpower = max(peakpower_reg);
  401. maxPeak_inds = find(peakpower_reg==maxPeakpower); %Indices of all instances where local maxima have the max peak power
  402. evPeakF{reg_i} = peakF_reg(maxPeak_inds); %Select TFR indices at max regional peak
  403. evPeakT{reg_i} = peakT_reg(maxPeak_inds); %Select TFR indices at max regional peak
  404. evPeakpower(reg_i) = maxPeakpower(1);
  405. end
  406. % Find local maxima lowerbound, upperbound, and full width at half max
  407. % for both frequency and time
  408. evBndsF = nan(numReg,3);
  409. evBndsT = nan(numReg,3);
  410. evPeakF_inds = nan(numReg,1);
  411. evPeakT_inds = nan(numReg,1);
  412. evPeakpower_norm = nan(numReg,1);
  413. for reg_i=1:numReg
  414. numRegPeaks = numel(evPeakF{reg_i});
  415. peakF = evPeakF{reg_i};
  416. peakT = evPeakT{reg_i};
  417. peakpower = evPeakpower(reg_i);
  418. Ffwhm = nan(numRegPeaks,3); %2D matrix for freq-dimension event metrics with columns containing lowerbound, upperbound, and fwhm, respectively
  419. Tfwhm = nan(numRegPeaks,3); %2D matrix for time-dimension event metrics with columns containing lowerbound, upperbound, and fwhm, respectively
  420. peakpower_norm = nan(numRegPeaks,1); %Vector for storing the normalized power at each regional peak
  421. for lmi=1:numRegPeaks
  422. lmF_underthr = find(squeeze(TFR(:,peakT(lmi),ti) < peakpower/2)); %Indices of TFR frequencies of < half max power at the time of a given local peak
  423. if ~isempty(find(lmF_underthr < peakF(lmi), 1)) && ~isempty(find(lmF_underthr > peakF(lmi), 1))
  424. Ffwhm(lmi,1) = fVec(lmF_underthr(find(lmF_underthr < peakF(lmi),1,'last'))+1);
  425. Ffwhm(lmi,2) = fVec(lmF_underthr(find(lmF_underthr > peakF(lmi),1,'first'))-1);
  426. Ffwhm(lmi,3) = Ffwhm(lmi,2)-Ffwhm(lmi,1)+ min(diff(fVec));
  427. elseif isempty(find(lmF_underthr < peakF(lmi),1)) && ~isempty(find(lmF_underthr > peakF(lmi),1))
  428. Ffwhm(lmi,1) = fVec(1);
  429. Ffwhm(lmi,2) = fVec(lmF_underthr(find(lmF_underthr > peakF(lmi),1,'first'))-1);
  430. Ffwhm(lmi,3) = 2*(Ffwhm(lmi,2)-fVec(peakF(lmi)))+ min(diff(fVec));
  431. elseif ~isempty(find(lmF_underthr < peakF(lmi),1)) && isempty(find(lmF_underthr > peakF(lmi),1))
  432. Ffwhm(lmi,1) = fVec(lmF_underthr(find(lmF_underthr < peakF(lmi),1,'last'))+1);
  433. Ffwhm(lmi,2) = fVec(end);
  434. Ffwhm(lmi,3) = 2*(fVec(peakF(lmi))-Ffwhm(lmi,1))+ min(diff(fVec));
  435. else
  436. Ffwhm(lmi,1) = fVec(1);
  437. Ffwhm(lmi,2) = fVec(end);
  438. Ffwhm(lmi,3) = 2*(fVec(end)-fVec(1)+min(diff(fVec)));
  439. end
  440. lmT_underthr = find(squeeze(TFR(peakF(lmi),:,ti) < peakpower/2)); %Indices of TFR times of < half max power at the freq of a given local peak
  441. if ~isempty(find(lmT_underthr < peakT(lmi), 1)) && ~isempty(find(lmT_underthr > peakT(lmi), 1))
  442. Tfwhm(lmi,1) = tVec(lmT_underthr(find(lmT_underthr < peakT(lmi),1,'last'))+1);
  443. Tfwhm(lmi,2) = tVec(lmT_underthr(find(lmT_underthr > peakT(lmi),1,'first'))-1);
  444. Tfwhm(lmi,3) = Tfwhm(lmi,2)-Tfwhm(lmi,1)+ min(diff(tVec));
  445. elseif isempty(find(lmT_underthr < peakT(lmi),1)) && ~isempty(find(lmT_underthr > peakT(lmi),1))
  446. Tfwhm(lmi,1) = tVec(1);
  447. Tfwhm(lmi,2) = tVec(lmT_underthr(find(lmT_underthr > peakT(lmi),1,'first'))-1);
  448. Tfwhm(lmi,3) = 2*(Tfwhm(lmi,2)-tVec(peakT(lmi)))+ min(diff(tVec));
  449. elseif ~isempty(find(lmT_underthr < peakT(lmi),1)) && isempty(find(lmT_underthr > peakT(lmi),1))
  450. Tfwhm(lmi,1) = tVec(lmT_underthr(find(lmT_underthr < peakT(lmi),1,'last'))+1);
  451. Tfwhm(lmi,2) = tVec(end);
  452. Tfwhm(lmi,3) = 2*(tVec(peakT(lmi))-Tfwhm(lmi,1))+ min(diff(tVec));
  453. else
  454. Tfwhm(lmi,1) = tVec(1);
  455. Tfwhm(lmi,2) = tVec(end);
  456. Tfwhm(lmi,3) = 2*(tVec(end)-tVec(1)+min(diff(tVec)));
  457. end
  458. peakpower_norm(lmi) = TFR_ST(peakF(lmi),peakT(lmi));
  459. end
  460. evBndsF(reg_i,:) = mean(Ffwhm,1);
  461. evBndsT(reg_i,:) = mean(Tfwhm,1);
  462. evPeakF_inds(reg_i) = round(mean(peakF));
  463. evPeakT_inds(reg_i) = round(mean(peakT));
  464. evPeakpower_norm(reg_i) = mean(peakpower_norm);
  465. end
  466. % 12 column matrix with 1. trial index, 2. trial class, 3. maxima frequency, 4. lowerbound frequency, 5. upperbound frequency, 6. frequency span, ...
  467. % 7. maxima timing, 8. event onset timing, 9. event offset timing, 10. event duration, 11. maxima power, 12. maxima/median power, ...
  468. spectralEvents = [spectralEvents; ti*ones(size(evPeakpower)) classLabels(ti)*ones(size(evPeakpower))...
  469. fVec(evPeakF_inds)' evBndsF tVec(evPeakT_inds)' evBndsT evPeakpower evPeakpower_norm];
  470. end
  471. end
  472. end

spectralevents_find.m at commit cd0c83d, under BSD-3-Clause · at the source

Overview

Authors: Christopher J. Black1, Carl Y. Saab2, David A. Borton1,3,4
ORCID iDs: David A. Borton
  1. School of Engineering, Brown University, Providence, RI 02912, USA
  2. Biomedical Engineering, Lerner Research Institute, Cleveland Clinic, Cleveland, OH 44195, USA
  3. Carney Institute for Brain Science, Brown University, Providence, RI 02912, USA
  4. Center for Neurorestoration and Neurotechnology, Rehabilitation R&D Service, Department of Veterans Affairs, Providence, RI 02908, USA
Institutions: Brown University (United States); Cleveland Clinic (United States); United States Department of Veterans Affairs (United States); Providence VA Medical Center (United States); Rehabilitation Research and Development Service (United States)
Journal: iScience, volume 29, issue 9, article 117355
Dates: received 10 October 2025; accepted 11 August 2026; published online 26 August 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1016/j.isci.2026.117355 · PMID 42699307 · PMCID PMC13544319 · OpenAlex W4361814259
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: systems (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Machine learning, Preprocessing, Spectral & time-frequency
Keywords: somatosensory cortex, gamma-band activity, sensory modality, sensory discrimination
Topic: Neural dynamics and brain function (Cognitive Neuroscience, Neuroscience), according to OpenAlex
Funding: NIH (MH115895); NINDS; BRAIN Initiative (1R01NS108414-01)
Citations: not cited yet (Europe PMC); 46 references in the paper
Research resources: Adult male mice RRID:IMSR_JAX:017769, Adult male mice RRID:IMSR_JAX:024109

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

Its files are read in the Code ↔ Paper reader above, with 3 matches between paragraphs and lines of code.

jonescompneurolab/SpectralEvents

License: BSD-3-Clause
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: cd0c83d2492446e03f1e58b79ed31bc73c024f22, 22 July 2024
Languages: MATLAB (6), Python (4), Jupyter (1)
Size: 69 files, 11 scripts
Software Heritage: not archived
Found in: the text, “Spectral event analysis”
Holds: README, license file, environment (requirements.txt, setup.cfg), tests, continuous integration, 1 notebook
Not found: CITATION.cff, documentation
Tools: NumPy (3 files), SciPy (3 files), Matplotlib (2 files), Image Processing Toolbox (1 file)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
13 files

The paper's code and data availability statement is in the Data section.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 11 scripts, each with its path and the digest of its content;
  • 3 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Code and data availability statement

The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • it points to a dataset: OSF gu3jr
  • it says that the data are available on request
  • it says that the code is available on request

Read it in the paper: doi.org/10.1016/j.isci.2026.117355.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 2, 28 September 2026

  • Authors: added David A. Borton (0000-0003-0710-3005); removed David A. Borton

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 3 authors, 4 keywords, 3 funders, 46 references, 2 RRIDs.

Cite

This paper

Black, C. J., Saab, C. Y., & Borton, D. A. (2026). Transient gamma events delineate somatosensory modality in S1. iScience, 29(9), 117355. https://doi.org/10.1016/j.isci.2026.117355

BibTeX

@article{black2026transient,
author = {Black, Christopher J. and Saab, Carl Y. and Borton, David A.},
title = {{Transient gamma events delineate somatosensory modality in S1}},
journal = {iScience},
year = {2026},
month = aug,
volume = {29},
number = {9},
pages = {117355},
publisher = {Elsevier},
issn = {2589-0042},
doi = {10.1016/j.isci.2026.117355},
url = {https://doi.org/10.1016/j.isci.2026.117355},
pmid = {42699307},
pmcid = {PMC13544319}
}

RIS

TY - JOUR
AU - Black, Christopher J.
AU - Saab, Carl Y.
AU - Borton, David A.
TI - Transient gamma events delineate somatosensory modality in S1
T2 - iScience
J2 - iScience
PY - 2026
DA - 2026/08/26
VL - 29
IS - 9
SP - 117355
SN - 2589-0042
PB - Elsevier
DO - 10.1016/j.isci.2026.117355
UR - https://doi.org/10.1016/j.isci.2026.117355
LA - en
ER -

CSL-JSON

{
"id": "10.1016/j.isci.2026.117355",
"type": "article-journal",
"title": "Transient gamma events delineate somatosensory modality in S1",
"container-title": "iScience",
"author": [
{
"family": "Black",
"given": "Christopher J."
},
{
"family": "Saab",
"given": "Carl Y."
},
{
"family": "Borton",
"given": "David A."
}
],
"container-title-short": "iScience",
"volume": "29",
"issue": "9",
"page": "117355",
"DOI": "10.1016/j.isci.2026.117355",
"PMID": "42699307",
"PMCID": "PMC13544319",
"ISSN": "2589-0042",
"publisher": "Elsevier",
"URL": "https://doi.org/10.1016/j.isci.2026.117355",
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
26
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1097/j.pain.0000000000004044 [code]
No effect of rhythmic visual stimulation on experimental pain perception.
Journal: Pain
In common: SciPy, Matplotlib, NumPy, 4 references
[2] doi:10.1016/j.isci.2026.116152 [code]
Integrating multidimensional nociceptive-related cortical features for unsupervised assessment of anesthesia states in rats.
Journal: iScience
In common: 5 references
[3] doi:10.3390/bioengineering13070793
Vibrotactile Stimulation Encoded by Beta and Gamma Bands Varies with Locations on the Upper Limbs.
Journal: Bioengineering (Basel, Switzerland)
In common: 3 references
[4] doi:10.1371/journal.pcbi.1014378 [code]
A mean-field model of neural networks with PV and SOM interneurons reveals connectivity-based mechanisms of gamma oscillations.
Journal: PLoS computational biology
In common: SciPy, Matplotlib, NumPy, 2 references
[5] doi:10.1093/braincomms/fcag145 [code]
GABA&lt;sub&gt;A&lt;/sub&gt; binding correlates with high-frequency EEG: a possible proxy for depolarization in traumatic brain injury.
Journal: Brain communications
In common: SciPy, Matplotlib, NumPy, 2 references
[6] doi:10.1016/j.celrep.2026.117845 [code]
Hippocampal skill memory expansion drives online performance dynamics during skill learning.
Journal: Cell reports
In common: Image Processing Toolbox, SciPy, Matplotlib, 1 other tool, 1 reference
[7] doi:10.1162/imag.a.1229 [code]
40 Hz audiovisual stimulation improves sustained attention and related brain oscillations.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: Image Processing Toolbox, SciPy, Matplotlib, 1 other tool, 1 reference
[8] doi:10.1371/journal.pbio.3003824 [code]
Flexible goal learning involves coordinated population activity in dCA1 and medial orbitofrontal cortex.
Journal: PLoS biology
In common: SciPy, Matplotlib, NumPy, systems, 1 reference
[9] doi:10.7554/elife.108408 [code]
Frequency and laminar profile of feature-specific visual activity revealed by interleaved EEG-fMRI.
Journal: eLife
In common: Image Processing Toolbox, SciPy, Matplotlib, 1 other tool, systems
[10] doi:10.1016/j.isci.2026.117375 [code]
Motor priming is associated with widespread recruitment into neural ensembles and more rapid ensemble transitions.
Journal: iScience
In common: Image Processing Toolbox, SciPy, Matplotlib, 1 other tool, systems

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.