def test_depth_1_advanced_sequence(self): wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) program = Loop(children=[ Loop(waveform=wf_1, repetition_count=3), Loop(waveform=wf_2, repetition_count=4), Loop(waveform=wf_1, repetition_count=1) ], repetition_count=5) t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), device_properties=self.instr_props, **self.program_entry_kwargs) self.assertEqual(t_program.waveform_mode, TaborSequencing.ADVANCED) # partial unroll of the last segment self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), None), (TableDescription(4, 1, 0), None), (TableDescription(1, 0, 0), None)]]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableEntry(5, 1, 0)])
def test_depth_1_single_sequence_2(self): """Use the same wf twice""" wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) program = Loop(children=[ Loop(waveform=wf_1, repetition_count=3), Loop(waveform=wf_2, repetition_count=4), Loop(waveform=wf_1, repetition_count=1) ], repetition_count=1) t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), device_properties=self.instr_props, **self.program_entry_kwargs) self.assertEqual(t_program.waveform_mode, TaborSequencing.SINGLE) self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), None), (TableDescription(4, 1, 0), None), (TableDescription(1, 0, 0), None)]]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)])
def test_advanced_sequence_exceptions(self): temp_properties = self.instr_props.copy() temp_properties['max_seq_len'] = 5 program = Loop(children=[ Loop(waveform=DummyWaveform(defined_channels={'A'}, duration=1), repetition_count=1) for _ in range(temp_properties['max_seq_len'] + 1) ], repetition_count=2) with self.assertRaises(TaborException): TaborProgram(program.copy_tree_structure(), channels=(None, 'A'), markers=(None, None), device_properties=temp_properties, **self.program_entry_kwargs) temp_properties['min_seq_len'] = 100 temp_properties['max_seq_len'] = 120 with self.assertRaises(TaborException) as exception: TaborProgram(program.copy_tree_structure(), channels=(None, 'A'), markers=(None, None), device_properties=temp_properties, **self.program_entry_kwargs) self.assertEqual( str(exception.exception), 'The algorithm is not smart enough ' 'to make this sequence table longer') program = Loop(children=[ Loop(children=[ Loop(waveform=DummyWaveform(defined_channels={'A'}, duration=1)), Loop( waveform=DummyWaveform(defined_channels={'A'}, duration=1)) ]), Loop(children=[ Loop(waveform=DummyWaveform(defined_channels={'A'}, duration=1)), Loop( waveform=DummyWaveform(defined_channels={'A'}, duration=1)) ]) ]) with self.assertRaises(TaborException) as exception: TaborProgram(program.copy_tree_structure(), channels=(None, 'A'), markers=(None, None), device_properties=temp_properties, **self.program_entry_kwargs) self.assertEqual( str(exception.exception), 'The algorithm is not smart enough ' 'to make this sequence table longer')
def test_depth_0_single_waveform(self): program = Loop(waveform=DummyWaveform(defined_channels={'A'}, duration=1), repetition_count=3) t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), device_properties=self.instr_props, **self.program_entry_kwargs) self.assertEqual(t_program.waveform_mode, TaborSequencing.SINGLE) self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), None)]]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)])
def test_sampled_segments(self): def my_gen(gen): alternating_on_off = itertools.cycle((np.ones(192), np.zeros(192))) chan_gen = gen while True: for _ in range(2): yield next(chan_gen) yield next(alternating_on_off)[::2] yield np.zeros(192)[::2] with self.assertRaisesRegex(ValueError, "non integer length"): root_loop = LoopTests.get_test_loop( WaveformGenerator(waveform_data_generator=my_gen( self.waveform_data_generator), duration_generator=itertools.repeat(1 / 200), num_channels=4)) TaborProgram(root_loop, self.instr_props, ('A', 'B'), (None, None), **self.program_entry_kwargs) root_loop = LoopTests.get_test_loop( WaveformGenerator(waveform_data_generator=my_gen( self.waveform_data_generator), duration_generator=itertools.repeat(1), num_channels=4)) prog = TaborProgram(root_loop, self.instr_props, ('A', 'B'), (None, None), **self.program_entry_kwargs) sampled, sampled_length = prog.get_sampled_segments() self.assertEqual(len(sampled), 3) prog = TaborProgram(root_loop, self.instr_props, ('A', 'B'), ('C', None), **self.program_entry_kwargs) sampled, sampled_length = prog.get_sampled_segments() self.assertEqual(len(sampled), 6) iteroe = my_gen(self.waveform_data_generator) for i, sampled_seg in enumerate(sampled): data = [next(iteroe) for _ in range(4)] data = (voltage_to_uint16(data[0], 1., 0., 14), voltage_to_uint16(data[1], 1., 0., 14), data[2], data[3]) if i % 2 == 0: np.testing.assert_equal(sampled_seg.marker_a, np.ones(192, dtype=np.uint16)[::2]) else: np.testing.assert_equal(sampled_seg.marker_a, np.zeros(192, dtype=np.uint16)[::2]) np.testing.assert_equal(sampled_seg.marker_b, np.zeros(192, dtype=np.uint16)[::2]) np.testing.assert_equal(sampled_seg.ch_a, data[0]) np.testing.assert_equal(sampled_seg.ch_b, data[1])
def test_init(self): prog = self.root_loop tabor_program = TaborProgram(prog, self.instr_props, ('A', None), (None, None), **self.program_entry_kwargs) self.assertEqual(tabor_program.channels, ('A', None)) self.assertEqual(tabor_program.markers, (None, None)) self.assertIs(prog, tabor_program.program) self.assertIs(self.instr_props, tabor_program._device_properties) self.assertEqual(frozenset('A'), tabor_program._used_channels) self.assertEqual(TaborSequencing.ADVANCED, tabor_program._mode) with self.assertRaises(KeyError): # C not in prog TaborProgram(prog, self.instr_props, ('A', 'C'), (None, None), **self.program_entry_kwargs) with self.assertRaises(TaborException): TaborProgram(prog, self.instr_props, ('A', 'B'), (None, None, None), **self.program_entry_kwargs) with self.assertRaises(TaborException): TaborProgram(prog, self.instr_props, ('A', 'B', 'C'), (None, None), **self.program_entry_kwargs)
def test_update_volatile_parameters_with_depth1(self): parameters = {'s': 10, 'not': 13} s = VolatileRepetitionCount(expression=ExpressionScalar('s'), scope=DictScope(values=FrozenDict(s=3), volatile=set('s'))) wf_1 = DummyWaveform(defined_channels={'A'}, duration=1) wf_2 = DummyWaveform(defined_channels={'A'}, duration=1) program = Loop(children=[ Loop(waveform=wf_1, repetition_count=s), Loop(waveform=wf_2, repetition_count=4), Loop(waveform=wf_1, repetition_count=1) ], repetition_count=1) t_program = TaborProgram(program, channels=(None, 'A'), markers=(None, None), device_properties=self.instr_props, **self.program_entry_kwargs) self.assertEqual(t_program.get_sequencer_tables(), [[(TableDescription(3, 0, 0), s.volatile_property), (TableDescription(4, 1, 0), None), (TableDescription(1, 0, 0), None)]]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)]) modifications = t_program.update_volatile_parameters(parameters) expected_seq = VolatileRepetitionCount( expression=ExpressionScalar('s'), scope=DictScope(values=FrozenDict(s=10), volatile=set('s'))) expected_modifications = {(0, 0): TableDescription(10, 0, 0)} self.assertEqual( t_program.get_sequencer_tables(), [[(TableDescription(10, 0, 0), expected_seq.volatile_property), (TableDescription(4, 1, 0), None), (TableDescription(1, 0, 0), None)]]) self.assertEqual(t_program.get_advanced_sequencer_table(), [TableDescription(1, 1, 0)]) self.assertEqual(modifications, expected_modifications)
def upload(self, name: str, program: Loop, channels: Tuple[Optional[ChannelID], Optional[ChannelID]], markers: Tuple[Optional[ChannelID], Optional[ChannelID]], voltage_transformation: Tuple[Callable, Callable], force: bool = False) -> None: """Upload a program to the AWG. The policy is to prefer amending the unknown waveforms to overwriting old ones.""" if len(channels) != self.num_channels: raise ValueError('Channel ID not specified') if len(markers) != self.num_markers: raise ValueError('Markers not specified') if len(voltage_transformation) != self.num_channels: raise ValueError('Wrong number of voltage transformations') # adjust program to fit criteria sample_rate = self.device.sample_rate(self._channels[0]) make_compatible(program, minimal_waveform_length=192, waveform_quantum=16, sample_rate=fractions.Fraction(sample_rate, 10**9)) if name in self._known_programs: if force: self.free_program(name) else: raise ValueError('{} is already known on {}'.format(name, self.identifier)) # They call the peak to peak range amplitude ranges = (self.device.amplitude(self._channels[0]), self.device.amplitude(self._channels[1])) voltage_amplitudes = (ranges[0]/2, ranges[1]/2) if self._amplitude_offset_handling == AWGAmplitudeOffsetHandling.IGNORE_OFFSET: voltage_offsets = (0, 0) elif self._amplitude_offset_handling == AWGAmplitudeOffsetHandling.CONSIDER_OFFSET: voltage_offsets = (self.device.offset(self._channels[0]), self.device.offset(self._channels[1])) else: raise ValueError('{} is invalid as AWGAmplitudeOffsetHandling'.format(self._amplitude_offset_handling)) # parse to tabor program tabor_program = TaborProgram(program, channels=tuple(channels), markers=markers, device_properties=self.device.dev_properties, sample_rate=sample_rate / 10**9, amplitudes=voltage_amplitudes, offsets=voltage_offsets, voltage_transformations=voltage_transformation) segments, segment_lengths = tabor_program.get_sampled_segments() waveform_to_segment, to_amend, to_insert = self._find_place_for_segments_in_memory(segments, segment_lengths) self._segment_references[waveform_to_segment[waveform_to_segment >= 0]] += 1 for wf_index in np.flatnonzero(to_insert > 0): segment_index = to_insert[wf_index] self._upload_segment(to_insert[wf_index], segments[wf_index]) waveform_to_segment[wf_index] = segment_index if np.any(to_amend): segments_to_amend = [segments[idx] for idx in np.flatnonzero(to_amend)] waveform_to_segment[to_amend] = self._amend_segments(segments_to_amend) self._known_programs[name] = TaborProgramMemory(waveform_to_segment=waveform_to_segment, program=tabor_program)