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))
def _ct_dark_cleanup(oldnumim, gain_bit_dict, gain_state,
                     dark_sh_dict, dark_shutter_state):
    print('\nReturning to intial conditions (pre-count).')
    yield from bps.abs_set(fccd.cam.num_images, oldnumim, wait=True)

    yield from bps.mv(fccd.cam.fcric_gain, gain_state)
    yield from bps.mv(inout, dark_sh_dict.get(dark_shutter_state))
    yield from bps.sleep(fccd.cam.acquire_period.value)

    print('\tTotal images per trigger are NOW:\t {}'.format(
        fccd.cam.num_images.setpoint))
    print('\tFCCD FCRIC gain value is NOW:\t\t {}\n\n'.format(
        gain_bit_dict.get(fccd.cam.fcric_gain.value)))
def open_all_valves(valve_list):
    '''Open all the listed valves

    Parameters
    ----------
    valve_list : sequence
        The valves to open

    '''
    for v in valve_list:
        yield from bps.abs_set(v, 1, group='valve_set')
    yield from bps.wait('valve_set')
    # sleep might not be needed
    yield from bps.sleep(2)
Exemple #4
0
def E_fly(scan_title,
          *,
          operator,
          element,
          start,
          stop,
          step_size,
          num_scans,
          flyspeed=0.05,
          xspress3=None):
    _validate_motor_limits(mono.energy, start, stop, "E")
    assert step_size > 0, f"step_size ({step_size}) must be more than 0"
    assert num_scans > 0, f"num_scans ({num_scans}) must be more than 0"

    e_back = yield from _get_v_with_dflt(mono.e_back, 1977.04)
    energy_cal = yield from _get_v_with_dflt(mono.cal, 0.40118)
    roi = rois(element)
    xs.channel1.rois.roi01.bin_low.set(roi[0])
    xs.channel1.rois.roi01.bin_high.set(roi[1])

    def _linear_to_energy(linear):
        linear = np.asarray(linear)
        return e_back / np.sin(
            np.deg2rad(45) + 0.5 * np.arctan((28.2474 - linear) / 35.02333) +
            np.deg2rad(energy_cal) / 2)

    def _energy_to_linear(energy):
        energy = np.asarray(energy)
        return 28.2474 + 35.02333 * np.tan(np.pi / 2 -
                                           2 * np.arcsin(e_back / energy) +
                                           np.deg2rad(energy_cal))

    # get limits in linear parameters
    l_start, l_stop = _energy_to_linear([start, stop])
    l_step_size = np.diff(_energy_to_linear([start, start + step_size]))

    # scale to match motor resolution
    lmres = yield from _get_v_with_dflt(mono.linear.mres, 0.0001666)

    prescale = int(np.floor((l_step_size / (5 * lmres))))
    a_l_step_size = prescale * (5 * lmres)

    num_pixels = int(np.floor((l_stop - l_start) / a_l_step_size))

    bin_edges = _linear_to_energy(l_start +
                                  a_l_step_size * np.arange(num_pixels + 1))
    bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2

    yield from bps.mv(E_centers, bin_centers)

    # The flyspeed is set by Paul by edict
    # flyspeed = 0.05

    # set up delta-tau trigger to fast motor
    for v in [
            "p1600=0", "p1607=4", "p1601=5", "p1602 = 2", "p1604 = 0",
            "p1600=1"
    ]:
        yield from bps.mv(dtt, v)
        yield from bps.sleep(0.1)

    # TODO make this a message?
    sclr.set_mode("flying")

    # SRX original roi_key = getattr(xs.channel1.rois, roi_name).value.name

    # roi_livegrid_key = xs.channel1.rois.roi01.value.name
    # roi_livegrid = LivePlot(y=roi_livegrid_key)

    # poke the struck settings
    yield from bps.mv(sclr.mcas.prescale, prescale)
    yield from bps.mv(sclr.mcas.nuse, num_pixels)

    if xspress3 is not None:
        yield from bps.mv(xs.external_trig, True)
        yield from mv(xspress3.total_points, num_pixels)
        yield from mv(xspress3.hdf5.num_capture, num_pixels)
        yield from mv(xspress3.settings.num_images, num_pixels)

    @bpp.reset_positions_decorator([mono.linear])
    @bpp.stage_decorator([sclr])
    # @bpp.subs_decorator({"all": [roi_livegrid]})
    @bpp.monitor_during_decorator([xs.channel1.rois.roi01.value])
    @bpp.baseline_decorator([mono, xy_stage])
    # TODO put is other meta data
    @bpp.run_decorator(
        md={
            "scan_title": scan_title,
            "operator": operator,
            "user_input": {
                "element": element,
                "start": start,
                "stop": stop,
                "step_size": step_size,
            },
            "derived_input": {
                "l_start": l_start,
                "l_stop": l_stop,
                "l_step_size": l_step_size,
                "lmres": lmres,
                "actual_l_step_size": a_l_step_size,
                "fly_velocity": flyspeed,
                "num_pixels": num_pixels,
                "prescale": prescale,
            },
        })
    def fly_body():
        yield from bps.trigger_and_read([E_centers], name="energy_bins")

        @bpp.stage_decorator([x for x in [xspress3] if x is not None])
        def fly_once(y):
            # for y in range(num_scans):
            # go to start of row

            yield from bps.checkpoint()
            yield from bps.mv(mono.linear, l_start)

            # set the fly speed
            yield from bps.mv(mono.linear.velocity, flyspeed)

            yield from bps.trigger_and_read([mono], name="row_ends")

            for v in ["p1600=0", "p1600=1"]:
                yield from bps.mv(dtt, v)
                yield from bps.sleep(0.1)

            # arm the Struck
            yield from bps.trigger(sclr, group=f"fly_energy_{y}")
            if xspress3 is not None:
                yield from bps.trigger(xspress3, group=f"fly_energy_{y}")

            # fly the motor
            yield from bps.abs_set(mono.linear,
                                   l_stop + a_l_step_size,
                                   group=f"fly_energy_{y}")
            yield from bps.wait(group=f"fly_energy_{y}")

            yield from bps.trigger_and_read([mono], name="row_ends")

            yield from bps.mv(mono.linear.velocity, 0.5)
            # hard coded to let the sclr count its fingers and toes
            yield from bps.sleep(0.1)
            # read and save the struck
            yield from bps.create(name="primary")
            yield from bps.read(sclr)
            if xspress3 is not None:
                yield from bps.read(xspress3)

            yield from bps.save()

        for scan_iter in range(num_scans):
            if xspress3 is not None:
                yield from bps.mv(xspress3.fly_next, True)
            yield from fly_once(scan_iter)

    yield from fly_body()

    print("Waiting for files... ...")
    yield from bps.sleep(15)
    artifacts = e_fly_export(db[-1])
    pprint.pprint(artifacts)
Exemple #5
0
def fly_scan(*,
             x_start,
             x_stop,
             nx,
             y_start,
             y_stop,
             ny,
             exp_time,
             trigger_rate=7,
             md={}):
    """Fly scan plan with a stage (X and Y motors) and a camera.

    How to run:
    -----------
    RE(fly_scan(x_start=0, x_stop=0.1, nx=50, y_start=0, y_stop=0.1, ny=4,
                exp_time=0.01, trigger_rate=5))

    Parameters
    ----------
    x_start : float
        start position of the X-motor of the stage
    x_stop : float
        stop position of the X-motor of the stage
    nx : integer
        number of points for the X-motor
    y_start : float
        start position of the X-motor of the stage
    y_stop : float
        stop position of the Y-motor of the stage
    ny : integer
        number of points for the Y-motor
    exp_time : float
        exposure time of the camera
    trigger_rate : integer, optional
        trigger rate of the camera
    md : dict, optional
        metadata
    """

    yield from bps.mv(
        # X motor:
        flyer.hxn_stage.x_start,
        x_start,
        flyer.hxn_stage.x_stop,
        x_stop,
        flyer.hxn_stage.nx,
        nx,

        # Y motor:
        flyer.hxn_stage.y_start,
        y_start,
        flyer.hxn_stage.y_stop,
        y_stop,
        flyer.hxn_stage.ny,
        ny,

        # Trigger rate:
        flyer.hxn_stage.trigger_rate,
        trigger_rate,
    )

    yield from bps.sleep(1.0)
    for c in flyer.hxn_stage.component_names:
        print(f'{getattr(flyer.hxn_stage, c).read()}')

    yield from bps.mv(flyer.detector.cam.acquire_time, exp_time)
    yield from bps.mv(
        flyer.detector.cam.num_images,
        int(flyer.hxn_stage.nx.get()) * int(flyer.hxn_stage.ny.get()))

    # md.update({'x_start': x_start, 'x_stop': x_stop, 'nx': nx,
    #            'y_start': y_start, 'y_stop': y_stop, 'ny': nx,
    #            'exp_time': exp_time, 'trigger_rate': trigger_rate,
    #            })

    yield from bps.sleep(1.0)

    @bpp.stage_decorator([flyer])
    def _fly_scan():
        yield from bp.fly([flyer])

    yield from _fly_scan()
Exemple #6
0
def tune_GslitsCenter(md=None):
    """
    plan: optimize the guard slits' position

    tune to the peak centers
    """
    _md = dict()
    _md.update(md or {})

    # yield from IfRequestedStopBeforeNextScan()
    title = "tuning USAXS Gslit center"
    ts = str(datetime.datetime.now())
    # yield from bps.mv(
    #     user_data.sample_title, title,
    #     user_data.state, "tune Guard slits center",
    #     user_data.user_name, USERNAME,
    #     # user_data.user_dir, ZZZZZZZZZZZ,
    #     user_data.spec_scan, str(RE.md["scan_id"]+1+1),     # TODO: Why SCAN_N+1?
    #     user_data.time_stamp, ts,
    #     user_data.scan_macro, "tune_GslitCenter",
    #     )

    # yield from mode_USAXS()
    # yield from bps.mv(
    #     usaxs_slit.v_size, terms.SAXS.usaxs_v_size.get(),
    #     usaxs_slit.h_size, terms.SAXS.usaxs_h_size.get(),
    #     )
    # yield from bps.mv(ti_filter_shutter, "open")
    # yield from insertTransmissionFilters()
    yield from bps.sleep(0.1)
    logger.info("autoranging the PD -- skipped")
    # yield from bps.mv(
    #     user_data.state, "autoranging the PD",
    #     )
    # yield from autoscale_amplifiers([upd_controls, I0_controls, I00_controls])
    # yield from bps.mv(user_data.state, title)

    old_preset_time = scaler0.preset_time.get()
    yield from bps.mv(scaler0.preset_time, 0.2)

    def tune_guard_slit_motor(motor, width, steps):
        if steps < 10:
            raise GuardSlitTuneError(
                f"Not enough points ({steps}) to tune guard slits.")

        x_c = motor.position
        x_0 = x_c - abs(width) / 2
        x_n = x_c + abs(width) / 2

        scaler0.select_channels([UPD_SIGNAL.chname.get()])
        CLOCK_SIGNAL.kind = Kind.config

        tuner = TuneAxis([scaler0], motor, signal_name=UPD_SIGNAL.chname.get())
        yield from tuner.tune(width=-width, num=steps + 1)

        bluesky_runengine_running = RE.state != "idle"

        if bluesky_runengine_running:
            found = tuner.peak_detected()
            center = tuner.peaks.com  # center of mass

            table = pyRestTable.Table()
            table.addLabel("tune parameter")
            table.addLabel("fitted value")
            table.addRow(("peak detected?", found))
            table.addRow(("center of mass", center))
            table.addRow(("center from half max", tuner.peaks.cen))
            table.addRow(("peak max (x,y)", tuner.peaks.max))
            table.addRow(("FWHM", tuner.peaks.fwhm))
            logger.info(table)

            def cleanup_then_GuardSlitTuneError(msg):
                logger.warning(
                    "cleanup: %s -- %s: move to %f (initial position)",
                    msg,
                    motor.name,
                    x_c,
                )
                scaler0.select_channels(None)
                yield from bps.mv(
                    motor,
                    x_c,
                    scaler0.preset_time,
                    old_preset_time,
                    # ti_filter_shutter, "close"
                )
                raise GuardSlitTuneError(msg)

            if not found:
                yield from cleanup_then_GuardSlitTuneError(
                    f"{motor.name} Peak not found.")
            if center < x_0:  # sanity check that start <= COM
                msg = f"{motor.name}: Computed center too low: {center} < {x_0}"
                yield from cleanup_then_GuardSlitTuneError(msg)
            if center > x_n:  # sanity check that COM  <= end
                yield from cleanup_then_GuardSlitTuneError(
                    f"{motor.name}: Computed center too high: {center} > {x_n}"
                )
            if (max(tuner.peaks.y_data) <=
                    guard_slit.tuning_intensity_threshold):
                msg = f"{motor.name}: Peak intensity not strong enough to tune."
                msg += f" {max(tuner.peaks.y_data)} < {guard_slit.tuning_intensity_threshold}"
                yield from cleanup_then_GuardSlitTuneError(msg)

            logger.info(f"{motor.name}: move to {center} (center of mass)")
            yield from bps.mv(motor, center)

    # Here is the MAIN EVENT
    try:
        yield from tune_guard_slit_motor(guard_slit.y, 2, 50)
    except GuardSlitTuneError as exc:
        logger.warning("Could not tune guard_slit.y -- %s", str(exc))
    try:
        yield from tune_guard_slit_motor(guard_slit.x, 4, 20)
    except GuardSlitTuneError as exc:
        logger.warning("Could not tune guard_slit.y -- %s", str(exc))

    yield from bps.mv(scaler0.preset_time, old_preset_time)
