示例#1
0
 def status(self):
     text = f'\nCurrent temperature = {self.readback.get():.1f}, setpoint = {self.setpoint.get():.1f}\n\n'
     code = int(self.status_code.get())
     if code & 1:
         text += error_msg('Error        : yes') + '\n'
     else:
         text += 'Error        : no\n'
     if code & 2:
         text += go_msg('At setpoint  : yes') + '\n'
     else:
         text += 'At setpoint  : no\n'
     if code & 4:
         text += go_msg('Heater       : on') + '\n'
     else:
         text += 'Heater       : off\n'
     if code & 8:
         text += go_msg('Pump         : on') + '\n'
     else:
         text += 'Pump         : off\n'
     if code & 16:
         text += go_msg('Pump Auto    : yes') + '\n'
     else:
         text += 'Pump Auto    : no\n'
         
     boxedtext(f'Linkam {self.model}, stage {self.stage_model}', text, 'brown', width = 45)
示例#2
0
    def do_ChangeEdge(self):
        print(go_msg('You would like to change to a different edge...\n'))

        el = input(" What element? ")
        el = el.capitalize()
        if el == '':
            print(whisper('doing nothing'))
            return (yield from null())
        if el not in ELEMENTS:
            print(error_msg(f'{el} is not an element'))
            return (yield from null())

        if Z_number(el) < 46:
            default_ed = 'K'
            prompt = go_msg('K') + '/L3/L2/L1'
        else:
            default_ed = 'L3'
            prompt = 'K/' + go_msg('L3') + '/L2/L1'
        ed = input(f' What edge? [{prompt}] ')
        ed = ed.capitalize()
        if ed not in ('K', 'L3', 'L2', 'L1'):
            ed = default_ed

        focus = input(' Focused beam? [y/N] ')
        if focus.lower() == 'y':
            focus = True
        else:
            focus = False

        print(
            disconnected_msg(
                f'yield from change_edge("{el}", focus={focus}, edge="{ed}")'))
        yield from null()
示例#3
0
def show_reference_wheel():
    xafs_ref = user_ns['xafs_ref']
    wheel = xafs_ref.content.copy()
    this = xafs_ref.current_slot() - 1
    #wheel[this] = go_msg(wheel[this])
    text = 'Foil wheel:\n'
    text += bold_msg(
        '    1      2      3      4      5      6      7      8      9     10     11     12\n'
    )
    text += ' '
    for i in range(12):
        if i == this:
            text += go_msg('%4.4s' % str(wheel[i])) + '   '
        else:
            text += '%4.4s' % str(wheel[i]) + '   '
    text += '\n'
    text += bold_msg(
        '   13     14     15     16     17     18     19     20     21     22     23     24\n'
    )
    text += ' '
    for i in range(12, 24):
        if i == this:
            text += go_msg('%4.4s' % str(wheel[i])) + '   '
        else:
            text += '%4.4s' % str(wheel[i]) + '   '
    text += '\n'
    return (text)
 def table(self):
     '''Pretty print a table of values for each ROI.
     '''
     BMMuser = user_ns['BMMuser']
     print(' ROI    Chan1 ')
     print('================')
     for r in range(1, 17):
         el = getattr(self.channel8.rois, f'roi{r:02}').value.name
         if len(el) > 3:
             continue
         if el != 'OCR':
             el = el[:-1]
         if el == BMMuser.element or el == 'OCR':
             print(go_msg(f' {el:3} '), end='')
             for c in (8, ):
                 print(go_msg(
                     f"  {int(getattr(getattr(self, f'channel{c}').rois, f'roi{r:02}').value.get()):7}  "
                 ),
                       end='')
             print('')
         else:
             print(f' {el:3} ', end='')
             for c in (8, ):
                 print(
                     f"  {int(getattr(getattr(self, f'channel{c}').rois, f'roi{r:02}').value.get()):7}  ",
                     end='')
             print('')
示例#5
0
    def do_AdjustSlits(self):
        print(
            go_msg(
                'You would like to adjust the size of the hutch slits...\n'))
        which = input(" Horizontal or vertical? [H/v] ")
        which = which.lower()
        if which.startswith('h') or which == '':
            size = input(' Horizontal size (in mm): ')
            is_horiz = True
        elif which.startswith('v'):
            size = input(' Vertical size (in mm): ')
            is_horiz = False
        else:
            self.do_nothing()
            return

        try:
            size = float(size)
        except:
            print(error_msg(f'\n "{size}" cannot be interpreted as a number'))
            yield from null()
            return
        if is_horiz:
            #print(disconnected_msg(f'yield from mv(slits3.hsize, {size})'))
            #yield from null()
            yield from mv(user_ns['slits3'].hsize, size)
        else:
            #print(disconnected_msg(f'yield from mv(slits3.vsize, {size})'))
            #yield from null()
            yield from mv(user_ns['slits3'].vsize, size)
