Exemple #1
0
    def insert_take_dark(msg):
        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),
                    open_shutter_stub(),
                ),
                None,
            )
        elif msg.command == "open_run" and "dark_frame" not in msg.kwargs:
            return (
                bpp.pchain(bpp.single_gen(msg), open_shutter_stub()),
                None,
            )
        else:
            # do nothing if (not need_dark)
            return None, None
def test_monitors(hw):
    det = hw.det
    rand = hw.rand
    rand2 = hw.rand2

    # no-op
    D = SupplementalData()
    original = list(count([det]))
    processed = list(D(count([det])))
    assert len(processed) == len(original)

    # one monitor
    D.monitors.append(rand)
    original = list(count([det]))
    processed = list(D(count([det])))
    assert len(processed) == 2 + len(original)

    # two monitors
    D.monitors.append(rand2)
    processed = list(D(count([det])))
    assert len(processed) == 4 + len(original)

    # two monitors applied a plan with consecutive runs
    original = list(list(count([det])) + list(count([det])))
    processed = list(D(pchain(count([det]), count([det]))))
    assert len(processed) == 8 + len(original)
def test_monitors(hw):
    det = hw.det
    rand = hw.rand
    rand2 = hw.rand2

    # no-op
    D = SupplementalData()
    original = list(count([det]))
    processed = list(D(count([det])))
    assert len(processed) == len(original)

    # one monitor
    D.monitors.append(rand)
    original = list(count([det]))
    processed = list(D(count([det])))
    assert len(processed) == 2 + len(original)

    # two monitors
    D.monitors.append(rand2)
    processed = list(D(count([det])))
    assert len(processed) == 4 + len(original)

    # two monitors applied a plan with consecutive runs
    original = list(list(count([det])) + list(count([det])))
    processed = list(D(pchain(count([det]), count([det]))))
    assert len(processed) == 8 + len(original)
Exemple #4
0
    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (pchain(echo_plan(num=2, command=cmd2),
                           single_message_gen(msg)), bad_tail())
        return None, None
Exemple #5
0
    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (pchain(echo_plan(num=2, command=cmd2),
                           single_message_gen(msg)),
                    bad_tail())
        return None, None
Exemple #6
0
    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (pchain(echo_plan(num=pre_count, command=pre_cmd),
                           single_message_gen(msg)),
                    echo_plan(num=post_count, command=post_cmd))
        return None, None
Exemple #7
0
    def test_mutator(msg):
        nonlocal _mut_active
        if _mut_active:
            _mut_active = False

            return (pchain(echo_plan(num=pre_count, command=pre_cmd),
                           single_message_gen(msg)),
                    echo_plan(num=post_count, command=post_cmd))
        return None, None
def test_get_events_filtering_field(db, RE, hw):
    RE.subscribe(db.insert)
    uid, = RE(count([hw.det], num=7))
    h = db[uid]
    assert len(list(db.get_events(h, fields=['det']))) == 7
    assert len(list(h.documents(fields=['det']))) == 7 + 3

    uids = RE(pchain(count([hw.det1], num=7), count([hw.det2], num=3)))
    headers = db[uids]

    assert len(list(db.get_events(headers, fields=['det1']))) == 7
    assert len(list(db.get_events(headers, fields=['det2']))) == 3
Exemple #9
0
def fast_shutter_wrapper(plan):
    update_metadata()

    if USE_FAST_SHUTTER:
        plan = bpp.pchain(
            bps.abs_set(fast_shutter.output,
                        FastShutter.OPEN_SHUTTER,
                        settle_time=FastShutter.SETTLE_TIME), plan)
        plan = bpp.finalize_wrapper(
            plan,
            bps.abs_set(fast_shutter.output,
                        FastShutter.CLOSE_SHUTTER,
                        settle_time=FastShutter.SETTLE_TIME))

    return (yield from plan)
