예제 #1
0
def pole_figure(numrows, speed, timedelta, sampleinfo):
    """Run a typical pole figure measurement.

    The command runs 'numrows' continuous scans over the 'phis' device, which
    makes a full turn (360 deg) during the measurement.

    The changed parameter device is 'chis'. It divides the angle of 90 deg into
    'numrows' steps, starting at the half of the stepsize. A 'numrows' of 6
    will generate the 'chis' positions of 172.5, 157.5, 142.5, 127.5, 112.5,
    and 97.5 deg.

    Examples::

        # create a pole figure measurement with 6 steps taking every 10 s a
        # picture
        >>> pole_figure(6, 0.25, 10, 'Alpha_Ti')

    """
    chis = session.getDevice('chis')
    phis = session.getDevice('phis')
    dchi = round(90.0 / numrows, 2) / 2.0
    # creating a list beginnig from 180 + dchi downsteps to 90 + dchi
    positions = numpy.arange(90 + dchi, 180, 2 * dchi)[::-1]
    maw(phis, 0)
    for i, chipos in enumerate(positions):
        move_dev(chis, round(chipos, 2), maxtries=2)
        sleep(5)
        start, end = (360., 0.) if i % 2 else (0., 360.)
        contscan(phis, start, end, speed, timedelta,
                 '%s_Chis_%s' % (sampleinfo, str(chis.read())))
    sleep(5)
    maw(phis, 0)
    sleep(5)
    maw(chis, 180)
    sleep(5)
예제 #2
0
def prepare(session, dataroot):
    """Prepare a dataset for StressSpec"""

    session.experiment.setDetectors(['adet'])

    # Create devices needed in data sinks
    for dev in ['xt', 'yt', 'zt', 'slits', 'slitm', 'slite', 'slitp', 'omgm']:
        session.getDevice(dev)

    # Adjust the monochromator to reasonable position and check it
    tthm = session.getDevice('tthm')
    tthm.maw(69)
    transm = session.getDevice('transm')
    wav = session.getDevice('wav')
    assert wav.plane == ''  # pylint: disable=compare-to-empty-string
    transm.maw('Ge')
    wav.plane = '311'
    wav.maw(1.7)

    # Perform different scans
    phis = session.getDevice('phis')
    timescan(1, t=0.05)
    scan(phis, 0, 0.1, 1, t=0.05, info='phi scan on time')
    scan(phis, 0, 0.1, 1, mon1=50, info='phi scan on monitor')
    contscan(phis, 0, 1, 1000, 0.001)

    yield
예제 #3
0
def omscan(hkl, width=None, speed=None, timedelta=None, **kwds):
    """Perform a continuous omega scan at the specified Q point.

    The default scan width is calculated from the instrumental resolution.

    Examples:

    >>> omscan((1, 0, 0))     # with default with, speed and timedelta
    >>> omscan((1, 0, 0), 5)  # with a width of 5 degrees
    >>> omscan((1, 0, 0), 5, 0.1, 1)   # with width, speed and timedelta
    """
    instr = session.instrument
    if not isinstance(instr, SXTalBase):
        raise NicosError('your instrument is not a sxtal diffractometer')
    if width is None:
        width = instr.getScanWidthFor(hkl)
    calc = dict(instr._extractPos(instr._calcPos(hkl)))
    om1 = calc['omega'] - width / 2.
    om2 = calc['omega'] + width / 2.
    cur_om = instr._attached_omega.read()
    if abs(cur_om - om1) > abs(cur_om - om2):
        om1, om2 = om2, om1
    maw(instr._attached_gamma, calc['gamma'], instr._attached_nu, calc['nu'],
        instr._attached_omega, om1)
    contscan(instr._attached_omega, om1, om2, speed, timedelta)
예제 #4
0
def test_contscan(session):
    m = session.getDevice('motor')
    mm = session.getDevice('manual')
    ContinuousScan.DELTA = 0.1
    session.experiment.detlist = [session.getDevice('det')]
    try:
        contscan(m, 0, 2, 10)
    finally:
        ContinuousScan.DELTA = 1.0
        session.experiment.detlist = []
    assert m.speed == 0  # reset to old value
    dataman = session.experiment.data
    dataset = dataman.getLastScans()[-1]
    assert dataset.devvaluelists
    assert all(0 <= res[0] <= 2 for res in dataset.devvaluelists)
    # no speed parameter
    assert raises(UsageError, contscan, mm, 0, 2)
    # preset and multistep not allowed
    assert raises(UsageError, contscan, m, 0, 2, 2, t=1)
    assert raises(UsageError, contscan, m, 0, 2, 2, manual=[0, 1])
