sqdtoolz 0.9.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqdtoolz/Drivers/ACQ_ETH_FPGA.py +509 -0
- sqdtoolz/Drivers/ACQ_M4i_Digitiser.py +397 -0
- sqdtoolz/Drivers/ACQ_TektronixDSA70804B.py +775 -0
- sqdtoolz/Drivers/ATTEN_Vaunix.py +106 -0
- sqdtoolz/Drivers/AWG5014C.py +296 -0
- sqdtoolz/Drivers/Agilent_N8241A.py +1797 -0
- sqdtoolz/Drivers/DDG_DG645.py +232 -0
- sqdtoolz/Drivers/DSO_DS1054Z.py +426 -0
- sqdtoolz/Drivers/Dependencies/Agilent_N8241A_constants_python3.py +794 -0
- sqdtoolz/Drivers/Dependencies/PrologixGPIBEthernet.py +65 -0
- sqdtoolz/Drivers/Dependencies/RPi_gpio_interface.py +91 -0
- sqdtoolz/Drivers/Dependencies/RPi_serial_interface.py +82 -0
- sqdtoolz/Drivers/Dependencies/Spectrum/M4i.py +1380 -0
- sqdtoolz/Drivers/Dependencies/Spectrum/__init__.py +0 -0
- sqdtoolz/Drivers/Dependencies/Spectrum/py_header/__init__.py +0 -0
- sqdtoolz/Drivers/Dependencies/Spectrum/py_header/regs.py +2863 -0
- sqdtoolz/Drivers/Dependencies/Spectrum/py_header/spcerr.py +81 -0
- sqdtoolz/Drivers/Dependencies/Spectrum/pyspcm.py +245 -0
- sqdtoolz/Drivers/Dependencies/teproteus.py +977 -0
- sqdtoolz/Drivers/Dependencies/tevisainst.py +498 -0
- sqdtoolz/Drivers/FGEN_FY6900.py +234 -0
- sqdtoolz/Drivers/MWS_SGS100A.py +203 -0
- sqdtoolz/Drivers/MWS_SMB100A.py +274 -0
- sqdtoolz/Drivers/MWS_WFSynthHDProV2.py +222 -0
- sqdtoolz/Drivers/MWS_WFSynthHDProV2_RPi.py +56 -0
- sqdtoolz/Drivers/SA_RS_FSV.py +246 -0
- sqdtoolz/Drivers/SMU_B2901A.py +226 -0
- sqdtoolz/Drivers/SMU_Keithley236.py +404 -0
- sqdtoolz/Drivers/SMU_TENMA_72_2710.py +192 -0
- sqdtoolz/Drivers/SW_BJT_RPi.py +87 -0
- sqdtoolz/Drivers/SW_BJT_RPi_Multi.py +107 -0
- sqdtoolz/Drivers/SW_FPGA_VNA.py +114 -0
- sqdtoolz/Drivers/SW_RFSwitchController_CryoRadiall.py +146 -0
- sqdtoolz/Drivers/SW_RPiCryo.py +198 -0
- sqdtoolz/Drivers/SW_RPiRadial.py +183 -0
- sqdtoolz/Drivers/SW_RpiIQBox.py +41 -0
- sqdtoolz/Drivers/THERM_TC0309.py +72 -0
- sqdtoolz/Drivers/Tabor_P2584M.py +1874 -0
- sqdtoolz/Drivers/VNA_Agilent_N5232A.py +680 -0
- sqdtoolz/Drivers/VNA_Keysight_P9373A.py +17 -0
- sqdtoolz/Drivers/VOLT_Delft_IVVI.py +1194 -0
- sqdtoolz/Drivers/VOLT_IVVI_pyro.py +135 -0
- sqdtoolz/Drivers/VOLT_RpiMultiDAC.py +74 -0
- sqdtoolz/Drivers/VOLT_SIM928_PLX.py +371 -0
- sqdtoolz/Drivers/VOLT_SIM928_VCOM.py +381 -0
- sqdtoolz/Drivers/VOLT_SIM928_pyro.py +50 -0
- sqdtoolz/Drivers/VOLT_Stahl_16CH.py +304 -0
- sqdtoolz/Drivers/ZILabOneQ.py +41 -0
- sqdtoolz/Drivers/__init__.py +0 -0
- sqdtoolz/Drivers/dummyACQ.py +109 -0
- sqdtoolz/Drivers/dummyACQex.py +120 -0
- sqdtoolz/Drivers/dummyAWG.py +121 -0
- sqdtoolz/Drivers/dummyDDG.py +116 -0
- sqdtoolz/Drivers/dummyGENmwSource.py +125 -0
- sqdtoolz/Drivers/dummySMU.py +100 -0
- sqdtoolz/Experiment.py +406 -0
- sqdtoolz/ExperimentConfiguration.py +464 -0
- sqdtoolz/ExperimentSpecification.py +150 -0
- sqdtoolz/ExperimentSpecifications/__init__.py +0 -0
- sqdtoolz/ExperimentSweeps.py +70 -0
- sqdtoolz/Experiments/Experimental/ExpACstarkRamseyGE.py +122 -0
- sqdtoolz/Experiments/Experimental/ExpBodePlot.py +69 -0
- sqdtoolz/Experiments/Experimental/ExpCalibGE.py +67 -0
- sqdtoolz/Experiments/Experimental/ExpCalibXrot.py +107 -0
- sqdtoolz/Experiments/Experimental/ExpCalibXrotAuto.py +126 -0
- sqdtoolz/Experiments/Experimental/ExpGateBenchmarks.py +109 -0
- sqdtoolz/Experiments/Experimental/ExpHahnGE.py +121 -0
- sqdtoolz/Experiments/Experimental/ExpMixerCalibrationLO.py +130 -0
- sqdtoolz/Experiments/Experimental/ExpMixerCalibrationSB.py +102 -0
- sqdtoolz/Experiments/Experimental/ExpPeakScouterIQ.py +68 -0
- sqdtoolz/Experiments/Experimental/ExpPulsedCavitySpec.py +93 -0
- sqdtoolz/Experiments/Experimental/ExpQubitFluxSweep.py +83 -0
- sqdtoolz/Experiments/Experimental/ExpRabi.py +170 -0
- sqdtoolz/Experiments/Experimental/ExpRamseyGE.py +125 -0
- sqdtoolz/Experiments/Experimental/ExpRandomisedBenchmarking.py +142 -0
- sqdtoolz/Experiments/Experimental/ExpResistanceIVs.py +54 -0
- sqdtoolz/Experiments/Experimental/ExpResistanceIVsFast.py +45 -0
- sqdtoolz/Experiments/Experimental/ExpSingleShotGE.py +74 -0
- sqdtoolz/Experiments/Experimental/ExpT1GE.py +119 -0
- sqdtoolz/Experiments/Experimental/ExpVNAEquations.py +120 -0
- sqdtoolz/Experiments/Experimental/ExpVNAoptimalSNR.py +38 -0
- sqdtoolz/Experiments/Experimental/ExpZIActiveResetTuneup.py +81 -0
- sqdtoolz/Experiments/Experimental/ExpZIBenchmarkETH.py +95 -0
- sqdtoolz/Experiments/Experimental/ExpZIBlobs.py +83 -0
- sqdtoolz/Experiments/Experimental/ExpZICalibX.py +142 -0
- sqdtoolz/Experiments/Experimental/ExpZIChevrons.py +65 -0
- sqdtoolz/Experiments/Experimental/ExpZIChevrons2QFixedCoupler.py +182 -0
- sqdtoolz/Experiments/Experimental/ExpZICryoscope.py +313 -0
- sqdtoolz/Experiments/Experimental/ExpZIDailyTuneup.py +132 -0
- sqdtoolz/Experiments/Experimental/ExpZIDispersive.py +110 -0
- sqdtoolz/Experiments/Experimental/ExpZIDragScaling.py +90 -0
- sqdtoolz/Experiments/Experimental/ExpZIFixedCouplerTuneup.py +152 -0
- sqdtoolz/Experiments/Experimental/ExpZIQASM.py +133 -0
- sqdtoolz/Experiments/Experimental/ExpZIQASMDataViewer.py +63 -0
- sqdtoolz/Experiments/Experimental/ExpZIQubitFluxSweep.py +252 -0
- sqdtoolz/Experiments/Experimental/ExpZIQubitPowerSweep.py +114 -0
- sqdtoolz/Experiments/Experimental/ExpZIQubitSpec.py +59 -0
- sqdtoolz/Experiments/Experimental/ExpZIRabi.py +111 -0
- sqdtoolz/Experiments/Experimental/ExpZIRabiRamseyT1.py +164 -0
- sqdtoolz/Experiments/Experimental/ExpZIRamsey.py +103 -0
- sqdtoolz/Experiments/Experimental/ExpZIRandomisedBenchmarking.py +126 -0
- sqdtoolz/Experiments/Experimental/ExpZIRes.py +123 -0
- sqdtoolz/Experiments/Experimental/ExpZIResFluxSweep.py +101 -0
- sqdtoolz/Experiments/Experimental/ExpZIResOptimal.py +224 -0
- sqdtoolz/Experiments/Experimental/ExpZIResPowerSweep.py +66 -0
- sqdtoolz/Experiments/Experimental/ExpZISingleQubitTuneup.py +363 -0
- sqdtoolz/Experiments/Experimental/ExpZIT1.py +86 -0
- sqdtoolz/Experiments/Experimental/ExpZIT1SingleShot.py +53 -0
- sqdtoolz/Experiments/Experimental/ExpZITWPATuneup.py +134 -0
- sqdtoolz/Experiments/Experimental/ExpZIqubit.py +289 -0
- sqdtoolz/Experiments/Experimental/ZI/calibrate_tunable_transmon_fixed_coupler.py +311 -0
- sqdtoolz/Experiments/Experimental/ZI/calibrate_tunable_transmon_fixed_coupler_osc.py +291 -0
- sqdtoolz/Experiments/Experimental/ZI/cryo_scope.py +329 -0
- sqdtoolz/Experiments/Experimental/ZI/flux_scope.py +309 -0
- sqdtoolz/Experiments/Experimental/ZI/oqasm_scheduled_qubits.py +320 -0
- sqdtoolz/Experiments/Experimental/ZI/qubit_single_chevron.py +290 -0
- sqdtoolz/Experiments/Experimental/ZI/qubit_spectroscopy_gef.py +288 -0
- sqdtoolz/Experiments/Experimental/ZI/single_qubit_gates.py +259 -0
- sqdtoolz/Experiments/Experimental/ZI/single_qubit_gates_sweep.py +280 -0
- sqdtoolz/Experiments/Experimental/ZI/sinlge_qubit_gates_sweep_chunking.py +288 -0
- sqdtoolz/HAL/ACQ.py +171 -0
- sqdtoolz/HAL/ACQdso.py +166 -0
- sqdtoolz/HAL/ACQsa.py +108 -0
- sqdtoolz/HAL/ACQvna.py +192 -0
- sqdtoolz/HAL/AWG.py +1057 -0
- sqdtoolz/HAL/DDG.py +93 -0
- sqdtoolz/HAL/DataProcessor.py +45 -0
- sqdtoolz/HAL/DecisionBlock.py +10 -0
- sqdtoolz/HAL/Decisions/DEC_SVM.py +38 -0
- sqdtoolz/HAL/GENatten.py +34 -0
- sqdtoolz/HAL/GENfuncGen.py +86 -0
- sqdtoolz/HAL/GENmwSource.py +132 -0
- sqdtoolz/HAL/GENmwSrcAWG.py +157 -0
- sqdtoolz/HAL/GENsmu.py +176 -0
- sqdtoolz/HAL/GENswitch.py +38 -0
- sqdtoolz/HAL/GENswitchTrig.py +44 -0
- sqdtoolz/HAL/GENtherm.py +29 -0
- sqdtoolz/HAL/GENvoltSource.py +50 -0
- sqdtoolz/HAL/HALbase.py +78 -0
- sqdtoolz/HAL/LockableProperties.py +22 -0
- sqdtoolz/HAL/MultiACQ.py +160 -0
- sqdtoolz/HAL/Processors/CPU/CPU_AmpPhs.py +48 -0
- sqdtoolz/HAL/Processors/CPU/CPU_ChannelArithmetic.py +72 -0
- sqdtoolz/HAL/Processors/CPU/CPU_ConstantArithmetic.py +54 -0
- sqdtoolz/HAL/Processors/CPU/CPU_DDC.py +52 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Decimation.py +47 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Duplicate.py +35 -0
- sqdtoolz/HAL/Processors/CPU/CPU_ESD.py +54 -0
- sqdtoolz/HAL/Processors/CPU/CPU_FFT.py +55 -0
- sqdtoolz/HAL/Processors/CPU/CPU_FIR.py +67 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Integrate.py +39 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Max.py +39 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Mean.py +39 -0
- sqdtoolz/HAL/Processors/CPU/CPU_MeanBlock.py +46 -0
- sqdtoolz/HAL/Processors/CPU/CPU_MeanVariance.py +43 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Rename.py +27 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Slice.py +46 -0
- sqdtoolz/HAL/Processors/CPU/CPU_Variance.py +39 -0
- sqdtoolz/HAL/Processors/CPU/CPU_kMeans.py +49 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_DDC.py +54 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_DDCFIR.py +62 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_Decimation.py +29 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_FFT.py +24 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_FIR.py +56 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_Integrate.py +27 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_Mean.py +27 -0
- sqdtoolz/HAL/Processors/FPGA/FPGA_MultiplierConst.py +47 -0
- sqdtoolz/HAL/Processors/GPU/GPU_ChannelArithmetic.py +74 -0
- sqdtoolz/HAL/Processors/GPU/GPU_ConstantArithmetic.py +54 -0
- sqdtoolz/HAL/Processors/GPU/GPU_DDC.py +52 -0
- sqdtoolz/HAL/Processors/GPU/GPU_Decimation.py +52 -0
- sqdtoolz/HAL/Processors/GPU/GPU_Duplicate.py +35 -0
- sqdtoolz/HAL/Processors/GPU/GPU_ESD.py +56 -0
- sqdtoolz/HAL/Processors/GPU/GPU_FFT.py +57 -0
- sqdtoolz/HAL/Processors/GPU/GPU_FIR.py +87 -0
- sqdtoolz/HAL/Processors/GPU/GPU_Integrate.py +37 -0
- sqdtoolz/HAL/Processors/GPU/GPU_Max.py +37 -0
- sqdtoolz/HAL/Processors/GPU/GPU_Mean.py +37 -0
- sqdtoolz/HAL/Processors/GPU/GPU_MeanBlock.py +47 -0
- sqdtoolz/HAL/Processors/GPU/GPU_Rename.py +27 -0
- sqdtoolz/HAL/Processors/GPU/GPU_Slice.py +37 -0
- sqdtoolz/HAL/Processors/ProcessorCPU.py +176 -0
- sqdtoolz/HAL/Processors/ProcessorFPGA.py +91 -0
- sqdtoolz/HAL/Processors/ProcessorGPU.py +197 -0
- sqdtoolz/HAL/SOFTpid.py +169 -0
- sqdtoolz/HAL/SOFTqpu.py +254 -0
- sqdtoolz/HAL/TriggerPulse.py +223 -0
- sqdtoolz/HAL/WaveformGeneric.py +49 -0
- sqdtoolz/HAL/WaveformMapper.py +11 -0
- sqdtoolz/HAL/WaveformSegments.py +601 -0
- sqdtoolz/HAL/WaveformTransformations.py +221 -0
- sqdtoolz/HAL/ZI/QuantumElements/TunableTransmonCouplerFixed.py +139 -0
- sqdtoolz/HAL/ZI/QuantumElements/__init__.py +18 -0
- sqdtoolz/HAL/ZI/ZIACQ.py +209 -0
- sqdtoolz/HAL/ZI/ZIPulses.py +253 -0
- sqdtoolz/HAL/ZI/ZIQuantumElement.py +126 -0
- sqdtoolz/HAL/ZI/ZIQubit.py +294 -0
- sqdtoolz/HAL/ZI/ZIbase.py +3 -0
- sqdtoolz/HAL/ZI/__init__.py +3 -0
- sqdtoolz/Laboratory.py +654 -0
- sqdtoolz/Utilities/DataFitting.py +776 -0
- sqdtoolz/Utilities/DataIQDiscriminate.py +160 -0
- sqdtoolz/Utilities/DataIQNormalise.py +76 -0
- sqdtoolz/Utilities/DataQubitFlux.py +309 -0
- sqdtoolz/Utilities/DataSingleShotThreshold.py +92 -0
- sqdtoolz/Utilities/ExperimentViewer.py +878 -0
- sqdtoolz/Utilities/FileConverter.py +49 -0
- sqdtoolz/Utilities/FileIO.py +592 -0
- sqdtoolz/Utilities/FileJSON.py +48 -0
- sqdtoolz/Utilities/Flattenator.py +168 -0
- sqdtoolz/Utilities/Miscellaneous.py +111 -0
- sqdtoolz/Utilities/OpenQASM/ParserOpenQASM.py +1195 -0
- sqdtoolz/Utilities/OpenQASM/ScheduleParametersJSONConfigZI.py +72 -0
- sqdtoolz/Utilities/OpenQASM/ScheduleParametersSoftQPUZI.py +44 -0
- sqdtoolz/Utilities/OpenQASM/__init__.py +27 -0
- sqdtoolz/Utilities/OpenQASM/includes/stdgates.inc +270 -0
- sqdtoolz/Utilities/OpenQASM/includes/stdgates_transmon_fixed_coupler.inc +24 -0
- sqdtoolz/Utilities/Optimisers.py +64 -0
- sqdtoolz/Utilities/QubitGates.py +264 -0
- sqdtoolz/Utilities/ResonatorTools.py +2469 -0
- sqdtoolz/Utilities/TimingPlots.py +328 -0
- sqdtoolz/Variable.py +387 -0
- sqdtoolz/__init__.py +42 -0
- sqdtoolz-0.9.0.dev1.dist-info/METADATA +125 -0
- sqdtoolz-0.9.0.dev1.dist-info/RECORD +228 -0
- sqdtoolz-0.9.0.dev1.dist-info/WHEEL +5 -0
- sqdtoolz-0.9.0.dev1.dist-info/licenses/LICENSE +203 -0
- sqdtoolz-0.9.0.dev1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from sqdtoolz.Experiments.Experimental.ExpZIqubit import ExpZIqubit
|
|
3
|
+
from sqdtoolz.Variable import VariablePropertyTransient
|
|
4
|
+
from sqdtoolz.HAL.WaveformGeneric import *
|
|
5
|
+
from sqdtoolz.HAL.WaveformSegments import *
|
|
6
|
+
from sqdtoolz.Utilities.DataFitting import *
|
|
7
|
+
from sqdtoolz.Experiments.Experimental.ExpCalibGE import *
|
|
8
|
+
from sqdtoolz.Utilities.QubitGates import QubitGatesBase
|
|
9
|
+
import json
|
|
10
|
+
from sqdtoolz.Experiments.Experimental.ZI import single_qubit_gates_sweep
|
|
11
|
+
from sqdtoolz.Experiments.Experimental.ZI import sinlge_qubit_gates_sweep_chunking
|
|
12
|
+
from sqdtoolz.Utilities.QubitGates import QubitGatesBase
|
|
13
|
+
from sqdtoolz.Variable import VariableInternalTransient
|
|
14
|
+
|
|
15
|
+
class ExpZIBenchmarkRandomised(ExpZIqubit):
|
|
16
|
+
def __init__(self, name, expt_config, hal_QPU, qubit_ids, **kwargs):
|
|
17
|
+
self._qubit_datasets = qubit_ids
|
|
18
|
+
|
|
19
|
+
self._hal_QPU = hal_QPU
|
|
20
|
+
|
|
21
|
+
self._dont_show_plot = kwargs.pop('dont_show_plot', False)
|
|
22
|
+
assert (not 'update' in kwargs) or ('update' in kwargs and not kwargs['update']), "Don't set 'update=True'. The updates shall be done by calling update_qubit after running the experiment."
|
|
23
|
+
kwargs['update'] = False
|
|
24
|
+
|
|
25
|
+
kwargs['coordinate_system'] = kwargs.get('coordinate_system', 'RH')
|
|
26
|
+
assert kwargs['coordinate_system'] in ['LH', 'RH'], "The 'coordinate_system' must be either LH or RH for left/right handed."
|
|
27
|
+
|
|
28
|
+
self._fit_vals = []
|
|
29
|
+
|
|
30
|
+
#extra_gate_seqs = kwargs.get('extra_gate_seqs', [])
|
|
31
|
+
self._rb_seed = kwargs.get('rb_seed', 88)
|
|
32
|
+
self._rng = np.random.default_rng(seed = self._rb_seed)
|
|
33
|
+
|
|
34
|
+
self._sequence_lengths = kwargs.pop('sequence_lengths', [3,4,5,6,7,8,9,10,11,12])
|
|
35
|
+
self._num_trials = kwargs.pop('num_trials',5)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
self._gate_set = ['X', 'X/2', '-X/2', 'Y', 'Y/2', '-Y/2']
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
self._all_seqs = {}
|
|
42
|
+
kwargs['gate_lists'] = []
|
|
43
|
+
print("Generating gate sequences...")
|
|
44
|
+
for seq_len in self._sequence_lengths:
|
|
45
|
+
self._all_seqs[int(seq_len)] = {}
|
|
46
|
+
for trial in range(self._num_trials):
|
|
47
|
+
cur_seq = self._generate_sequence(seq_len)
|
|
48
|
+
kwargs['gate_lists'].append([cur_seq]*len(qubit_ids))
|
|
49
|
+
self._all_seqs[int(seq_len)][int(trial)] = [cur_seq]*len(qubit_ids)
|
|
50
|
+
self._all_seqs_list = kwargs['gate_lists']
|
|
51
|
+
print("Done.")
|
|
52
|
+
super().__init__(name, expt_config, sinlge_qubit_gates_sweep_chunking, hal_QPU, qubit_ids, **kwargs)
|
|
53
|
+
|
|
54
|
+
def _generate_sequence(self, seq_len):
|
|
55
|
+
#Keep trying to find random sequences that enable the final gate to be within the gate-set - e.g. X/2, Y will give a 45° rotation...
|
|
56
|
+
while(True):
|
|
57
|
+
rand_int_array = self._rng.integers(low=0, high=len(self._gate_set)-1, size=seq_len-1)
|
|
58
|
+
gate_seq = [self._gate_set[i] for i in rand_int_array]
|
|
59
|
+
gate_mats = [QubitGatesBase.get_rotation_from_Pauli_Matrix(g) for g in gate_seq]
|
|
60
|
+
gate_mats.reverse()
|
|
61
|
+
effective_gate = np.linalg.multi_dot(gate_mats)
|
|
62
|
+
#Final state should be excited-state...
|
|
63
|
+
XReInv = QubitGatesBase.get_rotation_from_Pauli_Matrix('X') @ np.linalg.inv(effective_gate)
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
final_gate = QubitGatesBase.convert_Pauli_rotation_to_natural( *QubitGatesBase.compute_rotation_Pauli_Matrices(XReInv))
|
|
67
|
+
except:
|
|
68
|
+
continue
|
|
69
|
+
if final_gate == 'Z' or final_gate == 'Z/2' or final_gate == '-Z/2':
|
|
70
|
+
final_gate = 'I'
|
|
71
|
+
gate_seq.append(final_gate)
|
|
72
|
+
|
|
73
|
+
return gate_seq
|
|
74
|
+
|
|
75
|
+
def _post_process(self, data):
|
|
76
|
+
for ind_qubit, qubit_dataset in enumerate(self._qubit_datasets):
|
|
77
|
+
leData = self.retrieve_last_dataset(qubit_dataset)
|
|
78
|
+
arr = leData.get_numpy_array()
|
|
79
|
+
seqs = leData.param_vals[0]
|
|
80
|
+
seq_lens = np.array(self._sequence_lengths)
|
|
81
|
+
norm = ExpZIqubit.normalise_qubit_data(self.retrieve_last_dataset(qubit_dataset+'_calib'), self._transition)
|
|
82
|
+
probs = norm.normalise_data(arr)
|
|
83
|
+
mean_vals = []
|
|
84
|
+
std_vals = []
|
|
85
|
+
|
|
86
|
+
fig, axs = plt.subplots(ncols=2); fig.set_figwidth(12); axs[0].grid(); axs[1].grid()
|
|
87
|
+
|
|
88
|
+
for m in range(len(self._sequence_lengths)):
|
|
89
|
+
trial_probs = []
|
|
90
|
+
xvals = []
|
|
91
|
+
for k in range(self._num_trials):
|
|
92
|
+
cur_seq_index = m*self._num_trials + k
|
|
93
|
+
if probs[cur_seq_index] < 0.8:
|
|
94
|
+
continue
|
|
95
|
+
trial_probs.append(probs[cur_seq_index])
|
|
96
|
+
xvals.append(self._sequence_lengths[m])
|
|
97
|
+
cur_x = xvals
|
|
98
|
+
cur_y = trial_probs
|
|
99
|
+
axs[0].plot(cur_x, cur_y, 'kx', alpha = 0.3)
|
|
100
|
+
mean_vals.append(np.mean(cur_y))
|
|
101
|
+
std_vals.append(np.std(cur_y))
|
|
102
|
+
mean_vals = np.array(mean_vals)
|
|
103
|
+
std_vals = np.array(std_vals)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
axs[0].plot(seq_lens, mean_vals)
|
|
108
|
+
axs[0].fill_between(seq_lens, mean_vals-std_vals, mean_vals+std_vals, alpha=0.5)
|
|
109
|
+
axs[0].set_xlabel('Sequence Length')
|
|
110
|
+
axs[0].set_ylabel('Excited State Probability')
|
|
111
|
+
axs[0].set_title(f'Number of Trials per Sequence Length: {self._num_trials}')
|
|
112
|
+
|
|
113
|
+
zProj = mean_vals - 0.5
|
|
114
|
+
slope, intercept = np.polyfit(seq_lens, np.log(zProj), deg=1)
|
|
115
|
+
error_per_gate = np.exp(slope)
|
|
116
|
+
axs[1].plot(seq_lens, np.log(zProj), 'kx')
|
|
117
|
+
axs[1].plot(seq_lens, seq_lens*slope+intercept, 'r-')
|
|
118
|
+
axs[1].set_xlabel('Sequence Length')
|
|
119
|
+
axs[1].set_ylabel(r'$\ell n(Z_{proj})$')
|
|
120
|
+
axs[1].set_title(f"Error per Gate: {(error_per_gate*100):.6g}%")
|
|
121
|
+
axs[1].legend(['Raw Data', 'Fitted Error line'])
|
|
122
|
+
|
|
123
|
+
fig.show()
|
|
124
|
+
fig.savefig(self._file_path + 'Summary.png')
|
|
125
|
+
|
|
126
|
+
return data
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from sqdtoolz.Experiments.Experimental.ExpZIqubit import ExpZIqubit
|
|
2
|
+
from sqdtoolz.Utilities.DataFitting import*
|
|
3
|
+
from sqdtoolz.Utilities.ResonatorTools import ResonatorPowerSweep
|
|
4
|
+
from laboneq_applications.experiments import (
|
|
5
|
+
resonator_spectroscopy,
|
|
6
|
+
resonator_spectroscopy_amplitude,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
class ExpZIRes(ExpZIqubit):
|
|
10
|
+
def __init__(self, name, expt_config, hal_QPU, qubit_id, **kwargs):
|
|
11
|
+
assert isinstance(qubit_id, str), "Supply qubit_id as the solitary string ID here (i.e. not a list)."
|
|
12
|
+
self._qubit_dataset = qubit_id
|
|
13
|
+
|
|
14
|
+
self._update_qubit = kwargs.pop('update_qubit_params', True)
|
|
15
|
+
|
|
16
|
+
self._dont_show_plot = kwargs.pop('dont_show_plot', False)
|
|
17
|
+
|
|
18
|
+
self._iq_indices = kwargs.pop('iq_indices', [0,1])
|
|
19
|
+
self._is_trough = kwargs.pop('is_trough', False)
|
|
20
|
+
self._fit_type = kwargs.pop('fit_type', 'Default') #Default, Fano, Full
|
|
21
|
+
assert self._fit_type in ["Default", "Fano", "Full"], "Choose fit_type as either 'Default', 'Fano' or 'Full'."
|
|
22
|
+
assert self._is_trough or (not self._is_trough and not self._fit_type=='Fano'), "Fano resonance fitting only supports troughs at the moment."
|
|
23
|
+
self._param_centre = kwargs.pop('param_freq', None)
|
|
24
|
+
self._param_width = kwargs.pop('param_width', None)
|
|
25
|
+
self._param_amplitude = kwargs.pop('param_amplitude', None)
|
|
26
|
+
self._param_offset = kwargs.pop('param_offset', None)
|
|
27
|
+
self._param_fano = kwargs.pop('param_fano', None)
|
|
28
|
+
self._dont_plot = kwargs.pop('dont_plot', False)
|
|
29
|
+
self._xUnits = kwargs.pop('plot_x_units', 'Hz')
|
|
30
|
+
self._hal_QPU = hal_QPU
|
|
31
|
+
|
|
32
|
+
self._frequencies = kwargs.pop('frequencies', None)
|
|
33
|
+
self._span = kwargs.pop('span', 5e6)
|
|
34
|
+
self._num_freq_pts = kwargs.pop('num_frequency_points', 401)
|
|
35
|
+
|
|
36
|
+
if self._frequencies is None:
|
|
37
|
+
self._frequencies = np.linspace(-self._span, self._span, self._num_freq_pts) + self._hal_QPU.get_qubit_obj(self._qubit_dataset).ReadoutFrequency
|
|
38
|
+
|
|
39
|
+
kwargs['frequencies'] = self._frequencies
|
|
40
|
+
|
|
41
|
+
super().__init__(name, expt_config, resonator_spectroscopy, hal_QPU, [qubit_id], **kwargs)
|
|
42
|
+
|
|
43
|
+
def _post_process(self, data):
|
|
44
|
+
data = self.retrieve_last_dataset(self._qubit_dataset)
|
|
45
|
+
assert len(data.param_names), "The sweep should only be 1D."
|
|
46
|
+
|
|
47
|
+
arr = data.get_numpy_array()
|
|
48
|
+
data_x = data.param_vals[0]
|
|
49
|
+
data_i = arr[:,self._iq_indices[0]]
|
|
50
|
+
data_q = arr[:,self._iq_indices[1]]
|
|
51
|
+
data_y = np.sqrt(arr[:,self._iq_indices[0]]**2 + arr[:,self._iq_indices[1]]**2)
|
|
52
|
+
|
|
53
|
+
if self._fit_type == "Default":
|
|
54
|
+
dfit = DFitPeakLorentzian()
|
|
55
|
+
dpkt = dfit.get_fitted_plot(data_x, data_y**2, xLabel="Frequency (Hz)", dip=self._is_trough, dontplot=self._dont_plot, xUnits=self._xUnits)
|
|
56
|
+
#Commit to parameters...
|
|
57
|
+
if self._update_qubit:
|
|
58
|
+
cur_qubit = self._hal_QPU.get_qubit_obj(self._qubit_dataset)
|
|
59
|
+
cur_qubit.ReadoutFrequency = dpkt['centre']
|
|
60
|
+
if self._param_centre:
|
|
61
|
+
self._param_centre.Value = dpkt['centre']
|
|
62
|
+
if self._param_width:
|
|
63
|
+
self._param_width.Value = dpkt['width']
|
|
64
|
+
if self._param_amplitude:
|
|
65
|
+
self._param_amplitude.Value = dpkt['amplitude']
|
|
66
|
+
if self._param_offset:
|
|
67
|
+
self._param_offset.Value = dpkt['offset']
|
|
68
|
+
dpkt['fit_data'] = {'squared_amplitude': dpkt['fit_data']}
|
|
69
|
+
elif self._fit_type == "Fano":
|
|
70
|
+
dfit = DFitFanoResonance()
|
|
71
|
+
dpkt = dfit.get_fitted_plot(data_x, data_y**2, xLabel="Frequency (Hz)", yLabel="Squared IQ Amplitude", dontplot=self._dont_plot, xUnits=self._xUnits) #, dip=self._is_trough)
|
|
72
|
+
#Commit to parameters...
|
|
73
|
+
if self._update_qubit:
|
|
74
|
+
cur_qubit = self._hal_QPU.get_qubit_obj(self._qubit_dataset)
|
|
75
|
+
cur_qubit.ReadoutFrequency = dpkt['xMinimum']
|
|
76
|
+
if self._param_centre:
|
|
77
|
+
self._param_centre.Value = dpkt['xMinimum']
|
|
78
|
+
if self._param_width:
|
|
79
|
+
self._param_width.Value = dpkt['width']
|
|
80
|
+
if self._param_amplitude:
|
|
81
|
+
self._param_amplitude.Value = dpkt['amplitude']
|
|
82
|
+
if self._param_offset:
|
|
83
|
+
self._param_offset.Value = dpkt['offset']
|
|
84
|
+
if self._param_fano:
|
|
85
|
+
self._param_fano.Value = dpkt['FanoFac']
|
|
86
|
+
dpkt['fit_data'] = {'squared_amplitude': dpkt['fit_data']}
|
|
87
|
+
elif self._fit_type == "Full":
|
|
88
|
+
if self._hal_QPU.get_qubit_obj(self._qubit_dataset).ReadoutLineAttenuation_dB:
|
|
89
|
+
atten = self._hal_QPU.get_qubit_obj(self._qubit_dataset).ReadoutLineAttenuation_dB
|
|
90
|
+
readout_pwr = self._hal_QPU.get_qubit_obj(self._qubit_dataset).ReadoutPower + 20*np.log10(self._hal_QPU.get_qubit_obj(self._qubit_dataset).ReadoutAmplitude)
|
|
91
|
+
dpkt = ResonatorPowerSweep.single_circlefit(data_x, data_i, data_q, power_dBm=atten + readout_pwr, dont_plot=self._dont_plot)
|
|
92
|
+
else:
|
|
93
|
+
dpkt = ResonatorPowerSweep.single_circlefit(data_x, data_i, data_q, power_dBm=-100, dont_plot=self._dont_plot)
|
|
94
|
+
#Commit to parameters...
|
|
95
|
+
if self._update_qubit:
|
|
96
|
+
cur_qubit = self._hal_QPU.get_qubit_obj(self._qubit_dataset)
|
|
97
|
+
if dpkt and dpkt['fr']:
|
|
98
|
+
cur_qubit.ReadoutFrequency = dpkt['fr']
|
|
99
|
+
cur_qubit.ReadoutQi = dpkt['Qi_dia_corr']
|
|
100
|
+
cur_qubit.ReadoutQc = dpkt['Qc_dia_corr']
|
|
101
|
+
cur_qubit.ReadoutQl = dpkt['Ql']
|
|
102
|
+
dpkt['fit_data'] = {'real': np.real(dpkt['fit_data']), 'imag': np.imag(dpkt['fit_data'])}
|
|
103
|
+
cur_qubit.ReadoutKappa = dpkt['fr'] / dpkt['Qc_dia_corr']
|
|
104
|
+
else:
|
|
105
|
+
print('Qubit parameters were not updated: bad fit.')
|
|
106
|
+
if self._param_centre:
|
|
107
|
+
self._param_centre.Value = dpkt['fr']
|
|
108
|
+
|
|
109
|
+
if dpkt:
|
|
110
|
+
if not self._dont_plot:
|
|
111
|
+
dpkt['fig'].savefig(self._file_path + 'fitted_plot.png')
|
|
112
|
+
if not self._dont_show_plot:
|
|
113
|
+
dpkt['fig'].show()
|
|
114
|
+
else:
|
|
115
|
+
plt.close(dpkt['fig'])
|
|
116
|
+
if 'fit_data' in dpkt:
|
|
117
|
+
np.save(self._file_path + 'fitted_data.npy', dpkt['fit_data'])
|
|
118
|
+
else:
|
|
119
|
+
if not self._dont_plot:
|
|
120
|
+
plt.plot(data_x, data_y)
|
|
121
|
+
plt.xlabel("Frequency (Hz)")
|
|
122
|
+
plt.ylabel("|S21|")
|
|
123
|
+
plt.show()
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from sqdtoolz.Experiments.Experimental.ExpZIqubit import ExpZIqubit
|
|
2
|
+
from laboneq_applications.experiments import resonator_spectroscopy
|
|
3
|
+
from sqdtoolz.Variable import VariablePropertyTransient
|
|
4
|
+
import numpy as np
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import scipy.interpolate
|
|
7
|
+
import scipy.optimize
|
|
8
|
+
from sqdtoolz.Utilities.DataFitting import DFitPeakLorentzian
|
|
9
|
+
|
|
10
|
+
class ExpZIResFluxSweep(ExpZIqubit):
|
|
11
|
+
def __init__(self, name, expt_config, hal_QPU, qubit_id, **kwargs):
|
|
12
|
+
assert isinstance(qubit_id, str), "Supply qubit_id as the solitary string ID here (i.e. not a list)."
|
|
13
|
+
self._qubit_id = qubit_id
|
|
14
|
+
|
|
15
|
+
self._update_qubit = kwargs.pop('update_qubit_params', True)
|
|
16
|
+
|
|
17
|
+
self._dont_show_plot = kwargs.pop('dont_show_plot', False)
|
|
18
|
+
|
|
19
|
+
self._is_trough = kwargs.pop('is_trough', True)
|
|
20
|
+
self._dont_plot = kwargs.pop('dont_plot', False)
|
|
21
|
+
self._xUnits = kwargs.pop('plot_x_units', 'Hz')
|
|
22
|
+
self._flux_range = kwargs.pop('flux_range', np.linspace(-1, 1, 10))
|
|
23
|
+
self._frequencies = kwargs.pop('frequencies', None)
|
|
24
|
+
self._span = kwargs.pop('span', 10e6)
|
|
25
|
+
self._num_freq_pts = kwargs.pop('num_frequency_points', 401)
|
|
26
|
+
self._hal_QPU = hal_QPU
|
|
27
|
+
|
|
28
|
+
self._opt_flux_val = None
|
|
29
|
+
|
|
30
|
+
if self._frequencies is None:
|
|
31
|
+
self._frequencies = np.linspace(-self._span, self._span, self._num_freq_pts) + self._hal_QPU.get_qubit_obj(self._qubit_id).ReadoutFrequency
|
|
32
|
+
|
|
33
|
+
kwargs['frequencies'] = self._frequencies
|
|
34
|
+
super().__init__(name, expt_config, resonator_spectroscopy, hal_QPU, [qubit_id], **kwargs)
|
|
35
|
+
|
|
36
|
+
def _run(self, file_path, sweep_vars=[], **kwargs):
|
|
37
|
+
assert len(sweep_vars) == 0, "Supply the frequency/flux when defining the Experiment object."
|
|
38
|
+
|
|
39
|
+
var_flux = VariablePropertyTransient('Flux', self._hal_QPU.get_qubit_obj(self._qubit_id),'FluxDC')
|
|
40
|
+
super()._run(file_path, sweep_vars=[(var_flux, self._flux_range)], **kwargs)
|
|
41
|
+
|
|
42
|
+
def _post_process(self, data):
|
|
43
|
+
leData = self.retrieve_last_dataset(self._qubit_id)
|
|
44
|
+
flux_vals,freq_vals = leData.param_vals
|
|
45
|
+
arr = leData.get_numpy_array()
|
|
46
|
+
|
|
47
|
+
ampl = np.sqrt(arr[:,:,0]**2 + arr[:,:,1]**2)
|
|
48
|
+
|
|
49
|
+
is_trough = self._is_trough
|
|
50
|
+
|
|
51
|
+
dfit = DFitPeakLorentzian()
|
|
52
|
+
res_freqs = []
|
|
53
|
+
for cur_slice in ampl:
|
|
54
|
+
dpkt = dfit.get_fitted_plot(freq_vals, cur_slice, dip=is_trough, dontplot=True)
|
|
55
|
+
res_freqs.append(dpkt['centre'])
|
|
56
|
+
res_freqs = np.array(res_freqs)
|
|
57
|
+
|
|
58
|
+
norm_fac = 10**np.round(np.log10(res_freqs).mean())
|
|
59
|
+
if flux_vals[1]-flux_vals[0] < 0:
|
|
60
|
+
spl = scipy.interpolate.UnivariateSpline(flux_vals[::-1], res_freqs[::-1]/norm_fac)
|
|
61
|
+
else:
|
|
62
|
+
spl = scipy.interpolate.UnivariateSpline(flux_vals, res_freqs/norm_fac)
|
|
63
|
+
spl.set_smoothing_factor(0.5)
|
|
64
|
+
soln = scipy.optimize.minimize_scalar(lambda x:-spl(x), bounds=(np.min(flux_vals), np.max(flux_vals)))
|
|
65
|
+
|
|
66
|
+
opt_flux = soln.x
|
|
67
|
+
sweet_freq = spl(opt_flux)*norm_fac
|
|
68
|
+
|
|
69
|
+
fitted_data = {
|
|
70
|
+
'raw_fit_freqs': res_freqs,
|
|
71
|
+
'smoothed_fit_freqs': spl(flux_vals)*norm_fac,
|
|
72
|
+
'sweet_freq_flux': np.array([sweet_freq, opt_flux])
|
|
73
|
+
}
|
|
74
|
+
np.save(self._file_path + 'fitted_data.npy', fitted_data)
|
|
75
|
+
|
|
76
|
+
if not self._dont_plot:
|
|
77
|
+
fig, ax = plt.subplots(1); fig.set_figwidth(15)
|
|
78
|
+
ExpZIResFluxSweep.plot_fitted_results(ax, self._qubit_id, freq_vals, flux_vals, ampl, fitted_data)
|
|
79
|
+
if not self._dont_show_plot:
|
|
80
|
+
fig.show()
|
|
81
|
+
else:
|
|
82
|
+
plt.close(fig)
|
|
83
|
+
fig.savefig(self._file_path + 'fitted_plot.png')
|
|
84
|
+
|
|
85
|
+
self._opt_flux_val = opt_flux
|
|
86
|
+
|
|
87
|
+
@staticmethod
|
|
88
|
+
def plot_fitted_results(ax, qubit_id, freq_vals, flux_vals, ampl, fitted_data):
|
|
89
|
+
ax.pcolor(freq_vals, flux_vals, ampl)
|
|
90
|
+
ax.plot(fitted_data['smoothed_fit_freqs'], flux_vals, 'w-')
|
|
91
|
+
ax.plot(fitted_data['raw_fit_freqs'], flux_vals, 'wo')
|
|
92
|
+
ax.plot([fitted_data['sweet_freq_flux'][0]], [fitted_data['sweet_freq_flux'][1]], 'ro')
|
|
93
|
+
ax.set_title(f"{qubit_id} resonator flux sweep: $f_r$={fitted_data['sweet_freq_flux'][0]*1e-9:.4f} GHz, $V_\Phi$={fitted_data['sweet_freq_flux'][1]:.4f} V")
|
|
94
|
+
ax.set_xlabel('Frequency (Hz)')
|
|
95
|
+
ax.set_ylabel('Flux (V)')
|
|
96
|
+
|
|
97
|
+
def update_qubit(self):
|
|
98
|
+
assert self._opt_flux_val != None, "Must run an experiment before updating qubit parameters."
|
|
99
|
+
self._hal_QPU.get_qubit_obj(self._qubit_id).FluxDC = self._opt_flux_val
|
|
100
|
+
# TODO: update flux range to minimum
|
|
101
|
+
self._opt_flux_val = None
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
from sqdtoolz.Experiments.Experimental.ExpZIqubit import ExpZIqubit
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
from sqdtoolz.Utilities.Miscellaneous import Miscellaneous
|
|
4
|
+
from laboneq_applications.experiments import dispersive_shift
|
|
5
|
+
import numpy as np
|
|
6
|
+
from sqdtoolz.Utilities.DataIQDiscriminate import DataIQDiscriminate
|
|
7
|
+
from sqdtoolz.Experiments.Experimental.ExpZIBlobs import ExpZIBlobs
|
|
8
|
+
|
|
9
|
+
class ExpZIResOptimal(ExpZIqubit):
|
|
10
|
+
def __init__(self, name, expt_config, hal_QPU, qubit_ids, **kwargs):
|
|
11
|
+
self._dont_show_plot = kwargs.pop('dont_show_plot', False)
|
|
12
|
+
assert (not 'update' in kwargs) or ('update' in kwargs and not kwargs['update']), "Don't set 'update=True'. This is just a diagnostic experiment."
|
|
13
|
+
kwargs['update'] = False
|
|
14
|
+
# self._fit_vals = []
|
|
15
|
+
assert 'states' in kwargs, "Must provide the states to measure traces over; e.g. 'ge' or 'gef'"
|
|
16
|
+
self._states = kwargs['states']
|
|
17
|
+
self._calc_single_shot_fidelities = kwargs.pop('calc_single_shot_fidelities', False)
|
|
18
|
+
if self._calc_single_shot_fidelities:
|
|
19
|
+
kwargs['do_analysis'] = False #The default ZI analysis will fail in this mode...
|
|
20
|
+
self._fit_data = {}
|
|
21
|
+
self._readout_fidelity = 0.0
|
|
22
|
+
super().__init__(name, expt_config, dispersive_shift, hal_QPU, qubit_ids, **kwargs)
|
|
23
|
+
|
|
24
|
+
def _run(self, file_path, sweep_vars=[], **kwargs):
|
|
25
|
+
if self._calc_single_shot_fidelities:
|
|
26
|
+
kwargs['override_ACQ_params'] = {'AveragingOrder': "SingleShot"}
|
|
27
|
+
return super()._run(file_path, sweep_vars, **kwargs)
|
|
28
|
+
|
|
29
|
+
def _post_process(self, data):
|
|
30
|
+
#This experiment only supports one qubit at a time...
|
|
31
|
+
leDatasets = [self.retrieve_last_dataset(self._qubit_ids[0] + '_' + x) for x in self._states]
|
|
32
|
+
arrs = [leDatasets[m].get_numpy_array() for m in range((len(self._states)))]
|
|
33
|
+
|
|
34
|
+
leCols = plt.rcParams['axes.prop_cycle'].by_key()['color']
|
|
35
|
+
if self._calc_single_shot_fidelities:
|
|
36
|
+
freqs = leDatasets[0].param_vals[1]
|
|
37
|
+
norm_fac, norm_prefix = Miscellaneous.get_metric_multiplier(freqs) #Should all be the same anyway...
|
|
38
|
+
|
|
39
|
+
fig = plt.figure(figsize=(8, 10))
|
|
40
|
+
gs = fig.add_gridspec(5, 4)
|
|
41
|
+
|
|
42
|
+
# First three rows each span all four columns
|
|
43
|
+
ax_mag = fig.add_subplot(gs[0, :])
|
|
44
|
+
axSeps = fig.add_subplot(gs[1, :], sharex=ax_mag)
|
|
45
|
+
axFids = fig.add_subplot(gs[2, :], sharex=ax_mag)
|
|
46
|
+
|
|
47
|
+
ax_mag.grid(); axSeps.grid(); axFids.grid()
|
|
48
|
+
|
|
49
|
+
axFids.set_ylabel('State Fidelities')
|
|
50
|
+
|
|
51
|
+
axFids.set_xlabel(f'Readout Frequency ({norm_prefix}Hz)')
|
|
52
|
+
else:
|
|
53
|
+
freqs = leDatasets[0].param_vals[0]
|
|
54
|
+
norm_fac, norm_prefix = Miscellaneous.get_metric_multiplier(freqs) #Should all be the same anyway...
|
|
55
|
+
fig, axs = plt.subplots(nrows=2)
|
|
56
|
+
ax_mag = axs[0]
|
|
57
|
+
axSeps = axs[1]
|
|
58
|
+
ax_mag.grid(); axSeps.grid()
|
|
59
|
+
ax_mag.set_xlabel(f'Readout Frequency ({norm_prefix}Hz)')
|
|
60
|
+
axSeps.set_xlabel(f'Readout Frequency ({norm_prefix}Hz)')
|
|
61
|
+
axSeps.set_ylabel('IQ separation')
|
|
62
|
+
|
|
63
|
+
ax_phase = ax_mag.twinx()
|
|
64
|
+
|
|
65
|
+
handles = []
|
|
66
|
+
for m in range(len(self._states)):
|
|
67
|
+
if self._calc_single_shot_fidelities:
|
|
68
|
+
arr = np.mean(arrs[m],axis=0)
|
|
69
|
+
else:
|
|
70
|
+
arr = arrs[m]
|
|
71
|
+
mag = np.sqrt(arr[:, 0]**2 + arr[:, 1]**2)
|
|
72
|
+
phase = np.unwrap(np.arctan2(arr[:, 1], arr[:, 0]))
|
|
73
|
+
# Plot magnitude and capture the line object
|
|
74
|
+
line, = ax_mag.plot(freqs/norm_fac, mag, label=self._states[m])
|
|
75
|
+
handles.append(line)
|
|
76
|
+
# Use the same colour for phase, but dashed
|
|
77
|
+
ax_phase.plot(freqs/norm_fac, phase,':',color=line.get_color())
|
|
78
|
+
|
|
79
|
+
ax_mag.set_ylabel('Magnitude')
|
|
80
|
+
ax_phase.set_ylabel('Phase (rad) (dotted)')
|
|
81
|
+
ax_mag.legend(handles=handles)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if len(self._states) == 2:
|
|
85
|
+
combs = [[0,1]]
|
|
86
|
+
else:
|
|
87
|
+
combs = [(0,1), (1,2), (0,2)]
|
|
88
|
+
|
|
89
|
+
all_diffs = []
|
|
90
|
+
maxSepInds = []
|
|
91
|
+
for m in range(len(combs)):
|
|
92
|
+
if self._calc_single_shot_fidelities:
|
|
93
|
+
arr1 = np.mean(arrs[combs[m][0]],axis=0)
|
|
94
|
+
arr2 = np.mean(arrs[combs[m][1]],axis=0)
|
|
95
|
+
else:
|
|
96
|
+
arr1 = arrs[combs[m][0]]
|
|
97
|
+
arr2 = arrs[combs[m][1]]
|
|
98
|
+
cur_diff = np.linalg.norm(arr1 - arr2, axis=1)
|
|
99
|
+
axSeps.plot(freqs/norm_fac, cur_diff, color=leCols[m])
|
|
100
|
+
maxSepInds.append(np.argmax(cur_diff))
|
|
101
|
+
axSeps.plot([freqs[maxSepInds[-1]]/norm_fac], [cur_diff[maxSepInds[-1]]], 'o', color=leCols[m], label='_nolegend_')
|
|
102
|
+
all_diffs.append(cur_diff)
|
|
103
|
+
if len(self._states) == 3:
|
|
104
|
+
cur_diff = np.sum(all_diffs, axis=0)
|
|
105
|
+
axSeps.plot(freqs/norm_fac, cur_diff, color=leCols[m+1])
|
|
106
|
+
maxSepInds.append(np.argmax(cur_diff))
|
|
107
|
+
axSeps.plot([freqs[maxSepInds[-1]]/norm_fac], [cur_diff[maxSepInds[-1]]], 'o', color=leCols[m+1], label='_nolegend_')
|
|
108
|
+
if len(self._states) == 2:
|
|
109
|
+
axSeps.legend(['GE'])
|
|
110
|
+
leTitlesSS = ['G','E','Mean']
|
|
111
|
+
else:
|
|
112
|
+
axSeps.legend(['GE', 'EF', 'GF', 'Total'])
|
|
113
|
+
leTitlesSS = ['G','E','F','Mean']
|
|
114
|
+
|
|
115
|
+
if self._calc_single_shot_fidelities:
|
|
116
|
+
leIQDiscs = [DataIQDiscriminate([arrs[x][:,m,:] for x in range(len(self._states))]) for m in range(freqs.size)]
|
|
117
|
+
leFids = [leIQDiscs[m].get_fidelities() for m in range(freqs.size)]
|
|
118
|
+
leFids = np.array(leFids)
|
|
119
|
+
#Gather fidelity data for each state the total
|
|
120
|
+
fidData = []
|
|
121
|
+
for m in range(len(self._states)):
|
|
122
|
+
fidData.append(leFids[:,m])
|
|
123
|
+
fidData.append(np.mean(leFids, axis=1))
|
|
124
|
+
|
|
125
|
+
maxFidInds = []
|
|
126
|
+
axFirst = None
|
|
127
|
+
for m in range(len(fidData)):
|
|
128
|
+
axFids.plot(freqs/norm_fac, fidData[m], color = leCols[m])
|
|
129
|
+
maxFidInds.append(np.argmax(fidData[m]))
|
|
130
|
+
axFids.plot(freqs[maxFidInds[-1]]/norm_fac, [fidData[m][maxFidInds[-1]]], 'o', color=leCols[m], label='_nolegend_')
|
|
131
|
+
|
|
132
|
+
if axFirst == None:
|
|
133
|
+
ax = fig.add_subplot(gs[3, m])
|
|
134
|
+
axFirst = ax
|
|
135
|
+
else:
|
|
136
|
+
ax = fig.add_subplot(gs[3, m], sharey=axFirst)
|
|
137
|
+
leIQDiscs[maxFidInds[-1]].plot_points(ax)
|
|
138
|
+
ax.set_title(leTitlesSS[m])
|
|
139
|
+
ax.set_xticklabels([])
|
|
140
|
+
ax.set_yticklabels([])
|
|
141
|
+
#
|
|
142
|
+
axA = fig.add_subplot(gs[4, m])
|
|
143
|
+
leIQDiscs[maxFidInds[-1]].plot_assignment_matrix(axA, sigFigs=2)
|
|
144
|
+
self._readout_fidelity = (leIQDiscs[maxFidInds[-1]].get_average_fidelity()*100)
|
|
145
|
+
axA.set_title(f"Mean: {self._readout_fidelity:.4g}%")
|
|
146
|
+
if m > 0:
|
|
147
|
+
ax.set_ylabel('')
|
|
148
|
+
axA.set_ylabel('')
|
|
149
|
+
axA.set_yticklabels([])
|
|
150
|
+
|
|
151
|
+
if len(self._states) == 2:
|
|
152
|
+
axFids.legend(['G','E','Mean'])
|
|
153
|
+
else:
|
|
154
|
+
axFids.legend(['G','E','F','Mean'])
|
|
155
|
+
|
|
156
|
+
self._fit_data = {'freqs':freqs, 'maxSepIndices':maxSepInds, 'maxFidIndices':maxFidInds, 'discriminators':leIQDiscs}
|
|
157
|
+
|
|
158
|
+
fig.subplots_adjust(hspace=0.1)
|
|
159
|
+
fig.tight_layout()
|
|
160
|
+
|
|
161
|
+
fig.savefig(self._file_path + f'fitted_plot_{self._qubit_ids[0]}.png')
|
|
162
|
+
if not self._dont_show_plot:
|
|
163
|
+
fig.show()
|
|
164
|
+
else:
|
|
165
|
+
plt.close(fig)
|
|
166
|
+
|
|
167
|
+
def update_qubits_by_separation(self, transition:str='Total'):
|
|
168
|
+
"""
|
|
169
|
+
transition is given as 'ge', 'ef', 'gf' or 'Total' (can capitalise etc.)
|
|
170
|
+
"""
|
|
171
|
+
assert len(self._fit_data) > 0, "Must run experiment first."
|
|
172
|
+
qubit_obj = self._hal_QPU.get_qubit_obj(self._qubit_ids[0])
|
|
173
|
+
transition = transition.lower()
|
|
174
|
+
if len(self._states) == 2:
|
|
175
|
+
assert transition in ['ge', 'total'], "Invalid transition (must be either 'ge' or 'total')"
|
|
176
|
+
ind = 0
|
|
177
|
+
else:
|
|
178
|
+
assert transition in ['ge', 'ef', 'gf', 'total'], "Invalid transition (must be either 'ge', 'ef', 'gf' or 'total')"
|
|
179
|
+
ind = ['ge', 'ef', 'gf', 'total'].index(transition)
|
|
180
|
+
qubit_obj.ReadoutFrequency = float( self._fit_data['freqs'][ self._fit_data['maxSepIndices'][ind] ] )
|
|
181
|
+
qubit_obj.FidelityReadout = self._readout_fidelity
|
|
182
|
+
|
|
183
|
+
def update_qubits_by_fidelity(self, state_fidelity:str='Mean'):
|
|
184
|
+
"""
|
|
185
|
+
state_fidelity is given as 'g', 'e', 'f' or 'Mean' (can capitalise etc.) to take the highest of the respective fidelities as the point.
|
|
186
|
+
"""
|
|
187
|
+
assert len(self._fit_data) > 0, "Must run experiment first."
|
|
188
|
+
assert self._calc_single_shot_fidelities, "Must run the experiment in single-shot by setting calc_single_shot_fidelities to True."
|
|
189
|
+
qubit_obj = self._hal_QPU.get_qubit_obj(self._qubit_ids[0])
|
|
190
|
+
state_fidelity = state_fidelity.lower()
|
|
191
|
+
if len(self._states) == 2:
|
|
192
|
+
assert state_fidelity in ['g', 'e', 'mean'], "Invalid state (must be either 'g', 'e' or 'mean')"
|
|
193
|
+
ind = ['g', 'e', 'mean'].index(state_fidelity)
|
|
194
|
+
else:
|
|
195
|
+
assert state_fidelity in ['g', 'e', 'f', 'mean'], "Invalid state (must be either 'g', 'e', 'f' or 'mean')"
|
|
196
|
+
ind = ['g', 'e', 'f', 'mean'].index(state_fidelity)
|
|
197
|
+
qubit_obj.ReadoutFrequency = float( self._fit_data['freqs'][ self._fit_data['maxFidIndices'][ind] ] )
|
|
198
|
+
qubit_obj.FidelityReadout = self._readout_fidelity
|
|
199
|
+
|
|
200
|
+
def print_best_frequencies_by_separation(self):
|
|
201
|
+
assert len(self._fit_data) > 0, "Must run experiment first."
|
|
202
|
+
if len(self._states) == 2:
|
|
203
|
+
print(f"Max GE: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxSepIndices'][0] ])}Hz")
|
|
204
|
+
else:
|
|
205
|
+
print(f"Max GE: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxSepIndices'][0] ])}Hz")
|
|
206
|
+
print(f"Max EF: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxSepIndices'][1] ])}Hz")
|
|
207
|
+
print(f"Max GF: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxSepIndices'][2] ])}Hz")
|
|
208
|
+
|
|
209
|
+
def print_best_frequencies_by_fidelity(self):
|
|
210
|
+
assert len(self._fit_data) > 0, "Must run experiment first."
|
|
211
|
+
assert self._calc_single_shot_fidelities, "Must run the experiment in single-shot by setting calc_single_shot_fidelities to True."
|
|
212
|
+
print(f"Max G: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxFidIndices'][0] ])}Hz")
|
|
213
|
+
print(f"Max E: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxFidIndices'][1] ])}Hz")
|
|
214
|
+
if len(self._states) == 2:
|
|
215
|
+
print(f"Max Mean: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxFidIndices'][2] ])}Hz")
|
|
216
|
+
else:
|
|
217
|
+
print(f"Max F: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxFidIndices'][2] ])}Hz")
|
|
218
|
+
print(f"Max Mean: {Miscellaneous.get_units(self._fit_data['freqs'][ self._fit_data['maxFidIndices'][3] ])}Hz")
|
|
219
|
+
|
|
220
|
+
def plot_blobs(self, frequency):
|
|
221
|
+
assert len(self._fit_data) > 0, "Must run experiment first."
|
|
222
|
+
assert self._calc_single_shot_fidelities, "Must run the experiment in single-shot by setting calc_single_shot_fidelities to True."
|
|
223
|
+
ind = np.argmin(np.abs(frequency-self._fit_data['freqs']))
|
|
224
|
+
ExpZIBlobs.plot_fitted_results(self._fit_data['discriminators'][ind], f"(Frequency: {Miscellaneous.get_units(self._fit_data['freqs'][ind])}Hz)")
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from sqdtoolz.Experiments.Experimental.ExpZIqubit import ExpZIqubit
|
|
2
|
+
from laboneq_applications.experiments import resonator_spectroscopy
|
|
3
|
+
from sqdtoolz.Variable import VariablePropertyTransient
|
|
4
|
+
import numpy as np
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import scipy.interpolate
|
|
7
|
+
import scipy.optimize
|
|
8
|
+
from sqdtoolz.Utilities.DataFitting import DFitPeakLorentzian
|
|
9
|
+
|
|
10
|
+
class ExpZIResPowerSweep(ExpZIqubit):
|
|
11
|
+
def __init__(self, name, expt_config, hal_QPU, qubit_id, frequencies, **kwargs):
|
|
12
|
+
assert isinstance(qubit_id, str), "Supply qubit_id as the solitary string ID here (i.e. not a list)."
|
|
13
|
+
self._qubit_id = qubit_id
|
|
14
|
+
|
|
15
|
+
self._amplitude_range = kwargs.pop('amplitude_range', np.linspace(0.001, 0.9, 20))
|
|
16
|
+
|
|
17
|
+
self._dont_show_plot = kwargs.pop('dont_show_plot', False)
|
|
18
|
+
|
|
19
|
+
self._is_trough = kwargs.pop('is_trough', True)
|
|
20
|
+
self._dont_plot = kwargs.pop('dont_plot', False)
|
|
21
|
+
self._frequencies = frequencies
|
|
22
|
+
self._hal_QPU = hal_QPU
|
|
23
|
+
|
|
24
|
+
kwargs['frequencies'] = frequencies
|
|
25
|
+
super().__init__(name, expt_config, resonator_spectroscopy, hal_QPU, [qubit_id], **kwargs)
|
|
26
|
+
|
|
27
|
+
def _run(self, file_path, sweep_vars=[], **kwargs):
|
|
28
|
+
var_ampl = VariablePropertyTransient('Amplitude', self._hal_QPU.get_qubit_obj(self._qubit_id),'ReadoutAmplitude')
|
|
29
|
+
super()._run(file_path, sweep_vars=[(var_ampl, self._amplitude_range)], **kwargs)
|
|
30
|
+
|
|
31
|
+
def _post_process(self, data):
|
|
32
|
+
leData = self.retrieve_last_dataset(self._qubit_id)
|
|
33
|
+
ampl_vals,freq_vals = leData.param_vals
|
|
34
|
+
arr = leData.get_numpy_array()
|
|
35
|
+
|
|
36
|
+
ampl = np.sqrt(arr[:,:,0]**2 + arr[:,:,1]**2)
|
|
37
|
+
|
|
38
|
+
is_trough = self._is_trough
|
|
39
|
+
|
|
40
|
+
dfit = DFitPeakLorentzian()
|
|
41
|
+
res_freqs = []
|
|
42
|
+
for cur_slice in ampl:
|
|
43
|
+
dpkt = dfit.get_fitted_plot(freq_vals, cur_slice, dip=is_trough, dontplot=True)
|
|
44
|
+
res_freqs.append(dpkt['centre'])
|
|
45
|
+
res_freqs = np.array(res_freqs)
|
|
46
|
+
|
|
47
|
+
fitted_data = {'raw_fit_freqs': res_freqs,}
|
|
48
|
+
|
|
49
|
+
if not self._dont_plot:
|
|
50
|
+
fig, ax = plt.subplots(1); fig.set_figwidth(15)
|
|
51
|
+
ExpZIResPowerSweep.plot_fitted_results(ax, self._hal_QPU, self._qubit_id, freq_vals, ampl_vals, ampl, fitted_data)
|
|
52
|
+
if not self._dont_show_plot:
|
|
53
|
+
fig.show()
|
|
54
|
+
else:
|
|
55
|
+
plt.close(fig)
|
|
56
|
+
fig.savefig(self._file_path + 'fitted_plot.png')
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def plot_fitted_results(ax, hal_QPU, qubit_id, freq_vals, ampl_vals, ampl, fitted_data):
|
|
60
|
+
row_means = np.nanmean(ampl, axis=1)
|
|
61
|
+
ampl_corrected = (ampl.T - row_means).T
|
|
62
|
+
ax.pcolor(freq_vals, ampl_vals, ampl_corrected)
|
|
63
|
+
ax.plot(fitted_data['raw_fit_freqs'], ampl_vals, 'wo')
|
|
64
|
+
ax.set_title(f"{qubit_id} resonator power sweep at {hal_QPU.get_qubit_obj(qubit_id).ReadoutPower} dBm")
|
|
65
|
+
ax.set_xlabel('Frequency (Hz)')
|
|
66
|
+
ax.set_ylabel('Readout amplitude')
|