def test_simple_scan_nd(): RE = RunEngine() hardware1 = yaqc_bluesky.Device(39423) hardware2 = yaqc_bluesky.Device(39424) sensor = yaqc_bluesky.Device(39425) cy = cycler(hardware1, [1, 2, 3]) * cycler(hardware2, [4, 5, 6]) RE(scan_nd([sensor], cy))
def tomo_xrf_proj_realmotor(xcen, zcen, hstepsize, hnumstep, ycen, ystepsize, ynumstep, dets=[]): ''' collect an XRF 'projection' map at the current angle zcen should be defined as the position when the sample is in focus at zero degree; if it is not given, the program should take the current z position ''' theta = tomo_stage.theta.position #horizontal axes x_motor = tomo_stage.finex_top z_motor = tomo_stage.finez_top #vertical axis y_motor = tomo_stage.finey_top #stepsize setup xstepsize = hstepsize * numpy.cos(numpy.deg2rad(theta)) zstepsize = hstepsize * numpy.sin(numpy.deg2rad(theta)) #start and end point setup xstart = xcen - xstepsize * hnumstep / 2 xstop = xcen + xstepsize * hnumstep / 2 zstart = zcen - zstepsize * hnumstep / 2 zstop = zcen + zstepsize * hnumstep / 2 ystart = ycen - ystepsize * ynumstep / 2 ystop = ycen + ystepsize * ynumstep / 2 xlist = numpy.linspace(xstart, xstop, hnumstep + 1) #some theta dependent function zlist = numpy.linspace(zstart, zstop, hnumstep + 1) ylist = numpy.linspace(ystart, ystop, ynumstep + 1) xz_cycler = cycler(x_motor, xlist) + cycler(z_motor, zlist) yxz_cycler = cycler(y_motor, ylist) * xz_cycler # The scan_nd plan expects a list of detectors and a cycler. plan = scan_nd(dets, yxz_cycler) # Optionally, add subscritpions. #TO-DO: need to figure out how to add LiveRaster with the new x/z axis plan = subs_wrapper(plan, [LiveTable([x_motor, y_motor, z_motor])]) # LiveMesh(...)] scaninfo = yield from plan return scaninfo
def scan_steps(dets, *args, time=None, per_step=None, md=None): ''' Absolute scan over an arbitrary N-dimensional trajectory. Parameters ---------- ``*args`` : {Positioner, list/sequence} Patterned like (``motor1, motor1_positions, ..., motorN, motorN_positions``) Where motorN_positions is a list/tuple/sequence of absolute positions for motorN to go to. time : float, optional applied to any detectors that have a `count_time` setting per_step : callable, optional hook for cutomizing action of inner loop (messages per step) See docstring of bluesky.plans.one_nd_step (the default) for details. md : dict, optional metadata ''' if len(args) % 2 == 1: if time is not None: raise ValueError('Wrong number of positional arguments') args, time = args[:-1], args[-1] cyclers = [cycler(motor, steps) for motor, steps in chunked(args, 2)] cyc = sum(cyclers[1:], cyclers[0]) total_points = len(cyc) if md is None: md = {} from collections import ChainMap md = ChainMap(md, {'plan_name': 'scan_steps'}) plan = plans.scan_nd(dets, cyc, md=md, per_step=per_step) plan = plans.configure_count_time_wrapper(plan, time) yield from _pre_scan(dets, total_points=total_points, count_time=time) return (yield from plans.reset_positions_wrapper(plan))
def SWCarbon_acq(multiple, mesh, det, en): energies = np.arange(270, 282, .5) energies = np.append(energies, np.arange(282, 286, .1)) energies = np.append(energies, np.arange(286, 292, .2)) energies = np.append(energies, np.arange(292, 305, 1)) energies = np.append(energies, np.arange(305, 320, 1)) energies = np.append(energies, np.arange(320, 350, 5)) times = energies.copy() times[energies < 282] = 1 times[(energies < 286) & (energies >= 282)] = 5 times[energies >= 286] = 2 times *= multiple # print(times) # print(energies) # print(len(times)) # print(len(energies)) times2 = times.copy() # print(len(times2)) yield from scan_nd([mesh, det], cycler(det.saxs.cam.acquire_time, times) + cycler(mesh.parent.exposure_time, times2) + cycler(en, energies))
def _gen(self): return scan_nd(self.detectors, self.cycler, md=self.md)
def EfixQapprox(detectors, E_start, E_end, npts, E_shift=0, *, per_step=None, md=None): '''Approximate fixed Q energy scan based on delta, theta positions for CSX-1 mono (pgm.energy) Parameters ---------- E_start : float starting energy [eV] E_stop : float stoping energy [eV] npts : integer number of points E_shift : float shift in energy calibration relative to orientation matrix (i.e, ) - not used currently per_step : callable, optional hook for cutomizing action of inner loop (messages per step) See docstring of bluesky.plans.one_nd_step (the default) for details. md : dict, optional metadata ''' x_motor = pgm.energy # This is CSX-1's mono motor name for energy x_start = E_start pattern_args = dict(x_motor=x_motor, x_start=E_start, npts=npts) deltas = [] thetas = [] deltaCALC = 0 thetaCALC = 0 E_init = x_motor.readback.value lam_init = 12398/E_init delta_init = delta.user_readback.value theta_init = theta.user_readback.value dsp = lam_init/(2*np.sin(np.radians(delta_init/2))) theta_offset = delta_init/2 - theta_init E_vals = np.linspace(E_start, E_end, npts) # lam_vals = np.linspace(12398/E_start, 12398/E_end, npts) x_range = max(E_vals) - min(E_vals) for lam_val in lam_vals: deltaCALC = np.degrees(np.arcsin(lam_val/2/dsp))*2 thetaCALC = deltaCALC/2 - theta_offset deltas.append(deltaCALC) thetas.append(thetaCALC) motor_pos = (cycler(delta, deltas) + cycler(theta, thetas) + cycler(x_motor, E_vals)) # TODO decide to include diffractometer motors below? # Before including pattern_args in metadata, replace objects with reprs. pattern_args['x_motor'] = repr(x_motor) _md = {'plan_args': {'detectors': list(map(repr, detectors)), 'x_motor': repr(x_motor), 'x_start': x_start, 'x_range': x_range, 'per_step': repr(per_step)}, 'extents': tuple([[x_start - x_range, x_start + x_range]]), 'plan_name': 'EfixQapprox', 'plan_pattern': 'scan', 'plan_pattern_args': pattern_args, # this is broken TODO do we need this? # 'plan_pattern_module': plan_patterns.__name__, 'hints': {}} try: dimensions = [(x_motor.hints['fields'], 'primary')] # print(dimensions) except (AttributeError, KeyError): pass else: _md['hints'].update({'dimensions': dimensions}) _md.update(md or {}) # this works without subs, Escan_plan = scan_nd(detectors, motor_pos, per_step=per_step, md=_md) reset_plan = bps.mv(x_motor, E_init, delta, delta_init, theta, theta_init) # Check for suitable syntax.. # yield from print('Starting an Escan fix Q at ({:.4f}, {:.4f}, {:.4f})'.format(h_init,k_init,l_init)) def plan_steps(): yield from Escan_plan print('/nMoving back to motor positions immediately before scan/n') yield from reset_plan try: return (yield from plan_steps()) except Exception: print('/nMoving back to motor positions immediately before scan/n') yield from reset_plan raise
def EfixQ(detectors, E_start, E_end, steps, E_shift=0, *, per_step=None, md=None): '''Fixed Q energy scan based on an orientation matrix for CSX-1 mono (pgm.energy) If using higher order harmonic of mono, adjust H K L, not energy. Parameters ---------- E_start : float starting energy [eV] E_stop : float stoping energy [eV] steps : integer number of points E_shift : float shift in energy calibration relative to orientation matrix (i.e, ) per_step : callable, optional hook for cutomizing action of inner loop (messages per step) See docstring of bluesky.plans.one_nd_step (the default) for details. md : dict, optional metadata ''' x_motor = pgm.energy # This is CSX-1's mono motor name for energy x_start = E_start pattern_args = dict(x_motor=x_motor, x_start=E_start, steps=steps, E_shift=E_shift) E_init = x_motor.readback.value tardis.calc.energy = (x_motor.setpoint.value + E_shift)/10000 h_init = tardis.position.h k_init = tardis.position.k l_init = tardis.position.l delta_init = delta.user_readback.value theta_init = theta.user_readback.value gamma_init = gamma.user_readback.value deltas = [] thetas = [] gammas = [] # TODO no plus one, use npts as arugument. E_vals = np.linspace(E_start, E_end, steps+1) x_range = max(E_vals) - min(E_vals) for E_val in E_vals: tardis.calc.energy = (E_val + E_shift)/10000 angles = tardis.forward([h_init, k_init, l_init]) deltas.append(angles.delta) thetas.append(angles.theta) gammas.append(angles.gamma) motor_pos = (cycler(delta, deltas) + cycler(theta, thetas) + cycler(gamma, gammas) + cycler(x_motor, E_vals)) # TODO decide to include diffractometer motors below? # Before including pattern_args in metadata, replace objects with reprs. pattern_args['x_motor'] = repr(x_motor) _md = {'plan_args': {'detectors': list(map(repr, detectors)), 'x_motor': repr(x_motor), 'x_start': x_start, 'x_range': x_range, 'per_step': repr(per_step)}, 'extents': tuple([[x_start - x_range, x_start + x_range]]), 'plan_name': 'EfixQ', 'plan_pattern': 'scan', 'plan_pattern_args': pattern_args, # this is broken TODO do we need this # 'plan_pattern_module': plan_patterns.__name__, 'hints': {}} try: dimensions = [(x_motor.hints['fields'], 'primary')] # print(dimensions) except (AttributeError, KeyError): pass else: _md['hints'].update({'dimensions': dimensions}) _md.update(md or {}) # this works without subs, Escan_plan = scan_nd(detectors, motor_pos, per_step=per_step, md=_md) reset_plan = bps.mv(x_motor, E_init, delta, delta_init, theta, theta_init, gamma, gamma_init) # yield from print('Starting an Escan fix Q at ({:.4f}, {:.4f}, {:.4f})'.format(h_init,k_init,l_init)) def plan_steps(): print('Starting fixed Q energy scan for ' '({:.4f}, {:.4f}, {:.4f}\n\n)'.format( tardis.h.position, tardis.k.position, tardis.l.position)) yield from Escan_plan print('\nMoving back to motor positions immediately before scan\n') yield from reset_plan yield from bps.sleep(1) tardis.calc.energy = (pgm.energy.readback.value + E_shift)/10000 print('Returned to Q at ({:.4f}, {:.4f}, {:.4f})'.format( tardis.h.position, tardis.k.position, tardis.l.position)) try: return (yield from plan_steps()) except Exception: print('\nMoving back to motor positions immediately before scan\n') yield from reset_plan yield from bps.sleep(1) tardis.calc.energy = (pgm.energy.readback.value + E_shift)/10000 print('Returned to Q at ({:.4f}, {:.4f}, {:.4f})'.format( tardis.h.position, tardis.k.position, tardis.l.position)) raise
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 outer_hints = { 'fields': [det4.name], 'dimensions': [([motor2.name], 'primary'), ([motor1.name], 'primary')] } md = { 'shape': (20, 20), #'extents': ([-1, 0], [-1, 0]), 'hints': outer_hints } RE(scan_nd([det4], mot1_cycl * mot2_cycl), **md) # make 40 points just to test
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 outer_hints = {'fields' : [det4.name], 'dimensions' : [([motor2.name],'primary'), ([motor1.name], 'primary')]} md = {'shape': (20, 20), #'extents': ([-1, 0], [-1, 0]), 'hints' : outer_hints } RE(scan_nd([det4], mot1_cycl*mot2_cycl), **md) # make 40 points just to test mot2_cycl = cycler(motor2, np.linspace(-1, 0, 20)) # now try rectilinear gridding
def spiral_continuous(detectors, x_motor, y_motor, x_start, y_start, npts, probe_size, overlap=0.8, *, tilt=0.0, per_step=None, md=None): '''Continuously increasing radius spiral scan. centered around (x_start, y_start) which is generic regarding motors and detectors. Parameters ---------- x_motor : object any 'setable' object (motor, etc.) y_motor : object any 'setable' object (motor, etc.) x_start : float x center y_start : float y center npts : integer number of points probe_size : float radius of probe in units of motors overlap : float fraction of probe overlap ---------------------------------------------------------------- Not implemented yet: tilt : float, optional (not yet enabled) Tilt angle in radians, default = 0.0 per_step : callable, optional hook for cutomizing action of inner loop (messages per step) See docstring of bluesky.plans.one_nd_step (the default) for details. ---------------------------------------------------------------- md : dict, optional metadata ''' # #TODO clean up pattern args and _md. Do not remove motors from _md. pattern_args = dict(x_motor=x_motor, y_motor=y_motor, x_start=x_start, y_start=y_start, npts=npts, probe_size=probe_size, overlap=overlap, tilt=tilt) # cyc = plan_patterns.spiral(**pattern_args)# - leftover from spiral. bxs = [] bzs = [] bx_init = x_start bz_init = y_start for i in range(0, npts): R = np.sqrt(i / np.pi) # this is to get the first point to be the center T = 2 * i / (R + 0.0000001) bx = (overlap * probe_size * R * np.cos(T)) + bx_init bz = (overlap * probe_size * R * np.sin(T)) + bz_init bxs.append(bx) bzs.append(bz) motor_vals = [bxs, bzs] x_range = max(motor_vals[0]) - min(motor_vals[0]) y_range = max(motor_vals[1]) - min(motor_vals[1]) motor_pos = cycler(x_motor, bxs) + cycler(y_motor, bzs) # Before including pattern_args in metadata, replace objects with reprs. pattern_args['x_motor'] = repr(x_motor) pattern_args['y_motor'] = repr(y_motor) _md = { 'plan_args': { 'detectors': list(map(repr, detectors)), 'x_motor': repr(x_motor), 'y_motor': repr(y_motor), 'x_start': x_start, 'y_start': y_start, 'overlap': overlap, # 'nth': nth, 'tilt': tilt, 'per_step': repr(per_step) }, 'extents': tuple([[x_start - x_range, x_start + x_range], [y_start - y_range, y_start + y_range]]), 'plan_name': 'spiral_continuous', 'plan_pattern': 'spiral_continuous', 'plan_pattern_args': pattern_args, # - leftover from spiral. # 'plan_pattern_module': plan_patterns.__name__, 'hints': {} } try: dimensions = [(x_motor.hints['fields'], 'primary'), (y_motor.hints['fields'], 'primary')] except (AttributeError, KeyError): pass else: _md['hints'].update({'dimensions': dimensions}) _md.update(md or {}) cont_sp_plan = bp.scan_nd(detectors, motor_pos, per_step=per_step, md=_md) reset_plan = bps.mv(x_motor, x_start, y_motor, y_start) def plan_steps(): yield from cont_sp_plan print('Moving back to first point position.') yield from reset_plan try: return (yield from plan_steps()) except Exception: # Catch the exception long enough to clean up. print('Moving back to first point position.') yield from reset_plan raise
def spiral_continuous(detectors, x_motor, y_motor, x_start, y_start, npts, probe_size, overlap=0.8, *, tilt=0.0, per_step=None, md=None): '''Continuously increasing radius spiral scan. centered around (x_start, y_start) which is generic regarding motors and detectors. Parameters ---------- x_motor : object any 'setable' object (motor, etc.) y_motor : object any 'setable' object (motor, etc.) x_start : float x center y_start : float y center npts : integer number of points probe_size : float radius of probe in units of motors overlap : float fraction of probe overlap ---------------------------------------------------------------- Not implemented yet: tilt : float, optional (not yet enabled) Tilt angle in radians, default = 0.0 per_step : callable, optional hook for cutomizing action of inner loop (messages per step) See docstring of bluesky.plans.one_nd_step (the default) for details. ---------------------------------------------------------------- md : dict, optional metadata ''' # #TODO clean up pattern args and _md. Do not remove motors from _md. pattern_args = dict(x_motor=x_motor, y_motor=y_motor, x_start=x_start, y_start=y_start, npts=npts, probe_size=probe_size, overlap=overlap, tilt=tilt) # cyc = plan_patterns.spiral(**pattern_args)# - leftover from spiral. bxs = [] bzs = [] bx_init = x_start bz_init = y_start for i in range(0, npts): R = np.sqrt(i/np.pi) # this is to get the first point to be the center T = 2*i/(R+0.0000001) bx = (overlap*probe_size*R * np.cos(T)) + bx_init bz = (overlap*probe_size*R * np.sin(T)) + bz_init bxs.append(bx) bzs.append(bz) motor_vals = [bxs, bzs] x_range = max(motor_vals[0]) - min(motor_vals[0]) y_range = max(motor_vals[1]) - min(motor_vals[1]) motor_pos = cycler(x_motor, bxs) + cycler(y_motor, bzs) # Before including pattern_args in metadata, replace objects with reprs. pattern_args['x_motor'] = repr(x_motor) pattern_args['y_motor'] = repr(y_motor) _md = {'plan_args': {'detectors': list(map(repr, detectors)), 'x_motor': repr(x_motor), 'y_motor': repr(y_motor), 'x_start': x_start, 'y_start': y_start, 'overlap': overlap, # 'nth': nth, 'tilt': tilt, 'per_step': repr(per_step)}, 'extents': tuple([[x_start - x_range, x_start + x_range], [y_start - y_range, y_start + y_range]]), 'plan_name': 'spiral_continuous', 'plan_pattern': 'spiral_continuous', 'plan_pattern_args': pattern_args, # - leftover from spiral. # 'plan_pattern_module': plan_patterns.__name__, 'hints': {}} try: dimensions = [(x_motor.hints['fields'], 'primary'), (y_motor.hints['fields'], 'primary')] except (AttributeError, KeyError): pass else: _md['hints'].update({'dimensions': dimensions}) _md.update(md or {}) cont_sp_plan = bp.scan_nd(detectors, motor_pos, per_step=per_step, md=_md) reset_plan = bps.mv(x_motor, x_start, y_motor, y_start) def plan_steps(): yield from cont_sp_plan print('Moving back to first point position.') yield from reset_plan try: return (yield from plan_steps()) except Exception: # Catch the exception long enough to clean up. print('Moving back to first point position.') yield from reset_plan raise