def cscan(dev, *args, **kwargs): """Scan around a center. This command is a specialisation of the `scan()` command to scan around a center a number of points left from the center and the same number right from the center with a certain step size. The command takes as parameters the center, a step size, and number of points on each side of the center: >>> cscan(dev, 0, 1, 5) # scans around 0 from -5 to 5 in steps of 1. The total number of points is (2 * numperside) + 1. The above commands counts at -5, -4, ..., 5. The equivalent `scan()` command would be: >>> scan(dev, -5, 1, 11) The device can also be a list of devices that should be moved for each step. In this case, the center and step width also have to be lists: >>> cscan([dev1, dev2], [0, 0], [0.5, 1], 3) Resulting positions: ==== ==== ==== Step dev1 dev2 ==== ==== ==== 1 -1.5 -3.0 2 -1.0 -2.0 3 -0.5 -1.0 4 0.0 0.0 5 0.5 1.0 6 1.0 2.0 7 1.5 3.0 ==== ==== ==== """ def mkpos(centers, steps, numperside): return [[ center + (i - numperside) * step for (center, step) in zip(centers, steps) ] for i in range(2 * numperside + 1)] scanstr = _infostr('cscan', (dev, ) + args, kwargs) devs, values, restargs = _fixType(dev, args, mkpos) subscan = kwargs.pop(SUBSCAN, False) preset, scaninfo, detlist, envlist, move, multistep = \ _handleScanArgs(restargs, kwargs, scanstr) Scan(devs, values, None, move, multistep, detlist, envlist, preset, scaninfo, subscan=subscan).run()
def doStart(self): positions = [[p] for p in self.positions] dataset = Scan([self._adevs['scandev']], positions, positions, detlist=[self._adevs['detector']], preset=self._preset, subscan=True).run() # process the values... yvalues = [subset.detvaluelist[0] for subset in dataset.subsets] self._last = [sum(yvalues) / float(len(yvalues)), dataset.filenames[0]]
def doStart(self): positions = [[p] for p in self.positions] self.readresult = self._processDataset( Scan([self._attached_scandev], positions, None, detlist=[self._attached_detector], preset=self._preset, subscan=True).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 amplscan(dev1, start1, step1, numpoints1, dev2, start2, step2, numpoints2, t): scandet = session.getDevice('scandet') scandet.scandev = str(dev2) scandet.positions = [start2 + i * step2 for i in range(numpoints2)] dev1pos = [[start1 + i * step1] for i in range(numpoints1)] ds = Scan([session.getDevice(dev1)], dev1pos, None, detlist=[scandet], preset={ 't': t }).run() fit(CosineFit, 'A', dataset=ds)
def gridscan(dev, *args, **kwargs): """Scans over a grid of device positions and count detector(s). The orthogonal grid will spanned by the positions of each device. >>> gridscan([dev1, dev2], [-1, -2], [1, 1], [3, 5]) which generates a measurement over a grid with positions: ==== ==== ==== Step dev1 dev2 ==== ==== ==== 1 -1.0 -2.0 2 0.0 -2.0 3 1.0 -2.0 4 -1.0 -1.0 5 0.0 -1.0 6 1.0 -1.0 7 -1.0 0.0 8 0.0 0.0 9 1.0 0.0 10 -1.0 1.0 11 0.0 1.0 12 1.0 1.0 13 -1.0 2.0 14 0.0 2.0 15 1.0 2.0 ==== ==== ==== """ def mkpos(starts, steps, numpoints): if isinstance(numpoints, (list, tuple)): if len(starts) != len(numpoints): raise UsageError('start, steps, and numpoint arguments must ' 'have the same length') scanvals = [[ start + j * step for j in range(numpoint) ] for start, step, numpoint in zip(starts, steps, numpoints)] values = meshgrid(*scanvals) for i, grid in enumerate(values): values[i] = list(grid.reshape(grid.size)) return [tuple(v[i] for v in values) for i in range(len(values[0]))] raise UsageError('numpoints must be a list') scanstr = _infostr('gridscan', (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 doStart(self): positions = [[p] for p in self.positions] ds = Scan([session.getDevice(self.scandev)], positions, None, detlist=[self._attached_detector], preset=self._preset, subscan=True).run() xs, ys, dys, _, ds = _getData() fit = self.fitcls() res = fit.run(xs, ys, dys) if res._failed: self.log.warning('Fit failed: %s.' % res._message) self.readresult = [0] * (self._nparams * 2) else: session.notifyFitCurve(ds, fit.fit_title, res.curve_x, res.curve_y) readres = [] for par, err in zip(res._pars[1], res._pars[2]): readres.append(par) readres.append(err) self.readresult = readres
def appendscan(numpoints=5, stepsize=None): """Go on *numpoints* steps from the end of the last scan. *numpoints* can also be negative to prepend scan points. Examples: >>> appendscan(5) # append 5 more points to last scan >>> appendscan(-5) # append 5 more points to beginning of last scan If *stepsize* is given, the step size of the last scan will be overridden. Example: >>> scan(x, 10, 0.1, 10) # original scan >>> appendscan(10, 0.5) # continue the scan, but with other step size If the previous scan wasn't a scan with fixed step size and *stepsize* is not given, the new step size will be calculated as the averaged step size from the previous scan: >>> scan(x, [0, 0.1, 0.2, 0.5, 1]) >>> appendscan(5) moves x to the following positions: ==== ==== Step x ==== ==== 1/5 1.25 2/5 1.50 3/5 1.75 4/5 2.00 5/5 2.25 ==== ==== The scan data will be plotted into the same live plot, if possible, but will be saved into a separate data file. Scans with multiple devices are supported: >>> scan([x, y], [0, 1], [0.1, 0.2], 10) >>> appendscan(3, [0.05, 0.1]) # append 5 points with new stepsizes If the original scan was made over multiple devices, the *stepsize* must be a list with the same number of elements. """ if numpoints == 0: raise UsageError('number of points must be either positive or ' 'negative') direction = numpoints / abs(numpoints) dslist = session.experiment.data.getLastScans() if not dslist: raise NicosError('no last scan saved') contuids = [] # Find the last scan that wasn't an appendscan. i = len(dslist) - 1 while i >= 0: contuids.append(dslist[i].uid) if not dslist[i].continuation: break i -= 1 # If the last scan was an appendscan in the same direction, append to it, # else append to the original scan. This DWUMs for # scan(...) # appendscan(5) # appendscan(2) # appendscan(-3) if dslist[-1].cont_direction == direction: scan = dslist[-1] # to continue an appendscan in the negative direction, which has # the points reversed, we need to reverse the direction again if scan.cont_direction == -1: numpoints = -numpoints else: scan = dslist[i] n_devs = len(scan.devices) n_steps = len(scan.subsets) if n_steps < 2: raise NicosError('cannot append to scan with no positions') if stepsize is not None: if isinstance(stepsize, number_types): stepsize = [stepsize] if n_devs != len(stepsize): raise NicosError('the stepsize must have %d elements' % n_devs) else: stepsize = [None] * n_devs # create the new list of positions positions = [[None] * n_devs for _ in range(abs(numpoints))] # for each device involved in the scan for i in range(n_devs): # determine step size by first and last position pos1 = scan.startpositions[0][i] pos2 = scan.startpositions[n_steps - 1][i] if isinstance(pos1, (tuple, ndarray)): stepsizes = tuple( (b - a) / (n_steps - 1) for (a, b) in zip(pos1, pos2)) if numpoints > 0: for j in range(1, numpoints + 1): positions[j - 1][i] = tuple( b + j * s for (b, s) in zip(pos2, stepsizes)) else: for j in range(1, -numpoints + 1): positions[j - 1][i] = tuple( a - j * s for (a, s) in zip(pos1, stepsizes)) elif isinstance(pos1, number_types): if stepsize[i] is None: stepsize[i] = (pos2 - pos1) / (n_steps - 1) if numpoints > 0: startpos = pos2 + stepsize[i] else: stepsize[i] = -stepsize[i] startpos = pos1 + stepsize[i] for j in range(abs(numpoints)): positions[j][i] = startpos + j * stepsize[i] else: # we can't produce new values for this device raise NicosError('cannot append to this scan; some devices ' 'have nonnumeric values') numpoints = abs(numpoints) s = Scan(scan.devices, positions, [], None, None, scan.detectors, scan.environment, scan.preset, '%d more steps of last scan' % numpoints) s._xindex = scan.xindex s._continuation = contuids s._cont_direction = direction # envlist must be reset since Scan.__init__ messes with the ordering s._envlist[:] = scan.environment s.run()
def scan(dev, *args, **kwargs): """Scan over device(s) and count detector(s). A scan is used to collect data during the experiment depending on the position of one or more devices: - Move the devices to a new position, called a **point**, and wait until all devices have reached their position. - Start the detectors and wait until the requested time and/or monitor counts, called a **preset**, are reached. The output is a sequence of detector data corresponding to the device positions. The command has two basic modes: - Equidistant steps between the points A start value, the step size, and the number of points are given to the command: >>> scan(dev, 0, 1, 11) # counts at positions from 0 to 10 in steps of 1 For scans *around* a center, use the `cscan()` command. - A user defined list of points Here, the command expects a list of points: >>> scan(dev, [0, 1, 2, 3, 7, 8, 9]) # counts at the given positions Instead of one device, the command also handles a list of devices that should be moved for each step. In this case, the start and step width also have to be lists: >>> scan([dev1, dev2], [0, 0], [0.5, 1], 4) The list of points will be: ==== ==== ==== Step dev1 dev2 ==== ==== ==== 1 0.0 0.0 2 0.5 1.0 3 1.0 2.0 4 1.5 3.0 ==== ==== ==== This also works for the second operation mode: >>> scan([dev1, dev2], [[0, 1, 2, 3], [0, 1, 5, 7]]) with positions: ==== ==== ==== Step dev1 dev2 ==== ==== ==== 1 0.0 0.0 2 1.0 1.0 3 2.0 5.0 4 3.0 7.0 ==== ==== ==== """ def mkpos(starts, steps, numpoints): return [[start + i * step for (start, step) in zip(starts, steps)] for i in range(numpoints)] scanstr = _infostr('scan', (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()