Ejemplo n.º 1
0
def _unstick_GslitsSizeMotors():
    """Workaround for issue #425 (and #404)."""
    pause = 4
    logger.info("Workaround for Guard Slit 'motor stuck in moving'.")
    yield from bps.sleep(pause)     # activity pause, empirical

    logger.info("Sync H&V axes.")
    yield from bps.mv(
        guard_slit.h_sync_proc, 1,
        guard_slit.v_sync_proc, 1,
    )

    # NOTE: These steps did not affect the process outcome.
    # # write the .STUP field on each motor
    # for axis in "top bot inb outb".split():
    #     logger.info("Unstick %s.", axis)
    #     m = getattr(guard_slit, axis)
    #     try:
    #         yield from bps.abs_set(m.status_update, 1, timeout=.1)
    #         yield from bps.sleep(pause)     # activity pause, empirical
    #     except FailedStatus:
    #         pass
    #     except Exception as exc:
    #         logger.error("%s: %s", axis, exc)

    # move each motor *individually*
    for axis in "top bot inb outb".split():
        m = getattr(guard_slit, axis)
        logger.info("Move %s a little bit.\n", m.name)
        yield from bps.mvr(m, 0.1)
        logger.info("Move %s back.\n", m.name)
        yield from bps.mvr(m, -0.1)

    logger.info("Workaround Complete.")
Ejemplo n.º 2
0
def test_mvr_with_timeout(hw):
    # special-case mv because the group is not configurable
    # move motors first to ensure that movement is absolute, not relative
    actual = list(mvr(hw.motor1, 1, hw.motor2, 2, timeout=42))
    for msg in actual[:2]:
        msg.command == 'set'
        msg.kwargs['timeout'] == 42
Ejemplo n.º 3
0
def tune_plan(step=0):
    '''
    Tune 2nd crystal pitch from a plan.  Argument is a value for the step, so a relative motion.
    '''
    yield from abs_set(dcm_pitch.kill_cmd, 1, wait=True)
    yield from mvr(dcm_pitch, step)
    yield from sleep(1.0)
    yield from abs_set(dcm_pitch.kill_cmd, 1, wait=True)
Ejemplo n.º 4
0
def tweak_bct(step):
    dm3_bct = user_ns['dm3_bct']
    if step is None:
        step = 0
    if dm3_bct.ampen.get() == 0:
        yield from mv(dm3_bct.enable_cmd, 1)     
    yield from mv(dm3_bct.kill_cmd, 1)
    print('Moving from %.4f to %.4f' % (dm3_bct.user_readback.get(), dm3_bct.user_readback.get() + step))
    yield from mvr(dm3_bct, step)
Ejemplo n.º 5
0
def mvrbct(target=None):
    '''
    A workaround to kill the BCT motor, then do a relative movement
    '''
    dm3_bct = user_ns['dm3_bct']
    if target is None:
        target = 0
    yield from abs_set(dm3_bct.kill_cmd, 1, wait=True)
    yield from mvr(dm3_bct, target)
Ejemplo n.º 6
0
def mvrbender(target=None):
    '''
    A workaround to kill the M2 bender motor, then do a relative movement
    '''
    m2_bender = user_ns['m2_bender']
    if target is None:
        target = 0
    yield from abs_set(m2_bender.kill_cmd, 1, wait=True)
    yield from mvr(m2_bender, target)
Ejemplo n.º 7
0
def tweak_bct(step):
    dm3_bct = user_ns['dm3_bct']
    if step is None:
        step = 0
    yield from abs_set(dm3_bct.kill_cmd,1, wait=True)
    print('Moving from %.4f to %.4f' % (dm3_bct.user_readback.get(), dm3_bct.user_readback.get() + step))
    yield from mvr(dm3_bct, step)
    time.sleep(3.0)
    yield from abs_set(dm3_bct.kill_cmd,1, wait=True)
Ejemplo n.º 8
0
def energystep(filename = None,
               start    = None,
               end      = None,
               nsteps   = None,
               delay    = 5,
               dosteps  = True):
    '''A simple energy scan, just step forward in energy and don't measure
    anything.  This is a quick hack for use with a crude resonant
    reflectivity experiment with IBM folks.

      filename: name of file, will be appended to DATA for the full path (required)
      start:    starting energy value (required)
      end:      ending energy value (required)
      nsteps:   number of energy steps (required)
      delay:    pause between energy steps, in seconds [5]
      dosteps:  False to see energy values printed to screen without moving mono [True]

    Writes a data file with columns of energy readback, energy
    requested, time of epoch, and ISO 8601 timestamp

    Example:
       energystep(filename='blahblah', start=18936, end=19036, nsteps=101)
    '''

    BMMuser, dcm = user_ns['BMMuser'], user_ns['dcm']
    BMM_log_info("energystep(filename=%s, start=%.1f, end=%.1f, nsteps=%d, delay=%.1f, dosteps=%s)" % (filename, start, end, nsteps, delay, str(dosteps)))
    datafile = BMMuser.DATA + filename
    handle = open(datafile, 'w')
    handle.write('# energy steps from %.1f to %.1f in %d steps\n' % (start, end, nsteps))
    handle.write('#----------------------------------------------------\n')
    handle.write('# energy        requested          epoch        iso8601\n')
    handle.flush()
    
    if dosteps:
        yield from mv(dcm.energy, start)
    print('  %.1f       %.1f     %.6f    %s' % (dcm.energy.readback.get(), start, time.time(), now()))
    handle.write('  %.1f       %.1f     %.6f    %s\n' % (dcm.energy.readback.get(), start, time.time(), now()))
    handle.flush()
    yield from sleep(delay)

    energy = start
    estep = (end-start) / nsteps
    while energy <= end:
        if dosteps:
            yield from mvr(dcm.energy, estep)
        print('  %.1f       %.1f     %.6f    %s' % (dcm.energy.readback.get(), energy, time.time(), now()))
        handle.write('  %.1f       %.1f     %.6f    %s\n' % (dcm.energy.readback.get(), energy, time.time(), now()))
        handle.flush()
        energy = energy + estep
        yield from sleep(delay)
        

    handle.flush()
    handle.close()
