Esempio n. 1
0
 def insert_take_dark(msg):
     now = time.time()
     nonlocal need_dark
     qualified_dark_uid = _validate_dark(expire_time=glbl.dk_window)
     # FIXME: should we do "or" or "and"?
     if (not need_dark) and (not qualified_dark_uid):
         need_dark = True
     if need_dark \
             and (not qualified_dark_uid) \
             and msg.command == 'open_run' \
             and ('dark_frame' not in msg.kwargs):
         # We are about to start a new 'run' (e.g., a count or a scan).
         # Insert a dark frame run first.
         need_dark = False
         # Annoying detail: the detector was probably already staged.
         # Unstage it (if it wasn't staged, nothing will happen) and
         # then take_dark() and then re-stage it.
         return bp.pchain(bp.unstage(glbl.area_det), take_dark(),
                          bp.stage(glbl.area_det), bp.single_gen(msg),
                          bp.abs_set(glbl.shutter, 60, wait=True)), None
     elif msg.command == 'open_run' and 'dark_frame' not in msg.kwargs:
         return bp.pchain(bp.single_gen(msg),
                          bp.abs_set(glbl.shutter, 60, wait=True)), None
     else:
         # do nothing if (not need_dark)
         return None, None
Esempio n. 2
0
 def insert_take_dark(msg):
     now = time.time()
     nonlocal need_dark
     qualified_dark_uid = _validate_dark(expire_time=glbl.dk_window)
     # FIXME: should we do "or" or "and"?
     if (not need_dark) and (not qualified_dark_uid):
         need_dark = True
     if need_dark \
             and (not qualified_dark_uid) \
             and msg.command == 'open_run' \
             and ('dark_frame' not in msg.kwargs):
         # We are about to start a new 'run' (e.g., a count or a scan).
         # Insert a dark frame run first.
         need_dark = False
         # Annoying detail: the detector was probably already staged.
         # Unstage it (if it wasn't staged, nothing will happen) and
         # then take_dark() and then re-stage it. 
         return bp.pchain(bp.unstage(glbl.area_det),
                          take_dark(),
                          bp.stage(glbl.area_det),
                          bp.single_gen(msg),
                          bp.abs_set(glbl.shutter, 60, wait=True)), None
     elif msg.command == 'open_run' and 'dark_frame' not in msg.kwargs:
         return bp.pchain(bp.single_gen(msg),
                          bp.abs_set(glbl.shutter, 60, wait=True)), None
     else:
         # do nothing if (not need_dark)
         return None, None
Esempio n. 3
0
def take_dark():
    """a plan for taking a single dark frame"""
    print('INFO: closing shutter...')
    yield from bp.abs_set(glbl.shutter, 0)
    if glbl.shutter_control:
        yield from bp.sleep(2)
    print('INFO: taking dark frame....')
    # upto this stage, glbl.pe1c has been configured to so exposure time is
    # correct
    acq_time = glbl.area_det.cam.acquire_time.get()
    num_frame = glbl.area_det.images_per_set.get()
    computed_exposure = acq_time * num_frame
    # update md
    _md = {'sp_time_per_frame': acq_time,
           'sp_num_frames': num_frame,
           'sp_computed_exposure': computed_exposure,
           'sp_type': 'ct',
           # 'sp_uid': str(uuid.uuid4()), # dark plan doesn't need uid
           'sp_plan_name': 'dark_{}'.format(computed_exposure),
           'dark_frame': True}
    c = bp.count([glbl.area_det], md=_md)
    yield from bp.subs_wrapper(c, {'stop': [_update_dark_dict_list]})
    print('opening shutter...')
    yield from bp.abs_set(glbl.shutter, 1)
    if glbl.shutter_control:
        yield from bp.sleep(2)
Esempio n. 4
0
def test_sigint_manyhits(fresh_RE, motor_det):
    motor, det = motor_det
    motor._fake_sleep = 0.3
    RE = fresh_RE

    pid = os.getpid()

    def sim_kill(n=1):
        for j in range(n):
            print('KILL')
            os.kill(pid, signal.SIGINT)

    lp = RE.loop
    motor.loop = lp
    lp.call_later(.02, sim_kill, 3)
    lp.call_later(.02, sim_kill, 3)
    lp.call_later(.02, sim_kill, 3)
    start_time = ttime.time()
    RE(bp.finalize_wrapper(bp.abs_set(motor, 1, wait=True),
                           bp.abs_set(motor, 0, wait=True)))
    end_time = ttime.time()
    assert end_time - start_time < 0.2  # not enough time for motor to cleanup
    RE.abort()  # now cleanup
    done_cleanup_time = ttime.time()
    assert done_cleanup_time - end_time > 0.3
