def test_add_subsequence_raises(protosequence1, squarepulse_baseelem): # raise if a non-Sequence object is added with pytest.raises(ValueError): protosequence1.addSubSequence(1, squarepulse_baseelem) seq = bb.Sequence() seq.addElement(1, squarepulse_baseelem) seq.setSR(squarepulse_baseelem.SR) mainseq = bb.Sequence() mainseq.setSR(seq.SR / 2) # raise if the subsequence sample rate does not match the main seq. SR with pytest.raises(ValueError): mainseq.addSubSequence(1, seq) mainseq.setSR(seq.SR) mainseq.addSubSequence(1, seq) doublemainseq = bb.Sequence() doublemainseq.setSR(seq.SR) with pytest.raises(ValueError): doublemainseq.addSubSequence(1, mainseq)
def sequence(self): seq = bb.Sequence() seq.name = 'SSB' net_time = self.seq_len() - self.pre_delay() - self.post_delay() for i, f in enumerate(self.ssb_frequency()): elem = bb.Element() bps = BluePrints(self.chan_map, sample_rate=self.sample_rate()) bps['src_I'].insertSegment(0, ramp, (0, 0), dur=self.pre_delay()) bps['src_I'].insertSegment(1, sine, (f, self.ssb_amp(), 0, 0), dur=net_time) bps['src_I'].insertSegment(2, ramp, (0, 0), dur=self.post_delay()) bps['src_Q'].insertSegment(0, ramp, (0, 0), dur=self.pre_delay()) bps['src_Q'].insertSegment(1, sine, (f, self.ssb_amp(), 0, -np.pi / 2), dur=net_time) bps['src_Q'].insertSegment(2, ramp, (0, 0), dur=self.post_delay()) bps['ro_trigger'] = [(self.pre_delay(), self.trigger_len())] bps['ro_gate'] = [(self.pre_delay(), net_time)] bps['src_gate'] = [(self.pre_delay(), net_time)] for n, bp in bps(): elem.addBluePrint(n, bp) seq.addElement(i + 1, elem) return seq
def test_addition_data_with_empty(protosequence1): newseq = bb.Sequence() newseq._awgspecs = protosequence1._awgspecs newseq = newseq + protosequence1 assert newseq._data == protosequence1._data
def buildSequenceWrap(self, chbox, offbox, contseqbox, timevoltbox, whichpulse, sparambox, seqstart, seqstop, seqpts): """ Build gseq from gelem """ self.gseq= bb.Sequence() timevolt=str(timevoltbox.currentText()) whichp=str(whichpulse.text()) sparam=str(sparambox.currentText()) sstart=float(seqstart.text()) sstop=float(seqstop.text()) spts=int(seqpts.text()) if timevolt=="Time": newparam="N-"+timevolt+"-0-"+whichp else: newparam="N-"+"Volt"+"-"+timevolt[2]+"-"+whichp self.gseq.setSR(self.gelem.SR) if contseqbox.isChecked(): self.gseq.addElement(1, self.gelem) self.gseq.setSequencingTriggerWait(1, 0) self.gseq.setSequencingNumberOfRepetitions(1, 0) self.gseq.setSequencingEventJumpTarget(1, 0) self.gseq.setSequencingGoto(1, 0) # for chan in self.gseq.channels: # self.gseq.setChannelAmplitude(chan, (float(chbox[chan-1].text()))) # self.gseq.setChannelOffset(chan, (float(offbox[chan-1].text()))) #return elif sparam!="-Special-": self.buildsequencetable(self.gelem, sparam, sstart, sstop, spts) else: self.buildsequencetable(self.gelem, newparam, sstart, sstop, spts) for chan in self.gseq.channels: self.gseq.setChannelAmplitude(chan,(float(chbox[chan-1].text()))) self.gseq.setChannelOffset(chan,(float(offbox[chan-1].text())))
def elements2sequence(element_lst, name='sequence', wait='first'): """ Create a sequence from a list of elements. Sequence will just be 1 element per list item, in that order. Parameters: ----------- element_lst : list of bb elements name : str (default: 'sequence') wait : str (default: 'first') if 'first', then we set the trigger wait to True for the first element. all other values are ignored at the Moment. Returns: -------- the generated bb sequence. """ seq = bb.Sequence() seq.name = name for i, e in enumerate(element_lst): seq.addElement(i + 1, e) seq.setSequencingTriggerWait(i + 1, int(wait == 'each')) seq.setSequencingNumberOfRepetitions(i + 1, 1) if wait == 'first': seq.setSequencingTriggerWait(1, 1) seq.setSequencingGoto(i + 1, 1) return seq
def build_seq_from_elem(self, elems, name): seq = bb.Sequence() for index, elem in enumerate(elems): seq.addElement(index+1, elem) seq.setSR(self.sample_rate) seq.checkConsistency() self.seq_dict[name] = seq return seq
def write_element(self, path: str, SR: float = 1e9, SeqAmp: float = 10e-3, SeqOffset: float = 0) -> None: if self.gelem.SR == None: self.gelem.setSR(SR) seqtmp = bb.Sequence() seqtmp.addElement(1, self.gelem) for ch in self.gelem.channels: seqtmp.setChannelAmplitude(ch, SeqAmp) seqtmp.setChannelOffset(ch, 0) seqtmp.setSR(self.gelem.SR) seqtmp.write_to_json(path)
def master_sequence(subseq1, subseq2, bp_element, noise_element): """ A sequence with subsequences and elements, some elements have ararys, some have blueprint. We try to aim wide. """ seq = bb.Sequence() seq.setSR(SR1) seq.addElement(1, noise_element) seq.addSubSequence(2, subseq1) seq.addElement(3, bp_element) seq.addSubSequence(4, subseq2) return seq
def protosequence1(): SR = 1e9 th = bb.BluePrint() th.insertSegment(0, ramp, args=(0, 0), name='ramp', dur=10e-6) th.insertSegment(1, ramp, args=(1, 1), name='ramp', dur=5e-6) th.insertSegment(2, ramp, args=(0, 0), name='ramp', dur=10e-6) th.setSR(SR) wiggle1 = bb.BluePrint() wiggle1.insertSegment(0, sine, args=(4e6, 0.5, 0, 0), dur=25e-6) wiggle1.setSR(SR) wiggle2 = bb.BluePrint() wiggle2.insertSegment(0, sine, args=(8e6, 0.5, 0, 0), dur=25e-6) wiggle2.setSR(SR) elem1 = bb.Element() elem1.addBluePrint(1, th) elem1.addBluePrint(2, wiggle1) elem2 = bb.Element() elem2.addBluePrint(1, th) elem2.addBluePrint(2, wiggle2) seq = bb.Sequence() seq.addElement(1, elem1) seq.addElement(2, elem2) seq.setSR(SR) seq.name = 'protoSequence' seq.setChannelAmplitude(1, 2) seq.setChannelAmplitude(2, 2) seq.setChannelOffset(1, 0) seq.setChannelOffset(2, 0) seq.setSequencingTriggerWait(1, 1) seq.setSequencingTriggerWait(2, 1) seq.setSequencingEventJumpTarget(1, 1) seq.setSequencingEventJumpTarget(2, 1) seq.setSequencingGoto(1, 1) seq.setSequencingGoto(2, 1) return seq
def subseq1(): """ A small sequence meant to be used as a subsequence """ longdur = 201e-9 wait = bb.BluePrint() wait.insertSegment(0, ramp, args=(0, 0), dur=10e-9) wait.setSR(SR1) wiggle = bb.BluePrint() wiggle.insertSegment(0, sine, args=(10e6, 10e-3, 0, 0), dur=longdur) wiggle.setSR(SR1) blob = bb.BluePrint() blob.insertSegment(0, gauss, args=(25e-3, 12e-9, 0, 0), dur=longdur) blob.setSR(SR1) slope = bb.BluePrint() slope.insertSegment(0, ramp, (0, 15e-3), dur=longdur) slope.setSR(SR1) elem1 = bb.Element() elem1.addBluePrint(1, wait) elem1.addBluePrint(2, wait) elem1.addBluePrint(3, wait) elem2 = bb.Element() elem2.addBluePrint(1, wiggle) elem2.addBluePrint(2, slope) elem2.addBluePrint(3, blob) elem3 = elem1.copy() seq = bb.Sequence() seq.setSR(SR1) seq.addElement(1, elem1) seq.addElement(2, elem2) seq.addElement(3, elem3) seq.setSequencingNumberOfRepetitions(1, 10) seq.setSequencingNumberOfRepetitions(3, 10) return seq
def protosequence2(): SR = 1e9 saw = bb.BluePrint() saw.insertSegment(0, ramp, args=(0, 100e-3), dur=11e-6) saw.insertSegment(1, 'waituntil', args=(25e-6)) saw.setSR(SR) lineandwiggle = bb.BluePrint() lineandwiggle.insertSegment(0, 'waituntil', args=(11e-6)) lineandwiggle.insertSegment(1, sine, args=(10e6, 50e-6, 10e-6), dur=14e-6) lineandwiggle.setSR(SR) elem1 = bb.Element() elem1.addBluePrint(1, saw) elem1.addBluePrint(2, lineandwiggle) elem2 = bb.Element() elem2.addBluePrint(2, saw) elem2.addBluePrint(1, lineandwiggle) seq = bb.Sequence() seq.setSR(SR) seq.addElement(1, elem1) seq.addElement(2, elem2) seq.setChannelAmplitude(1, 1.5) seq.setChannelOffset(1, 0) seq.setChannelAmplitude(2, 1) seq.setChannelOffset(2, 0) seq.setSequencingTriggerWait(1, 0) seq.setSequencingTriggerWait(2, 1) seq.setSequencingNumberOfRepetitions(1, 2) seq.setSequencingEventJumpTarget(1, 0) seq.setSequencingEventJumpTarget(2, 0) seq.setSequencingGoto(1, 2) seq.setSequencingGoto(2, 1) return seq
def sequence(self): elem = bb.Element() bps = BluePrints(self.chan_map, sample_rate=self.sample_rate(), length=self.seq_len()) bps['ro_trigger'] = [(self.pre_trigger_delay(), self.trigger_len())] try: bps['ro_gate'] = [ (self.pre_trigger_delay() + self.post_trigger_delay(), self.readout_gate_len()) ] except KeyError: logger.warning( 'No ro_gate defined in channel map. No readout gate pulse will be generated.' ) try: bps['src_gate'] = [ (self.pre_trigger_delay() + self.post_trigger_delay(), self.readout_gate_len()) ] except KeyError: logger.warning( 'No src_gate defined in channel map. No src gate pulse will be generated.' ) for n, bp in bps(): elem.addBluePrint(n, bp) seq = bb.Sequence() seq.name = 'trig' seq.addElement(1, elem) seq.setSequencingTriggerWait(1, 0) seq.setSequencingGoto(1, 1) return seq
def badseq_missing_pos(): SR = 1e9 saw = bb.BluePrint() saw.insertSegment(0, ramp, args=(0, 100e-3), dur=11e-6) saw.insertSegment(1, 'waituntil', args=(25e-6)) saw.setSR(SR) lineandwiggle = bb.BluePrint() lineandwiggle.insertSegment(0, 'waituntil', args=(11e-6)) lineandwiggle.insertSegment(1, sine, args=(10e6, 50e-6, 10e-6), dur=14e-6) lineandwiggle.setSR(SR) elem1 = bb.Element() elem1.addBluePrint(1, saw) elem1.addBluePrint(2, lineandwiggle) elem2 = bb.Element() elem2.addBluePrint(2, saw) elem2.addBluePrint(1, lineandwiggle) seq = bb.Sequence() seq.setSR(SR) seq.addElement(1, elem1) seq.addElement(3, elem2) # <--- A gap in the sequence seq.setChannelAmplitude(1, 1.5) seq.setChannelOffset(1, 0) seq.setChannelAmplitude(2, 1) seq.setChannelOffset(2, 0) seq.setSequencingTriggerWait(3, 1) seq.setSequencingNumberOfRepetitions(1, 2) seq.setSequencingGoto(1, 2) seq.setSequencingGoto(3, 1) # seq.setSequenceSettings(1, 0, 2, 0, 2) # seq.setSequenceSettings(2, 1, 1, 0, 1) return seq
def _DPE_makeSequence(hightime, trig_delay, meastime, prewaittime, cycletime, no_of_pulses, pulsehigh, SR, segname): """ Generate the pulse sequence for the experiment. The sequence consists of three 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 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 bp1 = bb.BluePrint() bp1.setSR(SR) bp1.insertSegment(0, ramp, (pulsehigh, pulsehigh), durs=hightime, name=segname) bp1.insertSegment(1, ramp, (0, 0), durs=meastime, name='measure') # dead time for the scope to re-arm its trigger bp1.insertSegment(2, 'waituntil', cycletime) bp1.marker1 = [(hightime + trig_delay, 10e-6)] # initial wait time to allow ZI trigger to get ready. This BP is repeated bp3 = bb.BluePrint() bp3.setSR(SR) bp3.insertSegment(0, 'waituntil', waitbittime) bp4 = bb.BluePrint() # segment to trigger the ramp bp4.insertSegment(0, 'waituntil', trig_duration) bp4.marker2 = [(0, trig_duration)] # the signal to trigger a new ramp bp4.setSR(SR) mainelem = bb.Element() mainelem.addBluePrint(1, bp1) trigelem = bb.Element() trigelem.addBluePrint(1, bp4) resetelem = bb.Element() resetelem.addBluePrint(1, bp3) seq = bb.Sequence() seq.addElement(1, resetelem) seq.addElement(2, trigelem) seq.addElement(3, mainelem) seq.setSR(SR) seq.setChannelVoltageRange(1, 2 * pulsehigh, 0) seq.setSequenceSettings(1, 0, waitbits, 0, 2) seq.setSequenceSettings(2, 0, 1, 0, 3) # the last zero disables jumping, i.e. seq. plays once seq.setSequenceSettings(3, 0, no_of_pulses, 0, 0) return seq
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
import pathlib from PyQt5.QtCore import QCoreApplication, Qt from PyQt5.QtWidgets import QFileDialog from PyQt5.QtWidgets import QApplication, QWidget, QFrame, QMainWindow, QPushButton, QAction, QMessageBox, QLineEdit, QLabel, QSizePolicy from PyQt5.QtWidgets import QCheckBox, QDialog, QTableWidget, QTableWidgetItem, QVBoxLayout, QHBoxLayout, QComboBox, QGridLayout from broadbean.plotting import plotter from pulsequantum.dftable import QTableWidgetDF from pulsequantum.annotateshape import annotateshape from pulsequantum.elem_from_plot import elem_on_plot from pulsequantum.elem_from_plot import elem_from_lists nchans = 2 ramp = bb.PulseAtoms.ramp # Globally defined ramp, element, and sequence gelem = bb.Element() gseq = bb.Sequence() class Gelem(): def __init__(self, AWG=None, gelem=None, libpath='pulselib/'): self.gelem = bb.Element() self.table = QTableWidgetDF() self.awgclock = 1.2e9 self.libpath = join(pathlib.Path(__file__).parents[0], libpath) self.seq_files = [ f for f in listdir(self.libpath) if isfile(join(self.libpath, f)) ] self.corrDflag = 0 self.w = None self.ch_x = None self.ch_y = None
def __init__(self, **kwargs): super().__init__(**kwargs) self.seq = bb.Sequence()
elem1.addBluePrint(1, bp1) # bp2 = bb.BluePrint() bp2.insertSegment(0, ramp, (1, 1), dur=t2, name='perturbation') bp2.setSR(SR) elem2 = bb.Element() elem2.addBluePrint(1, bp2) # bp3 = bb.BluePrint() bp3.insertSegment(0, ramp, (0, 0), dur=t3 / compression, name='marker') bp3.setSegmentMarker('marker', (0.0, 1e-6), 1) bp3.setSR(SR) elem3 = bb.Element() elem3.addBluePrint(1, bp3) seq = bb.Sequence() seq.addElement(1, elem1) seq.setSequencingNumberOfRepetitions(1, compression) seq.addElement(2, elem2) seq.addElement(3, elem3) seq.setSequencingNumberOfRepetitions(3, compression) seq.setSR(SR) # Now make the variation seq2 = seq.copy() seq2.element(2).changeArg(1, 'perturbation', 'start', 0.75) seq2.element(2).changeArg(1, 'perturbation', 'stop', 0.75) # seq3 = seq.copy() seq3.element(2).changeArg(1, 'perturbation', 'start', 0.5) seq3.element(2).changeArg(1, 'perturbation', 'stop', 0.5)
def makeT2Sequence(hightimes, trig_delay, RF_delay, meastime, cycletime, pulsehigh, pulselow, no_of_avgs, SR): """ Generate the pulse sequence for the experiment. The sequence consists of three 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 Args: hightimes (iterables): The widths of the pulse (s) trig_delay (float): The delay to start measuring after the end of the pulse (s). meastime (float): The time of each measurement (s). cycletime (float): The time of each pulse-measure cycle (s). pulsehigh (float): The amplitude of the pulse (V) pulselow (float): The amplitude during the measurement (V) no_of_avgs (int): The number of averages SR (int): The AWG sample rate (Sa/s) """ segname = 'high' # Fail if the sequence would end up being too long for the AWG to handle if len(hightimes) * cycletime * SR >= 16e6: raise ValueError("Sequence too long. You are trying to build a " "sequence with {:d} MSamples. The maximally allowed " "number of samples is " "16 MSamples.".format( int(len(hightimes) * cycletime * SR / 1e6))) ################################################################## # The pulsed part bp1 = bb.BluePrint() bp1.setSR(SR) bp1.insertSegment(0, ramp, (pulsehigh, pulsehigh), durs=hightimes[0], name=segname) bp1.insertSegment(1, ramp, (pulselow, pulselow), durs=meastime, name='measure') # dead time for the scope to re-arm its trigger bp1.insertSegment(2, 'waituntil', cycletime) bp1.setSegmentMarker(segname, (RF_delay, meastime), 1) # segment name, (delay, duration), markerID bp1.setSegmentMarker(segname, (trig_delay, meastime), 2) pulseelem = bb.Element() pulseelem.addBluePrint(1, bp1) seq = bb.Sequence() seq.setSR(SR) for index, ht in enumerate(hightimes): elem = pulseelem.copy() elem.changeDuration(1, segname, ht) seq.addElement(index + 1, elem) seq.setSequenceSettings(index + 1, 0, no_of_avgs, 0, 0) return seq
def empty_sequence(self): SR = self.seq.SR self.seq = bb.Sequence() self.seq.setSR(SR)
def __init__(self, AWG, gelem): super().__init__() self.AWG = AWG self.gelem = gelem self.gseq = bb.Sequence()
def makeSimpleSequence(hightime, trig_delay, meastime, cycletime, pulsehigh, pulselow, no_of_avgs, SR, compensation_ratio=0): """ Generate the pulse sequence for the experiment. The sequence consists of three 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 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). cycletime (float): The time of each pulse-measure cycle (s). pulsehigh (float): The amplitude of the pulse (V) pulselow (float): The amplitude during the measurement (V) no_of_avgs (int): The number of averages SR (int): The AWG sample rate (Sa/s) compensation_ratio (float): The time of the compensation pre-pulse (to ensure zero integral of the pulse) expressed as the ratio of the prepulse duration to the hightime+meastime. If zero, then no compensation is performed. """ segname = 'high' trigarmtime = 100e-6 # how long does the ZI need to arm its trigger? trigbits = 100 if compensation_ratio < 0: raise ValueError('compensation_ratio must bea positive number') # The pulsed part bp1 = bb.BluePrint() bp1.setSR(SR) bp1.insertSegment(0, ramp, (pulsehigh, pulsehigh), durs=hightime, name=segname) bp1.insertSegment(1, ramp, (pulselow, pulselow), durs=meastime, name='measure') # dead time for the scope to re-arm its trigger bp1.insertSegment(2, 'waituntil', cycletime) bp1.marker1 = [(hightime + trig_delay, meastime)] bp1.marker2 = [(hightime + trig_delay, meastime)] if compensation_ratio != 0: # area to compensate for area = pulsehigh * hightime + pulselow * meastime # Area of pulse in V*s compensation_duration = compensation_ratio * (hightime + meastime) compensation_height = -area / compensation_duration bp1.insertSegment(0, ramp, (compensation_height, compensation_height), durs=compensation_duration) # update the marker timing bp1.marker1 = [(hightime + trig_delay + compensation_duration, meastime)] bp1.marker2 = [(hightime + trig_delay + compensation_duration, meastime)] # In front of the real sequence, we need some dead time to # allow the scope to arm its trigger. The problem is that # the scope.get is blocking. Luckily, running the AWG is not # therefore, we do: # awg.run(); scope.get() # with some dead time in the awg.run() prebp = bb.BluePrint() prebp.insertSegment(0, ramp, (0, 0), durs=trigarmtime / trigbits) prebp.setSR(SR) pretrigelem = bb.Element() pretrigelem.addBluePrint(1, prebp) mainelem = bb.Element() mainelem.addBluePrint(1, bp1) seq = bb.Sequence() seq.addElement(1, pretrigelem) seq.addElement(2, mainelem) seq.setSR(SR) # NB: We have not specified voltage ranges yet # this will be done when the uploading is to happen seq.setSequenceSettings(1, 0, trigbits, 0, 0) # the last zero disables jumping, i.e. seq. plays once seq.setSequenceSettings(2, 0, no_of_avgs, 0, 0) return seq