ResDetect08.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. function [DATout]=ResDetect08(Rin,Rbasein,INTin,NORMTYPin,WINin,CI)
  2. % This function detects responses in peri-event histograms. Confidence intervals are extracted from the
  3. % distribution of the baseline period.
  4. % Arpil 2012, Fred: This version was adapted from RespDetect07 (now handles single-neuron PTH)
  5. % This version contains the helper functions "sigtestin", "normalizein", "findonset03in"
  6. % Inputs:
  7. % Rin is a matrix e.g. PTH1(neurons, bins)
  8. % Rbasein is the baseline version of Rin (used to normalize)
  9. % INTin is the window in which responses are searched
  10. % NORMTYPin for the function normalizein - should be set to zero
  11. % WINin are onset and offset requirements; by default it is [0.1 0.3]
  12. % CI is the confidence interval (inhibitions<lower bound, excitation>Upper bound)
  13. % Outputs:
  14. % DATout.R= Rin
  15. % .LUb(neurons, 1:2): Lower and Upper Bounds = Threshold ofr excitation and inhibitions
  16. % .Rnorm(neurons, bins)= z-score transformed Rin
  17. % .Rnormmask(neurons, bins) = z-score with all bins that are within the confidence intervals are zeroed
  18. % .RFLAG(neurons, 1): +1 for excitation, -1 for inhibition, 0 for no resp.
  19. % .CFLAG(neurons, 1)= 0 or 1. 1 means that an inhibition follows an excation or vice-versa
  20. % .Onsets(neurons,1:2): First and Second columns stores the onset of excitations and inhibitions respectively
  21. % .Offsets(neurons,1:2): same as onset
  22. % .Paramnames={'Dura','Baseline','Bsize','INT','WINs'};
  23. % .Params={Dura,Baseline,BSIZE,INTin,WINin};
  24. global Dura Tm Tbase BSIZE Erefnames
  25. %Allows to handle single neurones cases where R(bins, 1) instead of R(1,neurons)
  26. if size(Rin,2)==1
  27. R=Rin'; Rbase=Rbasein';
  28. else
  29. R=Rin;Rbase=Rbasein;
  30. end
  31. if isempty(WINin)
  32. WINON=ceil(0.1/BSIZE);WINOFF=ceil(0.3/BSIZE);
  33. WINFLAG=0;
  34. elseif size(WINin,1)==1
  35. WINON=ceil(WINin(1)/BSIZE);WINOFF=ceil(WINin(2)/BSIZE); %same detection for all neurons
  36. WINFLAG=0;
  37. else
  38. WINONmat=ceil(WINin(:,1)/BSIZE);WINOFFmat=ceil(WINin(:,2)/BSIZE); % different for each neuron
  39. WINFLAG=1;
  40. end
  41. if size(INTin,1)==1
  42. Iref=find(Tm>=INTin(1) & Tm<=INTin(2));
  43. INTFLAG=0;
  44. else
  45. INTmat=INTin;
  46. INTFLAG=1;
  47. end
  48. % ------------ Determines the thresholds and makes a mask ------------
  49. %ALPHA=0.05/(size(R,2)-length(Tmind)); %Bonferroni correction
  50. if length(CI)==1, CI0(1)=CI;CI0(2)=CI; else CI0=CI; end %size(CI0)=(1x2)
  51. if CI0(1)>0
  52. %LUb= Lower and Upper Bound = threshold determined by the confidence intervals
  53. LUb=(prctile(Rbase',[CI0(1)/2 100-CI0(2)/2]))'; % Outside LUb range consider significant
  54. if size(LUb,2)==1, LUb=LUb'; end %To handle single neuron cases
  55. else
  56. %Ali's stuff - I think it uses it to go beyond 0 & 100% confidence intervals
  57. %it can be reached by using negative CI values
  58. LUb(:,1)=min(Rbase,[],2)-(max(Rbase,[],2)-min(Rbase,[],2))*abs(CI0(1))/200;
  59. LUb(:,2)=max(Rbase,[],2)+(max(Rbase,[],2)-min(Rbase,[],2))*abs(CI0(2))/200;
  60. end
  61. [lmask,umask]=sigtestin(R,LUb);
  62. Rnorm=normalizein(R,Rbase,NORMTYPin);%used to put (-) to bins below lower bound
  63. Rnormmask=Rnorm.*(umask+lmask);
  64. %Outupts R, LUb, Normmask and Rnorm
  65. DATout.R=R;DATout.LUb=LUb;DATout.Rnormmask=Rnormmask;DATout.Rnorm=Rnorm;
  66. for j=1:size(R,1) %loops through neurons
  67. if mod(j,11)==0
  68. fprintf('.');
  69. elseif mod(j,100)==0
  70. fprintf('%d',j)
  71. end
  72. if WINFLAG
  73. WINON=WINONmat(j);WINOFF=WINOFFmat(j);
  74. end
  75. if INTFLAG
  76. Iref=find(Tm>INTmat(j,1) & Tm<INTmat(j,2));
  77. end
  78. %PInd1 and NInd1 are the Tm indexes of the first excitation and inhibition respectively
  79. PInd1=findonset03in(double(Rnormmask(j,Iref)>0),1,WINON);
  80. NInd1=findonset03in(double(Rnormmask(j,Iref)<0),1,WINON);
  81. %% Flag settings
  82. %------------ Finds the onsets/offset of the FIRST response detected ------------
  83. Ponset=NaN;Nonset=NaN;Poffset=NaN;Noffset=NaN;TFLAG=[0 0];%termination flag
  84. if PInd1<NInd1
  85. % RFLAG= Response Flag: +1:excitation, -1:inhibition, 0:No response
  86. RFLAG=1;
  87. % Ponset is the excitation onset
  88. Ponset=Tm(Iref(PInd1));
  89. elseif PInd1>NInd1
  90. RFLAG=-1;
  91. % Nonset is the inhibition onset
  92. Nonset=Tm(Iref(NInd1));
  93. elseif isinf(PInd1) && isinf(NInd1)
  94. RFLAG=0;
  95. end
  96. % CFLAG= conflict flag=1 if both excitation and inhibition detected
  97. if ~isinf(PInd1) && ~isinf(NInd1)
  98. CFLAG=1;
  99. Ponset=Tm(Iref(PInd1));Nonset=Tm(Iref(NInd1));
  100. else
  101. CFLAG=0;
  102. end
  103. %------------ Finds the onsets/offset of the SECOND response detected ------------
  104. if ~isinf(PInd1)
  105. PInd2=findonset03in(double(Rnormmask(j,:)<=0),Iref(PInd1)+1,WINOFF);
  106. if ~isinf(PInd2)
  107. Poffset=Tm(PInd2);
  108. if Poffset<-0.03 % 0.025 is the interp1 offset with 0.05 bin
  109. TFLAG(1)=1;
  110. end
  111. else
  112. Poffset=Tm(end)+sqrt(-1); % if offset not detected it is beyond Tm(end)
  113. PInd2=length(Tm);
  114. end
  115. end
  116. if ~isinf(NInd1)
  117. NInd2=findonset03in(double(Rnormmask(j,:)>=0),Iref(NInd1)+1,WINOFF);
  118. if ~isinf(NInd2)
  119. Noffset=Tm(NInd2);
  120. if Noffset<-0.03 % 0.025 is the interp1 offset with 0.05 bin
  121. TFLAG(2)=1;
  122. end
  123. else
  124. Noffset=Tm(end)+sqrt(-1); % if offset not detected it is beyond Tm(end)
  125. NInd2=length(Tm);
  126. end
  127. end
  128. % setting outputs (new change to work for LP,Ent and Ext while keeping DS,NS results intact
  129. if (CFLAG==0 && sum(TFLAG)==1) || (CFLAG==1 && sum(TFLAG)==2) % early termination response not valid (set as imaginary)
  130. DATout.RFLAG(j,1)=RFLAG*sqrt(-1);
  131. else
  132. DATout.RFLAG(j,1)=RFLAG;
  133. end
  134. DATout.RFLAG(j,1)=RFLAG;
  135. DATout.CFLAG(j,1)=CFLAG;
  136. % offset and onsets should be swaped and negated
  137. DATout.Onsets(j,:)=[Ponset,Nonset];DATout.Offsets(j,:)=[Poffset,Noffset];
  138. end
  139. % setting outputs
  140. DATout.Paramnames={'Dura','Bsize','INT','WINs'};
  141. DATout.Params={Dura,BSIZE,INTin,WINin};
  142. %fprintf('\n response detection completed \n')
  143. %----- HELPER FUNCTIONS ----
  144. function [LMask,UMask]=sigtestin(Matin,Bin)
  145. UMask=zeros(size(Matin));LMask=zeros(size(Matin));
  146. for k=1:size(Matin,1)
  147. TMP=Matin(k,:);B=Bin(k,:);
  148. LMask(k,find(TMP<(B(1)-eps)))=1;
  149. UMask(k,find(TMP>(B(2)+eps)))=1;
  150. end
  151. function Mnormal=normalizein(M,Mbase,MD)
  152. %MD is the type of normalization.
  153. % 0 = Z-score >>(X-mean)/SD
  154. % 1 = normalized to response max
  155. % 2 = Baseline substracted
  156. % 3 = normalized by SD only >> X/SD
  157. %Added April 2012 to handle vectors
  158. if size(M,2)==1, M=M'; Mbase=Mbase'; end
  159. Mnormal=zeros(size(M));
  160. for k=1:size(M,1)
  161. if MD==0
  162. Mnormal(k,:)=(M(k,:)-nanmean(Mbase(k,:)))/nanstd(Mbase(k,:)); % Zscore
  163. elseif MD==1
  164. Tmp=M(k,:)-nanmean(Mbase(k,:));
  165. Mnormal(k,:)=Tmp/max(abs(Tmp));% mean corrected normalized to RESPONSE MAX
  166. elseif MD==2
  167. Mnormal(k,:)=(M(k,:)-nanmean(Mbase(k,:)));
  168. elseif MD==3
  169. Mnormal(k,:)=M(k,:)/nanstd(Mbase(k,:)); % Zscore no demean
  170. end
  171. end
  172. function Indout=findonset03in(Rin,Indin,Dur)
  173. % Finds the index of the first element when 'Dur' consecutive elements are equal to 1
  174. % Rin must contain double and not logical values. Therefore, the result of a find function
  175. % must be converted as follow: double(find(MAT>X))
  176. % Indin: looks from index Indin onward
  177. % Dur: Indetfies onset only if response is Dur long
  178. Indout=Inf;
  179. if ~isinf(Indin)
  180. R=Rin(Indin:end);
  181. TMP=find(conv(ones(1,Dur),R)==Dur)-(Dur-1);
  182. if ~isempty(TMP)
  183. Indout=TMP(1)+Indin-1;
  184. end
  185. end