Exemple #7
0
def ct_dark(numim=None, detectors=None, gain_std=0):
    """Collect dark images for fccd and add metadata tag for dark and gain.

The pre-count shutter & gain states preserved.

    Parameters
    -----------
    numim: int

        Number of images to be measured. If different from current
        setting, the number of images will revert back to the original
        after the scan is complete.

    detectors: list
        List of detectors to be recorded.
        Default = [fccd]

    gain_std: int
        List of detectors to be recorded.
        Default = 0   (which is 'Auto' or x8, the most sensitive gain)

    Returns
    -------

    """
    if detectors is None:
        detectors = [fccd]

    try:
        # TODO figureout kwargs and self to mkae up to line 44 a
        # single definition
        oldnumim = fccd.cam.num_images.value

        # Printing info
        print('\nStarting procedure to acquire darks '
              '{:3.3}Hz or {:3.3f}s.\n'.format(1 / fccd.cam.acquire_time.value,
                                               fccd.cam.acquire_time.value))

        print('\tCurrent number of images = {}.\n'.format(
            fccd.cam.num_images.value))

        yield from bps.sleep(.3)

        if numim is not None:
            print('\tSetting to {} images.\n'.format(numim))
            yield from bps.abs_set(fccd.cam.num_images, numim, wait=True)

        dark_shutter_state = inout.status.value
        dark_sh_dict = {'Inserted': 'In', 'Not Inserted': 'Out'}
        gain_state = fccd.cam.fcric_gain.value
        gain_bit_dict = {0: 'auto', 1: 'x2', 2: 'x1'}

        yield from bps.mv(inout, 'In')
        # This has to be 2 until we can selectively remove dark images
        # get_fastccd_images()
        yield from bps.sleep(fccd.cam.acquire_period.value * 2.01)
        # SET TO 1 TO ARM FOR NEXT EVENT so that the FastCCD1 is
        # already bkg subt
        yield from bps.mv(fccd.fccd1.capture_bgnd, 1)

        # take darks
        yield from _ct_dark(detectors, gain_std, gain_bit_dict)

        # Putting things back
        yield from _ct_dark_cleanup(oldnumim, gain_bit_dict, gain_state,
                                    dark_sh_dict, dark_shutter_state)

    except Exception:
        yield from _ct_dark_cleanup(oldnumim, gain_bit_dict, gain_state,
                                    dark_sh_dict, dark_shutter_state)
        raise
    except KeyboardInterrupt:
        yield from _ct_dark_cleanup(oldnumim, gain_bit_dict, gain_state,
                                    dark_sh_dict, dark_shutter_state)
        raise
    def fly_each_step(motor, step):
        def move_to_start_fly():
            "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook"
            yield from abs_set(xmotor, xstart-delta, group='row')
            yield from one_1d_step([temp_nanoKB], motor, step)
            yield from bps.wait(group='row')

        # t_mvstartfly = tic()
        yield from move_to_start_fly()
        # toc(t_mvstartfly, str='Move to start fly each')

        # TODO  Why are we re-trying the move?  This should be fixed at
        # a lower level
        # yield from bps.sleep(1.0)  # wait for the "x motor" to move
        x_set = xstart - delta
        x_dial = xmotor.user_readback.get()
        # Get retry deadband value and check against that
        i = 0
        if (xmotor.egu == 'mm'):
            DEADBAND = 0.0005
        else:
            DEADBAND = 0.02
        while (np.abs(x_set - x_dial) > DEADBAND):
            if (i == 0):
                print('Waiting for motor to reach starting position...',
                      end='', flush=True)
            i = i + 1
            yield from mv(xmotor, xstart - delta)
            yield from bps.sleep(0.1)
            x_dial = xmotor.user_readback.get()
        if (i != 0):
            print('done')

        # Set the scan speed
        # Is abs_set(wait=True) or mv() faster?
        v = ((xstop - xstart) / (xnum-1)) / dwell  # compute "stage speed"
        # yield from abs_set(xmotor.velocity, v, wait=True)  # set the "stage speed"
        yield from mv(xmotor.velocity, v)
        # Change backlash speed for hf_stage.x and hf_stage.y
        if (hf_stage.x is xmotor):
            yield from mv(hf_stage.BACKLASH_SPEED_X, v)
        if (hf_stage.y is xmotor):
            yield from mv(hf_stage.BACKLASH_SPEED_Y, v)

        # set up all of the detectors
        # TODO we should be able to move this out of the per-line call?!
        if ('xs' in dets_by_name):
            xs = dets_by_name['xs']
            # yield from abs_set(xs.hdf5.num_capture, xnum, wait=True)
            # yield from abs_set(xs.settings.num_images, xnum, wait=True)
            yield from mv(xs.hdf5.num_capture, xnum,
                          xs.settings.num_images, xnum)

        if ('xs2' in dets_by_name):
            xs2 = dets_by_name['xs2']
            # yield from abs_set(xs2.hdf5.num_capture, xnum, wait=True)
            # yield from abs_set(xs2.settings.num_images, xnum, wait=True)
            yield from mv(xs2.hdf5.num_capture, xnum,
                          xs2.settings.num_images, xnum)

        if ('merlin' in dets_by_name):
            merlin = dets_by_name['merlin']
            yield from abs_set(merlin.hdf5.num_capture, xnum, wait=True)
            yield from abs_set(merlin.cam.num_images, xnum, wait=True)

        if ('dexela' in dets_by_name):
            dexela = dets_by_name['dexela']
            yield from abs_set(dexela.hdf5.num_capture, xnum, wait=True)
            yield from abs_set(dexela.cam.num_images, xnum, wait=True)

        ion = flying_zebra.sclr
        yield from abs_set(ion.nuse_all,xnum)

        # arm the Zebra (start caching x positions)
        # @timer_wrapper
        def zebra_kickoff():
            yield from kickoff(flying_zebra,
                               xstart=xstart, xstop=xstop, xnum=xnum, dwell=dwell,
                               wait=True)
        # t_zebkickoff = tic()
        yield from zebra_kickoff()
        # toc(t_zebkickoff, str='Zebra kickoff')

        # arm SIS3820, note that there is a 1 sec delay in setting X
        # into motion so the first point *in each row* won't
        # normalize...
        yield from abs_set(ion.erase_start, 1)

        # trigger all of the detectors
        for d in flying_zebra.detectors:
            yield from bps.trigger(d, group='row')
            if (d.name == 'dexela'):
                yield from bps.sleep(1)

        yield from bps.sleep(1.5)
        # start the 'fly'
        yield from abs_set(xmotor, xstop + 1*delta, group='row')  # move in x
        # wait for the motor and detectors to all agree they are done
        yield from bps.wait(group='row')

        # we still know about ion from above
        yield from abs_set(ion.stop_all, 1)  # stop acquiring scaler

        # @timer_wrapper
        def zebra_complete():
            yield from complete(flying_zebra)  # tell the Zebra we are done
        # t_zebcomplete = tic()
        yield from zebra_complete()
        # toc(t_zebcomplete, str='Zebra complete')


        # @timer_wrapper
        def zebra_collect():
            yield from collect(flying_zebra)  # extract data from Zebra
        # t_zebcollect = tic()
        yield from zebra_collect()
        # toc(t_zebcollect, str='Zebra collect')

        # TODO what?
        if ('e_tomo' in xmotor.name):
            v_return = min(4, xmotor.velocity.high_limit)
            yield from mv(xmotor.velocity, v_return)
        if ('nano_stage' in xmotor.name):
            yield from mv(xmotor.velocity, 30)
        else:
            # set the "stage speed"
            yield from mv(xmotor.velocity, 1.0)
 def infinite_plan():
     while True:
         for i in range(1, 5):
             yield from sleep(2)
             yield from scan([det], motor, -1, 1, 5 * i)
def planHeaterProcess():
    """BS plan: Run one temperature profile on the sample heater."""
    log_it(f"Starting planHeaterProcess() for {linkam.name}")
    report()

    yield from bps.mv(
        linkam.ramp,
        3,
    )
    log_it(f"Change {linkam.name.get()} rate to {linkam.ramp.get():.0f} C/min")

    t0 = time.time()
    # note: bps.mv waits until OBJECT.done.get() == 1 (just like a motor)
    # bps.abs_set only _sets_ the setpoint, must wait in a later step
    yield from bps.abs_set(
        linkam,
        1083,
    )
    log_it(
        f"Change {linkam.name.get()} setpoint to {linkam.setpoint.get():.2f} C"
    )
    while linkam.done.get() not in (1, "Done"):
        if linkam_exit.get():  # Watch for user exit while waiting
            yield from bps.abs_set(linkam.stop_signal, linkam_stop_value)
            log_it("User requested exit during set"
                   f" after {(time.time()-t0)/60:.2f}m."
                   " Stopping the heater.")
            report()
            return
        yield from bps.sleep(1)
    log_it(f"Done, that took {time.time()-t0:.2f}s")
    report()

    # two hours = 2 * HOUR, two minutes = 2 * MINUTE
    log_it("{linkam.name.get()} holding for 3 hours")
    t0 = time.time()
    time_expires = t0 + 3 * HOUR
    while time.time() < time_expires:
        if linkam_exit.get():
            yield from bps.abs_set(linkam.stop_signal, linkam_stop_value)
            log_it("User requested exit during hold"
                   f" after {(time.time()-t0)/60:.2f}m."
                   " Stopping the heater.")
            report()
            return
        yield from bps.sleep(1)
    log_it("{linkam.name.get()} holding period ended")
    report()

    # Change rate to 3 C/min :
    yield from bps.mv(
        linkam.ramp,
        3,
    )
    log_it(f"Change {linkam.name.get()} rate to {linkam.ramp.get():.0f} C/min")
    t0 = time.time()
    yield from bps.abs_set(
        linkam,
        40,
    )
    log_it(
        f"Change {linkam.name.get()} setpoint to {linkam.setpoint.get():.2f} C"
    )
    while linkam.done.get() not in (1, "Done"):
        if linkam_exit.get():  # Watch for user exit while waiting
            yield from bps.abs_set(linkam.stop_signal, linkam_stop_value)
            log_it("User requested exit during set"
                   f" after {(time.time()-t0)/60:.2f}m."
                   " Stopping the heater.")
            report()
            return
        yield from bps.sleep(1)
    # note: bps.mv waits until OBJECT.done.get() == 1 (just like a motor)
    log_it(f"Done, that took {time.time()-t0:.2f}s")
    report()

    # DEMO: signal for an orderly exit after first run
    yield from bps.mv(linkam_exit, True)
def change_xtals(xtal=None):
    '''Move between the Si(111) and Si(311) monochromators, also moving
     2nd crystal pitch and roll to approximate positions.  Then do a
     rocking curve scan.
     '''
    if xtal is None:
        print('No crystal set specified')
        return (yield from null())

    (ok, text) = BMM_clear_to_start()
    if ok == 0:
        print(error_msg(text))
        yield from null()
        return

    BMMuser, RE, dcm, dm3_bct = user_ns['BMMuser'], user_ns['RE'], user_ns[
        'dcm'], user_ns['dm3_bct']
    dcm_pitch, dcm_roll, dcm_x = user_ns['dcm_pitch'], user_ns[
        'dcm_roll'], user_ns['dcm_x']

    if '111' in xtal:
        xtal = 'Si(111)'
    if '311' in xtal:
        xtal = 'Si(311)'

    if xtal not in ('Si(111)', 'Si(311)'):
        print('%s is not a crytsal set' % xtal)
        return (yield from null())

    ######################################################################
    # this is a tool for verifying a macro.  this replaces an xafs scan  #
    # with a sleep, allowing the user to easily map out motor motions in #
    # a macro                                                            #
    if BMMuser.macro_dryrun:
        print(
            info_msg(
                '\nBMMuser.macro_dryrun is True.  Sleeping for %.1f seconds rather than changing to the %s crystal.\n'
                % (BMMuser.macro_sleep, xtal)))
        countdown(BMMuser.macro_sleep)
        return (yield from null())
    ######################################################################

    print('Moving to %s crystals' % xtal)
    action = input('Begin moving motors? [Y/n then Enter] ')
    if action.lower() == 'q' or action.lower() == 'n':
        yield from null()
        return

    current_energy = dcm.energy.readback.get()
    start = time.time()

    RE.msg_hook = None
    BMM_log_info('Moving to the %s crystals' % xtal)
    yield from mv(dcm_pitch.kill_cmd, 1)
    yield from mv(dcm_roll.kill_cmd, 1)
    if xtal is 'Si(111)':
        yield from mv(dcm_pitch, 4.1, dcm_roll, -6.26, dcm_x, 0.5)
        #dcm._crystal = '111'
        dcm.set_crystal('111')  # set d-spacing and bragg offset
    elif xtal is 'Si(311)':
        yield from mv(dcm_pitch, 2.28, dcm_roll, -23.86, dcm_x, 65.3)
        #dcm._crystal = '311'
        dcm.set_crystal('311')  # set d-spacing and bragg offset

    yield from sleep(2.0)
    yield from mv(dcm_roll.kill_cmd, 1)

    print('Returning to %.1f eV' % current_energy)
    yield from mv(dcm.energy, current_energy)

    print('Performing a rocking curve scan')
    yield from mv(dcm_pitch.kill_cmd, 1)
    yield from mv(dcm_pitch, approximate_pitch(current_energy))
    yield from sleep(1)
    yield from mv(dcm_pitch.kill_cmd, 1)
    yield from rocking_curve()
    yield from sleep(2.0)
    yield from mv(dcm_pitch.kill_cmd, 1)
    RE.msg_hook = BMM_msg_hook
    BMM_log_info(motor_status())
    close_last_plot()
    end = time.time()
    print('\n\nTime elapsed: %.1f min' % ((end - start) / 60))