示例#6
0
def recover_diagnostics():
    dm2_fs    = user_ns['dm2_fs']
    dm3_fs    = user_ns['dm3_fs']
    dm3_bct   = user_ns['dm3_bct']
    dm3_bpm   = user_ns['dm3_bpm']
    dm3_foils = user_ns['dm3_foils']
    yield from mv(dm2_fs.home_signal,  1)
    yield from mv(dm3_fs.home_signal,  1)
    yield from mv(dm3_bct.home_signal, 1)
    yield from mv(dm3_bpm.home_signal, 1)
    yield from mv(dm3_foils.home_signal, 1)
    yield from sleep(1.0)
    print('Begin homing dm2_fs, dm3_fs, dm3_bct, dm3_bpm, and dm3_foils:\n')
    hvalues = (dm2_fs.hocpl.get(), dm3_fs.hocpl.get(), dm3_bct.hocpl.get(), dm3_bpm.hocpl.get(), dm3_foils.hocpl.get())
    while any(v == 0 for v in hvalues):
        hvalues = (dm2_fs.hocpl.get(), dm3_fs.hocpl.get(), dm3_bct.hocpl.get(), dm3_bpm.hocpl.get(), dm3_foils.hocpl.get())
        strings = ['dm2_fs', 'dm3_fs', 'dm3_bct', 'dm3_bpm', 'dm3_foils']
        for i,v in enumerate(hvalues):
            strings[i] = go_msg(strings[i]) if hvalues[i] == 1 else error_msg(strings[i])
        print('  '.join(strings), end='\r')
        yield from sleep(1.0)
    print('\n')
    #yield from mv(dm3_bct.kill_cmd, 1)
    yield from mv(dm3_foils.kill_cmd, 1)
    ## take these from Modes.xlsx, mode D -- all out of the beam path
    yield from mv(dm2_fs, 67, dm3_fs, 55, dm3_bct, 43.6565, dm3_bpm, 5.511, dm3_foils, 41)
示例#7
0
def recover_mirrors():
    m2_xu, m2_xd, m2_yu, m2_ydo, m2_ydi = user_ns['m2_xu'], user_ns['m2_xd'], user_ns['m2_yu'], user_ns['m2_ydo'], user_ns['m2_ydi']
    m3_xu, m3_xd, m3_yu, m3_ydo, m3_ydi = user_ns['m3_xu'], user_ns['m3_xd'], user_ns['m3_yu'], user_ns['m3_ydo'], user_ns['m3_ydi']
    yield from mv(m2_yu.home_signal,  1)
    yield from mv(m2_xu.home_signal,  1)
    yield from mv(m3_yu.home_signal,  1)
    yield from mv(m3_xu.home_signal,  1)
    yield from sleep(1.0)
    print('Begin homing lateral and vertical motors in M2 and M3:\n')
    hvalues = (m2_yu.hocpl.get(), m2_ydo.hocpl.get(), m2_ydi.hocpl.get(), m2_xu.hocpl.get(), m2_xd.hocpl.get(),
               m3_yu.hocpl.get(), m3_ydo.hocpl.get(), m3_ydi.hocpl.get(), m3_xu.hocpl.get(), m3_xd.hocpl.get())
    while any(v == 0 for v in hvalues):
        hvalues = (m2_yu.hocpl.get(), m2_ydo.hocpl.get(), m2_ydi.hocpl.get(), m2_xu.hocpl.get(), m2_xd.hocpl.get(),
                   m3_yu.hocpl.get(), m3_ydo.hocpl.get(), m3_ydi.hocpl.get(), m3_xu.hocpl.get(), m3_xd.hocpl.get())
        strings = ['m2_yu', 'm2_ydo', 'm2_ydi', 'm2_xu', 'm2_xd', 'm3_yu', 'm3_ydo', 'm3_ydi', 'm3_xu', 'm3_xd',]
        for i,v in enumerate(hvalues):
            strings[i] = go_msg(strings[i]) if hvalues[i] == 1 else error_msg(strings[i])
        print('  '.join(strings), end='\r')
        yield from sleep(1.0)
    print('\n')
    yield from mv(m2_yu,  MODEDATA['m2_yu']['E'],
                  m2_ydo, MODEDATA['m2_ydo']['E'],
                  m2_ydi, MODEDATA['m2_ydi']['E'],
                  m2_xu,  MODEDATA['m2_xu']['E'],
                  m2_xd,  MODEDATA['m2_xd']['E'],
                  m3_yu,  MODEDATA['m3_yu']['E'],
                  m3_ydo, MODEDATA['m3_ydo']['E'],
                  m3_ydi, MODEDATA['m3_ydi']['E'],
                  m3_xu,  MODEDATA['m3_xu']['E'],
                  m3_xd,  MODEDATA['m3_xd']['E'])
