phase-encoding-simple.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #!/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. from scipy.optimize import differential_evolution
  4. from scipy.optimize import minimize
  5. import numpy as np
  6. voxel_num = 5
  7. phase_range = np.pi/2
  8. phase_init = 0.0
  9. noise_ratio = 0.0 #1e8
  10. total_periods = 50
  11. rf_samples_per_period = 1
  12. # B0=1.5T freq=64Mhz, period = 15.6 ns
  13. period = 15.6/1000/1000 #ms
  14. omega = 2.0*np.pi/period
  15. #T2s_scale = 0.01 #ms # need to be 10ms
  16. T2s_scale = total_periods*period #ms # need to be 10ms
  17. T2s_min = T2s_scale/1000.0
  18. #print(period)
  19. #ms
  20. time_steps = np.linspace(0, period*total_periods, rf_samples_per_period*total_periods)
  21. voxel_amplitudes = np.random.rand(voxel_num)
  22. voxel_T2s_decay = np.random.rand(voxel_num)*(T2s_scale-T2s_min) + T2s_min
  23. voxel_all = np.append(voxel_amplitudes,voxel_T2s_decay/T2s_scale)
  24. if voxel_num == 5:
  25. voxel_all = [0.822628,0.691376,0.282906,0.226013,0.90703,0.144985,0.328563,0.440353,0.662462,0.720518]
  26. voxel_all = [0.592606,0.135168,0.365712,0.667536,0.437378,0.918822,0.943879,0.590338,0.685997,0.658839]
  27. #first estimate 0.551777 0.190833 0.271438 0.814036 0.347389 0.926153 0.908453 0.581414 0.666012 0.673226
  28. #voxel_amplitudes = [0.4, 0.8, 0]
  29. #voxel_amplitudes = [0.9, 0.092893218813452, 0.5]
  30. #voxel_amplitudes = [0.6, 0.517157287525381, 0.4]
  31. test_amplitudes = np.zeros(voxel_num)
  32. test_amplitudes = voxel_amplitudes
  33. voxel_phases = np.linspace(0,phase_range, voxel_num)
  34. #print(voxel_phases)
  35. if len(voxel_amplitudes) != len(voxel_phases):
  36. print("ERROR! Size of amplitude and phase arrays do not match!")
  37. raise
  38. def gen_rf_signal(time):
  39. mag_sin = 0.0
  40. mag_cos = 0.0
  41. for i in range(voxel_num):
  42. amp = voxel_amplitudes[i] * (
  43. np.exp(-time/voxel_T2s_decay[i])
  44. ) + ( 0.0
  45. # + np.random.rand()*noise_ratio
  46. )
  47. mag_sin += amp * np.sin(
  48. voxel_phases[i] + phase_init
  49. )
  50. mag_cos += amp * np.cos(
  51. voxel_phases[i] + phase_init
  52. )
  53. return mag_sin, mag_cos
  54. def assumed_signal(time, values):
  55. amplitudes = values[:voxel_num]
  56. T2s_decay = values[voxel_num:]*T2s_scale
  57. mag_sin = 0.0
  58. mag_cos = 0.0
  59. for i in range(voxel_num):
  60. amp = amplitudes[i] * (
  61. np.exp(-time/T2s_decay[i])
  62. )
  63. mag_sin += amp * np.sin(
  64. voxel_phases[i] + phase_init
  65. )
  66. mag_cos += amp * np.cos(
  67. voxel_phases[i] + phase_init
  68. )
  69. return mag_sin, mag_cos
  70. mag_sin, mag_cos = gen_rf_signal(time_steps)
  71. def fitness(amplitudes, *args):
  72. assumed_sin, assumed_cos = assumed_signal(time_steps, amplitudes)
  73. diff = 0
  74. #amp = np.sqrt(mag_sin**2 + mag_cos**2)
  75. # diff += np.sqrt(np.mean(np.square((mag_sin - assumed_sin)/amp)))
  76. # diff += np.sqrt(np.mean(np.square((mag_cos - assumed_cos)/amp)))
  77. diff += np.sqrt(np.mean(np.square((mag_sin - assumed_sin))))
  78. diff += np.sqrt(np.mean(np.square((mag_cos - assumed_cos))))
  79. diff += np.sqrt(np.mean(np.square(mag_sin/mag_cos - assumed_sin/assumed_cos)))
  80. return diff
  81. def hyper_fit(amplitudes, *args):
  82. result = minimize(fitness, amplitudes, bounds = bounds, method='L-BFGS-B', options={'ftol': 1e-16,'gtol': 1e-16, 'disp': False})
  83. print (result.fun)
  84. return result.fun
  85. #print(voxel_phases)
  86. #print (voxel_amplitudes)
  87. # import matplotlib.pyplot as plt
  88. # plt.plot(time_steps, mag_sin)
  89. # plt.plot(time_steps, mag_cos)
  90. # plt.show()
  91. # #print(fitness(test_amplitudes))
  92. bounds = []
  93. amplitude_minmax = (0,1)
  94. T2s_minmax = (T2s_min/T2s_scale,1)
  95. for i in range(voxel_num):
  96. bounds.append(amplitude_minmax)
  97. for i in range(voxel_num):
  98. bounds.append(T2s_minmax)
  99. x0 = np.full(2*voxel_num,0.5)
  100. x0 = [0.551777,0.190833,0.271438,0.814036,0.347389,0.926153,0.908453,0.581414,0.666012,0.673226]
  101. # result = minimize(hyper_fit, x0, bounds = bounds, method='L-BFGS-B', options={'ftol': 1e-16,'gtol': 1e-16, 'disp': True})
  102. result = minimize(fitness, x0, bounds = bounds, method='L-BFGS-B', options={'ftol': 1e-16,'gtol': 1e-16, 'disp': True})
  103. # result = differential_evolution(hyper_fit, bounds, polish=True
  104. # , maxiter = voxel_num*2*500
  105. # , disp = True
  106. # )
  107. # bestresult = minimize(fitness, x0, bounds = bounds, method='L-BFGS-B', options={'ftol': 1e-16,'gtol': 1e-16, 'disp': True})
  108. # for x in range(50):
  109. # print("Try to solve: ", x)
  110. # x0 = np.random.rand(2*voxel_num)
  111. # result = minimize(fitness, x0, bounds = bounds, method='L-BFGS-B', options={'ftol': 1e-16,'gtol': 1e-16, 'disp': False})
  112. # if result.fun < bestresult.fun:
  113. # bestresult = result
  114. # print("new best: ", bestresult.fun)
  115. # result = bestresult
  116. #result = minimize(fitness, x0, bounds = bounds, method='COBYLA', tol=1e-16, options={ 'maxiter':20000,'disp': True})
  117. #result = minimize(fitness, result.x, bounds = bounds, method='L-BFGS-B', options={'gtol': 1e-16, 'disp': True})
  118. #result = minimize(hyper_fit, x0, bounds = bounds, method='Nelder-Mead', tol=1e-16, options={'maxiter':100,'disp': True})
  119. #result.x[voxel_num:] = result.x[voxel_num:]/T2s_scale
  120. print("amp/decay", voxel_amplitudes,voxel_T2s_decay)
  121. print("all ", voxel_all)
  122. print("eval ",result.x, "\n=====> fun=",result.fun)
  123. # print("Diff")
  124. # print((voxel_amplitudes-result.x))
  125. # print("percent")
  126. print("percent",np.abs(voxel_all-result.x)*100)
  127. if np.max(np.abs(voxel_all[:voxel_num]-result.x[:voxel_num])*100)>0.5:
  128. print ("============== !!!LARGE!!! ===============")
  129. print("\n")