예제 #1
0
 def dark_current(self):
     print(f'Measuring current offsets for {self.name}, this will take several seconds')
     yield from mv(self.compute_current_offset1,1)
     yield from mv(self.compute_current_offset2,1)
     yield from mv(self.compute_current_offset3,1)
     yield from mv(self.compute_current_offset4,1)
     BMM_log_info('Measured dark current on quadem1')
예제 #2
0
 def set_roi(self, i, el):
     '''Configure an ROI channel i ∈ (1 .. 3) for element el'''
     if Z_number(el) is None:
         self.slots[i - 1] = None
     else:
         self.slots[i - 1] = element_symbol(el)
     BMM_log_info('Set ROI channel %d to %s' % (i, str(self.slots[i - 1])))
예제 #3
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()
예제 #4
0
        def scan_dcmpitch(sgnl):
            line1 = '%s, %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
                    (motor.name, sgnl, start, stop, nsteps, motor.user_readback.get())

            yield from abs_set(user_ns['_locked_dwell_time'], 0.1, wait=True)
            yield from dcm.kill_plan()

            yield from mv(slits3.vsize, 3)
            if sgnl == 'Bicron':
                yield from mv(slitsg.vsize, 5)

            uid = yield from rel_scan(dets, motor, start, stop, nsteps)
            #yield from rel_adaptive_scan(dets, 'I0', motor,
            #                             start=start,
            #                             stop=stop,
            #                             min_step=0.002,
            #                             max_step=0.03,
            #                             target_delta=.15,
            #                             backstep=True)
            t = db[-1].table()
            signal = t[sgnl]
            if choice.lower() == 'com':
                position = com(signal)
                top = t[motor.name][position]
            elif choice.lower() == 'fit':
                pitch = t['dcm_pitch']
                mod = SkewedGaussianModel()
                pars = mod.guess(signal, x=pitch)
                out = mod.fit(signal, pars, x=pitch)
                print(whisper(out.fit_report(min_correl=0)))
                out.plot()
                top = out.params['center'].value
            else:
                position = peak(signal)
                top = t[motor.name][position]

            yield from sleep(3.0)
            yield from abs_set(motor.kill_cmd, 1, wait=True)
            RE.msg_hook = BMM_msg_hook

            BMM_log_info('rocking curve scan: %s\tuid = %s, scan_id = %d' %
                         (line1, uid, user_ns['db'][-1].start['scan_id']))
            yield from mv(motor, top)
            if sgnl == 'Bicron':
                yield from mv(slitsg.vsize, gonio_slit_height)
예제 #5
0
    def cleanup_plan():
        print('Cleaning up after an area scan')
        RE.clear_suspenders()
        if BMMuser.final_log_entry is True:
            BMM_log_info('areascan finished\n\tuid = %s, scan_id = %d' %
                         (db[-1].start['uid'], db[-1].start['scan_id']))
        yield from resting_state_plan()
        RE.msg_hook = BMM_msg_hook

        print('Disabling plot for re-plucking.')
        try:
            cid = BMMuser.fig.canvas.mpl_disconnect(cid)
        except:
            pass
        BMMuser.x = None
        BMMuser.y = None
        BMMuser.motor = None
        BMMuser.motor2 = None
        BMMuser.fig = None
        BMMuser.ax = None
def dark_current():
    shb = user_ns['shb']
    reopen = shb.state.get() == shb.openval
    if reopen:
        print('\nClosing photon shutter')
        yield from shb.close_plan()
    print('Measuring current offsets, this will take several seconds')
    EpicsSignal("XF:06BM-BI{EM:1}EM180:ComputeCurrentOffset1.PROC",
                name='').put(1)
    EpicsSignal("XF:06BM-BI{EM:1}EM180:ComputeCurrentOffset2.PROC",
                name='').put(1)
    EpicsSignal("XF:06BM-BI{EM:1}EM180:ComputeCurrentOffset3.PROC",
                name='').put(1)
    EpicsSignal("XF:06BM-BI{EM:1}EM180:ComputeCurrentOffset4.PROC",
                name='').put(1)
    yield from sleep(3)
    BMM_log_info('Measured dark current on quadem1')
    if reopen:
        print('Opening photon shutter')
        yield from shb.open_plan()
        print('You are ready to measure!\n')
    def dark_current(self):
        reopen = shb.state.get() == shb.openval
        if reopen:
            print('\nClosing photon shutter')
            yield from shb.close_plan()
        print('Measuring current offsets, this will take several seconds')

        ######################################################################
        # from Pete (email Feb 7, 2020):                                     #
        #   caput XF:06BM-BI{EM:3}EM180:CalibrationMode 1                    #
        #   caput XF:06BM-BI{EM:3}EM180:CopyADCOffsets.PROC 1                #
        #   caput XF:06BM-BI{EM:3}EM180:CalibrationMode 0                    #
        # ADC offset values should be around 3800, might need to hit Compute #
        # buttons to get lovely low dark current values                      #
        ######################################################################

        ## this almost works....
        self.current_offsets.ch1.put(0.0)
        self.current_offsets.ch2.put(0.0)
        self.calibration_mode.put(1)
        yield from sleep(0.5)
        self.copy_adc_offsets.put(1)
        yield from sleep(0.5)
        self.calibration_mode.put(0)
        yield from sleep(0.5)
        self.compute_current_offset1.put(1)
        self.compute_current_offset1.put(2)
        # EpicsSignal("XF:06BM-BI{EM:3}EM180:CalibrationMode", name='').put(1)
        # EpicsSignal("XF:06BM-BI{EM:3}EM180:CopyADCOffsets.PROC", name='').put(1)
        # EpicsSignal("XF:06BM-BI{EM:3}EM180:CalibrationMode", name='').put(0)
        # EpicsSignal("XF:06BM-BI{EM:1}EM180:ComputeCurrentOffset1.PROC", name='').put(1)
        # EpicsSignal("XF:06BM-BI{EM:1}EM180:ComputeCurrentOffset2.PROC", name='').put(1)
        yield from sleep(0.5)
        print(self.sigma1.get(), self.sigma2.get())
        BMM_log_info('Measured dark current on dualio ion chamber')
        if reopen:
            print('Opening photon shutter')
            yield from shb.open_plan()
            print('You are ready to measure!\n')
예제 #8
0
        def scan_slit(slp):

            #if slit_height < 0.5:
            #    yield from mv(slits3.vsize, 0.5)
            
            yield from mv(quadem1.averaging_time, 0.1)
            yield from mv(motor.velocity, 0.4)
            yield from mv(motor.kill_cmd, 1)

            uid = yield from rel_scan([quadem1], motor, start, stop, nsteps, md={'plan_name' : f'rel_scan linescan {motor.name} I0'})

            user_ns['RE'].msg_hook = BMM_msg_hook
            BMM_log_info('slit height scan: %s\tuid = %s, scan_id = %d' %
                         (line1, uid, user_ns['db'][-1].start['scan_id']))
            if move:
                t  = user_ns['db'][-1].table()
                signal = t['I0']
                #if get_mode() in ('A', 'B', 'C'):
                #    position = com(signal)
                #else:
                position = peak(signal)
                top = t[motor.name][position]
                
                yield from sleep(slp)
                yield from mv(motor.kill_cmd, 1)
                yield from sleep(slp)
                yield from mv(motor, top)

            else:
                action = input('\n' + bold_msg('Pluck motor position from the plot? [Y/n then Enter] '))
                if action.lower() == 'n' or action.lower() == 'q':
                    return(yield from null())
                yield from sleep(slp)
                yield from mv(motor.kill_cmd, 1)
                #yield from mv(motor.inpos, 1)
                yield from sleep(slp)
                yield from move_after_scan(motor)
            yield from mv(quadem1.averaging_time, 0.5)
