示例#1
0
    def generate_laser_mw_on(self, name='laser_mw_on', length=3.0e-6):
        """ General generation method for laser on and microwave on generation.

        @param string name: Name of the PulseBlockEnsemble to be generated
        @param float length: Length of the PulseBlockEnsemble in seconds

        @return object: the generated PulseBlockEnsemble object.
        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # create the laser_mw element
        laser_mw_element = self._get_mw_laser_element(
            length=length,
            increment=0,
            amp=self.microwave_amplitude,
            freq=self.microwave_frequency,
            phase=0)
        # Create block and append to created_blocks list
        laser_mw_block = PulseBlock(name=name)
        laser_mw_block.append(laser_mw_element)
        created_blocks.append(laser_mw_block)
        # Create block ensemble and append to created_ensembles list
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        block_ensemble.append((laser_mw_block.name, 0))
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#2
0
    def generate_simple_sin(self, name='simple_sin', length=1000e-9, amp=0.25,
                            freq=5e7, phase=0, num_of_points=50):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # Create the readout PulseBlockEnsemble
        # Get necessary PulseBlockElements

        iq_element = self._get_iq_mix_element(length=length, increment=0, amp=amp, freq=freq, phase=phase)

        # Create PulseBlock and append PulseBlockElements
        signal_block = PulseBlock(name=name)
        signal_block.append(iq_element)
        created_blocks.append(signal_block)
        # Create PulseBlockEnsemble and append block to it
        signal_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        signal_ensemble.append((signal_block.name, 0))

        if self.sync_channel:
            # Create the last readout PulseBlockEnsemble including a sync trigger
            # Get necessary PulseBlockElements
            sync_element = self._get_sync_element()
            # Create PulseBlock and append PulseBlockElements
            sync_block = PulseBlock(name=name)
            sync_block.append(iq_element)
            sync_block.append(sync_element)
            created_blocks.append(sync_block)
            # Create PulseBlockEnsemble and append block to it
            sync_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
            sync_ensemble.append((sync_block.name, 0))
            created_ensembles.append(sync_ensemble)

        # add metadata to invoke settings later on
        signal_ensemble.measurement_information['alternating'] = False
        signal_ensemble.measurement_information['laser_ignore_list'] = list()
        signal_ensemble.measurement_information['units'] = ('s', '')
        signal_ensemble.measurement_information['number_of_lasers'] = num_of_points
        signal_ensemble.measurement_information['counting_length'] = 0

        # Append PulseSequence to created_sequences list
        created_ensembles.append(signal_ensemble)

        return created_blocks, created_ensembles, created_sequences
示例#3
0
    def set_activation_config(self, activation_config):
        """

        @param activation_config:
        @return:
        """
        if isinstance(activation_config, list):
            activation_config = set(activation_config)

        # Do nothing if the activation config has not changed or is wrong data type
        if not isinstance(activation_config,
                          set) or activation_config == self.activation_config:
            return

        self.beginResetModel()

        self.activation_config = activation_config
        self.digital_channels = sorted(
            (chnl for chnl in activation_config if chnl.startswith('d')),
            key=lambda chnl: int(chnl.split('ch')[-1]))
        self.analog_channels = sorted(
            (chnl for chnl in activation_config if chnl.startswith('a')),
            key=lambda chnl: int(chnl.split('ch')[-1]))

        analog_shape = {
            chnl: SamplingFunctions.Idle()
            for chnl in self.analog_channels
        }
        digital_state = {chnl: False for chnl in self.digital_channels}
        self.__default_element = PulseBlockElement(pulse_function=analog_shape,
                                                   digital_high=digital_state)

        # The actual model data container with a single default element
        self._pulse_block = PulseBlock(name='EDITOR CONTAINER',
                                       element_list=[self.__default_element])

        self._col_widths = self._get_column_widths()
        self._create_header_data()

        self.endResetModel()

        self._notify_column_width()
        return
示例#4
0
    def __init__(self):
        super().__init__()

        self.digital_channels = list()
        self.analog_channels = list()
        self.activation_config = set()

        # The actual model data container.
        self._pulse_block = PulseBlock('EDITOR CONTAINER')
        # The default PulseBlockElement
        self.__default_element = PulseBlockElement()

        # Create header strings
        self._create_header_data()

        # The current column widths.
        # The fact that the widths are stored in the model saves a huge amount of computational
        # time when resizing columns due to item changes.
        self._col_widths = self._get_column_widths()
        # Notify the QTableView about a change in column widths
        self._notify_column_width()
        return
示例#5
0
    def generate_idle(self, name='idle', length=3.0e-6):
        """ Generate just a simple idle ensemble.

        @param str name: Name of the PulseBlockEnsemble to be generated
        @param float length: Length of the PulseBlockEnsemble in seconds

        @return object: the generated PulseBlockEnsemble object.
        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # create the laser_mw element
        idle_element = self._get_idle_element(length=length, increment=0)
        # Create block and append to created_blocks list
        idle_block = PulseBlock(name=name)
        idle_block.append(idle_element)
        created_blocks.append(idle_block)
        # Create block ensemble and append to created_ensembles list
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        block_ensemble.append((idle_block.name, 0))
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#6
0
    def generate_laser_on(self, name='laser_on', length=3.0e-6):
        """ Generates Laser on.

        @param str name: Name of the PulseBlockEnsemble
        @param float length: laser duration in seconds

        @return object: the generated PulseBlockEnsemble object.
        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # create the laser element
        laser_element = self._get_laser_element(length=length, increment=0)
        # Create block and append to created_blocks list
        laser_block = PulseBlock(name=name)
        laser_block.append(laser_element)
        created_blocks.append(laser_block)
        # Create block ensemble and append to created_ensembles list
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        block_ensemble.append((laser_block.name, 0))
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#7
0
    def generate_xy8_freq(self,
                          name='xy8_freq',
                          freq_start=0.1e6,
                          freq_step=0.01e6,
                          num_of_points=50,
                          xy8_order=4,
                          alternating=True):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # get frequency array for measurement ticks
        freq_array = freq_start + np.arange(num_of_points) * freq_step
        # get tau array from freq array
        tau_array = 1 / (2 * freq_array)
        # calculate "real" tau array (finite pi-pulse length)
        real_tau_array = tau_array - self.rabi_period / 2
        np.clip(real_tau_array, 0, None, real_tau_array)
        # Convert back to frequency in order to account for clipped values
        freq_array = 1 / (2 * (real_tau_array + self.rabi_period / 2))

        # create the elements
        waiting_element = self._get_idle_element(length=self.wait_time,
                                                 increment=0)
        laser_element = self._get_laser_gate_element(length=self.laser_length,
                                                     increment=0)
        delay_element = self._get_delay_gate_element()
        pihalf_element = self._get_mw_element(length=self.rabi_period / 4,
                                              increment=0,
                                              amp=self.microwave_amplitude,
                                              freq=self.microwave_frequency,
                                              phase=0)
        # Use a 180 deg phase shiftet pulse as 3pihalf pulse if microwave channel is analog
        if self.microwave_channel.startswith('a'):
            pi3half_element = self._get_mw_element(
                length=self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=180)
        else:
            pi3half_element = self._get_mw_element(
                length=3 * self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=0)
        pix_element = self._get_mw_element(length=self.rabi_period / 2,
                                           increment=0,
                                           amp=self.microwave_amplitude,
                                           freq=self.microwave_frequency,
                                           phase=0)
        piy_element = self._get_mw_element(length=self.rabi_period / 2,
                                           increment=0,
                                           amp=self.microwave_amplitude,
                                           freq=self.microwave_frequency,
                                           phase=90)

        # Create block and append to created_blocks list
        xy8_block = PulseBlock(name=name)
        for ii, tau in enumerate(real_tau_array):
            tauhalf_element = self._get_idle_element(length=tau / 2,
                                                     increment=0)
            tau_element = self._get_idle_element(length=tau, increment=0)
            xy8_block.append(pihalf_element)
            xy8_block.append(tauhalf_element)
            for n in range(xy8_order):
                xy8_block.append(pix_element)
                xy8_block.append(tau_element)
                xy8_block.append(piy_element)
                xy8_block.append(tau_element)
                xy8_block.append(pix_element)
                xy8_block.append(tau_element)
                xy8_block.append(piy_element)
                xy8_block.append(tau_element)
                xy8_block.append(piy_element)
                xy8_block.append(tau_element)
                xy8_block.append(pix_element)
                xy8_block.append(tau_element)
                xy8_block.append(piy_element)
                xy8_block.append(tau_element)
                xy8_block.append(pix_element)
                if n != xy8_order - 1:
                    xy8_block.append(tau_element)
            xy8_block.append(tauhalf_element)
            xy8_block.append(pihalf_element)
            xy8_block.append(laser_element)
            xy8_block.append(delay_element)
            xy8_block.append(waiting_element)
            if alternating:
                xy8_block.append(pihalf_element)
                xy8_block.append(tauhalf_element)
                for n in range(xy8_order):
                    xy8_block.append(pix_element)
                    xy8_block.append(tau_element)
                    xy8_block.append(piy_element)
                    xy8_block.append(tau_element)
                    xy8_block.append(pix_element)
                    xy8_block.append(tau_element)
                    xy8_block.append(piy_element)
                    xy8_block.append(tau_element)
                    xy8_block.append(piy_element)
                    xy8_block.append(tau_element)
                    xy8_block.append(pix_element)
                    xy8_block.append(tau_element)
                    xy8_block.append(piy_element)
                    xy8_block.append(tau_element)
                    xy8_block.append(pix_element)
                    if n != xy8_order - 1:
                        xy8_block.append(tau_element)
                xy8_block.append(tauhalf_element)
                xy8_block.append(pi3half_element)
                xy8_block.append(laser_element)
                xy8_block.append(delay_element)
                xy8_block.append(waiting_element)
        created_blocks.append(xy8_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=True)
        block_ensemble.append((xy8_block.name, 0))

        # Create and append sync trigger block if needed
        if self.sync_channel:
            sync_block = PulseBlock(name='sync_trigger')
            sync_block.append(self._get_sync_element())
            created_blocks.append(sync_block)
            block_ensemble.append((sync_block.name, 0))

        # add metadata to invoke settings later on
        number_of_lasers = num_of_points * 2 if alternating else num_of_points
        block_ensemble.measurement_information['alternating'] = alternating
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information[
            'controlled_variable'] = freq_array
        block_ensemble.measurement_information['units'] = ('Hz', '')
        block_ensemble.measurement_information[
            'number_of_lasers'] = number_of_lasers
        block_ensemble.measurement_information[
            'counting_length'] = self._get_ensemble_count_length(
                ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#8
0
    def generate_HHpol(self,
                       name='hh_pol',
                       spinlock_length=20.0e-6,
                       spinlock_amp=0.1,
                       polarization_steps=50):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # get steps array for measurement ticks
        steps_array = np.arange(2 * polarization_steps)

        # create the elements
        waiting_element = self._get_idle_element(length=self.wait_time,
                                                 increment=0)
        laser_element = self._get_laser_gate_element(length=self.laser_length,
                                                     increment=0)
        delay_element = self._get_delay_gate_element()
        pihalf_element = self._get_mw_element(length=self.rabi_period / 4,
                                              increment=0,
                                              amp=self.microwave_amplitude,
                                              freq=self.microwave_frequency,
                                              phase=0)
        # Use a 180 deg phase shiftet pulse as 3pihalf pulse if microwave channel is analog
        if self.microwave_channel.startswith('a'):
            pi3half_element = self._get_mw_element(
                length=self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=180)
        else:
            pi3half_element = self._get_mw_element(
                length=3 * self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=0)
        sl_element = self._get_mw_element(length=spinlock_length,
                                          increment=0,
                                          amp=spinlock_amp,
                                          freq=self.microwave_frequency,
                                          phase=90)

        # Create block for "up"-polarization and append to created_blocks list
        up_block = PulseBlock(name=name + '_up')
        up_block.append(pihalf_element)
        up_block.append(sl_element)
        up_block.append(pihalf_element)
        up_block.append(laser_element)
        up_block.append(delay_element)
        up_block.append(waiting_element)
        created_blocks.append(up_block)

        # Create block for "down"-polarization and append to created_blocks list
        down_block = PulseBlock(name=name + '_down')
        down_block.append(pi3half_element)
        down_block.append(sl_element)
        down_block.append(pi3half_element)
        down_block.append(laser_element)
        down_block.append(delay_element)
        down_block.append(waiting_element)
        created_blocks.append(down_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=True)
        block_ensemble.append((up_block.name, polarization_steps - 1))
        block_ensemble.append((down_block.name, polarization_steps - 1))

        # Create and append sync trigger block if needed
        if self.sync_channel:
            sync_block = PulseBlock(name='sync_trigger')
            sync_block.append(self._get_sync_element())
            created_blocks.append(sync_block)
            block_ensemble.append((sync_block.name, 0))

        # add metadata to invoke settings later on
        block_ensemble.measurement_information['alternating'] = False
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information[
            'controlled_variable'] = steps_array
        block_ensemble.measurement_information['units'] = ('#', '')
        block_ensemble.measurement_information[
            'number_of_lasers'] = 2 * polarization_steps
        block_ensemble.measurement_information[
            'counting_length'] = self._get_ensemble_count_length(
                ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#9
0
    def generate_HHtau(self,
                       name='hh_tau',
                       spinlock_amp=0.1,
                       tau_start=1e-6,
                       tau_step=1e-6,
                       num_of_points=50):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # get tau array for measurement ticks
        tau_array = tau_start + np.arange(num_of_points) * tau_step

        # create the elements
        waiting_element = self._get_idle_element(length=self.wait_time,
                                                 increment=0)
        laser_element = self._get_laser_gate_element(length=self.laser_length,
                                                     increment=0)
        delay_element = self._get_delay_gate_element()
        pihalf_element = self._get_mw_element(length=self.rabi_period / 4,
                                              increment=0,
                                              amp=self.microwave_amplitude,
                                              freq=self.microwave_frequency,
                                              phase=0)
        # Use a 180 deg phase shiftet pulse as 3pihalf pulse if microwave channel is analog
        if self.microwave_channel.startswith('a'):
            pi3half_element = self._get_mw_element(
                length=self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=180)
        else:
            pi3half_element = self._get_mw_element(
                length=3 * self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=0)
        sl_element = self._get_mw_element(length=tau_start,
                                          increment=tau_step,
                                          amp=spinlock_amp,
                                          freq=self.microwave_frequency,
                                          phase=90)

        # Create block and append to created_blocks list
        hhtau_block = PulseBlock(name=name)
        hhtau_block.append(pihalf_element)
        hhtau_block.append(sl_element)
        hhtau_block.append(pihalf_element)
        hhtau_block.append(laser_element)
        hhtau_block.append(delay_element)
        hhtau_block.append(waiting_element)

        hhtau_block.append(pi3half_element)
        hhtau_block.append(sl_element)
        hhtau_block.append(pihalf_element)
        hhtau_block.append(laser_element)
        hhtau_block.append(delay_element)
        hhtau_block.append(waiting_element)
        created_blocks.append(hhtau_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=True)
        block_ensemble.append((hhtau_block.name, num_of_points - 1))

        # Create and append sync trigger block if needed
        if self.sync_channel:
            sync_block = PulseBlock(name='sync_trigger')
            sync_block.append(self._get_sync_element())
            created_blocks.append(sync_block)
            block_ensemble.append((sync_block.name, 0))

        # add metadata to invoke settings later on
        block_ensemble.measurement_information['alternating'] = True
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information[
            'controlled_variable'] = tau_array
        block_ensemble.measurement_information['units'] = ('s', '')
        block_ensemble.measurement_information[
            'number_of_lasers'] = 2 * num_of_points
        block_ensemble.measurement_information[
            'counting_length'] = self._get_ensemble_count_length(
                ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#10
0
    def generate_pulsedodmr(self,
                            name='pulsedODMR',
                            freq_start=2870.0e6,
                            freq_step=0.2e6,
                            num_of_points=50):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # Create frequency array
        freq_array = freq_start + np.arange(num_of_points) * freq_step

        # create the elements
        waiting_element = self._get_idle_element(length=self.wait_time,
                                                 increment=0)
        laser_element = self._get_laser_gate_element(length=self.laser_length,
                                                     increment=0)
        delay_element = self._get_delay_gate_element()

        # Create block and append to created_blocks list
        pulsedodmr_block = PulseBlock(name=name)
        for mw_freq in freq_array:
            mw_element = self._get_mw_element(length=self.rabi_period / 2,
                                              increment=0,
                                              amp=self.microwave_amplitude,
                                              freq=mw_freq,
                                              phase=0)
            pulsedodmr_block.append(mw_element)
            pulsedodmr_block.append(laser_element)
            pulsedodmr_block.append(delay_element)
            pulsedodmr_block.append(waiting_element)
        created_blocks.append(pulsedodmr_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        block_ensemble.append((pulsedodmr_block.name, 0))

        # Create and append sync trigger block if needed
        if self.sync_channel:
            sync_block = PulseBlock(name='sync_trigger')
            sync_block.append(self._get_sync_element())
            created_blocks.append(sync_block)
            block_ensemble.append((sync_block.name, 0))

        # add metadata to invoke settings later on
        block_ensemble.measurement_information['alternating'] = False
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information[
            'controlled_variable'] = freq_array
        block_ensemble.measurement_information['units'] = ('Hz', '')
        block_ensemble.measurement_information[
            'number_of_lasers'] = num_of_points
        block_ensemble.measurement_information[
            'counting_length'] = self._get_ensemble_count_length(
                ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#11
0
    def generate_rabi(self,
                      name='rabi',
                      tau_start=10.0e-9,
                      tau_step=10.0e-9,
                      number_of_taus=50):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # get tau array for measurement ticks
        tau_array = tau_start + np.arange(number_of_taus) * tau_step

        # create the laser_mw element
        mw_element = self._get_mw_element(length=tau_start,
                                          increment=tau_step,
                                          amp=self.microwave_amplitude,
                                          freq=self.microwave_frequency,
                                          phase=0)
        waiting_element = self._get_idle_element(length=self.wait_time,
                                                 increment=0)
        laser_element = self._get_laser_gate_element(length=self.laser_length,
                                                     increment=0)
        delay_element = self._get_delay_gate_element()

        # Create block and append to created_blocks list
        rabi_block = PulseBlock(name=name)
        rabi_block.append(mw_element)
        rabi_block.append(laser_element)
        rabi_block.append(delay_element)
        rabi_block.append(waiting_element)
        created_blocks.append(rabi_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        block_ensemble.append((rabi_block.name, number_of_taus - 1))

        # Create and append sync trigger block if needed
        if self.sync_channel:
            sync_block = PulseBlock(name='sync_trigger')
            sync_block.append(self._get_sync_element())
            created_blocks.append(sync_block)
            block_ensemble.append((sync_block.name, 0))

        # add metadata to invoke settings later on
        block_ensemble.measurement_information['alternating'] = False
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information[
            'controlled_variable'] = tau_array
        block_ensemble.measurement_information['units'] = ('s', '')
        block_ensemble.measurement_information[
            'number_of_lasers'] = number_of_taus
        block_ensemble.measurement_information[
            'counting_length'] = self._get_ensemble_count_length(
                ensemble=block_ensemble, created_blocks=created_blocks)

        # Append ensemble to created_ensembles list
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#12
0
    def generate_pulsedodmr_iq(self, name='pulsedODMR_iq', freq_start=50e6, freq_step=1e6,
                               measure_time=500e-9, num_of_points=10):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # Create frequency array
        freq_array = freq_start + np.arange(num_of_points) * freq_step

        # create the elements
        # TODO delete this
        waiting_element = self._get_idle_element(length=1e-03,
                                                 increment=0)
        start_element = self._get_trigger_element(20e-9, 0, 'd_ch0')
        waiting_element = self._get_idle_element(length=measure_time,
                                                 increment=0)
        end_element = self._get_trigger_element(20e-9, 0, 'd_ch1')

        # Create block and append to created_blocks list
        pulsedodmr_block = PulseBlock(name=name)
        for mw_freq in freq_array:
            mw_element = self._get_iq_mix_element(length=self.rabi_period / 2,
                                                  increment=0,
                                                  amp=self.iq_amplitude,
                                                  freq=mw_freq,
                                                  phase=0)
            pulsedodmr_block.append(mw_element)
            pulsedodmr_block.append(start_element)
            pulsedodmr_block.append(waiting_element)
            pulsedodmr_block.append(end_element)

        created_blocks.append(pulsedodmr_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        block_ensemble.append((pulsedodmr_block.name, 0))

        # Create and append sync trigger block if needed
        if self.sync_channel:
            sync_block = PulseBlock(name='sync_trigger')
            sync_block.append(self._get_sync_element())
            created_blocks.append(sync_block)
            block_ensemble.append((sync_block.name, 0))

        # add metadata to invoke settings later on
        block_ensemble.measurement_information['alternating'] = False
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information['controlled_variable'] = freq_array
        block_ensemble.measurement_information['units'] = ('Hz', '')
        block_ensemble.measurement_information['labels'] = ('Frequency', 'Signal')
        block_ensemble.measurement_information['number_of_lasers'] = num_of_points
        block_ensemble.measurement_information['counting_length'] = self._get_ensemble_count_length(
            ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#13
0
    def generate_trig_click(self, name='trig_click(', num_clicks=3, num_reps=10, wait_time=100e-9):
        """

        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # create the elements
        waiting_element = self._get_idle_element(length=wait_time,
                                                 increment=0)
        start_element = self._get_trigger_element(10e-9, 0, 'd_ch0')
        click_element = self._get_trigger_element(10e-9, 0, 'd_ch1')

        # Create block and append to created_blocks list
        pulsedodmr_block = PulseBlock(name=name)
        trig = 0
        while trig < num_reps:
            pulsedodmr_block.append(start_element)
            pulsedodmr_block.append(waiting_element)
            count = 0
            while count < num_clicks:
                pulsedodmr_block.append(click_element)
                pulsedodmr_block.append(waiting_element)
                count += 1
            trig += 1

        created_blocks.append(pulsedodmr_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=False)
        block_ensemble.append((pulsedodmr_block.name, 0))

        # Create and append sync trigger block if needed
        if self.sync_channel:
            sync_block = PulseBlock(name='sync_trigger')
            sync_block.append(self._get_sync_element())
            created_blocks.append(sync_block)
            block_ensemble.append((sync_block.name, 0))

        # add metadata to invoke settings later on
        block_ensemble.measurement_information['alternating'] = False
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information['controlled_variable'] = np.arange(num_reps)
        block_ensemble.measurement_information['units'] = ('Hz', '')
        block_ensemble.measurement_information['labels'] = ('Frequency', 'Signal')
        block_ensemble.measurement_information['number_of_lasers'] = num_reps
        block_ensemble.measurement_information['counting_length'] = self._get_ensemble_count_length(
            ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#14
0
    def generate_rot_echo_N(self,
                            name='rot_echo_N',
                            amp_hh=0.05,
                            tau=0.5e-6,
                            order_start=4,
                            order_step=1,
                            num_of_points=50,
                            alternating=True):
        """
        Rotary echo - continuous dynamical decoupling with 0/180 phase changes.
        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # get order array
        order_array = order_start + np.arange(num_of_points) * order_step

        # create the elements
        waiting_element = self._get_idle_element(length=self.wait_time,
                                                 increment=0)
        laser_element = self._get_laser_gate_element(length=self.laser_length,
                                                     increment=0)
        delay_element = self._get_delay_gate_element()
        pihalf_element = self._get_mw_element(length=self.rabi_period / 4,
                                              increment=0,
                                              amp=self.microwave_amplitude,
                                              freq=self.microwave_frequency,
                                              phase=0)
        # Use a 180 deg phase shifted pulse as 3pihalf pulse if microwave channel is analog
        if self.microwave_channel.startswith('a'):
            pi3half_element = self._get_mw_element(
                length=self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=180)
        else:
            pi3half_element = self._get_mw_element(
                length=3 * self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=0)
        pix_element = self._get_mw_element(length=tau,
                                           increment=0,
                                           amp=amp_hh,
                                           freq=self.microwave_frequency,
                                           phase=0)
        piy_element = self._get_mw_element(length=tau,
                                           increment=0,
                                           amp=amp_hh,
                                           freq=self.microwave_frequency,
                                           phase=180)
        # Create block and append to created_blocks list
        rot_echo_tau = PulseBlock(name=name)
        for order in order_array:
            rot_echo_tau.append(pihalf_element)
            for n in range(order):
                rot_echo_tau.append(pix_element)
                rot_echo_tau.append(piy_element)
            rot_echo_tau.append(pihalf_element)
            rot_echo_tau.append(laser_element)
            rot_echo_tau.append(delay_element)
            rot_echo_tau.append(waiting_element)
            if alternating:
                rot_echo_tau.append(pihalf_element)
                for n in range(order):
                    rot_echo_tau.append(pix_element)
                    rot_echo_tau.append(piy_element)
                rot_echo_tau.append(pi3half_element)
                rot_echo_tau.append(laser_element)
                rot_echo_tau.append(delay_element)
                rot_echo_tau.append(waiting_element)
        created_blocks.append(rot_echo_tau)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=True)
        block_ensemble.append((rot_echo_tau.name, 0))

        # Create and append sync trigger block if needed
        self._add_trigger(created_blocks=created_blocks,
                          block_ensemble=block_ensemble)

        # add metadata to invoke settings later on
        number_of_lasers = num_of_points * 2 if alternating else num_of_points
        block_ensemble.measurement_information['alternating'] = alternating
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information[
            'controlled_variable'] = order_array
        block_ensemble.measurement_information['units'] = ('', '')
        block_ensemble.measurement_information['labels'] = ('order', 'Signal')
        block_ensemble.measurement_information[
            'number_of_lasers'] = number_of_lasers
        block_ensemble.measurement_information[
            'counting_length'] = self._get_ensemble_count_length(
                ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#15
0
    def generate_HHphase_tau(self,
                             name='HH_Phase',
                             amp_hh=0.5,
                             tau_start=0.5e-6,
                             tau_step=0.01e-6,
                             num_of_points=50,
                             xy8_order=4,
                             alternating=True):
        """
        Continuous dynamical decoupling with XY8 like phase changes.
        """
        created_blocks = list()
        created_ensembles = list()
        created_sequences = list()

        # get tau array for measurement ticks
        tau_array = tau_start + np.arange(num_of_points) * tau_step

        # create the elements
        waiting_element = self._get_idle_element(length=self.wait_time,
                                                 increment=0)
        laser_element = self._get_laser_gate_element(length=self.laser_length,
                                                     increment=0)
        delay_element = self._get_delay_gate_element()
        pihalf_element = self._get_mw_element(length=self.rabi_period / 4,
                                              increment=0,
                                              amp=self.microwave_amplitude,
                                              freq=self.microwave_frequency,
                                              phase=0)
        # Use a 180 deg phase shifted pulse as 3pihalf pulse if microwave channel is analog
        if self.microwave_channel.startswith('a'):
            pi3half_element = self._get_mw_element(
                length=self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=180)
        else:
            pi3half_element = self._get_mw_element(
                length=3 * self.rabi_period / 4,
                increment=0,
                amp=self.microwave_amplitude,
                freq=self.microwave_frequency,
                phase=0)
        pix_element = self._get_mw_element(length=tau_start,
                                           increment=tau_step,
                                           amp=amp_hh,
                                           freq=self.microwave_frequency,
                                           phase=0)
        piy_element = self._get_mw_element(length=tau_start,
                                           increment=tau_step,
                                           amp=amp_hh,
                                           freq=self.microwave_frequency,
                                           phase=90)
        # Create block and append to created_blocks list
        hhphase_block = PulseBlock(name=name)
        hhphase_block.append(pihalf_element)
        for n in range(xy8_order):
            hhphase_block.append(pix_element)
            hhphase_block.append(piy_element)
            hhphase_block.append(pix_element)
            hhphase_block.append(piy_element)
            hhphase_block.append(piy_element)
            hhphase_block.append(pix_element)
            hhphase_block.append(piy_element)
            hhphase_block.append(pix_element)
        hhphase_block.append(pihalf_element)
        hhphase_block.append(laser_element)
        hhphase_block.append(delay_element)
        hhphase_block.append(waiting_element)
        if alternating:
            hhphase_block.append(pihalf_element)
            for n in range(xy8_order):
                hhphase_block.append(pix_element)
                hhphase_block.append(piy_element)
                hhphase_block.append(pix_element)
                hhphase_block.append(piy_element)
                hhphase_block.append(piy_element)
                hhphase_block.append(pix_element)
                hhphase_block.append(piy_element)
                hhphase_block.append(pix_element)
            hhphase_block.append(pi3half_element)
            hhphase_block.append(laser_element)
            hhphase_block.append(delay_element)
            hhphase_block.append(waiting_element)
        created_blocks.append(hhphase_block)

        # Create block ensemble
        block_ensemble = PulseBlockEnsemble(name=name, rotating_frame=True)
        block_ensemble.append((hhphase_block.name, num_of_points - 1))

        # Create and append sync trigger block if needed
        self._add_trigger(created_blocks=created_blocks,
                          block_ensemble=block_ensemble)

        # add metadata to invoke settings later on
        number_of_lasers = num_of_points * 2 if alternating else num_of_points
        block_ensemble.measurement_information['alternating'] = alternating
        block_ensemble.measurement_information['laser_ignore_list'] = list()
        block_ensemble.measurement_information[
            'controlled_variable'] = tau_array
        block_ensemble.measurement_information['units'] = ('s', '')
        block_ensemble.measurement_information['labels'] = ('Frequency',
                                                            'Signal')
        block_ensemble.measurement_information[
            'number_of_lasers'] = number_of_lasers
        block_ensemble.measurement_information[
            'counting_length'] = self._get_ensemble_count_length(
                ensemble=block_ensemble, created_blocks=created_blocks)

        # append ensemble to created ensembles
        created_ensembles.append(block_ensemble)
        return created_blocks, created_ensembles, created_sequences
示例#16
0
class BlockEditorTableModel(QtCore.QAbstractTableModel):
    """

    """
    # signals
    sigColumnWidthChanged = QtCore.Signal(int, int)

    # User defined roles for model data access
    lengthRole = QtCore.Qt.UserRole + 1
    incrementRole = QtCore.Qt.UserRole + 2
    digitalStateRole = QtCore.Qt.UserRole + 3
    analogFunctionRole = QtCore.Qt.UserRole + 4
    analogShapeRole = QtCore.Qt.UserRole + 5
    analogParameterRole = QtCore.Qt.UserRole + 6
    analogChannelSetRole = QtCore.Qt.UserRole + 7
    digitalChannelSetRole = QtCore.Qt.UserRole + 8
    channelSetRole = QtCore.Qt.UserRole + 9
    blockElementRole = QtCore.Qt.UserRole + 10
    pulseBlockRole = QtCore.Qt.UserRole + 11

    def __init__(self):
        super().__init__()

        self.digital_channels = list()
        self.analog_channels = list()
        self.activation_config = set()

        # The actual model data container.
        self._pulse_block = PulseBlock('EDITOR CONTAINER')
        # The default PulseBlockElement
        self.__default_element = PulseBlockElement()

        # Create header strings
        self._create_header_data()

        # The current column widths.
        # The fact that the widths are stored in the model saves a huge amount of computational
        # time when resizing columns due to item changes.
        self._col_widths = self._get_column_widths()
        # Notify the QTableView about a change in column widths
        self._notify_column_width()
        return

    def _create_header_data(self):
        """

        @return:
        """
        # The horizontal header data
        self._h_header_data = ['length\nin s', 'increment\nin s']
        if self.digital_channels:
            self._h_header_data.append('digital\nchannels')
        for chnl in self.analog_channels:
            self._h_header_data.append('{0}\nshape'.format(chnl))
            self._h_header_data.append('{0}\nparameters'.format(chnl))
        return

    def _notify_column_width(self, column=None):
        """

        @param column:
        @return:
        """
        if column is None:
            for column, width in enumerate(self._col_widths):
                self.sigColumnWidthChanged.emit(column, width)
            return

        if isinstance(column, int):
            if 0 <= column < len(self._col_widths):
                self.sigColumnWidthChanged.emit(column, self._col_widths[column])
        return

    def _get_column_widths(self):
        """

        @return:
        """
        widths = list()
        for column in range(self.columnCount()):
            width = self._get_column_width(column)
            if width < 0:
                return -1
            widths.append(width)
        return widths

    def _get_column_width(self, column):
        """

        @return:
        """
        if not isinstance(column, int):
            return -1

        if column < self.columnCount():
            has_digital = bool(len(self.digital_channels))

            if column < 2:
                width = 90
            elif column == 2 and has_digital:
                width = 30 * len(self.digital_channels)
            else:
                a_ch_offset = 2 + int(has_digital)
                if (column - a_ch_offset) % 2 == 0:
                    width = 80
                else:
                    channel = self.analog_channels[(column - a_ch_offset) // 2]
                    max_param_number = 0
                    for element in self._pulse_block:
                        tmp_size = len(element.pulse_function[channel].params)
                        if tmp_size > max_param_number:
                            max_param_number = tmp_size
                    width = 90 * max_param_number

            return width
        else:
            return -1

    def set_activation_config(self, activation_config):
        """

        @param activation_config:
        @return:
        """
        if isinstance(activation_config, list):
            activation_config = set(activation_config)

        # Do nothing if the activation config has not changed or is wrong data type
        if not isinstance(activation_config, set) or activation_config == self.activation_config:
            return

        self.beginResetModel()

        self.activation_config = activation_config
        self.digital_channels = sorted((chnl for chnl in activation_config if chnl.startswith('d')),
                                       key=lambda chnl: int(chnl.split('ch')[-1]))
        self.analog_channels = sorted((chnl for chnl in activation_config if chnl.startswith('a')),
                                      key=lambda chnl: int(chnl.split('ch')[-1]))

        analog_shape = {chnl: SamplingFunctions.Idle() for chnl in self.analog_channels}
        digital_state = {chnl: False for chnl in self.digital_channels}
        self.__default_element = PulseBlockElement(pulse_function=analog_shape,
                                                   digital_high=digital_state)

        # The actual model data container with a single default element
        self._pulse_block = PulseBlock(name='EDITOR CONTAINER',
                                       element_list=[self.__default_element])

        self._col_widths = self._get_column_widths()
        self._create_header_data()

        self.endResetModel()

        self._notify_column_width()
        return

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self._pulse_block)

    def columnCount(self, parent=QtCore.QModelIndex()):
        return 2 + int(len(self.digital_channels) > 0) + 2 * len(self.analog_channels)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            return None

        if role == self.pulseBlockRole:
            self._pulse_block.refresh_parameters()
            return self._pulse_block
        if role == self.analogChannelSetRole:
            return self._pulse_block.analog_channels
        if role == self.digitalChannelSetRole:
            return self._pulse_block.digital_channels
        if role == self.channelSetRole:
            return self._pulse_block.channel_set

        if not index.isValid():
            return None

        if role == self.lengthRole:
            return self._pulse_block[index.row()].init_length_s
        if role == self.incrementRole:
            return self._pulse_block[index.row()].increment_s
        if role == self.digitalStateRole:
            return self._pulse_block[index.row()].digital_high
        if role == self.analogFunctionRole:
            element = self._pulse_block[index.row()]
            if len(self.digital_channels) > 0:
                col_offset = 3
            else:
                col_offset = 2
            analog_chnl = self.analog_channels[(index.column() - col_offset) // 2]
            return element.pulse_function[analog_chnl]
        if role == self.analogShapeRole:
            element = self._pulse_block[index.row()]
            if len(self.digital_channels) > 0:
                col_offset = 3
            else:
                col_offset = 2
            analog_chnl = self.analog_channels[(index.column() - col_offset) // 2]
            return element.pulse_function[analog_chnl].__class__.__name__
        if role == self.analogParameterRole:
            element = self._pulse_block[index.row()]
            if len(self.digital_channels) > 0:
                col_offset = 3
            else:
                col_offset = 2
            analog_chnl = self.analog_channels[(index.column() - col_offset) // 2]
            return vars(element.pulse_function[analog_chnl])
        if role == self.blockElementRole:
            return self._pulse_block[index.row()]

        return None

    def setData(self, index, data, role=QtCore.Qt.DisplayRole):
        """
        """
        if isinstance(data, PulseBlockElement):
            self._pulse_block[index.row()] = copy.deepcopy(data)
            return

        if role == self.lengthRole and isinstance(data, (int, float)):
            old_elem = self._pulse_block[index.row()]
            if data != old_elem.init_length_s:
                new_elem = PulseBlockElement(init_length_s=max(0, data),
                                             increment_s=old_elem.increment_s,
                                             pulse_function=old_elem.pulse_function,
                                             digital_high=old_elem.digital_high)
                self._pulse_block[index.row()] = new_elem
        elif role == self.incrementRole and isinstance(data, (int, float)):
            old_elem = self._pulse_block[index.row()]
            if data != old_elem.increment_s:
                new_elem = PulseBlockElement(init_length_s=old_elem.init_length_s,
                                             increment_s=data,
                                             pulse_function=old_elem.pulse_function,
                                             digital_high=old_elem.digital_high)
                self._pulse_block[index.row()] = new_elem
        elif role == self.digitalStateRole and isinstance(data, dict):
            old_elem = self._pulse_block[index.row()]
            if data != old_elem.digital_high:
                new_elem = PulseBlockElement(init_length_s=old_elem.init_length_s,
                                             increment_s=old_elem.increment_s,
                                             pulse_function=old_elem.pulse_function,
                                             digital_high=data.copy())
                self._pulse_block[index.row()] = new_elem
        elif role == self.analogShapeRole and isinstance(data, str):
            if self.data(index=index, role=self.analogShapeRole) != data:
                old_elem = self._pulse_block[index.row()]

                sampling_func = getattr(SamplingFunctions, data)
                col_offset = 3 if self.digital_channels else 2
                chnl = self.analog_channels[(index.column() - col_offset) // 2]

                pulse_function = old_elem.pulse_function.copy()
                pulse_function[chnl] = sampling_func()

                new_elem = PulseBlockElement(init_length_s=old_elem.init_length_s,
                                             increment_s=old_elem.increment_s,
                                             pulse_function=pulse_function,
                                             digital_high=old_elem.digital_high)
                self._pulse_block[index.row()] = new_elem

                new_column_width = self._get_column_width(index.column()+1)
                if new_column_width >= 0 and new_column_width != self._col_widths[index.column()+1]:
                    self._col_widths[index.column() + 1] = new_column_width
                    self._notify_column_width(index.column()+1)

        elif role == self.analogParameterRole and isinstance(data, dict):
            col_offset = 3 if self.digital_channels else 2
            chnl = self.analog_channels[(index.column() - col_offset) // 2]
            self._pulse_block[index.row()].pulse_function[chnl].__init__(**data)
        elif role == self.pulseBlockRole and isinstance(data, PulseBlock):
            self._pulse_block = copy.deepcopy(data)
            self._pulse_block.name = 'EDITOR CONTAINER'
            self._pulse_block.refresh_parameters()
        return

    def headerData(self, section, orientation, role):
        # Horizontal header
        if orientation == QtCore.Qt.Horizontal:
            # if role == QtCore.Qt.BackgroundRole:
            #     return QVariant(QBrush(QColor(Qt::green), Qt::SolidPattern))
            if role == QtCore.Qt.SizeHintRole:
                if section < len(self._col_widths):
                    return QtCore.QSize(self._col_widths[section], 40)

            if role == QtCore.Qt.DisplayRole:
                if section < len(self._h_header_data):
                    return self._h_header_data[section]

        # Vertical header
        # if orientation == QtCore.Qt.Vertical:
        #     if role == QtCore.Qt.BackgroundRole:
        #         return QtCore.Qt.QVariant(QtGui.Qt.QBrush(QtGui.Qt.QColor(QtCore.Qt.green),
        #                                                   QtCore.Qt.SolidPattern))
        return super().headerData(section, orientation, role)

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled

    def insertRows(self, row, count, parent=None):
        """

        @param row:
        @param count:
        @param parent:
        @return:
        """
        # Sanity/range checking
        if row < 0 or row > self.rowCount():
            return False

        if parent is None:
            parent = QtCore.QModelIndex()

        self.beginInsertRows(parent, row, row + count - 1)

        for i in range(count):
            self._pulse_block.insert(position=row, element=self.__default_element)

        self.endInsertRows()
        return True

    def removeRows(self, row, count, parent=None):

        """

        @param row:
        @param count:
        @param parent:
        @return:
        """
        # Sanity/range checking
        if row < 0 or row >= self.rowCount() or (row + count) > self.rowCount():
            return False

        if parent is None:
            parent = QtCore.QModelIndex()

        self.beginRemoveRows(parent, row, row + count - 1)

        del self._pulse_block[row:row + count]

        self._col_widths = self._get_column_widths()
        self._notify_column_width()

        self.endRemoveRows()
        return True

    def set_pulse_block(self, pulse_block):
        """

        @param pulse_block:
        @return:
        """
        if not isinstance(pulse_block, PulseBlock):
            return False
        elif pulse_block.channel_set != self.activation_config:
            return False
        self.beginResetModel()
        self.setData(QtCore.QModelIndex(), pulse_block, self.pulseBlockRole)
        self._col_widths = self._get_column_widths()
        self._notify_column_width()
        self.endResetModel()
        return True