def test_end_to_end(self, freq_shift):
        """Test the experiment end to end."""
        exp_helper = FineFreqHelper(sx_duration=self.sx_duration, freq_shift=freq_shift)
        backend = MockIQBackend(exp_helper)
        exp_helper.dt = backend.configuration().dt

        freq_exp = FineFrequency(0, 160, backend)
        freq_exp.set_transpile_options(inst_map=self.inst_map)

        expdata = freq_exp.run(shots=100)
        self.assertExperimentDone(expdata)
        result = expdata.analysis_results(1)
        d_theta = result.value.n
        dt = backend.configuration().dt
        d_freq = d_theta / (2 * np.pi * self.sx_duration * dt)

        tol = 0.01e6

        self.assertAlmostEqual(d_freq, freq_shift, delta=tol)
        self.assertEqual(result.quality, "good")
    def test_calibration_version(self):
        """Test the calibration version of the experiment."""

        exp_helper = FineFreqHelper(sx_duration=self.sx_duration, freq_shift=0.1e6)
        backend = MockIQBackend(exp_helper)
        exp_helper.dt = backend.configuration().dt

        fine_freq = FineFrequencyCal(0, self.cals, backend)
        armonk_freq = FakeArmonk().defaults().qubit_freq_est[0]

        freq_before = self.cals.get_parameter_value(self.cals.__drive_freq_parameter__, 0)

        self.assertAlmostEqual(freq_before, armonk_freq)

        expdata = fine_freq.run()
        self.assertExperimentDone(expdata)

        freq_after = self.cals.get_parameter_value(self.cals.__drive_freq_parameter__, 0)

        # Test equality up to 10kHz on a 100 kHz shift
        self.assertAlmostEqual(freq_after, armonk_freq + exp_helper.freq_shift, delta=1e4)
Exemple #3
0
class TestFineAmplitudeCal(QiskitExperimentsTestCase):
    """A class to test the fine amplitude calibration experiments."""

    def setUp(self):
        """Setup the tests"""
        super().setUp()

        library = FixedFrequencyTransmon()

        self.backend = MockIQBackend(FineAmpHelper(-np.pi * 0.07, np.pi, "xp"))
        self.backend.configuration().basis_gates.append("sx")
        self.backend.configuration().basis_gates.append("x")
        self.cals = Calibrations.from_backend(self.backend, libraries=[library])

    def test_cal_options(self):
        """Test that the options are properly propagated."""

        # Test the X gate cal
        amp_cal = FineXAmplitudeCal(0, self.cals, "x")

        exp_opt = amp_cal.experiment_options

        self.assertEqual(exp_opt.gate.name, "x")
        self.assertTrue(exp_opt.add_cal_circuits)
        self.assertEqual(exp_opt.result_index, -1)
        self.assertEqual(exp_opt.group, "default")
        self.assertTrue(np.allclose(exp_opt.target_angle, np.pi))

        # Test the SX gate cal
        amp_cal = FineSXAmplitudeCal(0, self.cals, "sx")

        exp_opt = amp_cal.experiment_options

        self.assertEqual(exp_opt.gate.name, "sx")
        self.assertFalse(exp_opt.add_cal_circuits)
        self.assertEqual(exp_opt.result_index, -1)
        self.assertEqual(exp_opt.group, "default")
        self.assertTrue(np.allclose(exp_opt.target_angle, np.pi / 2))

    def test_run_x_cal(self):
        """Test that we can transpile in the calibrations before and after update.

        If this test passes then we were successful in running a calibration experiment,
        updating a pulse parameter, having this parameter propagated to the schedules
        for use the next time the experiment is run.
        """

        # Initial pulse amplitude
        init_amp = 0.5

        amp_cal = FineXAmplitudeCal(0, self.cals, "x")

        circs = transpile(amp_cal.circuits(), self.backend, inst_map=self.cals.default_inst_map)

        with pulse.build(name="x") as expected_x:
            pulse.play(pulse.Drag(160, 0.5, 40, 0), pulse.DriveChannel(0))

        with pulse.build(name="sx") as expected_sx:
            pulse.play(pulse.Drag(160, 0.25, 40, 0), pulse.DriveChannel(0))

        self.assertEqual(circs[5].calibrations["x"][((0,), ())], expected_x)
        self.assertEqual(circs[5].calibrations["sx"][((0,), ())], expected_sx)

        # run the calibration experiment. This should update the amp parameter of x which we test.
        exp_data = amp_cal.run(self.backend)
        self.assertExperimentDone(exp_data)
        d_theta = exp_data.analysis_results(1).value.n
        new_amp = init_amp * np.pi / (np.pi + d_theta)

        circs = transpile(amp_cal.circuits(), self.backend, inst_map=self.cals.default_inst_map)

        x_cal = circs[5].calibrations["x"][((0,), ())]

        # Requires allclose due to numerical precision.
        self.assertTrue(np.allclose(x_cal.blocks[0].pulse.amp, new_amp))
        self.assertFalse(np.allclose(x_cal.blocks[0].pulse.amp, init_amp))
        self.assertEqual(circs[5].calibrations["sx"][((0,), ())], expected_sx)

    def test_run_sx_cal(self):
        """Test that we can transpile in the calibrations before and after update.

        If this test passes then we were successful in running a calibration experiment,
        updating a pulse parameter, having this parameter propagated to the schedules
        for use the next time the experiment is run.
        """

        # Initial pulse amplitude
        init_amp = 0.25

        amp_cal = FineSXAmplitudeCal(0, self.cals, "sx")

        circs = transpile(amp_cal.circuits(), self.backend, inst_map=self.cals.default_inst_map)

        with pulse.build(name="sx") as expected_sx:
            pulse.play(pulse.Drag(160, 0.25, 40, 0), pulse.DriveChannel(0))

        self.assertEqual(circs[5].calibrations["sx"][((0,), ())], expected_sx)

        # run the calibration experiment. This should update the amp parameter of x which we test.
        exp_data = amp_cal.run(MockIQBackend(FineAmpHelper(-np.pi * 0.07, np.pi / 2, "sx")))
        self.assertExperimentDone(exp_data)
        d_theta = exp_data.analysis_results(1).value.n
        new_amp = init_amp * (np.pi / 2) / (np.pi / 2 + d_theta)

        circs = transpile(amp_cal.circuits(), self.backend, inst_map=self.cals.default_inst_map)

        sx_cal = circs[5].calibrations["sx"][((0,), ())]

        # Requires allclose due to numerical precision.
        self.assertTrue(np.allclose(sx_cal.blocks[0].pulse.amp, new_amp))
        self.assertFalse(np.allclose(sx_cal.blocks[0].pulse.amp, init_amp))

    def test_experiment_config(self):
        """Test converting to and from config works"""
        exp = FineSXAmplitudeCal(0, self.cals, "sx")
        loaded_exp = FineSXAmplitudeCal.from_config(exp.config())
        self.assertNotEqual(exp, loaded_exp)
        self.assertTrue(self.json_equiv(exp, loaded_exp))

    def test_roundtrip_serializable(self):
        """Test round trip JSON serialization"""
        exp = FineSXAmplitudeCal(0, self.cals, "sx")
        self.assertRoundTripSerializable(exp, self.json_equiv)