예제 #9
0
    def main_plan(detector, axis, start, stop, nsteps, pluck, force):
        (ok, text) = BMM_clear_to_start()
        if force is False and ok is False:
            print(error_msg(text))
            yield from null()
            return

        detector, axis = ls_backwards_compatibility(detector, axis)
        # print('detector is: ' + str(detector))
        # print('axis is: ' + str(axis))
        # return(yield from null())

        RE.msg_hook = None
        ## sanitize input and set thismotor to an actual motor
        if type(axis) is str: axis = axis.lower()
        detector = detector.capitalize()

        ## sanity checks on axis
        if axis not in motor_nicknames.keys() and 'EpicsMotor' not in str(type(axis)) \
           and 'PseudoSingle' not in str(type(axis)) and 'WheelMotor' not in str(type(axis)):
            print(
                error_msg('\n*** %s is not a linescan motor (%s)\n' %
                          (axis, str.join(', ', motor_nicknames.keys()))))
            yield from null()
            return

        if 'EpicsMotor' in str(type(axis)):
            thismotor = axis
        elif 'PseudoSingle' in str(type(axis)):
            thismotor = axis
        elif 'WheelMotor' in str(type(axis)):
            thismotor = axis
        else:  # presume it's an xafs_XXXX motor
            thismotor = motor_nicknames[axis]

        current = thismotor.position
        if current + start < thismotor.limits[0]:
            print(
                error_msg(
                    f'These scan parameters will take {thismotor.name} outside it\'s lower limit of {thismotor.limits[0]}'
                ))
            print(whisper(f'(starting position = {thismotor.position})'))
            return (yield from null())
        if current + stop > thismotor.limits[1]:
            print(
                error_msg(
                    f'These scan parameters will take {thismotor.name} outside it\'s upper limit of {thismotor.limits[1]}'
                ))
            print(whisper(f'(starting position = {thismotor.position})'))
            return (yield from null())

        BMMuser.motor = thismotor

        ## sanity checks on detector
        if detector not in ('It', 'If', 'I0', 'Iy', 'Ir', 'Both', 'Bicron',
                            'Ia', 'Ib', 'Dualio', 'Xs', 'Xs1'):
            print(
                error_msg(
                    '\n*** %s is not a linescan measurement (%s)\n' %
                    (detector,
                     'it, if, i0, iy, ir, both, bicron, dualio, xs, xs1')))
            yield from null()
            return

        yield from abs_set(user_ns['_locked_dwell_time'], inttime, wait=True)
        if detector == 'Xs':
            yield from mv(xs.settings.acquire_time, inttime)
            yield from mv(xs.total_points, nsteps)
        dets = [
            user_ns['quadem1'],
        ]
        if user_ns['with_dualem']:
            dualio = user_ns['dualio']
        denominator = ''
        detname = ''

        ## func is an anonymous function, built on the fly, for feeding to DerivedPlot
        if detector == 'It':
            denominator = ' / I0'
            detname = 'transmission'
            func = lambda doc: (doc['data'][thismotor.name], doc['data']['It']
                                / doc['data']['I0'])
        elif detector == 'Ia' and dualio is not None:
            dets.append(dualio)
            detname = 'Ia'
            func = lambda doc: (doc['data'][thismotor.name], doc['data']['Ia'])
        elif detector == 'Ib' and dualio is not None:
            dets.append(dualio)
            detname = 'Ib'
            func = lambda doc: (doc['data'][thismotor.name], doc['data']['Ib'])
        elif detector == 'Ir':
            #denominator = ' / It'
            detname = 'reference'
            #func = lambda doc: (doc['data'][thismotor.name], doc['data']['Ir']/doc['data']['It'])
            func = lambda doc: (doc['data'][thismotor.name], doc['data']['Ir'])
        elif detector == 'I0':
            detname = 'I0'
            func = lambda doc: (doc['data'][thismotor.name], doc['data']['I0'])
        elif detector == 'Bicron':
            dets.append(user_ns['vor'])
            detname = 'Bicron'
            func = lambda doc: (doc['data'][thismotor.name], doc['data'][
                'Bicron'])
        elif detector == 'Iy':
            denominator = ' / I0'
            detname = 'electron yield'
            func = lambda doc: (doc['data'][thismotor.name], doc['data']['Iy']
                                / doc['data']['I0'])
        elif detector == 'If':
            dets.append(user_ns['vor'])
            denominator = ' / I0'
            detname = 'fluorescence'
            func = lambda doc: (doc['data'][thismotor.name], (doc['data'][
                BMMuser.dtc1] + doc['data'][BMMuser.dtc2] + doc['data'][
                    BMMuser.dtc3] + doc['data'][BMMuser.dtc4]) / doc['data'][
                        'I0'])
        elif detector == 'Xs':
            dets.append(user_ns['xs'])
            denominator = ' / I0'
            detname = 'fluorescence'
            func = lambda doc: (doc['data'][thismotor.name],
                                (doc['data'][BMMuser.xs1] + doc['data'][
                                    BMMuser.xs2] + doc['data'][BMMuser.xs3] +
                                 doc['data'][BMMuser.xs4]) / doc['data']['I0'])
            yield from mv(xs.total_points,
                          nsteps)  # Xspress3 demands that this be set up front

        elif detector == 'Xs1':
            dets.append(user_ns['xs'])
            denominator = ' / I0'
            detname = 'fluorescence'
            func = lambda doc: (doc['data'][thismotor.name], doc['data'][
                BMMuser.xs8] / doc['data']['I0'])
            yield from mv(xs1.total_points,
                          nsteps)  # Xspress3 demands that this be set up front

        elif detector == 'Dualio':
            dets.append(dualio)
            funcia = lambda doc: (doc['data'][thismotor.name], doc['data']['Ia'
                                                                           ])
            funcib = lambda doc: (doc['data'][thismotor.name], doc['data']['Ib'
                                                                           ])

        ## need a "Both" for trans + xs !!!!!!!!!!
        elif detector == 'Both':
            dets.append(user_ns['vor'])
            functr = lambda doc: (doc['data'][thismotor.name], doc['data'][
                'It'] / doc['data']['I0'])
            funcfl = lambda doc: (doc['data'][thismotor.name], (doc['data'][
                BMMuser.dtc1] + doc['data'][BMMuser.dtc2] + doc['data'][
                    BMMuser.dtc3] + doc['data'][BMMuser.dtc4]) / doc['data'][
                        'I0'])
        ## and this is the appropriate way to plot this linescan

        #abs_set(_locked_dwell_time, 0.5)
        if detector == 'Both':
            plot = [
                DerivedPlot(funcfl,
                            xlabel=thismotor.name,
                            ylabel='If/I0',
                            title='fluorescence vs. %s' % thismotor.name),
                DerivedPlot(functr,
                            xlabel=thismotor.name,
                            ylabel='It/I0',
                            title='transmission vs. %s' % thismotor.name)
            ]
        elif detector == 'Dualio':
            plot = [
                DerivedPlot(funcia,
                            xlabel=thismotor.name,
                            ylabel='Ia/I0',
                            title='Ia vs. %s' % thismotor.name),
                DerivedPlot(funcib,
                            xlabel=thismotor.name,
                            ylabel='Ib/I0',
                            title='Ib vs. %s' % thismotor.name)
            ]
        else:
            plot = DerivedPlot(func,
                               xlabel=thismotor.name,
                               ylabel=detector + denominator,
                               title='%s vs. %s' % (detname, thismotor.name))
        if 'PseudoSingle' in str(type(axis)):
            value = thismotor.readback.get()
        else:
            value = thismotor.user_readback.get()
        line1 = '%s, %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
                (thismotor.name, detector, start, stop, nsteps, value)
        ##BMM_suspenders()            # engage suspenders

        thismd = dict()
        thismd['XDI'] = dict()
        thismd['XDI']['Facility'] = dict()
        thismd['XDI']['Facility']['GUP'] = BMMuser.gup
        thismd['XDI']['Facility']['SAF'] = BMMuser.saf

        rkvs.set('BMM:scan:type', 'line')
        rkvs.set('BMM:scan:starttime',
                 str(datetime.datetime.timestamp(datetime.datetime.now())))
        rkvs.set('BMM:scan:estimated', 0)

        @subs_decorator(plot)
        #@subs_decorator(src.callback)
        def scan_xafs_motor(dets, motor, start, stop, nsteps):
            uid = yield from rel_scan(dets,
                                      motor,
                                      start,
                                      stop,
                                      nsteps,
                                      md={
                                          **thismd,
                                          **md
                                      })
            return uid

        uid = yield from scan_xafs_motor(dets, thismotor, start, stop, nsteps)
        #global mytable
        #run = src.retrieve()
        #mytable = run.primary.read().to_dataframe()
        BMM_log_info('linescan: %s\tuid = %s, scan_id = %d' %
                     (line1, uid, user_ns['db'][-1].start['scan_id']))
        if pluck is True:
            action = input('\n' + bold_msg(
                'Pluck motor position from the plot? [Y/n then Enter] '))
            if action.lower() == 'n' or action.lower() == 'q':
                return (yield from null())
            yield from move_after_scan(thismotor)