示例#8
0
 def do_SetupXRD(self):
     print(go_msg('You would like to set up for XRD...\n'))
     print(
         disconnected_msg(
             'yield from change_edge("Ni", xrd=True, energy=8600)'))
     #yield from change_edge("Ni", xrd=True, energy=8600)
     yield from null()
示例#9
0
 def do_RunMacro(self):
     print(go_msg('You would like to run a measurement macro...\n'))
     macro = present_options('py')
     if macro is None:
         return
     ipython = get_ipython()
     fullpath = os.path.join(user_ns['BMMuser'].folder, macro)
     ipython.magic(f'run -i \'{fullpath}\'')
     print(disconnected_msg(f'yield from {macro[:-3]}()'))
     yield from null()
示例#10
0
 def show(self):
     '''Show configuration of ROI channels'''
     BMMuser = user_ns['BMMuser']
     text = 'Analog ROI channels:\n'
     for i in range(3):
         if i+1 == BMMuser.roi_channel:
             text +='      ROI %d : %s\n'% (i+1, go_msg(str(self.slots[i])))
         else:
             text +='      ROI %d : %s\n'% (i+1, str(self.slots[i]))
     return text
示例#11
0
 def show_rois(self):
     BMMuser = user_ns['BMMuser']
     text = 'Xspress3 ROIs:\n'
     text += bold_msg('    1      2      3      4      5      6      7      8\n')
     text += ' '
     for i in range(8):
         if self.slots[i] == BMMuser.element:
             text += go_msg('%4.4s' % self.slots[i]) + '   '
         else:
             text += '%4.4s' % self.slots[i] + '   '
     text += '\n'
     text += bold_msg('    9     10     11     12     13     14     15     16\n')
     text += ' '
     for i in range(8, 16):
         if self.slots[i] == BMMuser.element:
             text += go_msg('%4.4s' % self.slots[i]) + '   '
         else:
             text += '%4.4s' % self.slots[i] + '   '
     text += '\n'
     return(text)