Ejemplo n.º 9
0
def mvrbct(target=None):
    '''
    A workaround to kill the BCT motor, then do a relative movement

    Since Jan 27 2022, this should not be necessary.
    '''
    dm3_bct = user_ns['dm3_bct']
    if target is None:
        target = 0
    if dm3_bct.ampen.get() == 0:
        yield from mv(dm3_bct.enable_cmd, 1)     
    yield from mv(dm3_bct.kill_cmd, 1)
    yield from mvr(dm3_bct, target)
Ejemplo n.º 10
0
def test_mvr(RE, hw):
    # special-case mv because the group is not configurable
    # move motors first to ensure that movement is relative, not absolute
    hw.motor1.set(10)
    hw.motor2.set(10)
    actual = []
    RE.msg_hook = lambda msg: actual.append(msg)
    RE(mvr(hw.motor1, 1, hw.motor2, 2))
    actual = list(mv(hw.motor1, 1, hw.motor2, 2))
    strip_group(actual)
    for msg in actual[:2]:
        msg.command == 'set'
    assert set([msg.obj for msg in actual[:2]]) == set([hw.motor1, hw.motor2])
    assert actual[2] == Msg('wait', None)
Ejemplo n.º 11
0
def test_mvr(RE, hw):
    # special-case mv because the group is not configurable
    # move motors first to ensure that movement is relative, not absolute
    hw.motor1.set(10)
    hw.motor2.set(10)
    actual = []
    RE.msg_hook = lambda msg: actual.append(msg)
    RE(mvr(hw.motor1, 1, hw.motor2, 2))
    actual = list(mv(hw.motor1, 1, hw.motor2, 2))
    strip_group(actual)
    for msg in actual[:2]:
        msg.command == 'set'
    assert set([msg.obj for msg in actual[:2]]) == set([hw.motor1, hw.motor2])
    assert actual[2] == Msg('wait', None)
Ejemplo n.º 12
0
 def set_slot(self, n):
     '''Move to a numbered slot on a sample wheel.'''
     if type(n) is not int:
         print(
             error_msg(
                 'Slots numbers must be integers between 1 and 24 (argument was %s)'
                 % type(n)))
         return (yield from null())
     if n < 1 or n > 24:
         print(error_msg('Slots are numbered from 1 to 24'))
         return (yield from null())
     angle = self.angle_from_current(n)
     yield from mvr(self, angle)
     report('Arrived at sample wheel slot %d' % n, level='bold')
Ejemplo n.º 13
0
 def to(self, number):
     '''Rotate to the specified spinner. Turn off all other spinners.  Turn
     on the specified spinner.'''
     if not self.valid(number):
         print(error_msg('The fans are numbered from 1 to 8'))
         yield from null()
         return
     yield from self.alloff_plan()
     distance = number - self.current()
     if distance > 4:
         distance = distance - 8
     elif distance < -4:
         distance = 8 + distance
     angle = -45*distance
     yield from mvr(self.garot, angle)
     if self.spin is True:
         this = getattr(self, f'spinner{number}')
         yield from mv(this, 1)
def random_step(x: float = 0,y: float = 0, **kwargs):

    '''
    This plan will move the stage randomly by a random number between
    x/2 and x  and y/2 and y, sampling a donut around the original point
    '''
    sys.stdout = kwargs.pop('stdout', sys.stdout)
    print_to_gui('Executing random move',sys.stdout)
    if  type(x) == str:
        x = float(x)
        y = float(y)
    if not 'motor_x' in kwargs.keys():
        motor_x = giantxy.x
    if not 'motor_y' in kwargs.keys():
        motor_y = giantxy.y
    random_x = 2 * x * (random()-0.5)
    random_x = random_x * 0.5 + 0.5 * np.sign(random_x)
    random_y = 2 * y*(random()-0.5)
    random_y = random_y * 0.5 + 0.5 * np.sign(random_y)
    yield from mvr(motor_x,random_x,motor_y,random_y)