Esempio n. 5
0
def test_sigint_three_hits(fresh_RE, motor_det):
    motor, det = motor_det
    motor._fake_sleep = 0.3
    RE = fresh_RE

    pid = os.getpid()

    def sim_kill(n=1):
        for j in range(n):
            print('KILL')
            os.kill(pid, signal.SIGINT)

    lp = RE.loop
    motor.loop = lp
    lp.call_later(.02, sim_kill, 3)
    lp.call_later(.02, sim_kill, 3)
    lp.call_later(.02, sim_kill, 3)
    start_time = ttime.time()
    RE(
        bp.finalize_wrapper(bp.abs_set(motor, 1, wait=True),
                            bp.abs_set(motor, 0, wait=True)))
    end_time = ttime.time()
    assert end_time - start_time < 0.2  # not enough time for motor to cleanup
    RE.abort()  # now cleanup
    done_cleanup_time = ttime.time()
    assert done_cleanup_time - end_time > 0.3
    def inner():
        # Prepare TIFF plugin
        if filepath is not None and filename is not None:
            fp = filepath

            if fp[-1] != '/':
                fp+= '/'

            print("Saving files as", "".join((fp, filename, "_XXX.tif")))
            print("First file number:", cam_8.tiff.file_number.get())

            yield from bp.mv(
                tiff.enable, 1,
                tiff.auto_increment, 1,
                tiff.file_path, fp,
                tiff.file_name, filename,
                tiff.file_template, "%s%s_%3.3d.tif",
                tiff.file_write_mode, 1, # Capture mode
                tiff.num_capture, steps,
            )

        # Prepare statistics plugin
        yield from bp.mv(
            stats.enable, 1,
            stats.compute_centroid, 1
        )

        # Prepare Camera
        yield from bp.mv(cam.acquire, 0)      # Stop camera...
        yield from bp.sleep(.5)               # ...and wait for the pipeline to empty.
        yield from bp.mv(
            cam.trigger_mode, "Sync In 1",    # External Trigger
            cam.array_counter, 0,
        )
        yield from bp.abs_set(cam.acquire, 1) # wait=False
        yield from bp.abs_set(tiff.capture, 1)

        # Move to the starting positions
        yield from bp.mv(
            slt_gap, gap,                     # Move gap to desired position
            slt_ctr, start - move_slack,      # Move slits to the beginning of the motion
            stats.ts_control, "Erase/Start",  # Prepare statistics Time Series
        )

        # Set Slits Center velocity for the scan
        yield from bp.mv(slt_ctr.velocity, speed)

        # Go
        yield from bp.kickoff(flyer, wait=True)
        st = yield from bp.complete(flyer)
        yield from bp.abs_set(slt_ctr, end + move_slack)

        while not st.done:
            yield from bp.collect(flyer, stream=True)
            yield from bp.sleep(0.2)

        yield from bp.sleep(1)
        yield from bp.collect(flyer, stream=True)

        yield from bp.mv(stats.ts_control, "Stop")
Esempio n. 7
0
def take_dark():
    """a plan for taking a single dark frame"""
    print('INFO: closing shutter...')
    # 60 means open at XPD, Oct.4, 2016
    yield from bp.abs_set(glbl.shutter, 0, wait=True)
    #if glbl.shutter_control:
    #    yield from bp.sleep(2)
    print('INFO: taking dark frame....')
    # upto this stage, glbl.pe1c has been configured to so exposure time is
    # correct
    acq_time = glbl.area_det.cam.acquire_time.get()
    num_frame = glbl.area_det.images_per_set.get()
    computed_exposure = acq_time * num_frame
    # update md
    _md = {
        'sp_time_per_frame': acq_time,
        'sp_num_frames': num_frame,
        'sp_computed_exposure': computed_exposure,
        'sp_type': 'ct',
        # 'sp_uid': str(uuid.uuid4()), # dark plan doesn't need uid
        'sp_plan_name': 'dark_{}'.format(computed_exposure),
        'dark_frame': True
    }
    c = bp.count([glbl.area_det], md=_md)
    yield from bp.subs_wrapper(c, {'stop': [_update_dark_dict_list]})
    print('opening shutter...')
Esempio n. 8
0
 def plan():
     while True:
         for step in np.linspace(start, stop, num):
             yield from abs_set(motor, step, wait=True)
             yield from trigger_and_read(list(detectors) + [motor])
         err = errorbar(lf.result, 'sigma')
         if err < .03:
             break
Esempio n. 9
0
def continuous_step_scan(mymotor, motor_min, motor_max, motor_step, collection_time):
    "Step mymotor, produce a single file."
    # Move to start position
    yield from abs_set(mymotor, motor_min, wait=True)
    # Start
    yield from bp.kickoff(detector, wait=True)
    # and immediately pause
    yield from bp.pause(detector, wait=True)

    for num in range(motor_min, motor_max, motor_step):
        yield from abs_set(mymotor, num, wait=True)
        yield from abs_set(bs_adned_reset_counters, 1, wait=True)
        yield from bp.resume(detector, wait=True)
        yield from bp.sleep(collection_time)
        yield from bp.pause(detector, wait=True)

    yield from bp.complete(detector, wait=True)
    yield from bp.collect(detector)
Esempio n. 10
0
def step_scan_pcharge(mymotor, motor_min, motor_max, motor_step, pcharge):
    "Step mymotor from min -> max with a step size of step and collect for a given pcharge"
    for num in np.arange(motor_min, motor_max, motor_step):
        yield from abs_set(mymotor, num, wait=True)
        yield from bp.kickoff(detector, wait=True)
        yield from _waitfor_proton_charge(pcharge)
        yield from bp.complete(detector, wait=True)
        yield from bp.collect(detector)
        yield from bp.trigger_and_read([mymotor, bs_neutrons_roi, bs_pcharge])
Esempio n. 11
0
def slit_scan_fiducialize(slits,
                          yag,
                          x_width=0.01,
                          y_width=0.01,
                          samples=10,
                          filters=None,
                          centroid='detector_stats2_centroid_y'):
    """
    Assists beam alignment by setting the slits to a w,h and checking,
    returning the centroid position.

    Parameters
    ----------
    slits : pcdsdevices.slits.Slits
        Ophyd slits object from pcdsdevices.slits.Slits

    yag : pcdsdevices.pim.PIM
        Detector to fidicuialize. This plan assumes the detector is stated and
        inserted

    x_width : float
        x dimensions of the gap in the slits. EGU: mm

    y_width : float
        y dimensions of the gap in the slits. EGU: mm

    samples : int
        Returned measurements are averages over multiple samples. samples arg
        determines the number of samples to average over for returned data

    filters : dict, optional
        Key, callable pairs of event keys and single input functions that
        evaluate to True or False. For more infromation see
        :meth:`.apply_filters`

    centroid : str, optional
        Key to gather centroid information

    Returns
    -------
    float
        return centroid position in pixel space, single axis
    """
    #Set slits
    yield from abs_set(slits, x_width, wait=True)

    #Collect data from yags
    yag_measurements = yield from measure_average([yag],
                                                  num=samples,
                                                  filters=filters)

    #Extract centroid positions from yag_measurments dict
    centroid = yag_measurements[field_prepend(centroid, yag)]

    return centroid
