def append(self, other, time=None): ''' append other segments the the current ones in the container. Args: other (segment_container) : other segment to append ''' if not isinstance(other, segment_container): raise TypeError( "segment_container object expected. Did you supply a single segment?" ) # make sure all object have a full size. my_shape = find_common_dimension(self.shape, other.shape) other.extend_dim(my_shape) self.extend_dim(my_shape) self._setpoints += other._setpoints if time == None: times = self.total_time time = lp.loop_obj(no_setpoints=True) time.add_data(times, list(range(len(times.shape) - 1, -1, -1))) for i in self.channels: segment = getattr(self, i) segment.append(getattr(other, i), time)
def reset_time(self, extend_only=False): ''' Args: extend_only (bool) : will just extend the time in the segment and not reset it if set to true [do not use when composing wavoforms...]. Allings all segments togeter and sets the input time to 0, e.g. , chan1 : waveform until 70 ns chan2 : waveform until 140ns -> totaltime will be 140 ns, when you now as a new pulse (e.g. at time 0, it will actually occur at 140 ns in both blocks) ''' n_channels = len(self.channels) shape = list(self.shape) time_data = np.empty([n_channels] + shape) for i in range(len(self.channels)): time_data[i] = upconvert_dimension( getattr(self, self.channels[i]).total_time, shape) times = np.amax(time_data, axis=0) times, axis = reduce_arr(times) if len(axis) == 0: loop_obj = times else: loop_obj = lp.loop_obj(no_setpoints=True) loop_obj.add_data(times, axis) for i in self.channels: segment = getattr(self, i) segment.reset_time(loop_obj, False)
def reset_time(self, extend_only=False): ''' Args: extend_only (bool) : will just extend the time in the segment and not reset it if set to true [do not use when composing wavoforms...]. Allings all segments togeter and sets the input time to 0, e.g. , chan1 : waveform until 70 ns chan2 : waveform until 140ns -> totaltime will be 140 ns, when you now as a new pulse (e.g. at time 0, it will actually occur at 140 ns in both blocks) ''' n_branches = len(self.branches) n_channels = len(self.branches[0].channels) shape = list(self.shape) time_data = np.empty([n_branches * n_channels] + shape) for ibranch, branch in enumerate(self.branches): for ich, ch in enumerate(branch.channels): time_data[ibranch * n_channels + ich] = upconvert_dimension( branch[ch].total_time, shape) times = np.amax(time_data, axis=0) times, axis = reduce_arr(times) logging.info(f'times {times}') if len(axis) == 0: loop_obj = times else: loop_obj = lp.loop_obj(no_setpoints=True) loop_obj.add_data(times, axis) for branch in self.branches: for ch in branch.channels: branch[ch].reset_time(loop_obj, False)
def generate_state_tomography(segment, *qubits, repeat=1, axis=0): ''' perform a state tomography on the given qubits Args: segment (segment_container) : container of the segments *qubits (single_qubit_gate_spec) : gate spec of the qubits to be targetted axis (int) : axis where this tomography should run on ''' m_operators = generate_measurement_operators(len(qubits)) * repeat setpoint = loop_obj() setpoint.add_data(np.linspace(1, len(m_operators), len(m_operators)), axis=axis, labels='State Tomography projection', units='#') for i in range(len(qubits)): getattr(segment, qubits[i].qubit).update_dim(setpoint) # todo generalize for i in range(setpoint.data.size): gates = m_operators[i].split('_') for j in range(len(qubits)): qubits[j].load_std_gate( getattr(segment, qubits[j].qubit)[i], gates[j])
def to_loop_obj(oiginal, shape, loop_axis, l, u, s): looper = loop_obj() looper.add_data(upsize(oiginal, shape), axis=loop_axis[::-1], labels=l, units=u, setvals=tuple(s)) return looper
def add_sequence(self, sequence): ''' Adds a sequence to this object. Args: sequence (array) : array of segment_container ''' # check input for entry in sequence: if isinstance( entry, pulse_lib.segments.segment_container.segment_container): self.sequence.append(entry) else: raise ValueError( 'The provided element in the sequence seems to be of the wrong data type. {} provided, segment_container expected' .format(type(entry))) # update dimensionality of all sequence objects for seg_container in self.sequence: seg_container.enter_rendering_mode() self._shape = find_common_dimension(seg_container.shape, self._shape) # Set the waveform cache equal to the the sum of the length of all axis of all channels. # The cache will than be big enough for 1D iterations along every axis. This gives best performance total_axis_length = 0 for seg_container in self.sequence: for channel_name in seg_container.channels: shape = getattr(seg_container, channel_name).data.shape total_axis_length += sum(shape) parent_data.set_waveform_cache_size(total_axis_length) self._shape = tuple(self._shape) self._sweep_index = [0] * self.ndim self._HVI_variables = data_container(marker_HVI_variable()) self._HVI_variables = update_dimension(self._HVI_variables, self.shape) # enforce master clock for the current segments (affects the IQ channels (translated into a phase shift) and and the marker channels (time shifts)) t_tot = np.zeros(self.shape) for seg_container in self.sequence: seg_container.extend_dim(self._shape, ref=True) lp_time = loop_obj(no_setpoints=True) lp_time.add_data(t_tot, axis=list(range(self.ndim - 1, -1, -1))) seg_container.add_master_clock(lp_time) self._HVI_variables += seg_container._software_markers.pulse_data_all t_tot += seg_container.total_time self.params = [] for i in range(len(self.labels)): par_name = self.labels[i] set_param = index_param(par_name, self, dim=i) self.params.append(set_param) setattr(self, par_name, set_param)
def add_HVI_marker(self, marker_name, t_off=0): ''' Add a HVI marker that corresponds to the current time of the segment (defined by reset_time). Args: marker_name (str) : name of the marker to add t_off (str) : offset to be given from the marker ''' times = loop_obj(no_setpoints=True) times.add_data(self.data.start_time, axis=list(range(self.data.ndim - 1, -1, -1))) self.add_HVI_variable(marker_name, times + t_off, True)
def get_allXY_specs(repeat): allXY_set = repeat * [['I', 'I'], ['X2', 'X2'], ['Y2', 'Y2'], ['X2', 'Y2'], ['Y2', 'X2'], ['X', 'I'], ['Y', 'I'], ['X', 'Y'], ['X', 'Y'], ['X', 'Y2'], ['Y', 'X2'], ['X2', 'Y'], ['Y2', 'X'], ['X', 'X2'], ['X2', 'X'], ['Y', 'Y2'], ['Y2', 'Y'], ['X2', 'I'], ['Y2', 'I'], ['X', 'X'], ['Y', 'Y']] setpoint = loop_obj() setpoint.add_data(np.linspace(1, len(allXY_set), len(allXY_set)), axis=0, labels='ALL XY gate id', units='#') return allXY_set, setpoint
def append(self, other, time=None): ''' Put the other segment behind this one. Args: other (segment_single) : the segment to be appended time (double/loop_obj) : attach at the given time (if None, append at total_time of the segment) A time reset will be done after the other segment is added. TODO: transfer of units ''' other_loopobj = loop_obj() other_loopobj.add_data(other.data, axis=list(range(other.data.ndim - 1, -1, -1))) self._setpoints += other._setpoints self.__append(other_loopobj, time) return self