def __init__(self, url): self.cache = {} print('Epics Bridge', url) self._scan_info = {} self._scan_data = {} self._last_data = [] self._url = None # Setting the url property, causes the xmlrpc serverproxy to connect self.url = url self.detectors = {} self.array_list = [SCAN_TAG] self.scan_arrays = {} for detector, pv_info in self.server.get_detector_list(): self.monitor_detector(detector, pv_info) self._update_available = True self.update_timer = QTimer() self.update_timer.start(500) self.update_timer.timeout.connect(self.update)
class EpicsBridge(object): instance = None init_thread = None def __init__(self, url): self.cache = {} print('Epics Bridge', url) self._scan_info = {} self._scan_data = {} self._last_data = [] self._url = None # Setting the url property, causes the xmlrpc serverproxy to connect self.url = url self.detectors = {} self.array_list = [SCAN_TAG] self.scan_arrays = {} for detector, pv_info in self.server.get_detector_list(): self.monitor_detector(detector, pv_info) self._update_available = True self.update_timer = QTimer() self.update_timer.start(500) self.update_timer.timeout.connect(self.update) def _get_url(self): return self._url def _set_url(self, url): if url != self._url: self.server = xmlrpclib.ServerProxy(url) self._url = url url = property(_get_url, _set_url, doc='XMLRPC server URL') def monitor_detector(self, name, pvs): print('Monitor detector %s (pvs: %s)' % (name, pvs)) self.detectors[name] = det = EpicsDetector(name, pvs) self.array_list.append(name) if hasattr(det, 'calibration'): self.array_list.append('%s_PARAM' % name) def remove_detector(self, name): if name not in self.detectors: return del self.detectors[name] def update(self): if self.server is None: return # check to add/remove detectors det_list = self.server.get_detector_list() det_dict = dict(det_list) det_names = set(det_dict.keys()) new_detectors = det_names - set(self.detectors.keys()) for det_name in new_detectors: self.monitor_detector(det_name, det_dict[det_name]) remove_detectors = set(self.detectors.keys()) - det_names for det_name in remove_detectors: self.remove_detector(det_name) # see if scan in progress, and get status @property def scan_dim(self): return self.scan_info.get('nopts', 0), self.scan_info.get('counters', 0) def _update_scan_info(self): if self.server is None or not self.update_available: return self._scan_info = info = self.server.get_scan_info() if 'key' not in info: print('scan info has no key?', info) return self._scan_key = info['key'] ndim = info.get('ndim', 1) labels = info.get('labels', []) label_str = ','.join(labels) # todo label_str = label_str.replace('(', '') label_str = label_str.replace(')', '') info['plotlist'] = label_str info['axistitles'] = label_str.replace(',', ' ') if ndim == 2: old_keys = set(self.scan_arrays.keys()) keys = set(['2D_%s' % label for label in labels]) if keys != old_keys: remove_keys = old_keys - keys for remove in remove_keys: del self.scan_arrays[remove] for key in keys: if key not in self.scan_arrays: self.scan_arrays[key] = {'key': -1} else: self.scan_arrays.clear() print('got scan info', info) self._last_data.append(self._scan_data) self._scan_data = np.array(self.server.get_scan_data()) self._update_available = False return info def getarrayinfo(self, name): # rows, cols, type, flag print('get array info', name) if name.startswith(SCAN_TAG): self._update_scan_info() nopts, counters = self.scan_dim print('Scan points', nopts, 'Counters', counters) return [nopts, counters, sps.FLOAT, sps.TAG_SCAN | sps.TAG_ARRAY] elif name in self.detectors: det = self.detectors[name] return det.sps_info elif name.endswith('_PARAM'): # calibration #detector = name.rsplit('_', 1)[0] return [3, 1, sps.FLOAT, sps.TAG_ARRAY] elif name in self.scan_arrays: name = name[3:] dim = self.scan_info.get('dimensions') print('array info', name, dim) return [dim[0], dim[1], sps.FLOAT, sps.TAG_ARRAY | sps.TAG_IMAGE] def getarraylist(self): return self.array_list + list(self.scan_arrays.keys()) def _isupdated(self, name): if self.server is None: return False if name in self.detectors: if self.detectors[name].updated: self.detectors[name].updated = False return True elif name == SCAN_TAG: return self.update_available elif name in self.scan_arrays: last_key = self.scan_arrays[name]['key'] return (self.update_available or last_key != self._scan_key) return False def isupdated(self, name): ret = self._isupdated(name) print('isupdated %s = %s' % (name, ret)) return ret def getenv(self, shmenv, key): print('getenv', shmenv, key) if shmenv == SCAN_ENV_TAG: return self.scan_info[key] else: return '' @property def update_available(self): if not self._update_available: newest_key = self.server.get_scan_key() self._update_available = (newest_key != self._scan_key) return self._update_available else: return True @property def scan_info(self): if self._scan_info is None or self.update_available: self._update_scan_info() return self._scan_info @property def scan_data(self): if self._scan_data is None or self.update_available: self._update_scan_info() return self._scan_data def _getdata(self, name): print('getdata', name) if name == SCAN_TAG: return self.scan_data elif name.endswith('_PARAM'): # calibration detector = name.rsplit('_', 1)[0] return np.array([self.detectors[detector].calibration]) elif name in self.detectors: return self.detectors[name].data.T # expects transpose elif name in self.scan_arrays: self.scan_arrays[name]['key'] = self._scan_key # Strip off the 2D_ prefix name = name[3:] labels = self.scan_info['labels'] label_idx = labels.index(name) data = self.scan_data data = data[:, label_idx] if 0: data = data + np.random.random(data.shape[0]) import traceback traceback.print_stack() return np.array(data).reshape(self.scan_info['dimensions']) else: return np.zeros(1) def getdata(self, name): ret = self._getdata(name) #print('getdata %s = %s' % (name, ret)) return ret def getkeylist(self, shmenv): if shmenv == SCAN_ENV_TAG: return self.scan_info.keys() else: return [] def specrunning(self): return 1 def getspeclist(self): #import traceback; traceback.print_stack() return [EPICS_TAG] + sps._getspeclist() # unused functions: def updatedone(self, shmenv): raise NotImplementedError # unused in current PyMca code def getdatacol(self, shm, idx): raise NotImplementedError # unused in current PyMca code def getdatarow(self, shm, idx): raise NotImplementedError # unused in current PyMca code def putenv(self, shmenv, cmd, outp): raise NotImplementedError