예제 #1
0
    def get_metadata(self, name):
        metadata = {}

        self._pre_process()

        # TODO: add custom pulses

        j = 0
        bb_d = {}
        for i in range(len(self._times) - 1):
            start = self._times[i]
            stop = self._times[i + 1]
            v_start = self._amplitudes[i]
            v_stop = self._amplitudes_end[i + 1]
            if stop == np.inf:
                stop = self._end_time
            if stop - start < 1 or (v_start == 0 and v_stop == 0):
                continue
            bb_d[f'p{j}'] = {
                'start': start,
                'stop': stop,
                'v_start': v_start,
                'v_stop': v_stop
            }
            j += 1

        if bb_d:
            metadata[name + '_baseband'] = bb_d

        pulsedata = self.MW_pulse_data
        all_pulse = {}
        for (i, pulse) in enumerate(pulsedata):
            phase_shift = 0
            for ps in self.phase_shifts:
                if ps.time <= pulse.start:
                    phase_shift += ps.phase_shift
            pd = {}
            pd['start'] = pulse.start
            pd['stop'] = pulse.stop
            pd['amplitude'] = pulse.amplitude
            pd['frequency'] = pulse.frequency
            pd['start_phase'] = pulse.start_phase + phase_shift
            envelope = pulse.envelope
            if envelope is None:
                envelope = envelope_generator()
            pd['AM_envelope'] = repr(envelope.AM_envelope_function)
            pd['PM_envelope'] = repr(envelope.PM_envelope_function)
            all_pulse[('p%i' % i)] = pd

        if all_pulse:
            metadata[name + '_pulses'] = all_pulse

        return metadata
예제 #2
0
    def add_chirp(self, t0, t1, f0, f1, amp):
        '''
        Add chirp to the segment.
        Args:
            t0(float) : start time in ns
            t1(float) : stop tiume in ns
            f0(float) : start frequency
            f1 (float) : stop frequency
            amp (float) : amplitude of the pulse.
        '''
        PM = make_chirp(f0, f1, t0, t1)
        MW_data = IQ_data_single(t0 + self.data_tmp.start_time,
                                 t1 + self.data_tmp.start_time, amp, f0, 0,
                                 envelope_generator(None, PM))

        self.data_tmp.add_MW_data(MW_data)
        return self.data_tmp
예제 #3
0
    def add_MW_pulse(self, t0, t1, amp, freq, phase=0, AM=None, PM=None):
        '''
        Make a sine pulse (generic constructor)

        Args:
            t0(float) : start time in ns
            t1(float) : stop tiume in ns
            amp (float) : amplitude of the pulse.
            freq(float) : frequency
            phase (float) : phase of the microwave.
            AM ('str/tuple/function') : function describing an amplitude modulation (see examples in pulse_lib.segments.data_classes.data_IQ)
            PM ('str/tuple/function') : function describing an phase modulation (see examples in pulse_lib.segments.data_classes.data_IQ)
        '''
        MW_data = IQ_data_single(t0 + self.data_tmp.start_time,
                                 t1 + self.data_tmp.start_time, amp, freq,
                                 phase + self.data_tmp.global_phase,
                                 envelope_generator(AM, PM))
        self.data_tmp.add_MW_data(MW_data)
        return self.data_tmp
예제 #4
0
    def render_MW_and_custom(self, sample_rate, ref_channel_states):
        '''
        Render MW pulses and custom data in 'rendered_elements'.
        '''
        elements = []

        self._pre_process()

        # express in Gs/s
        sample_rate = sample_rate * 1e-9

        # render MW pulses.
        # create list with phase shifts per ref_channel
        phase_shifts_channels = {}
        for ps in self.phase_shifts:
            ps_ch = phase_shifts_channels.setdefault(ps.channel_name, [])
            ps_ch.append(ps)

        for IQ_data_single_object in self.MW_pulse_data:
            # start stop time of MW pulse

            start_pulse = IQ_data_single_object.start
            stop_pulse = IQ_data_single_object.stop

            # max amp, freq and phase.
            amp = IQ_data_single_object.amplitude
            freq = IQ_data_single_object.frequency
            phase = IQ_data_single_object.start_phase
            if ref_channel_states and IQ_data_single_object.ref_channel in ref_channel_states.start_phase:
                ref_start_time = ref_channel_states.start_time
                ref_start_phase = ref_channel_states.start_phase[
                    IQ_data_single_object.ref_channel]
                phase_shift = 0
                if IQ_data_single_object.ref_channel in phase_shifts_channels:
                    for ps in phase_shifts_channels[
                            IQ_data_single_object.ref_channel]:
                        if ps.time <= start_pulse:
                            phase_shift += ps.phase_shift
            else:
                ref_start_time = 0
                ref_start_phase = 0
                phase_shift = 0

            # envelope data of the pulse
            if IQ_data_single_object.envelope is None:
                IQ_data_single_object.envelope = envelope_generator()

            amp_envelope = IQ_data_single_object.envelope.get_AM_envelope(
                (stop_pulse - start_pulse), sample_rate)
            phase_envelope = IQ_data_single_object.envelope.get_PM_envelope(
                (stop_pulse - start_pulse), sample_rate)

            #self.baseband_pulse_data[-1,0] convert to point numbers
            n_pt = int((stop_pulse - start_pulse) * sample_rate) if isinstance(
                amp_envelope, float) else len(amp_envelope)
            start_pt = iround(start_pulse * sample_rate)
            stop_pt = start_pt + n_pt

            # add the sin pulse
            total_phase = phase_shift + phase + phase_envelope + ref_start_phase
            t = start_pt + ref_start_time / sample_rate + np.arange(n_pt)
            wvf = amp * amp_envelope * np.sin(2 * np.pi * freq / sample_rate *
                                              1e-9 * t + total_phase)
            elements.append(rendered_element(start_pt, stop_pt, wvf))

        for custom_pulse in self.custom_pulse_data:
            wvf = self._render_custom_pulse(custom_pulse, sample_rate * 1e9)
            start_pt = iround(custom_pulse.start * sample_rate)
            stop_pt = start_pt + len(wvf)
            elements.append(rendered_element(start_pt, stop_pt, wvf))

        return self._merge_elements(elements)