예제 #10
0
 def clear_encoder_loss(self):
     self.clear_enc_lss.put(1)
     self.enable()
     BMM_log_info('clearing encoder loss for %s' % self.name)
예제 #11
0
    def main_plan(detector, slow, startslow, stopslow, nslow, fast, startfast,
                  stopfast, nfast, pluck, force, dwell, md):
        (ok, text) = BMM_clear_to_start()
        if force is False and ok is False:
            print(error_msg(text))
            BMMuser.final_log_entry = False
            yield from null()
            return

        user_ns['RE'].msg_hook = None

        ## sanity checks on slow axis
        if type(slow) is str: slow = slow.lower()
        if slow not in motor_nicknames.keys() and 'EpicsMotor' not in str(
                type(slow)) and 'PseudoSingle' not in str(type(slow)):
            print(
                error_msg('\n*** %s is not an areascan motor (%s)\n' %
                          (slow, str.join(', ', motor_nicknames.keys()))))
            BMMuser.final_log_entry = False
            yield from null()
            return
        if slow in motor_nicknames.keys():
            slow = motor_nicknames[slow]

        ## sanity checks on fast axis
        if type(fast) is str: fast = fast.lower()
        if fast not in motor_nicknames.keys() and 'EpicsMotor' not in str(
                type(fast)) and 'PseudoSingle' not in str(type(fast)):
            print(
                error_msg('\n*** %s is not an areascan motor (%s)\n' %
                          (fast, str.join(', ', motor_nicknames.keys()))))
            BMMuser.final_log_entry = False
            yield from null()
            return
        if fast in motor_nicknames.keys():
            fast = motor_nicknames[fast]

        detector = detector.capitalize()
        yield from mv(_locked_dwell_time, dwell)
        dets = [
            quadem1,
        ]

        if with_xspress3 and detector == 'If':
            detector = 'Xs'

        if detector == 'If':
            dets.append(vor)
            detector = 'ROI1'
        if detector.lower() == 'xs':
            dets.append(xs)
            detector = BMMuser.xs1
            yield from mv(xs.total_points, nslow * nfast)

        if 'PseudoSingle' in str(type(slow)):
            valueslow = slow.readback.get()
        else:
            valueslow = slow.user_readback.get()
        line1 = 'slow motor: %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
            (slow.name, startslow, stopslow, nslow, valueslow)

        if 'PseudoSingle' in str(type(fast)):
            valuefast = fast.readback.get()
        else:
            valuefast = fast.user_readback.get()
        line2 = 'fast motor: %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
            (fast.name, startfast, stopfast, nfast, valuefast)

        npoints = nfast * nslow
        estimate = int(npoints * (dwell + 0.7))

        # extent = (
        #     valuefast + startfast,
        #     valueslow + startslow,
        #     valuefast + stopfast,
        #     valueslow + stopslow,
        # )
        # extent = (
        #     0,
        #     nfast-1,
        #     0,
        #     nslow-1
        # )
        # print(extent)
        # return(yield from null())

        # areaplot = LiveScatter(fast.name, slow.name, detector,
        #                        xlim=(startfast, stopfast), ylim=(startslow, stopslow))

        close_all_plots()

        areaplot = LiveGrid(
            (nslow, nfast),
            detector,  #aspect='equal', #aspect=float(nslow/nfast), extent=extent,
            xlabel='fast motor: %s' % fast.name,
            ylabel='slow motor: %s' % slow.name)
        #BMMuser.ax     = areaplot.ax
        #BMMuser.fig    = areaplot.ax.figure
        BMMuser.motor = fast
        BMMuser.motor2 = slow
        #BMMuser.fig.canvas.mpl_connect('close_event', handle_close)

        thismd = dict()
        thismd['XDI'] = dict()
        thismd['XDI']['Facility'] = dict()
        thismd['XDI']['Facility']['GUP'] = BMMuser.gup
        thismd['XDI']['Facility']['SAF'] = BMMuser.saf
        thismd['slow_motor'] = slow.name
        thismd['fast_motor'] = fast.name

        report(
            f'Starting areascan at x,y = {fast.position:.3f}, {slow.position:.3f}',
            level='bold',
            slack=True)

        ## engage suspenders right before starting scan sequence
        if force is False: BMM_suspenders()

        @subs_decorator(areaplot)
        #@subs_decorator(src.callback)
        def make_areascan(dets,
                          slow,
                          startslow,
                          stopslow,
                          nslow,
                          fast,
                          startfast,
                          stopfast,
                          nfast,
                          snake=False):
            BMMuser.final_log_entry = False
            uid = yield from grid_scan(
                dets,
                slow,
                startslow,
                stopslow,
                nslow,
                fast,
                startfast,
                stopfast,
                nfast,
                snake,
                md={
                    'plan_name':
                    f'grid_scan measurement {slow.name} {fast.name} {detector}'
                })
            BMMuser.final_log_entry = True
            return uid

        rkvs.set('BMM:scan:type', 'area')
        rkvs.set('BMM:scan:starttime',
                 str(datetime.datetime.timestamp(datetime.datetime.now())))
        rkvs.set('BMM:scan:estimated', estimate)

        BMM_log_info('begin areascan observing: %s\n%s%s' %
                     (detector, line1, line2))
        uid = yield from make_areascan(dets,
                                       slow,
                                       valueslow + startslow,
                                       valueslow + stopslow,
                                       nslow,
                                       fast,
                                       valuefast + startfast,
                                       valuefast + stopfast,
                                       nfast,
                                       snake=False)

        if pluck is True:

            close_all_plots()
            thismap = user_ns['db'].v2[uid]
            x = numpy.array(thismap.primary.read()[fast.name])
            y = numpy.array(thismap.primary.read()[slow.name])
            z=numpy.array(thismap.primary.read()[BMMuser.xs1]) +\
                numpy.array(thismap.primary.read()[BMMuser.xs2]) +\
                numpy.array(thismap.primary.read()[BMMuser.xs3]) +\
                numpy.array(thismap.primary.read()[BMMuser.xs4])
            z = z.reshape(nfast, nslow)

            # grabbing the first nfast elements of x and every
            # nslow-th element of y is more reliable than
            # numpy.unique due to float &/or motor precision issues

            #plt.title(f'Energy = {energies["below"]}')
            plt.xlabel(f'fast axis ({fast.name}) position (mm)')
            plt.ylabel(f'slow axis ({slow.name}) position (mm)')
            plt.gca().invert_yaxis()  # plot an xafs_x/xafs_y plot upright
            plt.contourf(x[:nfast], y[::nslow], z, cmap=plt.cm.viridis)
            plt.colorbar()
            plt.show()
            fname = os.path.join(BMMuser.folder, 'map-' + now() + '.png')
            plt.savefig(fname)
            try:
                img_to_slack(fname)
            except:
                post_to_slack('failed to post image: {fname}')
                pass

            BMMuser.x = None
            figs = list(map(plt.figure, plt.get_fignums()))
            canvas = figs[0].canvas
            action = input('\n' + bold_msg(
                'Pluck motor position from the plot? [Y/n then Enter] '))
            if action.lower() == 'n' or action.lower() == 'q':
                return (yield from null())
            print(
                'Single click the left mouse button on the plot to pluck a point...'
            )
            cid = canvas.mpl_connect(
                'button_press_event',
                interpret_click)  # see 65-derivedplot.py and
            while BMMuser.x is None:  #  https://matplotlib.org/users/event_handling.html
                yield from sleep(0.5)

            # print('Converting plot coordinates to real coordinates...')
            # begin = valuefast + startfast
            # stepsize = (stopfast - startfast) / (nfast - 1)
            # pointfast = begin + stepsize * BMMuser.x
            # #print(BMMuser.x, pointfast)

            # begin = valueslow + startslow
            # stepsize = (stopslow - startslow) / (nslow - 1)
            # pointslow = begin + stepsize * BMMuser.y
            # #print(BMMuser.y, pointslow)

            # print('That translates to x=%.3f, y=%.3f' % (pointfast, pointslow))
            yield from mv(fast, BMMuser.x, slow, BMMuser.y)
            report(
                f'Moved to position x,y = {fast.position:.3f}, {slow.position:.3f}',
                level='bold',
                slack=True)