def test_baseline(hw):
    # one baseline detector
    D = SupplementalData(baseline=[hw.det2])
    original = list(count([hw.det]))
    processed = list(D(count([hw.det])))
    # should add 2X (trigger, wait, create, read, save)
    assert len(processed) == 10 + len(original)

    # two baseline detectors
    D.baseline.append(hw.det3)
    processed = list(D(count([hw.det])))
    # should add 2X (trigger, triger, wait, create, read, read, save)
    assert len(processed) == 14 + len(original)

    # two baseline detectors applied to a plan with two consecutive runs
    original = list(list(count([hw.det])) + list(count([hw.det])))
    processed = list(D(pchain(count([hw.det]), count([hw.det]))))
    assert len(processed) == 28 + len(original)
def test_baseline(hw):
    # one baseline detector
    D = SupplementalData(baseline=[hw.det2])
    original = list(count([hw.det]))
    processed = list(D(count([hw.det])))
    # should add 2X (trigger, wait, create, read, save)
    assert len(processed) == 10 + len(original)

    # two baseline detectors
    D.baseline.append(hw.det3)
    processed = list(D(count([hw.det])))
    # should add 2X (trigger, triger, wait, create, read, read, save)
    assert len(processed) == 14 + len(original)

    # two baseline detectors applied to a plan with two consecutive runs
    original = list(list(count([hw.det])) + list(count([hw.det])))
    processed = list(D(pchain(count([hw.det]), count([hw.det]))))
    assert len(processed) == 28 + len(original)
def test_flyers(hw):
    # one flyer
    D = SupplementalData(flyers=[hw.flyer1])
    original = list(count([hw.det]))
    processed = list(D(count([hw.det])))
    # should add kickoff, wait, complete, wait, collect
    assert len(processed) == 5 + len(original)

    # two flyers
    D.flyers.append(hw.flyer2)
    processed = list(D(count([hw.det])))
    # should add 2 * (kickoff, complete, collect) + 2 * (wait)
    assert len(processed) == 8 + len(original)

    # two flyers applied to a plan with two consecutive runs
    original = list(list(count([hw.det])) + list(count([hw.det])))
    processed = list(D(pchain(count([hw.det]), count([hw.det]))))
    assert len(processed) == 16 + len(original)
def test_flyers(hw):
    # one flyer
    D = SupplementalData(flyers=[hw.flyer1])
    original = list(count([hw.det]))
    processed = list(D(count([hw.det])))
    # should add kickoff, wait, complete, wait, collect
    assert len(processed) == 5 + len(original)

    # two flyers
    D.flyers.append(hw.flyer2)
    processed = list(D(count([hw.det])))
    # should add 2 * (kickoff, complete, collect) + 2 * (wait)
    assert len(processed) == 8 + len(original)

    # two flyers applied to a plan with two consecutive runs
    original = list(list(count([hw.det])) + list(count([hw.det])))
    processed = list(D(pchain(count([hw.det]), count([hw.det]))))
    assert len(processed) == 16 + len(original)
Exemple #14
0
def test_uid_list_multiple_headers(db, RE, hw):
    RE.subscribe(db.insert)
    uids = RE(pchain(count([hw.det]), count([hw.det])))
    headers = db[uids]
    assert uids == tuple([h['start']['uid'] for h in headers])
Exemple #15
0
 pchain(
     bp.scan([hw.noisy_det], hw.motor, 0, 10, 10),
     bp.grid_scan([hw.ab_det],
                  hw.motor,
                  0,
                  10,
                  10,
                  hw.motor2,
                  0,
                  10,
                  10,
                  True,
                  per_step=one_nd_step),
     bp.spiral([hw.ab_det],
               hw.motor,
               hw.motor2,
               0,
               0,
               10,
               10,
               1,
               10,
               per_step=one_nd_step),
     bp.grid_scan([hw.direct_img],
                  hw.motor,
                  0,
                  10,
                  10,
                  hw.motor2,
                  0,
                  10,
                  10,
                  True,
                  per_step=one_nd_step),
 ))
