def test_live_grid(fresh_RE): RE = fresh_RE motor1._fake_sleep = 0 motor2._fake_sleep = 0 RE(outer_product_scan([det4], motor1, -3, 3, 6, motor2, -5, 5, 10, False), LiveGrid((6, 10), 'det4')) # Test the deprecated name. RE(outer_product_scan([det4], motor1, -3, 3, 6, motor2, -5, 5, 10, False), LiveRaster((6, 10), 'det4'))
def test_live_fit_multidim(fresh_RE): RE = fresh_RE try: import lmfit except ImportError: raise pytest.skip('requires lmfit') motor1._fake_sleep = 0 motor2._fake_sleep = 0 det4.exposure_time = 0 def gaussian(x, y, A, sigma, x0, y0): return A * np.exp(-((x - x0)**2 + (y - y0)**2) / (2 * sigma**2)) model = lmfit.Model(gaussian, ['x', 'y']) init_guess = { 'A': 2, 'sigma': lmfit.Parameter('sigma', 3, min=0), 'x0': -0.2, 'y0': 0.3 } cb = LiveFit(model, 'det4', { 'x': 'motor1', 'y': 'motor2' }, init_guess, update_every=50) RE(outer_product_scan([det4], motor1, -1, 1, 10, motor2, -1, 1, 10, False), cb) expected = {'A': 1, 'sigma': 1, 'x0': 0, 'y0': 0} for k, v in expected.items(): assert np.allclose(cb.result.values[k], v, atol=1e-6)
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 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_colliding_streams(fresh_RE): RE = fresh_RE motor = Mover('motor', {'motor': lambda x: x}, {'x': 0}) motor1 = Mover('motor1', {'motor1': lambda x: x}, {'x': 0}) collector = {'primary': [], 'baseline': []} descs = {} def local_cb(name, doc): if name == 'descriptor': descs[doc['uid']] = doc['name'] elif name == 'event': collector[descs[doc['descriptor']]].append(doc) RE( bp.baseline_wrapper( bp.outer_product_scan([motor], motor, -1, 1, 5, motor1, -5, 5, 7, True), [motor, motor1]), local_cb) assert len(collector['primary']) == 35 assert len(collector['baseline']) == 2 assert list(range(1, 36)) == [e['seq_num'] for e in collector['primary']] assert list(range(1, 3)) == [e['seq_num'] for e in collector['baseline']]
def test_multi_fit(): #Create RunEngine RE = RunEngine() #Excepted values of fit expected = {'x0': 5, 'x1': 4, 'x2': 3} #Create simulated devices m1 = Mover('m1', {'m1': lambda x: x}, {'x': 0}) m2 = Mover('m2', {'m2': lambda x: x}, {'x': 0}) det = Reader( 'det', { 'centroid': lambda: 5 + 4 * m1.read()['m1']['value'] + 3 * m2.read()['m2'][ 'value'] }) #Assemble fitting callback cb = MultiPitchFit('centroid', ('m1', 'm2'), update_every=None) #Scan through variables RE(outer_product_scan([det], m1, -1, 1, 10, m2, -1, 1, 10, False), cb) #Check accuracy of fit print(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 _plan(self, p1, p2): x1, y1 = p1 x2, y2 = p2 return outer_product_scan(self.dets, self.motor1, x1, x2, self.num1, self.motor2, y1, y2, self.num2, self.snake, md=self.md)
def test_live_scatter(fresh_RE): RE = fresh_RE RE( outer_product_scan([det5], jittery_motor1, -3, 3, 6, jittery_motor2, -5, 5, 10, False), LiveScatter('jittery_motor1', 'jittery_motor2', 'det5', xlim=(-3, 3), ylim=(-5, 5))) # Test the deprecated name. RE( outer_product_scan([det5], jittery_motor1, -3, 3, 6, jittery_motor2, -5, 5, 10, False), LiveMesh('jittery_motor1', 'jittery_motor2', 'det5', xlim=(-3, 3), ylim=(-5, 5)))
def absolute_mesh(dets, *args, time=None, md=None): if (len(args) % 4) == 1: if time is not None: raise ValueError('wrong number of positional arguments') args, time = args[:-1], args[-1] total_points = 1 new_args = [] add_snake = False for motor, start, stop, num in chunked(args, 4): total_points *= num new_args += [motor, start, stop, num] if add_snake: new_args += [False] add_snake = True yield from _pre_scan(dets, total_points=total_points, count_time=time) return (yield from plans.outer_product_scan(dets, *new_args, md=md, per_step=one_nd_step))
def test_live_fit_multidim(): try: import lmfit except ImportError: raise pytest.skip('requires lmfit') motor1._fake_sleep = 0 motor2._fake_sleep = 0 def gaussian(x, y, A, sigma, x0, y0): return A*np.exp(-((x - x0)**2 + (y - y0)**2)/(2 * sigma**2)) model = lmfit.Model(gaussian, ['x', 'y']) init_guess = {'A': 2, 'sigma': lmfit.Parameter('sigma', 3, min=0), 'x0': -0.2, 'y0': 0.3} cb = LiveFit(model, 'det4', {'x': 'motor1', 'y': 'motor2'}, init_guess) RE(outer_product_scan([det4], motor1, -1, 1, 20, motor2, -1, 1, 20, False), cb) expected = {'A': 1, 'sigma': 1, 'x0': 0, 'y0': 0} for k, v in expected.items(): assert np.allclose(cb.result.values[k], v, atol=1e-6)
def hf2dxrf(*, xstart, xnumstep, xstepsize, ystart, ynumstep, ystepsize, acqtime, shutter=True, align=False, xmotor=hf_stage.x, ymotor=hf_stage.y, numrois=1, extra_dets=[], setenergy=None, u_detune=None, echange_waittime=10, samplename=None, snake=True): '''input: xstart, xnumstep, xstepsize : float ystart, ynumstep, ystepsize : float acqtime : float acqusition time to be set for both xspress3 and F460 numrois : integer number of ROIs set to display in the live raster scans. This is for display ONLY. The actualy number of ROIs saved depend on how many are enabled and set in the read_attr However noramlly one cares only the raw XRF spectra which are all saved and will be used for fitting. energy (float): set energy, use with caution, hdcm might become misaligned u_detune (float): amount of undulator to detune in the unit of keV ''' # Record relevant metadata in the Start document, defined in 90-usersetup.py scan_md = {} get_stock_md(scan_md) scan_md['sample'] = {'name': samplename} scan_md['scan_input'] = str( [xstart, xnumstep, xstepsize, ystart, ynumstep, ystepsize, acqtime]) scan_md['scaninfo'] = {'type': 'XRF', 'raster': True} # Setup detectors dets = [sclr1, xs] dets = dets + extra_dets dets_by_name = {d.name: d for d in dets} # Scaler if (acqtime < 0.001): acqtime = 0.001 sclr1.preset_time.put(acqtime) # XS3 xs.external_trig.put(False) xs.settings.acquire_time.put(acqtime) xs.total_points.put((xnumstep + 1) * (ynumstep + 1)) if ('merlin' in dets_by_name): dpc = dets_by_name['merlin'] # Setup Merlin dpc.cam.trigger_mode.put(0) dpc.cam.acquire_time.put(acqtime) dpc.cam.acquire_period.put(acqtime + 0.005) dpc.cam.num_images.put(1) dpc.hdf5.stage_sigs['num_capture'] = (xnumstep + 1) * (ynumstep + 1) dpc._mode = SRXMode.step dpc.total_points.put((xnumstep + 1) * (ynumstep + 1)) if ('xs2' in dets_by_name): xs2 = dets_by_name['xs2'] xs2.external_trig.put(False) xs2.settings.acquire_time.put(acqtime) xs2.total_points.put((xnumstep + 1) * (ynumstep + 1)) # Setup the live callbacks livecallbacks = [] # Setup scanbroker to update time remaining def time_per_point(name, doc, st=ttime.time()): if ('seq_num' in doc.keys()): scanrecord.scan0.tpp.put((doc['time'] - st) / doc['seq_num']) scanrecord.scan0.curpt.put(int(doc['seq_num'])) scanrecord.time_remaining.put( (doc['time'] - st) / doc['seq_num'] * ((xnumstep + 1) * (ynumstep + 1) - doc['seq_num']) / 3600) livecallbacks.append(time_per_point) # Setup LiveTable livetableitem = [xmotor.name, ymotor.name, i0.name] xstop = xstart + xnumstep * xstepsize ystop = ystart + ynumstep * ystepsize for roi_idx in range(numrois): roi_name = 'roi{:02}'.format(roi_idx + 1) roi_key = getattr(xs.channel1.rois, roi_name).value.name livetableitem.append(roi_key) roimap = LiveGrid((ynumstep + 1, xnumstep + 1), roi_key, clim=None, cmap='viridis', xlabel='x (mm)', ylabel='y (mm)', extent=[xstart, xstop, ystart, ystop], x_positive='right', y_positive='down') livecallbacks.append(roimap) if ('xs2' in dets_by_name): for roi_idx in range(numrois): roi_key = getattr(xs2.channel1.rois, roi_name).value.name livetableitem.append(roi_key) fig = plt.figure('xs2_ROI{:02}'.format(roi_idx + 1)) fig.clf() roimap = LiveGrid((ynumstep + 1, xnumstep + 1), roi_key, clim=None, cmap='viridis', xlabel='x (mm)', ylabel='y (mm)', extent=[xstart, xstop, ystart, ystop], x_positive='right', y_positive='down', ax=fig.gca()) livecallbacks.append(roimap) if ('merlin' in dets_by_name) and (hasattr(dpc, 'stats1')): fig = plt.figure('DPC') fig.clf() dpc_tmap = LiveGrid((ynumstep + 1, xnumstep + 1), dpc.stats1.total.name, clim=None, cmap='viridis', xlabel='x (mm)', ylabel='y (mm)', x_positive='right', y_positive='down', extent=[xstart, xstop, ystart, ystop], ax=fig.gca()) livecallbacks.append(dpc_tmap) # Change energy (if provided) if (setenergy is not None): if (u_detune is not None): energy.detune.put(u_detune) print('Changing energy to ', setenergy) yield from mv(energy, setenergy) print('Waiting time (s) ', echange_waittime) yield from bps.sleep(echange_waittime) def at_scan(name, doc): scanrecord.current_scan.put(doc['uid'][:6]) scanrecord.current_scan_id.put(str(doc['scan_id'])) scanrecord.current_type.put(scan_md['scaninfo']['type']) scanrecord.scanning.put(True) def finalize_scan(name, doc): scanrecord.scanning.put(False) # Setup the scan hf2dxrf_scanplan = outer_product_scan(dets, ymotor, ystart, ystop, ynumstep + 1, xmotor, xstart, xstop, xnumstep + 1, snake, md=scan_md) hf2dxrf_scanplan = subs_wrapper(hf2dxrf_scanplan, { 'all': livecallbacks, 'start': at_scan, 'stop': finalize_scan }) # Move to starting position yield from mv(xmotor, xstart, ymotor, ystart) # Peak up monochromator at this energy if (align): yield from peakup_fine(shutter=shutter) # Open shutter if (shutter): yield from mv(shut_b, 'Open') # Run the scan scaninfo = yield from hf2dxrf_scanplan #TO-DO: implement fast shutter control (close) if (shutter): yield from mv(shut_b, 'Close') # Write to scan log if ('merlin' in dets_by_name): logscan_event0info('2dxrf_withdpc') # Should this be here? merlin.hdf5.stage_sigs['num_capture'] = 0 else: logscan_detailed('2dxrf') return scaninfo
def xrfmap( *, xstart, xnumstep, xstepsize, ystart, ynumstep, ystepsize, rois=(), # shutter=True, # align=False, # acqtime, # numrois=1, # i0map_show=True, # itmap_show=False, # record_cryo=False, # setenergy=None, # u_detune=None, # echange_waittime=10 ): ''' input: xstart, xnumstep, xstepsize (float) ystart, ynumstep, ystepsize (float) ''' # define detector used for xrf mapping functions xrfdet = [sclr] # currently only the scalar; to-do: save full spectra xstop = xstart + xnumstep * xstepsize ystop = ystart + ynumstep * ystepsize # setup live callbacks: livetableitem = [xy_stage.x, xy_stage.y] livecallbacks = [] for roi in rois: livecallbacks.append( LiveGrid((ynumstep + 1, xnumstep + 1), roi, xlabel='x (mm)', ylabel='y (mm)', extent=[xstart, xstop, ystart, ystop])) livetableitem.append(roi) # # setup LiveOutput # xrfmapOutputTiffTemplate = (xrfmapTiffOutputDir + # "xrfmap_scan{start[scan_id]}" + # roi + ".tiff") # # xrfmapTiffexporter = LiveTiffExporter(roi, xrfmapOutputTiffTemplate, db=db) # xrfmapTiffexporter = RasterMaker(xrfmapOutputTiffTemplate, roi) # livecallbacks.append(xrfmapTiffexporter) livecallbacks.append(LiveTable(livetableitem)) # setup LiveOutput # if sclr in xrfdet: # for sclrDataKey in [getattr(sclr.cnts.channels, f'chan{j:02d}') for d in range(1, 21)]: # xrfmapOutputTiffTemplate = (xrfmapTiffOutputDir + # "xrfmap_scan{start[scan_id]}" + # sclrDataKey + ".tiff") # # # xrfmapTiffexporter = LiveTiffExporter(roi, xrfmapOutputTiffTemplate, db=db) # # # LiveTiffExporter exports one array from one event, # # commented out for future reference # xrfmapTiffexporter = RasterMaker(xrfmapOutputTiffTemplate, # sclrDataKey) # livecallbacks.append(xrfmapTiffexporter) xrfmap_scanplan = outer_product_scan(xrfdet, xy_stage.y, ystart, ystop, ynumstep + 1, xy_stage.x, xstart, xstop, xnumstep + 1, False) xrfmap_scanplan = bp.subs_wrapper(xrfmap_scanplan, livecallbacks) scaninfo = yield from xrfmap_scanplan return scaninfo
import matplotlib.pyplot as plt from bluesky.plan_tools import plot_raster_path from bluesky.examples import motor1, motor2, det from bluesky.plans import outer_product_scan plan = outer_product_scan([det], motor1, -5, 5, 10, motor2, -7, 7, 15, True) fig, ax = plt.subplots() plot_raster_path(plan, 'motor1', 'motor2', probe_size=.3, ax=ax) plt.show()
RE = RunEngine({}) # subscribe BEC bec = BestEffortCallback() 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))
db = Broker.from_config(config) RE = RunEngine({}) # subscribe BEC bec = BestEffortCallback() 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 = {
from ophyd.sim import motor, motor1, motor2, det from bluesky.simulators import print_summary, plot_raster_path from bluesky.plans import count, scan, outer_product_scan ############################################################################### # Inspect plans # ------------- # # Use ``print_summary`` which translates the plan into a human-readable list # of steps. print_summary(count([det])) print_summary(scan([det], motor, 1, 3, 3)) print_summary( outer_product_scan([det], motor1, 1, 3, 3, motor2, 1, 2, 2, False)) ############################################################################### # Use ``plot_raster_path`` to visualize a two-dimensional trajectory. plot_raster_path( outer_product_scan([det], motor1, 1, 3, 3, motor2, 1, 2, 2, False), 'motor1', 'motor2') ############################################################################### # Note that ``print_summary`` cannot be used on plans the require feedback from # the hardware, such as adaptively-spaced step scans. # # Rehearse plans # -------------- #