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)
def fly_scan(experiment, cfg_tomo):
    """
    Collect projections with fly motion
    """
    det = experiment.det
    psofly = experiment.psofly

    yield from bps.mv(det.hdf1.nd_array_port, 'PG1')
    yield from bps.mv(det.tiff1.nd_array_port, 'PG1')

    # we are assuming that the global psofly is available
    yield from bps.mv(
        psofly.start,
        cfg_tomo['omega_start'],
        psofly.end,
        cfg_tomo['omega_end'],
        psofly.scan_delta,
        abs(cfg_tomo['omega_step']),
        psofly.slew_speed,
        cfg_tomo['slew_speed'],
    )
    # taxi
    yield from bps.mv(psofly.taxi, "Taxi")
    yield from bps.mv(
        det.cam.num_images,
        cfg_tomo['n_projections'],
        det.cam.trigger_mode,
        "Overlapped",
    )
    # start the fly scan
    yield from bps.trigger(det, group='fly')
    yield from bps.abs_set(psofly.fly, "Fly", group='fly')
    yield from bps.wait(group='fly')
    def _plan(self):
        yield from bps.open_run()

        # stash numcapture and shutter_enabled
        num_capture = yield from bps.rd(self.device.hdf5.num_capture)
        shutter_enabled = yield from bps.rd(self.device.dg1.shutter_enabled)

        # set to 1 temporarily
        self.device.hdf5.num_capture.put(1)

        # Restage to ensure that dark frames goes into a separate file.
        yield from bps.stage(self.device)
        yield from bps.mv(self.device.dg1.shutter_enabled, 2)
        # The `group` parameter passed to trigger MUST start with
        # bluesky-darkframes-trigger.
        yield from bps.trigger_and_read([self.device], name='dark')
        # Restage.
        yield from bps.unstage(self.device)
        # restore numcapture and shutter_enabled
        yield from bps.mv(self.device.hdf5.num_capture, num_capture)
        yield from bps.mv(self.device.dg1.shutter_enabled, shutter_enabled)

        # Dark frames finished, moving on to data

        yield from bps.stage(self.device)
        status = yield from bps.trigger(self.device, group='primary-trigger')
        while not status.done:
            yield from bps.trigger_and_read(self.async_poll_devices,
                                            name='labview')
            yield from bps.sleep(1)
        yield from bps.create('primary')
        yield from bps.read(self.device)
        yield from bps.save()
        yield from bps.unstage(self.device)
    def fly_body():
        yield from bps.trigger_and_read([E_centers], name='energy_bins')

        for y in range(num_scans):
            # go to start of row
            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}')
            # 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(.1)
            # read and save the struck
            yield from bps.create(name='primary')
            yield from bps.read(sclr)
            yield from bps.save()
Beispiel #5
0
def dark_plan():
    yield from bps.mv(shutter, 'closed')
    yield from bps.unstage(det)
    yield from bps.stage(det)
    yield from bps.trigger(det, group='darkframe-trigger')
    yield from bps.wait('darkframe-trigger')
    snapshot = bluesky_darkframes.SnapshotDevice(det)
    yield from bps.unstage(det)
    yield from bps.stage(det)
    yield from bps.mv(shutter, 'open')
    return snapshot
        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.velocity, 1)
            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, flyspeed)
            # 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()
Beispiel #7
0
    def per_step(detectors, step, pos_cache):
        """
        Override default per_step to start the sequencer on each row.

        The first move is not a fly scan move: it moves us into the start
        position. The second move is, as is the fourth, sixth...
        """
        nonlocal is_seq_step
        if is_seq_step:
            yield from trigger(seq)
            is_seq_step = False
        else:
            is_seq_step = True
        yield from one_nd_step(detectors, step, pos_cache)
        def fly_row():
            # go to start of row
            yield from bps.mv(xy_fly_stage.x, xstart, xy_fly_stage.y,
                              ystart + y * ystep_size)

            # set the fly speed
            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(.1)
            # read and save the struck
            yield from bps.create(name='primary')
            yield from bps.read(sclr)
            # and maybe the xspress3
            if xspress3 is not None:
                yield from bps.read(xspress3)
            yield from bps.save()
