def test_get_pulses(self): pulse_sequence = PulseSequence() self.assertListEqual(pulse_sequence.get_pulses(), []) pulse1 = DCPulse(name='dc1', amplitude=1.5, duration=10, t_start=1) pulse2 = DCPulse(name='dc2', amplitude=2.5, duration=10, t_start=1) pulse3 = TriggerPulse(name='trig', duration=12, t_start=1) pulse_sequence.add(pulse1, pulse2, pulse3) subset_pulses = pulse_sequence.get_pulses() self.assertEqual(subset_pulses[0], pulse1) self.assertListEqual(subset_pulses, [pulse1, pulse2, pulse3]) subset_pulses = pulse_sequence.get_pulses(t_start=1) self.assertListEqual(subset_pulses, [pulse1, pulse2, pulse3]) subset_pulses = pulse_sequence.get_pulses(duration=10) self.assertListEqual(subset_pulses, [pulse1, pulse2]) subset_pulses = pulse_sequence.get_pulses(amplitude=1.5) self.assertListEqual(subset_pulses, [pulse1]) subset_pulses = pulse_sequence.get_pulses(amplitude=('>', 1.5)) self.assertListEqual(subset_pulses, [pulse2]) subset_pulses = pulse_sequence.get_pulses(amplitude=('>=', 1.5)) self.assertListEqual(subset_pulses, [pulse1, pulse2]) pulse = pulse_sequence.get_pulse(amplitude=1.5) self.assertEqual(pulse, pulse1) pulse = pulse_sequence.get_pulse(duration=12) self.assertEqual(pulse, pulse3) with self.assertRaises(RuntimeError): pulse_sequence.get_pulse(duration=10)
def test_pulse_equality(self): pulse1 = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) self.assertTrue(pulse1) pulse2 = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) self.assertEqual(pulse1, pulse2) pulse3 = DCPulse(name='dc', amplitude=2.5, duration=10, t_start=0) self.assertNotEqual(pulse1, pulse3)
def test_quick_add_pulse_id(self): pulses = [ DCPulse('DC', duration=10), DCPulse('DC', duration=10), DCPulse('DC2', duration=10) ] pulse_sequence = PulseSequence() added_pulses = pulse_sequence.quick_add(*pulses) pulse_sequence.finish_quick_add() self.assertNotEqual(pulses, added_pulses) self.assertEqual(pulses[0].t_start, None) self.assertEqual(added_pulses[0].t_start, 0) self.assertEqual(added_pulses[1].t_start, 10) self.assertEqual(added_pulses[2].t_start, 20) self.assertEqual(pulses[0].full_name, 'DC') self.assertEqual(pulses[1].full_name, 'DC') self.assertEqual(pulses[2].full_name, 'DC2') self.assertEqual(added_pulses[0].full_name, 'DC[0]') self.assertEqual(added_pulses[1].full_name, 'DC[1]') self.assertEqual(added_pulses[2].full_name, 'DC2') self.assertEqual(pulse_sequence.duration, 30)
def test_sort(self): pulse_sequence = PulseSequence() pulse1 = DCPulse(name='dc1', amplitude=1.5, duration=10, t_start=1) pulse2 = DCPulse(name='dc2', amplitude=1.5, duration=10, t_start=0) pulse_sequence.add(pulse1, pulse2) self.assertEqual(pulse_sequence[0], pulse2)
def test_remove_reinstantiated_pulse(self): # Remove other pulse using .remove pulse_sequence = PulseSequence() pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse_sequence.add(pulse) pulse2 = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse_sequence.remove(pulse2) # Should work since all attributes match self.assertEqual(len(pulse_sequence.pulses), 0)
def test_overlapping_pulses_different_connection_label(self): pulses = [ DCPulse(t_start=0, duration=10, connection_label='con1'), DCPulse(t_start=5, duration=10, connection_label='con2') ] pulse_sequence = PulseSequence(allow_pulse_overlap=False) pulse_sequence.quick_add(*pulses) pulse_sequence.finish_quick_add()
def test_initialize_with_pulses(self): pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse2 = DCPulse(name='dc', amplitude=1.5, duration=10) pulse_sequence = PulseSequence(pulses=[pulse, pulse2]) self.assertEqual(len(pulse_sequence), 2) self.assertEqual(pulse_sequence.pulses[0], pulse) self.assertNotEqual(pulse_sequence.pulses[1], pulse2) #t_start differs pulse2.t_start = 10 self.assertEqual(pulse_sequence.pulses[1], pulse2)
def test_overlapping_pulses(self): pulses = [ DCPulse(t_start=0, duration=10), DCPulse(t_start=5, duration=10) ] pulse_sequence = PulseSequence(allow_pulse_overlap=False) pulse_sequence.quick_add(*pulses) with self.assertRaises(AssertionError): pulse_sequence.finish_quick_add()
def test_remove_wrong_pulse_remove(self): # Remove other pulse using .remove pulse_sequence = PulseSequence() pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse_sequence.add(pulse) pulse2 = DCPulse(name='dc', amplitude=2, duration=10, t_start=0) with self.assertRaises(AssertionError): pulse_sequence.remove( pulse2) # Should not work since different amplitude self.assertEqual(len(pulse_sequence.pulses), 1)
def test_quick_add_pulses(self): pulses = [DCPulse(duration=10), DCPulse(duration=10)] pulse_sequence = PulseSequence() added_pulses = pulse_sequence.quick_add(*pulses) self.assertNotEqual(pulses, added_pulses) self.assertEqual(pulses[0].t_start, None) self.assertEqual(added_pulses[0].t_start, 0) self.assertEqual(added_pulses[1].t_start, 10) self.assertEqual(pulse_sequence.duration, 20)
def test_transition_voltages(self): # To test transitions, pulses must be on the same connection channel_out = Channel('arbstudio', 'ch1', id=1, output=True) channel_in = Channel('device', 'input', id=1, output=True) c1 = SingleConnection(output_instrument='arbstudio', output_channel=channel_out, input_instrument='device', input_channel=channel_in) pulses = [ DCPulse(name='dc1', amplitude=0, duration=5, t_start=0, connection=c1), DCPulse(name='dc2', amplitude=1, duration=10, t_start=5, connection=c1), DCPulse(name='dc3', amplitude=2, duration=8, t_start=15, connection=c1), DCPulse(name='dc4', amplitude=3, duration=7, t_start=12, connection=c1) ] pulse_sequence = PulseSequence(pulses) self.assertRaises(TypeError, pulse_sequence.get_transition_voltages) self.assertRaises(TypeError, pulse_sequence.get_transition_voltages, connection=c1) self.assertRaises(TypeError, pulse_sequence.get_transition_voltages, t=5) transition_voltage = pulse_sequence.get_transition_voltages( pulse=pulses[1]) self.assertTupleEqual(transition_voltage, (0, 1)) transition_voltage = pulse_sequence.get_transition_voltages( connection=c1, t=5) self.assertTupleEqual(transition_voltage, (0, 1)) transition_voltage = pulse_sequence.get_transition_voltages( connection=c1, t=15) self.assertTupleEqual(transition_voltage, (1, 2))
def test_deepcopy_pulse_equality(self): p = DCPulse(t_start=2, duration=1) p_copy = deepcopy(p) self.assertEqual(p, p_copy) p_copy.duration = 2 self.assertNotEqual(p, p_copy) p_copy.duration = 1 self.assertEqual(p, p_copy) p.duration = 2 self.assertNotEqual(p, p_copy)
def test_arbstudio_pulseblaster(self): self.layout.acquisition_channels([]) self.layout.primary_instrument('pulseblaster') self.layout.acquisition_instrument('ATS') self.layout.add_connection(output_arg='arbstudio.ch1', input_arg='chip.TGAC') self.layout.add_connection(output_arg='arbstudio.ch2', input_arg='chip.DF', default=True) self.layout.add_connection(output_arg='pulseblaster.ch1', input_arg='arbstudio.trig_in', trigger=True) trigger_connections = self.layout.get_connections( input_instrument='arbstudio', trigger=True) self.assertEqual(len(trigger_connections), 1) trigger_connection = trigger_connections[0] self.assertEqual(trigger_connection.output['instrument'], 'pulseblaster') pulse_sequence = PulseSequence() empty_pulse = DCPulse(name='empty', t_start=0, duration=10, amplitude=1.5) load_pulse = DCPulse(name='load', t_start=10, duration=10, amplitude=-1.5) read_pulse = DCPulse(name='read', t_start=20, duration=10, amplitude=0) pulses = [empty_pulse, load_pulse, read_pulse] for pulse in pulses: pulse_sequence.add(pulse) self.layout.pulse_sequence = pulse_sequence self.layout.setup() self.assertEqual(len(self.pulseblaster.instructions()), 7) self.assertEqual([ins[0] for ins in self.pulseblaster.instructions()], [1, 0, 1, 0, 1, 0, 0]) self.assertEqual(self.pulseblaster.instructions()[-1][2], 1) self.pulseblaster.instructions([]) self.interfaces['pulseblaster'].ignore_first_trigger(True) self.layout.pulse_sequence = pulse_sequence self.layout.setup() self.assertEqual(len(self.pulseblaster.instructions()), 7) self.assertEqual([ins[0] for ins in self.pulseblaster.instructions()], [0, 0, 1, 0, 1, 0, 1])
def test_overlapping_random_pulses(self): for connection_label in [ 'connection1', 'connection2', 'connection3', None ]: pulses = [] t = 0 for k in range(30): duration = np.round(np.random.rand(), 11) pulses.append( DCPulse('DC', t_start=t, duration=duration, connection_label='connection1')) t += duration random.shuffle(pulses) pulse_sequence = PulseSequence(allow_pulse_overlap=False) pulse_sequence.quick_add(*pulses) pulse_sequence.finish_quick_add() # No overlap # Add pulses with connection label second_pulses = [] t = 0 for k in range(30): duration = np.round(np.random.rand(), 11) second_pulses.append( DCPulse('DC', t_start=t, duration=duration, connection_label='connection2')) t += duration random.shuffle(second_pulses) pulse_sequence.quick_add(*second_pulses) pulse_sequence.finish_quick_add() # No overlap # Add pulse that potentially overlaps based on connection_label overlapping_pulse = DCPulse(t_start=pulse_sequence.duration / 2, duration=1e-5, connection_label=connection_label) overlapping_pulse_copy, = pulse_sequence.quick_add( overlapping_pulse) if connection_label in ['connection1', 'connection2', None]: with self.assertRaises(AssertionError): pulse_sequence.finish_quick_add() else: pulse_sequence.finish_quick_add() pulse_sequence.remove(overlapping_pulse_copy) pulse_sequence.finish_quick_add()
def test_pulse_implementation(self): sine_pulse = SinePulse(t_start=0, duration=10, frequency=1e6, amplitude=1) self.assertIsNone( self.arbstudio_interface.get_pulse_implementation(sine_pulse)) DC_pulse = DCPulse(t_start=0, duration=10, amplitude=1) self.assertIsNotNone( self.arbstudio_interface.get_pulse_implementation(DC_pulse)) DC_pulse.amplitude = 3 self.assertIsNone( self.arbstudio_interface.get_pulse_implementation(DC_pulse))
def test_add_multiple_pulses(self): pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse2 = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=10) pulse_sequence = PulseSequence() pulse_sequence.add(pulse, pulse2) self.assertEqual(len(pulse_sequence), 2) self.assertEqual(pulse_sequence.pulses[0], pulse) self.assertEqual(pulse_sequence.pulses[1], pulse2) pulse3 = DCPulse(name='dc', amplitude=1.5, duration=10) pulse3_added, = pulse_sequence.add(pulse3) # This one shouldn't be equal since t_stop was not set self.assertNotEqual(pulse_sequence.pulses[2], pulse3) pulse3.t_start = pulse3_added.t_start self.assertEqual(pulse_sequence.pulses[2], pulse3)
def test_quick_add_unsorted_pulses(self): pulses = [] t = 0 for k in range(30): duration = np.round(np.random.rand(), 11) pulses.append(DCPulse('DC', t_start=t, duration=duration)) t += duration random.shuffle(pulses) pulse_sequence = PulseSequence() added_pulses = pulse_sequence.quick_add(*pulses) for pulse in added_pulses: self.assertEqual(pulse.id, None) pulse_sequence.finish_quick_add() t = 0 for k, pulse in enumerate(pulse_sequence.pulses): self.assertEqual(pulse.id, k) self.assertAlmostEqual(pulse.t_start, t) t += pulse.duration self.assertAlmostEqual(pulse_sequence.duration, t)
def test_pickle_pulse_sequence_two_pulses(self): p = DCPulse('pulse', duration=2, amplitude=3) pulse_sequence = PulseSequence(pulses=[p, p]) self.assertEqual(pulse_sequence.pulses[0].full_name, 'pulse[0]') self.assertEqual(pulse_sequence.pulses[1].full_name, 'pulse[1]') self.assertEqual(pulse_sequence.pulses[0].t_start, 0) self.assertEqual(pulse_sequence.pulses[0].duration, 2) self.assertEqual(pulse_sequence.pulses[0].amplitude, 3) self.assertEqual(pulse_sequence.duration, 4) pickle_dump = pickle.dumps(pulse_sequence) pickled_pulse_sequence = pickle.loads(pickle_dump) self.assertEqual(pickled_pulse_sequence.pulses[0].full_name, 'pulse[0]') self.assertEqual(pickled_pulse_sequence.pulses[0].t_start, 0) self.assertEqual(pickled_pulse_sequence.pulses[0].duration, 2) self.assertEqual(pickled_pulse_sequence.pulses[0].amplitude, 3) self.assertEqual(pickled_pulse_sequence.pulses[1].full_name, 'pulse[1]') self.assertEqual(pickled_pulse_sequence.pulses[1].t_start, 2) self.assertEqual(pickled_pulse_sequence.pulses[1].duration, 2) self.assertEqual(pickled_pulse_sequence.pulses[1].amplitude, 3) self.assertEqual(pickled_pulse_sequence.duration, 4)
def test_remove_pulse_remove(self): # Remove pulses using .remove pulse_sequence = PulseSequence() pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse_sequence.add(pulse) pulse_sequence.remove(pulse) self.assertEqual(len(pulse_sequence.pulses), 0)
def test_remove_wrong_pulse_by_name(self): # Remove pulses using .remove pulse_sequence = PulseSequence() pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse_sequence.add(pulse) with self.assertRaises(AssertionError): pulse_sequence.remove('dc2') self.assertEqual(len(pulse_sequence.pulses), 1)
def test_ELR_programming(self): empty_pulse = DCPulse(name='empty', t_start=0, duration=10, amplitude=1.5) load_pulse = DCPulse(name='load', t_start=10, duration=10, amplitude=-1.5) read_pulse = DCPulse(name='read', t_start=20, duration=10, amplitude=0) pulses = [empty_pulse, load_pulse, read_pulse] for pulse in pulses: targeted_pulse = self.arbstudio_interface.get_pulse_implementation( pulse) self.arbstudio_interface.pulse_sequence.add(targeted_pulse) self.assertEqual(len(pulses), len(self.arbstudio_interface.pulse_sequence.pulses))
def test_getitem(self): pulse_sequence = PulseSequence() pulse1, = pulse_sequence.add(DCPulse('DC', duration=1)) self.assertIs(pulse_sequence['DC'], pulse1) self.assertIs(pulse_sequence['duration'], pulse_sequence.parameters['duration']) pulse1.id = 0 self.assertIs(pulse_sequence['DC'], pulse1) self.assertIs(pulse_sequence['DC[0]'], pulse1) pulse2, = pulse_sequence.add(DCPulse('DC', duration=1)) self.assertIs(pulse_sequence['DC[0]'], pulse1) self.assertIs(pulse_sequence['DC[1]'], pulse2) with self.assertRaises(KeyError): pulse_sequence['DC']
def test_add_remove_pulse(self): pulse_sequence = PulseSequence() self.assertFalse(pulse_sequence) pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) pulse_sequence.add(pulse) self.assertIn(pulse, pulse_sequence) self.assertTrue(pulse_sequence)
def test_pulse_snapshotting(self): pulse = DCPulse('DC', duration=2) snapshot = pulse.snapshot() for parameter_name, parameter in pulse.parameters.items(): if parameter.unit: parameter_name += f' ({parameter.unit})' self.assertIn(parameter_name, snapshot, msg=f'{parameter_name} not present') if snapshot[parameter_name] != parameter(): print('hi') self.assertEqual(snapshot.pop(parameter_name), parameter(), msg=f'{parameter} not equal') self.assertEqual('silq.pulses.pulse_types.DCPulse', snapshot.pop('__class__')) self.assertFalse(snapshot, f'snapshot exists')
def setup(self, **kwargs): for channel in self.instrument.channels: channel.instruction_sequence().clear() self.instrument.channels.output_enable(False) self.instrument.channels.pcdds_enable(True) assert self.use_trig_in( ), "Interface not yet programmed for pxi triggering" # First pulses are 0V DC pulses # t_start and duration must be set but are irrelevant DC_0V_pulse = self.get_pulse_implementation( DCPulse('initial_0V', t_start=0, duration=0, amplitude=0)) current_pulses = { channel.name: DC_0V_pulse for channel in self.active_instrument_channels } # for channel in self.active_instrument_channels: # current_pulses[channel.name]: copy(DC_0V_pulse) # current_pulses[channel.name].t_start = 0 # next_pulse = next(self.pulse_sequence.get_pulses(output_channel=channel.name)) # current_pulses[channel.name].t_stop = next_pulse.t_start for channel in self.active_instrument_channels: current_pulse = current_pulses[channel.name] pulse_implementation = current_pulse.implementation.implement() pulse_implementation['pulse_idx'] = 0 pulse_implementation['next_pulse'] = 1 channel.write_instr(pulse_implementation) total_instructions = len(self.pulse_sequence.t_list) for pulse_idx, t in enumerate(self.pulse_sequence.t_list): if t == self.pulse_sequence.duration: continue pulse_idx += 1 # We start with 1 since we have initial 0V pulse for channel in self.active_instrument_channels: active_pulse = self.pulse_sequence.get_pulse( t_start=t, output_channel=channel.name) if active_pulse is not None: # New pulse starts current_pulses[channel.name] = active_pulse elif t >= current_pulses[channel.name].t_stop: current_pulses[channel.name] = DC_0V_pulse pulse_implementation = current_pulses[ channel.name].implementation.implement() pulse_implementation['pulse_idx'] = pulse_idx if pulse_idx + 1 < total_instructions: pulse_implementation['next_pulse'] = pulse_idx + 1 else: # Loop back to second pulse (ignore first 0V pulse) pulse_implementation['next_pulse'] = 1 channel.write_instr(pulse_implementation) # targeted_pulse_sequence is the pulse sequence that is currently setup self.targeted_pulse_sequence = self.pulse_sequence self.targeted_input_pulse_sequence = self.input_pulse_sequence
def test_deepcopy_copy_pulse_equality(self): p = DCPulse(t_start=2, duration=1) p_copy = deepcopy(p) p_copy.t_start = 3 p_copy2 = copy(p_copy) self.assertNotEqual(p, p_copy) self.assertNotEqual(p, p_copy2) self.assertEqual(p_copy, p_copy2)
def test_pickle_DC_pulse(self): p = DCPulse('pulse', t_start=1, duration=2, amplitude=5) pickle_dump = pickle.dumps(p) pickled_pulse = pickle.loads(pickle_dump) self.assertEqual(pickled_pulse.name, 'pulse') self.assertEqual(pickled_pulse.t_start, 1) self.assertEqual(pickled_pulse.duration, 2) self.assertEqual(pickled_pulse.t_stop, 3) self.assertEqual(pickled_pulse.amplitude, 5)
def test_pulse_full_name(self): p = Pulse('pulse1') self.assertEqual(p.full_name, 'pulse1') p.id = 2 self.assertEqual(p.full_name, 'pulse1[2]') p = DCPulse('pulse2') self.assertEqual(p.full_name, 'pulse2') p.id = 2 self.assertEqual(p.full_name, 'pulse2[2]')
def test_remove_pulse_by_name(self): # Remove pulses using .remove pulse_sequence = PulseSequence() pulse = DCPulse(name='dc', amplitude=1.5, duration=10, t_start=0) self.assertEqual(pulse.name, 'dc') self.assertEqual(pulse.full_name, 'dc') added_pulse, = pulse_sequence.add(pulse) self.assertEqual(added_pulse.full_name, 'dc') pulse_sequence.remove('dc') self.assertEqual(len(pulse_sequence.pulses), 0)
def test_non_empty_pulse_sequence_equality(self): pulse_sequence = PulseSequence( [DCPulse('read', duration=1, amplitude=2)]) self.assertEqual(pulse_sequence, pulse_sequence) pulse_sequence2 = PulseSequence( [DCPulse('read', duration=1, amplitude=2)]) self.assertEqual(pulse_sequence, pulse_sequence2) pulse_sequence2['read'].duration = 2 self.assertNotEqual(pulse_sequence, pulse_sequence2) pulse_sequence2['read'].duration = 1 pulse_sequence2.allow_pulse_overlap = False self.assertNotEqual(pulse_sequence, pulse_sequence2) pulse_sequence2.allow_pulse_overlap = True self.assertEqual(pulse_sequence, pulse_sequence) pulse_sequence2.duration = 5 self.assertNotEqual(pulse_sequence, pulse_sequence2)