def change_mode(mode=None,
                prompt=True,
                edge=None,
                reference=None,
                bender=True):
    '''Move the photon delivery system to a new mode. 
     A: focused at XAS end station, energy > 8000
     B: focused at XAS end station, energy < 6000
     C: focused at XAS end station, 6000 < energy < 8000
     D: unfocused, energy > 8000
     E: unfocused, 6000 < energy < 8000
     F: unfocused, energy < 8000
     XRD: focused at XRD end station, energy > 8000
     '''
    BMMuser, RE, dcm, dm3_bct, slits3 = user_ns['BMMuser'], user_ns[
        'RE'], user_ns['dcm'], user_ns['dm3_bct'], user_ns['slits3']
    xafs_table, m3, m2, m2_bender, xafs_ref = user_ns['xafs_table'], user_ns[
        'm3'], user_ns['m2'], user_ns['m2_bender'], user_ns['xafs_ref']
    if mode is None:
        print('No mode specified')
        return (yield from null())

    mode = mode.upper()
    if mode not in ('A', 'B', 'C', 'D', 'E', 'F', 'XRD'):
        print('%s is not a mode' % mode)
        return (yield from null())
    current_mode = get_mode()

    # crude hack around a problem I don't understand
    if dm3_bct.hlm.get() < 55 or dm3_bct.llm.get() > -55:
        dm3_bct.llm.put(-60)
        dm3_bct.hlm.put(60)

    if pds_motors_ready() is False:
        print(
            error_msg(
                '\nOne or more motors are showing amplifier faults.\nToggle the correct kill switch, then re-enable the faulted motor.'
            ))
        return (yield from null())

    ######################################################################
    # this is a tool for verifying a macro.  this replaces an xafs scan  #
    # with a sleep, allowing the user to easily map out motor motions in #
    # a macro                                                            #
    if BMMuser.macro_dryrun:
        print(
            info_msg(
                '\nBMMuser.macro_dryrun is True.  Sleeping for %.1f seconds rather than changing to mode %s.\n'
                % (BMMuser.macro_sleep, mode)))
        countdown(BMMuser.macro_sleep)
        return (yield from null())
    ######################################################################

    if mode == 'B':
        action = input(
            "You are entering Mode B -- focused beam below 6 keV is not properly configured at BMM. Continue? [y/N then Enter] "
        )
        if action.lower() != 'y':
            return (yield from null())

    if mode == 'A':
        description = 'focused, >8 keV'
    elif mode == 'B':
        description = 'focused, <6 keV'
    elif mode == 'C':
        description = 'focused, 6 to 8 keV'
    elif mode == 'D':
        description = 'unfocused, >8 keV'
    elif mode == 'E':
        description = 'unfocused, 6 to 8 keV'
    elif mode == 'F':
        description = 'unfocused, <6 keV'
    elif mode == 'XRD':
        description = 'focused at goniometer, >8 keV'
        print('Moving to mode %s (%s)' % (mode, description))
    if prompt:
        action = input("Begin moving motors? [Y/n then Enter] ")
        if action.lower() == 'q' or action.lower() == 'n':
            return (yield from null())

    RE.msg_hook = None
    BMM_log_info('Changing photon delivery system to mode %s' % mode)

    base = [
        dm3_bct,
        float(MODEDATA['dm3_bct'][mode]),
        xafs_table.yu,
        float(MODEDATA['xafs_yu'][mode]),
        xafs_table.ydo,
        float(MODEDATA['xafs_ydo'][mode]),
        xafs_table.ydi,
        float(MODEDATA['xafs_ydi'][mode]),
        m3.yu,
        float(MODEDATA['m3_yu'][mode]),
        m3.ydo,
        float(MODEDATA['m3_ydo'][mode]),
        m3.ydi,
        float(MODEDATA['m3_ydi'][mode]),
        m3.xu,
        float(MODEDATA['m3_xu'][mode]),
        m3.xd,
        float(MODEDATA['m3_xd'][mode]),
    ]
    if reference is not None:
        #base.extend([xafs_linxs, foils.position(reference.capitalize())])
        base.extend(
            [xafs_ref,
             xafs_ref.position_of_slot(reference.capitalize())])
    if edge is not None:
        #dcm_bragg.clear_encoder_loss()
        base.extend([dcm.energy, edge])
    # if mode in ('D', 'E', 'F'):
    #      base.extend([slits3.hcenter, 2])
    # else:
    #      base.extend([slits3.hcenter, 0])

    ###################################################################
    # check for amplifier faults on the motors, return without moving #
    # anything if any are found                                       #
    ###################################################################
    motors_ready = True
    problem_motors = list()
    for m in base[::2]:
        try:  # skip non-FMBO motors, which do not have the amfe or amfae attributes
            if m.amfe.get() == 1 or m.amfae.get() == 1:
                motors_ready = False
                problem_motors.append(m.name)
        except:
            continue
    if motors_ready is False:
        BMMuser.motor_fault = ', '.join(problem_motors)
        return (yield from null())

    ##########################
    # do the motor movements #
    ##########################
    yield from dcm.kill_plan()
    if dm3_bct.ampen.get() == 0:
        yield from mv(dm3_bct.enable_cmd, 1)
    #yield from mv(dm3_bct.kill_cmd, 1) # need to explicitly kill this before
    # starting a move, it is one of the
    # motors that reports MOVN=1 even when
    # still
    yield from sleep(0.2)
    yield from mv(dm3_bct.kill_cmd, 1)

    if mode in ('D', 'E', 'F') and current_mode in ('D', 'E', 'F'):
        yield from mv(*base)
    elif mode in ('A', 'B',
                  'C') and current_mode in ('A', 'B',
                                            'C'):  # no need to move M2
        yield from mv(*base)
    else:
        if bender is True:
            yield from mv(m2_bender.kill_cmd, 1)
            if mode == 'XRD':
                if abs(
                        m2_bender.user_readback.get() - BMMuser.bender_xrd
                ) > BMMuser.bender_margin:  # give some wiggle room for having
                    base.extend([m2_bender, BMMuser.bender_xrd
                                 ])  # recently adjusted the bend
            elif mode in ('A', 'B', 'C'):
                if abs(m2_bender.user_readback.get() -
                       BMMuser.bender_xas) > BMMuser.bender_margin:
                    base.extend([m2_bender, BMMuser.bender_xas])

        base.extend([m2.yu, float(MODEDATA['m2_yu'][mode])])
        base.extend([m2.ydo, float(MODEDATA['m2_ydo'][mode])])
        base.extend([m2.ydi, float(MODEDATA['m2_ydi'][mode])])
        yield from mv(*base)

    yield from sleep(2.0)
    yield from mv(m2_bender.kill_cmd, 1)
    yield from mv(dm3_bct.kill_cmd, 1)
    yield from m2.kill_jacks()
    yield from m3.kill_jacks()

    BMMuser.pds_mode = mode
    RE.msg_hook = BMM_msg_hook
    BMM_log_info(motor_status())
Exemple #13
0
def _inner_loop(dets,
                exposure_count,
                delay,
                deadline,
                per_step,
                stream_name,
                done_signal=None):
    """Helper plan for the inner loop of the sinter plans

    This is very much like the repeat plan, but has less
    delay input types and more logic about finishing on a deadline.

    Parameters
    ----------
    dets : List[OphydObj]
        The detectors passed to per_step

    exposure_count : int
        The maximum number of times to call per_step

    delay : float
        The target delay between subsequent starts of per_step.

    deadline : float
         Wall time to be done by.  Under no condition take longer
         than this to completely run through plan.

    per_step : Callable[List[OphydObj], Optional[str]] -> Generator[Msg]
        The plan to run 'per step'.

        This is the signature of triger_and_read

    primary : str
        Passed to per_step

    done_signal : Signal, optional
        If passed, will exit early when goes to 1
    """
    if done_signal is not None:

        from bluesky.utils import first_key_heuristic
        signal_key = first_key_heuristic(done_signal)

        def _check_signal():
            val = yield from bps.read(done_signal)
            if val is None:
                return True
            val = val[signal_key]['value']
            return bool(val)
    else:
        _check_signal = None

    for j in range(exposure_count):
        start_time = time.monotonic()

        yield from bps.checkpoint()
        # if things get bogged down in data collection, bail early!
        if start_time > deadline:
            print(f'{start_time} > {deadline} bail!')
            break

        # this triggers the cameras
        yield from per_step(dets, stream_name)

        stop_time = time.monotonic()
        exp_actual = stop_time - start_time
        sleep_time = delay - exp_actual

        yield from bps.checkpoint()
        if _check_signal is not None:
            done = yield from _check_signal()
            if done:
                return
        if stop_time + sleep_time > deadline:
            yield from bps.sleep(deadline - stop_time)
            return
        else:
            yield from bps.sleep(delay - exp_actual)
 def cleanup_plan(slp):
     yield from mv(slits3.vsize, slit_height)
     yield from abs_set(user_ns['_locked_dwell_time'], 0.5, wait=True)
     yield from sleep(slp)
     yield from abs_set(motor.kill_cmd, 1, wait=True)
     yield from resting_state_plan()
def pe_count(
    filename="",
    exposure=1,
    num_images: int = 1,
    num_dark_images: int = 1,
    num_repetitions: int = 5,
    delay=60,
):

    year = "2020"  # RE.md["year"]
    cycle = "C2"  # RE.md["cycle"]
    proposal = "67890"  # RE.md["PROPOSAL"]

    # write_path_template = 'Z:\\data\\pe1_data\\%Y\\%m\\%d\\'
    # write_path_template = f"Z:\\users\\{year}\\{cycle}\\{proposal}XRD\\"
    # file_path = datetime.now().strftime(write_path_template)
    # filename = filename + str(uuid.uuid4())[:6]

    # this is an example of what would be used at the beamline
    pe_detector.tiff_writer.resource_root_path = PureWindowsPath(
        f"Z:\\users\\")
    pe_detector.tiff_writer.relative_write_path = PureWindowsPath(
        f"{year}\\{cycle}\\{proposal}XRD\\")

    # for testing
    pe_detector.tiff_writer.resource_root_path = Path("/tmp/")
    pe_detector.tiff_writer.relative_write_path = Path(
        f"perkin_elmer/detector/{year}/{cycle}/XRD{proposal}"  # remove "XRD" from the end?
    )

    # start the run
    yield from bps.open_run()

    # stage the detector
    yield from bps.stage(pe_detector)

    yield from bps.mv(pe_detector.tiff_writer.file_number, 1)
    tiff_full_file_path = (pe_detector.tiff_writer.resource_root_path /
                           pe_detector.tiff_writer.relative_write_path)

    print(f"tiff_full_file_path: {str(tiff_full_file_path)}")
    yield from bps.mv(pe_detector.tiff_writer.file_path,
                      str(tiff_full_file_path))

    for repetition_index in range(int(num_repetitions)):

        print("\n")
        print(
            "<<<<<<<<<<<<<<<<< Doing repetition {} out of {} >>>>>>>>>>>>>>>>>"
            .format(repetition_index + 1, num_repetitions))

        # TiffWriter or similar plugin should do this
        yield from bps.mv(pe_detector.tiff_writer.file_name,
                          filename + str(uuid.uuid4()))

        if num_dark_images > 0:
            # originally used pe_detector.num_dark_images
            # but this is really pe_num_offset_frames
            yield from bps.mv(pe_detector.cam.pe_num_offset_frames,
                              num_dark_images)
            yield from bps.mv(
                pe_detector.cam.image_mode,
                PerkinElmerCamera.PerkinElmerImageMode.AVERAGE,
            )
            # yield from bps.mv(fast_shutter, "Close")
            yield from bps.sleep(0.5)
            yield from bps.mv(pe_detector.tiff_writer.file_write_mode,
                              NDFile.FileWriteMode.SINGLE)

            # acquire a "dark frame"
            pe_acquire_offset_status = SubscriptionStatus(
                pe_detector.cam.pe_acquire_offset,
                high_to_low_pe_acquire_offset)
            yield from bps.abs_set(
                pe_detector.cam.pe_acquire_offset,
                PerkinElmerCamera.AcquireOffset.ACQUIRE,
                wait=False,
            )
            yield Msg("wait_for_status", None, pe_acquire_offset_status)

            yield from bps.mv(pe_detector.tiff_writer.write_file,
                              NDFile.WriteFile.WRITE)

        # yield from bps.mv(
        #  pe1.cam.image_mode,
        #  NewPerkinElmerDetector.ImageMode.MULTIPLE
        # )
        yield from bps.mv(
            pe_detector.cam.image_mode,
            PerkinElmerCamera.PerkinElmerImageMode.AVERAGE,
        )
        yield from bps.mv(pe_detector.cam.acquire_time, exposure)
        yield from bps.mv(pe_detector.cam.num_images, num_images)

        # yield from bps.mv(fast_shutter, "Open")
        yield from bps.sleep(0.5)

        ## Below 'Capture' mode is used with 'Multiple' image_mode
        # yield from bps.mv(pe1.tiff_writer.file_write_mode, 'Capture')

        ## Below 'Single' mode is used with 'Average' image_mode
        yield from bps.mv(
            pe_detector.tiff_writer.file_write_mode,
            NDFile.FileWriteMode.SINGLE,  # "Single"
        )

        ## Uncomment 'capture' bit settings when used in 'Capture' mode
        # yield from bps.mv(pe1.tiff_writer.capture, 1)

        # this was the old way to initiate the acquisition
        # yield from bps.mv(pe_detector, "acquire_light")

        yield from bps.trigger_and_read([pe_detector], name="primary")

        # can TiffWriter or similar plugin do this?
        ##Below write_file is needed when used in 'Average' mode
        yield from bps.mv(
            pe_detector.tiff_writer.write_file,
            NDFile.WriteFile.WRITE  # 1
        )

        yield from bps.sleep(delay)

    # unstage the detector
    yield from bps.unstage(pe_detector)

    # end the run
    yield from bps.close_run()
Exemple #16
0
def delay_scan(detectors,
               motor,
               E0,
               start,
               stop,
               step_size,
               delay_time,
               per_step=delay_per_step,
               md={}):
    """
    Scan over one multi-motor trajectory with delay time.

    Parameters
    ----------
    detectors : list
        list of 'readable' objects

    motor : object, any 'settable' object (motor, temp controller, etc.)

    E0 : edge energy in eV

    start : start energy in eV

    stop : stop energy in eV

    step_size : energy step in eV

    per_step : callable, optional
               hook for customizing action of inner loop (messages per step)
               Expected signature:
               ``f(detectors, motor, step, delay_time) -> plan (a generator)``
    md : dict, optional, metadata

    See Also
    --------
    :func:`bluesky.plans.relative_inner_product_scan`
    :func:`bluesky.plans.grid_scan`
    :func:`bluesky.plans.scan_nd`
    """

    _md = {
        'detectors': [det.name for det in detectors],
        'motors': [motor.name],
        'plan_name': 'delay_scan',
        'delay_after_set_energy': delay_time,
        'hints': {},
    }
    _md.update(md or {})

    if per_step is None:
        per_step = bps.one_1d_step

    num = int((stop - start) / step_size) + 1
    start = E0 + start
    stop = E0 + stop
    scan_list = np.linspace(start, stop, num, endpoint=True)

    @bpp.stage_decorator(list(detectors) + [motor])
    @bpp.run_decorator(md=_md)
    def inner_scan_nd():
        for step in list(scan_list):
            yield from per_step(detectors, motor, step, delay_time)

    # # move Energy to E0
    # yield from bps.mv(dcm.energy, E0)

    # move Energy to Start_Energy - 200 eV
    yield from bps.mv(dcm.energy, start - 200)

    # sleep 2 seconds
    yield from bps.sleep(2)

    # move Energy to Start_Energy
    yield from bps.mv(dcm.energy, start)

    # sleep 1 seconds
    yield from bps.sleep(1)

    # mark as a checkpoint, motor comeback to this position
    # when scan is interrupted
    yield from bps.checkpoint()

    yield from inner_scan_nd()

    # move back to E0 after scan
    return (yield from bps.mv(dcm.energy, E0))