def dark_plan(detector):
    # Restage to ensure that dark frames goes into a separate file.
    yield from bps.unstage(detector)
    yield from bps.stage(detector)
    yield from bps.mv(shutter, 'closed')
    # The `group` parameter passed to trigger MUST start with
    # bluesky-darkframes-trigger.
    yield from bps.trigger(detector, group='bluesky-darkframes-trigger')
    yield from bps.wait('bluesky-darkframes-trigger')
    snapshot = bluesky_darkframes.SnapshotDevice(detector)
    yield from bps.mv(shutter, 'open')
    # Restage.
    yield from bps.unstage(detector)
    yield from bps.stage(detector)
    return snapshot
def dark_plan(cam, dark_frame_cache, obsolete_secs, shutter):
    if (dark_frame_cache.just_started or  # first run after instantiation
        (dark_frame_cache.last_collected is not None and
         time.monotonic() - dark_frame_cache.last_collected > obsolete_secs)):
        tmp = yield from bps.read(shutter.status)
        init_shutter_state = tmp[shutter.status.name]['value'] if tmp is not None else None
        yield from bps.mv(shutter, 'Close')
        yield from bps.trigger(cam, group='cam')
        yield from bps.wait('cam')
        yield from bps.mv(shutter, init_shutter_state)

        teleport(cam, dark_frame_cache)
        dark_frame_cache.just_started = False
        dark_frame_cache.update_done = True
    else:
        dark_frame_cache.update_done = False
def dark_plan(detector, dark_frame_cache, max_age, shutter):
    if (dark_frame_cache.just_started or  # first run after instantiation
        (dark_frame_cache.last_collected is not None and
         time.monotonic() - dark_frame_cache.last_collected > max_age)):
        init_shutter_state = shutter.get()
        yield from bps.mv(shutter, 0)
        yield from bps.trigger(detector, group='cam')
        yield from bps.wait('cam')
        yield from bps.mv(shutter, init_shutter_state)


        teleport(detector, dark_frame_cache)
        dark_frame_cache.just_started = False
        dark_frame_cache.update_done = True
    else:
        dark_frame_cache.update_done = False
Beispiel #12
0
 def dark_plan(self, detector):
     """The plan to take dark."""
     # Restage to ensure that dark frames goes into a separate file.
     yield from bps.unstage(detector)
     yield from bps.stage(detector)
     yield from bps.mv(self.shutter, self.shutter_close)
     # The `group` parameter passed to trigger MUST start with
     # bluesky-darkframes-trigger.
     yield from bps.trigger(detector, group='bluesky-darkframes-trigger')
     yield from bps.wait('bluesky-darkframes-trigger')
     snapshot = SnapshotDevice(detector)
     yield from bps.mv(self.shutter, self.shutter_open)
     # Restage.
     yield from bps.unstage(detector)
     yield from bps.stage(detector)
     return snapshot
Beispiel #13
0
def no_run_trigger_and_wait(objects):
    """
    count objects (presume detectors) but do not create a bluesky run

    Does most of bps.trigger_and_read() but does not create&save a run.
    Caller must call `.read()` on each object once this returns.

    The primary use case is to count detectors (on a scaler card)
    when measuring sample transmission.
    """
    if not isinstance(objects, (tuple, set, list)):
        objects = [objects]
    group = bps._short_uid("trigger_and_wait_no_run")
    for obj in objects:
        yield from bps.trigger(obj, group=group)
    yield from bps.wait(group=group)
        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
            # 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
            yield from bps.save()
Beispiel #15
0
 def inner_trigger_and_read():
     nonlocal group
     if group is None:
         group = short_uid('trigger')
     no_wait = True
     for obj in devices:
         if hasattr(obj, 'trigger'):
             no_wait = False
             yield from bps.trigger(obj, group=group)
     # Skip 'wait' if none of the devices implemented a trigger method.
     if not no_wait:
         yield from bps.wait(group=group)
     yield from bps.create(name)
     ret = {}  # collect and return readings to give plan access to them
     for obj in devices:
         reading = (yield from bps.read(obj))
         if reading is not None:
             ret.update(reading)
     yield from bps.save()
     return ret