예제 #12
0
def change_mode(mode=None,
                prompt=True,
                edge=None,
                reference=None,
                bender=True):
    '''Move the photon delivery system to a new mode. 
     A: focused at XAS end station, energy > 8000
     B: focused at XAS end station, energy < 6000
     C: focused at XAS end station, 6000 < energy < 8000
     D: unfocused, energy > 8000
     E: unfocused, 6000 < energy < 8000
     F: unfocused, energy < 8000
     XRD: focused at XRD end station, energy > 8000
     '''
    BMMuser, RE, dcm, dm3_bct, slits3 = user_ns['BMMuser'], user_ns[
        'RE'], user_ns['dcm'], user_ns['dm3_bct'], user_ns['slits3']
    xafs_table, m3, m2, m2_bender, xafs_ref = user_ns['xafs_table'], user_ns[
        'm3'], user_ns['m2'], user_ns['m2_bender'], user_ns['xafs_ref']
    if mode is None:
        print('No mode specified')
        return (yield from null())

    mode = mode.upper()
    if mode not in ('A', 'B', 'C', 'D', 'E', 'F', 'XRD'):
        print('%s is not a mode' % mode)
        return (yield from null())
    current_mode = get_mode()

    # crude hack around a problem I don't understand
    if dm3_bct.hlm.get() < 55 or dm3_bct.llm.get() > -55:
        dm3_bct.llm.put(-60)
        dm3_bct.hlm.put(60)

    if pds_motors_ready() is False:
        print(
            error_msg(
                '\nOne or more motors are showing amplifier faults.\nToggle the correct kill switch, then re-enable the faulted motor.'
            ))
        return (yield from null())

    ######################################################################
    # this is a tool for verifying a macro.  this replaces an xafs scan  #
    # with a sleep, allowing the user to easily map out motor motions in #
    # a macro                                                            #
    if BMMuser.macro_dryrun:
        print(
            info_msg(
                '\nBMMuser.macro_dryrun is True.  Sleeping for %.1f seconds rather than changing to mode %s.\n'
                % (BMMuser.macro_sleep, mode)))
        countdown(BMMuser.macro_sleep)
        return (yield from null())
    ######################################################################

    if mode == 'B':
        action = input(
            "You are entering Mode B -- focused beam below 6 keV is not properly configured at BMM. Continue? [y/N then Enter] "
        )
        if action.lower() != 'y':
            return (yield from null())

    if mode == 'A':
        description = 'focused, >8 keV'
    elif mode == 'B':
        description = 'focused, <6 keV'
    elif mode == 'C':
        description = 'focused, 6 to 8 keV'
    elif mode == 'D':
        description = 'unfocused, >8 keV'
    elif mode == 'E':
        description = 'unfocused, 6 to 8 keV'
    elif mode == 'F':
        description = 'unfocused, <6 keV'
    elif mode == 'XRD':
        description = 'focused at goniometer, >8 keV'
        print('Moving to mode %s (%s)' % (mode, description))
    if prompt:
        action = input("Begin moving motors? [Y/n then Enter] ")
        if action.lower() == 'q' or action.lower() == 'n':
            return (yield from null())

    RE.msg_hook = None
    BMM_log_info('Changing photon delivery system to mode %s' % mode)

    base = [
        dm3_bct,
        float(MODEDATA['dm3_bct'][mode]),
        xafs_table.yu,
        float(MODEDATA['xafs_yu'][mode]),
        xafs_table.ydo,
        float(MODEDATA['xafs_ydo'][mode]),
        xafs_table.ydi,
        float(MODEDATA['xafs_ydi'][mode]),
        m3.yu,
        float(MODEDATA['m3_yu'][mode]),
        m3.ydo,
        float(MODEDATA['m3_ydo'][mode]),
        m3.ydi,
        float(MODEDATA['m3_ydi'][mode]),
        m3.xu,
        float(MODEDATA['m3_xu'][mode]),
        m3.xd,
        float(MODEDATA['m3_xd'][mode]),
    ]
    if reference is not None:
        #base.extend([xafs_linxs, foils.position(reference.capitalize())])
        base.extend(
            [xafs_ref,
             xafs_ref.position_of_slot(reference.capitalize())])
    if edge is not None:
        #dcm_bragg.clear_encoder_loss()
        base.extend([dcm.energy, edge])
    # if mode in ('D', 'E', 'F'):
    #      base.extend([slits3.hcenter, 2])
    # else:
    #      base.extend([slits3.hcenter, 0])

    ###################################################################
    # check for amplifier faults on the motors, return without moving #
    # anything if any are found                                       #
    ###################################################################
    motors_ready = True
    problem_motors = list()
    for m in base[::2]:
        try:  # skip non-FMBO motors, which do not have the amfe or amfae attributes
            if m.amfe.get() == 1 or m.amfae.get() == 1:
                motors_ready = False
                problem_motors.append(m.name)
        except:
            continue
    if motors_ready is False:
        BMMuser.motor_fault = ', '.join(problem_motors)
        return (yield from null())

    ##########################
    # do the motor movements #
    ##########################
    yield from dcm.kill_plan()
    if dm3_bct.ampen.get() == 0:
        yield from mv(dm3_bct.enable_cmd, 1)
    #yield from mv(dm3_bct.kill_cmd, 1) # need to explicitly kill this before
    # starting a move, it is one of the
    # motors that reports MOVN=1 even when
    # still
    yield from sleep(0.2)
    yield from mv(dm3_bct.kill_cmd, 1)

    if mode in ('D', 'E', 'F') and current_mode in ('D', 'E', 'F'):
        yield from mv(*base)
    elif mode in ('A', 'B',
                  'C') and current_mode in ('A', 'B',
                                            'C'):  # no need to move M2
        yield from mv(*base)
    else:
        if bender is True:
            yield from mv(m2_bender.kill_cmd, 1)
            if mode == 'XRD':
                if abs(
                        m2_bender.user_readback.get() - BMMuser.bender_xrd
                ) > BMMuser.bender_margin:  # give some wiggle room for having
                    base.extend([m2_bender, BMMuser.bender_xrd
                                 ])  # recently adjusted the bend
            elif mode in ('A', 'B', 'C'):
                if abs(m2_bender.user_readback.get() -
                       BMMuser.bender_xas) > BMMuser.bender_margin:
                    base.extend([m2_bender, BMMuser.bender_xas])

        base.extend([m2.yu, float(MODEDATA['m2_yu'][mode])])
        base.extend([m2.ydo, float(MODEDATA['m2_ydo'][mode])])
        base.extend([m2.ydi, float(MODEDATA['m2_ydi'][mode])])
        yield from mv(*base)

    yield from sleep(2.0)
    yield from mv(m2_bender.kill_cmd, 1)
    yield from mv(dm3_bct.kill_cmd, 1)
    yield from m2.kill_jacks()
    yield from m3.kill_jacks()

    BMMuser.pds_mode = mode
    RE.msg_hook = BMM_msg_hook
    BMM_log_info(motor_status())