Exemple #16
0
def xpdacq_composer(beamtime: Beamtime,
                    sample: typing.Union[int, dict, typing.List[int]],
                    plan: typing.Union[int, Generator, typing.List[int],
                                       typing.Generator],
                    *,
                    robot: bool = False,
                    shutter_control: typing.Tuple[Device, typing.Any] = None,
                    dark_strategy: typing.Callable = None,
                    auto_load_calib: bool = False) -> typing.Generator:
    """Create a list of plans for an xpd experiment. Used in `~xpdacq.xpdacq.CumstomeizedRunEngine.__call__`.

    Parameters
    ----------
    beamtime :
        The beamtime object.

    sample :
        If a beamtime object is linked, an integer will be interpreted as the index appears in the ``bt.list()``
        method, corresponding metadata will be passed. A customized dict can also be passed as the sample
        metadata.

    plan :
        Scan plan. If a beamtime object is linked, an integer will be interpreted as the index appears in the
        ``bt.list()`` method, corresponding scan plan will be A generator or that yields ``Msg`` objects (or an
        iterable that returns such a generator) can also be passed.

    robot :
        If True, the plan is meant to be using robot.

    shutter_control :
        A tuple of the shutter device and its close state. The shutter will be closed after the whole scan.
        If None, shutter won't be controlled and no dark will be taken.

    dark_strategy :
        The strategy how to take the dark frame.

    auto_load_calib :
        If True, the calibration meta-data will be injected into the run. Else, do nothing.

    Returns
    -------
    grand_plan :
        The grand plan to be run by the RunEngine.
    """
    # check wavelength
    warn_wavelength(beamtime)
    # noramlize the sample and plan to two lists with the same length
    lst_sample, lst_plan = _normalize_sample_plan(sample, plan)
    # Turn ints into actual sample dictionary
    lst_metadata = [translate_to_sample(beamtime, s) for s in lst_sample]
    # Turn ints into bluesky generators
    lst_bp_plan = [translate_to_plan(beamtime, p) for p in lst_plan]
    # Make the complete plan by chaining the chained plans
    if robot:
        lst_bp_plan = gen_robot_plans(beamtime, lst_metadata, lst_bp_plan)
    # shutter control and dark
    if shutter_control:
        shutter, close_state = shutter_control
        # Alter the plan to incorporate dark frames.
        if dark_strategy:
            lst_bp_plan = [dark_strategy(p) for p in lst_bp_plan]
            lst_bp_plan = [
                bpp.msg_mutator(p, _inject_qualified_dark_frame_uid)
                for p in lst_bp_plan
            ]
        # force to close shutter after scan
        lst_bp_plan = [
            close_shutter_at_last(p, shutter, close_state) for p in lst_bp_plan
        ]
    # Load calibration file
    if auto_load_calib:
        lst_bp_plan = [
            bpp.msg_mutator(p, _inject_calibration_md) for p in lst_bp_plan
        ]
    # Insert xpdacq md version
    lst_bp_plan = [
        bpp.msg_mutator(p, _inject_xpdacq_md_version) for p in lst_bp_plan
    ]
    # Insert analysis stage tag
    lst_bp_plan = [
        bpp.msg_mutator(p, _inject_analysis_stage) for p in lst_bp_plan
    ]
    # Insert filter metadata
    lst_bp_plan = [
        bpp.msg_mutator(p, _inject_filter_positions) for p in lst_bp_plan
    ]
    # Inject the sample metadata
    lst_bp_plan = [
        inject_metadata(p, s) for p, s in zip(lst_bp_plan, lst_metadata)
    ]
    return pchain(*lst_bp_plan)
