Ejemplo n.º 1
0
def take_dark():
    """a plan for taking a single dark frame"""
    print("INFO: closing shutter...")
    yield from bps.abs_set(xpd_configuration.get("shutter"),
                           XPD_SHUTTER_CONF["close"],
                           wait=True)
    print("INFO: taking dark frame....")
    # upto this stage, area_det has been configured to so exposure time is
    # correct
    area_det = xpd_configuration["area_det"]
    acq_time = area_det.cam.acquire_time.get()
    num_frame = 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_plan_name": "dark_{}".format(computed_exposure),
        "dark_frame": True,
    }
    c = bp.count([area_det], md=_md)
    yield from bpp.subs_wrapper(c, {"stop": [_update_dark_dict_list]})
    print("opening shutter...")
Ejemplo n.º 2
0
    def insert_take_dark(msg):
        now = time.time()
        nonlocal need_dark
        qualified_dark_uid = _validate_dark(expire_time=glbl["dk_window"])
        area_det = xpd_configuration["area_det"]

        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 (
                bpp.pchain(
                    bps.unstage(area_det),
                    take_dark(),
                    bps.stage(area_det),
                    bpp.single_gen(msg),
                    bps.abs_set(
                        xpd_configuration.get("shutter"),
                        XPD_SHUTTER_CONF["open"],
                        wait=True,
                    ),
                    bps.sleep(glbl['shutter_sleep']),
                ),
                None,
            )
        elif msg.command == "open_run" and "dark_frame" not in msg.kwargs:
            return (
                bpp.pchain(
                    bpp.single_gen(msg),
                    bps.abs_set(
                        xpd_configuration.get("shutter"),
                        XPD_SHUTTER_CONF["open"],
                        wait=True,
                    ), bps.sleep(glbl['shutter_sleep'])),
                None,
            )
        else:
            # do nothing if (not need_dark)
            return None, None
Ejemplo n.º 3
0
def set_beamdump_suspender(xrun,
                           suspend_thres=None,
                           resume_thres=None,
                           wait_time=None,
                           clear=True):
    """helper function to set suspender based on ring_current

    Parameters
    ----------
    xrun : instance of RunEngine
        the run engine instance suspender will be installed
    suspend_thres : float, optional
        suspend if ring current value falls below this threshold. ring
        current value is read out from ring current signal when
        set_beamdump_suspender function is executed. default is the
        larger value between 50 mA or 50% of ring current
    resume_thres : float, optional
        resume if ring current value falls below this threshold. ring
        current value is read out from ring current signal when
        set_beamdump_suspender function is executed. default is the
        larger value among 50 mA or 80% of current ring current
    wait_time : float, optional
        wait time in seconds after the resume condition is met. default
        is 1200s (20 mins)
    clear : bool, optional
        option on whether to clear all the existing suspender(s).
        default is True (only newly added suspender will be applied)
    """
    signal = xpd_configuration.get("ring_current", None)
    if signal is None:
        # edge case, attribute is accidentally removed
        raise RuntimeError("no ring current signal is found in "
                           "current configuration, please reach out to "
                           "local contact for more help.")
    signal_val = signal.get()
    default_suspend_thres = 50
    default_resume_thres = 50
    if suspend_thres is None:
        suspend_thres = max(default_suspend_thres, 0.5 * signal_val)
    if resume_thres is None:
        resume_thres = max(default_resume_thres, 0.8 * signal_val)
    if wait_time is None:
        wait_time = 1200
    if suspend_thres <= 50:
        warnings.warn(
            "suspender set when beam current is low.\n"
            "For the best operation, run:\n"
            ">>> {}\n"
            "when beam current is at its full value."
            "To interrogate suspenders have"
            " been installed, please run :\n"
            ">>> {}\n".format("set_suspender(xrun)", "xrun.suspenders"),
            UserWarning,
        )
    sus = SuspendFloor(signal,
                       suspend_thres,
                       resume_thresh=resume_thres,
                       sleep=wait_time)
    if clear:
        xrun.clear_suspenders()
    xrun.install_suspender(sus)
    print("INFO: suspender on signal {}, with suspend threshold {} and "
          "resume threshold={}, wait time ={}s has been installed.\n".format(
              signal.name, suspend_thres, resume_thres, wait_time))
Ejemplo n.º 4
0
import bluesky.plans as bp
import bluesky.plan_stubs as bps
import bluesky.preprocessors as bpp
from bluesky import RunEngine
from bluesky.suspenders import SuspendFloor
from bluesky.utils import normalize_subs_input, single_gen, Msg
from bluesky.callbacks.broker import verify_files_saved
from bluesky.preprocessors import pchain

from xpdacq.glbl import glbl
from xpdacq.tools import xpdAcqException
from xpdacq.beamtime import ScanPlan, _summarize
from xpdacq.xpdacq_conf import xpd_configuration, XPDACQ_MD_VERSION
from xpdconf.conf import XPD_SHUTTER_CONF

XPD_shutter = xpd_configuration.get("shutter")


def _update_dark_dict_list(name, doc):
    """ generate dark frame reference

    This function should be subscribed to 'stop' documents from dark
    frame runs.
    """
    # always grab from glbl state
    dark_dict_list = list(glbl["_dark_dict_list"])
    # obtain light count time that is already set to area_det
    area_det = xpd_configuration["area_det"]
    acq_time = area_det.cam.acquire_time.get()
    num_frame = area_det.images_per_set.get()
    light_cnt_time = acq_time * num_frame