Exemple #17
0
def energy_list_scan(detectors,
                     motor,
                     E0,
                     energy_list,
                     time_list,
                     delay_time,
                     per_step=delay_per_step,
                     md={}):
    """
    Scan over energy lists.

    Parameters
    ----------
    detectors : list, list of 'readable' objects
    motor : object, any 'settable' object (motor, temp controller, etc.)
    E0 : edge energy in eV
    energy_list : list of energy list
    time_list : count time list
    per_step : callable, optional
               hook for customizing action of inner loop (messages per step)
               Expected signature:
               ``f(detectors, motor, step, delay_time) -> plan (a generator)``
    md : dict, optional, metadata
    """
    energy_list = list(energy_list)

    np_energy_list = np.array(energy_list).flatten()
    num_points = len(np_energy_list)

    _md = {
        'detectors': [det.name for det in detectors],
        'motors': [motor.name],
        'num_points': num_points,
        'num_intervals': num_points - 1,
        'plan_name': 'energy_list_scan',
        'delay_after_set_energy': delay_time,
        'hints': {},
    }
    _md.update(md or {})

    if per_step is None:
        per_step = bps.one_1d_step

    @bpp.stage_decorator(list(detectors) + [motor])
    @bpp.run_decorator(md=_md)
    def inner_list_scan(energy_list, time_list):
        index = 0
        for item in time_list:
            # set counter time
            yield from bps.abs_set(scaler.preset_time, item)

            # move and count
            for step in energy_list[index]:
                yield from per_step(detectors, motor, step, delay_time)
            index += 1

    startEnergy = energy_list[0][0]

    # move Energy to Start_Energy - 200 eV
    yield from bps.mv(dcm.energy, startEnergy - 200)

    # sleep 2 seconds at -200 eV from Start_Energy
    yield from bps.sleep(2)

    # move Energy to Start_Energy
    yield from bps.mv(dcm.energy, startEnergy)

    # sleep 1 seconds at Start_Energy
    yield from bps.sleep(1)

    # mark as a checkpoint, motor comeback to this position
    # when scan is interrupted
    yield from bps.checkpoint()
    yield from inner_list_scan(energy_list, time_list)

    # move back to E0 after scan
    yield from bps.mv(dcm.energy, E0)

    return 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
Exemple #19
0
def change_edge(el,
                focus=False,
                edge='K',
                energy=None,
                slits=True,
                target=300.,
                xrd=False,
                bender=True):
    '''Change edge energy by:
    1. Moving the DCM above the edge energy
    2. Moving the photon delivery system to the correct mode
    3. Running a rocking curve scan
    4. Running a slits_height scan

    Parameters
    ----------
    el : str
        one- or two-letter symbol
    focus : bool, optional
        T=focused or F=unfocused beam [False, unfocused]
    edge : str, optional
        edge symbol ['K']
    energy : float, optional
        e0 value [None, determined from el/edge]
    slits : bool, optional
        perform slit_height() scan [False]
    target : float, optional
        energy where rocking curve is measured [300]
    xrd : boolean, optional
        force photon delivery system to XRD [False]

    Examples
    --------
    Normal use, unfocused beam:
       
    >>> RE(change_edge('Fe'))

    Normal use, focused beam:
       
    >>> RE(change_edge('Fe', focus=True))

    L2 or L1 edge:
       
    >>> RE(change_edge('Re', edge='L2'))

    Measure rocking curve at edge energy:
      
    >>> RE(change_edge('Fe', target=0))

    XRD, new energy:
       
    >>> RE(change_edge('Fe', xrd=True, energy=8600))
        
    note that you must specify an element, but it doesn't matter which
    one the energy will be moved to the specified energy xrd=True
    implies focus=True and target=0

    '''
    BMMuser, RE, dcm, dm3_bct, dcm_pitch = user_ns['BMMuser'], user_ns[
        'RE'], user_ns['dcm'], user_ns['dm3_bct'], user_ns['dcm_pitch']
    rkvs = user_ns['rkvs']
    try:
        xs = user_ns['xs']
    except:
        pass
    #BMMuser.prompt = True
    el = el.capitalize()

    ######################################################################
    # this is a tool for verifying a macro.  this replaces an xafsmod scan  #
    # with a sleep, allowing the user to easily map out motor motions in #
    # a macro                                                            #
    if BMMuser.macro_dryrun:
        print(
            info_msg(
                '\nBMMuser.macro_dryrun is True.  Sleeping for %.1f seconds rather than changing to the %s edge.\n'
                % (BMMuser.macro_sleep, el)))
        countdown(BMMuser.macro_sleep)
        return (yield from null())
    ######################################################################

    if pds_motors_ready() is False:
        print(
            error_msg(
                '\nOne or more motors are showing amplifier faults.\nToggle the correct kill switch, then re-enable the faulted motor.'
            ))
        return (yield from null())

    (ok, text) = BMM_clear_to_start()
    if ok is False:
        print(
            error_msg('\n' + text) +
            bold_msg('Quitting change_edge() macro....\n'))
        return (yield from null())

    if energy is None:
        energy = edge_energy(el, edge)

    if energy is None:
        print(
            error_msg('\nEither %s or %s is not a valid symbol\n' %
                      (el, edge)))
        return (yield from null())
    if energy > 23500:
        edge = 'L3'
        energy = edge_energy(el, 'L3')

    if energy < 4000:
        print(warning_msg('The %s edge energy is below 4950 eV' % el))
        print(warning_msg('You have to change energy by hand.'))
        return (yield from null())

    if energy > 23500:
        print(
            warning_msg(
                'The %s edge energy is outside the range of this beamline!' %
                el))
        return (yield from null())

    BMMuser.edge = edge
    BMMuser.element = el
    BMMuser.edge_energy = energy
    rkvs.set('BMM:pds:edge', edge)
    rkvs.set('BMM:pds:element', el)
    rkvs.set('BMM:pds:edge_energy', energy)

    if energy > 8000:
        mode = 'A' if focus else 'D'
    elif energy < 6000:
        #mode = 'B' if focus else 'F'   ## mode B currently is inaccessible :(
        mode = 'C' if focus else 'F'
    else:
        mode = 'C' if focus else 'E'
    if xrd:
        mode = 'XRD'
        focus = True
        target = 0.0
    current_mode = get_mode()

    ################################
    # confirm configuration change #
    ################################
    print(bold_msg('\nEnergy change:'))
    print('   %s: %s %s' %
          (list_msg('edge'), el.capitalize(), edge.capitalize()))
    print('   %s: %.1f' % (list_msg('edge energy'), energy))
    print('   %s: %.1f' % (list_msg('target energy'), energy + target))
    print('   %s: %s' % (list_msg('focus'), str(focus)))
    print('   %s: %s' % (list_msg('photon delivery mode'), mode))
    print('   %s: %s' % (list_msg('optimizing slits height'), str(slits)))
    if BMMuser.prompt:
        action = input("\nBegin energy change? [Y/n then Enter] ")
        if action.lower() == 'q' or action.lower() == 'n':
            return (yield from null())
        if mode == 'C' and energy < 6000:
            print(
                warning_msg(
                    '\nMoving to mode C for focused beam and an edge energy below 6 keV.'
                ))
            action = input(
                "You will not get optimal harmonic rejection.  Continue anyway?  [Y/n then Enter] "
            )
            if action.lower() == 'q' or action.lower() == 'n':
                return (yield from null())

    start = time.time()
    if mode == 'XRD':
        report('Configuring beamline for XRD', level='bold', slack=True)
    else:
        report(
            f'Configuring beamline for {el.capitalize()} {edge.capitalize()} edge',
            level='bold',
            slack=True)
    yield from dcm.kill_plan()

    ################################################
    # change to the correct photon delivery mode   #
    #      + move mono to correct energy           #
    #      + move reference holder to correct slot #
    ################################################
    # if not calibrating and mode != current_mode:
    #     print('Moving to photon delivery mode %s...' % mode)
    yield from change_mode(mode=mode,
                           prompt=False,
                           edge=energy + target,
                           reference=el,
                           bender=bender)
    if arrived_in_mode(mode=mode) is False:
        print(error_msg(f'\nFailed to arrive in Mode {mode}'))
        print(
            'Fixing this is often as simple as re-running the change_mode() command.'
        )
        print('If that doesn\'t work, call for help')
        return (yield from null())

    yield from user_ns['kill_mirror_jacks']()
    yield from sleep(1)
    if BMMuser.motor_fault is not None:
        print(
            error_msg('\nSome motors are reporting amplifier faults: %s' %
                      BMMuser.motor_fault))
        print(
            'Clear the faults and try running the same change_edge() command again.'
        )
        print('Troubleshooting: ' + url_msg(
            'https://nsls-ii-bmm.github.io/BeamlineManual/trouble.html#amplifier-fault'
        ))
        BMMuser.motor_fault = None
        return (yield from null())
    BMMuser.motor_fault = None

    ############################
    # run a rocking curve scan #
    ############################
    print('Optimizing rocking curve...')
    yield from abs_set(dcm_pitch.kill_cmd, 1, wait=True)
    yield from mv(dcm_pitch, approximate_pitch(energy + target))
    yield from sleep(1)
    yield from abs_set(dcm_pitch.kill_cmd, 1, wait=True)
    yield from rocking_curve()
    close_last_plot()

    ##########################
    # run a slit height scan #
    ##########################
    if slits:
        print('Optimizing slits height...')
        yield from slit_height(move=True)
        close_last_plot()
        ## redo rocking curve?

    ##################################
    # set reference and roi channels #
    ##################################
    if not xrd:
        ## reference channel
        rois = user_ns['rois']
        print('Moving reference foil...')
        yield from rois.select_plan(el)
        ## Xspress3
        BMMuser.verify_roi(xs, el, edge)
        ## feedback
        show_edges()

    if mode == 'XRD':
        report('Finished configuring for XRD', level='bold', slack=True)
    else:
        report(
            f'Finished configuring for {el.capitalize()} {edge.capitalize()} edge',
            level='bold',
            slack=True)
    if slits is False:
        print(
            '  * You may need to verify the slit position:  RE(slit_height())')
    yield from dcm.kill_plan()
    end = time.time()
    print('\n\nThat took %.1f min' % ((end - start) / 60))
    return ()
Exemple #20
0
def E_Step_Scan(scan_title,
                *,
                operator,
                element,
                dwell_time=3,
                E_sections,
                step_size,
                num_scans,
                xspress3=None):
    #def E_Step_Scan(dwell_time,*, scan_title = "abc",E_sections = [2700, 2800, 2900, 3200], step_size = [4, 1, 2], num_scans=2, element = 's'):

    #for v in ["p1600=0", "p1607=4", "p1601=5", "p1602 = 2", "p1600=1"]:
    #yield from bps.mv(dtt, v)
    #yield from bps.sleep(0.1)
    roi = rois(element)
    yield from bps.mv(xs.channel1.rois.roi01.bin_low, roi[0],
                      xs.channel1.rois.roi01.bin_high, roi[1])
    yield from bps.sleep(0.1)
    #    xs.channel1.rois.roi01.bin_low.set(roi[0])
    #    xs.channel1.rois.roi01.bin_high.set(roi[1])
    E_sections = np.array(E_sections)
    step_size = np.array(step_size)

    ept = []
    for ii in range(step_size.shape[0]):
        ept = ept[0:-1]
        ept = np.append(
            ept,
            np.linspace(
                E_sections[ii], E_sections[ii + 1],
                np.int((E_sections[ii + 1] - E_sections[ii]) / step_size[ii]) +
                1))

    sclr.set_mode("counting")
    yield from bps.mv(xs.external_trig, False)
    yield from bps.mv(sclr.cnts.preset_time, dwell_time,
                      xs.settings.acquire_time, dwell_time)

    #yield from bps.mv(sclr.set_mode,"counting")

    #yield from bps.sleep(0.1)
    #@bpp.monitor_during_decorator([xs.channel1.rois.roi01.value])
    #@bpp.baseline_decorator([mono, xy_stage])
    # TODO put in other meta data
    def scan_once():
        return (yield from list_scan(
            [sclr, xs],
            mono.energy,
            ept,
            md={
                "scan_title": scan_title,
                "operator": operator,
                "user_input": {
                    "element": element,
                    "E_sections": E_sections,
                    "dwell_time": dwell_time,
                    "step_size": step_size,
                },
                "derived_input": {},
            }))

    for scan_iter in range(num_scans):
        yield from scan_once()
        h = db[-1]
        E = h.table()['mono_energy']
        I0 = h.table()['I0']
        If = h.table()['xs_channel1_rois_roi01_value_sum']
        df = pd.DataFrame({'#Energy': E, 'I0': I0, 'If': If})

        df.to_csv('/home/xf08bm/Users/TEMP/Step_Scan/' +
                  f'{operator}-{scan_title}-{scan_iter}.csv')
    print('Please go /home/xf08bm/Desktop/Users/TEMP/ to copy your data ASAP!')
Exemple #21
0
 def infinite_plan():
     while True:
         yield from sleep(3)
         yield from count([noisy_det], 20, delay=0.5)
