def setup_pv(pvname, con_cb=None, mon_cb=None, signal=None, mon_cb_once=False): """ Initialize an EPICS PV using psp with proper callbacks. :param pvname: EPICS PV name :type pvname: str :param con_cb: Connection callback. If left as None and provided with signal, emit our value from signal as the callback. :type con_cb: function(isconnected=None) :param mon_cb: Monitor callback. If left as None and provided with signal, emit our value from signal as the callback. :type mon_cb: function(errors=None) :param signal: Signal to emit our value on as the default callback when con_cb or mon_cb are left as None. Check the base :class:`PyDMConnection` class for available signals. :type signal: pyqtSignal :param mon_cb_once: True if we only want the monitor callback to run once. :type mon_cb_once: bool :rtype: Pv """ pv = Pv(pvname, use_numpy=True) if signal is None: default_mon_cb = lambda e: None else: default_mon_cb = generic_mon_cb(pv, signal) pv.add_connection_callback(con_cb or generic_con_cb(pv)) pv.add_monitor_callback(mon_cb or default_mon_cb, once=mon_cb_once) pv.connect(None) return pv
def caPutArray(pvName, value, timeout=-1.0): try: tmo = float(timeout) # See if this PV exists pv = Pv(pvName) pv.connect(1.0) # Convert value to the appropriate type for this PV # Assumption is that PV is a waveform record if isinstance(value, str): # Convert string values to a tuple value = stringToTuple(value) if not isinstance(value, tuple): raise TypeError, "Pv.put Error: value not a tuple for waveform PV" if len(value) != len(pv.value): raise TypeError, "Pv.put Error: Element count mismatch" pv.put_data(value, tmo) except Exception, msg: if verbose: print "Unable to connect to PV:", pvName if showCAErrors: print >> sys.stderr, "failed: pyca exception: ", msg return
def connect(self): Pv.connect(self, timeout=1.0) self.connected = True # self.monitor_cb = self.changed evtmask = pyca.DBE_VALUE | pyca.DBE_LOG | pyca.DBE_ALARM self.monitor(evtmask) pyca.flush_io()
def setup_pv(pvname, con_cb=None, mon_cb=None, rwaccess_cb=None, signal=None, mon_cb_once=False): """ Initialize an EPICS PV using psp with proper callbacks. :param pvname: EPICS PV name :type pvname: str :param con_cb: Connection callback. If left as None and provided with signal, emit our value from signal as the callback. :type con_cb: function(isconnected=None) :param mon_cb: Monitor callback. If left as None and provided with signal, emit our value from signal as the callback. :type mon_cb: function(errors=None) :param rwaccess_cb: Read/write access state callback. :type rwaccess_cb: function(access_state) :param signal: Signal to emit our value on as the default callback when con_cb or mon_cb are left as None. Check the base :class:`PyDMConnection` class for available signals. :type signal: Signal :param mon_cb_once: True if we only want the monitor callback to run once. :type mon_cb_once: bool :rtype: Pv """ pv = Pv(pvname, use_numpy=True) if signal is None: default_mon_cb = lambda e: None else: default_mon_cb = generic_mon_cb(pv, signal) pv.add_connection_callback(con_cb or generic_con_cb(pv)) pv.add_monitor_callback(mon_cb or default_mon_cb, once=mon_cb_once) if rwaccess_cb: pv.add_rwaccess_callback(rwaccess_cb) pv.connect(None) return pv
def caput(pvname, value, timeout=1.0): try: pv = Pv(pvname) pv.connect(timeout) pv.get(ctrl=False, timeout=timeout) pv.put(value, timeout) pv.disconnect() except pyca.pyexc, e: print 'pyca exception: %s' % (e)
def reconfigStream(cameraPvName, streamName, verbose=False): streamPvName = cameraPvName + ":" + streamName try: streamTypePv = Pv(streamPvName + ":StreamType") streamTypePv.connect(0.5) streamTypePv.get(timeout=1.0) except Exception, msg: if verbose: print "Stream %s not found." % streamName return
def caget_async(pvname): try: pv = Pv(pvname) pv.get_done = threading.Event() pv.connect_cb = lambda isconn: __connect_callback(pv, isconn) pv.getevt_cb = lambda e=None: __get_callback(pv, e) pv.connect(-1) return pv except pyca.pyexc, e: print 'pyca exception: %s' % (e) return None
def caget(pvname, timeout=1.0): try: pv = Pv(pvname) pv.connect(timeout) pv.get(ctrl=False, timeout=timeout) v = pv.value pv.disconnect() return v except pyca.pyexc, e: print 'pyca exception: %s' % (e) return None
def caPutValue(pvName, value, verbose=True): try: # See if this PV exists pv = Pv(pvName) pv.connect(1.0) pv.put(value, timeout=1.0) except Exception, msg: if verbose: print "Unable to connect to PV:", pvName if showCAErrors: print >> sys.stderr, "failed: pyca exception: ", msg return
def connectPv(name, timeout=-1.0): try: pv = Pv(name) if timeout < 0: pv.connect_cb = lambda isconn: __connect_callback(pv, isconn) pv.connect(timeout) else: pv.connect(timeout) pv.get(False, timeout) return pv except: return None
class Magnet(object): kick_delta = 0.0002 #in kG def __init__(self, device_name, z_pos): self.device_name = device_name self.z = z_pos self.bctrl_pv = Pv("{}:BCTRL".format(device_name)) self.bact_pv = Pv("{}:BACT".format(device_name)) @classmethod def pv_count(cls): return 2 @property def name(self): return self.device_name def connect(self): self.bctrl_pv.connect() self.bact_pv.connect() def connected(self): if self.bctrl_pv.state() == 2 and self.bact_pv.state() == 2: return True else: return False def monitor(self): self.bctrl_pv.monitor(pyca.DBE_VALUE) self.bact_pv.monitor(pyca.DBE_VALUE) @property def kick_setpoint(self): return self.bctrl_pv.data["value"] @kick_setpoint.setter def kick_setpoint(self, new_setpoint): return self.bctrl_pv.put(new_setpoint) @property def kick_readback(self): return self.bact_pv.data["value"] def increase_kick(self): before_val = self.kick_setpoint new_val = before_val + (self.kick_delta) self.kick_setpoint = new_val def decrease_kick(self): before_val = self.kick_setpoint new_val = before_val - (self.kick_delta) self.kick_setpoint = new_val
def caGetValue(pvName, verbose=True, timeout=0.1): try: # See if this PV exists pv = Pv(pvName) pv.connect(timeout) pv.get() return pv.value except Exception, msg: if verbose: print "Unable to connect to PV: %s" % pvName if showCAErrors: print >> sys.stderr, "failed: pyca exception: ", msg return None
def printPvNameValue(pvName): try: pv = Pv(pvName) pv.connect(0.1) pv.get() if isinstance(pv.value, str): print "%s \"%-.30s\"" % (pv.name, pv.value) else: print "%s %-.30s" % (pv.name, pv.value) except pyca.pyexc, msg: if showCAErrors: print >> sys.stderr, "failed: pyca exception: ", msg pass
def caget(pvname,timeout=30.0): try: pv = Pv(pvname) pv.connect(timeout) pv.get(ctrl=False, timeout=timeout) v = pv.value pv.disconnect() return v except pyca.pyexc as e: print('pyca exception: %s' %(e)) return None except pyca.caexc as e: print('channel access exception: %s' %(e)) return None
def caput(pvname, value, timeout=1.0, **kw): try: pv = Pv(pvname) pv.connect(timeout) pv.get(ctrl=False, timeout=timeout) try: if kw['enum']: pv.set_string_enum(True) except: pass pv.put(value, timeout=timeout) pv.disconnect() except pyca.pyexc, e: print 'pyca exception: %s' % (e)
def caget(pvname, timeout=1.0, **kw): try: pv = Pv(pvname) pv.connect(timeout) try: if kw['enum']: pv.set_string_enum(True) except: pass pv.get(ctrl=False, timeout=timeout) v = pv.value pv.disconnect() return v except pyca.pyexc as e: print('pyca exception: %s' % (e)) return None except pyca.caexc as e: print('channel access exception: %s' % (e)) return None
# ---------------------------------------------------------------------- if __name__ == "__main__": options = Options(['cameraPv', 'stream'], [], ['verbose']) try: options.parse() except Exception, msg: options.usage(str(msg)) sys.exit() cameraPvName = options.cameraPv streamName = options.stream try: camSizeXPv = Pv(cameraPvName + ":ArraySizeX_RBV") camSizeXPv.connect(0.1) camSizeXPv.get(timeout=1.0) except Exception, msg: print "Camera not accessible: ", msg sys.exit() verbose = False if options.verbose is not None: verbose = True if streamName != 'all': reconfigStream(cameraPvName, streamName, verbose=verbose) else: showCAErrors = False reconfigStream(cameraPvName, "DATA1", verbose=verbose) reconfigStream(cameraPvName, "IMAGE1", verbose=verbose) reconfigStream(cameraPvName, "IMAGE2", verbose=verbose)
def caget(pvname): pv = Pv(pvname) pv.connect(5.) pv.get(False, 5.) pv.disconnect() return pv.value
if __name__ == '__main__': options = Options(['motorpvname', 'start', 'end', 'delta'], [], []) try: options.parse() except Exception, msg: options.usage(str(msg)) sys.exit() motorpvname = options.motorpvname position = float(options.start) end = float(options.end) delta = float(options.delta) try: motorpv = Pv(motorpvname) motorpv.connect(1.0) dmovpv = donemoving(motorpvname + '.DMOV') steps = int((end-position)/delta) for step in range(0, steps+1): starttime = time.time() motorpv.put(position) pyca.pend_io(.1) dmovpv.wait_for_done(10) elapsed = time.time() - starttime print 'pos %f time %.4f elapsed %f' %(position, starttime, elapsed) position += delta except pyca.pyexc, e: print 'pyca exception: %s' %(e) except pyca.caexc, e: print 'channel access exception: %s' %(e) except Exception, e:
class SmartMotor: def __init__(self, motor_channel, motor_name=None, active_monitoring=False): self.motor_channel = motor_channel self.motor_name = motor_name self.active_monitoring = active_monitoring self.__move_pv = Pv(motor_channel) self.__move_pv.connect(1.0) # self.__pos_pv = Pv(self.__get_pv_name('.RBV')) # self.__pos_pv.connect(1.0) self.__dmovpv = Pv(self.__get_pv_name('.DMOV')) self.update() pass def update(self): self.egu = self.__get('.EGU') self.ulim_lo = self.__get('.LLM') self.ulim_hi = self.__get('.HLM') self.base_speed = self.__get('.SBAS') self.speed = self.__get('.S') self.accel = self.__get('.ACCL') self.base_speed_egu = self.__get('.VELO') self.speed_egu = self.__get('.VELO') self.backlash_speed = self.__get('.SBAK') self.backlash_accel = self.__get('.BACC') self.backlash_dist = self.__get('.BDST') if (self.motor_name is None): self.motor_name = self.__get('.DESC') pass pass # TODO: Add logic to consider backlash: def is_in_range(self, pos): return not (pos < self.ulim_lo or pos > self.ulim_hi) pass # TODO: Add logic to consider backlash: def why_outside_range(self, pos): if (pos < self.ulim_lo): return "Position (%f%s) exceeds user low-limit (%f%s) for '%s.'" % ( pos, self.egu, self.ulim_lo, self.egu, self.motor_name) elif (pos > self.ulim_hi): return "Position (%f%s) exceeds user high-limit (%f%s) for '%s.'" % ( pos, self.egu, self.ulim_hi, self.egu, self.motor_name) else: return "Position (%f%s) is within user limits [%f,%f]%s for '%s.'" % ( pos, self.egu, self.ulim_lo, self.ulim_hi, self.egu, self.motor_name) def is_in_range_relative(self, offset): return is_in_range(self.get_position() + offset) def get_position(self): return caget(self.__get_pv_name('.RBV')) # self.__pos_pv.get(False, 5.0) # return self.__pos_pv.value def move(self, pos): self.__move_pv.put(pos) pyca.pend_io(.5) pass def wait(self, timeout=DEFAULT_TIMEOUT): self.__dmovpv.wait_for_value(1, timeout) def move_wait(self, pos, timeout=None): if timeout == None: timeout = self.get_move_time(pos) self.move(pos) self.wait(timeout) # self.__dmovpv.wait_for_value(1, timeout) pass def move_relative(self, offset): self.move(self.get_position() + offset) pass def move_relative_wait(self, offset, timeout=None): pos = self.get_position() + offset if timeout == None: timeout = self.get_move_time(pos) self.move_wait(pos, timeout) pass def __get_pv_name(self, pv_field): return self.motor_channel + pv_field def __get(self, pv_field): return caget(self.__get_pv_name(pv_field)) def __put(self, pv_field, value): caput(self.__get_pv_name(pv_field), value) pass def get_dist_to(self, pos): return fabs(pos - self.get_position()) # TODO: Add logic to consider backlash def get_move_time(self, pos): return fabs(self.get_dist_to(pos) / self.speed_egu) + 2 * self.accel + EPICS_OVERHEAD # def get_move_time2(self, pos): # return fabs(self.get_dist_to(pos) / self.speed_egu) + 2*self.accel + EPICS_OVERHEAD # todo: add backlash checks def checkLimits(self): lim_lo = self.__get('.LLS') if (lim_lo == 1): return -1 else: lim_hi = self.__get('.HLS') if (lim_hi == 1): return 1 else: return 0 pass pass # TODO: This should pickle the important motor parameters to file def saveMotor(self, file, name): parms = {} parms['DESC'] = self.name pass # TODO: Maybe make this a global which returns a motor instance? # TODO: This should load a pickled record from a file def loadMotor(self, file, name): pass # TODO: This should install the important motor parameters to a user motor channel def installTo(self, channel, restict=True): if restrict and channel.split(':')[1] != 'USR': raise Exception( "Request refused. Destination channel is not a user motor.") else: pass pass pass
def caput(PVName, val): """Same definition of caput but with a connect timeout of 10.0""" pv = Pv(PVName) pv.connect(timeout=10.0) pv.put(value=val, timeout=10.0) pv.disconnect()
for post in collection.find_one(sort=[("cfg_id", DESCENDING)]): # get the latest for key, val in post.items(): if key in pvNames: # override pv value if "cfg_id" in key: pvdb[key] = val + 1 else: pvdb[key] = pvNames[key] print("Found match: ", key, val) else: pvdb[key] = val for key, val in pvdb.items(): if "cfg_id" not in key: _pv = Pv(prefix + ':' + key) _pv.connect(1.0) if type(val['value']) == list: _pv.put(tuple(val['value'])) else: _pv.put(val['value']) pyca.flush_io() # TODO: avoid creating Pv multiple times and avoid multiple connects for key, val in pvdb.items(): if "cfg_id" not in key: _pv = Pv(prefix + ':' + key) _pv.connect(1.0) _pv.get(False, 1.0) # config keys for pvNames are the strings after the last colon
def caput(pvname, value): pv = Pv(pvname) pv.connect(1.) pv.put(value, timeout=1.) pv.disconnect()