def test_per_step(RE, hw): # Check default behavior, using one motor and then two. RE(scan([hw.det], hw.motor, -1, 1, 3, per_step=one_nd_step)) RE( scan([hw.det], hw.motor, -1, 1, hw.motor2, -1, 1, 3, per_step=one_nd_step)) RE(inner_product_scan([hw.det], 3, hw.motor, -1, 1, per_step=one_nd_step)) RE( inner_product_scan([hw.det], 3, hw.motor, -1, 1, hw.motor2, -1, 1, per_step=one_nd_step)) # Check that scan still accepts old one_1d_step signature: RE(scan([hw.det], hw.motor, -1, 1, 3, per_step=one_1d_step)) RE(rel_scan([hw.det], hw.motor, -1, 1, 3, per_step=one_1d_step)) # Test that various error paths include a useful error message identifying # that the problem is with 'per_step': # You can't usage one_1d_step signature with more than one motor. with pytest.raises(TypeError) as excinfo: RE( scan([hw.det], hw.motor, -1, 1, hw.motor2, -1, 1, 3, per_step=one_1d_step)) assert excinfo.match("Signature of per_step assumes 1D trajectory") # The signature must be either like one_1d_step or one_nd_step: def bad_sig(detectors, mtr, step): ... with pytest.raises(TypeError) as excinfo: RE(scan([hw.det], hw.motor, -1, 1, 3, per_step=bad_sig)) assert excinfo.match("per_step must be a callable with the signature")
def _make_plan_marker(): args = [] ids = [] ## args.append( (bp.outer_product_scan([det], motor, 1, 2, 3, motor1, 4, 5, 6, True, motor2, 7, 8, 9, True), { 'motors': ('motor', 'motor1', 'motor2'), 'extents': ([1, 2], [4, 5], [7, 8]), 'shape': (3, 6, 9), 'snaking': (False, True, True), 'plan_pattern_module': 'bluesky.plan_patterns', 'plan_pattern': 'outer_product', 'plan_name': 'outer_product_scan' })) ids.append('outer_product_scan') ## args.append((bp.inner_product_scan([det], 9, motor, 1, 2, motor1, 4, 5, motor2, 7, 8), { 'motors': ('motor', 'motor1', 'motor2') })) ids.append('inner_product_scan') return pytest.mark.parametrize('plan,target', args, ids=ids)
def a2_scan(num, *args, wait=None, md=None, **kwargs): """Performs a multi-motor scan on a linear trajectory, waiting the specified amount of time at each step. Parameters ---------- num : integer number of steps ``*args`` : {Positioner, Positioner, int} patterned like (``motor1, start1, stop1, ..., motorN, startN, stopN``) Motors can be any 'setable' object (motor, temp controller, etc.) wait : int, optional The amount of time to wait at each step. md : dict, optional metadata """ # Define what to do at each step def per_step(detectors, motor, step): for m, pos in motor.items(): print("Moving '{0}' to {1}".format(m.name, pos)) yield from one_nd_step([], motor, step) if wait is not None: print("Step complete! Waiting for {0} second(s)...\n".format(wait)) time.sleep(wait) # Run the inner product scan yield from inner_product_scan([], num, *args, per_step=per_step, md=md, **kwargs)
def test_plan_header(RE, hw): args = [] ## args.append((bp.grid_scan([hw.det], hw.motor, 1, 2, 3, hw.motor1, 4, 5, 6, hw.motor2, 7, 8, 9, snake_axes=True), {'motors': ('motor', 'motor1', 'motor2'), 'extents': ([1, 2], [4, 5], [7, 8]), 'shape': (3, 6, 9), 'snaking': (False, True, True), 'plan_pattern_module': 'bluesky.plan_patterns', 'plan_pattern': 'outer_product', 'plan_name': 'grid_scan'})) ## args.append((bp.inner_product_scan([hw.det], 9, hw.motor, 1, 2, hw.motor1, 4, 5, hw.motor2, 7, 8), {'motors': ('motor', 'motor1', 'motor2')})) for plan, target in args: c = DocCollector() RE(plan, c.insert) for s in c.start: _validate_start(s, target)
def test_plan_header(RE, hw): args = [] ## args.append((bp.grid_scan([hw.det], hw.motor, 1, 2, 3, hw.motor1, 4, 5, 6, True, hw.motor2, 7, 8, 9, True), {'motors': ('motor', 'motor1', 'motor2'), 'extents': ([1, 2], [4, 5], [7, 8]), 'shape': (3, 6, 9), 'snaking': (False, True, True), 'plan_pattern_module': 'bluesky.plan_patterns', 'plan_pattern': 'outer_product', 'plan_name': 'grid_scan'})) ## args.append((bp.inner_product_scan([hw.det], 9, hw.motor, 1, 2, hw.motor1, 4, 5, hw.motor2, 7, 8), {'motors': ('motor', 'motor1', 'motor2')})) for plan, target in args: c = DocCollector() RE(plan, c.insert) for s in c.start: _validate_start(s, target)
def test_per_step(RE, hw): # Check default behavior, using one motor and then two. RE(scan([hw.det], hw.motor, -1, 1, 3, per_step=one_nd_step)) RE(scan([hw.det], hw.motor, -1, 1, hw.motor2, -1, 1, 3, per_step=one_nd_step)) RE(inner_product_scan([hw.det], 3, hw.motor, -1, 1, per_step=one_nd_step)) RE(inner_product_scan([hw.det], 3, hw.motor, -1, 1, hw.motor2, -1, 1, per_step=one_nd_step)) # Check that scan still accepts old one_1d_step signature: RE(scan([hw.det], hw.motor, -1, 1, 3, per_step=one_1d_step)) RE(rel_scan([hw.det], hw.motor, -1, 1, 3, per_step=one_1d_step)) # Test that various error paths include a useful error message identifying # that the problem is with 'per_step': # You can't usage one_1d_step signature with more than one motor. with pytest.raises(TypeError) as exc: RE(scan([hw.det], hw.motor, -1, 1, hw.motor2, -1, 1, 3, per_step=one_1d_step)) assert "Signature of per_step assumes 1D trajectory" in str(exc) # The signature must be either like one_1d_step or one_nd_step: def bad_sig(detectors, mtr, step): ... with pytest.raises(TypeError) as exc: RE(scan([hw.det], hw.motor, -1, 1, 3, per_step=bad_sig)) assert "per_step must be a callable with the signature" in str(exc)
def test_inner_product_ascan(RE, hw): scan = bp.inner_product_scan([hw.det], 3, hw.motor1, 1, 3, hw.motor2, 10, 30) # Note: motor1 is the first motor specified, and so it is the "slow" # axis, matching the numpy convention. expected_data = [ {'motor2': 10.0, 'det': 1.0, 'motor1': 1.0}, {'motor2': 20.0, 'det': 1.0, 'motor1': 2.0}, {'motor2': 30.0, 'det': 1.0, 'motor1': 3.0}] for d in expected_data: d.update({'motor1_setpoint': d['motor1']}) d.update({'motor2_setpoint': d['motor2']}) multi_traj_checker(RE, scan, expected_data)
def test_plotting_hints(RE, hw, db): ''' This tests the run and checks that the correct hints are created. Hints are mainly created to help the BestEffortCallback in plotting the data. Use a callback to do the checking. ''' dc = DocCollector() RE.subscribe(dc.insert) # check that the inner product hints are passed correctly hint = { 'dimensions': [([hw.motor1.name, hw.motor2.name, hw.motor3.name], 'primary')] } RE( inner_product_scan([hw.det], 20, hw.motor1, -1, 1, hw.motor2, -1, 1, hw.motor3, -2, 0)) assert dc.start[-1]['hints'] == hint # check that the outer product (grid_scan) hints are passed correctly hint = { 'dimensions': [(['motor1'], 'primary'), (['motor2'], 'primary'), (['motor3'], 'primary')] } # grid_scan passes "rectilinear" gridding as well # make sure this is also passed output_hint = hint.copy() output_hint['gridding'] = 'rectilinear' RE( grid_scan([hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True)) assert dc.start[-1]['hints'] == output_hint # check that if gridding is supplied, it's not overwritten by grid_scan # check that the outer product (grid_scan) hints are passed correctly hint = { 'dimensions': [(['motor1'], 'primary'), (['motor2'], 'primary'), (['motor3'], 'primary')], 'gridding': 'rectilinear' } RE( grid_scan([hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True)) assert dc.start[-1]['hints'] == hint
def test_round_trip_from_run_engine(db_all, RE): from bluesky.plans import count, scan, relative_scan, inner_product_scan from bluesky.examples import motor, det, motor1 fname = tempfile.NamedTemporaryFile().name cb = spec.DocumentToSpec(fname) RE.subscribe(cb) RE(scan([det], motor, -1, 1, 10), owner="Tom") RE(relative_scan([det], motor, -1, 1, 10)) RE(count([det])) RE(inner_product_scan([det], 10, motor, -1, 1, motor1, -1, 1)) sf = spec.Specfile(fname) sf1 = _round_trip(sf, db_all) # a2scan is not round trippable num_unconvertable_scans = 1 assert len(sf) == (len(sf1) + num_unconvertable_scans)
def test_plotting_hints(RE, hw, db): ''' This tests the run and checks that the correct hints are created. Hints are mainly created to help the BestEffortCallback in plotting the data. Use a callback to do the checking. ''' dc = DocCollector() RE.subscribe(dc.insert) # check that the inner product hints are passed correctly hint = {'dimensions': [([hw.motor1.name, hw.motor2.name, hw.motor3.name], 'primary')]} RE(inner_product_scan([hw.det], 20, hw.motor1, -1, 1, hw.motor2, -1, 1, hw.motor3, -2, 0)) assert dc.start[-1]['hints'] == hint # check that the outer product (grid_scan) hints are passed correctly hint = {'dimensions': [(['motor1'], 'primary'), (['motor2'], 'primary'), (['motor3'], 'primary')]} # grid_scan passes "rectilinear" gridding as well # make sure this is also passed output_hint = hint.copy() output_hint['gridding'] = 'rectilinear' RE(grid_scan([hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True)) assert dc.start[-1]['hints'] == output_hint # check that if gridding is supplied, it's not overwritten by grid_scan # check that the outer product (grid_scan) hints are passed correctly hint = {'dimensions': [(['motor1'], 'primary'), (['motor2'], 'primary'), (['motor3'], 'primary')], 'gridding': 'rectilinear'} RE(grid_scan([hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True)) assert dc.start[-1]['hints'] == hint
def _gen(self): return inner_product_scan(self.detectors, self.num, *self.args, md=self.md)
RE.subscribe(bec) RE.subscribe(db.insert) # move motor to a reproducible location RE(mov(motor1, 0)) RE(mov(motor2, 0)) RE( relative_outer_product_scan([det4], motor1, -1, 0, 10, motor2, -2, 0, 20, True)) RE(outer_product_scan([det4], motor1, -1, 0, 10, motor2, -2, 0, 20, True)) # move motor to a reproducible location RE(mov(motor1, 0)) RE(mov(motor2, 0)) RE(relative_inner_product_scan([det4], 10, motor1, -1, 0, motor2, -2, 0)) RE(inner_product_scan([det4], 10, motor1, -1, 0, motor2, -2, 0)) # do it manually from cycler import cycler mot1_cycl = cycler(motor1, np.linspace(-1, 0, 10)) mot2_cycl = cycler(motor2, np.linspace(-2, 0, 10)) # inner product inner_hints = { 'fields': [det4.name], 'dimensions': [([motor1.name, motor2.name], 'primary')] } RE(scan_nd([det4], mot1_cycl + mot2_cycl), hints=inner_hints) # outer product
def test_plotting_hints(RE, hw, db): """ This tests the run and checks that the correct hints are created. Hints are mainly created to help the BestEffortCallback in plotting the data. Use a callback to do the checking. """ dc = DocCollector() RE.subscribe(dc.insert) # check that the inner product hints are passed correctly hint = { "dimensions": [([hw.motor1.name, hw.motor2.name, hw.motor3.name], "primary")] } RE( inner_product_scan([hw.det], 20, hw.motor1, -1, 1, hw.motor2, -1, 1, hw.motor3, -2, 0)) assert dc.start[-1]["hints"] == hint # check that the outer product (grid_scan) hints are passed correctly hint = { "dimensions": [ (["motor1"], "primary"), (["motor2"], "primary"), (["motor3"], "primary"), ] } # grid_scan passes "rectilinear" gridding as well # make sure this is also passed output_hint = hint.copy() output_hint["gridding"] = "rectilinear" RE( grid_scan( [hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True, )) assert dc.start[-1]["hints"] == output_hint # check that if gridding is supplied, it's not overwritten by grid_scan # check that the outer product (grid_scan) hints are passed correctly hint = { "dimensions": [ (["motor1"], "primary"), (["motor2"], "primary"), (["motor3"], "primary"), ], "gridding": "rectilinear", } RE( grid_scan( [hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True, )) assert dc.start[-1]["hints"] == hint
def test_plotting_hints(RE, hw, db): """ This tests the run and checks that the correct hints are created. Hints are mainly created to help the BestEffortCallback in plotting the data. Use a callback to do the checking. """ dc = DocCollector() RE.subscribe(dc.insert) # check that the inner product hints are passed correctly hint = { "dimensions": [ ([hw.motor1.name, hw.motor2.name, hw.motor3.name], "primary") ] } RE( inner_product_scan( [hw.det], 20, hw.motor1, -1, 1, hw.motor2, -1, 1, hw.motor3, -2, 0 ) ) assert dc.start[-1]["hints"] == hint # check that the outer product (grid_scan) hints are passed correctly hint = { "dimensions": [ (["motor1"], "primary"), (["motor2"], "primary"), (["motor3"], "primary"), ] } # grid_scan passes "rectilinear" gridding as well # make sure this is also passed output_hint = hint.copy() output_hint["gridding"] = "rectilinear" RE( grid_scan( [hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True, ) ) assert dc.start[-1]["hints"] == output_hint # check that if gridding is supplied, it's not overwritten by grid_scan # check that the outer product (grid_scan) hints are passed correctly hint = { "dimensions": [ (["motor1"], "primary"), (["motor2"], "primary"), (["motor3"], "primary"), ], "gridding": "rectilinear", } RE( grid_scan( [hw.det], hw.motor1, -1, 1, 2, hw.motor2, -1, 1, 2, True, hw.motor3, -2, 0, 2, True, ) ) assert dc.start[-1]["hints"] == hint
# move motor to a reproducible location RE(mov(motor1, 0)) RE(mov(motor2, 0)) RE(relative_outer_product_scan([det4], motor1, -1, 0, 10, motor2, -2, 0, 20, True)) RE(outer_product_scan([det4], motor1, -1, 0, 10, motor2, -2, 0, 20, True)) # move motor to a reproducible location RE(mov(motor1, 0)) RE(mov(motor2, 0)) RE(relative_inner_product_scan([det4], 10, motor1, -1, 0, motor2, -2, 0)) RE(inner_product_scan([det4], 10, motor1, -1, 0, motor2, -2, 0)) # do it manually from cycler import cycler mot1_cycl = cycler(motor1, np.linspace(-1, 0, 10)) mot2_cycl = cycler(motor2, np.linspace(-2, 0, 10)) # inner product inner_hints = {'fields' : [det4.name], 'dimensions' : [ ([motor1.name, motor2.name],'primary')]} RE(scan_nd([det4], mot1_cycl+mot2_cycl), hints=inner_hints)
def e_inner_scan(*args, **kwargs): return (yield from bp.inner_product_scan(*args, per_step=one_nd_step_pseudo_shutter, **kwargs))
def c_inner_scan(*args, **kwargs): return (yield from bp.inner_product_scan(*args, per_step=one_nd_step_check_beam, **kwargs))
def a2_daq_scan(daq, num, *args, events_per_point=1000, record=False, controls=None, wait=None, md=None, **kwargs): """Performs an a2 scan and takes daq events at each step. Parameters ---------- daq : Daq DAQ instance to use. Must be running and allocated for the scan to work. num : int number of steps ``*args`` : {Positioner, Positioner, int} patterned like (``motor1, start1, stop1, ..., motorN, startN, stopN``) Motors can be any 'setable' object (motor, temp controller, etc.) events_per_point : int, optional Number of daq events to take at each step of the scan. record : bool, optional Record the data as a DAQ run. controls : dict, optional Dictionary containing the EPICS pvs to record in the DAQ. Has the form: {"motor_name" : motor.position} wait : int, optional The amount of time to wait at each step. md : dict, optional metadata """ events = events_per_point # Define what to do at each step def per_step(detectors, motor, step): for m, pos in motor.items(): print("Moving '{0}' to {1}".format(m.name, pos)) yield from one_nd_step([], motor, step) if wait is not None: print("Step complete! Waiting for {0} second(s)...\n".format(wait)) time.sleep(wait) # Take daq events daq.begin(events=events, controls=controls) print('Waiting for {} events ...\n'.format(events)) daq.wait() try: # Connect and configure the daq daq.connect() daq.configure(record=record, controls=controls) if not daq.connected: raise Exception("Could not connect to the Daq!") # Run the inner product scan print("Established DAQ connection, beginning scan.") yield from inner_product_scan([], num, *args, per_step=per_step, md=md, **kwargs) finally: print("Completed scan, ending DAQ run.") daq.end_run() daq.disconnect()
def a2scan(dets, *args, time=None, md=None): args, time = _get_a2_args(*args, time=time) total_points = int(args[-1]) yield from _pre_scan(dets, total_points=total_points, count_time=time) return (yield from plans.inner_product_scan(dets, *args, md=md, per_step=one_nd_step))