Exemple #22
0
    def main_plan(detector, slow, startslow, stopslow, nslow, fast, startfast,
                  stopfast, nfast, pluck, force, dwell, md):
        (ok, text) = BMM_clear_to_start()
        if force is False and ok is False:
            print(error_msg(text))
            BMMuser.final_log_entry = False
            yield from null()
            return

        RE.msg_hook = None

        ## sanity checks on slow axis
        if type(slow) is str: slow = slow.lower()
        if slow not in motor_nicknames.keys() and 'EpicsMotor' not in str(
                type(slow)) and 'PseudoSingle' not in str(type(slow)):
            print(
                error_msg('\n*** %s is not an areascan motor (%s)\n' %
                          (slow, str.join(', ', motor_nicknames.keys()))))
            BMMuser.final_log_entry = False
            yield from null()
            return
        if slow in motor_nicknames.keys():
            slow = motor_nicknames[slow]

        ## sanity checks on fast axis
        if type(fast) is str: fast = fast.lower()
        if fast not in motor_nicknames.keys() and 'EpicsMotor' not in str(
                type(fast)) and 'PseudoSingle' not in str(type(fast)):
            print(
                error_msg('\n*** %s is not an areascan motor (%s)\n' %
                          (fast, str.join(', ', motor_nicknames.keys()))))
            BMMuser.final_log_entry = False
            yield from null()
            return
        if fast in motor_nicknames.keys():
            fast = motor_nicknames[fast]

        detector = detector.capitalize()
        yield from abs_set(_locked_dwell_time, dwell, wait=True)
        dets = [
            quadem1,
        ]
        if detector == 'If':
            dets.append(vor)
            detector = 'ROI1'
        if detector.lower() == 'xs':
            dets.append(xs)
            detector = BMMuser.xs1

        if 'PseudoSingle' in str(type(slow)):
            valueslow = slow.readback.get()
        else:
            valueslow = slow.user_readback.get()
            line1 = 'slow motor: %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
                    (slow.name, startslow, stopslow, nslow, valueslow)

        if 'PseudoSingle' in str(type(fast)):
            valuefast = fast.readback.get()
        else:
            valuefast = fast.user_readback.get()
        line2 = 'fast motor: %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
                (fast.name, startfast, stopfast, nfast, valuefast)

        npoints = nfast * nslow
        estimate = int(npoints * (dwell + 0.7))

        # extent = (
        #     valuefast + startfast,
        #     valueslow + startslow,
        #     valuefast + stopfast,
        #     valueslow + stopslow,
        # )
        # extent = (
        #     0,
        #     nfast-1,
        #     0,
        #     nslow-1
        # )
        # print(extent)
        # return(yield from null())

        # areaplot = LiveScatter(fast.name, slow.name, detector,
        #                        xlim=(startfast, stopfast), ylim=(startslow, stopslow))

        areaplot = LiveGrid(
            (nslow, nfast),
            detector,  #aspect='equal', #aspect=float(nslow/nfast), extent=extent,
            xlabel='fast motor: %s' % fast.name,
            ylabel='slow motor: %s' % slow.name)
        #BMMuser.ax     = areaplot.ax
        #BMMuser.fig    = areaplot.ax.figure
        BMMuser.motor = fast
        BMMuser.motor2 = slow
        #BMMuser.fig.canvas.mpl_connect('close_event', handle_close)

        thismd = dict()
        thismd['XDI'] = dict()
        thismd['XDI']['Facility'] = dict()
        thismd['XDI']['Facility']['GUP'] = BMMuser.gup
        thismd['XDI']['Facility']['SAF'] = BMMuser.saf
        thismd['slow_motor'] = slow.name
        thismd['fast_motor'] = fast.name

        ## engage suspenders right before starting scan sequence
        if force is False: BMM_suspenders()

        @subs_decorator(areaplot)
        #@subs_decorator(src.callback)
        def make_areascan(dets,
                          slow,
                          startslow,
                          stopslow,
                          nslow,
                          fast,
                          startfast,
                          stopfast,
                          nfast,
                          snake=False):
            BMMuser.final_log_entry = False
            uid = yield from grid_scan(dets, slow, startslow, stopslow, nslow,
                                       fast, startfast, stopfast, nfast, snake)
            BMMuser.final_log_entry = True
            return uid

        rkvs.set('BMM:scan:type', 'area')
        rkvs.set('BMM:scan:starttime',
                 str(datetime.datetime.timestamp(datetime.datetime.now())))
        rkvs.set('BMM:scan:estimated', estimate)

        BMM_log_info('begin areascan observing: %s\n%s%s' %
                     (detector, line1, line2))
        uid = yield from make_areascan(dets, slow, valueslow + startslow,
                                       valueslow + stopslow, nslow, fast,
                                       valuefast + startfast,
                                       valuefast + stopfast, nfast, False)

        if pluck is True:
            action = input('\n' + bold_msg(
                'Pluck motor position from the plot? [Y/n then Enter] '))
            if action.lower() == 'n' or action.lower() == 'q':
                return (yield from null())
            print(
                'Single click the left mouse button on the plot to pluck a point...'
            )
            cid = BMMuser.fig.canvas.mpl_connect(
                'button_press_event',
                interpret_click)  # see 65-derivedplot.py and
            while BMMuser.x is None:  #  https://matplotlib.org/users/event_handling.html
                yield from sleep(0.5)

            print('Converting plot coordinates to real coordinates...')
            begin = valuefast + startfast
            stepsize = (stopfast - startfast) / (nfast - 1)
            pointfast = begin + stepsize * BMMuser.x
            #print(BMMuser.x, pointfast)

            begin = valueslow + startslow
            stepsize = (stopslow - startslow) / (nslow - 1)
            pointslow = begin + stepsize * BMMuser.y
            #print(BMMuser.y, pointslow)

            print('That translates to x=%.3f, y=%.3f' % (pointfast, pointslow))
            yield from mv(fast, pointfast, slow, pointslow)
Exemple #23
0
def sscan_1D(
        sscan, 
        poll_delay_s=0.001, 
        phase_timeout_s = 60.0,
        running_stream="primary", 
        final_array_stream=None, 
        device_settings_stream="settings", 
        md={}):
    """
    simple 1-D scan using EPICS synApps sscan record
    
    assumes the sscan record has already been setup properly for a scan

    PARAMETERS

    sscan : Device
        one EPICS sscan record (instance of `apstools.synApps_ophyd.sscanRecord`)
    running_stream : str or `None`
        (default: ``"primary"``)
        Name of document stream to write positioners and detectors data
        made available while the sscan is running.  This is typically 
        the scan data, row by row.
        If set to `None`, this stream will not be written.
    final_array_stream : str or `None`
        (default: ``None``)
        Name of document stream to write positioners and detectors data 
        posted *after* the sscan has ended.
        If set to `None`, this stream will not be written.
    device_settings_stream : str or `None`
        (default: ``"settings"``)
        Name of document stream to write *settings* of the sscan device.
        This is all the information returned by ``sscan.read()``.
        If set to `None`, this stream will not be written.
    poll_delay_s : float
        (default: 0.001 seconds)
        How long to sleep during each polling loop while collecting
        interim data values and waiting for sscan to complete.
        Must be a number between zero and 0.1 seconds.
    phase_timeout_s : float
        (default: 60 seconds)
        How long to wait after last update of the ``sscan.FAZE``.
        When scanning, we expect the scan phase to update regularly
        as positioners move and detectors are triggered.  If the scan
        hangs for some reason, this is a way to end the plan early.
        To cancel this feature, set it to ``None``.
    
    NOTE about the document stream names
    
    Make certain the names for the document streams are different from 
    each other.  If you make them all the same (such as ``primary``),
    you will have difficulty when reading your data later on.
    
    *Don't cross the streams!*
    
    EXAMPLE
    
    Assume that the chosen sscan record has already been setup.
    
        from apstools.devices import sscanDevice
        scans = sscanDevice(P, name="scans")
        
        from apstools.plans import sscan_1D
        RE(sscan_1D(scans.scan1), md=dict(purpose="demo"))

    """
    global new_data, inactive_deadline
    
    msg = f"poll_delay_s must be a number between 0 and 0.1, received {poll_delay_s}"
    assert 0 <= poll_delay_s <= 0.1, msg
    
    t0 = time.time()
    sscan_status = ophyd.DeviceStatus(sscan.execute_scan)
    started = False
    new_data = False
    inactive_deadline = time.time()
    if phase_timeout_s is not None:
        inactive_deadline += phase_timeout_s
    
    def execute_cb(value, timestamp, **kwargs):
        """watch for sscan to complete"""
        if started and value in (0, "IDLE"):
            sscan_status._finished()
            sscan.execute_scan.unsubscribe_all()
            sscan.scan_phase.unsubscribe_all()
    
    def phase_cb(value, timestamp, **kwargs):
        """watch for new data"""
        global new_data, inactive_deadline
        if phase_timeout_s is not None:
            inactive_deadline = time.time() + phase_timeout_s
        if value in (15, "RECORD SCALAR DATA"):
            new_data = True            # set flag for main plan
    
    # acquire only the channels with non-empty configuration in EPICS
    sscan.select_channels()
    # pre-identify the configured channels
    sscan_data_objects = _get_sscan_data_objects(sscan)
    
    # watch for sscan to complete
    sscan.execute_scan.subscribe(execute_cb)
    # watch for new data to be read out
    sscan.scan_phase.subscribe(phase_cb)
    
    md["plan_name"] = "sscan_1D"

    yield from bps.open_run(md)               # start data collection
    yield from bps.mv(sscan.execute_scan, 1)   # start sscan
    started = True

    # collect and emit data, wait for sscan to end
    while not sscan_status.done or new_data:
        if new_data and running_stream is not None:
            yield from bps.create(running_stream)
            for k, obj in sscan_data_objects.items():
                yield from bps.read(obj)
            yield from bps.save()
        new_data = False
        if phase_timeout_s is not None and time.time() > inactive_deadline:
            print(f"No change in sscan record for {phase_timeout_s} seconds.")
            print("ending plan early as unsuccessful")
            sscan_status._finished(success=False)
        yield from bps.sleep(poll_delay_s)

    # dump the complete data arrays
    if final_array_stream is not None:
        yield from bps.create(final_array_stream)
        # we have to search for the arrays since they have ``kind="omitted"``
        # (which means they do not get reported by the ``.read()`` method)
        for part in (sscan.positioners, sscan.detectors):
            for nm in part.read_attrs:
                if "." not in nm:
                    # TODO: write just the acquired data, not the FULL arrays!
                    yield from bps.read(getattr(part, nm).array)
        yield from bps.save()

    # dump the entire sscan record into another stream
    if device_settings_stream is not None:
        yield from bps.create(device_settings_stream)
        yield from bps.read(sscan)
        yield from bps.save()

    yield from bps.close_run()

    return sscan_status
Exemple #24
0
def energystep(filename = None,
               start    = None,
               end      = None,
               nsteps   = None,
               delay    = 5,
               dosteps  = True):
    '''A simple energy scan, just step forward in energy and don't measure
    anything.  This is a quick hack for use with a crude resonant
    reflectivity experiment with IBM folks.

    Parameters
    ----------
    filename : str
        name of file, will be appended to DATA for the full path (required)
    start : float
        starting energy value (required)
    end : float
        ending energy value (required)
    nsteps : int
        number of energy steps (required)
    delay : float
        pause between energy steps, in seconds [5]
    dosteps : bool
        False to see energy values printed to screen without moving mono [True]

    Writes a data file with columns of energy readback, energy
    requested, time of epoch, and ISO 8601 timestamp

    Example
    -------

    >>> energystep(filename='blahblah', start=18936, end=19036, nsteps=101)
    '''

    BMM_log_info("energystep(filename=%s, start=%.1f, end=%.1f, nsteps=%d, delay=%.1f, dosteps=%s)" % (filename, start, end, nsteps, delay, str(dosteps)))
    datafile = BMMuser.DATA + filename
    handle = open(datafile, 'w')
    handle.write('# energy steps from %.1f to %.1f in %d steps\n' % (start, end, nsteps))
    handle.write('#----------------------------------------------------\n')
    handle.write('# energy        requested          epoch        iso8601\n')
    handle.flush()
    
    if dosteps:
        yield from mv(dcm.energy, start)
    print('  %.1f       %.1f     %.6f    %s' % (dcm.energy.readback.get(), start, time.time(), now()))
    handle.write('  %.1f       %.1f     %.6f    %s\n' % (dcm.energy.readback.get(), start, time.time(), now()))
    handle.flush()
    yield from sleep(delay)

    energy = start
    estep = (end-start) / nsteps
    while energy <= end:
        if dosteps:
            yield from mvr(dcm.energy, estep)
        print('  %.1f       %.1f     %.6f    %s' % (dcm.energy.readback.get(), energy, time.time(), now()))
        handle.write('  %.1f       %.1f     %.6f    %s\n' % (dcm.energy.readback.get(), energy, time.time(), now()))
        handle.flush()
        energy = energy + estep
        yield from sleep(delay)
        

    handle.flush()
    handle.close()
