def sleep(secs): """Sleep for a given number of seconds. This is different from Python's `time.sleep()` in that it allows breaking and stopping the sleep, and supports dry run mode. Fractional values are supported. Examples: >>> sleep(10) # sleep for 10 seconds >>> sleep(0.5) # sleep for half a second """ session.log.info('sleeping for %.1f seconds...', secs) if session.mode == SIMULATION: session.clock.tick(secs) return def f_notify(tmr): session.breakpoint(2) # allow break and continue here session.action('%s left' % formatDuration(tmr.remaining_time())) session.beginActionScope('Sleeping') session.action('%s left' % formatDuration(secs)) try: tmr = Timer(secs) tmr.wait(interval=1.0, notify_func=f_notify) finally: session.endActionScope()
def run(self): if session.mode == SIMULATION: session.clock.tick(self.duration) return if self.duration > 3: session.beginActionScope(self.reason or 'Sleeping %s (H:M:S)' % timedelta(seconds=self.duration)) self.endtime = currenttime() + self.duration
def pointScope(self, num): if self.dataset.npoints == 0: session.beginActionScope('Point %d' % num) else: session.beginActionScope('Point %d/%d' % (num, self.dataset.npoints)) try: yield finally: session.endActionScope()
def prepareScan(self, position): # XXX with actionscope session.beginActionScope('Moving to start') try: # the move-before devices if self._firstmoves: fm_devs, fm_pos = zip(*self._firstmoves) self.moveDevices(fm_devs, fm_pos) # the scanned-over devices self.moveDevices(self._devices, position) finally: session.endActionScope()
def run(self): if not self._subscan and getattr(session, '_currentscan', None): raise NicosError('cannot start scan while another scan is running') # stop previous inner_count / acquisition thread if available stop_acquire_thread() session._currentscan = self # XXX(dataapi): this is too early, dataset has no number yet session.beginActionScope(self.shortDesc()) try: self._inner_run() finally: session.endActionScope() session._currentscan = None return self.dataset
def execute(self, controller): """Execute the script in the given namespace, using "controller" to execute individual blocks. """ session.scriptEvent('start', (self.name, self.text)) session.countloop_request = None # reset any pause flag from before # this is to allow the traceback module to report the script's # source code correctly updateLinecache('<script>', self.text) # note: checking session._experiment since using session.experiment # would try to create the device, which means you can't execute any # command when the experiment fails if session._experiment and session.mode == MASTER: session.experiment.scripts += [self.text] self._exp_script_index = len(session.experiment.scripts) - 1 if self.name: session.elogEvent('scriptbegin', self.name) session.beginActionScope(path.basename(self.name)) # notify clients of "input" session.log.log(INPUT, formatScript(self)) try: while self.curblock < len(self.code) - 1: self._run.wait() self.curblock += 1 self.blockStart = time.time() self.emitETA(controller) controller.start_exec(self.code[self.curblock], controller.namespace, None, self.settrace) finally: if self.name: session.endActionScope() if session._experiment and session.mode == MASTER: session.experiment.scripts = session.experiment.scripts[:-1] if self.name: session.elogEvent('scriptend', self.name)
def __enter__(self): session.beginActionScope(self.filename) if session.experiment and session.mode in (MASTER, SIMULATION): session.experiment.scripts += [self.code] session.elogEvent('scriptbegin', self.filename)
def __enter__(self): session.beginActionScope(self.name)
def acquire(point, preset, iscompletefunc=None): """Low-level acquisition function. The loop delay is configurable in the instrument object, and defaults to 0.025 seconds. The result is stored in the given argument, which must be an empty list. This is so that a result can be returned even when a stop exception is propagated upwards. The *iscompletefunc* callback can be used to influence the stop of the detectors. When *iscompeletefunc* returns `True` the detectors will be stopped. This can be useful to implement scans with software synchronisation, e.g. stopping of the detector when the movement of the scanned axis has been finished although the preset has not yet been fulfilled. """ if iscompletefunc is None: # do not influence count loop using callback iscompletefunc = lambda: False # put detectors in a set and discard them when completed detset = set(point.detectors) delay = (session.instrument and session.instrument.countloopdelay or 0.025 if session.mode != SIMULATION else 0.0) dataman = session.experiment.data session.beginActionScope('Counting') if session.countloop_request: _wait_for_continuation(delay, only_pause=True) for det in point.detectors: det.setPreset(**preset) for det in point.detectors: det.prepare() for det in point.detectors: waitForCompletion(det) dataman.updateMetainfo() point.started = currenttime() try: for det in point.detectors: det.start() except: session.endActionScope() raise session.delay(delay) try: quality = None while True: looptime = currenttime() for det in list(detset): if session.mode != SIMULATION: quality = det.duringMeasureHook(looptime - point.started) if det.isCompleted(): det.finish() quality = FINAL if quality: try: res = det.readResults(quality) except Exception: det.log.exception('error reading measurement data') res = None dataman.putResults(quality, {det.name: res}) if quality == FINAL: detset.discard(det) if not detset: # all detectors finished measuring break if session.countloop_request: for det in detset: if not det.pause(): session.log.warning( 'detector %r could not be paused', det.name) if not _wait_for_continuation(delay): for det in detset: # next iteration of loop will see det is finished det.finish() else: for det in detset: det.resume() if iscompletefunc(): # stop via callback function for det in detset: det.stop() session.delay(delay) except BaseException as e: exc_info = sys.exc_info() point.finished = currenttime() if e.__class__.__name__ != 'ControlStop': session.log.warning('Exception during count, trying to save data', exc=True) for det in detset: try: # XXX: in theory, stop() can return True or False to indicate # whether saving makes sense. # # However, it might be better to leave that to the data sink # handling the INTERRUPTED quality. det.stop() res = det.readResults(INTERRUPTED) except Exception: det.log.exception('error reading measurement data') res = None try: dataman.putResults(INTERRUPTED, {det.name: res}) except Exception: det.log.exception('error saving measurement data') reraise(*exc_info) finally: point.finished = currenttime() session.endActionScope()
def manualBegin(self): session.beginActionScope('Scan') self.beginScan()
def waitfor(dev, condition, timeout=86400): """Wait for a device until a condition is fulfilled. Convenience function to avoid writing code like this: >>> while not motor.read() < 10: ... sleep(0.3) which now can be written as: >>> waitfor(motor, '< 10') The supported conditions are [#]_: - '<', '<=', '==', '!=', '>=', '>' with a value - 'is False', 'is True', 'is None' - 'in list', where list could be a Python list or tuple An optional timeout value can be added, which denominates the maximum time the command will wait (in seconds). If the timeout value is reached, an error will be raised. The default timeout value is 86400 seconds (1 day). Example: >>> waitfor(T, '< 10', timeout=3600) Will wait a maximum of 1 hour for T to get below 10. .. note:: In contrast to the `wait()` command this command will not only wait until the target is reached. You may define also conditions which represent intermediate states of a movement or you may wait on external trigger signals and so on. .. [#] The device value, determined by ``dev.read()``, will be added in front of the condition, so the resulting conditions is: >>> dev.read() < 10 The condition parameter will be given as a simple comparison to the value of the device. """ dev = session.getDevice(dev, Readable) full_condition = '_v %s' % condition try: ast.parse(full_condition) except Exception: raise UsageError('Could not parse condition %r' % condition) if session.mode == SIMULATION: return def check(tmr): session.breakpoint(2) # allow break and continue here waitfor.cond_fulfilled = eval(full_condition, {}, {'_v': dev.read(0)}) if waitfor.cond_fulfilled: session.log.info('Waiting for \'%s %s\' finished.', dev, condition) tmr.stop() waitfor.cond_fulfilled = False try: session.beginActionScope('Waiting until %s %s' % (dev, condition)) tmr = Timer(timeout if timeout else 86400) # max wait time 1 day tmr.wait(dev._base_loop_delay * 3, check) finally: if not waitfor.cond_fulfilled: raise NicosTimeoutError( dev, 'Waiting for \'%s %s\' timed out.' % (dev, condition)) session.endActionScope()
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()
def multiWait(devices): """Wait for the *devices*. Returns a dictionary mapping devices to current values after waiting. This is the main waiting loop to be used when waiting for multiple devices. It checks the device status until all devices are OK or errored. Errors raised are handled like in the following way: The error is logged, and the first exception with the highest serverity (exception in `CONTINUE_EXECPTIONS` < `SKIP_EXCPTIONS` < other exceptions) is re-raised at the end. *baseclass* allows to restrict the devices waited on. """ from nicos.core.device import Waitable def get_target_str(): return ', '.join( '%s -> %s' % (dev, dev.format(dev.target)) if hasattr(dev, 'target') else str(dev) for dev in reversed(devlist)) delay = 0.3 final_exc = None devlist = list(devIter(devices, baseclass=Waitable, allwaiters=True)) session.log.debug('multiWait: initial devices %s, all waiters %s', devices, devlist) values = {} loops = -2 # wait 2 iterations for full loop eta_update = 1 if session.mode != SIMULATION else 0 first_ts = currenttime() session.beginActionScope('Waiting') eta_str = '' target_str = get_target_str() session.action(target_str) try: while devlist: session.log.debug('multiWait: iteration %d, devices left %s', loops, devlist) loops += 1 for dev in devlist[:]: try: done = dev.isCompleted() if done: dev.finish() except Exception: final_exc = filterExceptions(sys.exc_info(), final_exc) # remove this device from the waiters - we might still have # its subdevices in the list so that multiWait() should not # return until everything is either OK or ERROR devlist.remove(dev) if devlist: # at least one more device left, show the exception now dev.log.exception('while waiting') continue if not done: # we found one busy dev, normally go to next iteration # until this one is done (saves going through the whole # list of devices and doing unnecessary HW communication) if loops % 10: break # every 10 loops, go through everything to get an accurate # display in the action line continue if dev in devices: # populate the results dictionary, but only with the values # of excplicitly given devices values[dev] = dev.read() # this device is done: don't wait for it anymore devlist.remove(dev) target_str = get_target_str() session.action(eta_str + target_str) if devlist: if eta_update >= 1: eta_update -= 1 now = currenttime() eta = {dev.estimateTime(now - first_ts) for dev in devlist} eta.discard(None) # use max here as we wait for ALL movements to finish eta_str = ('estimated %s left / ' % formatDuration(max(eta)) if eta else '') session.action(eta_str + target_str) session.delay(delay) eta_update += delay if final_exc: reraise(*final_exc) finally: session.endActionScope() session.log.debug('multiWait: finished') return values