示例#12
0
    def recover(self):
        '''Home and re-position all DCM motors after a power interruption.
        '''
        user_ns['dcm_bragg'].acceleration.put(BMMuser.acc_fast)
        user_ns['dcm_para'].velocity.put(0.6)
        user_ns['dcm_para'].hvel_sp.put(0.4)
        user_ns['dcm_perp'].velocity.put(0.2)
        user_ns['dcm_perp'].hvel_sp.put(0.2)
        user_ns['dcm_x'].velocity.put(0.6)
        ## initiate homing for Bragg, pitch, roll, para, perp, and x
        yield from mv(user_ns['dcm_bragg'].home_signal, 1)
        yield from mv(user_ns['dcm_pitch'].home_signal, 1)
        yield from mv(user_ns['dcm_roll'].home_signal, 1)
        yield from mv(user_ns['dcm_para'].home_signal, 1)
        yield from mv(user_ns['dcm_perp'].home_signal, 1)
        yield from mv(user_ns['dcm_x'].home_signal, 1)
        yield from sleep(1.0)
        ## wait for them to be homed
        print('Begin homing DCM motors:\n')
        hvalues = (user_ns['dcm_bragg'].hocpl.get(),
                   user_ns['dcm_pitch'].hocpl.get(),
                   user_ns['dcm_roll'].hocpl.get(),
                   user_ns['dcm_para'].hocpl.get(),
                   user_ns['dcm_perp'].hocpl.get(),
                   user_ns['dcm_x'].hocpl.get())
        while any(v == 0 for v in hvalues):
            hvalues = (user_ns['dcm_bragg'].hocpl.get(),
                       user_ns['dcm_pitch'].hocpl.get(),
                       user_ns['dcm_roll'].hocpl.get(),
                       user_ns['dcm_para'].hocpl.get(),
                       user_ns['dcm_perp'].hocpl.get(),
                       user_ns['dcm_x'].hocpl.get())
            strings = ['Bragg', 'pitch', 'roll', 'para', 'perp', 'x']
            for i, v in enumerate(hvalues):
                strings[i] = go_msg(
                    strings[i]) if hvalues[i] == 1 else error_msg(strings[i])
            print('  '.join(strings), end='\r')
            yield from sleep(1.0)

        ## move x into the correct position for Si(111)
        print('\n')
        yield from mv(user_ns['dcm_x'], 1)
        yield from mv(user_ns['dcm_x'], 0.3)
        ## move pitch and roll to the Si(111) positions
        this_energy = self.energy.readback.get()
        yield from self.kill_plan()
        yield from mv(user_ns['dcm_pitch'], approximate_pitch(this_energy),
                      user_ns['dcm_roll'], -6.26)
        yield from mv(self.energy, this_energy)
        print('DCM is at %.1f eV.  There should be signal in I0.' %
              dcm.energy.readback.get())
        yield from sleep(2.0)
        yield from self.kill_plan()
    def table(self):
        '''Pretty print a table of values for each ROI and for all four channels.
        '''
        BMMuser = user_ns['BMMuser']
        print(' ROI    Chan1      Chan2      Chan3      Chan4 ')
        print('=================================================')
        first_channel_number = self.channel_numbers[0]
        first_channel = self.get_channel(channel_number=first_channel_number)
        for r in first_channel.mcaroi_numbers:
            el = self.channels.channel01.get_mcaroi(mcaroi_number=r).name
            if len(el) > 3:
                continue
            if el != 'OCR':
                el = el[:-1]
            if '_value' in el:
                print(' None', end='')
                for channel_number in self.channel_numbers:
                    print(f"  {0:7}  ", end='')
                print('')
            elif el == BMMuser.element or el == 'OCR':
                print(go_msg(f' {el:3} '), end='')
                for channel in self.iterate_channels():
                    mcaroi = channel.get_mcaroi(mcaroi_number=r)
                    val = mcaroi.total_rbv.get()
                    if math.isnan(val):
                        val = 0
                    print(go_msg(f"  {int(val):7}  "), end='')

                print('')
            else:
                print(f' {el:3} ', end='')

                for channel in self.iterate_channels():
                    mcaroi = channel.get_mcaroi(mcaroi_number=r)
                    val = mcaroi.total_rbv.get()
                    if math.isnan(val):
                        val = 0
                    print(f"  {int(val):7}  ", end='')
                print('')
示例#14
0
 def roi_details(self):
     BMMuser = user_ns['BMMuser']
     print(' ROI  Elem   low   high')
     print('==========================')
     template = ' %3d  %-4s  %4d  %4d'
     for i, el in enumerate(self.slots):
         rs = self.channel1.rois
         this = getattr(rs, 'roi{:02}'.format(i+1))
         if el is None:
             print(template % (i+1, 'None', this.bin_low.value, this.bin_high.value))
         elif el == BMMuser.element:
             print(go_msg(template % (i+1, el.capitalize(), this.bin_low.value, this.bin_high.value)))
         else:
             print(template % (i+1, el.capitalize(), this.bin_low.value, this.bin_high.value))
 def table(self):
     '''Pretty print a table of values for each ROI and for all four channels.
     '''
     BMMuser = user_ns['BMMuser']
     print(' ROI    Chan1      Chan2      Chan3      Chan4 ')
     print('=================================================')
     for r in range(1, 17):
         el = getattr(self.channel1.rois, f'roi{r:02}').value.name
         if len(el) > 3:
             continue
         if el != 'OCR':
             el = el[:-1]
         if '_value' in el:
             print(' None', end='')
             for c in (1, 2, 3, 4):
                 print(f"  {0:7}  ", end='')
             print('')
         elif el == BMMuser.element or el == 'OCR':
             print(go_msg(f' {el:3} '), end='')
             for c in (1, 2, 3, 4):
                 val = getattr(
                     getattr(self, f'channel{c}').rois,
                     f'roi{r:02}').value.get()
                 if math.isnan(val):
                     val = 0
                 print(go_msg(f"  {int(val):7}  "), end='')
             print('')
         else:
             print(f' {el:3} ', end='')
             for c in (1, 2, 3, 4):
                 val = getattr(
                     getattr(self, f'channel{c}').rois,
                     f'roi{r:02}').value.get()
                 if math.isnan(val):
                     val = 0
                 print(f"  {int(val):7}  ", end='')
             print('')