Esempio n. 12
0
def Gas_Plan(gas_in='He', liveplot_key=None, totExpTime=5, num_exp=1, delay=1):
    """
    Example
    -------
    Set the gasses. They can be in any other, nothing to do with
    the order they are used in the plan. But, should match the connections on switch.
    >>> gas.gas_list = ['He', 'N2', 'CO2']
    >>> RGA mass is set to different value, base shows 1^-13 with He 5 cc flow shows max 2^-8
    >>> RGA mass setup in mID mode: 4,18,28,31,44,79,94,32,81
    Parameters
    ----------
    gas_in : string
        e.g., 'He', default is 'He'
        These gas must be in `gas.gas_list` but they may be in any order.
    liveplot_key : str, optional
        e. g., liveplot_key = rga_mass1
        data key for LivePlot. default is None, which means no LivePlot
    totExpTime : float
        total exposure time per frame in seconds. Dafault value is 5 sec
    num_exp : int
        number of images/exposure, default is 1
    delay: float
        delay time between exposures in sec

    Execute it
    ----------
    >> %run -i /home/xf28id1/Documents/Sanjit/Scripts/GasXrun_Plan.py
    >> change all the parameters inside Gas_Plan as required
    >>> gas_plan = Gas_Plan(gas_in = 'He', liveplot_key= 'rga_mass1', totExpTime = 5, num_exp = 3, delay = 1)
    >> to run the xrun, save metadata & save_tiff run the following
    >>> run_and_save(sample_num = 0)  
    """

    ## switch gas
    yield from abs_set(gas, gas_in)

    ## configure the exposure time first
    _configure_area_det(totExpTime)  # 5 secs exposuretime

    ## ScanPlan you need
    plan = bp.count([pe1c, gas.current_gas, rga], num=num_exp, delay=delay)

    #plan = bp.subs_wrapper(plan, LiveTable([xpd_configuration['area_det'], rga]))   # give you LiveTable
    plan = bp.subs_wrapper(
        plan, LiveTable([xpd_configuration['area_det'], gas.current_gas, rga]))
    if liveplot_key and isinstance(liveplot_key, str):
        plan = bp.subs_wrapper(plan, LivePlot(liveplot_key))

    yield from plan
Esempio n. 13
0
def test_dets_shutter(db, tmp_dir, name, fp):
    det = det_factory(name, db.fs, fp, save_path=tmp_dir, shutter=shctl1)
    RE = setup_test_run_engine()
    RE.subscribe('all', db.mds.insert)
    scan = Count([det], )
    db.fs.register_handler('RWFS_NPY', be.ReaderWithFSHandler)
    cycle2 = build_image_cycle(fp)
    cg = cycle2()
    # With the shutter down
    RE(abs_set(shctl1, 0, wait=True))
    uid = RE(scan)
    for n, d in db.restream(db[-1], fill=True):
        if n == 'event':
            assert_array_equal(d['data']['pe1_image'],
                               np.zeros(next(cg)['pe1_image'].shape))
    assert uid is not None

    # With the shutter up
    RE(abs_set(shctl1, 1, wait=True))
    uid = RE(scan)
    for n, d in db.restream(db[-1], fill=True):
        if n == 'event':
            assert_array_equal(d['data']['pe1_image'], next(cg)['pe1_image'])
    assert uid is not None
