def kscan(dev, start, step, numpoints, speed=None, *args, **kwargs): """Kinematic scan over device(s). The syntax is to give start, step and number of points: >>> kscan(dev, 3, 2, 4) # kinematic scan starting at 3 oscillate by 2 # 4 times with default speed >>> kscan(dev, 3, 2, 4, 1) # same scan as above with speed 1. oscillates between 3 and 5 during exposure for each interval of (3, 5) respectively (5, 3). """ def mkpos(starts, steps, numpoints): startpositions = [] endpositions = [] for i in range(numpoints): for start, step in zip(starts, steps): startpositions.append([start + (i % 2) * step]) endpositions.append([start + ((i + 1) % 2) * step]) return startpositions, endpositions scanargs = (start, step, numpoints) + args scanstr = _infostr('kscan', (dev, ) + scanargs, kwargs) devs, values, restargs = _fixTypeNPoints(dev, scanargs, mkpos) _preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(restargs, kwargs, scanstr) KScan(devs, values[0], values[1], speed, move, multistep, detlist, envlist, scaninfo).run()
def timeadscan(numpoints, header, parnames, parlist, psi, phi, mono, cad, t): """Time scan in multianalyzer setup. Count a number of times without moving devices, except the 'psi', 'phi', 'mono', and 'cad' before counting the first time. * numpoints - number of repititions can be -1 to scan for unlimited points (break using Ctrl-C or the GUI to quit). * header - additional header (maybe stored in data file) * parnames - additional parameters (stored in data file) * parlist - values to additional parnames (stored in data files), must have a length of 11 (one for each detector) and each entry must have the length of the parnames list * psipos - target position of psi device * phipos - target position of phi device * monopos - target position of mono device * cadpos - target position of cad device * timepreset - time to count per point Example: >>> timeadscan(5, 'The following configs are selected: configuration 419 ' 'ki= 5.40 Psi = 151.22 Phi0 = 65.50 CAD = -7.83 ' 'tilt =-2.00 config-type 2', ['h', 'k', 'l', 'ny/THz', 'x/cm', 'y/cm', 'theta/deg', 'phi/deg'], [ [-4.68, 2.97, 0.00, -6.64, 10.00, 2.00, -8.27, 71.89], [-4.51, 2.73, 0.00, -4.54, 8.00, 1.60, -8.71, 70.59], [-4.37, 2.52, 0.00, -2.76, 6.00, 1.20, -9.15, 69.31], [-4.23, 2.33, 0.00, -1.24, 4.00, 0.80, -9.58, 68.03], [-4.11, 2.16, 0.00, 0.07, 2.00, 0.40, -10.01, 66.76], [-4.00, 2.00, 0.00, 1.20, 0.00, 0.00, -10.43, 65.50], [-3.90, 1.85, 0.00, 2.18, -2.00, -0.40, -10.84, 64.25], [-3.80, 1.72, 0.00, 3.05, -4.00, -0.80, -11.24, 63.01], [-3.72, 1.60, 0.00, 3.80, -6.00, -1.20, -11.63, 61.79], [-3.64, 1.48, 0.00, 4.47, -8.00, -1.60, -12.01, 60.58], [-3.56, 1.38, 0.00, 5.07, -10.00, -2.00, -12.39, 59.38], ], 276.25, 19.995, 3.235, -0.8016, 1) """ preset = {'t': t} scanstr = _infostr('timeadscan', (numpoints, ) + (psi, phi, mono, cad), preset) move = [[session.getDevice(devname), pos] for devname, pos in zip( ['psi', 'phi', 'mono', 'cad'], [psi, phi, mono, cad])] scan = TimeADScan(header, parnames, parlist, numpoints, move, preset=preset, scaninfo='%s %s' % (scanstr, header)) scan.run()
def msingle(settings, *args, **kwargs): """Single MIEZE counting. First argument is a list of MIEZE settings or -1 to scan all setings. All other arguments are handled like for `count`. """ scanstr = _infostr('msingle', (settings, ) + args, kwargs) preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(args, kwargs, scanstr) MiezeScan(settings, [], [], move, multistep, detlist, envlist, preset, scaninfo).run()
def sscan(dev, *args, **kwargs): """Scan over device(s) and count detector(s). The general syntax is either to give start, step and end: >>> sscan(dev, 0, 1, 10) # scans from 0 to 10 in steps of 1. or a list of positions to scan: >>> sscan(dev, [0, 1, 2, 3, 7, 8, 9, 10]) # scans at the given positions. For floating point arguments, the length of the result is ``int(round((end - start) / step + 1)``. Because of floating point overflow, this rule may result in the last element being greater than ``end``, e.g. >>> sscan(dev, 30, .1, 30.19) # scans from 30 to 30.2 in steps of 0.1. """ def mkpos(starts, steps, ends): def mk(starts, steps, numpoints): return [[start + i * step for (start, step) in zip(starts, steps)] for i in range(numpoints)] # use round to handle floating point overflows numpoints = [ int(round((end - start) / step + 1)) for (start, step, end) in zip(starts, steps, ends) ] if all(n == numpoints[0] for n in numpoints): if numpoints[0] > 0: if numpoints[0] > 1: return mk(starts, steps, numpoints[0]) else: raise UsageError("invalid number of points. At least two " "points are necessary to define a range " "scan. Please check parameters.") else: raise UsageError("negative number of points. Please check " "parameters. Maybe step parameter has wrong" "sign.") else: raise UsageError("all entries must generate the same number of " "points") scanstr = _infostr("sscan", (dev, ) + args, kwargs) devs, values, restargs = _fixType(dev, args, mkpos) preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(restargs, kwargs, scanstr) Scan(devs, values, None, move, multistep, detlist, envlist, preset, scaninfo).run()
def walltimecount(numpoints, walltime, *args, **kwargs): """Count a number of times for the given amount of time on wall. "numpoints" can be -1 to scan for unlimited points (break using Ctrl-C or the GUI to quit). "walltime" provides the time in seconds Example: >>> walltimecount(500, 10) # counts 500 times, every count for 10 seconds A special "delay" argument is supported to allow time delays between two points: >>> walltimecount(500, 2, delay=5) """ scanstr = _infostr('walltimecount', ( numpoints, walltime, ) + args, kwargs) preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(args, kwargs, scanstr) # Get AMOR detector if not detlist: detlist = session.experiment.detectors detector = None for det in detlist: if isinstance(det, SinqDetector): detector = det if not detector: session.log.error('Detector not found in the detector list') # Set the beam threshold to 0 oldthreshold = detector.threshold # Complete the scan scan = WallTimeScan([], [], numpoints, walltime, move, multistep, detlist, envlist, preset, scaninfo) scan.run() # Reset the beam threshold to oldvalue detector.threshold = oldthreshold
def mscan(settings, dev, *args, **kwargs): """MIEZE scan over device(s). First argument is a list of MIEZE settings or -1 to scan all settings. All other arguments are handled like for `scan`. """ def mkpos(starts, steps, numsteps): return [[start + i * step for (start, step) in zip(starts, steps)] for i in range(numsteps)] scanstr = _infostr('mscan', (settings, dev) + args, kwargs) devs, values, restargs = _fixType(dev, args, mkpos) preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(restargs, kwargs, scanstr) MiezeScan(settings, devs, values, move, multistep, detlist, envlist, preset, scaninfo).run()
def atscan(time, *args, **kwargs): """A timescan that has an adjustable running time.""" time = parseDuration(time, 'atscan') scanstr = _infostr('vartimescan', (time, ) + args, kwargs) target = kwargs.pop('target', 'eta') preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(args, kwargs, scanstr) scan = VariableTimeScan([], [], move, multistep, detlist, envlist, preset, scaninfo, totaltime=time, target=target) scan.run()
def qscan(Q, dQ, numpoints, *args, **kwargs): """Perform a single-sided Q scan. The *Q* and *dQ* arguments can be lists of 3 or 4 components, or a `Q` object. Example: >>> qscan((1, 0, 0, 0), (0, 0, 0, 0.1), 11, kf=1.55, mon1=100000) will perform an energy scan at (100) from 0 to 1 meV (or THz, depending on the instrument setting) with the given constant kf and the given monitor counts per point. The special "plot" parameter can be given to plot the scan instead of running it: * plot='res' -- plot resolution ellipsoid along scan * plot='hkl' -- plot position of scan points in scattering plane """ Q, dQ = _getQ(Q, 'Q'), _getQ(dQ, 'dQ') scanstr = _infostr('qscan', (Q, dQ, numpoints) + args, kwargs) plotval = kwargs.pop('plot', None) preset, scaninfo, detlist, envlist, move, multistep, Q, dQ = \ _handleQScanArgs(args, kwargs, Q, dQ, scanstr) if all(v == 0 for v in dQ) and numpoints > 1: raise UsageError('scanning with zero step width') values = [[(Q[0] + i * dQ[0], Q[1] + i * dQ[1], Q[2] + i * dQ[2], Q[3] + i * dQ[3])] for i in range(numpoints)] if plotval == 'res': resscan(*(p[0] for p in values), kf=kwargs.get('kf'), ki=kwargs.get('ki')) elif plotval == 'hkl': hklplot(scan=[p[0] for p in values], kf=kwargs.get('kf'), ki=kwargs.get('ki')) else: scan = QScan(values, move, multistep, detlist, envlist, preset, scaninfo) scan.run()
def qscan(Q, dQ, numpoints, *args, **kwargs): """Perform a single-sided Q step scan. The *Q* and *dQ* arguments should be lists of 3 components. Example: >>> qscan((1, 0, 0), (0, 0, 0.1), 11, mon1=100000) will perform an L scan at (100) with the given monitor counts per point. """ Q, dQ = _getQ(Q, 'Q'), _getQ(dQ, 'dQ') scanstr = _infostr('qscan', (Q, dQ, numpoints) + args, kwargs) preset, scaninfo, detlist, envlist, move, multistep, Q, dQ = \ _handleQScanArgs(args, kwargs, Q, dQ, scanstr) if all(v == 0 for v in dQ) and numpoints > 1: raise UsageError('scanning with zero step width') values = [[(Q[0] + i * dQ[0], Q[1] + i * dQ[1], Q[2] + i * dQ[2])] for i in range(numpoints)] scan = QScan(values, move, multistep, detlist, envlist, preset, scaninfo) scan.run()
def qcscan(Q, dQ, numperside, *args, **kwargs): """Perform a centered Q scan. The *Q* and *dQ* arguments can be lists of 3 or 4 components, or a `Q` object. Example: >>> qcscan((1, 0, 0, 1), (0.001, 0, 0, 0), 20, mon1=1000) will perform a longitudinal scan around (100) with the given monitor counts per point. The special "plot" parameter can be given to plot the scan instead of running it: * plot='res' -- plot resolution ellipsoid along scan * plot='hkl' -- plot position of scan points in scattering plane """ Q, dQ = _getQ(Q, 'Q'), _getQ(dQ, 'dQ') scanstr = _infostr('qcscan', (Q, dQ, numperside) + args, kwargs) plotval = kwargs.pop('plot', None) preset, scaninfo, detlist, envlist, move, multistep, Q, dQ = \ _handleQScanArgs(args, kwargs, Q, dQ, scanstr) if all(v == 0 for v in dQ) and numperside > 0: raise UsageError('scanning with zero step width') values = [[(Q[0] + i * dQ[0], Q[1] + i * dQ[1], Q[2] + i * dQ[2], Q[3] + i * dQ[3])] for i in range(-numperside, numperside + 1)] if plotval == 'res': resscan(*(p[0] for p in values), kf=kwargs.get('kf'), ki=kwargs.get('ki')) elif plotval == 'hkl': hklplot(scan=[p[0] for p in values], kf=kwargs.get('kf'), ki=kwargs.get('ki')) else: scan = QScan(values, move, multistep, detlist, envlist, preset, scaninfo) scan.run()
def qcscan(Q, dQ, numperside, *args, **kwargs): """Perform a centered Q step scan. The *Q* and *dQ* arguments should be lists of 3 components. Example: >>> qcscan((1, 0, 0), (0.001, 0, 0), 20, mon1=1000) will perform a longitudinal scan around (100) with the given monitor counts per point. """ Q, dQ = _getQ(Q, 'Q'), _getQ(dQ, 'dQ') scanstr = _infostr('qcscan', (Q, dQ, numperside) + args, kwargs) preset, scaninfo, detlist, envlist, move, multistep, Q, dQ = \ _handleQScanArgs(args, kwargs, Q, dQ, scanstr) if all(v == 0 for v in dQ) and numperside > 0: raise UsageError('scanning with zero step width') values = [[(Q[0] + i * dQ[0], Q[1] + i * dQ[1], Q[2] + i * dQ[2])] for i in range(-numperside, numperside + 1)] scan = QScan(values, move, multistep, detlist, envlist, preset, scaninfo) scan.run()
def __init__(self, settings, args, kwargs): # pylint: disable=super-init-not-called scanstr = _infostr('mmanualscan', (settings, ) + args, kwargs) preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(args, kwargs, scanstr) self.scan = MiezeManualScan(settings, move, multistep, detlist, envlist, preset, scaninfo)