Ejemplo n.º 15
0
def kmvr(*args):
    for m in args[0::2]:
        if 'Vacuum' in str(type(m)):
            yield from abs_set(m.kill_cmd, 1, wait=True)
    yield from mvr(*args)
def center_pin(cam=cam_8):
    """
    Centers a pin in Y
    
    Requirements
    ------------
    * Alignment pin mounted. Pin should be aligned in X to within 0.25 of the Mag3 width
    
    Parameters
    ----------
    cam: ophyd camera device. Should be cam_7 or cam_8 (default)
    
    Examples
    --------
    RE(center_pin())
    RE(center_pin(cam_7))
    """

    if cam not in [cam_7, cam_8]:
        print('cam must be one of: [cam_7, cam_8]')
        return -1

    # Copy ROI2 geometry (HiMag Mag3 and LoMag Mag1) to ROI4 and use ROI4 centroid plugin
    cam.roi4.min_xyz.min_x.put(cam.roi2.min_xyz.min_x.get())
    cam.roi4.min_xyz.min_y.put(cam.roi2.min_xyz.min_y.get())
    cam.roi4.size.x.put(cam.roi2.size.x.get() * 0.25)
    cam.roi4.size.y.put(cam.roi2.size.y.get())
    cam.roi4.min_xyz.min_x.put(cam.roi2.min_xyz.min_x.get() +
                               cam.roi2.size.x.get() / 2 -
                               cam.roi4.size.x.get() / 2)

    # Invert camera image, so dark pin on light image becomes a peak
    cam.proc1.scale.put(-1)

    # High threshold, so AD centroid doesn't interpret background
    camThresholdOld = cam.stats4.centroid_threshold.get()
    cam.stats4.centroid_threshold.put(150)

    # Get centroids at Omega = 0, 90, 180, 270 deg
    yield from bps.mv(gonio.o, 0)
    time.sleep(2)
    c0 = centroid_avg(cam.stats4)[1]

    yield from bps.mv(gonio.o, 90)
    time.sleep(2)
    c90 = centroid_avg(cam.stats4)[1]

    yield from bps.mv(gonio.o, 180)
    time.sleep(2)
    c180 = centroid_avg(cam.stats4)[1]

    yield from bps.mv(gonio.o, 270)
    time.sleep(2)
    c270 = centroid_avg(cam.stats4)[1]

    # Camera calibration [um/px]
    if cam == cam_8:
        camCal = BL_calibration.HiMagCal.get()
    elif cam == cam_7:
        camCal = BL_calibration.LoMagCal.get()

    # Center offset Y
    offsY = ((c180 - c0)) / 2 * camCal
    print('Y offset = {:.6g} um'.format(offsY))

    # Center offset Z
    offsZ = ((c270 - c90)) / 2 * camCal
    print('Z offset = {:.6g} um'.format(offsZ))

    # Move pin to center
    yield from bps.mvr(gonio.py, offsY)
    yield from bps.mvr(gonio.pz, offsZ)

    # De-invert image
    cam.proc1.scale.put(1)

    # Set thresold to previous value
    cam.stats4.centroid_threshold.put(camThresholdOld)
Ejemplo n.º 17
0
 def _tweak(self, direction):
     motor = self._cur_alignment_motor
     step = self.doubleSpinBox_tweak_motor_step.value()
     self.RE(bps.mvr(motor, direction * step))
     pos = motor.user_readback.get()
     self.doubleSpinBox_tweak_motor_pos.setValue(pos)
def plan(FBref):
    # The loop variable, FBi, is changed from within the loop.
    FBi = 90
    while 90 <= FBi <= 100:
        print(f'FBi: {FBi}')
        pico_value = (yield from read(pm))["pm"]["value"]
        outb_value = (yield from read(outb))["outb"]["value"]
        inb_value = (yield from read(inb))["inb"]["value"]
        FACTOR = 1000000  # TODO What is this, a unit conversion?
        BPMpos = (outb_value - inb_value) / (inb_value + outb_value) * FACTOR
        print(f"inboard signal {inb_value:.6}")
        print(f"outboard signal {outb_value:.6}")
        print(f"position {BPMpos:.4}    pico {pico_value:.6}")
        deltaPos = BPMpos - FBref
        # Check limits.
        FBi2 = 90
        if pico_value - 1 < -550.0:
            FBi = 101
        else:
            FBi = FBi2
        if pico_value - 1 > 400.0:
            FBi = 101
        # check for no beam.
        if (inb_value < 0.07) and (outb_value < 0.07):
            FBi = 97
        # compare and move as needed:
        if FBi < 96:
            if 20000 < deltaPos < 150000:
                move_by = 0.021
            elif -150000 < deltaPos < -25000:
                move_by = -0.021
            elif 150000 < deltaPos < 400000:
                move_by = 0.063
            elif -400000 < deltaPos < -150000:
                move_by = -0.063
            elif deltaPos > 400000:
                move_by = 0.200
            elif deltaPos < -400000:
                move_by = -0.200
            else:
                move_by = 0
        else:
            move_by = 0
        if move_by:
            yield from mvr(pm, move_by)
            print(f"moved {move_by} at {datetime.now().isoformat()}")
        # set feedback frequency:
        yield from sleep(0.05)  # 20 Hz
        # if beam is lost, pause 10 sec and re-loop
        if FBi == 97:
            print(
                f"lost signal, waiting 10 sec starting at {datetime.now().isoformat()}"
            )
            yield from sleep(10)
    yield from sleep(1.0)
    pico_value = (yield from read(pm))["pm"]["value"]
    print(f"feedback stopped...     pico  {pico_value}")
    print(f"inboard signal  {inb_value:.6}")
    print(f"outboard signal {outb_value:.6}")
    print(f"position        {BPMpos:.4}")
    print(f"Plan exited at {datetime.now().isoformat()}")
