intSpikeHeight.m 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. function varargout = intSpikeHeight(files, varargin)
  2. %% Function to measure the amplitude of interneuron spikes
  3. % This function is written to detect spikes in interneuron recordings and
  4. % obtain their mean amplitude. A three step mechanism is used to
  5. % distinguish the spikes from noise or other rapid changes in the membrane
  6. % potential. If requested a plot is generated showing the selected peaks
  7. % (set the plotflag to 1). The function can handle multiple files at a
  8. % time.
  9. % -------------------------------------------------------------------------
  10. % Input [additional arguments are positional,
  11. % ----- optional arguments are name-value pairs]
  12. %
  13. % file: ID(s) of the file(s) in the 'CleanDatasets' folder
  14. % type: integer or vector
  15. % trials: select which trials should be used, default: 'all'
  16. % (additional) type: integer or vector
  17. % PlotFlag: select if a plot should be created for each trial
  18. % (optional) showing the detected peaks. 0 (no plots, default),
  19. % 1 (plots)
  20. % ------
  21. % Output
  22. % ------
  23. % varargout{1}: measured average spike amplitude
  24. % varargout{2}: standard deviation across all spikes of one cell
  25. % -------------------------------------------------------------------------
  26. % Program by: Bjarne Schultze [last modified: 20.01.2022]
  27. % -------------------------------------------------------------------------
  28. %% Preparations
  29. % parse the user input
  30. [fileNums, trials, ~,~,~,~,~,~, plotflag] = ...
  31. parse_input_peakfun(files, varargin{:});
  32. % access the data using the function 'extract_data', filtering hum noise
  33. recData = extract_data(fileNums,'hn');
  34. % preallocate vectors to gather the results
  35. m_prom = zeros(length(fileNums),1);
  36. sd_prom = zeros(length(fileNums),1);
  37. %% Main calculations
  38. % iterate through the requested files
  39. for file = 1:length(fileNums)
  40. % get the number of trials where the interneuron was stimulated
  41. trialNum = size(recData{file,1}.recordingINT,2);
  42. stimulated = setdiff(1:trialNum, recData{file,1}.stimulatedT(:), ...
  43. 'stable');
  44. % select single trials if requested
  45. if ~isequal(trials, 'all')
  46. stimulated = intersect(stimulated,trials);
  47. end
  48. % iterate through the trials computing the mean spike height/prominence
  49. for trial_index = 1:length(stimulated)
  50. % access the data of the current trial
  51. trial = stimulated(trial_index);
  52. dataINT = recData{file,1}.recordingINT(:,trial);
  53. % find the peaks in the data
  54. [peak_values, locations, ~, prom] = findpeaks(dataINT,...
  55. 'Annotate','extents', 'WidthReference','halfprom',...
  56. 'MinPeakProminence', 1,'MaxPeakWidth',200);
  57. % preassign a vector to gather the quater prominence width
  58. qprom_width = zeros(length(peak_values),1);
  59. % measure the peak width at one quarter of the prominence for each
  60. % spike (default would be half prom)
  61. for spike = 1:length(peak_values)
  62. % set the quarter prom as reference value for width measurement
  63. measure_level = peak_values(spike) - 0.25*prom(spike);
  64. % select a window of 100 datapoints around the current spike if
  65. % possible, otherwise a one-sided smaller window
  66. if locations(spike) < 51
  67. spikeData = dataINT(1:locations(spike)+50);
  68. spikeLoc = locations(spike);
  69. elseif locations(spike)+50 > locations(end)
  70. spikeData = dataINT(locations(spike)-50:end);
  71. spikeLoc = 51;
  72. else
  73. spikeData = ...
  74. dataINT(locations(spike)-50:locations(spike)+50);
  75. spikeLoc = 51;
  76. end
  77. % devide the points in left and right of the peak
  78. dataL = spikeData(1:spikeLoc);
  79. dataR = spikeData(spikeLoc+1:end);
  80. % take the points (left and right) that are closest to the
  81. % measure level of a quarter of the prominence
  82. [~,minL] = min((dataL - measure_level), [], ...
  83. 'ComparisonMethod','abs');
  84. [~,minR] = min((dataR - measure_level), [], ...
  85. 'ComparisonMethod','abs');
  86. % calculate the final width at quarter peak prominence
  87. qprom_width(spike) = minR + spikeLoc - minL;
  88. end
  89. % sort and select the all found peaks in a 3-step algorithm
  90. % 1st step: exclude every peak beneath the overall mean +1 mV
  91. select_peaks = peak_values > mean(dataINT)+1;
  92. peaks_subset1 = peak_values(select_peaks);
  93. % select the corresponding values/properties
  94. locs_subset1 = locations(select_peaks);
  95. qprom_width_subset1 = qprom_width(select_peaks);
  96. prom_subset1 = prom(select_peaks);
  97. % 2nd step: select only peaks with a quarter peak prom over 4 and
  98. % under 45
  99. select_peaks = 4 < qprom_width_subset1 & qprom_width_subset1 < 45;
  100. peaks_subset2 = peaks_subset1(select_peaks);
  101. % select the coorresponding values/properties
  102. locs_subset2 = locs_subset1(select_peaks);
  103. prom_subset2 = prom_subset1(select_peaks);
  104. % 3rd step: exclude the peaks smaller than 20% of the largest peak
  105. select_peaks = prom_subset2 > max(prom_subset2)*0.2;
  106. peaks_subset3 = peaks_subset2(select_peaks);
  107. % select the corresponding values/properties
  108. locs_subset3 = locs_subset2(select_peaks);
  109. prom_subset3 = prom_subset2(select_peaks);
  110. % add the prominence values to the all_proms vector
  111. if eq(trial_index,1)
  112. all_proms = prom_subset3;
  113. else
  114. all_proms = [all_proms;prom_subset3];
  115. end
  116. % plot the peaks that are found plus their prominence and width
  117. if plotflag
  118. % create appropriate title
  119. plot_title = sprintf("File %g - trial %g", fileNums(file), ...
  120. trial);
  121. figure
  122. findpeaks(dataINT, 10000,...
  123. 'Annotate','extents', 'WidthReference','halfprom',...
  124. 'MinPeakProminence', 1,'MaxPeakWidth',200);
  125. locs_subset3_plot = locs_subset3 / 10000;
  126. hold on; plot(locs_subset3_plot, peaks_subset3, 'og'); hold off;
  127. title(plot_title)
  128. xlabel("time [s]"); ylabel("membrane potential [mV]")
  129. legend('signal','peaks from findpeaks function','prominence',...
  130. 'width (half-prominence)',['peaks identified as ' ...
  131. 'action potentials'], 'Location', 'southeast')
  132. end
  133. % end of iteration through the trials
  134. end
  135. % calculate mean and sd over all spikes from all trials
  136. m_prom(file,1) = mean(all_proms, 'omitnan');
  137. sd_prom(file,1) = std(all_proms, 'omitnan');
  138. % end of iteration through the files
  139. end
  140. % return mean and sd values
  141. varargout{1} = m_prom;
  142. if nargout > 1
  143. varargout{2} = sd_prom;
  144. end
  145. % end of function definition
  146. end