Beispiel #16
0
    def fly_each_step(detectors, motor, step, firststep):
        "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook"
        # First, let 'scan' handle the normal y step, including a checkpoint.
        yield from one_1d_step(detectors, motor, step)

        # Now do the x steps.
        v = (xstop - xstart) / (xnum-1) / dwell  # compute "stage speed"
        yield from abs_set(xmotor, xstart - delta, wait=True) # ready to move
        yield from abs_set(xmotor.velocity, v, wait=True)  # set the "stage speed"

        yield from abs_set(xs.hdf5.num_capture, xnum, wait=True)
        yield from abs_set(xs.settings.num_images, xnum, wait=True)
        yield from abs_set(ion.nuse_all,xnum)
        # arm the Zebra (start caching x positions)


        yield from kickoff(flying_zebra, xstart=xstart, xstop=xstop, xnum=xnum, dwell=dwell, wait=True)
        yield from abs_set(ion.erase_start, 1) # 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 bps.trigger(xs, group='row')
        #if firststep == True:
        #    ttime.sleep(0.)
        yield from bps.sleep(1.5)
        yield from abs_set(xmotor, xstop+1*delta, group='row')  # move in x
        yield from bps.wait(group='row')
        # yield from abs_set(xs.settings.acquire, 0)  # stop acquiring images
        yield from abs_set(ion.stop_all, 1)  # stop acquiring scaler
        yield from complete(flying_zebra)  # tell the Zebra we are done
        yield from collect(flying_zebra)  # extract data from Zebra
        if ('e_tomo' in xmotor.name):
            v_return = 4
            v_max = xmotor.velocity.high_limit
            if (v_return > v_max):
                xmotor.velocity.set(v_max)
            else:
                xmotor.velocity.set(v_return)
        else:
            yield from abs_set(xmotor.velocity, 1.0, wait=True)  # set the "stage speed"
def dark_plan(detector):
    # stash numcapture and shutter_enabled
    num_capture = yield from bps.rd(detector.hdf5.num_capture)
    shutter_enabled = yield from bps.rd(detector.dg1.shutter_enabled)

    # set to 1 temporarily
    detector.hdf5.num_capture.put(1)

    # Restage to ensure that dark frames goes into a separate file.
    yield from bps.unstage(detector)
    yield from bps.stage(detector)
    yield from bps.mv(detector.dg1.shutter_enabled, 2)
    # The `group` parameter passed to trigger MUST start with
    # bluesky-darkframes-trigger.
    yield from bps.trigger(detector, group='bluesky-darkframes-trigger')
    yield from bps.wait('bluesky-darkframes-trigger')
    snapshot = bluesky_darkframes.SnapshotDevice(detector)
    # Restage.
    yield from bps.unstage(detector)
    # restore numcapture and shutter_enabled
    yield from bps.mv(detector.hdf5.num_capture, num_capture)
    yield from bps.mv(detector.dg1.shutter_enabled, shutter_enabled)
    return snapshot
Beispiel #18
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)

            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])

        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)

        # 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
        yield from abs_set(ion.nuse_all, 2 * xnum)

        # arm the Zebra (start caching x positions)
        # @timer_wrapper
        def zebra_kickoff():
            if row_start < row_stop:
                yield from kickoff(flying_zebra,
                                   xstart=xstart,
                                   xstop=xstop,
                                   xnum=xnum,
                                   dwell=dwell,
                                   wait=True)
            else:
                yield from kickoff(flying_zebra,
                                   xstart=xstop,
                                   xstop=xstart,
                                   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...
        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('/home/xf05id1/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
        yield from abs_set(ion.stop_all, 1)  # stop acquiring scaler

        # set speed back
        reset_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')

        # @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')
    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 fly_each_step(motor, step):
        "See http://nsls-ii.github.io/bluesky/plans.html#the-per-step-hook"
        # First, let 'scan' handle the normal y step, including a checkpoint.
        yield from one_1d_step([], motor, step)
        # yield from bps.sleep(1.0)  # wait for the "x motor" to move

        # Now do the x steps.
        v = ((xstop - xstart) / (xnum - 1)) / dwell  # compute "stage speed"
        yield from abs_set(xmotor, xstart - delta, wait=True)  # ready to move

        # 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()
        i = 0
        while (np.abs(x_set - x_dial) > 0.0001):
            if (i == 0):
                print('Waiting for motor to reach starting position...',
                      end='')
            i = i + 1
            yield from abs_set(xmotor, xstart - delta, wait=True)
            yield from bps.sleep(1.0)
            x_dial = xmotor.user_readback.get()
        if (i != 0):
            print('done')

        yield from abs_set(xmotor.velocity, v,
                           wait=True)  # set the "stage speed"

        # 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)

        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)

        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)
        yield from kickoff(flying_zebra,
                           xstart=xstart,
                           xstop=xstop,
                           xnum=xnum,
                           dwell=dwell,
                           wait=True)

        # 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')

        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')

        # yield from abs_set(xs.settings.acquire, 0)  # stop acquiring images

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

        yield from complete(flying_zebra)  # tell the Zebra we are done
        yield from collect(flying_zebra)  # extract data from Zebra
        # TODO what?
        if ('e_tomo' in xmotor.name):
            v_return = min(4, xmotor.velocity.high_limit)
            yield from bps.mov(xmotor.velocity, v_return)
        else:
            # set the "stage speed"
            yield from bps.mov(xmotor.velocity, 1.0)
            # TODO wat
            # set the "stage speed" twice just in case
            yield from abs_set(xmotor.velocity, 1.0, wait=True)
