def test_one(save_png=False): """Perform the first test demonstrating a pi/2 pulse.""" # create output figure fig = plt.figure(figsize=(7, 7)) ax1 = fig.add_subplot(221) ax2 = fig.add_subplot(222, projection='3d') ax3 = fig.add_subplot(223) ax4 = fig.add_subplot(224, projection='3d') # initialize pulse Bloch class bloch = pulse(T1=0.001, T2=0.0005, t_sim=0.005) # solve bloch.solve(m_init=bloch.zunit) # create lab-frame plots bloch.plot_magnetization(ax1, version='lab') bloch.plot_magnetization3d(ax2, version='lab') # create rot-frame plots bloch.plot_magnetization(ax3, version='rot') bloch.plot_magnetization3d(ax4, version='rot') # adjust axes position low, bot, wid, hei = ax1.get_position().bounds ax1.set_position([low, bot * 1.1, wid, hei - 0.05]) low, bot, wid, hei = ax3.get_position().bounds ax3.set_position([low, bot * 1.1, wid, hei - 0.05]) # adjust titles ax1.set_title(r'$^1$H | B0 = {:.1f}$\mu$T'.format(bloch.B0 * 1e6)) ax2.set_title(r'$\gamma>0$') ax3.set_title(r'$^1$H | B1 ~ {:.2f}$\mu$T'.format(bloch.Pulse.factor * bloch.B0 * 1e6)) ax4.set_title(r'$(\pi/2)_{+x}$ - pulse') # adjust legends ax1.legend(prop={"size": 8}, loc='lower left') ax3.legend(prop={"size": 8}, loc='lower right') # save figure if save_png: fig.savefig('example2a.png', dpi=300)
def test_four(save_png=False): """Perform the fourth test demonstrating different off-resonances. here we basically re-plot Fig. 10.28 (p. 255) from Levitt, 2008, "spin dynamics" 2nd ed positive ratio means the pulse frequency is "higher" as absolute value (i.e. instead of -2000 Hz it is -2100 Hz) because of the negative Larmor frequency of H-protons the rotation axis dips downwards for negative ratios """ # initialize pulse Bloch class bloch = pulse(T1=0.001, T2=0.0005, t_sim=0.005) # pulse axis bloch.Pulse.axis = '+y' # df/omega_nut ratio ratio = np.arange(-4., 5., 1.) # nutation frequency for a pi/2 pulse with 5 ms is 50 Hz omega_nut = (np.pi / 2.0) / bloch.Pulse.t_pulse / 2.0 / np.pi # [Hz] # create output figure fig = plt.figure(figsize=(7, 7)) for i in np.arange(len(ratio)): # frequency offsets [Hz] freq_offset = ratio[i] * omega_nut # update frequency offset parameter bloch.Pulse.fmod.v_range[1] = freq_offset # solve bloch.solve(m_init=bloch.zunit) # create rot-frame plot ax1 = fig.add_subplot(331 + i, projection='3d') bloch.plot_magnetization3d(ax1, version='rot') ax1.set_title(r'$\Omega_0 / \omega_{{{}}}$ = {}'.format( 'nut', ratio[i])) # save figure if save_png: fig.savefig('example2d.png', dpi=300)
def test_three(save_png=False): """Perform the third test demonstrating different pulse axes.""" # create output figure fig = plt.figure(figsize=(7, 7)) ax1 = fig.add_subplot(221, projection='3d') ax2 = fig.add_subplot(222, projection='3d') ax3 = fig.add_subplot(223, projection='3d') ax4 = fig.add_subplot(224, projection='3d') # initialize pulse Bloch class bloch = pulse(T1=0.001, T2=0.0005, t_sim=0.005) # solve #1 bloch.solve(m_init=bloch.zunit) # create rot-frame plot bloch.plot_magnetization3d(ax1, version='rot') # solve #2 bloch.Pulse.axis = '+y' bloch.solve(m_init=bloch.zunit) # create rot-frame plot bloch.plot_magnetization3d(ax2, version='rot') # solve #3 bloch.Pulse.axis = '-x' bloch.solve(m_init=bloch.zunit) # create rot-frame plot bloch.plot_magnetization3d(ax3, version='rot') # solve #4 bloch.Pulse.axis = '-y' bloch.solve(m_init=bloch.zunit) # create rot-frame plot bloch.plot_magnetization3d(ax4, version='rot') # adjust titles ax1.set_title(r'$(\pi/2)_{+x}$ - pulse') ax2.set_title(r'$(\pi/2)_{+y}$ - pulse') ax3.set_title(r'$(\pi/2)_{-x}$ - pulse') ax4.set_title(r'$(\pi/2)_{-y}$ - pulse') # save figure if save_png: fig.savefig('example2c.png', dpi=300)
def test(save_png=False, save_data=False): """Perform the lookup table calculation.""" # LOOKUP TABLE SETTINGS # global lookup table settings (change as you like): # B1 excitation amplitude [T] # in the Grunewald et al., 2016 paper, there are in total 5000 points which # would increase the calculation time to more than 10h! pulse_num = 1000 b_pulse = np.logspace(-8, -4, pulse_num) # pulse length [s] t_pulse = 0.08 # initialize pulse Bloch class bloch = pulse(t_sim=t_pulse) # set Larmor freq. bloch.larmor_f = -2300 # pulse type bloch.Pulse.pulse_type = 'AHP' bloch.Pulse.axis = '+y' # frequency modulation bloch.Pulse.fmod.mod_type = 'lin' bloch.Pulse.fmod.v_range[0] = -200 bloch.Pulse.fmod.v_range[1] = 0 # current modulation bloch.Pulse.imod.mod_type = 'const' bloch.Pulse.imod.qual_fac = 10 # create output dictionary mag_final = np.zeros((pulse_num, 3)) # loop over all B1 values for i_1 in reversed(np.arange(pulse_num)): # because the B1 values are given in [T] they need to by divided by # B0 because the pulse factor is given in units of [B0] bloch.Pulse.factor = b_pulse[i_1] / bloch.B0 # solve bloch.solve(m_init=bloch.zunit, use_numba=True) # command line output string = '{:d} / {:d}'.format(i_1 + 1, pulse_num) print(string) # save final magnetization orientation in rotating frame of reference mag_final[i_1, :] = bloch.mrot[:, -1] # create the output figure fig = plt.figure(figsize=(7, 5)) ax1 = fig.add_subplot(121) ax2 = fig.add_subplot(122) # plot data ax1.plot(mag_final[:, 0], b_pulse * 1e6) ax2.plot(mag_final[:, 1], b_pulse * 1e6) # adjust axes ax1.set_yscale('log') ax2.set_yscale('log') ax1.set_xlim(-1, 1) ax2.set_xlim(-1, 1) ax1.set_ylim(b_pulse.min() * 1e6, b_pulse.max() * 1e6) ax2.set_ylim(b_pulse.min() * 1e6, b_pulse.max() * 1e6) ax1.set_xlabel(r'$M_x/M_0$') ax2.set_xlabel(r'$M_y/M_0$') ax1.set_ylabel(r'$B_1$ [$\mu T$]') ax1.grid(color='lightgray') ax2.grid(color='lightgray') # save data if save_data: data = {'B1': b_pulse, 'M': mag_final} np.save('example5_lookup-data', data, allow_pickle=True) # save figure if save_png: fig.savefig('example5.png', dpi=300)