예제 #13
0
def change_xtals(xtal=None):
    '''Move between the Si(111) and Si(311) monochromators, also moving
     2nd crystal pitch and roll to approximate positions.  Then do a
     rocking curve scan.
     '''
    if xtal is None:
        print('No crystal set specified')
        return (yield from null())

    (ok, text) = BMM_clear_to_start()
    if ok == 0:
        print(error_msg(text))
        yield from null()
        return

    BMMuser, RE, dcm, dm3_bct = user_ns['BMMuser'], user_ns['RE'], user_ns[
        'dcm'], user_ns['dm3_bct']
    dcm_pitch, dcm_roll, dcm_x = user_ns['dcm_pitch'], user_ns[
        'dcm_roll'], user_ns['dcm_x']

    if '111' in xtal:
        xtal = 'Si(111)'
    if '311' in xtal:
        xtal = 'Si(311)'

    if xtal not in ('Si(111)', 'Si(311)'):
        print('%s is not a crytsal set' % xtal)
        return (yield from null())

    ######################################################################
    # this is a tool for verifying a macro.  this replaces an xafs scan  #
    # with a sleep, allowing the user to easily map out motor motions in #
    # a macro                                                            #
    if BMMuser.macro_dryrun:
        print(
            info_msg(
                '\nBMMuser.macro_dryrun is True.  Sleeping for %.1f seconds rather than changing to the %s crystal.\n'
                % (BMMuser.macro_sleep, xtal)))
        countdown(BMMuser.macro_sleep)
        return (yield from null())
    ######################################################################

    print('Moving to %s crystals' % xtal)
    action = input('Begin moving motors? [Y/n then Enter] ')
    if action.lower() == 'q' or action.lower() == 'n':
        yield from null()
        return

    current_energy = dcm.energy.readback.get()
    start = time.time()

    RE.msg_hook = None
    BMM_log_info('Moving to the %s crystals' % xtal)
    yield from mv(dcm_pitch.kill_cmd, 1)
    yield from mv(dcm_roll.kill_cmd, 1)
    if xtal is 'Si(111)':
        yield from mv(dcm_pitch, 4.1, dcm_roll, -6.26, dcm_x, 0.5)
        #dcm._crystal = '111'
        dcm.set_crystal('111')  # set d-spacing and bragg offset
    elif xtal is 'Si(311)':
        yield from mv(dcm_pitch, 2.28, dcm_roll, -23.86, dcm_x, 65.3)
        #dcm._crystal = '311'
        dcm.set_crystal('311')  # set d-spacing and bragg offset

    yield from sleep(2.0)
    yield from mv(dcm_roll.kill_cmd, 1)

    print('Returning to %.1f eV' % current_energy)
    yield from mv(dcm.energy, current_energy)

    print('Performing a rocking curve scan')
    yield from mv(dcm_pitch.kill_cmd, 1)
    yield from mv(dcm_pitch, approximate_pitch(current_energy))
    yield from sleep(1)
    yield from mv(dcm_pitch.kill_cmd, 1)
    yield from rocking_curve()
    yield from sleep(2.0)
    yield from mv(dcm_pitch.kill_cmd, 1)
    RE.msg_hook = BMM_msg_hook
    BMM_log_info(motor_status())
    close_last_plot()
    end = time.time()
    print('\n\nTime elapsed: %.1f min' % ((end - start) / 60))
