Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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))
Ejemplo n.º 4
0
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