def test_reset_positions_no_position_attr(RE, hw): motor = hw.motor_no_pos motor.set(5) msgs = [] def accumulator(msg): msgs.append(msg) RE.msg_hook = accumulator def plan(): yield from (m for m in [Msg('set', motor, 8)]) RE(reset_positions_wrapper(plan())) expected = [ Msg('read', motor), Msg('set', motor, 8), Msg('set', motor, 5), Msg('wait') ] for msg in msgs: msg.kwargs.pop('group', None) assert msgs == expected
def test_reset_positions(RE, hw): motor = hw.motor motor.set(5) msgs = [] def accumulator(msg): msgs.append(msg) RE.msg_hook = accumulator def plan(): yield from (m for m in [Msg('set', motor, 8)]) RE(reset_positions_wrapper(plan())) expected = [Msg('set', motor, 8), Msg('set', motor, 5), Msg('wait')] for msg in msgs: msg.kwargs.pop('group', None) assert msgs == expected
def relative_mesh(dets, *args, time=None, md=None): plan = absolute_mesh(dets, *args, time=time, md=md) plan = bpp.relative_set_wrapper(plan) # re-write trajectory as relative return (yield from bpp.reset_positions_wrapper(plan))
def Ecal_old(detectors, motor, guessed_energy, mode, *, guessed_amplitude=0.5, guessed_sigma=0.004, min_step=0.001, D='LaB6', max_n=3, margin=0.5, md=None): """ Energy calibration scan Parameters ---------- detectors : detectors motor : the motor guessed_energy : number units of keV mode : {'peaks', 'dips'} guessed_amplitude : number, optional detector units, defaults to 1500 guessed_sigma : number, optional in units of degrees, defaults to 0.004 min_step : number, optional step size in degrees, defaults to 0.001 D : string or array, optional Either provide the spacings literally (as an array) or give the name of a known spacing ('LaB6' or 'Si') max_n : integer, optional how many peaks (on one side of 0), default is 3 margin : number, optional how far to scan in two theta beyond the guessed left and right peaks, default 0.5 Example ------- Execute an energy calibration scan with default steps. >>> RE(Ecal(68)) """ if mode == 'peaks': #motor = tth_cal factor = 2 offset = 0 sign = 1 if mode == 'dips': #motor = th_cal factor = 1 # theta_hardware = theta_theorhetical + offset offset = -35.26 # degrees sign = -1 if isinstance(D, str): D = D_SPACINGS[D] # Based on the guessed energy, compute where the peaks should be centered # in theta. This will be used as an initial guess for peak-fitting. guessed_wavelength = 12.398 / guessed_energy # angtroms theta = np.rad2deg(np.arcsin(guessed_wavelength / (2 * D))) guessed_centers = factor * theta # 'factor' puts us in two-theta units if applicable _range = max(guessed_centers) + (factor * margin) # Scan from positive to negative because that is the direction # that the th_cal and tth_cal motors move without backlash. start, stop = _range + offset, -_range + offset print('guessed_wavelength={} [Angstroms]'.format(guessed_wavelength)) print('guessed_centers={} [in {}-theta DEGREES]'.format( guessed_centers, factor)) print('will scan from {} to {} in hardware units'.format(start, stop)) if max_n > 3: raise NotImplementedError("I only work for n up to 3.") # todo : make a model and sum them def peaks(x, c0, wavelength, a1, a2, sigma): # x comes from hardware in [theta or two-theta] degrees x = np.deg2rad(x / factor - offset) # radians assert np.all(wavelength < 2 * D), \ "wavelength would result in illegal arg to arcsin" cs = np.arcsin(wavelength / (2 * D)) c1 = cs[0] c2 = cs[1] #c3 = cs[2] # first peak result = ( voigt(x=x, amplitude=sign * a1, center=c0 - c1, sigma=sigma) + voigt(x=x, amplitude=sign * a1, center=c0 + c1, sigma=sigma)) # second peak result += ( voigt(x=x, amplitude=sign * a2, center=c0 - c2, sigma=sigma) + voigt(x=x, amplitude=sign * a2, center=c0 + c2, sigma=sigma)) # third peak #result += (voigt(x=x, amplitude=sign*a3, center=c0 - c3, sigma=sigma) + #voigt(x=x, amplitude=sign*a3, center=c0 + c3, sigma=sigma)) return result model = Model(peaks) + LinearModel() # Fill out initial guess. init_guess = { 'intercept': Parameter('intercept', value=0, min=-100, max=100), 'slope': Parameter('slope', value=0, min=-100, max=100), 'sigma': Parameter('sigma', value=np.deg2rad(guessed_sigma)), 'c0': Parameter('c0', value=np.deg2rad(0), min=-0.2, max=0.2), 'wavelength': Parameter('wavelength', guessed_wavelength, min=0.8 * guessed_wavelength, max=1.2 * guessed_wavelength) } # min=0, max=np.min(2 * D))} kwargs = {'min': 0.5 * guessed_amplitude, 'max': 2 * guessed_amplitude} for i, center in enumerate(guessed_centers): init_guess.update({ 'a%d' % (1 + i): Parameter('a%d' % (1 + i), guessed_amplitude, **kwargs) }) print(init_guess) lf = LiveFit(model, detectors[0].name, {'x': motor.name}, init_guess, update_every=100) fig, ax = plt.subplots() # explitly create figure, axes to use below plot = LivePlot(detectors[0].name, motor.name, linestyle='none', marker='o', ax=ax) lfp = LiveFitPlot(lf, ax=ax, color='r') subs = [lfp, plot] #detectors = [det]#[sc] # Set up metadata -- based on the sourcecode of bluesky.plans.scan. _md = { 'detectors': [det.name for det in detectors], 'motors': [motor.name], 'hints': {}, } _md.update(md or {}) try: dimensions = [(motor.hints['fields'], 'primary')] except (AttributeError, KeyError): pass else: _md['hints'].setdefault('dimensions', dimensions) initial_steps = np.arange(start, stop, -min_step) assert len(initial_steps), "bad start, stop, min_step parameters" size = factor * 0.05 # region around each predicted peak location @bpp.stage_decorator(list(detectors) + [motor]) @bpp.run_decorator(md=_md) def inner_scan(): wavelength = guessed_wavelength for step in initial_steps: yield from bps.one_1d_step(detectors, motor, step) x_data = lf.independent_vars_data['x'] if x_data and lf.result is not None: # Have we yet scanned past the third peak? wavelength = lf.result.values['wavelength'] # Convert c's to hardware units here for comparison with x_data. c1, c2, c3 = factor * np.rad2deg( np.arcsin(wavelength / (2 * D))) + offset if np.min(x_data) < (c1 - 1): # Stop dense scanning. print('Preliminary result:\n', lf.result.values) print('Becoming adaptive to save time....') break # left of zero peaks c1, c2, c3 = -factor * np.rad2deg(np.arcsin(wavelength / (2 * D))) + offset neighborhoods = [ np.arange(c + size, c - size, -min_step) for c in (c1, c2, c3) ] for neighborhood in neighborhoods: for step in neighborhood: yield from bps.one_1d_step(detectors, motor, step) plan = inner_scan() plan = bpp.subs_wrapper(plan, subs) plan = bpp.reset_positions_wrapper(plan, [motor]) ret = (yield from plan) print(lf.result.values) print('WAVELENGTH: {} [Angstroms]'.format(lf.result.values['wavelength'])) return ret