def gridScan(dets,
             exp_spreadsheet_fn,
             glbl,
             xpd_configuration,
             XPD_SHUTTER_CONF,
             *,
             crossed=False,
             dx=None,
             dy=None,
             wait_time=5):
    """
    Scan plan for the multi-sample grid scan.

    This function takes in a templated excel spreadsheet and constructs a
    spatial scan plan. Single-shot  with total exposure specified in
    the ``Exposure time`` columns will be executed at the spatial
    points specified in the ``X-position`` and ``Y-position`` columns.
    A set of optional arguments ``crossed``, ``dx`` and ``dy``  can be
    passed so that 4 extra data will be collected with respect at each
    spatial point. An optional wait time between spatial points data can
    also be set to avoid residuals (ghost image). Please see
    ``Examples`` below.

    Parameters
    ----------
    dets : list
        A list of detectors will be triggered in the experiment.
        Note the first three detectors in the list must be in the order
        as "area detector, x-motor, y-motor".
    exp_spreadsheet_fn : str
        filename of the spreadsheet contains sample metadata in each
        well, locations, exposure times and all additional metadata.
        This spread MUST be placed inside ``xpdUser/Import``.
    crossed : bool, optional
        option if to perform a crossed scan in each well. If it's true,
        then at each well (x0, y0), 4 additional data will be collected
        at (x0-dx, y0), (x0+dx, y0), (x0, dy+y0), (x0, y0-dy). Default
        to False.
    dx : float, optional
        offset in x-direction for crossed scan per well. Must be
        a float if ``crossed`` is set to True. Default to None.
    dy : float, optional
        offset in y-direction for crossed scan per well. Must be
        a float if ``crossed`` is set to True. Default to None.
    wait_time : float, optional
        Wait time between each count, default is 5s

    Examples
    --------
    # define a list of detectors will be triggered in the spatial scan
    # plan. The first 3 detectors should be in the sequence of
    # "area_det, x-motor,  y-motor" used in the scan.
    dets = [pe1c, diff_x, diff_y, shctl1]

    # case 1
    # define a plan based on the information entered in the
    # spreadsheet ``wandaHY1_sample.xlsx``.
    # Note, this spreadsheet MUST be placed in the ``Import`` directory
    grid_plan = gridScan(dets,  'wandaHY1_sample.xlsx', wait_time=5)

    # preview the plan to check.
    summarize_plan(grid_plan)

    # redefine the scan plan again then execute the plan.
    grid_plan = gridScan(dets,  'wandaHY1_sample.xlsx', wait_time=5)
    uids = xrun(gridScan_sample, grid_plan)

    # case 2
    # define a grid scan that collects 4 extra points at each spatial
    # point to account for potential inhomogeneity
    grid_plan = gridScan(dets, 'wandaHY1_sample.xlsx', crossed=True,
                         dx=0.2, dy=0.1, wai_time=5)

    # preview the plan to check.
    summarize_plan(grid_plan)

    # redefine the scan plan again then execute the plan.
    grid_plan = gridScan(dets,  'wandaHY1_sample.xlsx', wait_time=5)
    uids = xrun(gridScan_sample, grid_plan)

    # finally, retrieve event information as a dataframe
    hdrs = db[-len(uids):]
    df = db.get_table(hdrs)
    # visualize the dataframe
    df
    # save the dataframe as a csv
    df.to_csv('wandaHY1_spatial_scan_df.csv')

    Notes
    -----
    1. ``gridScan_sample`` used in the example is in fact an empty
      dictionary (and it has been defined in this script as well).
      Sample metadata is handled inside the plan, therefore it's
      simply an auxiliary object.

    2. ``gridScan`` yields a generator so you would need to construct
      it every time after using it. As demonstrated in the Example,
      we redefine the ``grid_plan`` again after printing the summary.
      Similarly, if you wish to execute the same scan plan, you would
      have to repeat the syntax.
    """
    def count_dets(_dets, _full_md):
        _count_plan = bp.count(_dets, md=_full_md)
        _count_plan = bpp.subs_wrapper(_count_plan, LiveTable(_dets))
        _count_plan = bpp.finalize_wrapper(
            _count_plan,
            bps.abs_set(xpd_configuration['shutter'],
                        XPD_SHUTTER_CONF['close'],
                        wait=True))
        yield from bps.abs_set(xpd_configuration['shutter'],
                               XPD_SHUTTER_CONF['open'],
                               wait=True)
        yield from _count_plan

    # read exp spreadsheet
    spreadsheet_parser = ExceltoYaml(glbl['import_dir'])
    fp = os.path.join(spreadsheet_parser.src_dir, exp_spreadsheet_fn)
    spreadsheet_parser.pd_df = pd.read_excel(fp, skiprows=[1])
    spreadsheet_parser.parse_sample_md()
    # get detectors
    area_det = xpd_configuration['area_det']
    x_motor, y_motor = list(dets)[:2]
    dets = [area_det] + dets
    # compute Nsteps
    _md = {
        'sp_time_per_frame': None,
        'sp_num_frames': None,
        'sp_requested_exposure': None,
        'sp_computed_exposure': None,
        'sp_type': 'gridScan',
        'sp_uid': str(uuid.uuid4())[:4],
        'sp_plan_name': 'gridScan'
    }
    # first validate through sa_md list
    for md_dict in spreadsheet_parser.parsed_sa_md_list:
        if not ('x-position' in md_dict and 'y-position' in md_dict
                and 'exposure_time(s)' in md_dict):
            raise xpdAcqException("either X-position, Y-position "
                                  "or Exposure time column in {} "
                                  "row is missing. Please fill it "
                                  "and rerun".format(md_dict['sample_name']))
    # validate crossed scan
    if crossed and (not dx or not dy):
        raise xpdAcqException(
            "dx and dy must both be provided if crossed is set to True")
    # construct scan plan
    for md_dict in spreadsheet_parser.parsed_sa_md_list:
        expo = float(md_dict['exposure_time(s)'])
        # setting up area_detector
        yield from _configure_area_det(expo)
        expo_md = calc_expo_md(dets[0], expo)
        # inject md for each sample
        full_md = dict(_md)
        full_md.update(expo_md)
        full_md.update(md_dict)
        # Manually open shutter before collecting. See the reason
        # stated below.
        # main plan
        x_center = float(md_dict['x-position'])
        y_center = float(md_dict['y-position'])
        yield from bps.mv(x_motor, x_center)
        yield from bps.mv(y_motor, y_center)
        yield from count_dets(dets, full_md)  # no crossed
        if crossed:
            x_traj = [-dx + x_center, x_center + dx, x_center, x_center]
            y_traj = [y_center, y_center, y_center + dy, y_center - dy]
            for x_setpoint, y_setpoint in zip(x_traj, y_traj):
                yield from bps.mv(x_motor, x_setpoint)
                yield from bps.mv(y_motor, y_setpoint)
                full_md['x-position'] = x_setpoint
                full_md['y-position'] = y_setpoint
                yield from count_dets(dets, full_md)
        # use specified sleep time -> avoid residual from the calibrant
        yield from bps.sleep(wait_time)
    def fly_body():

        yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, ystart)

        #  This part is not necessary to be here. revised by YDu
        for v in ["p1600=0", "p1600=1"]:
            yield from bps.mv(dtt, v)
            yield from bps.sleep(0.1)

        @bpp.stage_decorator([x for x in [xspress3] if x is not None])
        def fly_row():
            # go to start of row
            target_y = ystart + y * a_ystep_size
            yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, target_y)
            yield from bps.mv(y_centers,
                              np.ones(num_xpixels) *
                              target_y)  # set the fly speed

            #         ret = yield from bps.read(xy_fly_stage.z.user_readback)  # (in mm)
            #  revised by YDu, no such value before
            #yield from bps.sleep(0)
            #         zpos = (
            #            ret[xy_fly_stage.z.user_readback.name]["value"]
            #           if ret is not None
            #          else 0
            #     )
            #    yield from bps.mov(z_centers, np.ones(num_xpixels) * zpos)

            yield from bps.mv(xy_fly_stage.x.velocity, flyspeed)

            yield from bps.trigger_and_read([xy_fly_stage], name="row_ends")

            # arm the struck
            yield from bps.trigger(sclr, group=f"fly_row_{y}")
            # maybe start the xspress3
            if xspress3 is not None:
                yield from bps.trigger(xspress3, group=f"fly_row_{y}")
            #  revised by YDu, use to be 0.1
            yield from bps.sleep(1.5)  # fly the motor
            yield from bps.abs_set(xy_fly_stage.x,
                                   xstop + a_xstep_size,
                                   group=f"fly_row_{y}")
            yield from bps.wait(group=f"fly_row_{y}")

            # yield from bps.trigger_and_read([xy_fly_stage], name="row_ends")
            yield from bps.mv(xy_fly_stage.x.velocity, 5.0)
            #  revised by YDu, use to be 0.1
            yield from bps.sleep(0.1)
            # read and save the struck
            yield from bps.create(name="primary")
            #
            yield from bps.read(sclr)
            yield from bps.read(mono)
            yield from bps.read(x_centers)
            yield from bps.read(y_centers)
            yield from bps.read(z_centers)
            yield from bps.read(xy_fly_stage.y)
            yield from bps.read(xy_fly_stage.z)
            # and maybe the xspress3
            if xspress3 is not None:
                yield from bps.read(xspress3)
            yield from bps.sleep(0.2)
            yield from bps.save()
            yield from bps.sleep(0.2)

    #     if 5 - abs(xstop - xstart)/5 > 0:
    #        #print(5 - abs(xstop - xstart)/5)
    #       time.sleep(5.3 - abs(xstop - xstart)/5)

        for y in range(num_ypixels):
            if xspress3 is not None:
                yield from bps.mv(xspress3.fly_next, True)

            yield from fly_row()
Exemple #27
0
def sleepy_scan():
    yield from checkpoint()
    yield from sleep(0.2)
    def remote_ops(self, *args, **kwargs):
        """
        Bluesky plan to enable PV-directed data collection

        To start the automatic data collection plan:

            RE(auto_collect.remote_ops())

        The plan will exit when:

        * `permit` is not "yes" or 1
        * user types `^C` twice (user types `RE.abort()` then)
        * unhandled exception

        The plan will collect data when `trigger_signal` goes to "start" or 1.
        `trigger_signal` immediately goes back to "stop" or 0.

        The command to be run is in `commands` which is:

        * a named command defined here
        * a command file in the present working directory
        """
        yield from bps.mv(self.permit, "yes")
        yield from bps.sleep(1)

        logger.info("auto_collect is waiting for user commands")
        while self.permit.get() in (1, "yes"):
            if self.trigger_signal.get() in (1, "start"):
                print()  # next line if emerging from idle_reporter()
                logger.debug("starting user commands")
                yield from bps.mv(self.trigger_signal, 0)

                command = self.commands.get()
                try:
                    if command == "preUSAXStune":
                        yield from bps.mv(
                            user_data.collection_in_progress,
                            1,
                        )
                        yield from preUSAXStune()
                        yield from bps.mv(
                            user_data.collection_in_progress,
                            0,
                        )
                    elif command == "useModeRadiography":
                        yield from bps.mv(
                            user_data.collection_in_progress,
                            1,
                        )
                        yield from mode_Radiography()
                        yield from bps.mv(
                            user_data.collection_in_progress,
                            0,
                        )
                    elif os.path.exists(command):
                        yield from run_command_file(command)
                    else:
                        logger.warning("unrecognized command: %s", command)
                except Exception as exc:
                    logger.warn(
                        "Exception during execution of command %s:\n%s",
                        command, str(exc))
                logger.info("waiting for next user command")
            else:
                yield from bps.sleep(self.idle_interval)
                idle_reporter()

        print()  # next line if emerging from idle_reporter()
        logger.info("auto_collect is ending")
Exemple #29
0
    def fly_each_step(motor, step, row_start, row_stop):
        def move_to_start_fly():
            "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook"
            # row_str = short_uid('row')
            # yield from abs_set(xmotor, row_start, group=row_str)
            # yield from one_1d_step([temp_nanoKB], motor, step)
            # yield from bps.wait(group=row_str)

            print(f"Start moving to beginning of the row")
            row_str = short_uid('row')
            yield from bps.checkpoint()
            yield from bps.abs_set(xmotor, row_start, group=row_str)
            yield from bps.abs_set(motor, step, group=row_str)
            yield from bps.wait(group=row_str)
            # yield from bps.trigger_and_read([temp_nanoKB, motor])  ## Uncomment this
            print(f"Finished moving to the beginning of the row")
            print(f"Fast axis: {xmotor.read()} Slow axis: {motor.read()}")

        if verbose:
            t_mvstartfly = tic()
        yield from move_to_start_fly()

        # TODO  Why are we re-trying the move?  This should be fixed at
        # a lower level
        # yield from bps.sleep(1.0)  # wait for the "x motor" to move
        x_set = row_start
        x_dial = xmotor.user_readback.get()
        # Get retry deadband value and check against that
        i = 0
        DEADBAND = 0.050  # retry deadband of nPoint scanner
        while (np.abs(x_set - x_dial) > DEADBAND):
            if (i == 0):
                print('Waiting for motor to reach starting position...',
                      end='',
                      flush=True)
            i = i + 1
            yield from mv(xmotor, row_start)
            yield from bps.sleep(0.1)
            x_dial = xmotor.user_readback.get()
        if (i != 0):
            print('done')

        if verbose:
            toc(t_mvstartfly, str='Move to start fly each')

        # Set the scan speed
        # Is abs_set(wait=True) or mv() faster?
        v = ((xstop - xstart) / (xnum - 1)) / dwell  # compute "stage speed"
        # yield from abs_set(xmotor.velocity, v, wait=True)  # set the "stage speed"
        # if (v > xmotor.velocity.high_limit):
        #     raise ValueError(f'Desired motor velocity too high\nMax velocity: {xmotor.velocity.high_limit}')
        # elif (v < xmotor.velocity.low_limit):
        #     raise ValueError(f'Desired motor velocity too low\nMin velocity: {xmotor.velocity.low_limit}')
        # else:
        #     yield from mv(xmotor.velocity, v)
        yield from mv(xmotor.velocity, v)

        # set up all of the detectors
        # TODO we should be able to move this out of the per-line call?!
        # if ('xs' in dets_by_name):
        #     xs = dets_by_name['xs']
        #     yield from abs_set(xs.hdf5.num_capture, xnum, group='set')
        #     yield from abs_set(xs.settings.num_images, xnum, group='set')
        #     yield from bps.wait(group='set')
        #     # yield from mv(xs.hdf5.num_capture, xnum,
        #     #               xs.settings.num_images, xnum)
        #     # xs.hdf5.num_capture.put(xnum)
        #     # xs.settings.num_images.put(xnum)

        # if ('xs2' in dets_by_name):
        #     xs2 = dets_by_name['xs2']
        #     # yield from abs_set(xs2.hdf5.num_capture, xnum, wait=True)
        #     # yield from abs_set(xs2.settings.num_images, xnum, wait=True)
        #     yield from mv(xs2.hdf5.num_capture, xnum,
        #                   xs2.settings.num_images, xnum)

        # if ('merlin' in dets_by_name):
        #     merlin = dets_by_name['merlin']
        #     yield from abs_set(merlin.hdf5.num_capture, xnum, wait=True)
        #     yield from abs_set(merlin.cam.num_images, xnum, wait=True)

        # if ('dexela' in dets_by_name):
        #     dexela = dets_by_name['dexela']
        #     yield from abs_set(dexela.hdf5.num_capture, xnum, wait=True)
        #     # yield from abs_set(dexela.hdf5.num_frames_chunks, xnum, wait=True)
        #     yield from abs_set(dexela.cam.num_images, xnum, wait=True)

        ion = flying_zebra.sclr
        if ion:
            yield from abs_set(ion.nuse_all, 2 * xnum)

        # arm the Zebra (start caching x positions)
        # @timer_wrapper
        def zebra_kickoff():
            # start_zebra, stop_zebra = xstart * 1000000, xstop * 1000000
            start_zebra, stop_zebra = xstart, xstop
            if row_start < row_stop:
                yield from kickoff(flying_zebra,
                                   xstart=start_zebra,
                                   xstop=stop_zebra,
                                   xnum=xnum,
                                   dwell=dwell,
                                   wait=True)
            else:
                yield from kickoff(flying_zebra,
                                   xstart=stop_zebra,
                                   xstop=start_zebra,
                                   xnum=xnum,
                                   dwell=dwell,
                                   wait=True)

        if verbose:
            t_zebkickoff = tic()
        yield from zebra_kickoff()
        if verbose:
            toc(t_zebkickoff, str='Zebra kickoff')

        if verbose:
            t_datacollect = tic()
        # arm SIS3820, note that there is a 1 sec delay in setting X
        # into motion so the first point *in each row* won't
        # normalize...
        if ion:
            yield from abs_set(ion.erase_start, 1)
        if verbose:
            toc(t_datacollect, str='  reset scaler')

        # trigger all of the detectors
        row_str = short_uid('row')
        if verbose:
            print('Data collection:')
        for d in flying_zebra.detectors:
            if verbose:
                print(f'  triggering {d.name}')
            st = yield from bps.trigger(d, group=row_str)
            st.add_callback(lambda x: toc(
                t_datacollect,
                str=
                f"  status object  {datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S.%f')}"
            ))
            if (d.name == 'dexela'):
                yield from bps.sleep(1)
        if verbose:
            toc(t_datacollect, str='  trigger detectors')

        # yield from bps.sleep(1.5)
        if verbose:
            toc(t_datacollect, str='  sleep')

        # start the 'fly'
        def print_watch(*args, **kwargs):
            with open('~/bluesky_output.txt', 'a') as f:
                f.write(
                    datetime.datetime.strftime(datetime.datetime.now(),
                                               '%Y-%m-%d %H:%M:%S.%f\n'))
                # print(args)
                f.write(json.dumps(kwargs))
                f.write('\n')

        st = yield from abs_set(xmotor, row_stop, group=row_str)
        # st.watch(print_watch)

        if verbose:
            toc(t_datacollect, str='  move start')

        if verbose and False:
            ttime.sleep(1)
            while (xmotor.motor_is_moving.get()):
                ttime.sleep(0.001)
            toc(t_datacollect, str='  move end')
            while (xs.settings.detector_state.get()):
                ttime.sleep(0.001)
            toc(t_datacollect, str='  xs done')
            while (sclr1.acquiring.get()):
                ttime.sleep(0.001)
            toc(t_datacollect, str='  sclr1 done')
        # wait for the motor and detectors to all agree they are done
        yield from bps.wait(group=row_str)
        st.wait()

        if verbose:
            toc(t_datacollect, str='Total time')

        # we still know about ion from above
        if ion:
            yield from abs_set(ion.stop_all, 1)  # stop acquiring scaler

        print(f"Resetting scanner velocity")
        # set speed back
        reset_scanner_velocity()
        print(f"Completed resetting scanner velocity")

        # @timer_wrapper
        def zebra_complete():
            yield from complete(flying_zebra)  # tell the Zebra we are done

        if verbose:
            t_zebcomplete = tic()
        yield from zebra_complete()
        if verbose:
            toc(t_zebcomplete, str='Zebra complete')
        print(f"'zebra_complete' finished")

        # @timer_wrapper
        def zebra_collect():
            yield from collect(flying_zebra)  # extract data from Zebra

        if verbose:
            t_zebcollect = tic()
        yield from zebra_collect()
        if verbose:
            toc(t_zebcollect, str='Zebra collect')
        print(f"'zebra_collect' finished")

        print(f"Step is completed")
