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 = Sequence() seq.addElement(1, squarepulse_baseelem) seq.setSR(squarepulse_baseelem.SR) mainseq = 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 = Sequence() doublemainseq.setSR(seq.SR) with pytest.raises(ValueError): doublemainseq.addSubSequence(1, mainseq)
def test_write_read_sequence(protosequence1, protosequence2, tmp_path): d = tmp_path / "Sequence" d.mkdir() for seq in (protosequence1, protosequence2): seq.write_to_json(os.path.join(d, "Seq.json")) readbackseq = Sequence.init_from_json(os.path.join(d, "Seq.json")) assert seq == readbackseq
def test_addition_data_with_empty(protosequence1): newseq = Sequence() newseq._awgspecs = protosequence1._awgspecs newseq = newseq + protosequence1 assert newseq._data == protosequence1._data
def repeatAndVarySequence(seq, poss, channels, names, args, iters): """ Repeat a sequence and vary part(s) of it. Returns a new sequence. Given N specifications of M steps, N parameters are varied in M steps. Args: seq (Sequence): The sequence to be repeated. poss (Union[list, tuple]): A length N list/tuple specifying at which sequence position(s) the blueprint to change is. channels (Union[list, tuple]): A length N list/tuple specifying on which channel(s) the blueprint to change is. names (Union[list, tuple]): A length N list/tuple specifying the name of the segment to change. args (Union[list, tuple]): A length N list/tuple specifying which argument to change. A valid argument is also 'duration'. iters (Union[list, tuple]): A length N list/tuple containing length M indexable iterables with the values to step through. """ if not seq.checkConsistency(): raise SequenceConsistencyError('Inconsistent input sequence! Can not ' 'proceed. Check all positions ' 'and channels.') inputlens = [len(poss), len(channels), len(names), len(args), len(iters)] if not inputlens.count(inputlens[0]) == len(inputlens): raise ValueError('Inconsistent number of position, channel, name, args' ', and ' 'parameter sequences. Please specify the same number ' 'of each.') noofvals = [len(itr) for itr in iters] if not noofvals.count(noofvals[0]) == len(iters): raise ValueError('Not the same number of values in each parameter ' 'value sequence (input argument: iters)') newseq = Sequence() newseq._awgspecs = seq._awgspecs no_of_steps = noofvals[0] for step in range(no_of_steps): tempseq = seq.copy() for (pos, chan, name, arg, vals) in zip(poss, channels, names, args, iters): element = tempseq.element(pos) val = vals[step] if arg == 'duration': element.changeDuration(chan, name, val) else: element.changeArg(chan, name, arg, val) newseq = newseq + tempseq return newseq
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 = 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 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 = 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 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 = 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 make_seq(seqlen, channels, SR): seq = Sequence() seq.setSR(SR) for pos in range(1, seqlen + 1): elem = bb.Element() for chan in channels: bp = bb.BluePrint() bp.insertSegment(-1, ramp, (0, 0), dur=20 / SR) bp.insertSegment(-1, ramp, (1, 1), dur=10 / SR) bp.insertSegment(-1, ramp, (0, 0), dur=5 / SR) bp.setSR(SR) elem.addBluePrint(chan, bp) seq.addElement(pos, elem) 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 = 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 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 = 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 makeLinearlyVaryingSequence(baseelement, channel, name, arg, start, stop, step): """ Make a pulse sequence where a single parameter varies linearly. The pulse sequence will consist of N copies of the same element with just the specified argument changed (N = abs(stop-start)/steps) Args: baseelement (Element): The basic element. channel (int): The channel where the change should happen name (str): Name of the blueprint segment to change arg (Union[str, int]): Name (str) or position (int) of the argument to change. If the arg is 'duration', the duration is changed instead. start (float): Start point of the variation (included) stop (float): Stop point of the variation (included) step (float): Increment of the variation """ # TODO: validation # TODO: Make more general varyer and refactor code sequence = Sequence() sequence.setSR(baseelement.SR) iterator = np.linspace(start, stop, round(abs(stop - start) / step) + 1) for ind, val in enumerate(iterator): element = baseelement.copy() if arg == 'duration': element.changeDuration(channel, name, val) else: element.changeArg(channel, name, arg, val) sequence.addElement(ind + 1, element) return sequence
def makeVaryingSequence(baseelement, channels, names, args, iters): """ Make a pulse sequence where N parameters vary simultaneously in M steps. The user inputs a baseelement which is copied M times and changed according to the given inputs. Args: baseelement (Element): The basic element. channels (Union[list, tuple]): Either a list or a tuple of channels on which to find the blueprint to change. Must have length N. names (Union[list, tuple]): Either a list or a tuple of names of the segment to change. Must have length N. args (Union[list, tuple]): Either a list or a tuple of argument specifications for the argument to change. Use 'duration' to change the segment duration. Must have length N. iters (Union[list, tuple]): Either a list or a tuple of length N containing Union[list, tuple, range] of length M. Raises: ValueError: If not channels, names, args, and iters are of the same length. ValueError: If not each iter in iters specifies the same number of values. """ # Validation baseelement.validateDurations() inputlengths = [len(channels), len(names), len(args), len(iters)] if not inputlengths.count(inputlengths[0]) == len(inputlengths): raise ValueError('Inconsistent number of channel, names, args, and ' 'parameter sequences. Please specify the same number ' 'of each.') noofvals = [len(itr) for itr in iters] if not noofvals.count(noofvals[0]) == len(iters): raise ValueError('Not the same number of values in each parameter ' 'value sequence (input argument: iters)') sequence = Sequence() sequence.setSR(baseelement.SR) for elnum in range(1, noofvals[0] + 1): sequence.addElement(elnum, baseelement.copy()) for (chan, name, arg, vals) in zip(channels, names, args, iters): for mpos, val in enumerate(vals): element = sequence.element(mpos + 1) if arg == 'duration': element.changeDuration(chan, name, val) else: element.changeArg(chan, name, arg, val) log.info('Created varying sequence using makeVaryingSequence.' ' Now validating it...') if not sequence.checkConsistency(): raise SequenceConsistencyError('Invalid sequence. See log for ' 'details.') else: log.info('Valid sequence') return sequence