mirror of
https://github.com/nqrduck/quackseq-simulator.git
synced 2025-01-03 02:18:06 +00:00
Added sequence examples.
This commit is contained in:
parent
bb63d6908a
commit
054e87b5e3
6 changed files with 228 additions and 2 deletions
59
examples/COMPFID.py
Normal file
59
examples/COMPFID.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
"""Composite FID example.
|
||||||
|
|
||||||
|
This example demonstrates how to simulate a composite FID signal using the quackseq simulator.
|
||||||
|
|
||||||
|
See the paper:
|
||||||
|
Sauer, K.L., Klug, C.A., Miller, J.B. et al. Using quaternions to design composite pulses for spin-1 NQR. Appl. Magn. Reson. 25, 485–500 (2004). https://doi.org/10.1007/BF03166543
|
||||||
|
|
||||||
|
This also works for Samples with spin > 1.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from quackseq_simulator.simulator import Simulator
|
||||||
|
from quackseq.pulsesequence import QuackSequence
|
||||||
|
from quackseq.functions import RectFunction
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
seq = QuackSequence("COMPFID")
|
||||||
|
seq.add_pulse_event("tx1", "3u", 100, 0, RectFunction())
|
||||||
|
seq.add_pulse_event("tx2", "6u", 100, 45, RectFunction())
|
||||||
|
# This makes the phase 45, 135, 225, 315
|
||||||
|
seq.set_tx_n_phase_cycles("tx2", 4)
|
||||||
|
seq.add_blank_event("blank", "5u")
|
||||||
|
|
||||||
|
seq.add_readout_event("rx", "100u")
|
||||||
|
|
||||||
|
# No phase shifiting of the receive data but weighting of -1 for the 45 degree pulse, +1 for the 135 degree pulse, -1 for the 225 degree pulse and +1 for the 315 degree pulse
|
||||||
|
readout_scheme = [[1, 0], [-1, 0], [1, 0], [-1, 0]]
|
||||||
|
|
||||||
|
sim = Simulator()
|
||||||
|
sim.set_averages(100)
|
||||||
|
|
||||||
|
sim.settings.noise = 1 # microvolts
|
||||||
|
|
||||||
|
result = sim.run_sequence(seq)
|
||||||
|
# Plot time and frequency domain next to each other
|
||||||
|
plt.subplot(1, 2, 1)
|
||||||
|
plt.title("Time domain Simulation of BiPh3 COMPFID")
|
||||||
|
plt.xlabel("Time (µs)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.tdx[-1], result.tdy[-1].imag, label="imaginary")
|
||||||
|
plt.plot(result.tdx[-1], result.tdy[-1].real, label="real")
|
||||||
|
plt.plot(result.tdx[-1], abs(result.tdy[-1]), label="abs")
|
||||||
|
|
||||||
|
plt.subplot(1, 2, 2)
|
||||||
|
plt.title("Frequency domain Simulation of BiPh3 COMPFID")
|
||||||
|
plt.xlabel("Frequency (kHz)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.fdx[-1], result.fdy[-1].imag, label="imaginary")
|
||||||
|
plt.plot(result.fdx[-1], result.fdy[-1].real, label="real")
|
||||||
|
plt.plot(result.fdx[-1], abs(result.fdy[-1]), label="abs")
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
48
examples/FID.py
Normal file
48
examples/FID.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
"""Example Free Induction Decay (FID) simulation using the quackseq simulator.
|
||||||
|
|
||||||
|
The sample is the default BiPh3 NQR sample.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from quackseq_simulator.simulator import Simulator
|
||||||
|
from quackseq.pulsesequence import QuackSequence
|
||||||
|
from quackseq.functions import RectFunction
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
seq = QuackSequence("FID")
|
||||||
|
seq.add_pulse_event("tx", "3u", 100, 0, RectFunction())
|
||||||
|
seq.add_blank_event("blank", "5u")
|
||||||
|
seq.add_readout_event("rx", "100u")
|
||||||
|
seq.add_blank_event("TR", "1m")
|
||||||
|
|
||||||
|
sim = Simulator()
|
||||||
|
sim.set_averages(100)
|
||||||
|
|
||||||
|
sim.settings.noise = 1 # microvolts
|
||||||
|
|
||||||
|
result = sim.run_sequence(seq)
|
||||||
|
# Plot time and frequency domain next to each other
|
||||||
|
plt.subplot(1, 2, 1)
|
||||||
|
plt.title("Time domain Simulation of BiPh3 FID")
|
||||||
|
plt.xlabel("Time (µs)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.tdx[0], result.tdy[0].imag, label="imaginary")
|
||||||
|
plt.plot(result.tdx[0], result.tdy[0].real, label="real")
|
||||||
|
plt.plot(result.tdx[0], abs(result.tdy[0]), label="abs")
|
||||||
|
|
||||||
|
plt.subplot(1, 2, 2)
|
||||||
|
plt.title("Frequency domain Simulation of BiPh3 FID")
|
||||||
|
plt.xlabel("Frequency (kHz)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.fdx[0], result.fdy[0].imag, label="imaginary")
|
||||||
|
plt.plot(result.fdx[0], result.fdy[0].real, label="real")
|
||||||
|
plt.plot(result.fdx[0], abs(result.fdy[0]), label="abs")
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
49
examples/SE.py
Normal file
49
examples/SE.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
"""Example Spin Echo (SE) simulation using the quackseq simulator.
|
||||||
|
|
||||||
|
The sample is the default BiPh3 NQR sample.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from quackseq_simulator.simulator import Simulator
|
||||||
|
from quackseq.pulsesequence import QuackSequence
|
||||||
|
from quackseq.functions import RectFunction
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
seq = QuackSequence("SE")
|
||||||
|
seq.add_pulse_event("pi-half", "3u", 100, 0, RectFunction())
|
||||||
|
seq.add_blank_event("te-half", "150u")
|
||||||
|
seq.add_pulse_event("pi", "6u", 100, 0, RectFunction())
|
||||||
|
seq.add_blank_event("blank", "50u")
|
||||||
|
seq.add_readout_event("rx", "200u")
|
||||||
|
|
||||||
|
sim = Simulator()
|
||||||
|
sim.set_averages(100)
|
||||||
|
|
||||||
|
sim.settings.noise = 1 # microvolts
|
||||||
|
|
||||||
|
result = sim.run_sequence(seq)
|
||||||
|
# Plot time and frequency domain next to each other
|
||||||
|
plt.subplot(1, 2, 1)
|
||||||
|
plt.title("Time domain Simulation of BiPh3 SE")
|
||||||
|
plt.xlabel("Time (µs)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.tdx[0], result.tdy[0].imag, label="imaginary")
|
||||||
|
plt.plot(result.tdx[0], result.tdy[0].real, label="real")
|
||||||
|
plt.plot(result.tdx[0], abs(result.tdy[0]), label="abs")
|
||||||
|
|
||||||
|
plt.subplot(1, 2, 2)
|
||||||
|
plt.title("Frequency domain Simulation of BiPh3 SE")
|
||||||
|
plt.xlabel("Frequency (kHz)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.fdx[0], result.fdy[0].imag, label="imaginary")
|
||||||
|
plt.plot(result.fdx[0], result.fdy[0].real, label="real")
|
||||||
|
plt.plot(result.fdx[0], abs(result.fdy[0]), label="abs")
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
58
examples/SEPC.py
Normal file
58
examples/SEPC.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
"""Spin Echo with Phase Cycling (SEPC) simulation using the quackseq simulator.
|
||||||
|
|
||||||
|
The sample is the default BiPh3 NQR sample.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from quackseq_simulator.simulator import Simulator
|
||||||
|
from quackseq.pulsesequence import QuackSequence
|
||||||
|
from quackseq.functions import RectFunction
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
seq = QuackSequence("SEPC")
|
||||||
|
seq.add_pulse_event("pi-half", "3u", 100, 0, RectFunction())
|
||||||
|
# This causes the phase to cycle through 0, 90, 180, 270
|
||||||
|
seq.set_tx_n_phase_cycles("pi-half", 4)
|
||||||
|
|
||||||
|
seq.add_blank_event("te-half", "150u")
|
||||||
|
# For the second pulse we just need a phase of 180
|
||||||
|
seq.add_pulse_event("pi", "6u", 100, 180, RectFunction())
|
||||||
|
seq.add_blank_event("blank", "50u")
|
||||||
|
|
||||||
|
seq.add_readout_event("rx", "200u")
|
||||||
|
# Readout scheme for phase cycling TX pulses have the scheme 0 90 180 270 for the first pulse and 180 always for the second pulse
|
||||||
|
readout_scheme = [[1, 0], [1, 90], [1, 180], [1, 270]]
|
||||||
|
|
||||||
|
seq.set_rx_readout_scheme("rx", readout_scheme)
|
||||||
|
|
||||||
|
sim = Simulator()
|
||||||
|
sim.set_averages(100)
|
||||||
|
|
||||||
|
sim.settings.noise = 1 # microvolts
|
||||||
|
|
||||||
|
result = sim.run_sequence(seq)
|
||||||
|
# Plot time and frequency domain next to each other
|
||||||
|
plt.subplot(1, 2, 1)
|
||||||
|
plt.title("Time domain Simulation of BiPh3 SEPC")
|
||||||
|
plt.xlabel("Time (µs)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.tdx[-1], result.tdy[-1].imag, label="imaginary")
|
||||||
|
plt.plot(result.tdx[-1], result.tdy[-1].real, label="real")
|
||||||
|
plt.plot(result.tdx[-1], abs(result.tdy[-1]), label="abs")
|
||||||
|
|
||||||
|
plt.subplot(1, 2, 2)
|
||||||
|
plt.title("Frequency domain Simulation of BiPh3 SEPC")
|
||||||
|
plt.xlabel("Frequency (kHz)")
|
||||||
|
plt.ylabel("Signal (a.u.)")
|
||||||
|
plt.plot(result.fdx[-1], result.fdy[-1].imag, label="imaginary")
|
||||||
|
plt.plot(result.fdx[-1], result.fdy[-1].real, label="real")
|
||||||
|
plt.plot(result.fdx[-1], abs(result.fdy[-1]), label="abs")
|
||||||
|
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
|
@ -38,7 +38,7 @@ class SimulatorModel(SpectrometerModel):
|
||||||
|
|
||||||
# Sample settings, this will be done in a separate module later on
|
# Sample settings, this will be done in a separate module later on
|
||||||
SAMPLE_NAME = "Name"
|
SAMPLE_NAME = "Name"
|
||||||
NUMBER_ATOMS = "Number of atoms per unit volume (1/m^3)"
|
NUMBER_ATOMS = "N. atoms (1/m^3)"
|
||||||
DENSITY = "Density (g/cm^3)"
|
DENSITY = "Density (g/cm^3)"
|
||||||
MOLAR_MASS = "Molar mass (g/mol)"
|
MOLAR_MASS = "Molar mass (g/mol)"
|
||||||
RESONANT_FREQUENCY = "Resonant freq. (MHz)"
|
RESONANT_FREQUENCY = "Resonant freq. (MHz)"
|
||||||
|
|
|
@ -170,10 +170,22 @@ class TestQuackSequence(unittest.TestCase):
|
||||||
# Plotting the results
|
# Plotting the results
|
||||||
plt.title("Phase cycling")
|
plt.title("Phase cycling")
|
||||||
logger.info(f"Number of data sets {len(result.tdy)}")
|
logger.info(f"Number of data sets {len(result.tdy)}")
|
||||||
plt.plot(result.tdx[0], result.tdy[0].real, label="pc 1")
|
plt.plot(result.tdx[0], result.tdy[0].real, label="pc 1 real")
|
||||||
|
plt.plot(result.tdx[0], result.tdy[0].imag, label="pc 2 imag")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
plt.plot(result.tdx[1], result.tdy[1].real, label="pc 2")
|
plt.plot(result.tdx[1], result.tdy[1].real, label="pc 2")
|
||||||
|
plt.plot(result.tdx[1], result.tdy[1].imag, label="pc 2")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
plt.plot(result.tdx[2], result.tdy[2].real, label="pc 3")
|
plt.plot(result.tdx[2], result.tdy[2].real, label="pc 3")
|
||||||
|
plt.plot(result.tdx[2], result.tdy[2].imag, label="pc 3")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
plt.plot(result.tdx[3], result.tdy[3].real, label="pc 4")
|
plt.plot(result.tdx[3], result.tdy[3].real, label="pc 4")
|
||||||
|
plt.plot(result.tdx[3], result.tdy[3].imag, label="pc 4")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
plt.plot(result.tdx[4], abs(result.tdy[4]), label="Phase Cycling")
|
plt.plot(result.tdx[4], abs(result.tdy[4]), label="Phase Cycling")
|
||||||
plt.legend()
|
plt.legend()
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
Loading…
Reference in a new issue