예제 #14
0
    def main_plan(inifile, force, **kwargs):
        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## read and check INI content
        orig = inifile
        if not os.path.isfile(inifile):
            inifile = DATA + inifile
            if not os.path.isfile(inifile):
                print(
                    warning_msg('\n%s does not exist!  Bailing out....\n' %
                                orig))
                return (orig, -1)
        print(bold_msg('reading ini file: %s' % inifile))
        (p, f) = scan_metadata(inifile=inifile, **kwargs)
        if not any(
                p):  # scan_metadata returned having printed an error message
            return (yield from null())
        #if not os.path.isdir(p['folder']):
        #    print(error_msg('\n%s is not a folder\n' % p['folder']))
        #    return(yield from null())

        detector = 'It'
        if 'trans' in p['mode']:
            detector = 'It'
        elif 'fluo' in p['mode']:
            detector = 'If'

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## verify output file name won't be overwritten
        outfile = '%s.%3.3d' % (os.path.join(p['folder'],
                                             p['filename']), p['start'])
        if os.path.isfile(outfile):
            print(error_msg('%s already exists!  Bailing out....' % outfile))
            return (yield from null())

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## prompt user and verify that we are clear to start
        text = '\n'
        for k in ('folder', 'filename', 'experimenters', 'e0', 'npoints',
                  'dwell', 'delay', 'sample', 'prep', 'comment', 'mode',
                  'snapshots'):
            text = text + '      %-13s : %-50s\n' % (k, p[k])
        if BMMuser.prompt:
            boxedtext('How does this look?',
                      text + '\n      %-13s : %-50s\n' %
                      ('output file', outfile),
                      'green',
                      width=len(outfile) + 25)  # see 05-functions
            action = input("\nBegin time scan? [Y/n then Enter] ")
            if action.lower() == 'q' or action.lower() == 'n':
                return (yield from null())

        (ok, ctstext) = BMM_clear_to_start()
        if force is False and ok is False:
            print(error_msg(ctstext))
            yield from null()
            return

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        # organize metadata for injection into database and XDI output
        print(bold_msg('gathering metadata'))
        md = bmm_metadata(
            measurement=p['mode'],
            experimenters=p['experimenters'],
            edge=p['edge'],
            element=p['element'],
            edge_energy=p['e0'],
            direction=0,
            scantype='fixed',
            channelcut=p['channelcut'],
            mono='Si(%s)' % dcm._crystal,
            i0_gas='N2',  #\
            it_gas='N2',  # > these three need to go into INI file
            ir_gas='N2',  #/
            sample=p['sample'],
            prep=p['prep'],
            stoichiometry=None,
            mode=p['mode'],
            comment=p['comment'],
        )
        del (md['XDI']['Element']['edge'])
        del (md['XDI']['Element']['symbol'])
        md['XDI']['Column']['01'] = 'time seconds'
        md['XDI']['Column']['02'] = md.copy()['XDI']['Column']['03']
        md['XDI']['Column']['03'] = md.copy()['XDI']['Column']['04']
        md['XDI']['Column']['04'] = md['XDI']['Column']['05']
        del (md['XDI']['Column']['05'])
        md['_kind'] = 'sead'

        rightnow = metadata_at_this_moment()  # see 62-metadata.py
        for family in rightnow.keys():  # transfer rightnow to md
            if type(rightnow[family]) is dict:
                if family not in md:
                    md[family] = dict()
                for k in rightnow[family].keys():
                    md[family][k] = rightnow[family][k]
        xdi = {'XDI': md}

        BMM_log_info(
            'Starting single-energy absorption detection time scan using\n%s:\n%s\nCommand line arguments = %s\nMoving to measurement energy: %.1f eV'
            % (inifile, text, str(kwargs), p['e0']))

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## move to the energy specified in the INI file
        print(bold_msg('Moving to measurement energy: %.1f eV' % p['e0']))
        dcm.mode = 'fixed'
        yield from mv(dcm.energy, p['e0'])

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## snap photos
        if p['snapshots']:
            image = os.path.join(
                p['folder'], 'snapshots',
                "%s_XASwebcam_%s.jpg" % (p['filename'], now()))
            snap('XAS', filename=image)
            image = os.path.join(p['folder'], 'snapshots',
                                 "%s_analog_%s.jpg" % (p['filename'], now()))
            snap('analog', filename=image)

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## engage suspenders right before starting measurement
        if not force: BMM_suspenders()

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## perform the actual time scan
        uid = yield from timescan(detector,
                                  p['npoints'],
                                  p['dwell'],
                                  p['delay'],
                                  force=force,
                                  md={**xdi})

        ## --*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
        ## write the output file
        header = db[uid]
        write_XDI(outfile, header)  # yield from ?
        report('wrote time scan to %s' % outfile)