Beispiel #21
0
 def mona_core(detector_list, acquire, num=1):
     yield from bps.trigger(area_det, wait=False)
     yield from bp.scan(detector_list, motor, start, finish, num=num)
Beispiel #22
0
 def mona_core(detectors, acquire, num=1):
     yield from bps.trigger(adsimdet, wait=False)
     yield from bp.count(detectors, num=num)
Beispiel #23
0
 def add_daq_trigger(msg):
     if msg.obj is not daq:
         yield from bps.trigger(daq, group=msg.kwargs['group'])
     return (yield msg)
Beispiel #24
0
 def take_image(self):
     yield from bps.stage(self)
     yield from bps.trigger(self, wait=True)
     yield from bps.unstage(self)
Beispiel #25
0
    def _scan_():
        count_time = count_time_base

        ar0 = terms.USAXS.center.AR.get()
        sy0 = s_stage.y.position
        for i, target_ar in enumerate(ar_series.stepper()):

            if useDynamicTime:
                if i / intervals < 0.33:
                    count_time = count_time_base / 3
                elif i / intervals < 0.66:
                    count_time = count_time_base
                else:
                    count_time = count_time_base * 2

            # track ay & dy on scattered beam position
            target_ay = ay0 + _triangulate_(target_ar - ar0, SAD_mm)
            target_dy = dy0 + _triangulate_(target_ar - ar0, SDD_mm)

            # re-position the sample before each step
            target_sy = sy0 + i * terms.USAXS.sample_y_step.get()

            moves = [
                a_stage.r, target_ar, a_stage.y, target_ay, d_stage.y,
                target_dy, s_stage.y, target_sy, scaler0.preset_time,
                count_time
            ]

            if terms.USAXS.useSBUSAXS.get():
                # adjust the ASRP piezo on the AS side-bounce stage
                tanBragg = math.tan(reference * math.pi / 180)
                cosScatAngle = math.cos(
                    (reference - target_ar) * math.pi / 180)
                diff = math.atan(
                    tanBragg / cosScatAngle) * 180 / math.pi - reference

                # Note on asrp adjustment:  NOTE: seems wrong, but may need to be revisited???
                #   use "-" when reflecting  inboard towards storage ring (single bounce setup)
                #   use "+" when reflecting outboard towards experimenters (channel-cut setup)
                ### on 2/06/2002 Andrew realized, that we are moving in wrong direction
                ## the sign change to - moves ASRP towards larger Bragg angles...
                ## verified experimentally - higher voltage on piezo = lower Bragg angle...
                ## and we need to INCREASE the Bragg Angle with increasing Q, to correct for tilt down...

                asrp_vdc = asrp0 - diff / terms.usaxs.asrp_degrees_per_VDC.get(
                )
                moves += [as_stage.rp, asrp_vdc]

            # added for fuel spray users as indication that we are counting...
            moves += [fuel_spray_bit, 1]

            yield from user_data.set_state_plan(
                f"moving motors {i+1}/{intervals}")
            yield from bps.mv(*moves)

            # count
            yield from user_data.set_state_plan(f"counting {i+1}/{intervals}")
            yield from bps.trigger(scaler0,
                                   group="uascan_count")  # start the scaler
            yield from bps.wait(group="uascan_count")  # wait for the scaler

            # collect data for the primary stream
            yield from addDeviceDataAsStream(read_devices, "primary")

            if useDynamicTime:
                if i < intervals / 3:
                    count_time = count_time_base / 2
                elif intervals / 3 <= i < intervals * 2 / 3:
                    count_time = count_time_base
                else:
                    count_time = 2 * count_time_base
