예제 #1
0
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))
예제 #2
0
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
예제 #3
0
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))
예제 #4
0
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))
예제 #5
0
 def _gen(self):
     return scan_nd(self.detectors, self.cycler, md=self.md)
예제 #6
0
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
예제 #7
0
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
예제 #8
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
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
예제 #9
0
                               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
예제 #10
0
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
예제 #11
0
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