Esempio n. 14
0
def get_ID_calibration_dan(gapstart,gapstop,gapstep=.2,gapoff=0):
    """
    by LW 04/20/2015
    function to automatically take a ID calibration curve_fit
    calling sequence: get_ID_calibration(gapstart,gapstop,gapstep=.2,gapoff=0)
	gapstart: minimum gap used in calibration (if <5.2, value will be set to 5.2)
	gapstop: maximum gap used in calibration
	gapstep: size of steps between two gap points
	gapoff: offset applied to calculation gap vs. energy from xfuncs.get_Es(gap-gapoff)
	thermal management of Bragg motor is automatic, waiting for cooling <80C between Bragg scans
    writes outputfile with fitted value for the center of the Bragg scan to:  '/home/xf11id/Repos/chxtools/chxtools/X-ray_database/
	changes 03/18/2016: made compatible with python V3 and latest versio of bluesky (working on it!!!)
    """
    import numpy as np
    #import xfuncs as xf
    #from dataportal import DataBroker as db, StepScan as ss, DataMuxer as dm
    import time
    from epics import caput, caget
    from matplotlib import pyplot as plt
    from scipy.optimize import curve_fit
    gaps = np.arange(gapstart, gapstop, gapstep) - gapoff   # not sure this should be '+' or '-' ...
    print('ID calibration will contain the following gaps [mm]: ',gaps)
    xtal_map = {1: 'Si111cryo', 2: 'Si220cryo'}
    pos_sts_pv = 'XF:11IDA-OP{Mono:DCM-Ax:X}Pos-Sts'
    try:
        xtal = xtal_map[caget(pos_sts_pv)]
    except KeyError:
        raise CHX_utilities_Exception('error: trying to do ID gap calibration with no crystal in the beam')
    print('using', xtal, 'for ID gap calibration')
    # create file for writing calibration data:
    fn='id_CHX_IVU20_'+str(time.strftime("%m"))+str(time.strftime("%d"))+str(time.strftime("%Y"))+'.dat'
    fpath='/tmp/'
    # fpath='/home/xf11id/Repos/chxtools/chxtools/X-ray_database/'
    try:
        outFile = open(fpath+fn, 'w')
        outFile.write('% data from measurements '+str(time.strftime("%D"))+'\n')
        outFile.write('% K colkumn is a placeholder! \n')
        outFile.write('% ID gap [mm]     K      E_1 [keV] \n')
        outFile.close()
        print('successfully created outputfile: ',fpath+fn)
    except:
        raise CHX_utilities_Exception('error: could not create output file')
    
    ### do the scanning and data fitting, file writing,....
    t_adjust=0
    center=[]
    E1=[]
    realgap=[]
    detselect(xray_eye1)
    print(gaps)
    MIN_GAP = 5.2
    for i in gaps:
        if i >= MIN_GAP: 
            B_guess=-1.0*xf.get_Bragg(xtal,xf.get_Es(i+gapoff,5)[1])[0]
        else:
            i = MIN_GAP 
            B_guess=-1.0*xf.get_Bragg(xtal,xf.get_Es(i,5)[1])[0]
        if i > 8 and t_adjust == 0:     # adjust acquistion time once while opening the gap (could write something more intelligent in the long run...)
           exptime=caget('XF:11IDA-BI{Bpm:1-Cam:1}cam1:AcquireTime')
           caput('XF:11IDA-BI{Bpm:1-Cam:1}cam1:AcquireTime',2*exptime)
           t_adjust = 1
        print('initial guess: Bragg= ',B_guess,' deg.   ID gap = ',i,' mm')
        es = xf.get_Es(i, 5)[1]
        mirror_stripe_pos = round(caget('XF:11IDA-OP{Mir:HDM-Ax:Y}Mtr.VAL'),1)
        SI_STRIPE = -7.5
        RH_STRIPE = 7.5
        if es < 9.5:
            stripe = SI_STRIPE
        elif es >= 9.5:
            stripe = RH_STRIPE
        yield from bp.abs_set(hdm.y, stripe)
        yield from bp.abs_set(foil_y, 0)  # Put YAG in beam.
        print('moving DCM Bragg angle to:', B_guess ,'deg and ID gap to', i, 'mm')
        yield from bp.abs_set(dcm.b, B_guess)
        yield from bp.abs_set(ivu_gap,i)
        print('hurray, made it up to here!')
        print('about to collect data')
        yield from ascan(dcm.b, float(B_guess-.4), float(B_guess+.4), 60,
                         md={'plan_name': 'ID_calibration',
                             'mirror_stripe': stripe})
        header = db[-1]					#retrive the data (first data point is often "wrong", so don't use
        data = get_table(header)
        B = data.dcm_b[2:]
        intdat = data.xray_eye1_stats1_total[2:] 																	
        B=np.array(B)
        intdat=np.array(intdat)
        A=np.max(intdat)          # initial parameter guess and fitting
        xc=B[np.argmax(intdat)]
        w=.2
        yo=np.mean(intdat)
        p0=[yo,A,xc,w]
        print('initial guess for fitting: ',p0)
        try:
            coeff,var_matrix = curve_fit(gauss,B,intdat,p0=p0)
            center.append(coeff[2])
            E1.append(xf.get_EBragg(xtal,-coeff[2])/5.0)
            realgap.append(caget('SR:C11-ID:G1{IVU20:1-LEnc}Gap'))
#   # append data file by i, 1 & xf.get_EBragg(xtal,-coeff[2]/5.0):
            with open(fpath+fn, "a") as myfile:
                myfile.write(str(caget('SR:C11-ID:G1{IVU20:1-LEnc}Gap'))+'    1.0 '+str(float(xf.get_EBragg(xtal,-coeff[2])/5.0))+'\n')
            print('added data point: ',caget('SR:C11-ID:G1{IVU20:1-LEnc}Gap'),' ',1.0,'     ',str(float(xf.get_EBragg(xtal,-coeff[2])/5.0)))
        except: print('could not evaluate data point for ID gap = ',i,' mm...data point skipped!')
        while caget('XF:11IDA-OP{Mono:DCM-Ax:Bragg}T-I') > 80:
            time.sleep(30)
            print('DCM Bragg axis too hot (>80C)...waiting...')
    plt.close(234)
    plt.figure(234)
    plt.plot(E1,realgap,'ro-')
    plt.xlabel('E_1 [keV]')
    plt.ylabel('ID gap [mm]')
    plt.title('ID gap calibration in file: '+fpath+fn,size=12)
    plt.grid()
 def dwell(detectors, motor, step):
     yield from checkpoint()
     yield from bp.abs_set(motor, step, wait=True)
     yield from bp.sleep(sleep_time)
     
     return (yield from bp.trigger_and_read(list(detectors)+[motor]))