Exemple #30
0
def edge_ascan(sample_name, edge, md=None):
    '''Run a multi-edge nexafs scan for single sample and edge

    Parameters
    ----------
    sample_name : str
        Base sample name

    sample_position : float
        Postion of sample on manipulator arm

    edge : str
        Key into EDGE_MAP


    '''
    if md is None:
        md = {}
    local_md = {'plan_name': 'edge_ascan'}
    local_md['edge'] = edge
    md = ChainMap(md, local_md)

    e_scan_params = EDGE_MAP[edge]
    # TODO configure the vortex
    det_settings = DET_SETTINGS[edge]
    sample_props = SAMPLE_MAP[sample_name]
#    sample_props = list(sample_manager.find(name=sample_name))
    local_md.update(sample_props)

    # init_group = 'ME_INIT_' + str(uuid.uuid4())
    yield from bps.abs_set(ioxas_x, sample_props['pos'], wait=True)
    yield from bps.abs_set(diag3_y, sample_props['diag3_y'], wait=True)
#    yield from bps.mov(appes_x, sample_props['pos_x'])
#    yield from bps.mov(appes_y, sample_props['pos_y'])
    yield from bps.mov(au_mesh, e_scan_params['au_mesh'])
#    yield from bps.mov(appes_t, sample_props['pos_theta'])
    yield from bps.abs_set(feedback, 0, wait=True)
    yield from bps.abs_set(pgm_energy, e_scan_params['e_align'], wait=True)
    yield from bps.abs_set(epu1table, e_scan_params['epu_table'], wait=True)
    yield from bps.abs_set(epu1offset, e_scan_params['epu1offset'], wait=True)
    yield from bps.sleep(5)
#    yield from bps.abs_set(m1b1_fp, 100)
    yield from bps.abs_set(feedback, 1, wait=True)
    yield from bps.sleep(5)
#    yield from bps.abs_set(feedback, 0, wait=True)
    yield from bps.abs_set(vortex_x, det_settings['vortex_pos'], wait=True)
    yield from bps.abs_set(sample_sclr_gain, det_settings['samplegain'], wait=True)
    yield from bps.abs_set(sample_sclr_decade, det_settings['sampledecade'], wait=True)
    yield from bps.abs_set(aumesh_sclr_gain, det_settings['aumeshgain'], wait=True)
    yield from bps.abs_set(aumesh_sclr_decade, det_settings['aumeshdecade'], wait=True)
    yield from bps.abs_set(sclr_time, det_settings['sclr_time'], wait=True)
    yield from bps.abs_set(pd_sclr_gain, det_settings['pd_gain'], wait=True)
    yield from bps.abs_set(pd_sclr_decade, det_settings['pd_decade'], wait=True)
 
 #   yield from open_all_valves(all_valves)
    # yield from bp.wait(init_group)

# TODO make this an ohypd obj!!!!!!
    #caput('XF:23IDA-PPS:2{PSh}Cmd:Opn-Cmd',1)
#   yield from bp.sleep(2)
    # TODO make this an ohypd obj!!!!!!
    # TODO ask stuart
    #caput('XF:23IDA-OP:2{Mir:1A-Ax:FPit}Mtr_POS_SP',50)
    yield from bps.sleep(5)

#    yield from bps.configure(vortex, VORTEX_SETTINGS[edge])
#    yield from bps.sleep(2)
    yield from bps.abs_set(vortex.mca.rois.roi4.lo_chan, det_settings['vortex_low'], wait=True)
    yield from bps.abs_set(vortex.mca.rois.roi4.hi_chan, det_settings['vortex_high'], wait=True)
    yield from bps.abs_set(vortex.mca.preset_real_time, det_settings['vortex_time'], wait=True)
    yield from bps.abs_set(sample_sclr_decade, det_settings['sampledecade'], wait=True)
    yield from bps.abs_set(aumesh_sclr_decade, det_settings['aumeshdecade'], wait=True)
    yield from bps.abs_set(pd_sclr_decade, det_settings['pd_decade'], wait=True)


#    lp_list = []
#    for n in ['sclr_ch4', 'vortex_mca_rois_roi4_count']:
#        fig = plt.figure(edge + ': ' + n)
#        lp = bs.callbacks.LivePlot(n, 'pgm_energy_readback', fig=fig)
#        lp_list.append(lp)

#    class norm_plot(bs.callbacks.LivePlot):
#        def event(self,doc):
#            try:
#                doc.data['norm_intensity'] = doc.data['sclr_ch4']/doc.data['sclr_ch3']
#            except KeyError:
#                pass
#            super().event(doc)

#    for n in ['sclr_ch4']:
#        fig = plt.figure(edge + ': ' + n)
#        lp = bs.callbacks.LivePlot(n, 'pgm_energy_readback', fig=fig)
#        lp = norm_plot('norm_intensity', 'pgm_energy_readback', fig=fig)
#        lp_list.append(lp)
    dets = [sclr, vortex, norm_ch4, ring_curr]
    for channel in ['mca.rois.roi2.count','mca.rois.roi3.count','mca.rois.roi4.count']:
            getattr(vortex, channel).kind = 'hinted'
    for channel in ['mca.rois.roi2.count','mca.rois.roi3.count']:
            getattr(vortex, channel).kind = 'normal'
    for channel in ['channels.chan3','channels.chan4']:
        getattr(sclr, channel).kind = 'hinted'
    for channel in ['channels.chan2']:
        getattr(sclr, channel).kind = 'normal'

   
    scan_kwargs = {'start': e_scan_params['stop'],
                   'stop': e_scan_params['start'],
                   'velocity': e_scan_params['velocity'],
                   'deadband': e_scan_params['deadband'],
                   'md': md}
    ret = []
    for j in range(e_scan_params['scan_count']):
        tmp_pos = sample_props['pos'] + (j-((e_scan_params['scan_count']-1)/2))*e_scan_params['intervals']
        yield from bps.abs_set(ioxas_x, tmp_pos, wait=True)
        yield from bps.abs_set(feedback, 0, wait=True)
        yield from bps.abs_set(pgm_energy, e_scan_params['e_align'], wait=True)
        yield from bps.abs_set(epu1table, e_scan_params['epu_table'], wait=True)
        yield from bps.abs_set(epu1offset, e_scan_params['epu1offset'], wait=True)
        yield from bps.sleep(20)
#       yield from bps.abs_set(m1b1_fp, 100)
        yield from bps.abs_set(feedback, 1, wait=True)
        yield from bps.sleep(5)
#        yield from bps.abs_set(feedback, 0, wait=True)
        yield from bps.abs_set(pgm_energy, e_scan_params['stop'], wait=True)
        yield from open_all_valves(all_valves)
        res = yield from bpp.subs_wrapper(E_ramp(dets, **scan_kwargs), {'stop': save_csv})
        yield from bps.abs_set(valve_diag3_close, 1, wait=True)
        yield from bps.abs_set(valve_mir3_close, 1, wait=True)
        yield from bps.sleep(5)
        if res is None:
            res = []
        ret.extend(res)
        if not ret:
            return ret


    # hdr = db[ret[0]]
    # redo_count = how_many_more_times_to_take_data(hdr)
    # for j in range(redo_count):
    #     res = yield from bpp.subs_wrapper(ascan(*scan_args, md=md), lp)
    #     ret.extend(res)


    # new_count_time = compute_new_count_time(hdr, old_count_time)
    # if new_count_time != old_count_time:
    #     yield from bps.configure(vortex, {'count_time': new_count_time})
    #     res = yield from bpp.subs_wrapper(ascan(*scan_args, md=md), lp)
    #     ret.extend(res)

    return ret
def edge_ascan(sample_name, edge, md=None):
    '''Run a multi-edge nexafs scan for single sample and edge

    Parameters
    ----------
    sample_name : str
        Base sample name

    sample_position : float
        Postion of sample on manipulator arm

    edge : str
        Key into EDGE_MAP


    '''
    if md is None:
        md = {}
    local_md = {'plan_name': 'edge_ascan'}
    local_md['edge'] = edge
    md = ChainMap(md, local_md)

    e_scan_params = EDGE_MAP[edge]
    # TODO configure the vortex
    det_settings = DET_SETTINGS[edge]
    sample_props = SAMPLE_MAP[sample_name]
#    sample_props = list(sample_manager.find(name=sample_name))
    local_md.update(sample_props)

    # init_group = 'ME_INIT_' + str(uuid.uuid4())
    yield from bps.abs_set(ioxas_x, sample_props['pos'], wait=True)
#    yield from bps.mov(appes_x, sample_props['pos_x'])
#    yield from bps.mov(appes_y, sample_props['pos_y'])
    yield from bps.abs_set(feedback, 0, wait=True)
    yield from bps.abs_set(pgm_energy, e_scan_params['start'], wait=True)
    yield from bps.abs_set(epu1table, e_scan_params['epu_table'], wait=True)
    yield from bps.abs_set(epu1offset, e_scan_params['epu1offset'], wait=True)
    yield from bps.sleep(15)
    yield from bps.abs_set(m1b1_fp, 100)
    yield from bps.abs_set(feedback, 1, wait=True)
    yield from bps.sleep(5)
    yield from bps.abs_set(feedback, 0, wait=True)
    yield from bps.abs_set(vortex_x, det_settings['vortex_pos'], wait=True)
    yield from bps.abs_set(sample_sclr_gain, det_settings['samplegain'], wait=True)
    yield from bps.abs_set(sample_sclr_decade, det_settings['sampledecade'], wait=True)
    yield from bps.abs_set(aumesh_sclr_gain, det_settings['aumeshgain'], wait=True)
    yield from bps.abs_set(aumesh_sclr_decade, det_settings['aumeshdecade'], wait=True)
    yield from bps.abs_set(sclr_time, det_settings['sclr_time'], wait=True)

 #   yield from open_all_valves(all_valves)
    # yield from bp.wait(init_group)

# TODO make this an ohypd obj!!!!!!
    #caput('XF:23IDA-PPS:2{PSh}Cmd:Opn-Cmd',1)
#   yield from bp.sleep(2)
    # TODO make this an ohypd obj!!!!!!
    # TODO ask stuart
    #caput('XF:23IDA-OP:2{Mir:1A-Ax:FPit}Mtr_POS_SP',50)
    yield from bps.sleep(5)

#    yield from bps.configure(vortex, VORTEX_SETTINGS[edge])
#    yield from bps.sleep(2)
    yield from bps.abs_set(vortex.mca.rois.roi4.lo_chan, det_settings['vortex_low'], wait=True)
    yield from bps.abs_set(vortex.mca.rois.roi4.hi_chan, det_settings['vortex_high'], wait=True)
    yield from bps.abs_set(vortex.mca.preset_real_time, det_settings['vortex_time'], wait=True)

#    lp_list = []
#    for n in ['sclr_ch4', 'vortex_mca_rois_roi4_count']:
#        fig = plt.figure(edge + ': ' + n)
#        lp = bs.callbacks.LivePlot(n, 'pgm_energy_readback', fig=fig)
#        lp_list.append(lp)

#    class norm_plot(bs.callbacks.LivePlot):
#        def event(self,doc):
#            try:
#                doc.data['norm_intensity'] = doc.data['sclr_ch4']/doc.data['sclr_ch3']
#            except KeyError:
#                pass
#            super().event(doc)

#    for n in ['sclr_ch4']:
#        fig = plt.figure(edge + ': ' + n)
#        lp = bs.callbacks.LivePlot(n, 'pgm_energy_readback', fig=fig)
#        lp = norm_plot('norm_intensity', 'pgm_energy_readback', fig=fig)
#        lp_list.append(lp)
    dets = [sclr, vortex, norm_ch4, ring_curr]
    for channel in ['mca.rois.roi2.count','mca.rois.roi3.count','mca.rois.roi4.count']:
            getattr(vortex, channel).kind = 'hinted'
    for channel in ['mca.rois.roi2.count','mca.rois.roi3.count']:
            getattr(vortex, channel).kind = 'normal'
    for channel in ['channels.chan3','channels.chan4']:
        getattr(sclr, channel).kind = 'hinted'
    for channel in ['channels.chan2']:
        getattr(sclr, channel).kind = 'normal'
    
    scan_kwargs = {'start': e_scan_params['stop'],
                   'stop': e_scan_params['start'],
                   'velocity': e_scan_params['velocity'],
                   'deadband': e_scan_params['deadband'],
                   'md': md}
    ret = []
    for j in range(e_scan_params['scan_count']):
        tmp_pos = sample_props['pos'] + (j-((e_scan_params['scan_count']-1)/2))*e_scan_params['intervals']