Ejemplo n.º 19
0
def kmvr(*args):
    for m in args[0::2]:
        if 'Vacuum' in str(type(m)):
            yield from mv(m.kill_cmd, 1)
    yield from mvr(*args)
Ejemplo n.º 20
0
    def xy_fly_scan(self,
                    nshots,
                    nrows=2,
                    y_distance=None,
                    rate=5,
                    record=True,
                    xrays=True):
        """
        Plan for doing a 2D fly scan. Uses the target x motor as the flying
        axis, running for a specified distance at a specified velocity, taking
        shots at a specified rate. 

        Parameters
        ----------
        nshots : int
            The number of shots to take in the x scan. 

        rate : int <default : 5>
            The rate at which to take shots (120, 30, 10, 5, 1)

        y_distance : float <default : x.grid.y_spacing>
            The distance to move the y stage down. 

        nrows : int <default : 2>
            The number of "rows" to scan the x stage on.

        record : bool <default : True>
            Flag to record the data. 

        xrays : bool <default : True>
            Flag to take an x-ray + optical (True) shot or optical only (False).
        """
        logging.debug("rate: {}".format(rate))
        logging.debug("nshots: {}".format(nshots))
        logging.debug("nrows: {}".format(nrows))
        logging.debug("record: {}".format(record))
        logging.debug("xrays: {}".format(xrays))

        if not y_distance:
            y_distance = self.grid.y_spacing
        logging.debug("y_distance: {}".format(y_distance))

        assert rate in [120, 30, 10, 5,
                        1], "Please choose a rate in {120, 30, 10,5,1}"

        print("Configuring DAQ...")
        daq.configure(events=0, record=record)  # run infinitely
        daq.begin_infinite()

        print("Configuring sequencer...")
        # Setup the pulse picker for single shots in flip flop mode
        pp.flipflop(wait=True)
        # Setup sequencer for requested rate
        sync_mark = int(self._sync_markers[rate])
        seq.sync_marker.put(sync_mark)
        seq.play_mode.put(1)  # Run for n shots
        seq.rep_count.put(nshots)
        # Setup sequence
        self._seq.rate = rate
        if xrays:
            s = self._seq.duringSequence(1, 'shortpulse')
        else:
            s = self._seq.opticalSequence(1, 'shortpulse')
        seq.sequence.put_seq(s)

        # Get starting positions
        start = self.grid.wm()

        # Calculate and set velocity
        vel = self.grid.x_spacing * rate  # mm * (1/s) = mm/s
        self.grid.x.velocity.put(vel)

        # Estimate distance to move given requested shots and rate
        dist = (nshots / rate) * vel  # (shots/(shots/sec))*mm/s = mm

        # Close shutter 6 (requested)
        self._shutters[6].close()
        time.sleep(5)

        for i in range(nrows):
            if i != 0:
                yield from bps.mvr(self.grid.y, y_distance)
            # Play the sequencer
            seq.play_control.put(1)

            # Start the move
            yield from bps.mvr(self.grid.x, dist)  # Waits for move to complete

            # Make sure the sequencer stopped
            seq.play_control.put(0)

            yield from bps.mv(self.grid.x, start['x'])

        # Return to start
        print("Returning to starting position")
        yield from bps.mv(self.grid.x, start['x'])
        yield from bps.mv(self.grid.y, start['y'])

        daq.end_run()

        self._shutters[6].open()
Ejemplo n.º 21
0
 def stage_left(self):
     h_step = self.spinBox_hor_step.value()
     self.RE(bps.mvr(self.sample_stage.x, h_step))
     self.show_image()
Ejemplo n.º 22
0
 def stage_down(self):
     v_step = self.spinBox_ver_step.value()
     self.RE(bps.mvr(self.sample_stage.y, -v_step))
     self.show_image()
