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
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
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 __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 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
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
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
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
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
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
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
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
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
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
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
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