#        yield from bps.mov(appes_y, tmp_pos)
        yield from bps.mov(ioxas_x, tmp_pos)
        yield from bps.abs_set(pgm_energy, e_scan_params['stop'], wait=True)
        yield from open_all_valves(all_valves)
        res = yield from bpp.subs_wrapper(E_ramp(dets, **scan_kwargs), {'stop': save_csv})
        yield from bps.abs_set(valve_diag3_close, 1, wait=True)
        yield from bps.abs_set(valve_mir3_close, 1, wait=True)
        yield from bps.sleep(5)
        if res is None:
            res = []
        ret.extend(res)
        if not ret:
            return ret


    # hdr = db[ret[0]]
    # redo_count = how_many_more_times_to_take_data(hdr)
    # for j in range(redo_count):
    #     res = yield from bpp.subs_wrapper(ascan(*scan_args, md=md), lp)
    #     ret.extend(res)


    # new_count_time = compute_new_count_time(hdr, old_count_time)
    # if new_count_time != old_count_time:
    #     yield from bps.configure(vortex, {'count_time': new_count_time})
    #     res = yield from bpp.subs_wrapper(ascan(*scan_args, md=md), lp)
    #     ret.extend(res)

    return ret
def _sim_plan_inner(npts: int, delay: float = 1.0):
    for j in range(npts):
        yield from bps.mov(motor1, j * 0.1 + 1, motor2, j * 0.2 - 2)
        yield from bps.trigger_and_read([motor1, motor2, det2])
        yield from bps.sleep(delay)
Exemple #33
0
 def infinite_plan():
     while True:
         yield from sleep(3)
         yield from count([noisy_det], 20, delay=0.5)
         yield from count([random_img], 10, delay=1)
Exemple #34
0
def xy_fly(
    scan_title,
    *,
    beamline_operator,
    dwell_time,
    xstart,
    xstop,
    xstep_size,
    ystart,
    ystop,
    ystep_size=None,
    xspress3=None,
):
    """Do a x-y fly scan.

    The x-motor is the 'fast' direction.

    Parameters
    ----------
    scan_title : str
       A name for the scan.

    beamline_operator : str
       The individual responsible for this scan. Appears in output directory path.

    dwell_time : float
       Target time is s on each pixel

    xstart, xstop : float
       The start and stop values in the fast direction in mm

    xstep_size :
        xstep_size is step of x movement

    ystart, ystop : float
       The start and stop values in the slow direction in mm

    ystep_size :
        ystep_size use xstep_size if it isn't passed in

    scan_title : str
       Title of scan, required.
    """
    xy_fly_stage = xy_stage
    _validate_motor_limits(xy_fly_stage.x, xstart, xstop, "x")
    _validate_motor_limits(xy_fly_stage.y, ystart, ystop, "y")
    ystep_size = ystep_size if ystep_size is not None else xstep_size
    assert dwell_time > 0, f"dwell_time ({dwell_time}) must be more than 0"
    assert xstep_size > 0, f"xstep_size ({xstep_size}) must be more than 0"
    assert ystep_size > 0, f"ystep_size ({ystep_size}) must be more than 0"
    ret = yield from bps.read(xy_fly_stage.x.mres)  # (in mm)
    xmres = ret[
        xy_fly_stage.x.mres.name]["value"] if ret is not None else 0.0003125

    ret = yield from bps.read(xy_fly_stage.y.mres)  # (in mm)
    ymres = ret[
        xy_fly_stage.y.mres.name]["value"] if ret is not None else 0.0003125

    prescale = int(np.floor((xstep_size / (5 * xmres))))
    a_xstep_size = prescale * (5 * xmres)

    a_ystep_size = int(np.floor((ystep_size / (ymres)))) * ymres

    num_xpixels = int(np.floor((xstop - xstart) / a_xstep_size))
    num_ypixels = int(np.floor((ystop - ystart) / a_ystep_size))

    yield from bps.mv(
        x_centers,
        a_xstep_size / 2 + xstart + np.arange(num_xpixels) * a_xstep_size)

    # SRX original roi_key = getattr(xs.channel1.rois, roi_name).value.name
    roi_livegrid_key = xs.channel1.rois.roi01.value.name
    fig = plt.figure("xs")
    fig.clf()
    roi_livegrid = LiveGrid(
        (num_ypixels + 1, num_xpixels + 1),
        roi_livegrid_key,
        clim=None,
        cmap="inferno",
        xlabel="x (mm)",
        ylabel="y (mm)",
        extent=[xstart, xstop, ystart, ystop],
        x_positive="right",
        y_positive="down",
        ax=fig.gca(),
    )

    flyspeed = a_xstep_size / dwell_time  # this is in mm/s

    try:
        xy_fly_stage.x.velocity.check_value(flyspeed)
    except LimitError as e:
        raise LimitError(f"You requested a range of {xstop - xstart} with "
                         f"{num_xpixels} pixels and a dwell time of "
                         f"{dwell_time}.  This requires a "
                         f"motor velocity of {flyspeed} which "
                         "is out of range.") from e

    # set up delta-tau trigger to fast motor
    for v in ["p1600=0", "p1607=1", "p1600=1"]:
        yield from bps.mv(dtt, v)
        yield from bps.sleep(0.1)

    # TODO make this a message?
    sclr.set_mode("flying")
    # poke the struck settings
    yield from bps.mv(sclr.mcas.prescale, prescale)
    yield from bps.mv(sclr.mcas.nuse, num_xpixels)
    if xspress3 is not None:
        yield from bps.mv(xs.external_trig, True)
        yield from bps.mv(xspress3.total_points, num_xpixels)
        yield from bps.mv(xspress3.hdf5.num_capture, num_xpixels)
        yield from bps.mv(xspress3.settings.num_images, num_xpixels)

    @bpp.reset_positions_decorator([xy_fly_stage.x, xy_fly_stage.y])
    @bpp.subs_decorator({"all": [roi_livegrid]})
    @bpp.monitor_during_decorator([xs.channel1.rois.roi01.value])
    @bpp.stage_decorator([sclr])
    @bpp.baseline_decorator([mono, xy_fly_stage])
    # TODO put is other meta data
    @bpp.run_decorator(
        md={
            "scan_title": scan_title,
            "operator": beamline_operator,
            "user_input": {
                "dwell_time": dwell_time,
                "xstart": xstart,
                "xstop": xstop,
                "xstep_size": xstep_size,
                "ystart": ystart,
                "ystep_size": ystep_size,
            },
            "derived_input": {
                "actual_ystep_size": a_ystep_size,
                "actual_xstep_size": a_xstep_size,
                "fly_velocity": flyspeed,
                "xpixels": num_xpixels,
                "ypixels": num_ypixels,
                "prescale": prescale,
            },
        })
    def fly_body():

        yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, ystart)

        @bpp.stage_decorator([x for x in [xspress3] if x is not None])
        def fly_row():
            # go to start of row
            target_y = ystart + y * a_ystep_size
            yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y, target_y)
            yield from bps.mv(y_centers,
                              np.ones(num_xpixels) *
                              target_y)  # set the fly speed

            ret = yield from bps.read(xy_fly_stage.z.user_readback)  # (in mm)
            zpos = (ret[xy_fly_stage.z.user_readback.name]["value"]
                    if ret is not None else 0)
            yield from bps.mov(z_centers, np.ones(num_xpixels) * zpos)

            yield from bps.mv(xy_fly_stage.x.velocity, flyspeed)

            yield from bps.trigger_and_read([xy_fly_stage], name="row_ends")

            for v in ["p1600=0", "p1600=1"]:
                yield from bps.mv(dtt, v)
                yield from bps.sleep(0.1)

            # arm the struck
            yield from bps.trigger(sclr, group=f"fly_row_{y}")
            # maybe start the xspress3
            if xspress3 is not None:
                yield from bps.trigger(xspress3, group=f"fly_row_{y}")
            yield from bps.sleep(0.1)
            # fly the motor
            yield from bps.abs_set(xy_fly_stage.x,
                                   xstop + a_xstep_size,
                                   group=f"fly_row_{y}")
            yield from bps.wait(group=f"fly_row_{y}")

            yield from bps.trigger_and_read([xy_fly_stage], name="row_ends")
            yield from bps.mv(xy_fly_stage.x.velocity, 5.0)
            yield from bps.sleep(0.1)
            # read and save the struck
            yield from bps.create(name="primary")
            #
            yield from bps.read(sclr)
            yield from bps.read(mono)
            yield from bps.read(x_centers)
            yield from bps.read(y_centers)
            yield from bps.read(z_centers)
            yield from bps.read(xy_fly_stage.y)
            yield from bps.read(xy_fly_stage.z)
            # and maybe the xspress3
            if xspress3 is not None:
                yield from bps.read(xspress3)
            yield from bps.save()

        for y in range(num_ypixels):
            if xspress3 is not None:
                yield from bps.mv(xspress3.fly_next, True)

            yield from fly_row()

    yield from fly_body()

    # save the start document to a file for the benefit of the user
    start = db[-1].start
    dt = datetime.datetime.fromtimestamp(start["time"])
    filepath = os.path.expanduser(
        f"~/Users/Data/{start['operator']}/{dt.date().isoformat()}/xy_fly/"
        f"{start['scan_title']}-{start['scan_id']}-{start['operator']}-{dt.time().isoformat()}.log"
    )
    os.makedirs(os.path.dirname(filepath), exist_ok=True)
    with open(filepath, "wt") as output_file:
        output_file.write(pprint.pformat(start))
 def plan():
     yield from fly_during_wrapper(run_wrapper(sleep(1)), [seq])
Exemple #36
0
def autoplan(bt: Beamtime,
             sample_index,
             plan_index,
             wait_time=30.,
             auto_shutter=False):
    """
    Yield messages to count the predefined measurement plan on the a list of samples on a sample rack. It requires
    the following information to be added for each sample.
        position_x The x position of the sample in mm.
        position_y The y position of the sample in mm.
        wait_time The waiting time between the end of the former plan and the start of the latter plan in second.

    Parameters
    ----------
    bt: Beamtime
        The Beamtime instance that contains the sample information.
    sample_index : List[int]
        A list of the sample index in the BeamTime instance.
    plan_index: List[int]
        A list of the plan index in the BeamTime instance.
    wait_time : float
        Waiting time before conduct plan for each sample in second.
    auto_shutter : bool
        Whether to mutate the plan with inner_shutter_control.

    Yields
    ------
    Msg
        Messages of the plan.

    Examples
    --------
    Add position controller to the xpd_configuration.
        >>> xpd_configuration["posx_controller"] = Grid_X
        >>> xpd_configuration["posy_controller"] = Grid_Y
    Register the scan plan to the beamtime.
        >>> ScanPlan(bt, ct, 30)
    Add the information of 'position_x', 'position_y' and 'wait_time' to the excel and import.
    Automatically conduct the scan plan for sample No.0 and No.1
        >>> plan = autoplan(bt, [0, 1])
        >>> xrun({}, plan)
    """
    posx_controller = xpd_configuration["posx_controller"]
    posy_controller = xpd_configuration["posy_controller"]

    for sample_ind, plan_ind in zip(sample_index, plan_index):
        sample = translate_to_sample(bt, int(sample_ind))
        posx = mg.get_from_sample(sample, "position_x")
        posy = mg.get_from_sample(sample, "position_y")
        count_plan = mg.translate_to_plan(bt, int(plan_ind), sample)
        if auto_shutter:
            count_plan = plan_mutator(count_plan, inner_shutter_control)
        if posx and posy and count_plan:
            yield from checkpoint()
            print(f"INFO: Move to x: {posx}")
            yield from mv(posx_controller, float(posx))
            yield from checkpoint()
            print(f"INFO: Move to y: {posy}")
            yield from mv(posy_controller, float(posy))
            yield from checkpoint()
            yield from wait()
            print(f"INFO: Wait for {wait_time} s")
            yield from sleep(float(wait_time))
            yield from checkpoint()
            yield from count_plan
def ct_dark(numim=None, detectors=None, gain_std=0):
    """Collect dark images for fccd and add metadata tag for dark and gain.

The pre-count shutter & gain states preserved.

    Parameters
    -----------
    numim: int

        Number of images to be measured. If different from current
        setting, the number of images will revert back to the original
        after the scan is complete.

    detectors: list
        List of detectors to be recorded.
        Default = [fccd]

    gain_std: int
        List of detectors to be recorded.
        Default = 0   (which is 'Auto' or x8, the most sensitive gain)

    Returns
    -------

    """
    if detectors is None:
        detectors = [fccd]

    try:
        # TODO figureout kwargs and self to mkae up to line 44 a
        # single definition
        oldnumim = fccd.cam.num_images.value

        # Printing info
        print(
            '\nStarting procedure to acquire darks '
            '{:3.3}Hz or {:3.3f}s.\n'.format(
                1/fccd.cam.acquire_time.value, fccd.cam.acquire_time.value))

        print('\tCurrent number of images = {}.\n'.format(
            fccd.cam.num_images.value))

        yield from bps.sleep(.3)

        if numim is not None:
            print('\tSetting to {} images.\n'.format(numim))
            yield from bps.abs_set(fccd.cam.num_images, numim, wait=True)

        dark_shutter_state = inout.status.value
        dark_sh_dict = {'Inserted': 'In', 'Not Inserted': 'Out'}
        gain_state = fccd.cam.fcric_gain.value
        gain_bit_dict = {0: 'auto', 1: 'x2', 2: 'x1'}

        yield from bps.mv(inout, 'In')
        # This has to be 2 until we can selectively remove dark images
        # get_fastccd_images()
        yield from bps.sleep(fccd.cam.acquire_period.value*2.01)
        # SET TO 1 TO ARM FOR NEXT EVENT so that the FastCCD1 is
        # already bkg subt
        yield from bps.mv(fccd.fccd1.capture_bgnd, 1)

        # take darks
        yield from _ct_dark(detectors, gain_std, gain_bit_dict)

        # Putting things back
        yield from _ct_dark_cleanup(oldnumim, gain_bit_dict,
                                    gain_state, dark_sh_dict,
                                    dark_shutter_state)

    except Exception:
        yield from _ct_dark_cleanup(oldnumim, gain_bit_dict, gain_state,
                                    dark_sh_dict, dark_shutter_state)
        raise
    except KeyboardInterrupt:
        yield from _ct_dark_cleanup(oldnumim, gain_bit_dict,
                                    gain_state, dark_sh_dict,
                                    dark_shutter_state)
        raise