Beispiel #26
0
def _scaler_autoscale_(controls, count_time=0.05, max_iterations=9):
    """plan: internal: autoscale amplifiers for signals sharing a common scaler"""
    global _last_autorange_gain_

    scaler = controls[0].scaler
    originals = {}

    originals["preset_time"] = scaler.preset_time.get()
    originals["delay"] = scaler.delay.get()
    originals["count_mode"] = scaler.count_mode.get()
    yield from bps.mv(
        scaler.preset_time,
        count_time,
        scaler.delay,
        0.2,
        scaler.count_mode,
        "OneShot",
    )

    last_gain_dict = _last_autorange_gain_[scaler.name]

    settling_time = AMPLIFIER_MINIMUM_SETTLING_TIME
    for control in controls:
        yield from bps.mv(control.auto.mode, AutorangeSettings.automatic)
        # faster if we start from last known autoscale gain
        gain = last_gain_dict.get(control.auto.gain.name)
        if gain is not None:  # be cautious, might be unknown
            yield from control.auto.setGain(gain)
        last_gain_dict[control.auto.gain.name] = control.auto.gain.get()
        settling_time = max(settling_time, control.femto.settling_time.get())

    yield from bps.sleep(settling_time)

    # Autoscale has converged if no gains change
    # Also, make sure no detector count rates are stuck at max

    complete = False
    for iteration in range(max_iterations):
        converged = []  # append True is convergence criteria is satisfied
        yield from bps.trigger(scaler, wait=True)  #timeout=count_time+1.0)

        # amplifier sequence program (in IOC) will adjust the gain now

        for control in controls:
            # any gains changed?
            gain_now = control.auto.gain.get()
            gain_previous = last_gain_dict[control.auto.gain.name]
            converged.append(gain_now == gain_previous)
            last_gain_dict[control.auto.gain.name] = gain_now

            # are we topped up on any detector?
            max_rate = control.auto.max_count_rate.get()
            if isinstance(control.signal, ScalerChannel):  # ophyd.ScalerCH
                actual_rate = control.signal.s.get() / control.scaler.time.get(
                )
            elif isinstance(control.signal,
                            EpicsSignalRO):  # ophyd.EpicsScaler
                # actual_rate = control.signal.get()      # FIXME
                raise RuntimeError("This scaler needs to divide by time")
            else:
                raise ValueError(
                    f"unexpected control.signal: {control.signal}")
            converged.append(actual_rate <= max_rate)
            logger.debug(
                f"gain={gain_now}  rate: {actual_rate}  max: {max_rate}  converged={converged}"
            )

        if False not in converged:  # all True?
            complete = True
            for control in controls:
                yield from bps.mv(control.auto.mode, "manual")
            logger.debug(f"converged: {converged}")
            break  # no changes

    # scaler.stage_sigs = stage_sigs["scaler"]
    # restore starting conditions
    yield from bps.mv(
        scaler.preset_time,
        originals["preset_time"],
        scaler.delay,
        originals["delay"],
        scaler.count_mode,
        originals["count_mode"],
    )

    if not complete and aps.inUserOperations:  # bailed out early from loop
        logger.warning(f"converged={converged}")
        msg = f"FAILED TO FIND CORRECT GAIN IN {max_iterations} AUTOSCALE ITERATIONS"
        if RE.state != "idle":  # don't raise if in summarize_plan()
            raise AutoscaleError(msg)
