Pulse Sequencer¶
PyEPR provides an intuitive object-oriented pulse programmer allowing the user to design pulsesequences in a hardware-agnostic manner. Additionally, several common EPR experiments are pre-defined and can be easily instantiated and modified.
PyEPR uses ns, GHz and G as the default time, frequency and field units. Very occasionally, other units such as µs or MHz are used, in which case it will be explicitly mentioned.
Seqeunce Construction¶
First we must import the pyepr package, and set our waveform precision. This waveform precision determines the time resolution of the pulse length and positons. If values are given that are not multiples of the waveform precision, they will be rounded.
import pyepr as epr
epr.set_waveform_precision(2) # Set waveform precision to 2 ns
Next, we want to create a sequence object. Here we are aiming to create a simple Hahn Echo sequence.
It is normally recommened, to set the field B and frequency freq as external variables.
B = 12200 # Magnetic field in Gauss
freq = 34.0 # Microwave frequency in GHz
seq = epr.Sequence(name='Hahn Echo Sequence',
B = B,
freq = freq,
reptime = 3e3,# Repetition time in us
averages = 1,
shots = 20, # Number of shots per point
)
Now we need to define some pulses that can be used in our sequence. Here we create a 90 degree and a 180 degree rectangular pulse. These pulses will eventually need a scale (amplitude), before the sequence can be run on hardware. A Detection window is also created
p90 = epr.RectPulse(tp=16,
freq=0, # Frequency offset in MHz, w.r.t the sequence frequency,
flipangle=np.pi/2, # Flip angle in degrees
pcyc = {"phases":[0, np.pi], "dets":[1,-1]}
)
p180 = epr.RectPulse(tp=32,
freq=0, # Frequency offset in MHz, w.r.t the sequence frequency,
flipangle=np.pi, # Flip angle in degrees
)
det = epr.Detetction(tp=32,
freq=0, # Frequency offset in MHz, w.r.t the sequence frequency,
)
We now need a time axis for our sequence and to add them to the sequence object.
When a pulse is copied into the sequence using the add_pulse method, parameters can be modified allowing the same pulse can be used multiple times with different timings or amplitudes.
t = epr.Parameter(name='Interpulse Delay',
value=400, # Initial interpulse delay in ns
step=8, # Step size in ns
dim=1024 # Number of points,
unit='ns' # Unit of the parameter
description='Interpulse delay between the pi/2 and pi pulse'
)
# Adding the pulses to the sequence
seq.add_pulse(p90.copy(t=0))
seq.add_pulse(p180.copy(t=t))
seq.add_pulse(det.copy(t=2*t))
# Defining the evolution
seq.evolution([t])
Advanced Sequences¶
The sequence class is capable of more advanced features such as:
Linked axes
Reduced axes
Non-linear axes
Default Experiments¶
For convienience, several common EPR experiments are pre-defined and can be easily instantiated and modified. A list of currently implemented experiments can be found in the API documentation. Here we show how to create a simple Hahn Echo Relaxation experiment.
HE_Seq = epr.HahnEchoRelaxationSequence(
B = B,
freq = freq,
reptime = 3e3, # Repetition time in us
averages = 1,
shots = 20, # Number of shots per point
start = 400, # Initial interpulse delay in ns
step = 8, # Step size in ns
dim = 1024 # Number of points
pi2_pulse = p90, # The 90 degree pulse
pi_pulse = p180 # The 180 degree pulse
)
Advanced Pulses¶
More complex pulse shapes can be created using the pulse classes provided in the pyepr.pulses module. A list of currently implemented pulse shapes, and their necessary inputs can be found in the API documentation.
Here we show how to create a simple chirp pulse
from pyepr.pulses import ChirpPulse
pulse = ChirpPulse(
tp = 128, # Pulse length in ns
init_freq = -0.1, # Frequency offset in GHz, w.r.t the sequence frequency,
final_freq = 0.1, # Frequency offset in GHz, w.r.t the sequence frequency,
flipangle = np.pi, # Flip angle in radians
)