Ejemplo n.º 23
0
    def uxi_shot(self, delta=0.3, record=True, lasps=True):
        """
        Returns a BlueSky plan to run a scan for the LV08 experiment. Used for
        the UXI camera which requires near continuous acquisition for stable
        camera behavior. The following shots are combined in a single run.

        Shot sequence:
        --------------
        1) 10 dark frames    # Warm up camera
        2) 10 X-ray frames
        3) Sample moves in
        4) 10 dark frames    # Warm up camera
        5) 1 X-ray + Optical laser frame
        6) 10 dark frames
        7) Sample moves out
        8) 10 dark frames    # Warm up camera
        9) 10 X-ray frames
        
        Parameters:
        -----------
        delta : float <default: 0.3>
            The relative distance in mm to move the sample in and out.

        record : bool <default: True>
            Flag to record the data (or not).

        lasps : bool <default: True>
            Flag to perform pre-and post shot pulse shaping routines. 
        """
        logging.debug("Calling User.shot with parameters:")
        logging.debug("delta: {}".format(delta))        
        logging.debug("record: {}".format(record))        
        logging.debug("lasps: {}".format(lasps))        

        print("Configuring DAQ...")
#        yield from bps.configure(daq,events=0, record=record) # run infinitely, let sequencer
                                               # control number of events
        daq.begin_infinite(record=record)

        long_seq = [[0, 240, 0, 0],
                    [0, 0, 0, 0],
                    [0, 0, 0, 0],
                    [0, 0, 0, 0],
                    [0, 0, 0, 0],
                    [0, 0, 0, 0],
                    [0, 0, 0, 0],
                    [0, 0, 0, 0]]
        
        print("Configuring sequencer...")
        # Setup the pulse picker for single shots in flip flop mode
        pp.flipflop(wait=True)
        # Setup sequencer for requested rate
        sync_mark = int(self._sync_markers[0.5])
        seq.sync_marker.put(sync_mark)
        seq.play_mode.put(1) # Run N times
        seq.rep_count.put(10) 
        # Setup sequence
        self._seq.rate = 0.5

        # close the shutters specified by the user
        for shutter in self.shutters:
            self._shutters[shutter].close()
        # Shutters are slow; give them time to close
        time.sleep(5)

        if lasps:
            print("Running mecps.pspreshot()...")
            pspreshot()

        # Run 10 Pre-laser dark shots (step 1 above)
        s = self._seq.darkSequence(1, preshot=False)
#        seq.sequence.put_seq(long_seq)
#        seq.sequence.put_seq(s)
        self.scalar_sequence_write(s)
        print("Taking 10 dark shots...")
        time.sleep(1)
        seq.start()
        self.seq_wait()
 #       yield from bps.trigger_and_read([daq, seq])

        # Run 10 Pre-laser x-ray shots (step 2 above)
        s = self._seq.darkXraySequence(1, preshot=False)
#        seq.sequence.put_seq(long_seq)
#        seq.sequence.put_seq(s)
        self.scalar_sequence_write(s)
        print("Taking 10 x-ray shots...")
        time.sleep(1)
        seq.start()
        self.seq_wait()
        #yield from bps.trigger_and_read([daq, seq])
        
        # Move sample in (step 3 above)
        print("Moving sample in...")
        yield from bps.mvr(self.target_x, delta) #TODO Check direction

        # Run 10 Pre-laser dark shots (step 4 above)
        print("Taking 10 dark shots...")
        s = self._seq.darkSequence(1, preshot=False)
#        seq.sequence.put_seq(long_seq)
#        seq.sequence.put_seq(s)
        self.scalar_sequence_write(s)
        time.sleep(1)
        seq.start()
        self.seq_wait()
 #       yield from bps.trigger_and_read([daq, seq])

        # Run x-ray + optical sequence (step 5 above)
        print("Taking optical laser shots...")
        seq.rep_count.put(1) 
        s = self._seq.duringSequence(1, 'longpulse')
#        seq.sequence.put_seq(long_seq)
#        seq.sequence.put_seq(s)
        self.scalar_sequence_write(s)
        time.sleep(1)
        seq.start()
        self.seq_wait()
 #       yield from bps.trigger_and_read([daq, seq])

        # Run 10 Post-laser dark shots (step 6 above)
        print("Taking 10 dark shots...")
        seq.rep_count.put(10) 
        s = self._seq.darkSequence(1, preshot=False)
#        seq.sequence.put_seq(long_seq)
#        seq.sequence.put_seq(s)
        self.scalar_sequence_write(s)
        time.sleep(1)
        seq.start()
        self.seq_wait()
 #       yield from bps.trigger_and_read([daq, seq])

        # Move sample out (step 7 above)
        print("Moving sample out...")
        yield from bps.mvr(self.target_x, -delta) #TODO Check direction

        # Run 10 Pre-x-ray dark shots (step 8 above)
        print("Taking 10 dark shots...")
        seq.rep_count.put(10) 
        s = self._seq.darkSequence(1, preshot=False)
#        seq.sequence.put_seq(long_seq)
#        seq.sequence.put_seq(s)
        self.scalar_sequence_write(s)
        time.sleep(1)
        seq.start()
        self.seq_wait()
 #       yield from bps.trigger_and_read([daq, seq])

        # Run 10 Pre-laser x-ray shots (step 9 above)
        print("Taking 10 x-ray shots...")
        s = self._seq.darkXraySequence(1, preshot=False)