示例#16
0
 def roi_details(self):
     BMMuser = user_ns['BMMuser']
     print(' ROI  Elem   low   high')
     print('==========================')
     template = ' %3d  %-4s  %4d  %4d'
     for i, el in enumerate(self.slots):
         this = self.get_channel(channel_number=1).get_mcaroi(
             mcaroi_number=i + 1)
         if el is None:
             print(template % (i + 1, 'None', this.min_x.get(),
                               this.min_x.get() + this.size_x.get()))
         elif el == BMMuser.element:
             print(
                 go_msg(template %
                        (i + 1, el.capitalize(), this.min_x.get(),
                         this.min_x.get() + this.size_x.get())))
         else:
             print(template % (i + 1, el.capitalize(), this.min_x.get(),
                               this.min_x.get() + this.size_x.get()))
示例#17
0
 def do_ChangeXtals(self):
     if user_ns['dcm']._crystal == '111':
         print(
             go_msg('You would like to change from the ') +
             whisper('Si(111)') + go_msg(' to the ') + bold_msg('Si(311)') +
             go_msg(' crystals...\n'))
         print(disconnected_msg('yield from change_xtals("311")'))
     else:
         print(
             go_msg('You would like to change from the ') +
             whisper('Si(311)') + go_msg(' to the ') + bold_msg('Si(111)') +
             go_msg(' crystals...\n'))
         print(disconnected_msg('yield from change_xtals("111")'))
     yield from null()
示例#18
0
def recover_slits2():
    inb  = user_ns['dm2_slits_i']
    outb = user_ns['dm2_slits_o']
    top  = user_ns['dm2_slits_t']
    bot  = user_ns['dm2_slits_b']
    slits2 = user_ns['slits2']
    yield from mv(inb.home_signal,  1)
    yield from mv(top.home_signal,  1)
    yield from sleep(1.0)
    print('Begin homing slits2 inboard/outboard & top/bottom:\n')
    hvalues = (inb.hocpl.get(), outb.hocpl.get(), top.hocpl.get(), bot.hocpl.get())
    while any(v == 0 for v in hvalues):
        hvalues = (inb.hocpl.get(), outb.hocpl.get(), top.hocpl.get(), bot.hocpl.get())
        strings = ['dm2_slits_i', 'dm2_slits_o', 'dm2_slits_t', 'dm2_slits_b']
        for i,v in enumerate(hvalues):
            strings[i] = go_msg(strings[i]) if hvalues[i] == 1 else error_msg(strings[i])
        print('  '.join(strings), end='\r')
        yield from sleep(1.0)
    print('\n')
    yield from mv(slits2.vsize, 1.1, slits2.hsize, 18)
示例#19
0
 def do_SlitHeight(self):
     print(go_msg('You would like to set the slit height...\n'))
     print(disconnected_msg('yield from slit_height()'))
     yield from null()
示例#20
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
示例#21
0
 def do_Spreadsheet(self):
     print(go_msg('You would like to import a spreadsheet...\n'))
     ## prompt for type of spreadsheet: wheel or glancing angle
     ret = user_ns['wmb'].spreadsheet()
     yield from null()
示例#22
0
 def do_AlignSlot(self):
     print(go_msg('You would like to align a wheel slot...\n'))
     yield from find_slot()
示例#23
0
 def do_AlignGA(self):
     print(go_msg('You would like to align the glancing angle stage...\n'))
     yield from align_ga()
示例#24
0
 def do_RockingCurve(self):
     print(go_msg('You would like to measure a rocking curve scan...\n'))
     print(disconnected_msg('yield from rocking_curve()'))
     yield from null()
示例#25
0
 def do_XAFS(self):
     print(go_msg('You would like to do an XAFS scan...\n'))
     howlong()
     yield from null()
示例#26
0
 def do_XRFSpectrum(self):
     print(go_msg('You would like to see an XRF spectrum...\n'))
     user_ns['xs'].measure_xrf()
     yield from null()