phase-encoding-method-of-moments.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. from scipy.optimize import differential_evolution
  4. from scipy.optimize import minimize
  5. from scipy.special import gamma, binom
  6. import numpy as np
  7. voxel_num = 2
  8. phase_range = np.pi/2
  9. phase_init = 0.0
  10. U_points = voxel_num * 1000
  11. noise_ratio = 0.0 #1e8
  12. total_periods = 8
  13. rf_samples_per_period = 16
  14. # B0=1.5T freq=64Mhz, period = 15.6 ns
  15. period = 15.6/1000/1000 #ms
  16. omega = 2.0*np.pi/period
  17. #T2s_scale = 0.01 #ms # need to be 10ms
  18. T2s_scale = total_periods*period #ms # need to be 10ms
  19. T2s_min = T2s_scale/1000.0
  20. #print(period)
  21. #ms
  22. time_steps = np.linspace(0, period*total_periods, rf_samples_per_period*total_periods)
  23. voxel_amplitudes = np.random.rand(voxel_num)
  24. voxel_T2s_decay = np.random.rand(voxel_num)*(T2s_scale-T2s_min) + T2s_min
  25. voxel_all = np.append(voxel_amplitudes,voxel_T2s_decay/T2s_scale)
  26. if voxel_num == 5:
  27. voxel_all = np.array([0.822628,0.691376,0.282906,0.226013,0.90703,0.144985,0.328563,0.440353,0.662462,0.720518])
  28. #voxel_all = [0.592606,0.135168,0.365712,0.667536,0.437378,0.918822,0.943879,0.590338,0.685997,0.658839]
  29. voxel_amplitudes = voxel_all[:voxel_num]
  30. voxel_T2s_decay = voxel_all[voxel_num:]*T2s_scale
  31. #first estimate 0.551777 0.190833 0.271438 0.814036 0.347389 0.926153 0.908453 0.581414 0.666012 0.673226
  32. #voxel_amplitudes = [0.4, 0.8, 0]
  33. #voxel_amplitudes = [0.9, 0.092893218813452, 0.5]
  34. #voxel_amplitudes = [0.6, 0.517157287525381, 0.4]
  35. test_amplitudes = np.zeros(voxel_num)
  36. test_amplitudes = voxel_amplitudes
  37. voxel_phases = np.linspace(0,phase_range, voxel_num)
  38. if len(voxel_amplitudes) != len(voxel_phases):
  39. print("ERROR! Size of amplitude and phase arrays do not match!")
  40. raise
  41. def gen_rf_signal(time):
  42. mag_sin = 0.0
  43. mag_cos = 0.0
  44. for i in range(voxel_num):
  45. amp = voxel_amplitudes[i] * (
  46. np.exp(-time/voxel_T2s_decay[i])
  47. ) + ( 0.0
  48. # + np.random.rand()*noise_ratio
  49. )
  50. mag_sin += amp * np.sin(
  51. voxel_phases[i] + phase_init
  52. )
  53. mag_cos += amp * np.cos(
  54. voxel_phases[i] + phase_init
  55. )
  56. return mag_sin, mag_cos
  57. def factorial(n):
  58. return gamma(n+1)
  59. def shiftedLegendre(n):
  60. coeffs = []
  61. for k in range(n+1):
  62. val = (-1)**n * binom(n,k) * binom(n+k,k) * (-1)**k
  63. coeffs.insert(0,val)
  64. return np.poly1d(coeffs)
  65. def K ( i, j):
  66. polyL = L[i] #shiftedLegendre(i)
  67. return polyL.coeffs[-j-1]
  68. def GetLambda(mag_rf):
  69. M_cutoff = len(mag_rf)
  70. all_lambda = []
  71. for i in range(M_cutoff):
  72. lambd = 0
  73. for j in range(i+1):
  74. lambd += K(i,j)*mag_rf[i]
  75. all_lambda.append(lambd)
  76. all_lambda = np.zeros(M_cutoff)
  77. all_lambda[19] = 1
  78. return all_lambda
  79. def GetU (lambdas):
  80. x = np.linspace(0,1, U_points)
  81. U = np.zeros(U_points)
  82. for i in range (len(lambdas)):
  83. polyL = L[i] #shiftedLegendre(i)
  84. U += lambdas[i]*polyL(x)
  85. return U
  86. mag_sin, mag_cos = gen_rf_signal(time_steps)
  87. L = [] # Shifted Legendre polinomials
  88. for i in range(len(mag_sin)):
  89. polyL = shiftedLegendre(i)
  90. L += [polyL]
  91. #print(len(L))
  92. print(L[20])
  93. lambdas = GetLambda(mag_sin)
  94. U = GetU(lambdas)
  95. import matplotlib.pyplot as plt
  96. x = np.linspace(0,1, U_points)
  97. mag_x = np.linspace(0,1, len(mag_sin))
  98. # crop = 1
  99. # plt.plot(x[:-crop],U[:-crop])
  100. plt.plot(x,U)
  101. # plt.plot(mag_x,mag_sin)
  102. #plt.xlim(0.2,0.8)
  103. #plt.ylim(0.0,2.8)
  104. plt.savefig("plt.pdf")
  105. #plt.show()
  106. #print(voxel_phases)
  107. #print (voxel_amplitudes)
  108. # import matplotlib.pyplot as plt
  109. # plt.plot(time_steps, mag_sin)
  110. # plt.plot(time_steps, mag_cos)
  111. # plt.show()
  112. # #print(fitness(test_amplitudes))
  113. amplitude_minmax = (0,1)
  114. T2s_minmax = (T2s_min/T2s_scale,1)
  115. x0 = np.full(2*voxel_num,0.5)
  116. x0 = [0.551777,0.190833,0.271438,0.814036,0.347389,0.926153,0.908453,0.581414,0.666012,0.673226]
  117. # #result.x[voxel_num:] = result.x[voxel_num:]/T2s_scale
  118. # print("amp/decay", voxel_amplitudes,voxel_T2s_decay)
  119. # print("all ", voxel_all)
  120. # print("eval ",result.x, "\n=====> fun=",result.fun)
  121. # # print("Diff")
  122. # # print((voxel_amplitudes-result.x))
  123. # # print("percent")
  124. # print("percent",np.abs(voxel_all-result.x)*100)
  125. # if np.max(np.abs(voxel_all[:voxel_num]-result.x[:voxel_num])*100)>0.5:
  126. # print ("============== !!!LARGE!!! ===============")
  127. # print("\n")