spikeTrigAvg_postsyn.m 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. function varargout = spikeTrigAvg_postsyn(files, varargin)
  2. %% Calculate spike triggered average of the postsynaptic response
  3. % For each spike in the stimulated cell the membrane potential of the not
  4. % stimulated cell is gathered and summed up from 5 ms before to 30 ms after
  5. % the spike. Devided by the number of spikes the averaged postsynaptic
  6. % membrane potential is obtained. If there is a clear peak (due to EPSPs
  7. % for example), the time of this peak is determined as the latency of the
  8. % reaction to the spike in the other cell. The latency and the number of
  9. % used spikes are returned. Alternatively the result can be plotted. The
  10. % function can handle multiple files at a time.
  11. % -------------------------------------------------------------------------
  12. % Input [additional arguments are positional,
  13. % ----- optional arguments are name-value pairs]
  14. %
  15. % file: number(s) of the '.mat' file(s) in the directory,
  16. % type: integer or vector
  17. % trials: number(s) of the trials to be analysed, type: integer
  18. % (additional) of vector, default: 'all'
  19. % Filter: select between three filter options:
  20. % (optional) 'hn' applys a hum-noise-remove filter
  21. % 'hnhfn' additonally applys a low pass filter to
  22. % remove high frequency noise
  23. % If not set, no filter will be applyed (default).
  24. % MinPeakPromT: set the value for 'MinPeakProminence' which is used in
  25. % (optional) the 'findpeaks' function to find T-cell peaks.
  26. % Default: 17
  27. % StimCell: set whether the data for a stimulated T cell or a
  28. % (optional) stimulated interneuron should be used.
  29. % 'INT' for the interneuron
  30. % 'T' for the T-cell (default)
  31. % ------
  32. % Output
  33. % ------
  34. % varargout{1}: latency from spike of the stimulated cell to peak in
  35. % average response of the not stimullated cell (no plot)
  36. % type: float (single file) or vector (multiple
  37. % files)
  38. % varargout{2}: number of spikes used from the stimulated cell
  39. % type: float (single file) or vector (multiple
  40. % files)
  41. %
  42. % visually output of the plot, if no output variable set
  43. % -------------------------------------------------------------------------
  44. % Program by: Bjarne Schultze [last modified 02.03.2022]
  45. % -------------------------------------------------------------------------
  46. %% Preparations
  47. % parse the user input
  48. [file_nums, trials, filter_choice, ~, MinPeakPromT, ...
  49. stimCell, ~,~,~] = parse_input_peakfun(files, varargin{:});
  50. % extract the requested data
  51. recData = extract_data(file_nums, filter_choice);
  52. % pre-define vectors for the output (optional)
  53. if nargout > 0
  54. latencies = zeros(length(file_nums),1);
  55. spikesNum = zeros(length(file_nums),1);
  56. end
  57. % iterate through the single files as requested by the input
  58. for file = 1:length(file_nums)
  59. % get the number or trials for the current file
  60. trial_count = size(recData{file,1}.recordingT,2);
  61. % set the length of the time frame to gather the triggered data
  62. trig_len = 0.03; % in seconds
  63. trig_len_dp = trig_len * 10000; % in datapoints
  64. % distinguish between a stimulated T cell and a stimulated interneuron
  65. if isequal(stimCell, "INT")
  66. % get the columns with data for a stimulated interneuron
  67. stimulated = setdiff(1:trial_count, recData{file,1}.stimulatedT(:), ...
  68. 'stable');
  69. % select the requested trials, ensure only valid trials
  70. if ~isequal(trials, 'all')
  71. stimulated = intersect(stimulated,trials);
  72. end
  73. % set an appropriate plot title
  74. plot_title = sprintf("Postsynaptic Spike Response - File: " + ...
  75. "%02.f - Interneuron stimulated", file_nums(file));
  76. % assign the data to working variables
  77. recDataNSTIM = recData{file,1}.recordingT(:,stimulated);
  78. recDataSTIM = recData{file,1}.recordingINT(:,stimulated);
  79. else
  80. % get the columns with data for a stimulated T-cell
  81. stimulated = recData{file,1}.stimulatedT(:);
  82. % select the requested trials, ensure only valid trials
  83. if ~isequal(trials, 'all')
  84. stimulated = intersect(stimulated,trials);
  85. end
  86. % set an appropriate plot title
  87. plot_title = sprintf("Postsynaptic Spike Response - File: " + ...
  88. "%02.f - T-cell stimulated", file_nums(file));
  89. % assign the data to working variables
  90. recDataSTIM = recData{file,1}.recordingT(:,stimulated);
  91. recDataNSTIM = recData{file,1}.recordingINT(:,stimulated);
  92. MinPeakPromSTIM = MinPeakPromT;
  93. end
  94. %% Main calculations
  95. % pre-define a variable to sum up the triggered membrane potentials
  96. triggered_sum = 0;
  97. spike_counter = 0;
  98. % iterate through the trials
  99. for exp = 1:length(stimulated)
  100. % search for spikes in the stimulated cell
  101. if isequal(stimCell, 'INT')
  102. [~,spike_indexSTIM_all] = findIntSpikes(recDataSTIM(:,exp));
  103. else
  104. [~, spike_indexSTIM_all] = findpeaks(recDataSTIM(:,exp), ...
  105. 'MinPeakProminence', MinPeakPromSTIM);
  106. end
  107. % exclude spikes at the very beginning and the end of one recording
  108. % to ensure a complete time frame for the triggered data
  109. spike_indexSTIM_sel = spike_indexSTIM_all > 50 & ...
  110. spike_indexSTIM_all < (size(recDataSTIM,1) - trig_len_dp);
  111. spike_indexSTIM = spike_indexSTIM_all(spike_indexSTIM_sel);
  112. % if no spikes are found the next trial is examined
  113. if isempty(spike_indexSTIM)
  114. continue
  115. else
  116. % select the membrane potentail of the not-stimulated cell in
  117. % an index frame of the length 'trig_len_dp' datapoints for
  118. % each spike of the stimulated cell
  119. for spike = 1:length(spike_indexSTIM)
  120. % select the data (triggered by a spike)
  121. triggered_data = ...
  122. recDataNSTIM((spike_indexSTIM(spike)-50):...
  123. (spike_indexSTIM(spike) + trig_len_dp), exp);
  124. % sum up the data
  125. triggered_sum = triggered_sum + triggered_data;
  126. end
  127. % count the spikes
  128. spike_counter = spike_counter + spike;
  129. end
  130. end
  131. % calculate the averaged postsynaptic membrane potential if more than 8
  132. % spikes were found in the T cell
  133. if spike_counter < 8
  134. afterSpkAvg = NaN;
  135. fprintf("File %g: Not enough T cell spikes (n < 8)!\n", ...
  136. file_nums(file))
  137. else
  138. afterSpkAvg = triggered_sum ./ spike_counter;
  139. % create a time vector for the selected data
  140. timeVector = [sort(-recData{file,1}.timeVector(1:50)); 0;...
  141. recData{file,1}.timeVector(1:trig_len_dp)];
  142. timeVector = timeVector * 1000; % in ms
  143. % find the peaks in the average spike response if there are some
  144. [peaks, locs] = findpeaks(afterSpkAvg, timeVector, ...
  145. 'MinPeakProminence',0.05);
  146. % exclude peaks with locations before zero
  147. sel_peaks = peaks(locs > 0); sel_locs = locs(locs > 0);
  148. % select peaks that are by at least 0.2 mV bigger than value at 0
  149. search_peaks = sel_peaks > (afterSpkAvg(51)+0.2);
  150. % subset the peak and corresponding location values
  151. sel_peaks = sel_peaks(search_peaks);
  152. sel_locs = sel_locs(search_peaks);
  153. % select the peak with the location closest to zero
  154. % firstPeak_l is giving the latency (delay of the reaction to the
  155. % spike in the stimulated cell)
  156. [firstPeak_l,index] = min(sel_locs);
  157. firstPeak_v = sel_peaks(index);
  158. end
  159. %% Plotting of the result and output
  160. % suitable output based on whether calculations were made (n >= 8) and
  161. % based on the number of output variables
  162. if nargout > 0 && spike_counter >=8
  163. % return the latency (firstPeak_l) if determined
  164. if isempty(firstPeak_l)
  165. latencies(file,1) = NaN;
  166. else
  167. latencies(file,1) = firstPeak_l;
  168. end
  169. % return the number of spikes used to the second output variable
  170. if nargout > 1
  171. spikesNum(file,1) = spike_counter;
  172. end
  173. elseif spike_counter >= 8
  174. % plot the averaged postsynaptic membrane potential
  175. figure();
  176. plot(timeVector, afterSpkAvg);
  177. title(plot_title);
  178. xlabel("time after spike [ms]");
  179. ylabel("average membrane potentail [mV]");
  180. % add a reference line at zero
  181. xline(0, 'Color', [0.6,0.6,0.6]);
  182. % add the distance from zero to the measured peak if determined
  183. if ~isempty(firstPeak_v)
  184. % set the coordinates for line and text
  185. distanceLine = [0,firstPeak_l];
  186. text_X = firstPeak_l/2; text_Y = firstPeak_v*0.997;
  187. % add the text
  188. text_T = sprintf("%g ms", firstPeak_l);
  189. text(text_X, text_Y, text_T, 'FontSize', 12, 'Color', ...
  190. [0.6,0.6,0.6]);
  191. % add the distance line
  192. hold on;
  193. plot(distanceLine, [firstPeak_v,firstPeak_v], '|-', ...
  194. 'Color', [0.6,0.6,0.6])
  195. hold off;
  196. % adjust the limits of the y-axis
  197. max_data = max(afterSpkAvg);
  198. min_data = min(afterSpkAvg);
  199. range_data = abs(max_data-min_data);
  200. ylim([(min_data-range_data*0.1),(max_data+range_data*0.1)]);
  201. end
  202. else
  203. % give back NaN for no result
  204. latencies(file,1) = NaN;
  205. end
  206. % end of outer for loop (iteration through files)
  207. end
  208. % return the output values if requested
  209. if nargout > 0
  210. varargout{1} = latencies;
  211. if nargout > 1
  212. varargout{2} = spikesNum;
  213. end
  214. end
  215. % end of function definition
  216. end