Esempio n. 16
0
def slit_scan_area_comp(slits, yag, x_width=1.0, y_width=1.0, samples=1):
    """Find the ratio of real space/pixel in the PIM

    1. Send slits to specified position
    2. Measure pixel dimensions of passed light. 
        The idea is that the width, height values will be pulled from the
        PIMPulnixDetector instance.

    2b. Should diffraction issues (as observed with the test laser) persist
        when using the x-ray laser, another method will be necessary  instead 
        of using the gap dimensions for calibration, we could move the gap in 
        the slits a small distance and observe the position change of the 
        passed light. If the light is highly collimated (it should be), the 
        motion of the gap should be 1:1 with the motion of the passed light on
        the PIM detector. Only investigate if issues persisit in x-ray. 

    Parameters
    ----------
    slits : pcdsdevices.slits.Slits
        Ophyd slits object from pcdsdevices.slits.Slits 
    
    yag : pcdsdevices.sim.pim.PIM (subject to change?)
        Ophyd object of some type, this will allow me to read the w, h 
        (w,h don't exist yet but they should shortly)

    x_width : int 
        Define the target x width of the gap in the slits. Units: mm

    y_width : int 
        Define the target y width of the gap in the slits. Units: mm

    samples : int
        number of sampels to use and average over when measuring width, height


    Returns
    -------
    (float,float)
        returns a tuple of x and y scaling respectively. Units mm/pixels
    """
    # place slits then read a value that doesn't exist yet
    # easy
    # measure_average()
    #data = yield from measure_average([yag],['xwidth','ywidth'])

    # set slits to specified gap size
    yield from abs_set(slits, x=x_width, y=y_width)

    # read profile dimensions from image (width plugin pending)
    yag_measurements = yield from measure_average([yag], num=samples)

    # extract measurements of interest from returned dict
    yag_measured_x_width = yag_measurements['xwidth']
    yag_measured_y_width = yag_measurements['ywidth']

    logger.debug("Measured x width: {}".format(yag_measured_x_width))
    logger.debug("Measured y width: {}".format(yag_measured_y_width))

    # err if image not received or image has 0 width,height
    if (yag_measured_x_width <= 0 \
        or yag_measured_y_width <=0):
        raise ValueError("A measurement less than or equal to zero has been"
                         "measured. Unable to calibrate")
        x_scaling = nan
        y_scaling = nan
    else:
        #data format: Real space / pixel
        x_scaling = x_width / yag_measured_x_width
        y_scaling = y_width / yag_measured_y_width

    return x_scaling, y_scaling
Esempio n. 17
0
def prep_img_motors(n_mot,
                    img_motors,
                    prev_out=True,
                    tail_in=True,
                    timeout=None):
    """
    Plan to prepare image motors for taking data. Moves the correct imagers in
    and waits for them to be ready.

    Parameters
    ----------
    n_mot: int
        Index of the motor in img_motors that we need to take data with.

    img_motors: list of OphydObject
        OphydObjects to move in or out. These objects need to have .set methods
        that accept the strings "IN" and "OUT", reacting appropriately, and
        need to accept a "timeout" kwarg that allows their status to be set as
        done after a timeout. These should be ordered by increasing distance
        to the source.

    prev_out: bool, optional
        If True, pull out imagers closer to the source than the one we need to
        use. Default True. (True if imager blocks beam)

    tail_in: bool, optional
        If True, put in imagers after this one, to be ready for later. If
        False, don't touch them. We won't wait for the tail motors to move in.

    timeout: number, optional
        Only wait for this many seconds before moving on.

    Returns
    -------
    ok: bool
        True if the wait succeeded, False otherwise.
    """
    start_time = time.time()

    prev_img_mot = str(uuid.uuid4())
    ok = True

    try:
        for i, mot in enumerate(img_motors):
            if i < n_mot and prev_out:
                if timeout is None:
                    yield from abs_set(mot, "OUT", group=prev_img_mot)
                else:
                    yield from abs_set(mot,
                                       "OUT",
                                       group=prev_img_mot,
                                       timeout=timeout)
            elif i == n_mot:
                if timeout is None:
                    yield from abs_set(mot, "IN", group=prev_img_mot)
                else:
                    yield from abs_set(mot,
                                       "IN",
                                       group=prev_img_mot,
                                       timeout=timeout)
            elif tail_in:
                yield from abs_set(mot, "IN")
        yield from plan_wait(group=prev_img_mot)
    except FailedStatus:
        ok = False

    if ok and timeout is not None:
        ok = time.time() - start_time < timeout

    if ok:
        logger.debug("prep_img_motors completed successfully")
    else:
        logger.debug("prep_img_motors exitted with timeout")
    return ok