예제 #5
0
def centerpeak(*args, **kwargs):
    """Center a peak with multiple scans over multiple devices.

    This does repeated scans of all devices to iteratively center a peak until
    the peak center does not shift anymore.  Starting position is the current
    position of all devices.

    Non-keyword arguments are devices to scan over. At least one is required.

    Supported keyword arguments are:

    * ``rounds`` - maximum number of rounds (a round is one scan per device).
      The default is 5.
    * ``steps`` - number of steps per side for each scan. The default is 15.
    * ``steps_devname`` - special number of steps per side for this device.
    * ``step`` - step size for each scan. The default is 0.1.
    * ``step_devname`` - special step size for this device.
    * ``convergence`` - maximum delta of peak center between two scans of a
      device, in units of the scan step size. The default is 0.5.
    * ``fit`` - fit function to use for determining peak center, see below.
    * ``cont`` - True/False whether to use continuous scans. Default is false.
    * all further keyword arguments (like ``t=1``) are used as detector
      presets.

    Examples::

       # default scan without special options, count 2 seconds
       >>> centerpeak(omega, gamma, 2)
       # scan with device-specific step size and number of steps
       >>> centerpeak(omega, gamma, step_omega=0.05, steps_omega=20, t=1)
       # allow a large number of rounds with very small convergence window
       # (1/5 of step size)
       >>> centerpeak(omega, gamma, rounds=10, convergence=0.2, t=1)
       # center using Gaussian peak fits
       >>> centerpeak(omega, gamma, fit='gauss', t=1)

    Fit functions:

    * ``'center_of_mass'``: default, works for any peak shape
    * ``'gauss'``: symmetric Gaussian
    """
    nrounds = 5
    devices = []
    defsteps = 15
    nsteps = {}
    defstepsize = 0.1
    stepsizes = {}
    preset = {}
    fit = 'center_of_mass'
    allowed_fit = {'center_of_mass', 'gauss'}
    continuous = False
    convergence = 0.5
    for devname in args:
        if isinstance(devname, number_types):
            preset['t'] = devname
        else:
            devices.append(session.getDevice(devname, Moveable))
    if not devices:
        raise UsageError('need at least one device to scan over')
    for kw, value in kwargs.items():
        if kw == 'rounds':
            nrounds = value
        elif kw == 'fit':
            if value not in allowed_fit:
                raise UsageError('fit function %s is not allowed' % value)
            fit = value
        elif kw == 'convergence':
            convergence = value
        elif kw == 'steps':
            defsteps = value
        elif kw == 'step':
            defstepsize = value
        elif kw == 'cont':
            continuous = bool(value)
        elif kw.startswith('step_'):
            dev = session.getDevice(kw[5:], Moveable)
            if dev not in devices:
                raise UsageError('device %s not in list of devices to scan' %
                                 dev)
            stepsizes[dev] = value
        elif kw.startswith('steps_'):
            dev = session.getDevice(kw[6:], Moveable)
            if dev not in devices:
                raise UsageError('device %s not in list of devices to scan' %
                                 dev)
            nsteps[dev] = value
        else:
            preset[kw] = value
    for dev in devices:
        if dev not in stepsizes:
            stepsizes[dev] = defstepsize
        if dev not in nsteps:
            nsteps[dev] = defsteps

    # main loop
    lastround = {dev: dev.read() for dev in devices}
    for i in range(nrounds):
        session.log.info('Round %d of %d', i + 1, nrounds)
        session.log.info('*' * 100)
        # results of last round
        thisround = {}
        for dev in devices:
            center = lastround[dev]
            if continuous:
                contscan(dev,
                         center - nsteps[dev] * stepsizes[dev],
                         center + nsteps[dev] * stepsizes[dev],
                         speed=stepsizes[dev] / preset.get('t', 1),
                         timedelta=preset.get('t', 1))
            else:
                cscan(dev, center, stepsizes[dev], nsteps[dev], *devices,
                      **preset)
            if session.mode == SIMULATION:
                thisround[dev] = center
            elif fit == 'center_of_mass':
                thisround[dev] = center_of_mass()
            elif fit == 'gauss':
                params, _ = gauss()
                minvalue = center - abs(stepsizes[dev] * nsteps[dev])
                maxvalue = center + abs(stepsizes[dev] * nsteps[dev])
                if params is None:
                    maw(dev, center)
                    session.log.error('no Gaussian fit found in this scan')
                    return
                fit_center, fit_ampl, _fit_fwhm, fit_bkgd = params
                if math.isnan(fit_center) or \
                   not (minvalue <= fit_center <= maxvalue) or \
                   fit_ampl < 0.5 * fit_bkgd:
                    maw(dev, center)
                    session.log.error('Gaussian peak too small, or center '
                                      'outside scanning area')
                    return
                thisround[dev] = fit_center
            maw(dev, thisround[dev])
        session.log.info('*' * 100)
        again = False
        for dev in devices:
            diff = abs(lastround[dev] - thisround[dev])
            session.log.info('%-10s center: %8.6g -> %8.6g (delta %8.6g)', dev,
                             lastround[dev], thisround[dev], diff)
            if session.mode == SIMULATION:
                again = i < 1
                if i == 1:
                    session.log.info('=> dry run: limiting to 2 rounds')
            elif diff > convergence * stepsizes[dev]:
                if i == nrounds - 1:
                    session.log.info(
                        '=> would need another round, but command'
                        ' limited to %d rounds', nrounds)
                else:
                    session.log.info('=> needs another round')
                again = True
        if not again:
            session.log.info('=> found convergence on peak:')
            for dev in devices:
                session.log.info('%-10s : %s', dev, dev.format(dev()))
            return
        lastround = thisround
