Surface NMR processing and inversion GUI
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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