def test_repeatAndVarySequence_fail_inputlength2(protosequence1): poss = (1, 2) channels = [1, 1] names = ['ramp', 'ramp'] args = ['start', 'stop'] iters = [(1, 0.2, 0.3), (1, 0.2)] with pytest.raises(ValueError): bb.repeatAndVarySequence(protosequence1, poss, channels, names, args, iters)
def test_repeatAndVarySequence_fail_consistency(protosequence1, squarepulse_baseelem): protosequence1.addElement(5, squarepulse_baseelem) print(protosequence1.checkConsistency()) poss = (1,) channels = [1] names = ['ramp'] args = ['start'] iters = [(1, 0.2, 0.3)] with pytest.raises(SequenceConsistencyError): bb.repeatAndVarySequence(protosequence1, poss, channels, names, args, iters)
def test_repeatAndVarySequence_same_elements(protosequence1, pos): poss = (1,) channels = [1] names = ['ramp'] args = ['start'] iters = [(1, 0.2, 0.3)] newseq = bb.repeatAndVarySequence(protosequence1, poss, channels, names, args, iters) assert newseq.element(pos) == protosequence1.element(2)
def test_repeatAndVarySequence_awgspecs(protosequence1): poss = (1,) channels = [1] names = ['ramp'] args = ['stop'] iters = [[1, 0.9, 0.8]] newseq = bb.repeatAndVarySequence(protosequence1, poss, channels, names, args, iters) assert newseq._awgspecs == protosequence1._awgspecs
def test_repeatAndVarySequence_length(protosequence1): poss = [1] channels = [1] names = ['ramp'] args = ['start'] iters = [[1, 1.1, 1.2]] newseq = bb.repeatAndVarySequence(protosequence1, poss, channels, names, args, iters) expected_l = len(iters[0])*protosequence1.length_sequenceelements assert newseq.length_sequenceelements == expected_l
def add_dc_correction(self): offset_time = 0.33 * self.seq_total_time offset_mag = -self.area / offset_time print(offset_mag) variables = ['start', 'stop', 'duration'] poss = [] channels_iters = [] names = [] args = [] # for DC offset pulse for index_ch, ch in enumerate(self.channels): poss.extend([1 for _ in variables]) channels_iters.extend([ch for _ in variables]) names.extend(['offset' + '{}ch'.format(ch) for _ in variables]) args.extend([v for v in variables]) iters = [] for index_ch, ch in enumerate(self.channels): offset = offset_mag[index_ch] start_ch = [offset] stop_ch = [offset] duration_ch = [offset_time] iters.append(start_ch) iters.append(stop_ch) iters.append(duration_ch) newseq = bb.repeatAndVarySequence(self.base_seq, poss, channels_iters, names, args, iters) # plotter(newseq) # plt.show() return newseq
def vary_base_sequence(self, vary_name, detuning_vector, detunings, durations, lever_arms, fast_param='detuning'): '''fast_param = detuning or time''' variables = ['start', 'stop', 'duration'] if len(lever_arms)!= len(self.channels): print('Lever arms must be the same length as channels') poss = [] channels_iters = [] names = [] args = [] if vary_name not in self.vary_name: print('No blueprint with that name') # for varied pulse for index_ch, ch in enumerate(self.channels): poss.extend([1 for _ in variables]) channels_iters.extend([ch for _ in variables]) names.extend([vary_name + '{}ch'.format(ch) for _ in variables]) args.extend([v for v in variables]) # for DC offset pulse for index_ch, ch in enumerate(self.channels): poss.extend([1 for _ in variables]) channels_iters.extend([ch for _ in variables]) names.extend(['offset' + '{}ch'.format(ch) for _ in variables]) args.extend([v for v in variables]) print(names) scaled_detunings = (np.array( [self.sequencer._scale_from_vec(detuning_vector, i).tolist() for i in detunings])*np.array(lever_arms)).T.tolist() offset_time = 0.33 * self.seq_total_time offset_mag = -self.area / offset_time if fast_param == 'detuning': iters = [] # for exchange pulse for index_ch, ch in enumerate(self.channels): start_ch = [] stop_ch = [] duration_ch = [] for t in durations: start_ch.extend(scaled_detunings[index_ch]) stop_ch.extend(scaled_detunings[index_ch]) duration_ch.extend([t] * len(scaled_detunings[index_ch])) iters.append(start_ch) iters.append(stop_ch) iters.append(duration_ch) # for dc offset for index_ch, ch in enumerate(self.channels): start_ch = [] stop_ch = [] duration_ch = [] for t in durations: offset = (offset_mag[index_ch] + (np.array(scaled_detunings[index_ch]) * t / offset_time)).tolist() start_ch.extend(offset) stop_ch.extend(offset) duration_ch.extend([offset_time] * len(scaled_detunings[index_ch])) iters.append(start_ch) iters.append(stop_ch) iters.append(duration_ch) elif fast_param == 'time': iters = [] # for exchange pulse for index_ch, ch in enumerate(self.channels): start_ch = [] stop_ch = [] duration_ch = [] for d in scaled_detunings[index_ch]: start_ch.extend([d] * len(durations)) stop_ch.extend([d] * len(durations)) duration_ch.extend(durations.tolist()) iters.append(start_ch) iters.append(stop_ch) iters.append(duration_ch) # for dc offset for index_ch, ch in enumerate(self.channels): start_ch = [] stop_ch = [] duration_ch = [] for d in scaled_detunings[index_ch]: offset = offset_mag[index_ch] + (d * durations / offset_time) start_ch.extend(offset) stop_ch.extend(offset) duration_ch.extend([offset_time] * len(durations)) iters.append(start_ch) iters.append(stop_ch) iters.append(duration_ch) newseq = bb.repeatAndVarySequence(self.base_seq, poss, channels_iters, names, args, iters) # plotter(newseq) # plt.show() return newseq
def _DPE_makeFullSequence(hightimes, trig_delay, meastime, prewaittime, cycletime, no_of_avgs, no_of_pulses, pulsehigh, SR, segname): """ Generate the full sequence (to be uploaded exactly once). The sequence is a varied sequence with a baseelement consisting of four parts: 1: A wait with zeros allowing the ZI to get ready. This part is short, but repeated waitbits times 2: A short zero part with the marker2 trigger for the ramp 3: The high pulse and a marker1 trigger for the ZI 4: A short zero part with an event jump leading back to part one. This leading back happens no_of_avgs times. Args: hightime (float): The width of the pulse (s)p trig_delay (float): The delay to start measuring after the end of the pulse (s). meastime (float): The time of each measurement (s). prewaittime (float): The time to wait before each ramp (s). cycletime (float): The time of each ramp (s). no_of_pulses (int): The number of pulse per ramp. pulsehigh (float): The amplitude of the pulse (V) SR (int): The AWG sample rate (Sa/s) segname (str): The name of the high pulse segment as used internally by broadbean. """ waitbits = 100 # no. of repetitions of the first part waitbittime = prewaittime / waitbits trig_duration = 5e-6 if waitbittime < 10 / SR: raise ValueError('prewaittime too short.') # The pulsed part bp_pulse = bb.BluePrint() bp_pulse.setSR(SR) bp_pulse.insertSegment(0, ramp, (pulsehigh, pulsehigh), durs=hightimes[0], name=segname) bp_pulse.insertSegment(1, ramp, (0, 0), durs=meastime, name='measure') # dead time for the scope to re-arm its trigger bp_pulse.insertSegment(2, 'waituntil', cycletime) bp_pulse.setSegmentMarker('measure', (trig_delay, 10e-6), 1) # initial wait time to allow ZI trigger to get ready. This BP is repeated bp_wait = bb.BluePrint() bp_wait.setSR(SR) bp_wait.insertSegment(0, 'waituntil', waitbittime) bp_minimalwait = bb.BluePrint() bp_minimalwait.setSR(SR) bp_minimalwait.insertSegment(0, 'waituntil', 10 / SR) # FIXME! bp_ramptrig = bb.BluePrint() # segment to trigger the ramp bp_ramptrig.insertSegment(0, 'waituntil', trig_duration) bp_ramptrig.marker2 = [(0, trig_duration) ] # the signal to trigger a new ramp bp_ramptrig.setSR(SR) bp_return = bb.BluePrint() bp_return.insertSegment(0, 'waituntil', 10 / SR) bp_return.setSR(SR) # The one-element router sequence routerelem = bb.Element() routerelem.addBluePrint(1, bp_minimalwait) routerseq = bb.Sequence() routerseq.addElement(1, routerelem) routerseq.setSequenceSettings(1, 1, 1, 0, 0) # overridden below routerseq.setSR(SR) routerseq.setChannelVoltageRange(1, 2 * pulsehigh, 0) # The base sequence to be repeated and varied resetelem = bb.Element() resetelem.addBluePrint(1, bp_wait) trigrampelem = bb.Element() trigrampelem.addBluePrint(1, bp_ramptrig) mainelem = bb.Element() mainelem.addBluePrint(1, bp_pulse) returnelem = bb.Element() returnelem.addBluePrint(1, bp_return) baseseq = bb.Sequence() baseseq.addElement(1, resetelem) baseseq.setSequenceSettings(1, 0, waitbits, 0, 0) baseseq.addElement(2, trigrampelem) baseseq.setSequenceSettings(2, 0, 1, 0, 0) baseseq.addElement(3, mainelem) baseseq.setSequenceSettings(3, 0, no_of_pulses, 0, 0) baseseq.addElement(4, returnelem) # is an event jump even needed? Can't we just rerun from top? baseseq.setSequenceSettings(4, 0, 0, 1, 0) baseseq.setSR(SR) baseseq.setChannelVoltageRange(1, 2 * pulsehigh, 0) # Now make the variation poss = [3] channels = [1] names = [segname] args = ['duration'] iters = [hightimes] # might as well have a bit of auto-debug... baseseq.checkConsistency(verbose=True) longseq = bb.repeatAndVarySequence(baseseq, poss, channels, names, args, iters) fullseq = routerseq + longseq # Now set all event jumps to point back to the first (routing) element for ii in range(len(hightimes)): fullseq.setSequenceSettings(1 + (ii + 1) * 4, 0, 0, 1, 0) # And set the routing element to route correctly for the first iteration fullseq.setSequenceSettings(1, 1, 1, 0, 2) return fullseq