def test_soft_derived(): timestamp = 1.0 value = 'q' original = Signal(name='original', timestamp=timestamp, value=value) cb_values = [] def callback(value=None, **kwargs): nonlocal cb_values cb_values.append(value) derived = DerivedSignal(derived_from=original, name='derived') derived.subscribe(callback, event_type=derived.SUB_VALUE) assert derived.timestamp == timestamp assert derived.get() == value assert derived.timestamp == timestamp assert derived.describe()[derived.name]['derived_from'] == original.name new_value = 'r' derived.put(new_value) assert original.get() == new_value assert derived.get() == new_value assert derived.timestamp == original.timestamp assert derived.limits == original.limits copied = copy.copy(derived) assert copied.derived_from.value == original.value assert copied.derived_from.timestamp == original.timestamp assert copied.derived_from.name == original.name derived.put('s') assert cb_values == ['r', 's']
def test_describe(bool_enum_signal): sig = bool_enum_signal sig.put(1) desc = sig.describe()['bool_enum'] assert desc['dtype'] == 'integer' assert desc['shape'] == [] # assert 'precision' in desc assert desc['enum_strs'] == ('Off', 'On') assert 'upper_ctrl_limit' in desc assert 'lower_ctrl_limit' in desc sig = Signal(name='my_pv') sig.put('Off') desc = sig.describe()['my_pv'] assert desc['dtype'] == 'string' assert desc['shape'] == [] sig.put(3.14) desc = sig.describe()['my_pv'] assert desc['dtype'] == 'number' assert desc['shape'] == [] import numpy as np sig.put(np.array([1, ])) desc = sig.describe()['my_pv'] assert desc['dtype'] == 'array' assert desc['shape'] == [1, ]
def test_set_method(): sig = Signal(name='sig') st = sig.set(28) wait(st) assert st.done assert st.success assert sig.get() == 28
def test_ndderivedsignal_with_scalars(): sig = Signal(value=np.zeros(12), name='zeros') shaped = NDDerivedSignal(sig, shape=(4, 3), num_dimensions=2, name='shaped') shaped.derived_shape == (4, 3) shaped.derived_ndims == 2 assert shaped.get().shape == (4, 3) # Describe returns list assert shaped.describe()[shaped.name]['shape'] == [4, 3] shaped.put(np.ones((4, 3))) assert all(sig.get() == np.ones(12))
def test_signal_copy(self): start_t = time.time() name = 'test' value = 10.0 signal = Signal(name=name, value=value, timestamp=start_t) sig_copy = copy.copy(signal) self.assertEquals(signal.name, sig_copy.name) self.assertEquals(signal.value, sig_copy.value) self.assertEquals(signal.get(), sig_copy.get()) self.assertEquals(signal.timestamp, sig_copy.timestamp)
def test_signal_copy(): start_t = time.time() name = 'test' value = 10.0 signal = Signal(name=name, value=value, timestamp=start_t) sig_copy = copy.copy(signal) assert signal.name == sig_copy.name assert signal.value == sig_copy.value assert signal.get() == sig_copy.get() assert signal.timestamp == sig_copy.timestamp
def test_soft_derived(): timestamp = 1.0 value = 'q' original = Signal(name='original', timestamp=timestamp, value=value) cb_values = [] def callback(value=None, **kwargs): cb_values.append(value) derived = DerivedSignal(derived_from=original, name='derived') derived.subscribe(callback, event_type=derived.SUB_VALUE) assert derived.timestamp == timestamp assert derived.get() == value assert derived.timestamp == timestamp assert derived.describe()[derived.name]['derived_from'] == original.name assert derived.write_access == original.write_access assert derived.read_access == original.read_access new_value = 'r' derived.put(new_value) assert original.get() == new_value assert derived.get() == new_value assert derived.timestamp == original.timestamp assert derived.limits == original.limits copied = copy.copy(derived) assert copied.derived_from.value == original.value assert copied.derived_from.timestamp == original.timestamp assert copied.derived_from.name == original.name derived.put('s') assert cb_values == ['r', 's'] called = [] event = threading.Event() def meta_callback(*, connected, read_access, write_access, **kw): called.append(('meta', connected, read_access, write_access)) event.set() derived.subscribe(meta_callback, event_type=derived.SUB_META, run=False) original._metadata['write_access'] = False original._run_subs(sub_type='meta', **original._metadata) event.wait(1) assert called == [('meta', True, True, False)]
def test_describe(cleanup, signal_test_ioc): sig = EpicsSignal(signal_test_ioc.pvs['bool_enum'], name='my_pv') cleanup.add(sig) sig.wait_for_connection() sig.put(1) desc = sig.describe()['my_pv'] assert desc['dtype'] == 'integer' assert desc['shape'] == [] # assert 'precision' in desc assert desc['enum_strs'] == ['Off', 'On'] assert 'upper_ctrl_limit' in desc assert 'lower_ctrl_limit' in desc sig = Signal(name='my_pv') sig.put('Off') desc = sig.describe()['my_pv'] assert desc['dtype'] == 'string' assert desc['shape'] == [] sig.put(3.14) desc = sig.describe()['my_pv'] assert desc['dtype'] == 'number' assert desc['shape'] == [] import numpy as np sig.put(np.array([ 1, ])) desc = sig.describe()['my_pv'] assert desc['dtype'] == 'array' assert desc['shape'] == [ 1, ]
def basic(): pos = Signal(name='pos') return FuncPositioner( name='basic', move=pos.put, get_pos=pos.get, update_rate=0.1, )
def test_soft_derived(self): timestamp = 1.0 value = 'q' original = Signal(name='original', timestamp=timestamp, value=value) derived = DerivedSignal(derived_from=original, name='derived') self.assertEqual(derived.timestamp, timestamp) self.assertEqual(derived.get(), value) self.assertEqual(derived.timestamp, timestamp) self.assertEqual(derived.describe()[derived.name]['derived_from'], original.name) new_value = 'r' derived.put(new_value) self.assertEqual(original.get(), new_value) self.assertEqual(derived.get(), new_value) self.assertEqual(derived.timestamp, original.timestamp) self.assertEqual(derived.limits, original.limits) copied = copy.copy(derived) self.assertEqual(copied.derived_from.value, original.value) self.assertEqual(copied.derived_from.timestamp, original.timestamp) self.assertEqual(copied.derived_from.name, original.name)
def __init__(self, *, name, move, get_pos, set_pos=None, stop=None, done=None, check_value=None, info=None, egu='', limits=None, update_rate=1, timeout=60, notepad_pv=None, parent=None, kind=None, **kwargs): self._check_signature('move', move, 1) self._move = move self._check_signature('get_pos', get_pos, 0) self._get_pos = get_pos self._check_signature('set_pos', set_pos, 1) self._set_pos = set_pos self._check_signature('stop', stop, 0) self._stop = stop self._check_signature('done', done, 0) self._done = done self._check_signature('check_value', check_value, 1) self._check = check_value self._info = info self._last_update = 0 self._goal = None self.update_rate = 1 notepad_name = name + '_notepad' if notepad_pv is None: self.notepad_signal = Signal(name=notepad_name) else: self.notepad_signal = EpicsSignal(notepad_pv, name=notepad_name) if parent is None and kind is None: kind = 'hinted' super().__init__(name=name, egu=egu, limits=limits, source='func', timeout=timeout, parent=parent, kind=kind, **kwargs)
def test_panel_creation(qtbot, panel, panel_widget): standard = FakeEpicsSignal('Tst:Pv', name='standard') read_and_write = FakeEpicsSignal('Tst:Read', write_pv='Tst:Write', name='read_and_write') read_only = FakeEpicsSignalRO('Tst:Pv:RO', name='read_only') simulated = SynSignal(func=random.random, name='simul') simulated_ro = SynSignalRO(func=random.random, name='simul_ro') standard.sim_put(1) read_and_write.sim_put(2) read_only.sim_put(3) simulated.put(4) signals = { # Signal is its own write 'Standard': standard, # Signal has separate write/read 'Read and Write': read_and_write, 'Read Only': read_only, 'Simulated': simulated, 'SimulatedRO': simulated_ro, 'Array': Signal(name='array', value=np.ones((5, 10))) } for name, signal in signals.items(): panel.add_signal(signal, name=name) wait_panel(qtbot, panel, signal_names=set(sig.name for sig in signals.values())) def widget_at(row, col): return panel.itemAtPosition(row, col).widget() # Check read-only channels do not have write widgets assert widget_at(2, 1) is widget_at(2, 2) assert widget_at(4, 1) is widget_at(4, 2) # Array widget has only a button, even when writable assert widget_at(5, 1) is widget_at(5, 2) # Check write widgets are present assert widget_at(0, 1) is not widget_at(0, 2) assert widget_at(1, 1) is not widget_at(1, 2) assert widget_at(3, 1) is not widget_at(3, 2) return panel_widget
def test_interface_basic(): one = Signal(name='one', kind=Kind.config) two = Signal(name='two') assert one.kind == Kind.config two_sig = TwoSignal('prefix', name='name', sig_one=one, sig_two=two) assert one.kind == Kind.hinted two_sig.sig_one.put(1) two_sig.sig_two.put(2) assert one.get() == 1 assert two.get() == 2
def test_soft_derived(): timestamp = 1.0 value = 'q' original = Signal(name='original', timestamp=timestamp, value=value) cb_values = [] def callback(value=None, **kwargs): cb_values.append(value) derived = DerivedSignal(derived_from=original, name='derived') derived.subscribe(callback, event_type=derived.SUB_VALUE) assert derived.timestamp == timestamp assert derived.get() == value assert derived.timestamp == timestamp assert derived.describe()[derived.name]['derived_from'] == original.name assert derived.write_access == original.write_access assert derived.read_access == original.read_access new_value = 'r' derived.put(new_value) assert original.get() == new_value assert derived.get() == new_value assert derived.timestamp == original.timestamp assert derived.limits == original.limits copied = copy.copy(derived) with pytest.warns(UserWarning): assert copied.derived_from.value == original.value assert copied.derived_from.timestamp == original.timestamp assert copied.derived_from.name == original.name derived.put('s') assert cb_values == ['r', 's'] called = [] event = threading.Event() def meta_callback(*, connected, read_access, write_access, **kw): called.append(('meta', connected, read_access, write_access)) event.set() derived.subscribe(meta_callback, event_type=derived.SUB_META, run=False) original._metadata['write_access'] = False original._run_subs(sub_type='meta', **original._metadata) event.wait(1) assert called == [('meta', True, True, False)]
def test_daq_during_decorator(RE, daq): """ Run a daq during scan and make sure the daq is running during it. """ logger.debug('test_daq_during_decorator') @daq_during_decorator() @bpp.run_decorator() def plan(reader): yield from bps.null() for i in range(10): assert daq.state == 'Running' yield from bps.trigger_and_read([reader]) assert daq.state == 'Running' yield from bps.null() daq.connect() RE(plan(Signal(name='sig'))) assert daq.state == 'Configured'
def test_to_interface(): SomeDeviceInterface = to_interface(SomeDevice) some = Signal(name='some') where = Signal(name='where') sdi = SomeDeviceInterface('', name='sdi', some=some, where=where) sd = SomeDevice('', name='sd') sdi.some.put(1) sdi.where.put(2) sd.some.put(3) sd.where.put(4) assert some.get() == 1 assert where.get() == 2
def test_ocpt(): sig_one = Signal(name='one', kind=Kind.config) sig_two = Signal(name='two') class ObjectDevice(Device): one = OCpt(sig_one, kind=Kind.hinted) two = OCpt(sig_two) assert sig_one.kind == Kind.config obj = ObjectDevice('prefix', name='name') assert 'one' in obj.component_names assert obj.one.kind == Kind.hinted obj.one.put(5) assert sig_one.get() == 5 obj.two.put(3) assert sig_two.get() == 3
def test_suspenders_stress(RE): """ Run scan with tons of inconvenient suspenders """ sig = Signal(name="dull signal") def pre_plan(*args, **kwargs): yield from null() logger.debug("starting suspender") def post_plan(*args, **kwargs): yield from null() logger.debug("releasing suspender") suspenders = [ SuspendFloor(sig, i, sleep=10, pre_plan=pre_plan, post_plan=post_plan) for i in range(10) ] for s in suspenders: RE.install_suspender(s) mot = SlowSoftPositioner(n_steps=1000, delay=0.001, position=0, name='test_mot') def sig_sequence(sig): sig.put(15) time.sleep(1) sig.put(9) logger.debug('expect suspend soon') time.sleep(1) sig.put(8) logger.debug('expect second suspend layer') time.sleep(1) sig.put(14) logger.debug('expect resume after 1 second') time.sleep(2) sig.put(2) logger.debug('expect many layered suspend') time.sleep(1) sig.put(15) logger.debug('expect resume after 1 second') time.sleep(2) sig.put(-10) logger.debug('expect to confuse the scan now') sig.put(10) sig.put(3) sig.put(5) sig.put(456) sig.put(0) sig.put(23) sig.put(0) sig.put(15) logger.debug('hopefully it suspended and is now waiting to resume') # 3 suspends and 3 resumes should add 6s to the scan @run_decorator() def dull_scan(mot, count, sig=None, sleep_time=0): if sig: thread = threading.Thread(target=sig_sequence, args=(sig, )) thread.start() for i in range(count): yield from checkpoint() try: yield from mv(mot, i) except: pass # make every step take 1s extra yield from sleep(sleep_time) yield from checkpoint() yield from create() yield from read(mot) yield from save() yield from checkpoint() out = [] coll = collector("test_mot", out) RE.subscribe('event', coll) base_start = time.time() RE(dull_scan(mot, 10, sleep_time=1)) base_elapsed = time.time() - base_start susp_start = time.time() RE(dull_scan(mot, 10, sig=sig, sleep_time=1)) susp_elapsed = time.time() - susp_start assert susp_elapsed - base_elapsed > 6
from bluesky.plan_stubs import move_per_step, trigger_and_read, mv from bluesky.preprocessors import stub_wrapper from dataclasses import dataclass from IPython import get_ipython import numpy from ophyd.signal import Signal import pandas import typing ip = get_ipython() # Define ``ophyd.Signal``'s that we can use to track which spectra, group and # step we are at in the scan when necessary. spectra_num = Signal(name='spectra_num') group_num = Signal(name='group_num') step_num = Signal(name='step_num') class MultiSpectraValueError(ValueError): ... class FileDataRouterValueError(ValueError): ... def _str_to_obj(str_ref): '''Converts a string ref to an ``ophyd.Device`` object reference. Parameters ---------- str_ref : str
def test_signal_base(): start_t = time.time() name = 'test' value = 10.0 signal = Signal(name=name, value=value, timestamp=start_t) signal.wait_for_connection() assert signal.connected assert signal.name == name assert signal.value == value assert signal.get() == value assert signal.timestamp == start_t info = dict(called=False) def _sub_test(**kwargs): info['called'] = True info['kw'] = kwargs signal.subscribe(_sub_test, run=False, event_type=signal.SUB_VALUE) assert not info['called'] signal.value = value signal.clear_sub(_sub_test) signal.subscribe(_sub_test, run=False, event_type=signal.SUB_VALUE) signal.clear_sub(_sub_test, event_type=signal.SUB_VALUE) kw = info['kw'] assert 'value' in kw assert 'timestamp' in kw assert 'old_value' in kw assert kw['value'] == value assert kw['old_value'] == value assert kw['timestamp'] == signal.timestamp # readback callback for soft signal info = dict(called=False) signal.subscribe(_sub_test, event_type=Signal.SUB_VALUE, run=False) assert not info['called'] signal.put(value + 1) assert info['called'] signal.clear_sub(_sub_test) kw = info['kw'] assert 'value' in kw assert 'timestamp' in kw assert 'old_value' in kw assert kw['value'] == value + 1 assert kw['old_value'] == value assert kw['timestamp'] == signal.timestamp signal.trigger() signal.read() signal.describe() signal.read_configuration() signal.describe_configuration() eval(repr(signal))
def test_describe(bool_enum_signal): sig = bool_enum_signal sig.put(1) desc = sig.describe()['bool_enum'] assert desc['dtype'] == 'integer' assert desc['shape'] == [] # assert 'precision' in desc assert desc['enum_strs'] == ('Off', 'On') assert 'upper_ctrl_limit' in desc assert 'lower_ctrl_limit' in desc sig = Signal(name='my_pv') sig.put('Off') desc = sig.describe()['my_pv'] assert desc['dtype'] == 'string' assert desc['shape'] == [] sig.put(3.14) desc = sig.describe()['my_pv'] assert desc['dtype'] == 'number' assert desc['shape'] == [] import numpy as np sig.put(np.array([ 1, ])) desc = sig.describe()['my_pv'] assert desc['dtype'] == 'array' assert desc['shape'] == [ 1, ]
def test_signal_widget_waveform(qtbot): signal = Signal(name='test_wave', value=np.zeros((4, ))) widget = create_signal_widget(signal) qtbot.addWidget(widget) assert isinstance(widget, WaveformDialogButton) return widget
def test_avg_signal(): logger.debug('test_avg_signal') sig = Signal(name='raw') avg = AvgSignal(sig, 2, name='avg') assert avg.averages == 2 sig.put(1) assert avg.get() == 1 sig.put(3) assert avg.get() == 2 sig.put(2) assert avg.get() == 2.5 avg.averages = 3 sig.put(1) assert avg.get() == 1 sig.put(3) assert avg.get() == 2 sig.put(2) assert avg.get() == 2 cb = Mock() avg.subscribe(cb) sig.put(0) assert cb.called
def test_signal_widget_image(qtbot): signal = Signal(name='test_img', value=np.zeros((400, 540))) widget = create_signal_widget(signal) qtbot.addWidget(widget) assert isinstance(widget, ImageDialogButton) return widget
def test_signal_base(self): start_t = time.time() name = 'test' value = 10.0 signal = Signal(name=name, value=value, timestamp=start_t) signal.wait_for_connection() self.assertTrue(signal.connected) self.assertEquals(signal.name, name) self.assertEquals(signal.value, value) self.assertEquals(signal.get(), value) self.assertEquals(signal.timestamp, start_t) info = dict(called=False) def _sub_test(**kwargs): info['called'] = True info['kw'] = kwargs signal.subscribe(_sub_test, run=False) self.assertFalse(info['called']) signal.value = value signal.clear_sub(_sub_test) signal.subscribe(_sub_test, run=False) signal.clear_sub(_sub_test, event_type=signal.SUB_VALUE) kw = info['kw'] self.assertIn('value', kw) self.assertIn('timestamp', kw) self.assertIn('old_value', kw) self.assertEquals(kw['value'], value) self.assertEquals(kw['old_value'], value) self.assertEquals(kw['timestamp'], signal.timestamp) # readback callback for soft signal info = dict(called=False) signal.subscribe(_sub_test, event_type=Signal.SUB_VALUE, run=False) self.assertFalse(info['called']) signal.put(value + 1) self.assertTrue(info['called']) signal.clear_sub(_sub_test) kw = info['kw'] self.assertIn('value', kw) self.assertIn('timestamp', kw) self.assertIn('old_value', kw) self.assertEquals(kw['value'], value + 1) self.assertEquals(kw['old_value'], value) self.assertEquals(kw['timestamp'], signal.timestamp) signal.trigger() signal.read() signal.describe() signal.read_configuration() signal.describe_configuration() eval(repr(signal))
def set(self, value, *, timestamp=None, force=False): return Signal.set(self, value, timestamp=timestamp, force=force)