#        seq.sequence.put_seq(long_seq)
#        seq.sequence.put_seq(s)
        self.scalar_sequence_write(s)
        time.sleep(1)
        seq.start()
        self.seq_wait()
 #       yield from bps.trigger_and_read([daq, seq])

        daq.end_run()

        if lasps:
            print("Running mecps.pspostshot()...")
            pspostshot()

        # open the shutters specified by the user
        for shutter in self.shutters:
            self._shutters[shutter].open()
Ejemplo n.º 24
0
    def auto_align(self, pitch=2, drop=None):
        '''Align a sample on a spinner automatically.  This performs 5 scans.
        The first four iterate twice between linear and pitch
        against the signal in It.  This find the flat position.

        Then the sample is pitched to the requested angle and a fifth
        scan is done to optimize the linear motor position against the
        fluorescence signal.

        The linear scans against It look like a step-down function.
        The center of this step is found as the centroid of a fitted
        error function.

        The xafs_pitch scan should be peaked.  Move to the max of the
        signal.

        The linear scan against fluorescence ideally looks like a
        flat-topped peak.  Move to the center of mass.

        At the end, a three-panel figure is drawn showing the last
        three scans.  This is posted to Slack.  It also finds its way
        into the dossier as a record of the quality of the alignment.

        Arguments
        =========
        pitch : int
          The angle at which to make the glancing angle measurements.
        drop : int or None
          If not None, then this many points will be dropped from the
          end of linear scan against transmission when fitting the error
          function. This is an attempt to deal gracefully with leakage 
          through the adhesive at very high energy.

        '''
        BMMuser = user_ns['BMMuser']
        if BMMuser.macro_dryrun:
            report(f'Auto-aligning glancing angle stage, spinner {self.current()}', level='bold', slack=False)
            print(info_msg(f'\nBMMuser.macro_dryrun is True.  Sleeping for %.1f seconds at spinner %d.\n' %
                           (BMMuser.macro_sleep, self.current())))
            countdown(BMMuser.macro_sleep)
            return(yield from null())

        report(f'Auto-aligning glancing angle stage, spinner {self.current()}', level='bold', slack=True)
            
        BMM_suspenders()

        ## first pass in transmission
        yield from self.align_linear(drop=drop)
        yield from self.align_pitch()

        ## for realsies X or Y in transmission
        yield from self.align_linear(drop=drop)
        self.y_uid = user_ns['db'].v2[-1].metadata['start']['uid'] 

        ## for realsies Y in pitch
        yield from self.align_pitch()
        self.pitch_uid = user_ns['db'].v2[-1].metadata['start']['uid'] 

        ## record the flat position
        if self.orientation == 'parallel':
            motor = user_ns['xafs_y']
        else:
            motor = user_ns['xafs_x']
        self.flat = [motor.position, user_ns['xafs_pitch'].position]

        ## move to measurement angle and align
        yield from mvr(user_ns['xafs_pitch'], pitch)
        yield from linescan(motor, 'xs', -2.3, 2.3, 51, pluck=False)
        self.f_uid = user_ns['db'].v2[-1].metadata['start']['uid'] 
        tf = user_ns['db'][-1].table()
        yy = tf[motor.name]
        signal = (tf[BMMuser.xs1] + tf[BMMuser.xs2] + tf[BMMuser.xs3] + tf[BMMuser.xs4]) / tf['I0']
        if BMMuser.element == 'Zr':
            centroid = yy[signal.idxmax()]
        else:
            com = int(center_of_mass(signal)[0])+1
            centroid = yy[com]
        yield from mv(motor, centroid)
        
        ## make a pretty picture, post it to slack
        self.alignment_plot(self.y_uid, self.pitch_uid, self.f_uid)
        self.alignment_filename = os.path.join(BMMuser.folder, 'snapshots', f'spinner{self.current()}-alignment-{now()}.png')
        plt.savefig(self.alignment_filename)
        try:
            img_to_slack(self.alignment_filename)
        except:
            post_to_slack('failed to post image: {self.alignment_filename}')
            pass
        BMM_clear_suspenders()
