Relaxation time T1 of the bosonic mode (coherent state decay)¶
Using pulsed
mode, we measure the energy-relaxation time \(T_1\) of the bosonic mode. We first displace the memory with a pulse at the memory frequency with a \(\sin^2\) envelope. Then the memory enegy decays during the delay time \(\delta\). The qubit-control pulse is a selective \(\pi\) pulse with a \(\sin^2\) envelope whose frequency is the frequency of the qubit when the memory is in the Fock state \(|0\rangle\). The readout pulse is at the frequency of the readout resonator and has a square envelope. By probing the state of the qubit, we directly get the probablility that the memory is in state \(|0\rangle\).
The class for performing the \(T_1\) experiment is available at presto-measure/t1_memory_coherent.py. Here, we run the experiment and observe the qubit population exponentially approaching the excited state. This translates in the memory starting in the Fock state \(|1\rangle\) and exponentially approaching the ground state \(|0\rangle\). We then have a look at the main parts of the code.
You can create a new experiment and run it on your Presto. Be sure to change the parameters of T1_memory_coherent
to match your experiment and change presto_address
to match the IP address of your Presto:
from t1_memory_coherent import T1_memory_coherent
import numpy as np
experiment = T1_memory_coherent(
readout_freq=6.2e9,
control_freq=4.2e9,
memory_freq=3.5e9,
readout_amp=0.1,
control_amp=0.5,
memory_amp=0.2,
readout_duration=2.5e-6,
control_duration=2000e-9,
memory_duration=50e-9,
sample_duration=2.5e-6,
delay_arr=np.linspace(0, 2000e-6, 101),
readout_port=1,
control_port=2,
memory_port=5,
sample_port=1,
wait_delay=5e-3,
readout_sample_delay=0e-9,
num_averages=100,
)
presto_address = "192.168.88.65" # your Presto IP address
save_filename = experiment.run(presto_address)
Or you can also load older data:
experiment = T1_memory_coherent.load("../data/t1_memory_coherent_20230704_150826.h5")
In either case, we analyze the data to get a nice plot. In odrer to fit the data, we should know the amplitude of the displacement beta
.
experiment.analyze(beta=3.31)
It is also possible to fit beta
by not providing it to the analyze method.
experiment.analyze()
Note
To convert amplitudes from Presto units into displacement amplitude units perform Displacement calibration experiment and extract the conversion factor.
The qubit starts in the ground state at zero delay \(\delta = 0~\mu s\) as there is no population of Fock state \(|0\rangle\) since the displacement amplitude is relatively large and the selective qubit \(\pi\) pulse does not affect the qubit state. The amplitude of the coherent state exponentially decays for increasing \(\delta\) \(\alpha(\delta)=\alpha_0 \exp(-\delta/(2T_1))\). Hence, the probability to find the Fock state \(|0\rangle\) is \(P_{|0\rangle}(\delta)=\exp(-|\alpha(\delta)|^2)\). We qubit population is proportional to Fock state \(|0\rangle\) population after the selective \(\pi\) pulse, so the relaxation time \(T_1\) of the memory is extracted from the fit. The complex-valued readout signal is rotated using utils.rotate_opt()
so that all the information about the qubit state is in the I quadrature.
Code explanation¶
Here we discuss the main part of the code of the t1_memory_coherent
class: the definition of the experiment
sequence. The full source is available at presto-measure/t1_memory_coherent.py.
We implement the variable delay in the measurement with a single for
loop:
T = 0.0 # s, start at time zero ...
for delay in self.delay_arr:
pls.output_pulse(T, memory_pulse) # displace memory
T += self.memory_duration
T += delay # increasing delay
pls.output_pulse(T, control_pulse) # pi pulse conditioned on memory in |0>
T += self.control_duration
pls.output_pulse(T, readout_pulse) # Readout
pls.store(T + self.readout_sample_delay)
T += self.readout_duration
T += self.wait_delay # Wait for decay
We first displace the memory. After waiting a variable amount of time, we output qubit-control \(\pi\) pulse that maps the population of Fock state \(|0\rangle\) in the memory onto qubit population. Finally, we perform the readout.
run()
executes the experiment sequence. We set repeat_count=1
since the whole
pulse sequence is already programmed in the for loop.
pls.run(period=T, repeat_count=1, num_averages=self.num_averages)