예제 #15
0
def timescan(detector, readings, dwell, delay, force=False, md={}):
    '''
    Generic timescan plan.

    Parameters
    ----------
    detector : str
        detector to display -- if, it, ir, or i0
    readings : int
        number of measurements to make
    dwell : float
        dwell time in seconds for each measurement
    delay : float
        pause in seconds between measurements
    outfile :  str
        data file name (relative to DATA), False to not write
    force : bool
        flag for forcing a scan even if not clear to start

    This does not write an ASCII data file, but it does make a log entry.

    Use the ts2dat() function to extract the linescan from the
    database and write it to a file.

    Examples
       
    >>> RE(timescan('it', 100, 0.5))

    '''

    RE, BMMuser, quadem1, _locked_dwell_time = user_ns['RE'], user_ns[
        'BMMuser'], user_ns['quadem1'], user_ns['_locked_dwell_time']
    rkvs = user_ns['rkvs']
    ######################################################################
    # this is a tool for verifying a macro.  this replaces an xafs scan  #
    # with a sleep, allowing the user to easily map out motor motions in #
    # a macro                                                            #
    if BMMuser.macro_dryrun:
        print(
            info_msg(
                '\nBMMuser.macro_dryrun is True.  Sleeping for %.1f seconds rather than running a time scan.\n'
                % BMMuser.macro_sleep))
        countdown(BMMuser.macro_sleep)
        return (yield from null())
    ######################################################################

    (ok, text) = BMM_clear_to_start()
    if force is False and ok is False:
        print(error_msg(text))
        yield from null()
        return

    RE.msg_hook = None
    ## sanitize and sanity checks on detector
    detector = detector.capitalize()
    if detector not in ('It', 'If', 'I0', 'Iy',
                        'Ir') and 'Dtc' not in detector:
        print(
            error_msg('\n*** %s is not a timescan measurement (%s)\n' %
                      (detector, 'it, if, i0, iy, ir')))
        yield from null()
        return

    yield from mv(_locked_dwell_time, dwell)
    dets = [
        quadem1,
    ]
    denominator = ''

    epoch_offset = pandas.Timestamp.now(tz='UTC').value / 10**9
    ## func is an anonymous function, built on the fly, for feeding to DerivedPlot
    if detector == 'It':
        denominator = ' / I0'
        func = lambda doc: (doc['time'] - epoch_offset, doc['data']['It'] /
                            doc['data']['I0'])
    elif detector == 'Ir':
        denominator = ' / It'
        func = lambda doc: (doc['time'] - epoch_offset, doc['data']['Ir'] /
                            doc['data']['It'])
    elif detector == 'I0':
        func = lambda doc: (doc['time'] - epoch_offset, doc['data']['I0'])
    elif detector == 'Iy':
        denominator = ' / I0'
        func = lambda doc: (doc['time'] - epoch_offset, doc['data']['Iy'] /
                            doc['data']['I0'])
    elif detector == 'Dtc':
        dets.append(vor)
        denominator = ' / I0'
        func = lambda doc: (doc['time'] - epoch_offset, doc['data'][
            BMMuser.dtc2] / doc['data']['I0'])
        func3 = lambda doc: (doc['time'] - epoch_offset, doc['data'][
            BMMuser.dtc3] / doc['data']['I0'])
    elif detector == 'If':
        dets.append(vor)
        denominator = ' / I0'
        func = lambda doc: (doc['time'] - epoch_offset, (doc['data'][
            BMMuser.dtc1] + doc['data'][BMMuser.dtc2] + doc['data'][
                BMMuser.dtc3] + doc['data'][BMMuser.dtc4]) / doc['data']['I0'])

    ## and this is the appropriate way to plot this linescan
    if detector == 'Dtc':
        plot = [
            DerivedPlot(func,
                        xlabel='elapsed time (seconds)',
                        ylabel='dtc2',
                        title='time scan'),
            DerivedPlot(func3,
                        xlabel='elapsed time (seconds)',
                        ylabel='dtc3',
                        title='time scan')
        ]
    else:
        plot = DerivedPlot(func,
                           xlabel='elapsed time (seconds)',
                           ylabel=detector + denominator,
                           title='time scan')

    line1 = '%s, N=%s, dwell=%.3f, delay=%.3f\n' % (detector, readings, dwell,
                                                    delay)

    thismd = dict()
    thismd['XDI'] = dict()
    thismd['XDI']['Facility'] = dict()
    thismd['XDI']['Facility']['GUP'] = BMMuser.gup
    thismd['XDI']['Facility']['SAF'] = BMMuser.saf
    thismd['XDI']['Beamline'] = dict()
    thismd['XDI']['Beamline']['energy'] = dcm.energy.readback.get()
    thismd['XDI']['Scan'] = dict()
    thismd['XDI']['Scan']['dwell_time'] = dwell
    thismd['XDI']['Scan']['delay'] = delay

    @subs_decorator(plot)
    #@subs_decorator(src.callback)
    def count_scan(dets, readings, delay):
        #if 'purpose' not in md:
        #    md['purpose'] = 'measurement'
        uid = yield from count(dets,
                               num=readings,
                               delay=delay,
                               md={
                                   **thismd,
                                   **md, 'plan_name':
                                   f'count measurement {detector}'
                               })
        return uid

    rkvs.set('BMM:scan:type', 'time')
    rkvs.set('BMM:scan:starttime',
             str(datetime.datetime.timestamp(datetime.datetime.now())))
    rkvs.set('BMM:scan:estimated', 0)

    uid = yield from count_scan(dets, readings, delay, md)

    BMM_log_info('timescan: %s\tuid = %s, scan_id = %d' %
                 (line1, uid, db[-1].start['scan_id']))

    yield from mv(_locked_dwell_time, 0.5)
    RE.msg_hook = BMM_msg_hook
    return (uid)
예제 #16
0
def calibrate_high_end(mono='111', focus=False):
    '''Step through the upper 5 elements of the mono calibration procedure.'''
    BMMuser, shb, dcm_pitch = user_ns['BMMuser'], user_ns['shb'], user_ns[
        'dcm_pitch']
    (ok, text) = BMM_clear_to_start()
    if ok is False:
        print(error_msg('\n' + text) + bold_msg('Quitting macro....\n'))
        return (yield from null())

    BMM_log_info('Beginning high end calibration macro')

    def main_plan():
        BMMuser.prompt = False
        datafile = os.path.join(BMMuser.DATA, 'edges%s.ini' % mono)
        handle = open(datafile, 'a')

        #yield from shb.open_plan()

        yield from change_edge('Pt', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='ptcal',
                        edge='Pt',
                        e0=11563,
                        sample='Pt foil')
        close_last_plot()
        handle.write('pt = 11111.11,    11562.76,    22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Au', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='aucal',
                        edge='Au',
                        e0=11919,
                        sample='Au foil')
        close_last_plot()
        handle.write('au = 11111.11,    11919.70,    22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Pb', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='pbcal',
                        edge='Pb',
                        e0=13035,
                        sample='Pb foil')
        close_last_plot()
        handle.write('pb = 11111.11,    13035.07,    22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Nb', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='nbcal',
                        edge='Nb',
                        e0=18986,
                        sample='Nb foil')
        close_last_plot()
        handle.write('nb = 11111.11,     18982.97,   22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Mo', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='mocal',
                        edge='Mo',
                        e0=20000,
                        sample='Mo foil')
        close_last_plot()
        handle.write('mo = 11111.11,    20000.36,    22222.22,   %.5f\n' %
                     pitch)

        handle.flush()
        handle.close()

        #yield from shb.close_plan()

    def cleanup_plan():
        yield from resting_state_plan()

    yield from finalize_wrapper(main_plan(), cleanup_plan())
    yield from resting_state_plan()
    BMM_log_info('High end calibration macro finished!')
예제 #17
0
def calibrate_low_end(mono='111', focus=False):
    '''Step through the lower 5 elements of the mono calibration procedure.'''
    BMMuser, shb, dcm_pitch = user_ns['BMMuser'], user_ns['shb'], user_ns[
        'dcm_pitch']
    (ok, text) = BMM_clear_to_start()
    if ok is False:
        print(error_msg('\n' + text) + bold_msg('Quitting macro....\n'))
        return (yield from null())

    BMM_log_info('Beginning low end calibration macro')

    def main_plan():
        BMMuser.prompt = False

        datafile = os.path.join(BMMuser.DATA, 'edges%s.ini' % mono)
        handle = open(datafile, 'w')
        handle.write('[config]\n')
        handle.write("mono      = %s\n" % mono)
        if mono == '111':
            handle.write('DSPACING  = 3.13597211\n')
        else:
            handle.write('DSPACING  = 1.63762644\n')
        handle.write('thistitle = Si(%s) calibration curve\n' % mono)
        handle.write(
            'reference = Kraft et al, Review of Scientific Instruments 67, 681 (1996)\n'
        )
        handle.write('doi       = https://doi.org/10.1063/1.1146657\n\n')
        handle.write('##       found, tabulated, found_angle, dcm_pitch\n')
        handle.write('[edges]\n')
        handle.flush()

        yield from change_edge('Fe', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='fecal',
                        edge='Fe',
                        e0=7112,
                        sample='Fe foil')
        close_last_plot()
        handle.write('fe = 11111.11,    7110.75,    22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Co', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='cocal',
                        edge='Co',
                        e0=7709,
                        sample='Co foil')
        close_last_plot()
        handle.write('co = 11111.11,    7708.78,    22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Ni', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='nical',
                        edge='Ni',
                        e0=8333,
                        sample='Ni foil')
        close_last_plot()
        handle.write('ni = 11111.11,    8331.49,    22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Cu', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='cucal',
                        edge='Cu',
                        e0=8979,
                        sample='Cu foil')
        close_last_plot()
        handle.write('cu = 11111.11,    8980.48,    22222.22,   %.5f\n' %
                     pitch)
        handle.flush()

        yield from change_edge('Zn', target=0, focus=focus)
        pitch = dcm_pitch.user_readback.get()
        yield from xafs('/home/xf06bm/Data/Staff/mono_calibration/cal.ini',
                        folder=BMMuser.DATA,
                        filename='zncal',
                        edge='Zn',
                        e0=9659,
                        sample='Zn foil')
        close_last_plot()
        handle.write('zn = 11111.11,    9660.76,    22222.22,   %.5f\n' %
                     pitch)

        handle.flush()
        handle.close()

        #yield from shb.close_plan()

    def cleanup_plan():
        yield from resting_state_plan()

    yield from finalize_wrapper(main_plan(), cleanup_plan())
    yield from resting_state_plan()
    BMM_log_info('Low end calibration macro finished!')