Ejemplo n.º 25
0
def find_detector_position(start=205, inttime=0.1, verbose=True):
    RE, xafs_det, dwell_time, xs = user_ns['RE'], user_ns['xafs_det'], user_ns[
        'dwell_time'], user_ns['xs']

    RE.msg_hook = None

    # if step == 0:
    #     step = -5
    # if step > 0:
    #     step = -1 * step
    step = 5
    factor = 1 / inttime
    toomuch = 205000. / factor
    description = 'optimized'

    datatable = []

    yield from mv(xafs_det, start)
    yield from mv(dwell_time, inttime)

    yield from mv(xs.cam.acquire, 1)
    time.sleep(0.25)
    ocrs = [
        float(xs.channels.channel01.mcarois.mcaroi16.total_rbv.get()),
        float(xs.channels.channel02.mcarois.mcaroi16.total_rbv.get()),
        float(xs.channels.channel03.mcarois.mcaroi16.total_rbv.get()),
        float(xs.channels.channel04.mcarois.mcaroi16.total_rbv.get())
    ]
    datatable.append([xafs_det.position, *ocrs])
    if verbose:
        print(
            ' xafs_det  OCR 1     OCR 2     OCR 3     OCR 4   target      predictions'
        )
        print(
            '======================================================================================='
        )
        print(
            f' {xafs_det.position:5.1f}   {ocrs[0]:8.1f}  {ocrs[1]:8.1f}  {ocrs[2]:8.1f}  {ocrs[3]:8.1f}  {toomuch}'
        )

    while all(y < toomuch for y in ocrs):
        if xafs_det.position - xafs_det.llm.get() < 10:
            step = -1
        elif xafs_det.position - xafs_det.llm.get() < 30:
            step = -2
        elif xafs_det.position - xafs_det.llm.get() < 80:
            step = -5
        else:
            step = -10

        if xafs_det.position + step < xafs_det.llm.get():
            description = 'closest possible'
            print(
                whisper(
                    f'the next step would go below the xafs_det soft limit ({xafs_det.llm.get()})'
                ))
            break
        yield from mvr(xafs_det, step)

        yield from mv(xs.cam.acquire, 1)
        time.sleep(1.5 * inttime)
        ocrs = [
            float(xs.channels.channel01.mcarois.mcaroi16.total_rbv.get()),
            float(xs.channels.channel02.mcarois.mcaroi16.total_rbv.get()),
            float(xs.channels.channel03.mcarois.mcaroi16.total_rbv.get()),
            float(xs.channels.channel04.mcarois.mcaroi16.total_rbv.get())
        ]
        datatable.append([xafs_det.position, *ocrs])
        if verbose:
            if len(datatable) > 5:
                predictions = predict_detector_position(datatable, toomuch)
                print(
                    f' {xafs_det.position:5.1f}   {ocrs[0]:8.1f}  {ocrs[1]:8.1f}  {ocrs[2]:8.1f}  {ocrs[3]:8.1f}  {toomuch}  {predictions[0]}  {predictions[1]}  {predictions[2]}  {predictions[3]}'
                )
            else:
                print(
                    f' {xafs_det.position:5.1f}   {ocrs[0]:8.1f}  {ocrs[1]:8.1f}  {ocrs[2]:8.1f}  {ocrs[3]:8.1f}  {toomuch}'
                )

    if verbose:
        yield from mv(dwell_time, 1.0)
        #yield from mv(xs.total_points, 1)
        #yield from count([xs], 1)
        #yield from sleep(0.25)
        #xs.table()
        #xs.plot(add=True)
        xs.measure_xrf(doplot=False)
        print(whisper('make a plot with: xs.plot()'))

    yield from mv(dwell_time, 0.5)
    RE.msg_hook = BMM_msg_hook
    print(f'\nfound {description} detector position at ' +
          go_msg(f'{xafs_det.position:5.1f}'))
    #yield from resting_state_plan()
    return xafs_det.position
Ejemplo n.º 26
0
def kickoff():
    st = StatusBase()
    for i in range(20):
        yield from mvr(motor, -1)
        yield from mvr(motor, 1)
    return st
 def tweak(self, val):
     yield from mvr(self.motor, val)
Ejemplo n.º 28
0
    def __grid_scan(self,
                    x_motor,
                    x_start,
                    x_end,
                    xsteps,
                    y_motor,
                    y_start,
                    y_end,
                    ysteps,
                    z_motor,
                    angle,
                    ndaq,
                    record=True):
        logging.debug("Setting up the sequencer for %s daq points", ndaq)
        self.__setup_sequencer(ndaq)

        # Setup the pulse picker
        if pp.mode.get() == 3:
            logging.debug("The pulse picker is already in burst mode")
        else:
            logging.debug("Setting up the pulse picker for burst mode")
            pp.burst(wait=True)

        # Setup the DAQ
        daq.record = record
        daq.configure(events=ndaq)
        bps.configure(daq, events=ndaq)  # For plan introspection

        # Add sequencer, DAQ to detectors for scan
        dets = [daq, seq]

        # Log stuff
        logging.debug("Returning __grid_scan with the following parameters:")
        logging.debug("x_start: {}".format(x_start))
        logging.debug("x_end: {}".format(x_end))
        logging.debug("xsteps: {}".format(xsteps))
        logging.debug("y_start: {}".format(y_start))
        logging.debug("y_end: {}".format(y_end))
        logging.debug("y_steps: {}".format(ysteps))
        logging.debug("angle: {}".format(angle))
        logging.debug("ndaq: {}".format(ndaq))
        logging.debug("record: {}".format(record))
        logging.debug("detectors: {}".format(dets))

        z_start = z_motor.wm()

        x_step_size = (x_end - x_start) / (xsteps - 1)
        logging.debug("X step size: {}".format(x_step_size))
        y_step_size = (y_end - y_start) / (ysteps - 1)
        logging.debug("Y step size: {}".format(y_step_size))
        z_step = self.__comp_z(y_step_size, angle)
        logging.debug("Z step size: {}".format(z_step))
        for i in range(ysteps):
            new_y = y_start + y_step_size * i
            logging.debug("Moving Y to {}".format(new_y))
            yield from bps.mv(y_motor, new_y)
            if i != 0:  # Skip first step; assume focus is fine there
                logging.debug("Moving Z by {}".format(z_step))
                yield from bps.mvr(z_motor, z_step)
            yield from scan(dets, x_motor, x_start, x_end, xsteps)

        # Return to original positions
        yield from bps.mv(x_motor, x_start)
        yield from bps.mv(y_motor, y_start)
        yield from bps.mv(z_motor, z_start)
