Handling parameters in ParaQeet¶
The optimisation map is a utility class that collects all parameters that shall be considered during optimisation and associates them with the corresponding Optimisable interface. With this class, Quantities can be traced back to the Optimisable to which they belong. Before optimisation, an instance of this class needs to be filled and passed to the optimiser.
from paraqeet.optimisation_map import OptimisationMap
from paraqeet.signal.iq_mixer import IQMixer
from paraqeet.signal.envelopes import ConstantEnvelope, FlatTopGaussianEnvelope
Example devices and their parameters¶
We define some signal generator and look at its parameters:
tone = ConstantEnvelope()
gen = IQMixer(envelopes=[tone])
params = gen.get_parameters()
params
[Amplitude: 24.7 MHz x 2pi,
t_final: 32 ns,
lo_freq: 4.8 GHz x 2pi,
Phase: 0 rad]
The Optimisation Map¶
To handle the parameters of both tones, we make an OptimisationMap and add the parameters of the first tone explcitely.
optmap = OptimisationMap()
optmap.add(gen, params)
We can get a list output of all parameters with
optmap.get_all_parameters()
[Amplitude: 24.7 MHz x 2pi,
t_final: 32 ns,
lo_freq: 4.8 GHz x 2pi,
Phase: 0 rad]
Or a human readalbe output to check that we didn’t make a mistake in configuration.
optmap
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[Amplitude: 24.7 MHz x 2pi, t_final: 32 ns, lo_freq: 4.8 GHz x 2pi, Phase: 0 rad]
If we just want to optimise just the frequency, we set
optmap.add(gen, [params[2]])
optmap
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[lo_freq: 4.8 GHz x 2pi]
Adding more devices¶
As a second drive, we create a signal shaped by an error function envelope:
tone2 = FlatTopGaussianEnvelope()
gen2 = IQMixer(envelopes=[tone2])
If we don’t specify an explicit list of parameters, all of them get added.
optmap.add(gen2)
optmap.get_all_parameters()
[lo_freq: 4.8 GHz x 2pi,
Amplitude: 24.7 MHz x 2pi,
t_final: 32 ns,
lo_freq: 4.8 GHz x 2pi,
Phase: 0 rad]
optmap
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[lo_freq: 4.8 GHz x 2pi]
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[Amplitude: 24.7 MHz x 2pi, t_final: 32 ns, lo_freq: 4.8 GHz x 2pi, Phase: 0 rad]
Selecting parameters¶
There’s a convenient filter method to select parameters based on properties. The following example selects all amplitudes:
def all_amplitudes(par):
"""Get the amplitudes."""
return par.get_name() == "Amplitude"
optmap.filter_parameters(all_amplitudes)
optmap.get_all_parameters()
[Amplitude: 24.7 MHz x 2pi]
optmap
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[Amplitude: 24.7 MHz x 2pi]
Adding back all parameters:
optmap.add(gen)
optmap.add(gen2)
optmap
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[Amplitude: 24.7 MHz x 2pi, t_final: 32 ns, lo_freq: 4.8 GHz x 2pi, Phase: 0 rad]
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[Amplitude: 24.7 MHz x 2pi, t_final: 32 ns, lo_freq: 4.8 GHz x 2pi, Phase: 0 rad]
Now, we select every parameter with unit “Hz”:
def hz_filter(par):
"""Get every parameter with the unit 'Hz'."""
return par.get_unit() == "Hz"
optmap.filter_parameters(hz_filter)
optmap
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[Amplitude: 24.7 MHz x 2pi, lo_freq: 4.8 GHz x 2pi]
==== <class 'paraqeet.signal.iq_mixer.IQMixer'> ====
[Amplitude: 24.7 MHz x 2pi, lo_freq: 4.8 GHz x 2pi]