Beispiel #27
0
    def scan_closure():
        yield from bps.mv(det.cam.acquire_time, acquire_time)
        yield from bps.mv(det.cam.acquire_period, acquire_period)

        # -------------------
        # collect white field
        # -------------------
        # 1-1 monitor shutter status, auto-puase scan if beam is lost
        yield from bps.mv(A_shutter, 'open')
        yield from bps.install_suspender(suspend_A_shutter)

        # 1-2 move sample out of the way
        current_samx = samx.position
        current_samy = samy.position
        current_preci = preci.position
        dx = config['tomo']['sample_out_position']['samx']
        dy = config['tomo']['sample_out_position']['samy']
        dr = config['tomo']['sample_out_position']['preci']
        yield from bps.mv(samx, current_samx + dx)
        yield from bps.mv(samy, current_samy + dy)
        yield from bps.mv(preci, current_preci + dr)

        # 1-2.5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 0)

        # 1-3 collect front white field images
        yield from bps.mv(det.proc1.enable, 1)
        yield from bps.mv(det.proc1.reset_filter, 1)
        yield from bps.mv(det.proc1.num_filter, n_frames)
        yield from bps.mv(det.cam.trigger_mode, "Internal")
        yield from bps.mv(det.cam.image_mode, "Multiple")
        yield from bps.mv(det.cam.num_images, n_frames * n_white)
        yield from bps.trigger_and_read([det])

        # 1-4 move sample back
        yield from bps.mv(samx, current_samx)
        yield from bps.mv(samy, current_samy)
        yield from bps.mv(preci, current_preci)

        # -------------------
        # collect projections
        # -------------------
        # 1-4.5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 1)

        # 1-5 quicly reset proc1
        yield from bps.mv(det.proc1.reset_filter, 1)

        # 1-6 collect projections
        yield from motor_set_modulo(preci, 360.0)

        # configure the psofly interface
        yield from bps.mv(
            psofly.start,
            config['tomo']['omega_start'],
            psofly.end,
            config['tomo']['omega_end'],
            psofly.scan_control,
            "Standard",
            psofly.scan_delta,
            config['tomo']['omega_step'],
            psofly.slew_speed,
            slew_speed,
            preci.velocity,
            ROT_STAGE_FAST_SPEED,
            preci.acceleration,
            slew_speed / accl,
        )
        # taxi
        yield from bps.mv(psofly.taxi, "Taxi")
        yield from bps.mv(preci.velocity, slew_speed)
        # ???
        yield from bps.mv(
            det.cam.num_images,
            n_projections,
            det.cam.trigger_mode,
            "Overlapped",
        )
        # start the fly scan
        yield from bps.trigger(det, group='fly')
        yield from bps.abs_set(psofly.fly, "Fly", group='fly')
        yield from bps.wait(group='fly')

        # ------------------
        # collect back white
        # ------------------
        # 1-7 move the sample out of the way
        # NOTE:
        # this will return ALL motors to starting positions, we need a
        # smart way to calculate a shorter trajectory to move sample
        # out of way
        yield from bps.mv(preci, current_preci + dr)
        yield from bps.mv(samx, current_samx + dx)
        yield from bps.mv(samy, current_samy + dy)

        # 1-7.5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 2)

        # 1-8 take the back white
        yield from bps.mv(det.cam.num_images, n_frames * n_white)
        yield from bps.trigger_and_read([det])

        # 1-9 move sample back
        yield from bps.mv(samx, current_samx)
        yield from bps.mv(samy, current_samy)
        yield from bps.mv(preci, current_preci)

        # -----------------
        # collect back dark
        # -----------------
        # 1-10 close the shutter
        yield from bps.remove_suspender(suspend_A_shutter)
        yield from bps.mv(A_shutter, "close")

        # 1-10.5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 3)

        # 1-11 collect the back dark
        yield from bps.mv(det.cam.num_images, n_frames * n_dark)
        yield from bps.trigger_and_read([det])
