fitModel.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. import numpy
  2. #adapters
  3. def fDiff(f,t,y,w,par):
  4. fv=f(t,par)
  5. return (fv-y)*w
  6. def fDiffScalar(f,t,y,w,par):
  7. df=fDiff(f,t,y,w,par)
  8. return (df*df).sum()
  9. def jacScalar(f,t,y,w,jac,par):
  10. #(m,) array
  11. #m number of time points
  12. b=2*fDiff(f,t,y,w,par)
  13. J=jac(par)
  14. return numpy.dot(b,J)
  15. #add regularization with explicit lambda
  16. def fDiffScalarRegularized(fDiffScalar,fScalarReg,qLambda,par):
  17. #fDiffScalar and fScalar reg should return a scalar to be minimized
  18. return fDiffScalar(par)+qLambda*fScalarReg(par)
  19. def jacScalarRegularized(jacScalar,jacScalarReg,qLambda,par):
  20. #jac scalar (reg) should return (n,) vector with n number of parameters
  21. return jacScalar(par)+qLambda*jacScalarReg(par)
  22. #input function
  23. def fIVF(t,par):
  24. A=par[0]
  25. tau=par[1]
  26. alpha=par[2]
  27. dt=par[3]
  28. try:
  29. B=par[4]
  30. gamma=par[5]
  31. except IndexError:
  32. print('IndexError')
  33. B=0
  34. gamma=0
  35. t1=t-dt
  36. x=t1/tau
  37. if tau==1/alpha:
  38. et=getExp(x,1)
  39. fv=A*alpha*getX1(x,et)+B*gamma*getExp(t1,gamma)
  40. else:
  41. et=getExp(x,1)
  42. ea=getExp(t1,alpha)
  43. fv=A*alpha*getE(x,ea,et,1-alpha*tau)+B*gamma*getExp(t1,gamma)
  44. #fv*=A
  45. #fv[t1<0]=0
  46. return fv
  47. def jacIVF(t,par):
  48. #return m by n matrix, where m is t.shape and n is par.shape
  49. jac=numpy.zeros((t.shape[0],par.shape[0]))
  50. A=par[0]
  51. tau=par[1]
  52. alpha=par[2]
  53. dt=par[3]
  54. t1=t-dt
  55. x=t1/tau
  56. et=getExp(x,1)
  57. try:
  58. B=par[4]
  59. gamma=par[5]
  60. except IndexError:
  61. print('IndexError')
  62. B=0
  63. gamma=0
  64. eg=getExp(t1,gamma)
  65. fb=B*gamma*eg
  66. if tau==1/alpha:
  67. fv=A*alpha*getX1(x,et)
  68. #first column, df/dA
  69. jac[t1>0,0]=fv[t1>0]/A
  70. #second column, df/dtau
  71. jac[t1>0,1]=-fv[t1>0]/tau*(1+0.5*x[t1>0])
  72. #third column df/dalpha
  73. jac[t1>0,2]=fv[t1>0]*(1/alpha-0.5*t1[t1>0])
  74. #last column df/d(dt)
  75. jac[:,3]=fv*alpha-A*alpha*et/tau+gamma*fb
  76. else:
  77. Q=A*alpha/(1-alpha*tau)
  78. ea=getExp(t1,alpha)
  79. fv=Q*(ea-et)
  80. #first column, df/dA
  81. jac[:,0]=fv/A
  82. #second column, df/dtau
  83. jac[:,1]=fv*alpha/(1-alpha*tau)+Q*getX1(x,et)/tau
  84. #third column df/dalpha
  85. jac[:,2]=fv/alpha/(1-alpha*tau)-Q*getX1(t1,ea)
  86. #last column df/d(dt)
  87. jac[:,3]=Q*getF(x,alpha,ea,1/tau,et,1)+gamma*fb
  88. try:
  89. jac[:,4]=fb/B
  90. jac[:,5]=fb/gamma+B*getX1(t1,eg)
  91. except IndexError:
  92. pass
  93. return jac
  94. #regularizers, require A to be as small as possible
  95. def fIVFRegA(par):
  96. return par[0]
  97. def jacIVFRegA(par):
  98. jac=numpy.zeros(par.shape[0])
  99. jac[0]=1
  100. return jac
  101. #helper functions
  102. def getE(x,e,ek,w):
  103. #get Ea or Et
  104. #first argument is ea for Ea
  105. #or et for Et
  106. #last argument is w0 for Ea
  107. #or wk for Et
  108. E=numpy.zeros(x.shape)
  109. E[x>0]=(e[x>0]-ek[x>0])/w
  110. return E
  111. def getF(x,a,e,b,eb,w):
  112. F=numpy.zeros(x.shape)
  113. F[x>0]=(a*e[x>0]-b*eb[x>0])/w
  114. return F
  115. def getH(x,a,b,ea=numpy.empty(0),eb=numpy.empty(0)):
  116. if ea.size==0:
  117. ea=getExp(x,a)
  118. if a==b:
  119. return getX1(x,ea)
  120. if eb.size==0:
  121. eb=getExp(x,b)
  122. return (ea-eb)/(b-a)
  123. def getH2(x,a,b):
  124. #derivative with respect to the second parameter
  125. eb=getExp(x,b)
  126. if a==b:
  127. return -0.5*getX2(x,ea)
  128. return -(getH(x,a,b,eb=eb)+getX1(x,eb))/(b-a)
  129. def getHD(x,a,b):
  130. #derivative with respect to offset dt
  131. ea=getExp(x,a)
  132. if a==b:
  133. return -ea+a*getX1(t1,ea)
  134. eb=getExp(x,b)
  135. return (a*ea-b*eb)/(b-a)
  136. def getX1(x,e):
  137. #returns x1 or y1
  138. #for x1, use ea as the 2nd argument
  139. #for y1, use et as the 2nd argument
  140. x1=numpy.zeros(x.shape)
  141. x1[x>0]=x[x>0]*e[x>0]
  142. return x1
  143. def getX2(x,e):
  144. x2=numpy.zeros(x.shape)
  145. x2[x>0]=x[x>0]*x[x>0]*e[x>0]
  146. return x2
  147. def getX3(x,e):
  148. x2=numpy.zeros(x.shape)
  149. x2[x>0]=x[x>0]*x[x>0]*x[x>0]*e[x>0]
  150. return x2
  151. def getExp(x,k):
  152. e=numpy.zeros(x.shape)
  153. e[x>0]=numpy.exp(-x[x>0]*k)
  154. return e
  155. def fCompartment(ivfPar,t,par):
  156. A=ivfPar[0]
  157. tau=ivfPar[1]
  158. alpha=ivfPar[2]
  159. k1=par[0]
  160. BVF=par[1]
  161. k2=par[2]
  162. dt=par[3]
  163. try:
  164. B=ivfPar[4]
  165. gamma=ivfPar[5]
  166. except IndexError:
  167. B=0
  168. gamma=0
  169. return BVF*fIVFStar(t,A,tau,alpha,dt,B,gamma)+(1-BVF)*fC1(t,A,tau,alpha,dt,k1,k2,B,gamma)
  170. def fIVFStar(t,A,tau,alpha,dt,B=0,gamma=0):
  171. t1=t-dt
  172. x=t1/tau
  173. et=getExp(x,1)
  174. ea=getExp(t1,alpha)
  175. eg=getExp(t1,gamma)
  176. AT=alpha*tau
  177. wa=1-AT
  178. fv=numpy.zeros(t1.shape)
  179. if AT==1:
  180. fv[x>0]=A*alpha*x[x>0]*ea[x>0]+B*gamma*getExp(t1,gamma)
  181. else:
  182. fv=A*alpha*getE(x,ea,et,wa)+B*gamma*getExp(t1,gamma)
  183. return fv
  184. def fC1(t,A,tau,alpha,dt,k1,k2,B=0,gamma=0):
  185. #apply time shift
  186. t1=t-dt
  187. x=t1/tau
  188. #place to store results
  189. r0=numpy.zeros(t1.shape)
  190. #helper values
  191. et=getExp(x,1)
  192. ea=getExp(t1,alpha)
  193. ek=getExp(t1,k2)
  194. AT=alpha*tau
  195. K2T=k2*tau
  196. K1T=k1*tau
  197. w0=AT-K2T
  198. wk=1-K2T
  199. wa=1-AT
  200. #stratify by parameter values
  201. #option A and D
  202. if AT==1:
  203. #option D
  204. if K2T==1:
  205. r0=0.5*A*K1T*alpha*getX2(x,ea)+B*gamma*getH(t1,gamma,k2)
  206. else:
  207. #option A
  208. Ea=getE(x,ea,ek,-w0)
  209. x1=getX1(x,ea)
  210. r0=-K1T*A*alpha/w0*(-Ea+x1)+B*gamma*getH(t1,gamma,k2)
  211. else:
  212. #option 0, B and C; AT not equal to 1
  213. D1=getH(t1,alpha,k2)
  214. D2=getH(t1,1/tau,k2)
  215. r0=A*alpha*K1T/wa*(D1-D2)+k1*B*gamma*getH(t1,gamma,k2)
  216. return r0
  217. def jacDep(ivfPar,t,par):
  218. jac=numpy.zeros((t.shape[0],par.shape[0]))
  219. A=ivfPar[0]
  220. tau=ivfPar[1]
  221. alpha=ivfPar[2]
  222. try:
  223. B=ivfPar[4]
  224. gamma=ivfPar[5]
  225. except IndexError:
  226. B=0
  227. gamma=0
  228. k1=par[0]
  229. BVF=par[1]
  230. k2=par[2]
  231. dt=par[3]
  232. t1=t-dt
  233. x=t1/tau
  234. et=getExp(x,1)
  235. ea=getExp(t1,alpha)
  236. ek=getExp(t1,k2)
  237. AT=alpha*tau
  238. K2T=k2*tau
  239. K1T=k1*tau
  240. w0=AT-K2T
  241. wk=1-K2T
  242. wa=1-AT
  243. c1=fC1(t,A,tau,alpha,dt,k1,k2,B,gamma)
  244. c0=fIVFStar(t,A,tau,alpha,dt,B,gamma)
  245. #first column, df/dk1
  246. jac[t1>0,0]=c1[t1>0]/k1
  247. #second column, df/dBVF
  248. jac[t1>0,1]=c0[t1>0]-c1[t1>0]
  249. #more effort for k2 and dt
  250. #2nd column is df/dk2
  251. #3rd column is df/d(dt)
  252. if AT==1:
  253. jac[:,3]=BVF*(A*(AT*getX1(x,ea)-ea)+B*gamma*gamma*getExp(t1,gamma))
  254. if K2T==1:
  255. #option D
  256. jac[:,2]=-0.5*K1T*A*tau*tau*getX3(x,ea)+B*k1*gamma*getH2(t1,gamma,k2)
  257. jac[:,3]+=(1-BVF)*(0.5*K1T*A*(AT*getX2(x,ea)-2*getX1(x,ea))+B*k1*gamma*getHD(t1,gamma,k2))
  258. else:
  259. #option A
  260. jac[:,2]=c1*tau/w0+K1T*A*alpha/w0*getHD(t1,alpha,k2)+B*k1*gamma*getHD(t1,gamma,k2)
  261. jac[:,3]+=(1-BVF)*(K1T*A/w0*(tau*getF(x,alpha,ea,k2,ek,-w0)-AT*getX1(x,ea)+ea)+B*k1*gamma*getHD(t1,gamma,k2))
  262. else:
  263. #option 0,B,C
  264. jac[:,2]=A*K1T*alpha/wa*(getH2(t1,alpha,k2)-getH2(t1,1/tau,k2))+B*k1*gamma*getH2(t1,gamma,k2)
  265. jac[:,3]=BVF*A*alpha*getHD(t1,alpha,1/tau)
  266. jac[:,3]+=(1-BVF)*(K1T*A*alpha/wa*(getHD(t1,alpha,k2)-getHD(t1,1/tau,k2))+B*k1*gamma*getHD(t1,gamma,k2))
  267. jac[:,2]*=(1-BVF)
  268. return jac
  269. def fCRegBVF(par):
  270. return par[1]
  271. def jacDepRegBVF(par):
  272. jac=numpy.zeros(par.shape[0])
  273. jac[1]=1
  274. return jac