예제 #6
0
def ScanDataset(name, speed=None, timedelta=None, start=1, cont=True):
    """Do an omega-scan over all HKL reflections in a given CSV dataset.

    Takes a CSV file created by `GenDataset()` (maybe edited) and does an
    omega scan over all HKLs in the list.

    Use ``start=N`` to start at a different line than the first.

    Use ``cont=False`` to select step scans instead of continuous scans.

    Examples::

       # omega scan of  all peaks in "low_t" with default settings
       >>> ScanDataset('low_t')
       # same, but with speed 0.1 and timedelta 1 second
       >>> ScanDataset('low_t', 0.1, 1)
       # start at row 100
       >>> ScanDataset('low_t', start=100)
       # with stepwise scans
       >>> ScanDataset('low_t', 0.1, 1, cont=False)
    """
    instr = session.instrument
    root = session.experiment.samplepath
    fullpath = path.join(root, name + '.csv')
    session.log.info('Reading reflection list from %s.', fullpath)

    all_pos = []
    with open(fullpath, 'r', encoding='utf-8') as fp:
        reader = csv.reader(fp)
        for row in reader:
            if row[0] == 'h':
                continue
            h, k, l, _, _, _, width = row[:7]
            all_pos.append(([float(h), float(k),
                             float(l)], float(width.replace(',', '.'))))

    session.log.info('%d reflections read.', len(all_pos))

    if start != 1:
        if len(all_pos) < start:
            session.log.info('Nothing to do.')
            return
        else:
            session.log.info('Starting at reflection number %d.', start)
            all_pos = all_pos[start - 1:]

    Remark('Scan dataset %s (%d reflections)' % (name, len(all_pos)))

    skipped = 0
    for i, (hkl, width) in enumerate(all_pos, start=start):
        session.log.info('')
        info = (i, len(all_pos) + start - 1, hkl[0], hkl[1], hkl[2])
        text = '*** Scanning %d/%d: (%4.4g %4.4g %4.4g)' % info
        scope = 'HKL %d/%d: (%4.4g %4.4g %4.4g)' % info
        if skipped:
            text += ' [%d skipped]' % skipped
            scope += ' [%d skipped]' % skipped
        session.log.info(text)
        session.beginActionScope(scope)
        try:
            calc = dict(instr._extractPos(instr._calcPos(hkl)))
            om1 = calc['omega'] - width / 2.
            om2 = calc['omega'] + width / 2.
            # optimization to avoid unnecessary omega movement,
            # currently disabled due to backlash concerns
            #
            # cur_om = instr._attached_omega.read()
            # if abs(cur_om - om1) > abs(cur_om - om2):
            #     om1, om2 = om2, om1
            umin, umax = instr._attached_omega.userlimits
            if om1 < umin:
                om1 = umin
            if om1 > umax:
                om1 = umax
            try:
                maw(instr._attached_gamma, calc['gamma'], instr._attached_nu,
                    calc['nu'], instr._attached_omega, om1)
            except SKIP_EXCEPTIONS:
                session.log.warning('Skipping scan', exc=1)
                skipped += 1
                continue
            except CONTINUE_EXCEPTIONS:
                session.log.warning('Positioning problem, continuing', exc=1)
            if cont:
                contscan(instr._attached_omega, om1, om2, speed, timedelta,
                         '(%4.4g %4.4g %4.4g)' % info[2:])
            else:
                stepsize = speed * timedelta
                # steps per side, not including the central point
                nsteps = int(round(width / 2 / stepsize))
                cscan(instr._attached_omega,
                      calc['omega'],
                      stepsize,
                      nsteps,
                      t=timedelta)
        finally:
            session.endActionScope()