pade-method-of-moments.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #!/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. #from scipy.special import gamma, binom
  4. import numpy as np
  5. import matplotlib.pyplot as plt
  6. import scipy.sparse as sparse
  7. from scipy.sparse.linalg import eigsh
  8. from numpy.linalg import eig
  9. from mpmath import mp, mpf
  10. mp.dps = 2000
  11. voxel_num = 5
  12. phase_range = np.pi/2 *0.0
  13. phase_init = np.pi/2 #(0.0)
  14. U_points = voxel_num * 3000
  15. noise_ratio = (1.2e-16) #(1.2e-16) #1e8
  16. total_periods=5#10#DO NOT CHANGE to fit T2s_scale autoscale
  17. rf_samples_per_period = 2
  18. # max polynomial order equals rf_samples_per_period * total_periods
  19. # B0=1.5T freq=64Mhz, period = 15.6 ns
  20. period = (10.0) #ms
  21. omega = 2.0*np.pi/period
  22. #T2s_scale = 0.01 #ms # need to be 10ms
  23. T2s_scale = total_periods*period/rf_samples_per_period/voxel_num*8 #ms # need to be 10ms
  24. T2s_min = T2s_scale/20.0
  25. #ms
  26. total_steps = rf_samples_per_period*total_periods
  27. n_mu = total_steps
  28. #if total_steps % 2 != 0: total_steps -= 1
  29. time_steps = np.array(mp.linspace((0), (period*total_periods), total_steps))
  30. tmp = [np.random.rand()*0.0+(1.0) for n in range(voxel_num)]
  31. voxel_amplitudes = np.array(tmp)
  32. tmp = [np.random.rand() for n in range(voxel_num)]
  33. voxel_T2s_decay = np.sort(np.array(tmp))*(T2s_scale-2*T2s_min) + T2s_min
  34. voxel_all = np.append(voxel_amplitudes,voxel_T2s_decay/T2s_scale)
  35. if voxel_num == 5:
  36. # voxel_all = np.array([mpf(0.2),(0.6),(0.02),(0.1)])
  37. voxel_all = np.array([(0.822628),(0.691376),(0.282906),(0.226013),(0.90703),(0.144985),(0.228563),(0.340353),(0.462462),(0.720518)])
  38. #voxel_all = np.array([(0.592606),(0.135168),(0.365712),(0.667536),(0.437378),(0.918822),(0.943879),(0.590338),(0.685997),(0.658839)])
  39. voxel_amplitudes = voxel_all[:voxel_num]
  40. voxel_T2s_decay = voxel_all[voxel_num:]*T2s_scale
  41. a_i = np.array([(0.3),(0.1),(0.15),(0.1),(0.2)])
  42. d_i = np.array([(0.7),(0.9),(0.2),(0.67),(0.41)])
  43. voxel_num = len(a_i)
  44. voxel_phases = np.array(np.linspace(0,phase_range, voxel_num))
  45. # if len(voxel_amplitudes) != len(voxel_phases):
  46. # print("ERROR! Size of amplitude and phase arrays do not match!")
  47. # raise
  48. ampl = []
  49. def gen_rf_signal(time):
  50. '''Generates demodulated signal at radio frequence using voxels
  51. amplitudes, T2s decays, and phases.
  52. '''
  53. tmp = [mpf(0.0) for n in range(len(time))]
  54. mag_sin = np.array(tmp)
  55. mag_cos = np.array(tmp)
  56. v_sum = 0
  57. for t in range(len(time)):
  58. for i in range(voxel_num):
  59. mag_sin[t] += a_i[i]*(
  60. (d_i[i] + np.random.rand()*noise_ratio)**t
  61. )
  62. # amp = voxel_amplitudes[i] * (
  63. # mp.exp(-time[t]/voxel_T2s_decay[i])
  64. # ) + ( 0.0
  65. # # + np.random.rand()*noise_ratio
  66. # )
  67. # # if t == 0:
  68. # #print("a_{:d}".format(i),float(voxel_amplitudes[i]* np.sin(voxel_phases[i] + phase_init)))
  69. # #print("d_{:d}".format(i),float( np.exp(-(period/rf_samples_per_period)/voxel_T2s_decay[i]) ))
  70. # mag_sin[t] += amp * np.sin((voxel_phases[i] + phase_init))
  71. # mag_cos[t] += amp * np.cos((voxel_phases[i] + phase_init))
  72. # if t == 0:
  73. # v = voxel_amplitudes[i] * (
  74. # mp.exp(-(time[1])/voxel_T2s_decay[i])
  75. # )* np.sin((voxel_phases[i] + phase_init))
  76. # v_sum += v
  77. # print(float(v))
  78. # #sign+="{:4.3g}, ".format(float( mp.exp(-(period/rf_samples_per_period)/voxel_T2s_decay[i]) ))
  79. mag_sin[t] *= (1 + (np.random.rand()-0.5)*noise_ratio)
  80. # if t == 0:
  81. # print(v_sum, mag_sin[t])
  82. #mag_cos[t] += np.random.rand()*noise_ratio
  83. return mag_sin, mag_cos
  84. mag_sin_0, mag_cos_0 = gen_rf_signal(time_steps)
  85. mag_sin = np.copy(mag_sin_0)
  86. mag_cos = np.copy(mag_cos_0)
  87. # mu = [np.random.rand() for i in range(n_mu)]
  88. mu = mag_sin
  89. #print(mu)
  90. P = np.zeros((n_mu+1, n_mu+1),dtype=mpf)
  91. P[0,0] = 1
  92. for i in range(n_mu):
  93. P[i,1] = (-1)**i * mu[i]
  94. for j in range(2,n_mu+1):
  95. for i in range(n_mu-1,-1,-1):
  96. if i+j > n_mu: continue
  97. # print("i =",i, " j =",j, " P = ",P[i,j])
  98. P[i,j] = P[0,j-1]*P[i+1,j-2] - P[0,j-2]*P[i+1,j-1]
  99. # for i in range (n_mu+1):
  100. # line = [float("%5.3g"%(x)) for x in P[i,:]]
  101. # print(line)
  102. #print(P)
  103. alpha = np.zeros(n_mu,dtype=mpf)
  104. for k in range(1,n_mu):
  105. alpha[k] = (P[0,k+1])/((P[0,k])*(P[0,k-1]))
  106. # print("alpha:",len(alpha))
  107. # line = [float("%5.5g"%(x)) for x in alpha]
  108. # print(line)
  109. M=np.zeros((voxel_num,voxel_num), dtype=mpf)
  110. for i in range(voxel_num):
  111. for j in range(voxel_num):
  112. if i == j:
  113. M[i,j] = alpha[i*2]+alpha[i*2 +1]
  114. if abs(i-j) == 1:
  115. m = max(i,j)
  116. M[i,j] = -np.sqrt( alpha[2*m-1] * alpha[2*m] )
  117. M1 = mp.matrix(M.tolist())
  118. #print(M1)
  119. spectra = mp.eig(M1)[0]
  120. line = [float("%5.5g"%(x)) for x in spectra]
  121. print("eig(M1) =",line)
  122. # print("N = ",len(mag_sin))
  123. # print("Noise = ", noise_ratio )
  124. # print("c_n =",["%0.8f"%(x) for x in mag_sin])
  125. sign = ""
  126. # for i in range(voxel_num):
  127. # if i%5 == 0:
  128. # sign+="\n"
  129. # sign = sign + '{:3.2g}'.format(float(a_i[i]))+"/"+'{:3.2g}'.format(float(d_i[i]))+", "
  130. #
  131. # # print(mp.exp(-1.0/voxel_T2s_decay[i]))
  132. x = np.linspace(0,1, U_points)
  133. import time
  134. time1 = time.time()
  135. time2 = time.time()
  136. #print( 'It took %0.5f s' % ((time2-time1)))
  137. sign =""
  138. for i in range(voxel_num):
  139. sign+="{:4.3g}, ".format(float( mp.exp(-(period/rf_samples_per_period)/voxel_T2s_decay[i]) ))
  140. print(d_i)
  141. # x = np.linspace(0,1, U_points)
  142. # mag_x = np.linspace(0,1, len(mag_sin))
  143. # import matplotlib as matplotlib
  144. # matplotlib.rcParams.update({'font.size': 28})
  145. # plt.figure(figsize=(30, 20))
  146. # plt.plot(x,U, lw=0.2)
  147. # plt.title(r"$\sum^M \lambda_i L_i(x)$", y=1.02)
  148. # plt.xlim(0,1)
  149. # plt.xlabel(sign, fontsize=28)
  150. # plt.savefig("plt.pdf")
  151. # plt.clf()
  152. plt.plot(mag_sin, ls=' ', marker='o')
  153. plt.title("Signal to restore amp/decay_T:"+sign)
  154. plt.savefig("signal.pdf")
  155. plt.clf()