Пример #1
0
 def align_linear(self, force=False, drop=None):
     '''Fit an error function to the linear scan against It. Plot the
     result. Move to the centroid of the error function.'''
     if self.orientation == 'parallel':
         motor = user_ns['xafs_liny']
     else:
         motor = user_ns['xafs_linx']
     yield from linescan(motor, 'it', -2.3, 2.3, 51, pluck=False)
     close_last_plot()
     table  = user_ns['db'][-1].table()
     yy     = table[motor.name]
     signal = table['It']/table['I0']
     if drop is not None:
         yy = yy[:-drop]
         signal = signal[:-drop]
     if float(signal[2]) > list(signal)[-2] :
         ss     = -(signal - signal[2])
         self.inverted = 'inverted '
     else:
         ss     = signal - signal[2]
         self.inverted    = ''
     mod    = StepModel(form='erf')
     pars   = mod.guess(ss, x=numpy.array(yy))
     out    = mod.fit(ss, pars, x=numpy.array(yy))
     print(whisper(out.fit_report(min_correl=0)))
     target = out.params['center'].value
     yield from mv(motor, target)
     self.y_plot(yy, out)
 def align_y(self, force=False, drop=None):
     '''Fit an error function to the xafs_y scan against It. Plot the
     result. Move to the centroid of the error function.'''
     xafs_y = user_ns['xafs_y']
     db = user_ns['db']
     yield from linescan(xafs_y, 'it', -1, 1, 31, pluck=False)
     close_last_plot()
     table = db[-1].table()
     yy = table['xafs_y']
     signal = table['It'] / table['I0']
     if drop is not None:
         yy = yy[:-drop]
         signal = signal[:-drop]
     if float(signal[2]) > list(signal)[-2]:
         ss = -(signal - signal[2])
         self.inverted = 'inverted '
     else:
         ss = signal - signal[2]
         self.inverted = ''
     mod = StepModel(form='erf')
     pars = mod.guess(ss, x=numpy.array(yy))
     out = mod.fit(ss, pars, x=numpy.array(yy))
     print(whisper(out.fit_report(min_correl=0)))
     self.y_plot(yy, out)
     target = out.params['center'].value
     yield from mv(xafs_y, target)
Пример #3
0
def wafer_edge(motor='x'):
    '''Fit an error function to the linear scan against It. Plot the
    result. Move to the centroid of the error function.'''
    if motor == 'x':
        motor = user_ns['xafs_linx']
    else:
        motor = user_ns['xafs_liny']
    yield from linescan(motor, 'it', -2, 2, 41, pluck=False)
    close_last_plot()
    table = user_ns['db'][-1].table()
    yy = table[motor.name]
    signal = table['It'] / table['I0']
    if float(signal[2]) > list(signal)[-2]:
        ss = -(signal - signal[2])
    else:
        ss = signal - signal[2]
    mod = StepModel(form='erf')
    pars = mod.guess(ss, x=numpy.array(yy))
    out = mod.fit(ss, pars, x=numpy.array(yy))
    print(whisper(out.fit_report(min_correl=0)))
    out.plot()
    target = out.params['center'].value
    yield from mv(motor, target)
    yield from resting_state_plan()
    print(
        f'Edge found at X={user_ns["xafs_x"].position} and Y={user_ns["xafs_y"].position}'
    )
Пример #4
0
 def align_pitch(self, force=False):
     '''Find the peak of xafs_pitch scan against It. Plot the
     result. Move to the peak.'''        
     xafs_pitch = user_ns['xafs_pitch']
     yield from linescan(xafs_pitch, 'it', -2.5, 2.5, 51, pluck=False, force=force)
     close_last_plot()
     table  = user_ns['db'][-1].table()
     pitch  = table['xafs_pitch']
     signal = table['It']/table['I0']
     target = signal.idxmax()
     yield from mv(xafs_pitch, pitch[target])
     self.pitch_plot(pitch, signal)
