def test_rank_models(): RE = RunEngine() # Create accurate fit motor = SynAxis(name='motor') det = SynSignal(name='centroid', func=lambda: 5 * motor.read()['motor']['value'] + 2) fit1 = LinearFit('centroid', 'motor', update_every=None, name='Accurate') RE(scan([det], motor, -1, 1, 50), fit1) # Create inaccurate fit det2 = SynSignal(name='centroid', func=lambda: 25 * motor.read()['motor']['value'] + 2) fit2 = LinearFit('centroid', 'motor', update_every=None, name='Inaccurate') RE(scan([det2], motor, -1, 1, 50), fit2) # Create inaccurate fit det3 = SynSignal(name='centroid', func=lambda: 12 * motor.read()['motor']['value'] + 2) fit3 = LinearFit('centroid', 'motor', update_every=None, name='Midly Inaccurate') RE(scan([det3], motor, -1, 1, 50), fit3) # Rank models ranking = rank_models([fit2, fit1, fit3], target=22, x=4) assert ranking[0] == fit1 assert ranking[1] == fit3 assert ranking[2] == fit2
def run_exp(delay): # pragma: no cover time.sleep(delay) print("running exp") p = Publisher(proxy[0], prefix=b"raw") RE.subscribe(p) z = np.zeros(10) z[3] = 1 x = SynSignal(func=lambda: np.arange(10), name="x") y = SynSignal(func=lambda: z, name="y") RE(bp.count([x, y], md=dict(analysis_stage="raw")))
def test_multi_fit(): RE = RunEngine() # Expected values of fit expected = {'x0': 5, 'x1': 4, 'x2': 3} m1 = SynAxis(name='m1') m2 = SynAxis(name='m2') det = SynSignal(name='centroid', func=lambda: 5 + 4 * m1.read()['m1']['value'] + 3 * m2. read()['m2']['value']) # Assemble fitting callback cb = MultiPitchFit('centroid', ('m1', 'm2'), update_every=None) RE(outer_product_scan([det], m1, -1, 1, 10, m2, -1, 1, 10, False), cb) # Check accuracy of fit logger.debug(cb.result.fit_report()) for k, v in expected.items(): assert np.allclose(cb.result.values[k], v, atol=1e-6) # Check we create an accurate estimate assert np.allclose(cb.eval(a0=5, a1=10), 55, atol=1e-5) assert np.allclose(cb.backsolve(55, a1=10)['a0'], 5, atol=1e-5) assert np.allclose(cb.backsolve(55, a0=5)['a1'], 10, atol=1e-5)
def test_panel_creation(qtbot): panel = SignalPanel( signals={ # Signal is its own write 'Standard': EpicsSignal('Tst:Pv'), # Signal has separate write/read 'Read and Write': EpicsSignal('Tst:Read', write_pv='Tst:Write'), # Signal is read-only 'Read Only': EpicsSignalRO('Tst:Pv:RO'), # Simulated Signal 'Simulated': SynSignal(name='simul'), 'SimulatedRO': SynSignalRO(name='simul_ro') }) widget = QWidget() qtbot.addWidget(widget) widget.setLayout(panel) assert len(panel.signals) == 5 # Check read-only channels do not have write widgets panel.layout().itemAtPosition(2, 1).layout().count() == 1 panel.layout().itemAtPosition(4, 1).layout().count() == 1 # Check write widgets are present panel.layout().itemAtPosition(0, 1).layout().count() == 2 panel.layout().itemAtPosition(1, 1).layout().count() == 2 panel.layout().itemAtPosition(3, 1).layout().count() == 2 return panel
def test_full_field_tomo_pipeline(RE, hw, db): L = [] rr = RunRouter([ lambda x: tomo_callback_factory(x, publisher=lambda *x: L.append(x), handler_reg=db.reg.handler_reg) ]) RE.subscribe(rr) direct_img = SynSignal( func=lambda: np.array(np.random.random((10, 10))), name="img", labels={"detectors"}, ) RE( bp.scan( [direct_img], hw.motor1, 0, 180, 30, md={ "tomo": { "type": "full_field", "rotation": "motor1", "center": 0.0, } }, )) # det1 # sinogram and recon # 30 events + start, stop, descriptor assert len(L) == (30 + 2 + 1 + 2) * 2 assert len(L[7][1]["data"]["img_tomo"].shape) == 3 assert len(L[6][1]["data"]["img_sinogram"].shape) == 3
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 run_exp(delay): # pragma: no cover time.sleep(delay) print("running exp") p = Publisher(proxy[0], prefix=b"raw") RE.subscribe(p) det = SynSignal(func=lambda: np.ones(10), name="gr") RE(bp.count([det], md=dict(analysis_stage="raw"))) RE(bp.count([det], md=dict(analysis_stage="pdf")))
def generate_simulation(motor_column, signal_column, dataframe, motor_precision=3, random_state=None): """ Generate a simulation based on a provided DataFrame. Use collected data to simulate the relationship between a single input and output variable. A `SynAxis` object will be returned that can be set to a specified precision. The value of the dependent variable is then determined by finding the closest position of the motor we have recorded and returning the corresponding value. If multiple readings were taken at this position one is randomly chosen. Parameters ---------- motor_column : str The column of data that will be used as the independent variable. Will also be the name of the created motor. signal_column : str The name of the column to be the dependent variable. Will also be the name of the created signal. dataframe : pandas.DataFrame Data to use in simulation. motor_precision : int, optional Limit the accuracy of the simulated motor. random_state : np.random.RandomState, optional Seed the simulation. Returns ------- namespace : types.SimpleNamespace A namespace with attributes ``motor``, ``signal``, and ``data``. """ # Create our motor that will serve as the independent variable motor = SynAxis(name=motor_column, precision=motor_precision) ns = types.SimpleNamespace(data=dataframe, motor=motor) random_state = random_state or np.random.RandomState(0) # Create a function to return a random value from closest motor position def func(): motor_positions = ns.data[motor_column].unique() sim_data = dict(iter(ns.data.groupby(motor_column))) pos = ns.motor.position closest_position = motor_positions[np.abs(motor_positions - pos).argmin()] return random_state.choice(sim_data[closest_position][signal_column]) ns.signal = SynSignal(name=signal_column, func=func) return ns
def test_fitwalk(RE): # Create simulated devices motor = SynAxis(name='motor') det = SynSignal(name='centroid', func=lambda: 5*motor.read()['motor']['value'] + 2) linear = LinearFit('centroid', 'motor', average=1) parabola = ParabolicFit('centroid', 'motor', average=1) walk = fitwalk([det], motor, [parabola, linear], 89.4, average=1, tolerance=0.5) RE(run_wrapper(walk)) assert np.isclose(det.read()['centroid']['value'], 89.4, 0.5)
def test_walk_to_pixel(RE, one_bounce_system): logger.debug("test_walk_to_pixel") _, mot, det = one_bounce_system ########################## # Test on simple devices # ########################## simple_motor = SynAxis(name='motor') simple_det = SynSignal(name='det', func=lambda: 5*simple_motor.read()['motor']['value'] + 2) # Naive step plan = run_wrapper(walk_to_pixel(simple_det, simple_motor, 200, 0, first_step=1e-6, tolerance=10, average=None, target_fields=['det', 'motor'], max_steps=3)) RE(plan) assert np.isclose(simple_det.read()['det']['value'], 200, atol=1) simple_motor.set(0.) # Gradient simple_motor = SynAxis(name='motor') simple_det = SynSignal(name='det', func=lambda: 5*simple_motor.read()['motor']['value'] + 2) plan = run_wrapper(walk_to_pixel(simple_det, simple_motor, 200, 0, gradient=1.6842e+06, tolerance=10, average=None, target_fields=['det', 'motor'], max_steps=3)) RE(plan) assert np.isclose(simple_det.read()['det']['value'], 200, atol=1) ########################## # Test on full model # ########################## # Naive step cent = 'detector_stats2_centroid_x' plan = run_wrapper(walk_to_pixel(det, mot, 200, 0, first_step=1e-6, tolerance=10, average=None, target_fields=[cent, 'sim_alpha'], max_steps=3)) RE(plan) assert np.isclose(det.read()[det.name + "_" + cent]['value'], 200, atol=1) mot.set(0.) # Gradient plan = run_wrapper(walk_to_pixel(det, mot, 200, 0, gradient=1.6842e+06, tolerance=10, average=None, target_fields=[cent, 'sim_alpha'], max_steps=3)) RE(plan) assert np.isclose(det.read()[det.name + "_" + cent]['value'], 200, atol=10)
def test_measure(RE): # Simplest implementation plan = run_wrapper(measure([det, motor], num=5, delay=0.01)) # Fake callback storage shots = list() cb = collector('det', shots) # Run simple RE(plan, {'event': cb}) assert shots == [1.0, 1.0, 1.0, 1.0, 1.0] # Create counting detector index = -1 def count(): nonlocal index index += 1 return index counter = SynSignal(name='intensity', func=count) # Filtered implementation plan = run_wrapper(measure([counter], filters={'intensity': lambda x: x > 2}, num=5)) # Fake callback storage shots = list() cb = collector('intensity', shots) # Run filtered RE(plan, {'event': cb}) assert shots == [1, 2, 3, 4, 5, 6, 7] # Make sure an exception is raised when we fail too many filter checks plan = run_wrapper(measure([counter], filters={'intensity': lambda x: False}, num=500)) with pytest.raises(FilterCountError): RE(plan)
def test_linear_fit(): RE = RunEngine() # Expected values of fit expected = {'slope': 5, 'intercept': 2} motor = SynAxis(name='motor') det = SynSignal(name='centroid', func=lambda: 5 * motor.read()['motor']['value'] + 2) # Assemble fitting callback cb = LinearFit('centroid', 'motor', update_every=None) RE(scan([det], motor, -1, 1, 50), cb) # Check accuracy of fit for k, v in expected.items(): assert np.allclose(cb.result.values[k], v, atol=1e-6) # Check we create an accurate estimate assert np.allclose(cb.eval(x=10), 52, atol=1e-5) assert np.allclose(cb.eval(motor=10), 52, atol=1e-5) assert np.allclose(cb.backsolve(52)['x'], 10, atol=1e-5)
def run_exp(delay): # pragma: no cover time.sleep(delay) print("running exp") p = Publisher(proxy[0], prefix=b"an") RE.subscribe(p) det = SynSignal(func=lambda: np.ones((10, 10)), name="gr") RE( bp.scan( [det], hw.motor1, 0, 2, 2, md={ "tomo": { "type": "full_field", "rotation": "motor1", "center": 1, } }, ))
Returns ------- Document generator. """ yield from count(detectors, num) def add_noise(image: np.array): # Applies random 0 or 1 noise to the image return np.random.rand(*image.shape).round() + image test_file = '../assets/clyde.jpg' im = image_array(test_file) direct_img = SynSignal(func=partial(add_noise, im), name='img', labels={'detectors'}) DETECTORS = [direct_img] NUM = 10 RE = RunEngine() # Create a temporary /tmp directory to store our msgpack directory = tempfile.TemporaryDirectory().name # Define metadata for the plan md = {'detectors': [det.name for det in DETECTORS], 'num_steps': NUM, 'plan_args': {'detectors': list(map(repr, DETECTORS)), 'num': NUM}, 'plan_name': 'test_count'} with Serializer(directory) as serializer:
from glob import glob from pathlib import Path import numpy from ophyd.sim import SynSignal, SynAxis import pandas for filename in glob(str(Path(__file__).parent / "data" / "pitch_vs_I0" / "*.csv")): # Grab the first file. Maybe later take a random one. # Each one is at a different energy, so it would not make sense to concat them. data = pandas.read_csv(filename) break def compute_I0(): return numpy.interp(pitch.readback.get(), data["dcm_pitch"], data["I0"]) pitch = SynAxis(name="pitch") pitch.set(4).wait() # initialize at a reasonable value pitch.delay = 0.05 # to simulate movement time I0 = SynSignal(name="I0", func=compute_I0)
def test_monitor(RE, hw): from ophyd.sim import SynSignal signal = SynSignal(name='signal') signal.put(0.0) RE(monitor_during_wrapper(count([hw.det], 5), [signal]))
plt.ion() # Create a RunEngine RE = RunEngine() # Use BestEffortCallback for nice vizualizations during scans bec = BestEffortCallback() # Install our notebook kicker to have plots update during a scan install_nb_kicker() if args.sim: # Create our motors x_motor = SynAxis(name='x') y_motor = SynAxis(name='y') #Defines relationships between centroids and motors x_centroid = SynSignal(func=partial(centroid_from_motor_cross, x_motor, y_motor, noise_scale=1), name='x_syn') y_centroid = SynSignal(func=partial(centroid_from_motor_cross, y_motor, x_motor), name='y_syn') print('Running Simulated Scan') else: #The Newport motors x_motor = Newport('XPP:LAS:MMN:13', name='real_x') y_motor = Newport('XPP:LAS:MMN:14', name='real_y') #Readback from actual beamline devices x_centroid = EpicsSignalRO('XPP:OPAL1K:01:Stats2:CentroidX_RBV', name='x_readback') y_centroid = EpicsSignalRO('XPP:OPAL1K:01:Stats2:CentroidY_RBV', name='y_readback')
yield from wait(group=grp) motors = step.keys() yield from move() plt.pause(.001) yield from trigger_and_read(list(detectors) + list(motors)) install_kicker() p = Publisher(glbl_dict["inbound_proxy_address"]) hw = hw() import numpy as np rand_img = SynSignal( func=lambda: np.array(np.random.random((10, 10))), name="img", labels={"detectors"}, ) RE = RunEngine() # build the pipeline raw_source = Stream() raw_output = SimpleFromEventStream("event", ("data", "det_a"), raw_source, principle=True) raw_output2 = SimpleFromEventStream("event", ("data", "noisy_det"), raw_source) raw_output3 = SimpleFromEventStream("event", ("data", "img"), raw_source) pipeline = (raw_output.union(raw_output2, raw_output3.map( np.sum)).map(lambda x: x**2).accumulate(lambda x, y: x + y)) res = SimpleToEventStream(pipeline, ("result", ))
def current_intensity_peaks(): amplitude = 0.5 width = 0.004 # degrees wavelength = 12.398 / 66.4 # angtroms two_theta = motor1.read()['motor1']['value'] # degrees theta = np.deg2rad(two_theta / 2) # radians return intensity(theta, amplitude, np.deg2rad(width), wavelength) def current_intensity_dips(): amplitude = 0.5 width = 0.004 # degrees wavelength = 12.398 / 66.4 # angtroms hw_theta = motor1.read()['motor1']['value'] # degrees theta = np.deg2rad(hw_theta + 35.26) # radians return -intensity(theta, amplitude, np.deg2rad(width), wavelength) + 10000 th_cal = motor1 sc = SynSignal(name="det", func=current_intensity_dips) ''' test sim motors import bluesky.plan_stubs as bps import bluesky.plans as bp from bluesky.callbacks import LivePlot def myplan(): yield from bps.abs_set(motor1, 0) yield from bp.rel_scan([det_6peaks], motor1, -10, 10, 1000) RE(myplan(), LivePlot('det_6peaks', 'motor1')) '''
def sig(): sig = SynSignal(name='test') sig.put(0) return sig
from suitcase.jsonl import Serializer from bluesky import RunEngine from ophyd.sim import det, det4, noisy_det, motor, motor1, motor2, img from bluesky.plans import scan, count, grid_scan from bluesky.preprocessors import SupplementalData from event_model import RunRouter from ophyd.sim import SynSignal import numpy as np det.kind = 'hinted' noisy_det.kind = 'hinted' det4.kind = 'hinted' log = logging.getLogger('bluesky_browser') random_img = SynSignal(func=lambda: np.random.random((5, 10, 10)), name='random_img') def generate_example_catalog(data_path): data_path = Path(data_path) def factory(name, doc): serializer = Serializer(data_path / 'abc') serializer('start', doc) return [serializer], [] RE = RunEngine() sd = SupplementalData() RE.preprocessors.append(sd) sd.baseline.extend([motor1, motor2]) rr = RunRouter([factory])
def linear(): motor = SynAxis(name='motor') # Make our linear detector sig = SynSignal(func=lambda: 4 * motor.position, name='det') return (sig, motor)