Beispiel #28
0
    def scan_closure():
        # -------------------
        # collect white field
        # -------------------
        # 1-1 monitor shutter status, auto-puase scan if beam is lost
        yield from bps.open_run()
        yield from bps.mv(A_shutter, 'open')
        yield from bps.install_suspender(suspend_A_shutter)

        #1-1.5 configure output plugins     edited by Jason 07/19/2019
        for me in [det.tiff1, det.hdf1]:
            yield from bps.mv(me.file_path, fp)
            yield from bps.mv(me.file_name, fn)
            yield from bps.mv(me.file_write_mode, 2)
            yield from bps.mv(me.num_capture, total_images)
            yield from bps.mv(
                me.file_template,
                ".".join([r"%s%s_%06d", config['output']['type'].lower()]))

        if config['output']['type'] in ['tif', 'tiff']:
            yield from bps.mv(det.tiff1.enable, 1)
            yield from bps.mv(det.tiff1.capture, 1)
            yield from bps.mv(det.hdf1.enable, 0)
        elif config['output']['type'] in ['hdf', 'hdf1', 'hdf5']:
            yield from bps.mv(det.tiff1.enable, 0)
            yield from bps.mv(det.hdf1.enable, 1)
            yield from bps.mv(det.hdf1.capture, 1)
        else:
            raise ValueError(f"Unsupported output type {output_dict['type']}")

        # 1-2 move sample out of the way
        initial_samx = samX.position
        initial_samy = samY.position
        initial_preci = preci.position
        dx = config['tomo']['sample_out_position']['samX']
        dy = config['tomo']['sample_out_position']['samY']
        r = config['tomo']['sample_out_position']['preci']
        yield from bps.mv(samX, initial_samx + dx)
        yield from bps.mv(samY, initial_samy + dy)
        yield from bps.mv(preci, r)

        # 1-2.5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 0)

        # 1-3 collect front white field images
        yield from bps.mv(det.hdf1.nd_array_port, 'PROC1')
        yield from bps.mv(det.tiff1.nd_array_port, 'PROC1')
        yield from bps.mv(det.proc1.enable, 1)
        yield from bps.mv(det.proc1.reset_filter, 1)
        yield from bps.mv(det.proc1.num_filter, n_frames)
        yield from bps.mv(det.cam.trigger_mode, "Internal")
        yield from bps.mv(det.cam.image_mode, "Multiple")
        yield from bps.mv(det.cam.num_images, n_frames * n_white)
        yield from bps.mv(det.cam.acquire_time, acquire_time)
        yield from bps.mv(det.cam.acquire_period, acquire_period)
        yield from bps.trigger_and_read([det])

        # 1-4 move sample back
        yield from bps.mv(samX, initial_samx)
        yield from bps.mv(samY, initial_samy)
        #yield from bps.mv(preci, initial_preci)

        # -------------------
        # collect projections
        # -------------------
        # 1-5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 1)
        # 1-6 step and fly scan are differnt
        if config['tomo']['type'].lower() == 'step':
            yield from bps.mv(det.proc1.reset_filter, 1)
            yield from bps.mv(det.cam.num_images, n_frames)
            # 1-6 collect projections
            for ang in angs:
                yield from bps.checkpoint()
                yield from bps.mv(preci, ang)
                yield from bps.trigger_and_read([det])
        elif config['tomo']['type'].lower() == 'fly':
            yield from bps.mv(det.proc1.num_filter, 1)
            yield from bps.mv(det.hdf1.nd_array_port, 'PG1')
            yield from bps.mv(det.tiff1.nd_array_port, 'PG1')
            yield from bps.mv(
                psofly.start,
                config['tomo']['omega_start'],
                psofly.end,
                config['tomo']['omega_end'],
                psofly.scan_delta,
                abs(config['tomo']['omega_step']),
                psofly.slew_speed,
                slew_speed,
            )
            # taxi
            yield from bps.mv(psofly.taxi, "Taxi")
            # setup detector to overlap for fly scan
            yield from bps.mv(
                det.cam.num_images,
                n_projections,
                det.cam.trigger_mode,
                "Overlapped",
            )
            # start the fly scan
            print("before trigger")
            yield from bps.trigger(det, group='trigger')
            print("waiting for trigger")
            # yield from bps.wait(group='trigger')
            print("before plan()")
            try:
                yield from psofly.plan()
            except NotEnoughTriggers as err:
                reason = (
                    f"{err.expected:.0f} were expected but {err.actual:.0f} were received."
                )
                yield from bps.close_run('fail', reason=reason)
                return  # short-circuit

            # fly scan finished. switch image port and trigger_mode back
            yield from bps.mv(det.cam.trigger_mode, "Internal")
            yield from bps.mv(det.hdf1.nd_array_port, 'PROC1')
            yield from bps.mv(det.tiff1.nd_array_port, 'PROC1')
        else:
            raise ValueError(f"Unknown scan type: {config['tomo']['type']}")

        # ------------------
        # collect back white
        # ------------------
        # 1-7 move the sample out of the way
        # NOTE:
        # this will return ALL motors to starting positions, we need a
        # smart way to calculate a shorter trajectory to move sample
        # out of way
        yield from bps.mv(preci, r)
        yield from bps.mv(samX, initial_samx + dx)
        yield from bps.mv(samY, initial_samy + dy)

        # 1-7.5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 2)

        # 1-8 take the back white
        yield from bps.mv(det.proc1.num_filter, n_frames)
        yield from bps.mv(det.cam.num_images, n_frames * n_white)
        yield from bps.trigger_and_read([det])

        # 1-9 move sample back
        yield from bps.mv(samX, initial_samx)
        yield from bps.mv(samY, initial_samy)

        # -----------------
        # collect back dark
        # -----------------
        # 1-10 close the shutter
        yield from bps.remove_suspender(suspend_A_shutter)
        yield from bps.mv(A_shutter, "close")

        # 1-10.5 set frame type for an organized HDF5 archive
        yield from bps.mv(det.cam.frame_type, 3)

        # 1-11 collect the back dark
        yield from bps.mv(det.cam.num_images, n_frames * n_dark)
        yield from bps.trigger_and_read([det])
        yield from bps.close_run('success')
