def OLD_show_plot(self,pv=None,pv2=None,time_ago=None,date1=None,date2=None,**kw): self.kw.update(kw) pv1 = self.argclean(pv, self.kw['text_pv']) pv2 = self.argclean(pv2, self.kw['text_pv2']) self.arch.db.get_cursor() if pv1 != '': pv1 = normalize_pvname(pv1) self.html_title = "%s for %s" % (self.html_title,pv1) if not self.in_database(pv1): self.arch.add_pv(pv1) if pv2 != '': pv2 = normalize_pvname(pv2) self.html_title = "%s and %s" % (self.html_title,pv2) if not self.in_database(pv2): self.arch.add_pv(pv2) # self.starthtml() self.show_links(pv=pv1,help='plotting',active_tab='') self.draw_form(pv1=pv1,pv2=pv2,time_ago=time_ago,date1=None,date2=None) self.endhtml() self.arch.db.put_cursor() return self.get_buffer()
def do_plot(self,pv='',pv2='',time_ago=None,date1=None,date2=None,**kw): self.kw.update(kw) self.update_kw('pv',pv) self.update_kw('pv2',pv2) self.update_kw('time_ago',time_ago) self.update_kw('date1',date1) self.update_kw('date2',date2) self.starthtml() if self.kw.get('text_pv','') not in ('',None): self.kw['pv'] = self.kw['text_pv'] if self.kw.get('text_pv2','') not in ('',None): self.kw['pv2'] = self.kw['text_pv2'] pv1 = self.kw.get('pv','') pv2 = self.kw.get('pv2','') action = self.kw.get('submit','') if action == '': action = 'Time From Present' if (self.kw.get('date1','') != '' and self.kw.get('date2','') != ''): action = 'Date Range' if self.kw.get('submit','') == '': self.kw['submit'] = action self.arch.db.get_cursor() warnings = [] if pv1 != '': pv1 = normalize_pvname(pv1) self.html_title = "%s for %s" % (self.html_title,pv1) if not self.in_database(pv1): add_ok = self.arch.add_pv(pv1) if add_ok is None: warnings.append(" Warning: cannot add PV '%s'<br>" % pv1 ) if pv2 != '': pv2 = normalize_pvname(pv2) self.html_title = "%s and %s" % (self.html_title,pv2) if not self.in_database(pv2): add_ok = self.arch.add_pv(pv2) if add_ok is None: warnings.append(" Warning: cannot add PV '%s'<br>" % pv2 ) self.show_links(pv=pv1,help='plotting',active_tab='') for w in warnings: self.write(w) # self.show_keys(title='AT DO PLOT') self.draw_form(pv1=pv1,pv2=pv2,time_ago=time_ago,date1=date1,date2=date2) self.endhtml() self.arch.db.put_cursor() return self.get_buffer()
def add_alert(self, pvname=None, name=None, mailto=None, mailmsg=None, timeout=30, compare='ne', trippoint=None, **kw): """add a new alert""" if pvname is None: return pvname = normalize_pvname(pvname) if name is None: name = pvname if pvname not in self.pvinfo: self.add_pv(pvname) active = 'yes' if mailto is None: active, mailto = ('no','') if mailmsg is None: active, mailmsg= ('no','') if trippoint is None: active, trippoint = ('no', 0.) if compare not in alert_ops: compare = 'ne' alerts = self.tables['alerts'] alerts.insert().execute(name=name, pvname=pvname, active=active, mailto=mailto, mailmsg=mailmsg, timeout=timeout, compare=compare, trippoint=trippoint)
def set_pair_score(self, pvname1, pvname2, score=None): """set 'relatedness' score for 2 pvs if score is None it will be incremented by 1 """ ptab = self.tables['pairs'] npv1 = normalize_pvname(pvname1) npv2 = normalize_pvname(pvname2) q = self.query(ptab) pairs = q.filter((ptab.c.pv1==npv1)&(ptab.c.pv2==npv2)).all() if len(pairs) == 0: pairs = q.filter((ptab.c.pv1==npv2)&(ptab.c.pv2==npv1)).all() if len(pairs) < 1: ptab.insert().execute(pv1=npv1, pv2=npv2, score=1) else: pair = pairs[0] ptab.update(whereclause='id=%i' % pair.id).execute(score=pair.score+1)
def request_pv_cache(self, pvname): """request a PV to be included in caching. will take effect once a 'process_requests' is executed.""" npv = normalize_pvname(pvname) if npv in self.pvinfo: return requests = self.tables['requests'] requests.insert().execute(pvname=pvname, action='add', ts=time.time())
def get_data(self, pvname, tmin=None, tmax=None, with_current=None): """return data arrays for timestamp and value for a PV over the specified time range """ npv = normalize_pvname(pvname) tnow = time() if tmax is None: tmax = tnow if tmin is None: tmin = tnow - SEC_DAY if tmin > tmax: tmin, tmax = tmax, tmin # look back one day more than actually requested # to ensure stale data is found _tmax = tmax + 60 _tmin = tmin - SEC_DAY ts, vals = [], [] for dbname in self.dbs_for_time(tmin=_tmin, tmax=_tmax): # print(" Use DB ", dbname) if dbname not in self.data_dbs: self.data_dbs[dbname] = PVDataDB(dbname, **self.conn_opts) ddb = self.data_dbs[dbname] for t, v in ddb.get_data(npv, tmin=_tmin, tmax=_tmax): ts.append(float(t)) try: v = float(v) except: pass vals.append(v) if with_current is None: with_current = abs(tmax-tnow) < SEC_DAY if with_current: cache = self.cache_row(npv) try: val = float(cache.value) except: val = cache.value # ts.append(float(cache.ts)) # vals.append(val) # and current time ts.append(time()) vals.append(val) ts, vals = np.array(ts), np.array(vals) torder = ts.argsort() ts, vals = ts[torder], vals[torder] # now limit date to the actually requested time range, # plus the one most recent previous measurement tsel = np.where(ts >= tmin)[0] older = np.where(ts < tmin)[0] if len(older) > 0: tsel = np.concatenate(([older[-1]], tsel)) ts, vals = ts[tsel], vals[tsel] return ts, vals
def related_pvs(self, pvname): """return list of related PVs to provided pv, in order of score""" ptab = self.tables['pairs'] npv = normalize_pvname(pvname) pairs = [] for r in self.query(ptab).filter((ptab.c.pv1==npv)| (ptab.c.pv2==npv)).all(): other = (int(r.score), r.pv2) if npv == r.pv2: other = (int(r.score), r.pv1) pairs.append(other) pairs.sort() pairs.reverse() return [p[1] for p in pairs]
def read_pvinfo(self): "make dictionary of PVName -> PV info (id, data_table, etc)" self.pvinfo = {} pvtab = self.tables['pv'] for row in pvtab.select().execute().fetchall(): n = normalize_pvname(row.name) self.pvinfo[n] = dict(id=row.id, desc=row.description, data_table=row.data_table, type=row.type, graph_type=row.graph_type, graph_hi=row.graph_hi, graph_lo=row.graph_lo)
def add_pv(self, pvname, set_motor_pairs=True): """adds a PV to the cache: actually requests the addition, which will be handled by the next process_requests in mainloop(). Here, we check for 'Motor' PV typs and make sure all motor fields are requested together, and that the motor fields are 'related' by assigning a pair_score = 10. """ pvname = normalize_pvname(pvname.strip()) fields = (pvname,) if not valid_pvname(pvname): return prefix = pvname isMotor = False if pvname.endswith('.VAL'): prefix = pvname[:-4] p = epics.PV(pvname) p.wait_for_connection(timeout=0.25) if p.connected: self.request_pv_cache(pvname) if ('.' not in prefix and p.type == 'double'): rtype = epics.PV(prefix+'.RTYP') rtype.wait_for_connection(0.1) if rtype is not None: isMotor = 'motor' == rtype.get() if isMotor: fields.extend(["%s%s" % (prefix,i) for i in motor_fields]) pvs = [] for pvn in fields: pvs.append(epics.PV(pvn)) epics.poll() for p in pvs: p.wait_for_connection(timeout=0.5) if p.connected: self.request_pv_cache(p.pvname) if isMotor and set_motor_pairs: time.sleep(0.25) for f1 in fields: for f2 in fields: if f1 != f2: self.set_pair_score(f1, f2, score=10) return
def get_data(self, pvname, tmin=None, tmax=None): "get data for a PV over time range" if self.pvinfo is None: self.read_pvinfo() pvinfo = self.pvinfo[normalize_pvname(pvname)] pv_id = pvinfo['id'] dtab = self.tables[pvinfo['data_table']] tnow = time() if tmax is None: tmax = tnow if tmin is None: tmin = tmax - SEC_DAY # make sure tmin and tmax are ordered, and look back at least one day if tmin > tmax: tmin, tmax = tmax, tmin if tmin > tmax - SEC_DAY: tmin = tmax - SEC_DAY q = dtab.select().where(dtab.c.pv_id==pv_id).order_by(dtab.c.time) q = q.where(dtab.c.time >= tmin).where(dtab.c.time <= tmax) return [(float(row.time), row.value) for row in q.execute().fetchall()]
def get_related_pvs(self,pvname): tmp = [] npv = normalize_pvname(pvname) r1 = self.arch.read_master("select * from pairs where pv1='%s' and score>1 order by score" %npv) for j in r1: tmp.append((j['score'],j['pv1'],j['pv2'])) r2 = self.arch.read_master("select * from pairs where pv2='%s' and score>1 order by score" %npv) for j in r2: tmp.append((j['score'],j['pv1'],j['pv2'])) tmp.sort() out = [] for r in tmp: if r[1] == npv and r[2] not in out: out.append(r[2]) elif r[2] == npv and r[1] not in out: out.append(r[1]) out.reverse() return out
def __get_pvpairs(self,pv1,pv2): "fix and sort 2 pvs for use in the pairs tables" p = [normalize_pvname(pv1),normalize_pvname(pv2)] p.sort() return tuple(p)
def cache_row(self, pvname): """return full cache row for a pv""" ctab = self.tables['cache'] npv = normalize_pvname(pvname) return ctab.select().where(ctab.c.pvname==npv).execute().fetchone()
def get_pvinfo(self, pvname): npv = normalize_pvname(pvname) return self.pvinfo.get(npv, npv)