def fid(spin_system): sys_hamiltonian = pg.Hcs(spin_system) + pg.HJ(spin_system) read = pg.Fm(spin_system, "1H") ACQ = pg.acquire1D(pg.gen_op(read), sys_hamiltonian, 0.000001) sigma = pg.sigma_eq(spin_system) sigma0 = pg.Ixpuls(spin_system, sigma, "1H", 90.0) return pg.TTable1D(ACQ.table(sigma0))
def fid(sys, b0=123.23): sys.OmegaAdjust(b0) H = pg.Hcs(sys) + pg.HJ(sys) D = pg.Fm(sys) ACQ = pg.acquire1D(pg.gen_op(D), H, 0.1) sigma = pg.sigma_eq(sys) sigma0 = pg.Ixpuls(sys, sigma, 90.0) mx = pg.TTable1D(ACQ.table(sigma0)) return mx
def apply_crushed_180_rf(sys, sigma, dephase_ang=[0.0, 90.0, 180.0, 270.0], type='crusher'): sigma_mult = [] for i in dephase_ang: sigma_mult.append(pg.gen_op(sigma)) for i, angle in enumerate(dephase_ang): riz = pg.gen_op(pg.Rz(sys, angle)) sigma_mult[i] = pg.evolve(sigma_mult[i], riz) sigma_mult[i] = pg.Iypuls(sys, sigma_mult[i], '1H', 180.0) if type == 'bipolar': riz = pg.gen_op(pg.Rz(sys, -1 * angle)) sigma_mult[i] = pg.evolve(sigma_mult[i], riz) sigma_mult[i] *= 0.25 if i == 0: sigma_res = pg.gen_op(sigma_mult[i]) else: sigma_res += sigma_mult[i] return sigma_res
def apply_crushed_rf(sys, sigma, pulse_op, type='crusher'): """ The sigma input is a single density matrix object. This object is copied into 4 matrices that are rotated about Z axis by the symmetric angles in dephase_ang. The pulse_op RF pulse operator is applied to all 4 density matrices. These are further rotated about the Z axis by the symmetric angles in dephase_ang, if type='crusher', or by the negative angles in dephase_ang if type='bipolar'. The four matrices are summed into one density matrix and divided by 4. A single density matrix is returned. after the RF pulse, any spins that did not experience at least a 90 deg RF pulse then there will be some signal loss due to lack of refocusing of the four matrices. """ dephase_ang = [0.0, 90.0, 180.0, 270.0] sigma_mult = [] for i in dephase_ang: sigma_mult.append(pg.gen_op(sigma)) for i, angle in enumerate(dephase_ang): riz = pg.gen_op(pg.Rz(sys, angle)) sigma_mult[i] = pg.evolve(sigma_mult[i], riz) sigma_mult[i] = pulse_op.evolve(sigma_mult[i]) if type == 'bipolar': riz = pg.gen_op(pg.Rz(sys, -1 * angle)) sigma_mult[i] = pg.evolve(sigma_mult[i], riz) sigma_mult[i] *= 0.25 if i == 0: sigma_res = pg.gen_op(sigma_mult[i]) else: sigma_res += sigma_mult[i] return sigma_res
def press(spin_system, te1=34, te2=34): #---------------------------------------------------------------------- # This is an example PyGAMMA pulse sequence for use in Vespa-Simulation # # A timing diagram for this pulse sequence can be found in the Appendix # of the Simulation User Manual. #---------------------------------------------------------------------- # the isotope string used to sort/select the metabolites of interest is passed # in the sim_desc object so the user can tailor other object within their # code to be nuclei specific, such as the observe operator or pulses obs_iso = '1H' # extract the dynamically changing variable from loop 1 and 2 for 'te1' and # 'te2', divide by 1000.0 because the GUI states that values are entered in # [ms], but PyGAMMA wants [sec] te1 = te1 / 1000.0 te2 = te2 / 1000.0 # set up steady state and observation variables H = pg.Hcs(spin_system) + pg.HJ(spin_system) D = pg.Fm(spin_system, obs_iso) ac = pg.acquire1D(pg.gen_op(D), H, 0.000001) ACQ = ac sigma0 = pg.sigma_eq(spin_system) # excite, propagate, refocus and acquire the data sigma1 = pg.Iypuls(spin_system, sigma0, obs_iso, 90.0) Udelay = pg.prop(H, te1 * 0.5) sigma0 = pg.evolve(sigma1, Udelay) sigma1 = pg.Iypuls(spin_system, sigma0, obs_iso, 180.0) Udelay = pg.prop(H, (te1 + te2) * 0.5) sigma0 = pg.evolve(sigma1, Udelay) sigma1 = pg.Iypuls(spin_system, sigma0, obs_iso, 180.0) Udelay = pg.prop(H, te2 * 0.5) sigma0 = pg.evolve(sigma1, Udelay) # instantiate and save transition table of simulation results # note. this step copies the TTable1D result from the ACQ into # a TTable1D object in the sim_desc object. Thus, when # we return from this function and the ACQ variable gets # garbage collected, our copy of the results in not affected return pg.TTable1D(ACQ.table(sigma0))
#need to use pg.complex() so it can find correct function to call. for j in range(pulse.size()): ptime.put(pg.complex(pulsestep, 0), j) pwf = pg.PulWaveform(pulse, ptime, "TestPulse") pulc = pg.PulComposite(pwf, sys, "1H") H = pg.Hcs(sys) + pg.HJ(sys) D = pg.Fm(sys) Udelay1 = pg.prop(H, t1) Udelay2 = pg.prop(H, t2) # Neet to effectively typecast D as a gen_op. ac = pg.acquire1D(pg.gen_op(D), H, 0.001) ACQ = ac sigma0 = pg.sigma_eq(sys) sigma1 = pg.Iypuls(sys, sigma0, 90.0) #Apply a 90y pulse sigma0 = pg.evolve(sigma1, Udelay1) #Evolve through T1 Ureal180 = pulc.GetUsum(-1) #Get the propagator for steps of 180 sigma1 = Ureal180.evolve(sigma0) #Evolve through pulse sigma0 = pg.evolve(sigma1, Udelay2) #Evolve through T2
def steam(spin_system, te=20, tm=10): # ------------------------------------------------------------------------ # This is an example PyGAMMA pulse sequence for use in Vespa-Simulation # # A timing diagram for this pulse sequence can be found in the Appendix # of the Simulation User Manual. # ------------------------------------------------------------------------ # the isotope string used to sort/select the metabolites of interest is passed # in the sim_desc object so the user can tailor other object within their # code to be nuclei specific, such as the observe operator or pulses obs_iso = '1H' # extract the dynamically changing variable from loops 1 and 2 for 'te' # and 'tm', divide by 1000.0 because the GUI states that values are # entered in [ms], but PyGAMMA wants [sec] te = te / 1000.0 tm = tm / 1000.0 # set up steady state and observation variables H = pg.Hcs(spin_system) + pg.HJ(spin_system) D = pg.Fm(spin_system, obs_iso) ac = pg.acquire1D(pg.gen_op(D), H, 0.000001) ACQ = ac # excite, propagate, refocus and acquire the data # # for the case of STEAM, we need to simulate crusher gradients around the # second and third 90 pulses. We do this by creating 4 copies of the # operator matrix at that point, rotate respectively by 0, 90, 180 and 270 # degrees to each other, apply the 90 pulses and TM period, and then # add the four back into one normalized matrix. dephase_ang = [0.0, 90.0, 180.0, 270.0] Udelay1 = pg.prop(H, te * 0.5) Udelay2 = pg.prop(H, tm) sigma0 = pg.sigma_eq(spin_system) # first 90 pulse, excite spins sigma0 = pg.Iypuls(spin_system, sigma0, obs_iso, 90.0) # nutate TE/2 sigma0 = pg.evolve(sigma0, Udelay1) # Now we need to create the effect of crushers around the 2nd and 3rd # 90 pulses. This is done by creating 4 copies of spin state and repeating # the rest of the sequence for four different rotations around z-axis sigma_mult = [] for i in dephase_ang: sigma_mult.append(pg.gen_op(sigma0)) for i, angle in enumerate(dephase_ang): # calculate and apply rotation around z-axis riz = pg.gen_op(pg.Rz(spin_system, angle)) sigma_mult[i] = pg.evolve(sigma_mult[i], riz) # second 90 pulse sigma_mult[i] = pg.Ixpuls(spin_system, sigma_mult[i], obs_iso, 90.0) # this function removes all coherences still in transverse plane # this removes all stimulated echos from first and second 90 pulse pg.zero_mqc(spin_system, sigma_mult[i], 0, -1) # third 90 pulse sigma_mult[i] = pg.Ixpuls(spin_system, sigma_mult[i], obs_iso, 90.0) # undo rotation around z-axis sigma_mult[i] = pg.evolve(sigma_mult[i], riz) # scale results based on the number of phase angles sigma_mult[i] *= 1.0 / float(len(dephase_ang)) # sum up each rotated/unrotated results if i == 0: sigma_res = pg.gen_op(sigma_mult[i]) else: sigma_res += sigma_mult[i] # last TE/2 nutation sigma0 = pg.evolve(sigma_res, Udelay1) # instantiate and save transition table of simulation results # note. this step copies the TTable1D result from the ACQ into # a TTable1D object in the sim_desc object. Thus, when # we return from this function and the ACQ variable gets # garbage collected, our copy of the results in not affected return pg.TTable1D(ACQ.table(sigma0))
def megapress(spin_system, te=68, omega=OMEGA, high_ppm=-7.5, low_ppm=1): # ---------------------------------------------------------------- # This is an example megapress PyGAMMA pulse sequence # for use in Vespa-Simulation # # It expects that the editing and localization pulses # have been designed or read in from file via Vespa-RFPulse # # ---------------------------------------------------------------- # order of pulse objects from VeSPA # so lets load the pulses, and import them as pulse object # - these were exported directly from vespa as pickled objects pulse_names = [ 'siemens_hsinc_400_8750', 'siemens_mao_400_4', 'siemens_rf_gauss_44hz' ] rf_pulses = [] for ps_name in pulse_names: with open('./Simulators/PyGamma/pulses/' + ps_name + '.vps', 'rb') as ps_filename: rf_pulses.append(pickle.load(ps_filename)) # spectrometer frequency in MHz specfreq = omega # initial evolution time after 90,before 1st 180 tinitial = float(6.6) / 1000.0 # 6600 for svs_edit # echo time te = float(te) / 1000.0 # Pulse centers in ppm for editing pulses PulseCenterPPM_local = float(3) # 3.0 PulseCenterPPM_edit_on = float(1.9) # 1.9 PulseCenterPPM_edit_off = float(7.4) # 7.5 bw_pulse_bottom = float( 2000) # 2600.0 - Bandwidth of the pulse at the bottom min_peak_hz = ( -low_ppm) * specfreq # 224 Hz at 3T the lowest spin ~1.8 ppm max_peak_hz = ( -high_ppm ) * specfreq # 570 Hz at 3T the highest frequency spin (~4.6 ppm*spefreq) freqoff1 = min_peak_hz # this is the start of the sweep freqoff2 = -(bw_pulse_bottom / 2.0) + min_peak_hz freqoff3 = freqoff2 freqfinal = (bw_pulse_bottom / 2.0) + max_peak_hz # number of spatial points (for both x,y) numxy_points = int(5) # Number of Points in the z,x,y directions for spatial simulation Points1 = 5 Points2 = numxy_points Points3 = numxy_points Step = (Points2 * specfreq) / ( freqfinal - freqoff2 ) # may make is (freqfinal-freqoff2)/Points2 and remove specfreq from eqn. # Read Pulse Files, Initialize Waveforms -------------------------- # PulWaveform expects Hz amplitude and angle in degrees, while # Simulation gives us mT amplitude and angle in radians. # We need to use the appropriate gyromagnetic ratio to do the # conversion. This depends on our observe_isotope, since the pulse # is not isotope specific, but the spins we expect it to affect, # is. # (e.g. we use 42576.0 for 1H to covert mT and RAD2DEG for phase) obs_iso = '1H' gyratio = 42576.0 # ------ Pulse Setup Section ---------- # # # - set up RF Pulse containers and read pulse values into them. # - format values to units that GAMMA expects # - copy into row_vector objects # - apply phase roll for off-resonance pulse locations # - set up gamma waveform object # - set up composite pulse object # - get propagator for all steps of the shaped pulse # Pulse offsets in HZ (should be negative or 0) B1_offset_local = (0 - PulseCenterPPM_local) * specfreq B1_offset_edit_on = (0 - PulseCenterPPM_edit_on) * specfreq B1_offset_edit_off = (0 - PulseCenterPPM_edit_off) * specfreq # # ------ Excite Pulse # vol1, excite_length = pulse2op(rf_pulses[0], # gyratio, # "Excite_90", # spin_system, # obs_iso, # offset=B1_offset_local) # print(excite_length) # # ------ Refocus Pulse vol2, refocus_length = pulse2op(rf_pulses[1], gyratio, "Refocus_180", spin_system, obs_iso, offset=B1_offset_local) vol4 = vol2 # print(refocus_length) # ------ Editing Pulses edit1_on, edit1_length = pulse2op(rf_pulses[2], gyratio, "siemens_gauss44hz_on", spin_system, obs_iso, offset=B1_offset_edit_on) edit1_off, edit1_length = pulse2op(rf_pulses[2], gyratio, "siemens_gauss44hz_off", spin_system, obs_iso, offset=B1_offset_edit_off) # edit2_off, edit2_on, edit2_length = edit1_off, edit1_on, edit1_length edit2_on, edit2_length = pulse2op(rf_pulses[2], gyratio, "siemens_gauss44hz_on", spin_system, obs_iso, offset=B1_offset_edit_on) edit2_off, edit2_length = pulse2op(rf_pulses[2], gyratio, "siemens_gauss44hz_off", spin_system, obs_iso, offset=B1_offset_edit_off) # ------ Sequence Timings and GAMMA Initialization ---------- # excite_length = 0.0026 # if using Ideal 90y for excite # refocus_length = 0.003 # if using ideal 180y refocusing pulses # initial evolution time after 90 and before first localization 180 t1 = tinitial - excite_length / 2 - refocus_length / 2 te2 = (te - tinitial * 2.0) / 2.0 t2 = tinitial + te2 - edit1_length - 0.002 - refocus_length t3 = 0.002 t4 = 0.002 t5 = te2 - refocus_length / 2 - 0.002 - edit2_length print('Megapress pulse seuqence timing:') print(' te: ' + str(te)) print(' Tall: ' + str(t1 + t2 + t3 + t4 + t5 + edit1_length + edit2_length + (refocus_length * 2) + (excite_length / 2.0))) print(' t1: ' + str(t1)) print(' t2: ' + str(t2)) print(' t3: ' + str(t3)) print(' t4: ' + str(t4)) print(' t5: ' + str(t5)) # set up steady state and observation variables H = pg.Hcs(spin_system) + pg.HJ(spin_system) D = pg.Fm(spin_system, obs_iso) # Set up acquisition ac = pg.acquire1D(pg.gen_op(D), H, 0.000001) ACQ = ac # Calculate delays here (before spatial loop) Udelay1 = pg.prop(H, t1) # First evolution time Udelay2 = pg.prop(H, t2) # Second evolution time Udelay3 = pg.prop(H, t3) # Third evolution time Udelay4 = pg.prop(H, t4) # Fourth evolution time Udelay5 = pg.prop(H, t5) # Fifth evolution time # -- Do common first steps outside of spatial loop # Equilibrium density matrix sigma0 = pg.sigma_eq(spin_system) sigma_total = pg.gen_op(sigma0) # create a copy mx_tables = [] for edit_flag in [False, True]: loopcounter = 0 local_scale = 1.0 / float(Points1 * Points2 * Points3) for nss1 in range(Points1): # slice # Apply an ideal 90y pulse sigma1 = pg.Ixpuls(spin_system, sigma0, obs_iso, 90.0) # Apply a shaped 90 pulse # sigma1 = vol1.evolve(sigma0) # Evolve for t1 sigma0 = pg.evolve(sigma1, Udelay1) for nss2 in range(Points2): for nss3 in range(Points3): # First 180 volume selection pulse - with gradient crushers offsethz2 = freqoff2 + nss2 * specfreq / Step spin_system.offsetShifts(offsethz2) # note: arg. in Hz # sigma1 = apply_crushed_180_rf(spin_system, sigma0, dephase_ang=[0.0, 90.0], type='crusher') sigma1 = apply_crushed_rf(spin_system, sigma0, vol2, type='crusher') spin_system.offsetShifts(-offsethz2) # Evolve for t2 sigma2 = pg.evolve(sigma1, Udelay2) # First BASING bipolar gradient+editing pulse if edit_flag == 0: sigma1 = apply_crushed_rf(spin_system, sigma2, edit1_off, type='bipolar') else: sigma1 = apply_crushed_rf(spin_system, sigma2, edit1_on, type='bipolar') pg.zero_mqc(spin_system, sigma1, 2, 1) # Keep ZQC and SQC # Evolve for t3 sigma2 = pg.evolve(sigma1, Udelay3) # Second 180 volume selection - with gradient crushers offsethz3 = freqoff3 + nss3 * specfreq / Step spin_system.offsetShifts(offsethz3) # note: arg. in Hz # sigma1 = apply_crushed_180_rf(spin_system, sigma2, type='crusher') sigma1 = apply_crushed_rf(spin_system, sigma2, vol4, type='crusher') spin_system.offsetShifts(-offsethz3) # note: arg. in Hz # Evolve for t4 sigma2 = pg.evolve(sigma1, Udelay4) # Second BASING bipolar gradient+editing pulse if edit_flag == 0: sigma1 = apply_crushed_rf(spin_system, sigma2, edit2_off, type='bipolar') else: sigma1 = apply_crushed_rf(spin_system, sigma2, edit2_on, type='bipolar') pg.zero_mqc(spin_system, sigma1, 2, 1) # Keep ZQC and SQC # Evolve for t5 sigma2 = pg.evolve(sigma1, Udelay5) sigma2 *= local_scale print("System loop index is: " + str(loopcounter) + " offsethz2 = " + str(offsethz2) + " offsethz3 = " + str(offsethz3)) loopcounter += 1 if nss1 + nss2 + nss3 == 0: sigma_total = sigma2 else: sigma_total += sigma2 mx_tables.append(pg.TTable1D(ACQ.table(sigma_total))) return mx_tables
#need to use pg.complex() so it can find correct function to call. for j in range(pulse.size()): ptime.put(pg.complex(pulsestep, 0), j) pwf = pg.PulWaveform(pulse, ptime, "TestPulse") pulc = pg.PulComposite(pwf, sys, "1H") H = pg.Hcs(sys) + pg.HJ(sys); D = pg.Fm(sys); Udelay1 = pg.prop(H, t1); Udelay2 = pg.prop(H, t2); # Neet to effectively typecast D as a gen_op. ac = pg.acquire1D(pg.gen_op(D), H, 0.001) ACQ = ac; sigma0 = pg.sigma_eq(sys) sigma1 = pg.Iypuls(sys, sigma0, 90.0) #Apply a 90y pulse sigma0 = pg.evolve(sigma1, Udelay1) #Evolve through T1 Ureal180 = pulc.GetUsum(-1) #Get the propagator for steps of 180 sigma1 = Ureal180.evolve(sigma0) #Evolve through pulse sigma0 = pg.evolve(sigma1, Udelay2) #Evolve through T2
def simulate(self): self.postToConsole.emit(' | Simulating ... ' + self.insysfile) print(' | Simulating ...' + self.insysfile) metab_name = self.insysfile.replace('.sys', '') if self.sim_experiment.b0 == 123.3: self.insysfile = 'pints/metabolites/3T_' + self.insysfile elif self.sim_experiment.b0 == 297.2: self.insysfile = 'pints/metabolites/7T_' + self.insysfile elif self.sim_experiment.b0 == 400.2: self.insysfile = 'pints/metabolites/9.4T_' + self.insysfile if self.sim_experiment.name == "semi-LASER (Bruker)": spin_system = pg.spin_system() spin_system.read(self.insysfile) for i in range(spin_system.spins()): spin_system.PPM( i, spin_system.PPM(i) - self.sim_experiment.RF_OFFSET) TE = self.sim_experiment.TE * 1E-3 TE1 = self.sim_experiment.TE1 * 1E-3 TE2 = self.sim_experiment.TE2 * 1E-3 # build 90 degree pulse inpulse90file = self.sim_experiment.inpulse90file A_90 = self.sim_experiment.A_90 PULSE_90_LENGTH = self.sim_experiment.PULSE_90_LENGTH gyratio = self.sim_experiment.getGyratio() pulse90 = Pulse(inpulse90file, PULSE_90_LENGTH, 'bruker') n_old = np.linspace(0, PULSE_90_LENGTH, sp.size(pulse90.waveform)) n_new = np.linspace(0, PULSE_90_LENGTH, sp.size(pulse90.waveform) + 1) waveform_real = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.real(pulse90.waveform) * A_90)(n_new) waveform_imag = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.imag(pulse90.waveform) * A_90)(n_new) pulse90.waveform = waveform_real + 1j * (waveform_imag) ampl_arr = np.abs(pulse90.waveform) phas_arr = np.unwrap(np.angle(pulse90.waveform)) * 180.0 / math.pi pulse = pg.row_vector(len(pulse90.waveform)) ptime = pg.row_vector(len(pulse90.waveform)) for j, val in enumerate(zip(ampl_arr, phas_arr)): pulse.put(pg.complex(val[0], val[1]), j) ptime.put(pg.complex(pulse90.pulsestep, 0), j) pulse_dur_90 = pulse.size() * pulse90.pulsestep pwf_90 = pg.PulWaveform(pulse, ptime, "90excite") pulc_90 = pg.PulComposite(pwf_90, spin_system, self.sim_experiment.obs_iso) Ureal90 = pulc_90.GetUsum(-1) # build 180 degree pulse inpulse180file = self.sim_experiment.inpulse180file A_180 = self.sim_experiment.A_180 PULSE_180_LENGTH = self.sim_experiment.PULSE_180_LENGTH gyratio = self.sim_experiment.getGyratio() pulse180 = Pulse(inpulse180file, PULSE_180_LENGTH, 'bruker') n_old = np.linspace(0, PULSE_180_LENGTH, sp.size(pulse180.waveform)) n_new = np.linspace(0, PULSE_180_LENGTH, sp.size(pulse180.waveform) + 1) waveform_real = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.real(pulse180.waveform) * A_180)(n_new) waveform_imag = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.imag(pulse180.waveform) * A_180)(n_new) pulse180.waveform = waveform_real + 1j * (waveform_imag) ampl_arr = np.abs(pulse180.waveform) phas_arr = np.unwrap(np.angle(pulse180.waveform)) * 180.0 / math.pi freq_arr = np.gradient(phas_arr) pulse = pg.row_vector(len(pulse180.waveform)) ptime = pg.row_vector(len(pulse180.waveform)) for j, val in enumerate(zip(ampl_arr, phas_arr)): pulse.put(pg.complex(val[0], val[1]), j) ptime.put(pg.complex(n_new[1], 0), j) pulse_dur_180 = pulse.size() * pulse180.pulsestep pwf_180 = pg.PulWaveform(pulse, ptime, "180afp") pulc_180 = pg.PulComposite(pwf_180, spin_system, self.sim_experiment.obs_iso) Ureal180 = pulc_180.GetUsum(-1) H = pg.Hcs(spin_system) + pg.HJ(spin_system) D = pg.Fm(spin_system, self.sim_experiment.obs_iso) ac = pg.acquire1D(pg.gen_op(D), H, self.sim_experiment.dwell_time) ACQ = ac delay1 = TE1 / 2.0 - pulse_dur_90 / 2.0 - pulse_dur_180 / 2.0 delay2 = TE1 / 2.0 + TE2 / 2.0 - pulse_dur_180 delay3 = TE2 - pulse_dur_180 delay4 = delay2 delay5 = TE1 / 2.0 - pulse_dur_180 + self.sim_experiment.DigShift Udelay1 = pg.prop(H, delay1) Udelay2 = pg.prop(H, delay2) Udelay3 = pg.prop(H, delay3) Udelay4 = pg.prop(H, delay4) Udelay5 = pg.prop(H, delay5) sigma0 = pg.sigma_eq(spin_system) # init sigma1 = Ureal90.evolve(sigma0) # apply 90-degree pulse sigma0 = pg.evolve(sigma1, Udelay1) sigma1 = Ureal180.evolve(sigma0) # apply AFP1 sigma0 = pg.evolve(sigma1, Udelay2) sigma1 = Ureal180.evolve(sigma0) # apply AFP2 sigma0 = pg.evolve(sigma1, Udelay3) sigma1 = Ureal180.evolve(sigma0) # apply AFP3 sigma0 = pg.evolve(sigma1, Udelay4) sigma1 = Ureal180.evolve(sigma0) # apply AFP4 sigma0 = pg.evolve(sigma1, Udelay5) elif self.sim_experiment.name == "semi-LASER": spin_system = pg.spin_system() spin_system.read(self.insysfile) for i in range(spin_system.spins()): spin_system.PPM( i, spin_system.PPM(i) - self.sim_experiment.RF_OFFSET) TE = self.sim_experiment.TE TE1 = float((TE * 0.31) / 1000.0) TE3 = float((TE * 0.31) / 1000.0) TE2 = float(TE / 1000.0 - TE1 - TE3) TE_fill = TE / 1000.0 - TE1 - TE2 - TE3 # build 90 degree pulse inpulse90file = self.sim_experiment.inpulse90file A_90 = self.sim_experiment.A_90 PULSE_90_LENGTH = self.sim_experiment.PULSE_90_LENGTH gyratio = self.sim_experiment.getGyratio() pulse90 = Pulse(inpulse90file, PULSE_90_LENGTH) n_old = np.linspace(0, PULSE_90_LENGTH, sp.size(pulse90.waveform)) n_new = np.linspace(0, PULSE_90_LENGTH, sp.size(pulse90.waveform) + 1) waveform_real = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.real(pulse90.waveform) * A_90)(n_new) waveform_imag = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.imag(pulse90.waveform) * A_90)(n_new) pulse90.waveform = waveform_real + 1j * (waveform_imag) ampl_arr = np.abs(pulse90.waveform) * gyratio phas_arr = np.unwrap(np.angle(pulse90.waveform)) * 180.0 / math.pi pulse = pg.row_vector(len(pulse90.waveform)) ptime = pg.row_vector(len(pulse90.waveform)) for j, val in enumerate(zip(ampl_arr, phas_arr)): pulse.put(pg.complex(val[0], val[1]), j) ptime.put(pg.complex(pulse90.pulsestep, 0), j) pulse_dur_90 = pulse.size() * pulse90.pulsestep peak_to_end_90 = pulse_dur_90 - ( 209 + self.sim_experiment.fudge_factor) * pulse90.pulsestep pwf_90 = pg.PulWaveform(pulse, ptime, "90excite") pulc_90 = pg.PulComposite(pwf_90, spin_system, self.sim_experiment.obs_iso) Ureal90 = pulc_90.GetUsum(-1) # build 180 degree pulse inpulse180file = self.sim_experiment.inpulse180file A_180 = self.sim_experiment.A_180 PULSE_180_LENGTH = self.sim_experiment.PULSE_180_LENGTH gyratio = self.sim_experiment.getGyratio() pulse180 = Pulse(inpulse180file, PULSE_180_LENGTH) n_old = np.linspace(0, PULSE_180_LENGTH, sp.size(pulse180.waveform)) n_new = np.linspace(0, PULSE_180_LENGTH, sp.size(pulse180.waveform) + 1) waveform_real = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.real(pulse180.waveform) * A_180)(n_new) waveform_imag = sp.interpolate.InterpolatedUnivariateSpline( n_old, np.imag(pulse180.waveform) * A_180)(n_new) pulse180.waveform = waveform_real + 1j * (waveform_imag) ampl_arr = np.abs(pulse180.waveform) * gyratio phas_arr = np.unwrap(np.angle(pulse180.waveform)) * 180.0 / math.pi freq_arr = np.gradient(phas_arr) pulse = pg.row_vector(len(pulse180.waveform)) ptime = pg.row_vector(len(pulse180.waveform)) for j, val in enumerate(zip(ampl_arr, phas_arr)): pulse.put(pg.complex(val[0], val[1]), j) ptime.put(pg.complex(n_new[1], 0), j) pulse_dur_180 = pulse.size() * pulse180.pulsestep pwf_180 = pg.PulWaveform(pulse, ptime, "180afp") pulc_180 = pg.PulComposite(pwf_180, spin_system, self.sim_experiment.obs_iso) Ureal180 = pulc_180.GetUsum(-1) H = pg.Hcs(spin_system) + pg.HJ(spin_system) D = pg.Fm(spin_system, self.sim_experiment.obs_iso) ac = pg.acquire1D(pg.gen_op(D), H, self.sim_experiment.dwell_time) ACQ = ac delay1 = TE1 / 2.0 + TE_fill / 8.0 - pulse_dur_180 / 2.0 - peak_to_end_90 delay2 = TE1 / 2.0 + TE_fill / 8.0 + TE2 / 4.0 + TE_fill / 8.0 - pulse_dur_180 delay3 = TE2 / 4.0 + TE_fill / 8.0 + TE2 / 4.0 + TE_fill / 8.0 - pulse_dur_180 delay4 = TE2 / 4.0 + TE_fill / 8.0 + TE3 / 2.0 + TE_fill / 8.0 - pulse_dur_180 delay5 = TE3 / 2.0 + TE_fill / 8.0 - pulse_dur_180 / 2.0 Udelay1 = pg.prop(H, delay1) Udelay2 = pg.prop(H, delay2) Udelay3 = pg.prop(H, delay3) Udelay4 = pg.prop(H, delay4) Udelay5 = pg.prop(H, delay5) sigma0 = pg.sigma_eq(spin_system) # init sigma1 = Ureal90.evolve(sigma0) # apply 90-degree pulse sigma0 = pg.evolve(sigma1, Udelay1) sigma1 = Ureal180.evolve(sigma0) # apply AFP1 sigma0 = pg.evolve(sigma1, Udelay2) sigma1 = Ureal180.evolve(sigma0) # apply AFP2 sigma0 = pg.evolve(sigma1, Udelay3) sigma1 = Ureal180.evolve(sigma0) # apply AFP3 sigma0 = pg.evolve(sigma1, Udelay4) sigma1 = Ureal180.evolve(sigma0) # apply AFP4 sigma0 = pg.evolve(sigma1, Udelay5) elif self.sim_experiment.name == "LASER": spin_system = pg.spin_system() spin_system.read(self.insysfile) for i in range(spin_system.spins()): spin_system.PPM( i, spin_system.PPM(i) - self.sim_experiment.RF_OFFSET) # build 90 degree AHP pulse inpulse90file = self.sim_experiment.inpulse90file A_90 = self.sim_experiment.A_90 PULSE_90_LENGTH = self.sim_experiment.PULSE_90_LENGTH gyratio = self.sim_experiment.getGyratio() pulse90 = Pulse(inpulse90file, PULSE_90_LENGTH, 'varian') n_new = np.linspace(0, PULSE_90_LENGTH, 256) waveform_real = np.real(pulse90.waveform) * A_90 waveform_imag = np.imag(pulse90.waveform) * A_90 pulse90.waveform = waveform_real + 1j * (waveform_imag) ampl_arr = np.abs(pulse90.waveform) * gyratio phas_arr = np.unwrap(np.angle(pulse90.waveform)) * 180.0 / math.pi pulse = pg.row_vector(len(pulse90.waveform)) ptime = pg.row_vector(len(pulse90.waveform)) for j, val in enumerate(zip(ampl_arr, phas_arr)): pulse.put(pg.complex(val[0], val[1]), j) ptime.put(pg.complex(pulse90.pulsestep, 0), j) pulse_dur_90 = pulse.size() * pulse90.pulsestep pwf_90 = pg.PulWaveform(pulse, ptime, "90excite") pulc_90 = pg.PulComposite(pwf_90, spin_system, self.sim_experiment.obs_iso) Ureal90 = pulc_90.GetUsum(-1) # build 180 degree pulse inpulse180file = self.sim_experiment.inpulse180file A_180 = self.sim_experiment.A_180 PULSE_180_LENGTH = self.sim_experiment.PULSE_180_LENGTH gyratio = self.sim_experiment.getGyratio() pulse180 = Pulse(inpulse180file, PULSE_180_LENGTH, 'varian') n_new = np.linspace(0, PULSE_180_LENGTH, 512) waveform_real = np.real(pulse180.waveform) * A_180 waveform_imag = np.imag(pulse180.waveform) * A_180 pulse180.waveform = waveform_real + 1j * (waveform_imag) ampl_arr = np.abs(pulse180.waveform) * gyratio phas_arr = np.unwrap(np.angle(pulse180.waveform)) * 180.0 / math.pi freq_arr = np.gradient(phas_arr) pulse = pg.row_vector(len(pulse180.waveform)) ptime = pg.row_vector(len(pulse180.waveform)) for j, val in enumerate(zip(ampl_arr, phas_arr)): pulse.put(pg.complex(val[0], val[1]), j) ptime.put(pg.complex(n_new[1], 0), j) pulse_dur_180 = pulse.size() * pulse180.pulsestep pwf_180 = pg.PulWaveform(pulse, ptime, "180afp") pulc_180 = pg.PulComposite(pwf_180, spin_system, self.sim_experiment.obs_iso) Ureal180 = pulc_180.GetUsum(-1) # calculate pulse timings ROF1 = 100E-6 #sec ROF2 = 10E-6 #sec TCRUSH1 = 0.0008 #sec TCRUSH2 = 0.0008 #sec ss_grad_rfDelayFront = 0 #TCRUSH1 - ROF1 ss_grad_rfDelayBack = 0 #TCRUSH2 - ROF2 ro_grad_atDelayFront = 0 ro_grad_atDelayBack = 0 TE = self.sim_experiment.TE / 1000. ipd = (TE - pulse_dur_90 \ - 6*(ss_grad_rfDelayFront + pulse_dur_180 + ss_grad_rfDelayBack) \ - ro_grad_atDelayFront) / 12 delay1 = ipd + ss_grad_rfDelayFront delay2 = ss_grad_rfDelayBack + 2 * ipd + ss_grad_rfDelayFront delay3 = ss_grad_rfDelayBack + 2 * ipd + ss_grad_rfDelayFront delay4 = ss_grad_rfDelayBack + 2 * ipd + ss_grad_rfDelayFront delay5 = ss_grad_rfDelayBack + 2 * ipd + ss_grad_rfDelayFront delay6 = ss_grad_rfDelayBack + 2 * ipd + ss_grad_rfDelayFront delay7 = ss_grad_rfDelayBack + ipd + ro_grad_atDelayFront # print A_90, A_180, pulse_dur_90, pulse_dur_180 # print TE, ipd, pulse_dur_90+6*pulse_dur_180, delay1+delay2+delay3+delay4+delay5+delay6+delay7, pulse_dur_90+6*pulse_dur_180+delay1+delay2+delay3+delay4+delay5+delay6+delay7 # print '' # initialize acquisition H = pg.Hcs(spin_system) + pg.HJ(spin_system) D = pg.Fm(spin_system, self.sim_experiment.obs_iso) ac = pg.acquire1D(pg.gen_op(D), H, self.sim_experiment.dwell_time) ACQ = ac Udelay1 = pg.prop(H, delay1) Udelay2 = pg.prop(H, delay2) Udelay3 = pg.prop(H, delay3) Udelay4 = pg.prop(H, delay4) Udelay5 = pg.prop(H, delay5) Udelay6 = pg.prop(H, delay6) Udelay7 = pg.prop(H, delay7) sigma0 = pg.sigma_eq(spin_system) # init sigma1 = Ureal90.evolve(sigma0) # apply 90-degree pulse sigma0 = pg.evolve(sigma1, Udelay1) sigma1 = Ureal180.evolve(sigma0) # apply AFP1 sigma0 = pg.evolve(sigma1, Udelay2) sigma1 = Ureal180.evolve(sigma0) # apply AFP2 sigma0 = pg.evolve(sigma1, Udelay3) sigma1 = Ureal180.evolve(sigma0) # apply AFP3 sigma0 = pg.evolve(sigma1, Udelay4) sigma1 = Ureal180.evolve(sigma0) # apply AFP4 sigma0 = pg.evolve(sigma1, Udelay5) sigma1 = Ureal180.evolve(sigma0) # apply AFP5 sigma0 = pg.evolve(sigma1, Udelay6) sigma1 = Ureal180.evolve(sigma0) # apply AFP6 sigma0 = pg.evolve(sigma1, Udelay7) # acquire mx = pg.TTable1D(ACQ.table(sigma0)) # binning to remove degenerate peaks # BINNING # Note: Metabolite Peak Normalization and Blending # The transition tables calculated by the GAMMA density matrix simulations frequently contain a # large number of transitions caused by degenerate splittings and other processes. At the # conclusion of each simulation run a routine is called to extract lines from the transition table. # These lines are then normalized using a closed form calculation based on the number of spins. # To reduce the number of lines required for display, multiple lines are blended by binning them # together based on their PPM locations and phases. The following parameters are used to # customize these procedures: # Peak Search Range -- Low/High (PPM): the range in PPM that is searched for lines from the # metabolite simulation. # Peak Blending Tolerance (PPM and Degrees): the width of the bins (+/- in PPM and +/- in # PhaseDegrees) that are used to blend the lines in the simulation. Lines that are included in the # same bin are summed using complex addition based on Amplitude and Phase. b0 = self.sim_experiment.b0 obs_iso = self.sim_experiment.obs_iso tolppm = self.sim_experiment.tolppm tolpha = self.sim_experiment.tolpha ppmlo = self.sim_experiment.ppmlo ppmhi = self.sim_experiment.ppmhi rf_off = self.sim_experiment.RF_OFFSET field = b0 nspins = spin_system.spins() nlines = mx.size() tmp = pg.Isotope(obs_iso) obs_qn = tmp.qn() qnscale = 1.0 for i in range(nspins): qnscale *= 2 * spin_system.qn(i) + 1 qnscale = qnscale / (2.0 * (2.0 * obs_qn + 1)) freqs = [] outf = [] outa = [] outp = [] nbin = 0 found = False PI = 3.14159265358979323846 RAD2DEG = 180.0 / PI indx = mx.Sort(0, -1, 0) for i in range(nlines): freqs.append(-1 * mx.Fr(indx[i]) / (2.0 * PI * field)) for i in range(nlines): freq = freqs[i] if (freq > ppmlo) and (freq < ppmhi): val = mx.I(indx[i]) tmpa = np.sqrt(val.real()**2 + val.imag()**2) / qnscale tmpp = -RAD2DEG * np.angle(val.real() + 1j * val.imag()) if nbin == 0: outf.append(freq) outa.append(tmpa) outp.append(tmpp) nbin += 1 else: for k in range(nbin): if (freq >= outf[k] - tolppm) and (freq <= outf[k] + tolppm): if (tmpp >= outp[k] - tolpha) and (tmpp <= outp[k] + tolpha): ampsum = outa[k] + tmpa outf[k] = (outa[k] * outf[k] + tmpa * freq) / ampsum outp[k] = (outa[k] * outp[k] + tmpa * tmpp) / ampsum outa[k] += tmpa found = True if not found: outf.append(freq) outa.append(tmpa) outp.append(tmpp) nbin += 1 found = False for i, item in enumerate(outf): outf[i] = item + rf_off outp[i] = outp[i] - 90.0 metab = Metabolite() metab.name = metab_name metab.var = 0.0 for i in range(sp.size(outf)): if outf[i] <= 5: metab.ppm.append(outf[i]) metab.area.append(outa[i]) metab.phase.append(-1.0 * outp[i]) insysfile = self.insysfile.replace('pints/metabolites/3T_', '') insysfile = self.insysfile.replace('pints/metabolites/7T_', '') insysfile = self.insysfile.replace('pints/metabolites/9.4T_', '') if insysfile == 'alanine.sys': # metab.A_m = 0.078 metab.T2 = (87E-3) elif insysfile == 'aspartate.sys': metab.A_m = 0.117 metab.T2 = (87E-3) elif insysfile == 'choline_1-CH2_2-CH2.sys': # metab.A_m = 0.165 metab.T2 = (87E-3) elif insysfile == 'choline_N(CH3)3_a.sys' or insysfile == 'choline_N(CH3)3_b.sys': # metab.A_m = 0.165 metab.T2 = (121E-3) elif insysfile == 'creatine_N(CH3).sys': metab.A_m = 0.296 metab.T2 = (90E-3) elif insysfile == 'creatine_X.sys': metab.A_m = 0.296 metab.T2 = (81E-3) elif insysfile == 'd-glucose-alpha.sys': # metab.A_m = 0.049 metab.T2 = (87E-3) elif insysfile == 'd-glucose-beta.sys': # metab.A_m = 0.049 metab.T2 = (87E-3) elif insysfile == 'eth.sys': # metab.A_m = 0.320 metab.T2 = (87E-3) elif insysfile == 'gaba.sys': # metab.A_m = 0.155 metab.T2 = (82E-3) elif insysfile == 'glutamate.sys': metab.A_m = 0.898 metab.T2 = (88E-3) elif insysfile == 'glutamine.sys': metab.A_m = 0.427 metab.T2 = (87E-3) elif insysfile == 'glutathione_cysteine.sys': metab.A_m = 0.194 metab.T2 = (87E-3) elif insysfile == 'glutathione_glutamate.sys': metab.A_m = 0.194 metab.T2 = (87E-3) elif insysfile == 'glutathione_glycine.sys': metab.A_m = 0.194 metab.T2 = (87E-3) elif insysfile == 'glycine.sys': metab.A_m = 0.068 metab.T2 = (87E-3) elif insysfile == 'gpc_7-CH2_8-CH2.sys': # metab.A_m = 0.097 metab.T2 = (87E-3) elif insysfile == 'gpc_glycerol.sys': # metab.A_m = 0.097 metab.T2 = (87E-3) elif insysfile == 'gpc_N(CH3)3_a.sys': # metab.A_m = 0.097 metab.T2 = (121E-3) elif insysfile == 'gpc_N(CH3)3_b.sys': # metab.A_m = 0.097 metab.T2 = (121E-3) elif insysfile == 'lactate.sys': # metab.A_m = 0.039 metab.T2 = (87E-3) elif insysfile == 'myoinositol.sys': metab.A_m = 0.578 metab.T2 = (87E-3) elif insysfile == 'naa_acetyl.sys': metab.A_m = 1.000 metab.T2 = (130E-3) elif insysfile == 'naa_aspartate.sys': metab.A_m = 1.000 metab.T2 = (69E-3) elif insysfile == 'naag_acetyl.sys': metab.A_m = 0.160 metab.T2 = (130E-3) elif insysfile == 'naag_aspartyl.sys': metab.A_m = 0.160 metab.T2 = (87E-3) elif insysfile == 'naag_glutamate.sys': metab.A_m = 0.160 metab.T2 = (87E-3) elif insysfile == 'pcho_N(CH3)3_a.sys': # metab.A_m = 0.058 metab.T2 = (121E-3) elif insysfile == 'pcho_N(CH3)3_b.sys': # metab.A_m = 0.058 metab.T2 = (121E-3) elif insysfile == 'pcho_X.sys': # metab.A_m = 0.058 metab.T2 = (87E-3) elif insysfile == 'pcr_N(CH3).sys': metab.A_m = 0.422 metab.T2 = (90E-3) elif insysfile == 'pcr_X.sys': metab.A_m = 0.422 metab.T2 = (81E-3) elif insysfile == 'peth.sys': metab.A_m = 0.126 metab.T2 = (87E-3) elif insysfile == 'scyllo-inositol.sys': metab.A_m = 0.044 metab.T2 = (87E-3) elif insysfile == 'taurine.sys': metab.A_m = 0.117 metab.T2 = (85E-3) elif insysfile == 'water.sys': metab.A_m = 1.000 metab.T2 = (43.60E-3) # Send save data signal self.outputResults.emit(metab) self.postToConsole.emit(' | Simulation completed for ... ' + self.insysfile) self.finished.emit(self.thread_num)
'dw': dt2, 'complex': True, 'obs': 400.0, 'car': 0, 'size': t2pts, 'label': '1H', 'encoding': 'direct', 'time': False, 'freq': True } } fid = pg.row_vector(t2pts) #block_1D tmp(t2pts); // 1D-data block storage H = pg.Hcs(sys)+ pg.HJw(sys) # // Hamiltonian, weak coupling detect = pg.gen_op(pg.Fp(sys)) # // F+ for detection operator sigma0 = pg.sigma_eq(sys) # // equilibrium density matrix sigma1 = pg.Iypuls(sys, sigma0, 90) pg.FID(sigma1,detect,H,dt2,t2pts,fid) pg.exponential_multiply(fid,-5) spec = fid.FFT() npspec = spec.toNParray() uc0 = ng.fileiobase.unit_conversion(udic[0]['size'], udic[0]['complex'], udic[0]['sw'], udic[0]['obs'], udic[0]['car'])
t1pts = 1024 # points on t1 axis t2pts = 1024 # points on t2 axis # Read in spin system for cosy experiment sys = spin_system() # define the system, read in sys.read("cosy1.sys") # from disk # set up some neccessary variables tmp = row_vector(t2pts) #block_1D tmp(t2pts); // 1D-data block storage data = np.zeros((t1pts, t2pts), dtype=np.complex128 ) #block_2D data(t1pts,t2pts); // 2D-data matrix storage H = Hcs(sys) + HJw(sys) # // Hamiltonian, weak coupling detect = gen_op(Fm(sys)) # // F- for detection operator # APPLY PULSE SEQUENCE sigma0 = sigma_eq(sys) # equilibrium density matrix sigma1 = Iypuls(sys, sigma0, 90) # apply first 90 y-pulse for t1 in range(t1pts): sigma = evolve(sigma1, H, t1 * dt1) # evolution during t1 sigma = Iypuls(sys, sigma, 90) # apply second 90 y-pulse FID(sigma, detect, H, dt2, t2pts, tmp) # acquisition data[t1] = tmp.toNParray() # save FID # Apply QSIN processing in both dimensions, 2D-FFT and display in absolute mode
header = (s1, s2) sys = pg.sys_dynamic() sys.read(infile) specfreq = sys.Omega() mx = pg.TTable1D() H = pg.Ho(sys) detect = pg.Fm(sys) sigma0 = pg.sigma_eq(sys) sigmap = pg.Iypuls(sys, sigma0, 90.) L = pg.Hsuper(H) L *= pg.complex(0,1) L += pg.Kex(sys, H.get_basis()); ACQ1 = pg.acquire1D(pg.gen_op(detect), L) mx = ACQ1.table(sigmap); #mx.dbwrite_old(outfile, "test_lines", -10, 10, specfreq, .1, 0, header) mx.dbwrite(outfile, runname, specfreq, sys.spins(), 0, header)
ptime.put(pg.complex(pulsestep, 0), j) # pulse steps pwf = pg.PulWaveform(pulse, ptime, "TestPulse") pulc = pg.PulComposite(pwf, sys, "1H") H = pg.Hcs(sys) + pg.HJ(sys) D = pg.Fm(sys) Udelay1 = pg.prop(H, tinit) Udelay2 = pg.prop(H, TE2) Udelay3 = pg.prop(H, TE2) ac = pg.acquire1D(pg.gen_op(D), H, 0.001) # Set up acquisition ACQ = ac sigma0 = pg.sigma_eq(sys) #Equilibrium density matrix sigma1 = pg.Iypuls(sys, sigma0, 90.0) #Apply a 90y pulse sigma0 = pg.evolve(sigma1, Udelay1) #Evolve through TINIT Ureal180 = pulc.GetUsum(-1) #Get the propagator for steps of 180 sigma1 = Ureal180.evolve(sigma0) #Evolve through pulse sigma0 = pg.evolve(sigma1, Udelay2) #Evolve through TE/2 sigma1 = Ureal180.evolve(sigma0) #Evolve through pulse sigma0 = pg.evolve(sigma1, Udelay3) #Evolve through TE/2 mx = ACQ.table(sigma0) # Transitions table (no lb)