Esempio n. 18
0
def match_condition(signal,
                    condition,
                    mover,
                    setpoint,
                    timeout=None,
                    sub_type=None,
                    has_stop=True):
    """
    Plan to adjust mover until condition(signal.value) returns True.

    Parameters
    ----------
    signal: Signal
        Object that implements the Bluesky "readable" interface, including the
        optional subscribe function, sending at least the keyword "value" as in
        ophyd.Signal.

    condition: function
        Function that accepts a single argument, "value", and returns
        True or False.

    mover: Device
        Object that implements both the Bluesky "readable" and "movable"
        interfaces, accepting "moved_cb" as a keyword argument as in
        ophyd.positioner.PositionerBase.

    setpoint: any
        We will call mover.set(setpoint). Pick a good value (the limit switch?)

    timeout: float, optional
        Stop if we hit a timeout.

    sub_type: str, optional
        Use a different subscription than the signal's default.

    has_stop: bool, optional
        Boolean to indicate whether or not we can stop the motor. We usually
        use the motor's stop command to stop at the signal. If this is set to
        False (e.g. we can't stop it), go back to center of the largest range
        with the condition satisfied after reaching the end.

    Returns
    -------
    ok: bool
        True if we reached the condition, False if we timed out or reached the
        setpoint before satisfying the condition.
    """
    # done = threading.Event()
    success = threading.Event()

    if has_stop:

        def condition_cb(*args, value, **kwargs):
            if condition(value):
                success.set()
                mover.stop()
    else:
        pts = []

        def condition_cb(*args, value, **kwargs):
            nonlocal pts
            if condition(value):
                pts.append((mover.position, True))
            else:
                pts.append((mover.position, False))

    if sub_type is not None:
        signal.subscribe(condition_cb, sub_type=sub_type)
    else:
        signal.subscribe(condition_cb)

    try:
        yield from abs_set(mover, setpoint, wait=True, timeout=timeout)
    except FailedStatus:
        logger.warning("Timeout on motor %s", mover)

    if not has_stop:
        best_start = -1
        best_end = -1
        curr_start = -1
        curr_end = -1

        def new_best(best_start, best_end, curr_start, curr_end):
            if -1 in (best_start, best_end):
                return curr_start, curr_end
            elif -1 in (curr_start, curr_end):
                return best_start, best_end
            else:
                curr_dist = abs(pts[curr_end][0] - pts[curr_start][0])
                best_dist = abs(pts[best_end][0] - pts[best_start][0])
                if curr_dist > best_dist:
                    return curr_start, curr_end
                else:
                    return best_start, best_end

        logger.debug("Checking a set of %i stored points", len(pts))
        for i, (pos, ok) in enumerate(pts):
            if ok:
                if curr_start == -1:
                    curr_start = i
                curr_end = i
            else:
                best_start, best_end = new_best(best_start, best_end,
                                                curr_start, curr_end)
                curr_start = -1
                curr_end = -1
        best_start, best_end = new_best(best_start, best_end, curr_start,
                                        curr_end)
        if -1 in (best_start, best_end):
            logger.debug('did not find any valid points: %s', pts)
        else:
            logger.debug('found valid points, moving back')
            start = pts[best_start][0]
            end = pts[best_end][0]
            try:
                yield from abs_set(mover, (end + start) / 2,
                                   wait=True,
                                   timeout=timeout)
            except FailedStatus:
                logger.warning("Timeout on motor %s", mover)
            if condition(signal.value):
                success.set()

    signal.clear_sub(condition_cb)

    ok = success.is_set()
    if ok:
        logger.debug(('condition met in match_condition, '
                      'mover=%s setpt=%s cond value=%s'), mover.name, setpoint,
                     signal.value)
    else:
        logger.debug(('condition fail in match_condition, '
                      'mover=%s setpt=%s cond value=%s'), mover.name, setpoint,
                     signal.value)
    return ok
 def inner():
     yield from bp.abs_set(motor, start, wait=True)
     yield from bp.sleep(sleep_time)
     yield from scan([detector], motor, start, stop, steps, per_step=dwell)
    def inner():
        # Prepare Camera
        yield from bp.mv(cam.acquire, 0)      # Stop camera...
        yield from bp.sleep(.5)               # ...and wait for the pipeline to empty.
        yield from bp.mv(
            cam.trigger_mode, "Sync In 1",    # External Trigger
            cam.array_counter, 0,
        )

        if use_roi4:
            yield from bp.mv(
                cam.min_x, roi.min_xyz.min_x.get(),
                cam.min_y, roi.min_xyz.min_y.get(),
                cam.size.size_x, roi.size.x.get(),
                cam.size.size_y, roi.size.y.get()
            )

        # Prepare TIFF Plugin
        yield from bp.mv(
            tiff.file_write_mode, "Stream",
            tiff.num_capture, steps,
            tiff.auto_save, 1,
            tiff.auto_increment, 1,
            tiff.file_path, folder,
            tiff.file_name, filename,
            tiff.file_template, "%s%s_%d.tif",
            tiff.file_number, 1,
            tiff.enable, 1)

        yield from bp.abs_set(tiff.capture, 1)

        yield from bp.abs_set(cam.acquire, 1) # wait=False

        # Move to the starting positions
        yield from bp.mv(
            gonio.py, start_y - slack_y,
            gonio.pz, start_z - slack_z,
        )

        # Set velocity for the scan
        yield from bp.mv(
            gonio.py.velocity, speed_y,
            gonio.pz.velocity, speed_z
        )

        # Arm Zebra
        yield from bp.abs_set(zebra.pos_capt.arm.arm, 1)

        # Wait Zebra armed
        while not zebra2.download_status.get():
            time.sleep(0.1)

        # Go
        yield from bp.mv(
            gonio.py, end_y + slack_y,
            gonio.pz, end_z + slack_z
        )

        yield from abs_set(tiff.capture, 0)

        print(f"{cam.array_counter.get()} images captured")
