sta.m 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. function[s,t,E] = sta(data_spk,data_lfp,smp,plt,w,T,D,err)
  2. % Spike Triggered Average
  3. % Usage: [s,t,E] = sta(data_spk,data_lfp,smp,plt,w,T,D,err)
  4. %
  5. % Inputs
  6. %
  7. % Note that all times have to be consistent. If data_spk
  8. % is in seconds, so must be sig and t. If data_spk is in
  9. % samples, so must sig and t. The default is seconds.
  10. %
  11. % data_spk - strucuture array of spike times data
  12. % or NaN padded matrix
  13. % data_lfp - array of lfp data(samples x trials)
  14. %
  15. % Optional...
  16. % plt 'n'|'r' etc
  17. % width kernel smoothing in s
  18. % T = [-0.1 0.1] - extract this range about each spk
  19. % D = plot spike triggered average out to [D1 D2]
  20. % err = calcluate error bars (bootstrap)
  21. %
  22. % Outputs:
  23. %
  24. % s spike triggered average
  25. % t times
  26. % E bootstrap standard err
  27. if nargin < 3;error('Require spike, lfp and lfp times');end
  28. if isstruct(data_spk)
  29. [data_spk]=padNaN(data_spk); % create a zero padded data matrix from input structural array
  30. sz=size(data_spk);
  31. if sz(1)>sz(2); data_spk=data_spk'; end;% transpose data to get in form compatible with Murray's routine
  32. else
  33. sz=size(data_spk);
  34. if sz(1)>sz(2); data_spk=data_spk'; end;% transpose data to get in form compatible with Murray's routine
  35. end
  36. sz=size(data_lfp);
  37. if sz(1)>sz(2); data_lfp=data_lfp'; end;% transpose data to get in form compatible with Murray's routine
  38. verbose = 1;
  39. t = smp;
  40. if nargin < 4; plt = 'r'; end
  41. if nargin < 5; w = 0; end
  42. if nargin < 6; T = [min(t) max(t)]; end
  43. if nargin < 7; D = 0.25*[-1 1]; end
  44. if nargin < 8; err = 1;end
  45. if isempty(plt); plt = 'r'; end
  46. if isempty(w); w = 0; end
  47. if isempty(T); T = [min(t) max(t)]; end
  48. if isempty(D); D = 0.25*[-1 1]; end
  49. if isempty(err); err = 1;end
  50. if w > (T(2)-T(1))/2
  51. disp('Smoothing > data segment : should be in seconds : turn off smoothing')
  52. w = 0;
  53. end
  54. sz = size(data_spk);
  55. NT = sz(1);
  56. mlfp = 0;
  57. slfp = 0;
  58. Nspk = 0;
  59. smp = t(2)-t(1);
  60. if D(1) <= 0 && D(2) >= 0
  61. t1 = [D(1):smp:(-smp+eps) 0:smp:D(2)+eps];
  62. else
  63. t1 = (round(D(1)/smp)*smp):smp:D(2);
  64. end
  65. % count up the spikes...
  66. if err
  67. for n=1:NT
  68. indx = find(t>T(1)&t<T(2));
  69. % lfp = data_lfp(n,indx);
  70. spk = data_spk(n,data_spk(n,:)>T(1) && data_spk(n,:)<T(2) && data_spk(n,:)~=0);
  71. tt = t(indx);
  72. if ~isempty(spk) > 0
  73. ND = length(spk);
  74. for s=1:ND
  75. spktime = spk(s);
  76. t0 = tt-spktime + eps;
  77. if min(t0)>(D(1)-smp) || max(t0)<(D(2)+smp); break;end
  78. Nspk = Nspk + 1;
  79. end
  80. end
  81. end
  82. Err = zeros(Nspk,length(t1));
  83. Nspk = 0;
  84. end
  85. for n=1:NT
  86. indx = find(t>T(1)&t<T(2));
  87. lfp = data_lfp(n,indx);
  88. spk = data_spk(n,data_spk(n,:)>T(1) && data_spk(n,:)<T(2) && data_spk(n,:)~=0);
  89. tt = t(indx);
  90. if ~isempty(spk) > 0
  91. ND = length(spk);
  92. for s=1:ND
  93. spktime = spk(s);
  94. t0 = tt-spktime + eps;
  95. if min(t0) < (D(1)-smp) && max(t0) > (D(2)+smp);
  96. indx = find(t0<D(1));
  97. indx = indx(length(indx));
  98. offset = (t0(indx)-D(1))/smp;
  99. indx = indx:(indx+length(t1)-1);
  100. lfp_t1 = lfp(indx) + (lfp(indx+1)-lfp(indx))*offset;
  101. Nspk = Nspk + 1;
  102. mlfp = mlfp + lfp_t1;
  103. slfp = slfp + lfp_t1.^2;
  104. Err(Nspk,:) = lfp_t1;
  105. end
  106. end
  107. end
  108. end
  109. if Nspk == 0
  110. if verbose;disp('No spikes in interval');end
  111. t = t1;
  112. s = zeros(length(t),1);
  113. E = zeros(length(t),1);
  114. return
  115. end
  116. mlfp = mlfp/Nspk;
  117. slfp = slfp/Nspk;
  118. stdlfp = sqrt((slfp - mlfp.^2)/Nspk);
  119. % local smoother...
  120. N = fix(w/smp);
  121. if N > 5
  122. mlfp = locsmooth(mlfp,N,fix(N/2));
  123. end
  124. % bootstrap errorbars...
  125. if err == 1;
  126. Nboot = 20;
  127. blfp = 0;
  128. slfp = 0;
  129. for n = 1:Nboot
  130. indx = floor(Nspk*rand(1,Nspk)) + 1;
  131. lfptmp = mean(Err(indx,:));
  132. if N > 5
  133. lfptmp = locsmooth(lfptmp,N,fix(N/2));
  134. end
  135. blfp = blfp + lfptmp;
  136. slfp = slfp + lfptmp.^2;
  137. end
  138. stdlfp = sqrt((slfp/Nboot - blfp.^2/Nboot^2));
  139. end
  140. s = mlfp-mean(mlfp);
  141. E = stdlfp;
  142. t = t1;
  143. %cols = 'krbgycm';
  144. if plt == 'n';return;end
  145. plot(t1,s,plt)
  146. xax = get(gca,'xlim');
  147. %yax = get(gca,'ylim');
  148. if err == 1
  149. me = real(2*mean(stdlfp));
  150. line(xax,me*[1 1],'color','b')
  151. line(xax,-me*[1 1],'color','b')
  152. line(xax,0*[1 1],'color','k')
  153. % errorbar(0.1*xax(2)+0.9*xax(1),0.1*yax(2)+0.9*yax(1), ...
  154. % mean(stdlfp),'k')
  155. %plot(0.1*xax(2)+0.9*xax(1),0.1*yax(2)+0.9*yax(1),'k.')
  156. end
  157. title(['spike triggered average : ' ...
  158. num2str(Nspk) ' used : ' ...
  159. ' Errorbars are two std err']);
  160. %line(get(gca,'xlim'),mean(mlfp)*[1 1],'color','k')
  161. line([0 0],get(gca,'ylim'),'color','k')
  162. hold off