Skip to content

Instantly share code, notes, and snippets.

@chiahaoliu
Last active June 10, 2016 16:47
Show Gist options
  • Save chiahaoliu/2dfdd274085a155573436bb2749bdcf8 to your computer and use it in GitHub Desktop.
Save chiahaoliu/2dfdd274085a155573436bb2749bdcf8 to your computer and use it in GitHub Desktop.
  1. Maybe it is a good idea to make ScanPlan belongs to Beamtme like what we have for current xpdAcq There are two advantages to this approach:

    • we don't have to keep updating registered plan, we can simply maintain ct, Tramp and tseries

    • Unify plan input to RE and still make bluesky plan possible

      class Customized_RE(RunEngine)
      ....
      if isinstance(plan, ScanPlan):
          plan.factory
      elif isinstance(plan, Plan):
          # bluesky Plan base
          pass
      
  2. For complete take_dark functionality, we need an extra logic of examing exposure to current take_dark. Current dark logic includes two parts:

    • freshness of dark frame. --> dark frame should be taken within certain window
    • applicability of this dark frame --> dark frame should have the same exposure time as light frame.
# TODO: maybe stash a list of reference?
def _stash_uid(name, doc):
    # intercept the uid of a dark frame and stash it
    if name == 'start':
        glbl.last_dark_frame_uid = doc['uid']


def take_dark():
    "a plan for taking a single dark frame"
    print('closing shutter...')
    yield from bp.abs_set(glbl.shutter, 0)
    yield from bp.sleep(2)
    print('taking dark frame....')
    # FIXME : how can I get exposure time from generator?
    c = bp.count([glbl.pe1c], md={'dark_frame': True})
    yield from bp.subs_wrapper(c, _stash_uid)
    print('opening shutter...')
    yield from bp.abs_set(glbl.shutter, 1)
    yield from bp.sleep(2)


def periodic_dark(plan, period=3000*60, insert_position='open_run'):
    """
    a plan wrapper that takes a plan and inserts `take_dark`

    The `take_dark` plan is inserted on the fly before the beginning of
    any new run after a period of time `period` (in seconds) has passed.
    """
    last_dark_time = None
    need_dark = True

    def insert_take_dark(msg):
        now = time.time()
        nonlocal last_dark_time
        nonlocal need_dark
        if ((not need_dark) and
                (last_dark_time is None or (now - last_dark_time) > period)):
            need_dark = True
        if need_dark and msg.command == insert_position:
            # We are about to start a new 'run' (e.g., a count or a scan).
            # Insert a dark frame run first.
            last_dark_time = time.time()
            need_dark = False
            return bp.pchain(take_dark(), bp.single_gen(msg)), None
        else:
            return None, None

    return (yield from bp.plan_mutator(plan, insert_take_dark))


def _inject_last_dark_frame_uid(msg):
    if msg.command == 'open_run' and msg.kwargs.get('dark_frame') != True:
        msg.kwargs['dark_frame'] = glbl.last_dark_frame_uid
    return msg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment