def send(self, addr, cmd, param=0, length=0): try: cmdname, limits, retlen = IPC_MAGIC[cmd] except KeyError as err: raise ProgrammingError(self, 'Command %s not supported' % cmd) from err if limits: if length != limits[0] or not limits[1] <= param <= limits[2]: raise ProgrammingError( self, 'Parameter %s outside allowed values %s for cmd ' '%s' % (param, limits, cmdname)) elif length or param: raise ProgrammingError( self, 'Sending parameters is not allowed ' 'for cmd %s' % cmdname) s = chr(addr) + chr(cmd) if length > 0: s += '%0*d' % (length, param) self.log.debug('sending %s to card %s', cmdname, addr) for i in range(self.comtries, 0, -1): try: return self._comm(s, retlen) except (CommunicationError, ProgrammingError): if i == 1: raise
def _startSequence(self, sequence): """Check and start the sequence.""" # check sequence for i, step in enumerate(sequence): if not hasattr(step, '__iter__'): step = (step, ) sequence[i] = step for action in step: try: action.check() except Exception as e: self.log.error('action.check for %r failed with %r', action, e) self.log.debug('_checkFailed returned %r', self._checkFailed(i, action, sys.exc_info())) # if the above does not raise, consider this as OK if self._seq_is_running(): raise ProgrammingError(self, 'sequence is still running!') # debug hint: if self.loglevel == 'debug': self.log.debug('generated sequence has %d steps:', len(sequence)) for i, step in enumerate(sequence): self.log.debug(' - step %d:', i + 1) for action in step: self.log.debug(' - action: %r', action) self._set_seq_status(status.BUSY, '') self._asyncSequence(sequence)
def doStart(self, target): """Changes the intended setpoint Logic is as follows: if target is below absmax of the tube, let regulation mode decide if we move the stick or the tube or both. The unused one is switched off by moving to its absmin value or 0, whatever is bigger. If target is above absmax of the tube, we set tube to its absmax and the stick to the target. In this case, mode is ignored. Normally the absmax of the tube is set to 300K, which is compatible with requirements from the SE-group. """ if target < self._attached_tube.absmax: if self.regulationmode == 'stick': self.__start_tube_stick(max(self._attached_tube.absmin, 0), target) elif self.regulationmode == 'tube': self.__start_tube_stick(target, max(self._attached_stick.absmin, 0)) elif self.regulationmode == 'both': self.__start_tube_stick( max(self._attached_tube.absmin, target), max(self._attached_stick.absmin, target)) else: raise ProgrammingError( self, 'unknown mode %r, don\'t know how' ' to handle it!' % self.regulationmode) else: self.log.debug('ignoring mode, as target %r is above %s.absmax', target, self._attached_tube.name) self.__start_tube_stick(self._attached_tube.absmax, target)
def _startRaw(self, target): """Initiate movement to the unmapped/raw value from the device. Must be implemented in derived classes! """ raise ProgrammingError( self, 'Somebody please implement a proper ' '_startRaw or doStart method!')
def _readRaw(self, maxage=0): """Read the unmapped/raw value from the device. Must be implemented in derived classes! """ raise ProgrammingError( self, 'Somebody please implement a proper ' '_readRaw or doRead method!')
def _mapTargetValue(self, target): """Hook for integration of transformed devices. This method is called to get a value to pass to `._startRaw()` and should map the target value to a raw value. """ raise ProgrammingError( self, 'Somebody please implement a proper ' '_mapTargetValue method!')
def _mapReadValue(self, value): """Hook for integration of transformed devices. This method is called with the value returned by `._readRaw()` and should map the raw value to the transformed value. """ raise ProgrammingError( self, 'Somebody please implement a proper ' '_readMapValue method!')
def doPreinit(self, mode): if self.loglevel == 'debug': self._taco_guard = self._taco_guard_log if self.taco_class is None: raise ProgrammingError('missing taco_class attribute in class ' + self.__class__.__name__) if mode != SIMULATION: self._dev = self._create_client() else: self._dev = HardwareStub(self)
def doRead(self, maxage=0): if self._attached_stick.target is not None: if self._attached_stick.target >= self._attached_tube.absmax: return self._attached_stick.read(maxage) if self.regulationmode in ('stick', 'both'): return self._attached_stick.read(maxage) elif self.regulationmode == 'tube': return self._attached_tube.read(maxage) else: raise ProgrammingError( self, 'unknown mode %r, don\'t know how to ' 'handle it!' % self.regulationmode)
def doReadSetpoint(self): if self._attached_stick.target is not None: if self._attached_stick.target >= self._attached_tube.absmax: return self._attached_stick.setpoint # take the more important one, closer to the sample. if self.regulationmode in ('stick', 'both'): return self._attached_stick.setpoint elif self.regulationmode == 'tube': return self._attached_tube.setpoint else: raise ProgrammingError( self, 'unknown mode %r, don\'t know how to ' 'handle it!' % self.regulationmode)
def to_k(value, unit): try: if unit == 'A-1': return value elif unit == 'A': return 2.0 * pi / value elif unit == 'meV': return 2.0 * pi * sqrt(value / ANG2MEV) elif unit == 'THz': return 2.0 * pi * sqrt(value * THZ2MEV / ANG2MEV) else: raise ProgrammingError('unknown energy unit %r' % unit) except (ArithmeticError, ValueError) as err: raise ComputationError('cannot convert %s A-1 to %s: %s' % (value, unit, err))
def from_k(value, unit): try: if unit == 'A-1': return value elif unit == 'A': return 2.0 * pi / value elif unit == 'meV': return ANG2MEV * value**2 / (2 * pi)**2 elif unit == 'THz': return ANG2MEV / THZ2MEV * value**2 / (2 * pi)**2 else: raise ProgrammingError('unknown energy unit %r' % unit) except (ArithmeticError, ValueError) as err: raise ComputationError('cannot convert %s A-1 to %s: %s' % (value, unit, err)) from None
def __init__(self, title, model, parnames=None, parstart=None, xmin=None, xmax=None): self.title = title self.model = model self.parnames = parnames if parnames is not None else [] self.parstart = parstart if parstart is not None else [] self.xmin = xmin self.xmax = xmax if (parstart is not None and len(self.parnames) != len(self.parstart)): raise ProgrammingError('number of param names (%d) must match ' 'number of starting values (%d)' % (len(self.parnames), len(self.parstart)))
def _comm(self, request, retlen, ping=False): if not ping: request += crc_ipc(request) request = STX + request + EOT self.log.debug('sending %r', convert(request)) with self._lock: response = self._transmit(request, retlen) # now check data self.log.debug('received %r', convert(response)) if not response: raise CommunicationError(self, 'no response') elif response == ACK: return 0 elif response == NAK: if ping: return 1 raise CommunicationError(self, 'CRC error: %r' % convert(request)) elif response == DC1: raise InvalidCommandError( self, 'invalid command number: %r' % convert(request)) elif response == DC2: raise ProgrammingError( self, 'invalid command parameter: %r' % convert(request)) elif response == DC3: raise CommunicationError( self, 'command failed, e.g. limit ' 'switch reached or hardware error') elif len(response) < 3: raise CommunicationError(self, 'response too short') elif response[0] != STX: raise CommunicationError(self, 'response should start with STX') elif response[-1] != EOT: raise CommunicationError(self, 'response should end with EOT') else: # good response! response = response[1:-1] # remove STX/EOT if len(response) > 2: # try to check CRC if response[-3:] != crc_ipc(response[:-3]): raise CommunicationError(self, 'wrong CRC on response') # return response integer (excluding address and command number) try: # command might fail if no value was transmitted return int(response[2:-3]) except ValueError as err: raise CommunicationError( self, 'invalid response: missing value (%s)' % err) from err
def doReadBustimeout(self): if self._dev and hasattr(self._dev, 'timeout'): return float(self._taco_guard(self._dev.timeout)) raise ProgrammingError(self, "TacoDevice has no 'timeout'!")