예제 #18
0
    def main_plan(detector, slow, startslow, stopslow, nslow, fast, startfast,
                  stopfast, nfast, pluck, force, dwell, md):
        (ok, text) = BMM_clear_to_start()
        if force is False and ok is False:
            print(error_msg(text))
            BMMuser.final_log_entry = False
            yield from null()
            return

        RE.msg_hook = None

        ## sanity checks on slow axis
        if type(slow) is str: slow = slow.lower()
        if slow not in motor_nicknames.keys() and 'EpicsMotor' not in str(
                type(slow)) and 'PseudoSingle' not in str(type(slow)):
            print(
                error_msg('\n*** %s is not an areascan motor (%s)\n' %
                          (slow, str.join(', ', motor_nicknames.keys()))))
            BMMuser.final_log_entry = False
            yield from null()
            return
        if slow in motor_nicknames.keys():
            slow = motor_nicknames[slow]

        ## sanity checks on fast axis
        if type(fast) is str: fast = fast.lower()
        if fast not in motor_nicknames.keys() and 'EpicsMotor' not in str(
                type(fast)) and 'PseudoSingle' not in str(type(fast)):
            print(
                error_msg('\n*** %s is not an areascan motor (%s)\n' %
                          (fast, str.join(', ', motor_nicknames.keys()))))
            BMMuser.final_log_entry = False
            yield from null()
            return
        if fast in motor_nicknames.keys():
            fast = motor_nicknames[fast]

        detector = detector.capitalize()
        yield from abs_set(_locked_dwell_time, dwell, wait=True)
        dets = [
            quadem1,
        ]
        if detector == 'If':
            dets.append(vor)
            detector = 'ROI1'
        if detector.lower() == 'xs':
            dets.append(xs)
            detector = BMMuser.xs1

        if 'PseudoSingle' in str(type(slow)):
            valueslow = slow.readback.get()
        else:
            valueslow = slow.user_readback.get()
            line1 = 'slow motor: %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
                    (slow.name, startslow, stopslow, nslow, valueslow)

        if 'PseudoSingle' in str(type(fast)):
            valuefast = fast.readback.get()
        else:
            valuefast = fast.user_readback.get()
        line2 = 'fast motor: %s, %.3f, %.3f, %d -- starting at %.3f\n' % \
                (fast.name, startfast, stopfast, nfast, valuefast)

        npoints = nfast * nslow
        estimate = int(npoints * (dwell + 0.7))

        # extent = (
        #     valuefast + startfast,
        #     valueslow + startslow,
        #     valuefast + stopfast,
        #     valueslow + stopslow,
        # )
        # extent = (
        #     0,
        #     nfast-1,
        #     0,
        #     nslow-1
        # )
        # print(extent)
        # return(yield from null())

        # areaplot = LiveScatter(fast.name, slow.name, detector,
        #                        xlim=(startfast, stopfast), ylim=(startslow, stopslow))

        areaplot = LiveGrid(
            (nslow, nfast),
            detector,  #aspect='equal', #aspect=float(nslow/nfast), extent=extent,
            xlabel='fast motor: %s' % fast.name,
            ylabel='slow motor: %s' % slow.name)
        #BMMuser.ax     = areaplot.ax
        #BMMuser.fig    = areaplot.ax.figure
        BMMuser.motor = fast
        BMMuser.motor2 = slow
        #BMMuser.fig.canvas.mpl_connect('close_event', handle_close)

        thismd = dict()
        thismd['XDI'] = dict()
        thismd['XDI']['Facility'] = dict()
        thismd['XDI']['Facility']['GUP'] = BMMuser.gup
        thismd['XDI']['Facility']['SAF'] = BMMuser.saf
        thismd['slow_motor'] = slow.name
        thismd['fast_motor'] = fast.name

        ## engage suspenders right before starting scan sequence
        if force is False: BMM_suspenders()

        @subs_decorator(areaplot)
        #@subs_decorator(src.callback)
        def make_areascan(dets,
                          slow,
                          startslow,
                          stopslow,
                          nslow,
                          fast,
                          startfast,
                          stopfast,
                          nfast,
                          snake=False):
            BMMuser.final_log_entry = False
            uid = yield from grid_scan(dets, slow, startslow, stopslow, nslow,
                                       fast, startfast, stopfast, nfast, snake)
            BMMuser.final_log_entry = True
            return uid

        rkvs.set('BMM:scan:type', 'area')
        rkvs.set('BMM:scan:starttime',
                 str(datetime.datetime.timestamp(datetime.datetime.now())))
        rkvs.set('BMM:scan:estimated', estimate)

        BMM_log_info('begin areascan observing: %s\n%s%s' %
                     (detector, line1, line2))
        uid = yield from make_areascan(dets, slow, valueslow + startslow,
                                       valueslow + stopslow, nslow, fast,
                                       valuefast + startfast,
                                       valuefast + stopfast, nfast, False)

        if pluck is True:
            action = input('\n' + bold_msg(
                'Pluck motor position from the plot? [Y/n then Enter] '))
            if action.lower() == 'n' or action.lower() == 'q':
                return (yield from null())
            print(
                'Single click the left mouse button on the plot to pluck a point...'
            )
            cid = BMMuser.fig.canvas.mpl_connect(
                'button_press_event',
                interpret_click)  # see 65-derivedplot.py and
            while BMMuser.x is None:  #  https://matplotlib.org/users/event_handling.html
                yield from sleep(0.5)

            print('Converting plot coordinates to real coordinates...')
            begin = valuefast + startfast
            stepsize = (stopfast - startfast) / (nfast - 1)
            pointfast = begin + stepsize * BMMuser.x
            #print(BMMuser.x, pointfast)

            begin = valueslow + startslow
            stepsize = (stopslow - startslow) / (nslow - 1)
            pointslow = begin + stepsize * BMMuser.y
            #print(BMMuser.y, pointslow)

            print('That translates to x=%.3f, y=%.3f' % (pointfast, pointslow))
            yield from mv(fast, pointfast, slow, pointslow)