예제 #5
0
    def _render(self, sample_rate, ref_channel_states):
        '''
        make a full rendering of the waveform at a predetermined sample rate.
        '''
        self._pre_process()

        # express in Gs/s
        sample_rate = sample_rate * 1e-9

        t_tot = self.total_time

        # get number of points that need to be rendered
        t_tot_pt = iround(t_tot * sample_rate) + 1

        wvf = np.zeros([int(t_tot_pt)])

        t_pt = iround(self._times * sample_rate)

        for i in range(len(t_pt) - 1):
            pt0 = t_pt[i]
            pt1 = t_pt[i + 1]
            if pt0 != pt1:
                if self._ramps[i] != 0:
                    wvf[pt0:pt1] = np.linspace(self._amplitudes[i],
                                               self._amplitudes_end[i + 1],
                                               pt1 - pt0 + 1)[:-1]
                else:
                    wvf[pt0:pt1] = self._amplitudes[i]

        # render MW pulses.
        # create list with phase shifts per ref_channel
        phase_shifts_channels = {}
        for ps in self.phase_shifts:
            ps_ch = phase_shifts_channels.setdefault(ps.channel_name, [])
            ps_ch.append(ps)

        for IQ_data_single_object in self.MW_pulse_data:
            # start stop time of MW pulse

            start_pulse = IQ_data_single_object.start
            stop_pulse = IQ_data_single_object.stop

            # max amp, freq and phase.
            amp = IQ_data_single_object.amplitude
            freq = IQ_data_single_object.frequency
            phase = IQ_data_single_object.start_phase
            if ref_channel_states and IQ_data_single_object.ref_channel in ref_channel_states.start_phase:
                ref_start_time = ref_channel_states.start_time
                ref_start_phase = ref_channel_states.start_phase[
                    IQ_data_single_object.ref_channel]
                if IQ_data_single_object.ref_channel in phase_shifts_channels:
                    phase_shifts = [
                        ps.phase_shift for ps in phase_shifts_channels[
                            IQ_data_single_object.ref_channel]
                        if ps.time <= start_pulse
                    ]
                    phase_shift = sum(phase_shifts)
                else:
                    phase_shift = 0
            else:
                ref_start_time = 0
                ref_start_phase = 0
                phase_shift = 0

            # envelope data of the pulse
            if IQ_data_single_object.envelope is None:
                IQ_data_single_object.envelope = envelope_generator()

            amp_envelope = IQ_data_single_object.envelope.get_AM_envelope(
                (stop_pulse - start_pulse), sample_rate)
            phase_envelope = np.asarray(
                IQ_data_single_object.envelope.get_PM_envelope(
                    (stop_pulse - start_pulse), sample_rate))

            #self.baseband_pulse_data[-1,0] convert to point numbers
            n_pt = int((stop_pulse - start_pulse) * sample_rate) if isinstance(
                amp_envelope, float) else len(amp_envelope)
            start_pt = iround(start_pulse * sample_rate)
            stop_pt = start_pt + n_pt

            # add the sin pulse
            total_phase = phase_shift + phase + phase_envelope + ref_start_phase
            t = start_pt + ref_start_time / sample_rate + np.arange(n_pt)
            wvf[start_pt:stop_pt] += amp * amp_envelope * np.sin(
                2 * np.pi * freq / sample_rate * 1e-9 * t + total_phase)

        for custom_pulse in self.custom_pulse_data:
            data = self._render_custom_pulse(custom_pulse, sample_rate * 1e9)
            start_pt = iround(custom_pulse.start * sample_rate)
            stop_pt = start_pt + len(data)
            wvf[start_pt:stop_pt] += data

        # remove last value. t_tot_pt = t_tot + 1. Last value is always 0. It is only needed in the loop on the pulses.
        return wvf[:-1]
예제 #6
0
    frequency : float = 0
    start_phase : float = 0
    envelope : envelope_generator = None
    ref_channel : str = None


if __name__ == '__main__':

    """
    Example on how the envelope generator works.
    """
    import matplotlib.pyplot as plt

    # empty envelope
    from pulse_lib.segments.data_classes.data_IQ import envelope_generator
    env = envelope_generator('blackman')
    env.get_AM_envelope(50)

    # example generation of envelopes with different timings.
    env = envelope_generator('blackman')

    data_1 = env.get_AM_envelope(50)
    data_2 = env.get_AM_envelope(50.2)
    data_3 = env.get_AM_envelope(50.4)
    data_4 = env.get_AM_envelope(50.6)

    # plt.figure("general windowing function")
    # plt.plot(data_1, label = "50.0 ns pulse")
    # plt.plot(data_2, label = "50.2 ns pulse")
    # plt.plot(data_3, label = "50.4 ns pulse")
    # plt.plot(data_4, label = "50.6 ns pulse")