Esempio n. 21
0
    def __call__(self, sample, plan, subs=None, *,
                 verify_write=False, dark_strategy=periodic_dark,
                 raise_if_interrupted=False, **metadata_kw):
        # The CustomizedRunEngine knows about a Beamtime object, and it
        # interprets integers for 'sample' as indexes into the Beamtime's
        # lists of Samples from all its Experiments.

        # deprecated from v0.5 release
        #if getattr(glbl, 'collection', None) is None:
        #    raise RuntimeError("No collection has been linked to current "
        #                       "experiment yet.\nPlease do\n"
        #                       ">>> open_collection(<collection_name>)\n"
        #                       "before you run any prun")

        if isinstance(sample, int):
            try:
                sample = self.beamtime.samples[sample]
            except IndexError:
                print("WARNING: hmm, there is no sample with index `{}`"
                      ", please do `bt.list()` to check if it exists yet"
                      .format(sample))
                return
        # If a plan is given as a string, look in up in the global registry.
        if isinstance(plan, int):
            try:
                plan = self.beamtime.scanplans[plan]
            except IndexError:
                print("WARNING: hmm, there is no scanplan with index `{}`"
                      ", please do `bt.list()` to check if it exists yet"
                      .format(plan))
                return
        # If the plan is an xpdAcq 'ScanPlan', make the actual plan.
        if isinstance(plan, ScanPlan):
            plan = plan.factory()
        _subs = normalize_subs_input(subs)
        if verify_write:
            _subs.update({'stop': verify_files_saved})
        # No keys in metadata_kw are allows to collide with sample keys.
        if set(sample) & set(metadata_kw):
            raise ValueError("These keys in metadata_kw are illegal "
                             "because they are always in sample: "
                             "{}".format(set(sample) & set(metadata_kw)))
        if self._beamtime.get('bt_wavelength') is None:
            print("WARNING: there is no wavelength information in current"
                  "beamtime object, scan will keep going....")
        metadata_kw.update(sample)
        sh = glbl.shutter
        # force to open shutter before scan and close it after
        if glbl.shutter_control:
            plan = bp.pchain(bp.abs_set(sh, 1), plan, bp.abs_set(sh, 0))
        # Alter the plan to incorporate dark frames.
        if glbl.auto_dark:
            plan = dark_strategy(plan)
            plan = bp.msg_mutator(plan, _inject_qualified_dark_frame_uid)
        # Load calibration file
        if glbl.auto_load_calib:
            plan = bp.msg_mutator(plan, _inject_calibration_md)
        # Execute
        super().__call__(plan, subs,
                         raise_if_interrupted=raise_if_interrupted,
                         **metadata_kw)

        # deprecated from v0.5 release
        # insert collection
        #_insert_collection(glbl.collection_name, glbl.collection,
        #                   self._run_start_uids)

        return self._run_start_uids
Esempio n. 22
0
 def per_step(dets, motor, step):
     yield from one_1d_step(dets, motor, step)
     yield from bp.abs_set(camera, 1, wait=True)
     yield from bp.abs_set(camera, 0, wait=True)
     yield from bp.sleep(idle_time)
Esempio n. 23
0
    def __call__(self,
                 sample,
                 plan,
                 subs=None,
                 *,
                 verify_write=False,
                 dark_strategy=periodic_dark,
                 raise_if_interrupted=False,
                 **metadata_kw):
        # The CustomizedRunEngine knows about a Beamtime object, and it
        # interprets integers for 'sample' as indexes into the Beamtime's
        # lists of Samples from all its Experiments.

        # deprecated from v0.5 release
        #if getattr(glbl, 'collection', None) is None:
        #    raise RuntimeError("No collection has been linked to current "
        #                       "experiment yet.\nPlease do\n"
        #                       ">>> open_collection(<collection_name>)\n"
        #                       "before you run any xrun")

        if isinstance(sample, int):
            try:
                sample = self.beamtime.samples[sample]
            except IndexError:
                print(
                    "WARNING: hmm, there is no sample with index `{}`"
                    ", please do `bt.list()` to check if it exists yet".format(
                        sample))
                return
        # If a plan is given as a string, look in up in the global registry.
        if isinstance(plan, int):
            try:
                plan = self.beamtime.scanplans[plan]
            except IndexError:
                print(
                    "WARNING: hmm, there is no scanplan with index `{}`"
                    ", please do `bt.list()` to check if it exists yet".format(
                        plan))
                return
        # If the plan is an xpdAcq 'ScanPlan', make the actual plan.
        if isinstance(plan, ScanPlan):
            plan = plan.factory()
        _subs = normalize_subs_input(subs)
        if verify_write:
            _subs.update({'stop': verify_files_saved})
        # No keys in metadata_kw are allows to collide with sample keys.
        if set(sample) & set(metadata_kw):
            raise ValueError("These keys in metadata_kw are illegal "
                             "because they are always in sample: "
                             "{}".format(set(sample) & set(metadata_kw)))
        if self._beamtime.get('bt_wavelength') is None:
            print("WARNING: there is no wavelength information in current"
                  "beamtime object, scan will keep going....")
        metadata_kw.update(sample)
        sh = glbl.shutter

        if glbl.shutter_control:
            # Alter the plan to incorporate dark frames.
            # only works if user allows shutter control
            if glbl.auto_dark:
                plan = dark_strategy(plan)
                plan = bp.msg_mutator(plan, _inject_qualified_dark_frame_uid)
            # force to close shutter after scan
            plan = bp.finalize_wrapper(plan, bp.abs_set(sh, 0, wait=True))

        # Load calibration file
        if glbl.auto_load_calib:
            plan = bp.msg_mutator(plan, _inject_calibration_md)

        # Insert glbl mask
        plan = bp.msg_mutator(plan, _inject_mask)

        # Execute
        return super().__call__(plan,
                                subs,
                                raise_if_interrupted=raise_if_interrupted,
                                **metadata_kw)
