intSpikeHeight_trend.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. function intSpikeHeight_trend(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, ~,~,~,~,~,~, ~] = ...
  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. %% Main calculations
  35. % iterate through the requested files
  36. for file = 1:length(fileNums)
  37. % get the number of trials where the interneuron was stimulated
  38. trialNum = size(recData{file,1}.recordingINT,2);
  39. stimulated = setdiff(1:trialNum, recData{file,1}.stimulatedT(:), ...
  40. 'stable');
  41. % select single trials if requested
  42. if ~isequal(trials, 'all')
  43. stimulated = intersect(stimulated,trials);
  44. end
  45. % iterate through the trials computing the mean spike height/prominence
  46. for trial_index = 1:length(stimulated)
  47. % access the data of the current trial
  48. trial = stimulated(trial_index);
  49. dataINT = recData{file,1}.recordingINT(:,trial);
  50. % find the peaks in the data
  51. [peak_values, locations, ~, prom] = findpeaks(dataINT,...
  52. 'Annotate','extents', 'WidthReference','halfprom',...
  53. 'MinPeakProminence', 1,'MaxPeakWidth',200);
  54. % preassign a vector to gather the quater prominence width
  55. qprom_width = zeros(length(peak_values),1);
  56. % measure the peak width at one quarter of the prominence for each
  57. % spike (default would be half prom)
  58. for spike = 1:length(peak_values)
  59. % set the quarter prom as reference value for width measurement
  60. measure_level = peak_values(spike) - 0.25*prom(spike);
  61. % select a window of 100 datapoints around the current spike if
  62. % possible, otherwise a one-sided smaller window
  63. if locations(spike) < 51
  64. spikeData = dataINT(1:locations(spike)+50);
  65. spikeLoc = locations(spike);
  66. elseif locations(spike)+50 > locations(end)
  67. spikeData = dataINT(locations(spike)-50:end);
  68. spikeLoc = 51;
  69. else
  70. spikeData = ...
  71. dataINT(locations(spike)-50:locations(spike)+50);
  72. spikeLoc = 51;
  73. end
  74. % devide the points in left and right of the peak
  75. dataL = spikeData(1:spikeLoc);
  76. dataR = spikeData(spikeLoc+1:end);
  77. % take the points (left and right) that are closest to the
  78. % measure level of a quarter of the prominence
  79. [~,minL] = min((dataL - measure_level), [], ...
  80. 'ComparisonMethod','abs');
  81. [~,minR] = min((dataR - measure_level), [], ...
  82. 'ComparisonMethod','abs');
  83. % calculate the final width at quarter peak prominence
  84. qprom_width(spike) = minR + spikeLoc - minL;
  85. end
  86. % sort and select the all found peaks in a 3-step algorithm
  87. % 1st step: exclude every peak beneath the overall mean +1 mV
  88. select_peaks = peak_values > mean(dataINT)+1;
  89. % select the corresponding values/properties
  90. qprom_width_subset1 = qprom_width(select_peaks);
  91. prom_subset1 = prom(select_peaks);
  92. % 2nd step: select only peaks with a quarter peak prom over 4 and
  93. % under 45
  94. select_peaks = 4 < qprom_width_subset1 & qprom_width_subset1 < 45;
  95. % select the coorresponding values/properties
  96. prom_subset2 = prom_subset1(select_peaks);
  97. % 3rd step: exclude the peaks smaller than 20% of the largest peak
  98. select_peaks = prom_subset2 > max(prom_subset2)*0.2;
  99. % select the corresponding values/properties
  100. prom_subset3 = prom_subset2(select_peaks);
  101. % add the prominence values to the all_proms vector
  102. if eq(trial_index,1)
  103. all_proms = prom_subset3;
  104. else
  105. all_proms = [all_proms;prom_subset3];
  106. end
  107. % end of iteration through the trials
  108. end
  109. % calculate mean and sd over all spikes from all trials
  110. m_prom = mean(all_proms, 'omitnan');
  111. sd_prom = std(all_proms, 'omitnan');
  112. % define borders (mean +- sd) to fill
  113. fillX = [1, length(all_proms), length(all_proms), 1, 1];
  114. fillY = [(m_prom+sd_prom), (m_prom+sd_prom),(m_prom-sd_prom), ...
  115. (m_prom-sd_prom),(m_prom+sd_prom)];
  116. % plot the spike amplitudes over the index
  117. figure();
  118. plot(1:length(all_proms), all_proms)
  119. yline(m_prom, 'Color', [0 0.55 0], 'LineWidth', 2)
  120. yline((m_prom+sd_prom), 'Color', [1 0.67 0])
  121. yline((m_prom-sd_prom), 'Color', [1 0.67 0])
  122. % add an filled panel around the mean indicating one sd
  123. hold on;
  124. fill(fillX, fillY, [1 0.67 0], 'FaceAlpha', 0.2, 'LineStyle', 'none')
  125. hold off;
  126. % adapt the x limit
  127. xlim([0,length(all_proms)])
  128. % labelling
  129. xlabel("spike index over all trials");
  130. ylabel("spike amplitude [mV]")
  131. legend("spike amplitudes", "mean", sprintf("mean \x00B1 sd"))
  132. title(sprintf("Variation of the measured spike amplitude - " + ...
  133. "File: %g", fileNums(file)))
  134. % end of iteration through the files
  135. end
  136. % end of function definition
  137. end