Пример #5
0
def change_edge(el,
                focus=False,
                edge='K',
                energy=None,
                slits=True,
                target=300.,
                xrd=False,
                bender=True):
    '''Change edge energy by:
    1. Moving the DCM above the edge energy
    2. Moving the photon delivery system to the correct mode
    3. Running a rocking curve scan
    4. Running a slits_height scan

    Parameters
    ----------
    el : str
        one- or two-letter symbol
    focus : bool, optional
        T=focused or F=unfocused beam [False, unfocused]
    edge : str, optional
        edge symbol ['K']
    energy : float, optional
        e0 value [None, determined from el/edge]
    slits : bool, optional
        perform slit_height() scan [False]
    target : float, optional
        energy where rocking curve is measured [300]
    xrd : boolean, optional
        force photon delivery system to XRD [False]

    Examples
    --------
    Normal use, unfocused beam:
       
    >>> RE(change_edge('Fe'))

    Normal use, focused beam:
       
    >>> RE(change_edge('Fe', focus=True))

    L2 or L1 edge:
       
    >>> RE(change_edge('Re', edge='L2'))

    Measure rocking curve at edge energy:
      
    >>> RE(change_edge('Fe', target=0))

    XRD, new energy:
       
    >>> RE(change_edge('Fe', xrd=True, energy=8600))
        
    note that you must specify an element, but it doesn't matter which
    one the energy will be moved to the specified energy xrd=True
    implies focus=True and target=0

    '''
    BMMuser, RE, dcm, dm3_bct = user_ns['BMMuser'], user_ns['RE'], user_ns[
        'dcm'], user_ns['dm3_bct']
    dcm_pitch, dcm_bragg = user_ns['dcm_pitch'], user_ns['dcm_bragg']
    rkvs = user_ns['rkvs']
    try:
        xs = user_ns['xs']
    except:
        pass
    #BMMuser.prompt = True
    el = el.capitalize()

    ######################################################################
    # this is a tool for verifying a macro.  this replaces an xafsmod 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 edge.\n'
                % (BMMuser.macro_sleep, el)))
        countdown(BMMuser.macro_sleep)
        return (yield from null())
    ######################################################################

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

    (ok, text) = BMM_clear_to_start()
    if ok is False:
        print(
            error_msg('\n' + text) +
            bold_msg('Quitting change_edge() macro....\n'))
        return (yield from null())

    if energy is None:
        energy = edge_energy(el, edge)

    if energy is None:
        print(
            error_msg('\nEither %s or %s is not a valid symbol\n' %
                      (el, edge)))
        return (yield from null())
    if energy > 23500:
        edge = 'L3'
        energy = edge_energy(el, 'L3')

    if energy < 4000:
        print(warning_msg('The %s edge energy is below 4950 eV' % el))
        print(warning_msg('You have to change energy by hand.'))
        return (yield from null())

    if energy > 23500:
        print(
            warning_msg(
                'The %s edge energy is outside the range of this beamline!' %
                el))
        return (yield from null())

    BMMuser.edge = edge
    BMMuser.element = el
    BMMuser.edge_energy = energy
    rkvs.set('BMM:pds:edge', edge)
    rkvs.set('BMM:pds:element', el)
    rkvs.set('BMM:pds:edge_energy', energy)

    if energy > 8000:
        mode = 'A' if focus else 'D'
    elif energy < 6000:
        #mode = 'B' if focus else 'F'   ## mode B currently is inaccessible :(
        mode = 'C' if focus else 'F'
    else:
        mode = 'C' if focus else 'E'
    if xrd:
        mode = 'XRD'
        focus = True
        target = 0.0
    current_mode = get_mode()
    if mode in ('D', 'E', 'F') and current_mode in ('D', 'E', 'F'):
        with_m2 = False
    elif mode in ('A', 'B',
                  'C') and current_mode in ('A', 'B',
                                            'C'):  # no need to move M2
        with_m2 = False
    else:
        with_m2 = True
    if all_connected(with_m2) is False:
        print(warning_msg('Ophyd connection failure' % el))
        return (yield from null())

    ################################
    # confirm configuration change #
    ################################
    print(bold_msg('\nEnergy change:'))
    print('   %s: %s %s' %
          (list_msg('edge'), el.capitalize(), edge.capitalize()))
    print('   %s: %.1f' % (list_msg('edge energy'), energy))
    print('   %s: %.1f' % (list_msg('target energy'), energy + target))
    print('   %s: %s' % (list_msg('focus'), str(focus)))
    print('   %s: %s' % (list_msg('photon delivery mode'), mode))
    print('   %s: %s' % (list_msg('optimizing slits height'), str(slits)))
    if BMMuser.prompt:
        action = input("\nBegin energy change? [Y/n then Enter] ")
        if action.lower() == 'q' or action.lower() == 'n':
            return (yield from null())
        if mode == 'C' and energy < 6000:
            print(
                warning_msg(
                    '\nMoving to mode C for focused beam and an edge energy below 6 keV.'
                ))
            action = input(
                "You will not get optimal harmonic rejection.  Continue anyway?  [Y/n then Enter] "
            )
            if action.lower() == 'q' or action.lower() == 'n':
                return (yield from null())

    start = time.time()
    if mode == 'XRD':
        report('Configuring beamline for XRD', level='bold', slack=True)
    else:
        report(
            f'Configuring beamline for {el.capitalize()} {edge.capitalize()} edge',
            level='bold',
            slack=True)
    yield from dcm.kill_plan()

    ################################################
    # change to the correct photon delivery mode   #
    #      + move mono to correct energy           #
    #      + move reference holder to correct slot #
    ################################################
    # if not calibrating and mode != current_mode:
    #     print('Moving to photon delivery mode %s...' % mode)
    yield from mv(dcm_bragg.acceleration, BMMuser.acc_slow)
    yield from change_mode(mode=mode,
                           prompt=False,
                           edge=energy + target,
                           reference=el,
                           bender=bender)
    yield from mv(dcm_bragg.acceleration, BMMuser.acc_fast)
    if arrived_in_mode(mode=mode) is False:
        print(error_msg(f'\nFailed to arrive in Mode {mode}'))
        print(
            'Fixing this is often as simple as re-running the change_mode() command.'
        )
        print('Or try dm3_bct.kill() the re-run the change_mode() command.')
        print('If that doesn\'t work, call for help')
        return (yield from null())

    yield from user_ns['kill_mirror_jacks']()
    yield from sleep(1)
    if BMMuser.motor_fault is not None:
        print(
            error_msg('\nSome motors are reporting amplifier faults: %s' %
                      BMMuser.motor_fault))
        print(
            'Clear the faults and try running the same change_edge() command again.'
        )
        print('Troubleshooting: ' + url_msg(
            'https://nsls-ii-bmm.github.io/BeamlineManual/trouble.html#amplifier-fault'
        ))
        BMMuser.motor_fault = None
        return (yield from null())
    BMMuser.motor_fault = None

    ############################
    # run a rocking curve scan #
    ############################
    print('Optimizing rocking curve...')
    yield from abs_set(dcm_pitch.kill_cmd, 1, wait=True)
    yield from mv(dcm_pitch, approximate_pitch(energy + target))
    yield from sleep(1)
    yield from abs_set(dcm_pitch.kill_cmd, 1, wait=True)
    yield from rocking_curve()
    close_last_plot()

    ##########################
    # run a slit height scan #
    ##########################
    if slits:
        print('Optimizing slits height...')
        yield from slit_height(move=True)
        close_last_plot()
        ## redo rocking curve?

    ##################################
    # set reference and roi channels #
    ##################################
    if not xrd:
        ## reference channel
        rois = user_ns['rois']
        print('Moving reference foil...')
        yield from rois.select_plan(el)
        ## Xspress3
        BMMuser.verify_roi(xs, el, edge)
        ## feedback
        show_edges()

    if mode == 'XRD':
        report('Finished configuring for XRD', level='bold', slack=True)
    else:
        report(
            f'Finished configuring for {el.capitalize()} {edge.capitalize()} edge',
            level='bold',
            slack=True)
    if slits is False:
        print(
            '  * You may need to verify the slit position:  RE(slit_height())')
    self.to_json(os.path.join(self.DATA, '.BMMuser'))
    yield from dcm.kill_plan()
    end = time.time()
    print('\n\nThat took %.1f min' % ((end - start) / 60))
    return ()
Пример #6
0
    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()
Пример #7
0
    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()
Пример #8
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))