Surface NMR processing and inversion GUI
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

decay.py 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. import numpy, array #,rpy2
  2. from matplotlib import pyplot as plt
  3. import numpy as np
  4. from scipy.optimize import least_squares
  5. from rpy2.robjects.packages import importr
  6. import rpy2.robjects as robjects
  7. import rpy2.robjects.numpy2ri
  8. #import notch
  9. from numpy.fft import fft, fftfreq
  10. # We know/can calculate frequency peak, use this to guess where picks will be.
  11. # maybe have a sliding window that reports peak values.
  12. def peakPicker(data, omega, dt):
  13. # compute window based on omega and dt
  14. # make sure you are not aliased, grab every other peak
  15. window = (2*numpy.pi) / (omega*dt)
  16. data = numpy.array(data)
  17. peaks = []
  18. troughs = []
  19. times = []
  20. times2 = []
  21. indices = []
  22. ws = 0
  23. we = window
  24. ii = 0
  25. for i in range((int)(len(data)/window)):
  26. # initially was just returning this I think avg is better
  27. #times.append( (ws + numpy.abs(data[ws:we]).argmax()) * dt )
  28. peaks.append(numpy.max(data[ws:we]))
  29. times.append( (ws + data[ws:we].argmax()) * dt )
  30. indices.append( ii + data[ws:we].argmax() )
  31. troughs.append(numpy.min(data[ws:we]))
  32. times2.append( (ws + (data[ws:we]).argmin()) * dt )
  33. indices.append( ii + data[ws:we].argmin() )
  34. ws += window
  35. we += window
  36. ii += (int)(we-ws)
  37. #return numpy.array(peaks), numpy.array(times)
  38. # Averaging peaks does a good job of removing bias in noise
  39. return (numpy.array(peaks)-numpy.array(troughs))/2., \
  40. (numpy.array(times)+numpy.array(times2))/2., \
  41. indices
  42. #################################################
  43. # Regress for T2 using rpy2 interface
  44. def regressCurve(peaks,times,sigma2=1,intercept=True):
  45. # TODO, if regression fails, it might be because there is no exponential
  46. # term, maybe do a second regression then on a linear model.
  47. b1 = 0 # Bias
  48. b2 = 0 # Linear
  49. rT2 = 0.3 # T2 regressed
  50. r = robjects.r
  51. # Variable shared between R and Python
  52. robjects.globalenv['b1'] = b1
  53. robjects.globalenv['b2'] = b2
  54. robjects.globalenv['rT2'] = rT2
  55. robjects.globalenv['sigma2'] = sigma2
  56. value = robjects.FloatVector(peaks)
  57. times = robjects.FloatVector(numpy.array(times))
  58. # my_weights = robjects.RVector(value/sigma2)
  59. # robjects.globalenv['my_weigts'] = my_weights
  60. # if sigma2 != 0:
  61. # print "weighting"
  62. # tw = numpy.array(peaks)/sigma2
  63. # my_weights = robjects.RVector( tw/numpy.max(tw) )
  64. # else:
  65. # my_weights = robjects.RVector(numpy.ones(len(peaks)))
  66. # robjects.globalenv['my_weights'] = my_weights
  67. if (intercept):
  68. my_list = robjects.r('list(b1=50, b2=1e2, rT2=0.03)')
  69. my_lower = robjects.r('list(b1=0, b2=0, rT2=.005)')
  70. my_upper = robjects.r('list(b1=20000, b2=2000, rT2=.700)')
  71. else:
  72. my_list = robjects.r('list(b2=1e2, rT2=0.3)')
  73. my_lower = robjects.r('list(b2=0, rT2=.005)')
  74. my_upper = robjects.r('list(b2=2000, rT2=.700)')
  75. my_cont = robjects.r('nls.control(maxiter=1000, warnOnly=TRUE, printEval=FALSE)')
  76. if (intercept):
  77. #fmla = robjects.RFormula('value ~ b1 + exp(-times/rT2)')
  78. fmla = robjects.Formula('value ~ b1 + b2*exp(-times/rT2)')
  79. #fmla = robjects.RFormula('value ~ b1 + b2*times + exp(-times/rT2)')
  80. else:
  81. fmla = robjects.Formula('value ~ b2*exp(-times/rT2)')
  82. env = fmla.getenvironment()
  83. env['value'] = value
  84. env['times'] = times
  85. # ugly, but I get errors with everything else I've tried
  86. my_weights = robjects.r('rep(1,length(value))')
  87. for ii in range(len(my_weights)):
  88. my_weights[ii] *= peaks[ii]/sigma2
  89. Error = False
  90. #fit = robjects.r.nls(fmla,start=my_list,control=my_cont,weights=my_weights)
  91. if (sigma2 != 1):
  92. print("SIGMA 2")
  93. #fit = robjects.r.tryCatch(robjects.r.suppressWarnings(robjects.r.nls(fmla,start=my_list,control=my_cont,algorithm="port", \
  94. # weights=my_weights)), 'silent=TRUE')
  95. fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list,control=my_cont))#, \
  96. # weights=my_weights))
  97. else:
  98. try:
  99. fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list,control=my_cont,algorithm="port"))#,lower=my_lower,upper=my_upper))
  100. except:
  101. print("regression issue pass")
  102. Error = True
  103. # If failure fall back on zero regression values
  104. if not Error:
  105. #Error = fit[3][0]
  106. report = r.summary(fit)
  107. b1 = 0
  108. b2 = 0
  109. rT2 = 1
  110. if (intercept):
  111. if not Error:
  112. b1 = r['$'](report,'par')[0]
  113. b2 = r['$'](report,'par')[1]
  114. rT2 = r['$'](report,'par')[2]
  115. #print report
  116. #print r['$'](report,'convergence')
  117. #print r['convergence'] #(report,'convergence')
  118. #print r['$'](report,'par')[13]
  119. #print r['$'](report,'par')[14]
  120. else:
  121. print("ERROR DETECTED, regressed values set to default")
  122. b1 = 1e1
  123. b2 = 1e-2
  124. rT2 = 1e-2
  125. #print r['$'](report,'par')[0]
  126. #print r['$'](report,'par')[1]
  127. #print r['$'](report,'par')[2]
  128. return [b1,b2,rT2]
  129. else:
  130. if not Error:
  131. rT2 = r['$'](report,'par')[1]
  132. b2 = r['$'](report,'par')[0]
  133. else:
  134. print("ERROR DETECTED, regressed values set to default")
  135. return [b2, rT2]
  136. #################################################
  137. # Regress for T2 using rpy2 interface
  138. def regressCurve2(peaks,times,sigma2=[None],intercept=True):
  139. if sigma2[0] != None:
  140. my_weights = robjects.FloatVector( sigma2 )
  141. # TODO, if regression fails, it might be because there is no exponential
  142. # term, maybe do a second regression then on a linear model.
  143. b1 = 0 # Bias
  144. b2 = 0 # Linear
  145. bb2 = 0 # Linear
  146. rT2 = 0.3 # T2 regressed
  147. rrT2 = 1.3 # T2 regressed
  148. r = robjects.r
  149. # Variable shared between R and Python
  150. robjects.globalenv['b1'] = b1
  151. robjects.globalenv['b2'] = b2
  152. robjects.globalenv['rT2'] = rT2
  153. robjects.globalenv['bb2'] = b2
  154. robjects.globalenv['rrT2'] = rT2
  155. #robjects.globalenv['sigma2'] = sigma2
  156. value = robjects.FloatVector(peaks)
  157. times = robjects.FloatVector(numpy.array(times))
  158. if (intercept):
  159. my_list = robjects.r('list(b1=.50, b2=1e2, rT2=0.03, bb2=1e1, rrT2=1.3)')
  160. my_lower = robjects.r('list(b1=0, b2=0, rT2=.005, bb2=0, rrT2=.005 )')
  161. my_upper = robjects.r('list(b1=2000, b2=2000, rT2=.700, bb2=2000, rrT2=1.3 )')
  162. else:
  163. my_list = robjects.r('list(b2=.5, rT2=0.3, bb2=.5, rrT2=1.3)')
  164. my_lower = robjects.r('list(b2=0, rT2=.005, bb2=0, rrT2=.005)')
  165. my_upper = robjects.r('list(b2=1, rT2=2.6, bb2=1, rrT2=2.6)')
  166. my_cont = robjects.r('nls.control(maxiter=1000, warnOnly=TRUE, printEval=FALSE)')
  167. if (intercept):
  168. #fmla = robjects.RFormula('value ~ b1 + exp(-times/rT2)')
  169. fmla = robjects.Formula('value ~ b1 + b2*exp(-times/rT2) + bb2*exp(-times/rrT2)')
  170. #fmla = robjects.RFormula('value ~ b1 + b2*times + exp(-times/rT2)')
  171. else:
  172. fmla = robjects.Formula('value ~ b2*exp(-times/rT2) + bb2*exp(-times/rrT2)')
  173. env = fmla.getenvironment()
  174. env['value'] = value
  175. env['times'] = times
  176. # ugly, but I get errors with everything else I've tried
  177. Error = False
  178. #fit = robjects.r.nls(fmla,start=my_list,control=my_cont,weights=my_weights)
  179. if (sigma2[0] != None):
  180. #print("SIGMA 2")
  181. #fit = robjects.r.tryCatch(robjects.r.suppressWarnings(robjects.r.nls(fmla,start=my_list,control=my_cont,algorithm="port", \
  182. # weights=my_weights)), 'silent=TRUE')
  183. fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list,control=my_cont,algorithm='port',weights=my_weights,lower=my_lower,upper=my_upper))#, \
  184. # weights=my_weights))
  185. else:
  186. try:
  187. fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list,control=my_cont,algorithm="port"))#,lower=my_lower,upper=my_upper))
  188. except:
  189. print("regression issue pass")
  190. Error = True
  191. # If failure fall back on zero regression values
  192. if not Error:
  193. #Error = fit[3][0]
  194. report = r.summary(fit)
  195. b1 = 0
  196. b2 = 0
  197. rT2 = 1
  198. if (intercept):
  199. if not Error:
  200. b1 = r['$'](report,'par')[0]
  201. b2 = r['$'](report,'par')[1]
  202. rT2 = r['$'](report,'par')[2]
  203. #print report
  204. #print r['$'](report,'convergence')
  205. #print r['convergence'] #(report,'convergence')
  206. #print r['$'](report,'par')[13]
  207. #print r['$'](report,'par')[14]
  208. else:
  209. print("ERROR DETECTED, regressed values set to default")
  210. b1 = 1e1
  211. b2 = 1e-2
  212. rT2 = 1e-2
  213. #print r['$'](report,'par')[0]
  214. #print r['$'](report,'par')[1]
  215. #print r['$'](report,'par')[2]
  216. return [b1,b2,rT2, bb2, rrT2]
  217. else:
  218. if not Error:
  219. rT2 = r['$'](report,'par')[1]
  220. b2 = r['$'](report,'par')[0]
  221. rrT2 = r['$'](report,'par')[3]
  222. bb2 = r['$'](report,'par')[2]
  223. else:
  224. print("ERROR DETECTED, regressed values set to default")
  225. return [b2, rT2, bb2, rrT2]
  226. def fun(x, t, y):
  227. """ Cost function for regression, single exponential, no DC term
  228. x[0] = A0
  229. x[1] = zeta
  230. x[2] = df
  231. x[3] = T2
  232. """
  233. # concatenated real and imaginary parts
  234. pre = np.concatenate((-x[0]*np.sin(2.*np.pi*x[2]*t + x[1])*np.exp(-t/x[3]), \
  235. +x[0]*np.cos(2.*np.pi*x[2]*t + x[1])*np.exp(-t/x[3])))
  236. return y-pre
  237. def fun2(x, t, y):
  238. """ Cost function for regression, single exponential, no DC term
  239. x[0] = A0
  240. x[1] = zeta
  241. x[2] = T2
  242. """
  243. # concatenated real and imaginary parts
  244. pre = np.concatenate((x[0]*np.cos(x[1])*np.exp(-t/x[2]), \
  245. -1.*x[0]*np.sin(x[1])*np.exp(-t/x[2])))
  246. return y-pre
  247. def quadratureDetect2(X, Y, tt, x0="None"):
  248. """ Pure python quadrature detection using Scipy.
  249. X = real part of NMR signal
  250. Y = imaginary component of NMR signal
  251. tt = time
  252. """
  253. print("Pure Python Quad Det", "TODO look at loss functions and method")
  254. # Loss functions, linear, soft_l1, huber, cauchy, arctan
  255. # df
  256. loss = 'cauchy' # 'soft_l1'
  257. method = 'trf' # trf, dogbox, lm
  258. if x0=="None":
  259. x0 = np.array( [1., 0., 0., .2] ) # A0, zeta, df, T2
  260. res_lsq = least_squares(fun, x0, args=(tt, np.concatenate((X, Y))), loss=loss, f_scale=1.0,\
  261. bounds=( [1., -np.pi, -5, .005] , [1000., np.pi, 5, .800] ),
  262. method=method
  263. )
  264. x = res_lsq.x
  265. print ("df", x[0], x[1], x[2], x[3])
  266. else:
  267. res_lsq = least_squares(fun, x0, args=(tt, np.concatenate((X, Y))), loss=loss, f_scale=1.0,\
  268. bounds=( [1., -np.pi, -5, .005] , [1000., np.pi, 5, .800] ),
  269. method=method
  270. )
  271. #bounds=( [0., 0, -20, .0] , [1., np.pi, 20, .6] ))
  272. x = res_lsq.x
  273. return res_lsq.success, x[0], x[2], x[1], x[3]
  274. # no df
  275. #x = np.array( [1., 0., 0.2] )
  276. #res_lsq = least_squares(fun2, x, args=(tt, np.concatenate((X, Y))), loss='soft_l1', f_scale=0.1)
  277. #x = res_lsq.x
  278. #return conv, E0,df,phi,T2
  279. #return res_lsq.success, x[0], 0, x[1], x[2]
  280. def quadratureDetect(X, Y, tt, CorrectFreq=False, BiExp=False, CorrectDC=False):
  281. r = robjects.r
  282. if CorrectDC:
  283. robjects.r('''
  284. Xc1 <- function(E01, df, tt, phi, T2_1, DC) {
  285. DC + E01*cos(2*pi*df*tt + phi) * exp(-tt/T2_1)
  286. }
  287. Yc1 <- function(E01, df, tt, phi, T2_1, DC) {
  288. DC - E01*sin(2*pi*df*tt + phi) * exp(-tt/T2_1)
  289. }
  290. ''')
  291. else:
  292. robjects.r('''
  293. Xc1 <- function(E01, df, tt, phi, T2_1) {
  294. E01*cos(2*pi*df*tt + phi) * exp(-tt/T2_1)
  295. }
  296. Yc1 <- function(E01, df, tt, phi, T2_1) {
  297. -E01*sin(2*pi*df*tt + phi) * exp(-tt/T2_1)
  298. }
  299. ''')
  300. # bi-exponential
  301. if CorrectDC:
  302. robjects.r('''
  303. Xc2 <- function(E01, E02, df, tt, phi, T2_1, T2_2, DC) {
  304. DC + E01*cos(2*pi*df*tt + phi) * exp(-tt/T2_1) +
  305. DC + E02*cos(2*pi*df*tt + phi) * exp(-tt/T2_2)
  306. }
  307. Yc2 <- function(E01, E02, df, tt, phi, T2_1, T2_2, DC) {
  308. DC - E01*sin(2*pi*df*tt + phi) * exp(-tt/T2_1) +
  309. DC - E02*sin(2*pi*df*tt + phi) * exp(-tt/T2_2)
  310. }
  311. ''')
  312. else:
  313. robjects.r('''
  314. Xc2 <- function(E01, E02, df, tt, phi, T2_1, T2_2) {
  315. E01*cos(2*pi*df*tt + phi) * exp(-tt/T2_1) +
  316. E02*cos(2*pi*df*tt + phi) * exp(-tt/T2_2)
  317. }
  318. Yc2 <- function(E01, E02, df, tt, phi, T2_1, T2_2) {
  319. -E01*sin(2*pi*df*tt + phi) * exp(-tt/T2_1) +
  320. -E02*sin(2*pi*df*tt + phi) * exp(-tt/T2_2)
  321. }
  322. ''')
  323. # Make 0 vector
  324. Zero = robjects.FloatVector(numpy.zeros(len(X)))
  325. # Fitted Parameters
  326. E01 = 0.
  327. E02 = 0.
  328. df = 0.
  329. phi = 0.
  330. T2_1 = 0.
  331. T2_2 = 0.
  332. DC = 0.
  333. robjects.globalenv['DC'] = DC
  334. robjects.globalenv['E01'] = E01
  335. robjects.globalenv['E02'] = E02
  336. robjects.globalenv['df'] = df
  337. robjects.globalenv['phi'] = phi
  338. robjects.globalenv['T2_1'] = T2_1
  339. robjects.globalenv['T2_2'] = T2_2
  340. XY = robjects.FloatVector(numpy.concatenate((X,Y)))
  341. # Arrays
  342. tt = robjects.FloatVector(numpy.array(tt))
  343. X = robjects.FloatVector(numpy.array(X))
  344. Y = robjects.FloatVector(numpy.array(Y))
  345. Zero = robjects.FloatVector(numpy.array(Zero))
  346. if BiExp:
  347. if CorrectDC:
  348. fmla = robjects.Formula('XY ~ c(Xc2( E01, E02, df, tt, phi, T2_1, T2_2, DC ), Yc2( E01, E02, df, tt, phi, T2_1, T2_2, DC ))')
  349. if CorrectFreq:
  350. start = robjects.r('list(E01=.100, E02=.01, df=0, phi=0. , T2_1=.100, T2_2=.01, DC=0.0)')
  351. lower = robjects.r('list(E01=1e-6, E02=1e-6, df=-50, phi=-3.14 , T2_1=.001, T2_2=.001, DC=0.0)')
  352. upper = robjects.r('list(E01=1.00, E02=1.0, df=50, phi=3.14 , T2_1=.800, T2_2=.8, DC=0.5)')
  353. else:
  354. start = robjects.r('list(E01=.100, E02=.01, phi=0.9 , T2_1=.100, T2_2=.01, DC=0.0)')
  355. lower = robjects.r('list(E01=1e-6, E02=1e-6, phi=-3.14 , T2_1=.001, T2_2=.001, DC=0.0)')
  356. upper = robjects.r('list(E01=1.00, E02=1.0, phi=3.14 , T2_1=.800, T2_2=.8, DC=0.5)')
  357. else:
  358. fmla = robjects.Formula('XY ~ c(Xc2( E01, E02, df, tt, phi, T2_1, T2_2 ), Yc2( E01, E02, df, tt, phi, T2_1, T2_2))')
  359. if CorrectFreq:
  360. start = robjects.r('list(E01=.100, E02=.01, df=0, phi=0. , T2_1=.100, T2_2=.01)')
  361. lower = robjects.r('list(E01=1e-6, E02=1e-6, df=-50, phi=-3.14 , T2_1=.001, T2_2=.001)')
  362. upper = robjects.r('list(E01=1.00, E02=1.0, df=50, phi=3.14 , T2_1=.800, T2_2=.8)')
  363. else:
  364. start = robjects.r('list(E01=.100, E02=.01, phi=0.9 , T2_1=.100, T2_2=.01)')
  365. lower = robjects.r('list(E01=1e-6, E02=1e-6, phi=-3.14 , T2_1=.001, T2_2=.001)')
  366. upper = robjects.r('list(E01=1.00, E02=1.0, phi=3.14 , T2_1=.800, T2_2=.8)')
  367. else:
  368. if CorrectDC:
  369. fmla = robjects.Formula('XY ~ c(Xc1( E01, df, tt, phi, T2_1, DC), Yc1( E01, df, tt, phi, T2_1,DC))')
  370. if CorrectFreq:
  371. start = robjects.r('list(E01=.100, df=0 , phi=0. , T2_1=.100, DC=0.0)')
  372. lower = robjects.r('list(E01=1e-6, df=-50., phi=-3.14, T2_1=.001, DC=0.0)')
  373. upper = robjects.r('list(E01=1.00, df=50. , phi=3.14 , T2_1=.800, DC=0.5)')
  374. else:
  375. start = robjects.r('list(E01=.100, phi= 0. , T2_1=.100, DC=0.0)')
  376. lower = robjects.r('list(E01=1e-6, phi=-3.13, T2_1=.001, DC=0.0)')
  377. upper = robjects.r('list(E01=1.00, phi= 3.13, T2_1=.800, DC=0.5)')
  378. else:
  379. fmla = robjects.Formula('XY ~ c(Xc1( E01, df, tt, phi, T2_1), Yc1( E01, df, tt, phi, T2_1))')
  380. if CorrectFreq:
  381. start = robjects.r('list(E01=.100, df=0 , phi=0. , T2_1=.100)')
  382. lower = robjects.r('list(E01=1e-6, df=-50. , phi=-3.14 , T2_1=.001)')
  383. upper = robjects.r('list(E01=1.00, df=50. , phi=3.14 , T2_1=.800)')
  384. else:
  385. start = robjects.r('list(E01=.100, phi= 0. , T2_1=.100)')
  386. lower = robjects.r('list(E01=1e-6, phi=-3.13, T2_1=.001)')
  387. upper = robjects.r('list(E01=1.00, phi= 3.13, T2_1=.800)')
  388. env = fmla.getenvironment()
  389. env['Zero'] = Zero
  390. env['X'] = X
  391. env['Y'] = Y
  392. env['XY'] = XY
  393. env['tt'] = tt
  394. cont = robjects.r('nls.control(maxiter=10000, warnOnly=TRUE, printEval=FALSE)')
  395. fit = robjects.r.tryCatch(robjects.r.nls(fmla, start=start, control=cont, lower=lower, upper=upper, algorithm='port')) #, \
  396. #fit = robjects.r.tryCatch(robjects.r.nls(fmla, start=start, control=cont)) #, \
  397. report = r.summary(fit)
  398. conv = r['$'](fit,'convergence')[0]
  399. #if conv:
  400. # print (report)
  401. # print ("conv", conv)
  402. print ("Conv", r['$'](fit,'convergence')) # T2
  403. print (report)
  404. if BiExp:
  405. if CorrectFreq:
  406. E0 = r['$'](report,'par')[0] # E01
  407. E0 += r['$'](report,'par')[1] # E02
  408. df = r['$'](report,'par')[2] # offset
  409. phi = r['$'](report,'par')[3] # phase
  410. T2 = r['$'](report,'par')[4] # T2
  411. else:
  412. E0 = r['$'](report,'par')[0] # E01
  413. E0 += r['$'](report,'par')[1] # E02
  414. phi = r['$'](report,'par')[2] # phase
  415. T2 = r['$'](report,'par')[3] # T2
  416. else:
  417. if CorrectFreq:
  418. E0 = r['$'](report,'par')[0] # E01
  419. df = r['$'](report,'par')[1] # offset
  420. phi = r['$'](report,'par')[2] # phase
  421. T2 = r['$'](report,'par')[3] # T2
  422. else:
  423. E0 = r['$'](report,'par')[0] # E01
  424. phi = r['$'](report,'par')[1] # phase
  425. T2 = r['$'](report,'par')[2] # T2
  426. #phi = 0.907655876627
  427. #phi = 0
  428. #print ("df", df)# = 0
  429. return conv, E0,df,phi,T2
  430. #################################################
  431. # Regress for T2 using rpy2 interface
  432. def regressSpec(w, wL, X): #,sigma2=1,intercept=True):
  433. # compute s
  434. s = -1j*w
  435. # TODO, if regression fails, it might be because there is no exponential
  436. # term, maybe do a second regression then on a linear model.
  437. a = 0 # Linear
  438. rT2 = 0.1 # T2 regressed
  439. r = robjects.r
  440. # Variable shared between R and Python
  441. robjects.globalenv['a'] = a
  442. robjects.globalenv['rT2'] = rT2
  443. robjects.globalenv['wL'] = wL
  444. robjects.globalenv['nb'] = 0
  445. s = robjects.ComplexVector(numpy.array(s))
  446. XX = robjects.ComplexVector(X)
  447. Xr = robjects.FloatVector(numpy.real(X))
  448. Xi = robjects.FloatVector(numpy.imag(X))
  449. Xa = robjects.FloatVector(numpy.abs(X))
  450. Xri = robjects.FloatVector(numpy.concatenate((Xr,Xi)))
  451. #my_lower = robjects.r('list(a=.001, rT2=.001, nb=.0001)')
  452. my_lower = robjects.r('list(a=.001, rT2=.001)')
  453. #my_upper = robjects.r('list(a=1.5, rT2=.300, nb =100.)')
  454. my_upper = robjects.r('list(a=1.5, rT2=.300)')
  455. #my_list = robjects.r('list(a=.2, rT2=0.03, nb=.1)')
  456. my_list = robjects.r('list(a=.2, rT2=0.03)')
  457. my_cont = robjects.r('nls.control(maxiter=5000, warnOnly=TRUE, printEval=FALSE)')
  458. #fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
  459. ##fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
  460. #fmla = robjects.Formula('XX ~ a*(wL) / (wL^2 + (s+1/rT2)^2 )') # complex
  461. #fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 )) + nb') # complex
  462. fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 ))') # complex
  463. env = fmla.getenvironment()
  464. env['s'] = s
  465. env['Xr'] = Xr
  466. env['Xa'] = Xa
  467. env['Xi'] = Xi
  468. env['Xri'] = Xri
  469. env['XX'] = XX
  470. #fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list, control=my_cont)) #, lower=my_lower, algorithm='port')) #, \
  471. fit = robjects.r.tryCatch(robjects.r.nls(fmla, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
  472. report = r.summary(fit)
  473. #print report
  474. #print r.warnings()
  475. a = r['$'](report,'par')[0]
  476. rT2 = r['$'](report,'par')[1]
  477. nb = r['$'](report,'par')[2]
  478. return a, rT2, nb
  479. #################################################
  480. # Regress for T2 using rpy2 interface
  481. def regressSpecComplex(w, wL, X): #,sigma2=1,intercept=True):
  482. # compute s
  483. s = -1j*w
  484. # TODO, if regression fails, it might be because there is no exponential
  485. # term, maybe do a second regression then on a linear model.
  486. a = 1 # Linear
  487. rT2 = 0.1 # T2 regressed
  488. r = robjects.r
  489. phi2 = 0 # phase
  490. wL2 = wL
  491. # Variable shared between R and Python
  492. robjects.globalenv['a'] = a
  493. robjects.globalenv['rT2'] = rT2
  494. robjects.globalenv['wL'] = wL
  495. robjects.globalenv['wL2'] = 0
  496. robjects.globalenv['nb'] = 0
  497. robjects.globalenv['phi2'] = phi2
  498. s = robjects.ComplexVector(numpy.array(s))
  499. XX = robjects.ComplexVector(X)
  500. Xr = robjects.FloatVector(numpy.real(X))
  501. Xi = robjects.FloatVector(numpy.imag(X))
  502. Xa = robjects.FloatVector(numpy.abs(X))
  503. Xri = robjects.FloatVector(numpy.concatenate((X.real,X.imag)))
  504. robjects.r('''
  505. source('kernel.r')
  506. ''')
  507. #Kw = robjects.globalenv['Kwri']
  508. #print (numpy.shape(X))
  509. #my_lower = robjects.r('list(a=.001, rT2=.001, nb=.0001)')
  510. #my_lower = robjects.r('list(a=.001, rT2=.001)') # Working
  511. my_lower = robjects.r('list(a=.001, rT2=.001, phi2=-3.14, wL2=wL-5)')
  512. #my_upper = robjects.r('list(a=1.5, rT2=.300, nb =100.)')
  513. my_upper = robjects.r('list(a=3.5, rT2=.300, phi2=3.14, wL2=wL+5)')
  514. #my_list = robjects.r('list(a=.2, rT2=0.03, nb=.1)')
  515. my_list = robjects.r('list(a=.2, rT2=0.03, phi2=0, wL2=wL)')
  516. my_cont = robjects.r('nls.control(maxiter=5000, warnOnly=TRUE, printEval=FALSE)')
  517. #fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
  518. #fmla = robjects.Formula('Xi ~ Im(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 ))') # envelope
  519. #fmla = robjects.Formula('Xri ~ c(Re(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 )), Im(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 )))') # envelope
  520. #fmlar = robjects.Formula('Xr ~ (Kwr(a, phi2, s, rT2, wL)) ') # envelope
  521. #fmlai = robjects.Formula('Xi ~ (Kwi(a, phi2, s, rT2, wL)) ') # envelope
  522. fmla = robjects.Formula('Xri ~ c(Kwr(a, phi2, s, rT2, wL2), Kwi(a, phi2, s, rT2, wL2) ) ') # envelope
  523. #fmla = robjects.Formula('Xri ~ (Kwri(a, phi2, s, rT2, wL)) ') # envelope
  524. #fmla = robjects.Formula('Xa ~ (abs(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 )))') # envelope
  525. #fmla = robjects.Formula('XX ~ a*(wL) / (wL^2 + (s+1/rT2)^2 )') # complex
  526. #fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 )) + nb') # complex
  527. #fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
  528. # self.Gw[iw, iT2] = ((np.sin(phi2) * (alpha + 1j*self.w[iw]) + self.wL*np.cos(phi2)) / \
  529. # (self.wL**2 + (alpha+1.j*self.w[iw])**2 ))
  530. # self.Gw[iw, iT2] = ds * self.sc*((np.sin(phi2)*( alpha + 1j*self.w[iw]) + self.wL*np.cos(phi2)) / \
  531. # (self.wL**2 + (alpha+1.j*self.w[iw])**2 ))
  532. # Works Amplitude Only!
  533. #fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 ))') # complex
  534. env = fmla.getenvironment()
  535. env['s'] = s
  536. env['Xr'] = Xr
  537. env['Xa'] = Xa
  538. env['Xi'] = Xi
  539. env['Xri'] = Xri
  540. env['XX'] = XX
  541. fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list, control=my_cont)) #, lower=my_lower, algorithm='port')) #, \
  542. #fitr = robjects.r.tryCatch(robjects.r.nls(fmlar, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
  543. #env = fmlai.getenvironment()
  544. #fiti = robjects.r.tryCatch(robjects.r.nls(fmlai, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
  545. #reportr = r.summary(fitr)
  546. #reporti = r.summary(fiti)
  547. report = r.summary(fit)
  548. #print( report )
  549. #exit()
  550. #print( reportr )
  551. #print( reporti )
  552. #exit()
  553. #print r.warnings()
  554. #a = (r['$'](reportr,'par')[0] + r['$'](reporti,'par')[0]) / 2.
  555. #rT2 = (r['$'](reportr,'par')[1] + r['$'](reporti,'par')[1]) / 2.
  556. #nb = (r['$'](reportr,'par')[2] + r['$'](reporti,'par')[2]) / 2.
  557. a = r['$'](report,'par')[0]
  558. rT2 = r['$'](report,'par')[1]
  559. nb = r['$'](report,'par')[2] #phi2
  560. print ("Python wL2", r['$'](report,'par')[3] )
  561. print ("Python zeta", r['$'](report,'par')[2] )
  562. return a, rT2, nb
  563. ###################################################################
  564. ###################################################################
  565. ###################################################################
  566. if __name__ == "__main__":
  567. dt = .0001
  568. T2 = .1
  569. omega = 2000.*2*numpy.pi
  570. phi = .0
  571. T = 8.*T2
  572. t = numpy.arange(0, T, dt)
  573. # Synthetic data, simple single decaying sinusoid
  574. # with a single decay parameter and gaussian noise added
  575. data = numpy.exp(-t/T2) * numpy.sin(omega * t + phi) + numpy.random.normal(0,.05,len(t)) \
  576. + numpy.random.randint(-1,2,len(t))*numpy.random.exponential(.2,len(t))
  577. cdata = numpy.exp(-t/T2) * numpy.sin(omega * t + phi) #+ numpy.random.normal(0,.25,len(t))
  578. #data = numpy.random.normal(0,.25,len(t))
  579. sigma2 = numpy.std(data[::-len(data)/4])
  580. #sigma2 = numpy.var(data[::-len(data)/4])
  581. print("sigma2", sigma2)
  582. [peaks,times,indices] = peakPicker(data, omega, dt)
  583. [b1,b2,rT2] = regressCurve(peaks,times)
  584. print("rT2 nonweighted", rT2)
  585. [b1,b2,rT2] = regressCurve(peaks,times,sigma2)
  586. print("rT2 weighted", rT2)
  587. envelope = numpy.exp(-t/T2)
  588. renvelope = numpy.exp(-t/rT2)
  589. #outf = file('regress.txt','w')
  590. #for i in range(len(times)):
  591. # outf.write(str(times[i]) + " " + str(peaks[i]) + "\n")
  592. #outf.close()
  593. plt.plot(t,data, 'b')
  594. plt.plot(t,cdata, 'g', linewidth=1)
  595. plt.plot(t,envelope, color='violet', linewidth=4)
  596. plt.plot(t,renvelope, 'r', linewidth=4)
  597. plt.plot(times, numpy.array(peaks), 'bo', markersize=8, alpha=.25)
  598. plt.legend(['noisy data','clean data','real envelope','regressed env','picks'])
  599. plt.savefig("regression.pdf")
  600. # FFT check
  601. fourier = fft(data)
  602. plt.figure()
  603. freq = fftfreq(len(data), d=dt)
  604. plt.plot(freq, (fourier.real))
  605. plt.show()
  606. # TODO do a bunch in batch mode to see if T2 estimate is better with or without
  607. # weighting and which model is best.
  608. # TODO try with real data
  609. # TODO test filters (median, FFT, notch)
  610. # It looks like weighting is good for relatively low sigma, but for noisy data
  611. # it hurts us. Check