Exemple #17
0
def test_get_events_multiple_headers(db, RE, hw):
    RE.subscribe(db.insert)
    headers = db[RE(pchain(count([hw.det]), count([hw.det])))]
    assert len(list(db.get_events(headers))) == 2
    def _per_step(detectors, step, pos_cache, take_reading=my_take_reading):
        yield from bps.sleep(delay)
        sts = yield from bps.one_nd_step(detectors,
                                         step,
                                         pos_cache,
                                         take_reading=take_reading)
        return sts

    return _per_step


# Mandy's samples
per_step7 = gen_per_step(60 * 5)
plan42 = pchain(
    configure_area_det(pe1c, 60 * 5, 0.2),
    bp.list_scan([pe1c], cs700, [300, 433, 465], per_step=per_step7),
    configure_area_det(pe1c, 60, 0.2),
    bp.grid_scan([pe1c], cs700, 465, 300, 34, per_step=my_per_step))
plan43 = pchain(configure_area_det(pe1c, 60 * 5, 0.2),
                bp.list_scan([pe1c], cs700, [300, 433], per_step=per_step7),
                bps.mv(cs700, 300))
plan44 = pchain(
    configure_area_det(pe1c, 60 * 5, 0.2),
    bp.list_scan([pe1c], cs700, [300], per_step=my_per_step),
    configure_area_det(pe1c, 60, 0.2),
    bp.grid_scan([pe1c], cs700, 300, 455, 32, per_step=my_per_step),
    configure_area_det(pe1c, 60 * 5, 0.2),
    bp.list_scan([pe1c], cs700, [455], per_step=per_step7),
    configure_area_det(pe1c, 60, 0.2),
    bp.grid_scan([pe1c], cs700, 455, 300, 32, per_step=my_per_step),
)
Exemple #19
0
    def __call__(self,
                 sample,
                 plan,
                 subs=None,
                 *,
                 verify_write=False,
                 dark_strategy=periodic_dark,
                 robot=False,
                 **metadata_kw):
        """
        Execute a plan

        Any keyword arguments other than those listed below will
        be interpreted as metadata and recorded with the run.

        Parameters
        ----------
        sample : int or dict-like or list of int or dict-like
            Sample metadata. If a beamtime object is linked,
            an integer will be interpreted as the index appears in the
            ``bt.list()`` method, corresponding metadata will be passed.
            A customized dict can also be passed as the sample
            metadata.
        plan : int or generator or list of int or generator
            Scan plan. If a beamtime object is linked, an integer
            will be interpreted as the index appears in the
            ``bt.list()`` method, corresponding scan plan will be
            A generator or that yields ``Msg`` objects (or an iterable
            that returns such a generator) can also be passed.
        subs: callable, list, or dict, optional
            Temporary subscriptions (a.k.a. callbacks) to be used on
            this run. Default to None. For convenience, any of the
            following are accepted:

            * a callable, which will be subscribed to 'all'
            * a list of callables, which again will be subscribed to 'all'
            * a dictionary, mapping specific subscriptions to callables or
              lists of callables; valid keys are {'all', 'start', 'stop',
              'event', 'descriptor'}

        verify_write: bool, optional
            Double check if the data have been written into database.
            In general data is written in a lossless fashion at the
            NSLS-II. Therefore, False by default.
        dark_strategy: callable, optional.
            Protocol of taking dark frame during experiment. Default
            to the logic of matching dark frame and light frame with
            the sample exposure time and frame rate. Details can be
            found at ``http://xpdacq.github.io/xpdAcq/usb_Running.html#automated-dark-collection``
        robot: bool, optional
            If true run the scan as a robot scan, defaults to False
        metadata_kw:
            Extra keyword arguments for specifying metadata in the
            run time. If the extra metdata has the same key as the
            ``sample``, ``ValueError`` will be raised.

        Returns
        -------
        uids : list
            list of uids (i.e. RunStart Document uids) of run(s)
        """
        if self.md.get("robot", None) is not None:
            raise RuntimeError("Robot must be specified at call time, not in"
                               "global metadata")
        if robot:
            metadata_kw.update(robot=True)
        # 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.

        # Turn everything into lists
        sample, plan = self._normalize_sample_plan(sample, plan)
        # Turn ints into actual samples
        sample = self.translate_to_sample(sample)
        if robot:
            print("This is the current experimental plan:")
            print("Sample Name: Sample Position")
            for s, p in [
                (k, [o[1] for o in v])
                    for k, v in groupby(zip(sample, plan), key=lambda x: x[0])
            ]:
                print(
                    s["sample_name"],
                    ":",
                    self._beamtime.robot_info[s["sa_uid"]],
                )
                for pp in p:
                    # Check if this is a registered scanplan
                    if isinstance(pp, int):
                        print(
                            indent(
                                "{}".format(
                                    list(
                                        self.beamtime.scanplans.values())[pp]),
                                "\t",
                            ))
                    else:
                        print("This scan is not a registered scanplan so no "
                              "summary")
            ip = input("Is this ok? [y]/n")
            if ip.lower() == "n":
                return
        # Turn ints into generators
        plan = self.translate_to_plan(plan, sample)

        # Collect the plans by contiguous samples and chain them
        sample, plan = zip(
            *[(k, pchain(*[o[1] for o in v]))
              for k, v in groupby(zip(sample, plan), key=lambda x: x[0])])

        # Make the complete plan by chaining the chained plans
        total_plan = []
        for s, p in zip(sample, plan):
            if robot:
                # If robot scan inject the needed md into the sample
                s.update(self._beamtime.robot_info[s["sa_uid"]])
                total_plan.append(robot_wrapper(p, s))
            else:
                total_plan.append(p)
        plan = pchain(*total_plan)

        _subs = normalize_subs_input(subs)
        if verify_write:
            _subs.update({"stop": verify_files_saved})

        if self._beamtime and self._beamtime.get("bt_wavelength") is None:
            print("WARNING: there is no wavelength information in current"
                  "beamtime object, scan will keep going....")

        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 = bpp.msg_mutator(plan, _inject_qualified_dark_frame_uid)
            # force to close shutter after scan
            plan = bpp.finalize_wrapper(
                plan,
                bps.abs_set(
                    xpd_configuration["shutter"],
                    XPD_SHUTTER_CONF["close"],
                    wait=True,
                ),
            )

        # Load calibration file
        if glbl["auto_load_calib"]:
            plan = bpp.msg_mutator(plan, _inject_calibration_md)
        # Insert xpdacq md version
        plan = bpp.msg_mutator(plan, _inject_xpdacq_md_version)
        # Insert analysis stage tag
        plan = bpp.msg_mutator(plan, _inject_analysis_stage)
        # Insert filter metadata
        plan = bpp.msg_mutator(plan, _inject_filter_positions)

        # Execute
        return super().__call__(plan, subs, **metadata_kw)
Exemple #20
0
 pchain(
     bp.scan([hw.noisy_det], hw.motor, 0, 10, 10),
     bp.grid_scan(
         [hw.ab_det],
         hw.motor,
         0,
         5,
         5,
         hw.motor2,
         0,
         5,
         5,
         True,
         per_step=one_nd_step,
     ),
     bp.grid_scan(
         [hw.ab_det],
         hw.motor,
         0,
         10,
         10,
         hw.motor2,
         0,
         10,
         10,
         True,
         per_step=one_nd_step,
     ),
     bp.spiral(
         [hw.ab_det],
         hw.motor,
         hw.motor2,
         0,
         0,
         10,
         10,
         1,
         10,
         per_step=one_nd_step,
     ),
     bp.grid_scan(
         [rand_img],
         hw.motor,
         0,
         10,
         10,
         hw.motor2,
         0,
         10,
         10,
         True,
         per_step=one_nd_step,
     ),
 )