Beispiel #29
0
def _scaler_background_measurement_(control_list,
                                    count_time=0.2,
                                    num_readings=8):
    """plan: internal: measure amplifier backgrounds for signals sharing a common scaler"""
    scaler = control_list[0].scaler
    signals = [c.signal for c in control_list]

    stage_sigs = {}
    stage_sigs["scaler"] = scaler.stage_sigs  # benign
    original = {}
    original["scaler.preset_time"] = scaler.preset_time.get()
    original["scaler.auto_count_delay"] = scaler.auto_count_delay.get()
    yield from bps.mv(scaler.preset_time, count_time, scaler.auto_count_delay,
                      0)

    for control in control_list:
        yield from bps.mv(control.auto.mode, AutorangeSettings.manual)

    for n in range(NUM_AUTORANGE_GAINS - 1, -1, -1):  # reverse order
        # set gains
        settling_time = AMPLIFIER_MINIMUM_SETTLING_TIME
        for control in control_list:
            yield from control.auto.setGain(n)
            settling_time = max(settling_time,
                                control.femto.settling_time.get())
        yield from bps.sleep(settling_time)

        def getScalerChannelPvname(scaler_channel):
            try:
                return scaler_channel.pvname  # EpicsScaler channel
            except AttributeError:
                return scaler_channel.chname.get()  # ScalerCH channel

        # readings is a PV-keyed dictionary
        readings = {getScalerChannelPvname(s): [] for s in signals}

        for m in range(num_readings):
            yield from bps.sleep(0.05)  # allow amplifier to stabilize on gain
            # count and wait to complete
            yield from bps.trigger(scaler, wait=True)  #timeout=count_time+1.0)

            for s in signals:
                pvname = getScalerChannelPvname(s)
                value = s.get(
                )  # EpicsScaler channel value or ScalerCH ScalerChannelTuple
                if not isinstance(value, float):
                    value = s.s.get()  # ScalerCH channel value
                # logger.debug(f"scaler reading {m+1}: value: {value}")
                readings[pvname].append(value)

        s_range_name = f"gain{n}"
        for control in control_list:
            g = getattr(control.auto.ranges, s_range_name)
            pvname = getScalerChannelPvname(control.signal)
            # logger.debug(f"gain: {s_range_name} readings:{readings[pvname]}")
            yield from bps.mv(
                g.background,
                np.mean(readings[pvname]),
                g.background_error,
                np.std(readings[pvname]),
            )
            msg = f"{control.nickname}"
            msg += f" range={n}"
            msg += f" gain={ _gain_to_str_(control.auto.gain.get())}"
            msg += f" bkg={g.background.get()}"
            msg += f" +/- {g.background_error.get()}"

            logger.info(msg)

    scaler.stage_sigs = stage_sigs["scaler"]
    yield from bps.mv(
        scaler.preset_time,
        original["scaler.preset_time"],
        scaler.auto_count_delay,
        original["scaler.auto_count_delay"],
    )