computeiCSDCubicSplines.m 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. function [iCSDMat,zAxis]=computeiCSDCubicSplines(LFPMat,cAxis,conductance,diameter,numCSDSpaceSamples,GaussFiltSigma,filtRange,integralTolerance)
  2. %
  3. % This function computes iCSD Cubic Splines (Pettersen et al., J Neurosci Methods, 2005)
  4. %
  5. % List of INPUTs:
  6. % LFPMat -> Matrix of LFP recordings (Probe Channels x Time Sequence) [V]
  7. % cAxis -> Vector of Probe contact points [m]
  8. % conductance -> Conductance of the Extracellular Fluid [S/m]
  9. % diameter -> Diameter of disk around the Probe [m]
  10. % numCSDSpaceSamples -> Number of output samples (Spatial resolution)
  11. % GaussFiltSigma -> Standard Deviation of the Gaussian Filter
  12. % filtRange -> Extremity of the Gaussian Filter
  13. % integralTolerance -> Convergence criteria of the numeric integral approximation
  14. %
  15. % List of OUTPUTs:
  16. % iCSDMat -> Matrix of iCSDs
  17. % zAxis -> Vector of CSD surface positions
  18. %
  19. if nargin<8; integralTolerance=1e-6;
  20. if nargin<7;
  21. if nargin<6; GaussFiltSigma=1e-4;
  22. if nargin<5; numCSDSpaceSamples=200; end;
  23. end;
  24. filtRange=5*GaussFiltSigma;
  25. end;
  26. end;
  27. % Probe Contacts Parameters
  28. [numContacts,numCSDTimeSamples] = size(LFPMat);
  29. cAvgDiff=mean(diff(cAxis));
  30. % Add imaginary contacts on the Border
  31. cAxisBpad=[cAxis(1)-cAvgDiff cAxis cAxis(end)+cAvgDiff];
  32. % Output axis with higher spatial resolution
  33. zAxis=linspace(cAxis(1)-cAvgDiff/2,cAxis(end)+cAvgDiff/2,numCSDSpaceSamples);
  34. zAvgDiff=mean(diff(zAxis));
  35. zAxisBpad=[cAxisBpad(1):zAvgDiff:zAxis(1) zAxis(2:end-1) zAxis(end):zAvgDiff:cAxisBpad(end)];
  36. zAxisIndicesWithinBpad=find(zAxisBpad<=zAxis(1),1,'last'):find(zAxisBpad>=zAxis(end),1,'first');
  37. effNumCSDSpaceSamples=length(zAxisBpad);
  38. % C Vector and C Matrix
  39. CVec = 1./diff(cAxisBpad); CMat=diag(CVec);
  40. % C Matrix zero padded in a Up Frame
  41. CMat0padUF=zeros(numContacts+2); CMat0padUF(2:end-1,2:end-1)=diag(CVec(1:end-1));
  42. % C Matrix zero padded in a Down Frame
  43. CMat0padDF=zeros(numContacts+2); CMat0padDF(2:end-1,2:end-1)=diag(CVec(2:end));
  44. % C Matrix ones added along Diagonal Margins
  45. CMat1addDM=CMat0padDF; CMat1addDM(1)=1; CMat1addDM(end)=1;
  46. % Identity Matrix zero padded Up
  47. IMat0padU=[zeros(numContacts+1,1) eye(numContacts+1)];
  48. % Identity Matrix zero padded Down
  49. IMat0padD=[eye(numContacts+1) zeros(numContacts+1,1)];
  50. % Identity Matrix zero padded Up Down Left
  51. IMat0padUDL=[zeros(1,numContacts+2); eye(numContacts+1) zeros(numContacts+1,1)];
  52. % Identity Matrix zero padded Up Down 2x Right
  53. IMat0padUD2R=[zeros(1,numContacts+2); zeros(numContacts,2) eye(numContacts); zeros(1,numContacts+2)];
  54. % Identity Matrix zero padded in a Frame
  55. IMat0padF=[zeros(1,numContacts+2); zeros(numContacts,1) eye(numContacts) zeros(numContacts,1); zeros(1,numContacts+2)];
  56. % K Matrix divergency of cubic splines
  57. KMat = (CMat0padUF*IMat0padUDL+2*CMat0padUF*IMat0padF+2*CMat1addDM+CMat0padDF*IMat0padUD2R)^(-1)*3*...
  58. (CMat0padUF^2*IMat0padF-CMat0padUF^2*IMat0padUDL+CMat0padDF^2*IMat0padUD2R-CMat0padDF^2*IMat0padF);
  59. % E Matrix coefficients for cubic spline
  60. E0th = IMat0padD;
  61. E1st = IMat0padD*KMat;
  62. E2nd = 3*CMat^2*(IMat0padU-IMat0padD)-CMat*(IMat0padU+2*IMat0padD)*KMat;
  63. E3rd = 2*CMat^3*(IMat0padD-IMat0padU)+CMat^2*(IMat0padU+IMat0padD)*KMat;
  64. clear CVec CMat CMat0padUF CMat0padDF CMat1addDM IMat0padU IMat0padD IMat0padDL IMat0padUD2R IMat0padUDL IMat0padF KMat
  65. % Define integration matrixes
  66. F0th = zeros(numContacts,numContacts+1);
  67. F1st = zeros(numContacts,numContacts+1);
  68. F2nd = zeros(numContacts,numContacts+1);
  69. F3rd = zeros(numContacts,numContacts+1);
  70. for jth = 1:numContacts % Note: Needs to be fixed if conductivity not constant (conductivity~=conductivityTop)!
  71. for ith = 1:numContacts+1
  72. F0th(jth,ith) = integral(@(zeta) 1./(2.*conductance).*(sqrt((diameter/2)^2+((cAxisBpad(jth+1)-zeta)).^2)-abs(cAxisBpad(jth+1)-zeta)),...
  73. cAxisBpad(ith),cAxisBpad(ith+1),'RelTol',0,'AbsTol',integralTolerance);
  74. F1st(jth,ith) = integral(@(zeta) 1./(2.*conductance).*(zeta-cAxisBpad(ith)).*(sqrt((diameter/2)^2+((cAxisBpad(jth+1)-zeta)).^2)-abs(cAxisBpad(jth+1)-zeta)),...
  75. cAxisBpad(ith),cAxisBpad(ith+1),'RelTol',0,'AbsTol',integralTolerance);
  76. F2nd(jth,ith) = integral(@(zeta) 1./(2.*conductance).*(zeta-cAxisBpad(ith)).^2.*(sqrt((diameter/2)^2+((cAxisBpad(jth+1)-zeta)).^2)-abs(cAxisBpad(jth+1)-zeta)),...
  77. cAxisBpad(ith),cAxisBpad(ith+1),'RelTol',0,'AbsTol',integralTolerance);
  78. F3rd(jth,ith) = integral(@(zeta) 1./(2.*conductance).*(zeta-cAxisBpad(ith)).^3.*(sqrt((diameter/2)^2+((cAxisBpad(jth+1)-zeta)).^2)-abs(cAxisBpad(jth+1)-zeta)),...
  79. cAxisBpad(ith),cAxisBpad(ith+1),'RelTol',0,'AbsTol',integralTolerance);
  80. end;
  81. end;
  82. FMat=zeros(numContacts+2); FMat(2:numContacts+1,:)=F0th*E0th+F1st*E1st+F2nd*E2nd+F3rd*E3rd; FMat(1)=1; FMat(end)=1;
  83. clear F0th F1st F2nd F3rd ith jth
  84. VMat0padUD=[zeros(1,numCSDTimeSamples); LFPMat; zeros(1,numCSDTimeSamples)];
  85. % CSDLowRes=F^(-1)*VMat0padUD;
  86. iCSDLowRes=FMat\VMat0padUD;
  87. % The cubic spline polynomial coeffecients
  88. A0th = E0th*iCSDLowRes;
  89. A1st = E1st*iCSDLowRes;
  90. A2nd = E2nd*iCSDLowRes;
  91. A3rd = E3rd*iCSDLowRes;
  92. % Preallocate Unfiltered CSD Matrix
  93. uiCSDMat = zeros(effNumCSDSpaceSamples,numCSDTimeSamples);
  94. for zth=1:effNumCSDSpaceSamples;
  95. iCAxisBpad=find([cAxisBpad(1:end-1) cAxisBpad(end)+eps]>zAxisBpad(zth),1,'first')-1;
  96. uiCSDMat(zth,:) = A0th(iCAxisBpad,:) + A1st(iCAxisBpad,:).*(zAxisBpad(zth)-cAxisBpad(iCAxisBpad)) + ...
  97. A2nd(iCAxisBpad,:)*(zAxisBpad(zth)-cAxisBpad(iCAxisBpad)).^2 + A3rd(iCAxisBpad,:)*(zAxisBpad(zth)-cAxisBpad(iCAxisBpad)).^3;
  98. end;
  99. clear E0th E1st E2nd E3rd A0th A1st A2nd A3rd VMat0padUD CSDLowRes F iCAxisBpad zth
  100. % Create Gaussian Filter
  101. filtAxes = -filtRange/2:zAvgDiff:filtRange/2;
  102. numFiltSamples = length(filtAxes);
  103. GaussFiltSamples = 1/(GaussFiltSigma*sqrt(2*pi))*exp(-filtAxes.^2/(2*GaussFiltSigma^2));
  104. % Zero pad CSD Matrix of filter size Up and Down
  105. uiCSDMat0padfUD = [zeros(numFiltSamples,numCSDTimeSamples); uiCSDMat; zeros(numFiltSamples,numCSDTimeSamples)];
  106. % Filter padded CSD Matrix
  107. iCSDMat0padfUD = filter(GaussFiltSamples/sum(GaussFiltSamples),1,uiCSDMat0padfUD);
  108. % Remove extra samples due to the Zero padding and Filtering function (which adds 1/2 filter size samples)
  109. iCSDMat=iCSDMat0padfUD(round(1.5*numFiltSamples)+1:round(1.5*numFiltSamples)+effNumCSDSpaceSamples,:);
  110. clear uiCSDMat iCSDMat0padfUD uiCSDMat0padfUD filtAxes GaussFiltSamples numFiltSamples
  111. % Recenter the iCSDMat to zAxis (remove imaginary contacts)
  112. iCSDMat=iCSDMat(zAxisIndicesWithinBpad,:);
  113. end