def gonio_axis_align():
    """
    Center crosshair on pin
    
    Requirements
    ------------
    * Alignment pin mounted and centered. Pin should be aligned in X to within 0.25 of the Mag3 width
    * Governor in SA state
    * LoMag and HiMag Scale and Offset need to be enabled in Proc1
        * XF:17IDC-ES:FMX{Cam:7}Proc1:EnableOffsetScale
        * XF:17IDC-ES:FMX{Cam:8}Proc1:EnableOffsetScale
    """

    # Invert camera image, so dark pin on light image becomes a peak
    cam_7.proc1.scale.put(-1)
    cam_8.proc1.scale.put(-1)

    # High threshold, so AD centroid doesn't interpret background
    cam_8ThresholdOld = cam_8.stats4.centroid_threshold.get()
    cam_8.stats4.centroid_threshold.put(150)
    cam_7ThresholdOld = cam_7.stats4.centroid_threshold.get()
    cam_7.stats4.centroid_threshold.put(150)

    # HiMag
    # Copy ROI2 geometry (HiMag Mag3) to ROI4 and use ROI4 centroid plugin
    cam_8.roi4.min_xyz.min_x.put(cam_8.roi2.min_xyz.min_x.get())
    cam_8.roi4.min_xyz.min_y.put(cam_8.roi2.min_xyz.min_y.get())
    cam_8.roi4.size.x.put(cam_8.roi2.size.x.get() * 0.20)
    cam_8.roi4.size.y.put(cam_8.roi2.size.y.get())
    cam_8.roi4.min_xyz.min_x.put(cam_8.roi2.min_xyz.min_x.get() +
                                 cam_8.roi2.size.x.get() / 2 -
                                 cam_8.roi4.size.x.get() / 2)

    # LoMag
    # Copy ROI2 geometry (LoMag Mag1) to ROI4 and use ROI4 centroid plugin
    cam_7.roi4.min_xyz.min_x.put(cam_7.roi2.min_xyz.min_x.get())
    cam_7.roi4.min_xyz.min_y.put(cam_7.roi2.min_xyz.min_y.get())
    cam_7.roi4.size.x.put(cam_7.roi2.size.x.get() * 0.05)
    cam_7.roi4.size.y.put(cam_7.roi2.size.y.get())
    cam_7.roi4.min_xyz.min_x.put(cam_7.roi2.min_xyz.min_x.get() +
                                 cam_7.roi2.size.x.get() / 2 -
                                 cam_7.roi4.size.x.get() / 2)

    centerPinYHiMag0 = centroid_avg(cam_8.stats4)[1]
    centerPinYLoMag0 = centroid_avg(cam_7.stats4)[1]
    yield from bps.mvr(gonio.o, 180)
    time.sleep(2)
    centerPinYHiMag180 = centroid_avg(cam_8.stats4)[1]
    centerPinYLoMag180 = centroid_avg(cam_7.stats4)[1]
    centerPinYHiMag = (centerPinYHiMag0 + centerPinYHiMag180) / 2
    centerPinYLoMag = (centerPinYLoMag0 + centerPinYLoMag180) / 2

    centerPinOffsYHiMag = centerPinYHiMag - cam_8.roi4.size.y.get() / 2
    centerPinOffsYLoMag = centerPinYLoMag - cam_7.roi4.size.y.get() / 2

    # Correct Mag 3 (cam_8 ROI2)
    cam_8.roi2.min_xyz.min_y.put(cam_8.roi2.min_xyz.min_y.get() +
                                 centerPinOffsYHiMag)
    # Correct Mag 4 (cam_8 ROI1)
    cam_8.roi1.min_xyz.min_y.put(
        cam_8.roi2.min_xyz.min_y.get() +
        (cam_8.roi2.size.y.get() - cam_8.roi1.size.y.get()) / 2)

    # Correct Mag 1 (cam_7 ROI2)
    cam_7.roi2.min_xyz.min_y.put(cam_7.roi2.min_xyz.min_y.get() +
                                 centerPinOffsYLoMag)
    # Correct Mag 2 (cam_7 ROI3)
    cam_7.roi3.min_xyz.min_y.put(
        cam_7.roi2.min_xyz.min_y.get() +
        (cam_7.roi2.size.y.get() - cam_7.roi3.size.y.get()) / 2)

    # De-invert image
    cam_7.proc1.scale.put(-1)
    cam_8.proc1.scale.put(-1)

    # Set thresold to previous value
    cam_8.stats4.centroid_threshold.put(cam_8ThresholdOld)
    cam_7.stats4.centroid_threshold.put(cam_7ThresholdOld)

    return