Esempio n. 24
0
def hf2dwire(*,
             xstart,
             xnumstep,
             xstepsize,
             zstart,
             znumstep,
             zstepsize,
             acqtime,
             numrois=1,
             i0map_show=True,
             itmap_show=False,
             energy=None,
             u_detune=None):
    '''
    input:
        xstart, xnumstep, xstepsize (float)
        zstart, znumstep, zstepsize (float)
        acqtime (float): acqusition time to be set for both xspress3 and F460
        numrois (integer): number of ROIs set to display in the live raster scans. This is for display ONLY. 
                           The actualy number of ROIs saved depend on how many are enabled and set in the read_attr
                           However noramlly one cares only the raw XRF spectra which are all saved and will be used for fitting.
        i0map_show (boolean): When set to True, map of the i0 will be displayed in live raster, default is True
        itmap_show (boolean): When set to True, map of the trasnmission diode will be displayed in the live raster, default is True   
        energy (float): set energy, use with caution, hdcm might become misaligned
        u_detune (float): amount of undulator to detune in the unit of keV
    '''

    #record relevant meta data in the Start document, defined in 90-usersetup.py
    md = get_stock_md()

    #setup the detector
    # TODO do this with configure
    current_preamp.exp_time.put(acqtime - 0.09)
    xs.settings.acquire_time.put(acqtime)
    xs.total_points.put((xnumstep + 1) * (znumstep + 1))

    #    det = [current_preamp, xs]
    det = [xs]

    #setup the live callbacks
    livecallbacks = []

    livetableitem = [
        hf_stage.x, hf_stage.z, 'current_preamp_ch0', 'current_preamp_ch2',
        'xs_channel1_rois_roi01_value'
    ]

    xstop = xstart + xnumstep * xstepsize
    zstop = zstart + znumstep * zstepsize

    print('xstop = ' + str(xstop))
    print('zstop = ' + str(zstop))

    for roi_idx in range(numrois):
        roi_name = 'roi{:02}'.format(roi_idx + 1)

        roi_key = getattr(xs.channel1.rois, roi_name).value.name
        livetableitem.append(roi_key)

        #    livetableitem.append('saturn_mca_rois_roi'+str(roi_idx)+'_net_count')
        #    livetableitem.append('saturn_mca_rois_roi'+str(roi_idx)+'_count')
        #    #roimap = LiveRaster((xnumstep, znumstep), 'saturn_mca_rois_roi'+str(roi_idx)+'_net_count', clim=None, cmap='viridis', xlabel='x', ylabel='y', extent=None)
        colormap = 'inferno'  #previous set = 'viridis'
        #    roimap = LiveRaster((znumstep, xnumstep), 'saturn_mca_rois_roi'+str(roi_idx)+'_count', clim=None, cmap='inferno',
        #                        xlabel='x (mm)', ylabel='y (mm)', extent=[xstart, xstop, zstop, zstart])

        #        roimap = myLiveRaster((znumstep+1, xnumstep+1), roi_key, clim=None, cmap='inferno', aspect='equal',
        #                            xlabel='x (mm)', ylabel='y (mm)', extent=[xstart, xstop, zstop, zstart])
        roimap = LiveRaster((znumstep + 1, xnumstep + 1),
                            roi_key,
                            clim=None,
                            cmap='inferno',
                            aspect=0.01,
                            xlabel='x (mm)',
                            ylabel='y (mm)',
                            extent=[xstart, xstop, zstop, zstart])
        #        liveplotfig = plt.figure('through focus')
        #        roiplot = LivePlot(roi_key,x=hf_stage.x.name, fig=liveplotfig)
        livecallbacks.append(roimap)
#        livecallbacks.append(roiplot)

#    if i0map_show is True:
#        i0map = myLiveRaster((znumstep+1, xnumstep+1), 'current_preamp_ch2', clim=None, cmap='inferno',
#                        xlabel='x (mm)', ylabel='y (mm)', extent=[xstart, xstop, zstop, zstart])
#        livecallbacks.append(i0map)

#    if itmap_show is True:
#        itmap = myLiveRaster((znumstep+1, xnumstep+1), 'current_preamp_ch0', clim=None, cmap='inferno',
#                        xlabel='x (mm)', ylabel='y (mm)', extent=[xstart, xstop, zstop, zstart])
#        livecallbacks.append(itmap)
#    commented out liveTable in 2D scan for now until the prolonged time issue is resolved
    livecallbacks.append(LiveTable(livetableitem))

    #setup the plan

    if energy is not None:
        if u_detune is not None:
            # TODO maybe do this with set
            energy.detune.put(u_detune)
        # TODO fix name shadowing
        yield from bp.abs_set(energy, energy, wait=True)


#    shut_b.open_cmd.put(1)
#    while (shut_b.close_status.get() == 1):
#        epics.poll(.5)
#        shut_b.open_cmd.put(1)

    hf2dwire_scanplan = bp.grid_scan(det,
                                     hf_stage.z,
                                     zstart,
                                     zstop,
                                     znumstep + 1,
                                     hf_stage.x,
                                     xstart,
                                     xstop,
                                     xnumstep + 1,
                                     True,
                                     md=md)
    hf2dwire_scanplan = bp.subs_wrapper(hf2dwire_scanplan, livecallbacks)
    scaninfo = yield from hf2dwire_scanplan

    #    shut_b.close_cmd.put(1)
    #    while (shut_b.close_status.get() == 0):
    #        epics.poll(.5)
    #        shut_b.close_cmd.put(1)

    #write to scan log
    logscan('2dwire')

    return scaninfo
def fast_shutter_wrapper(plan):
    if gs.USE_FAST_SHUTTER:
        plan = bsp.pchain(bsp.abs_set(fast_shutter.output, FastShutter.OPEN_SHUTTER, settle_time=FastShutter.SETTLE_TIME), plan)
        plan = bsp.finalize_wrapper(plan, bsp.abs_set(fast_shutter.output, FastShutter.CLOSE_SHUTTER, settle_time=FastShutter.SETTLE_TIME))
    return (yield from plan)
Esempio n. 26
0
def step_scan(mymotor, motor_min, motor_max, motor_step, collection_time):
    "Step mymotor from min -> max with a step size of step and collect for a given time"
    for num in np.arange(motor_min, motor_max, motor_step):
        yield from abs_set(mymotor, num, wait=True)
        yield from _time_plan(collection_time)
Esempio n. 27
0
 def per_step(dets, motor, step):
     yield from one_1d_step(dets, motor, step)
     yield from bp.abs_set(camera, 1, wait=True)
     yield from bp.abs_set(camera, 0, wait=True)
     yield from bp.sleep(idle_time)