/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 """ 00002 RPC HV scraping specialization 00003 """ 00004 import os, logging 00005 log = logging.getLogger(__name__) 00006 from datetime import datetime, timedelta 00007 00008 from base import Regime, Scraper, Faker, DCS, SourceContext 00009 from GaudiPython import gbl 00010 SiteFromString = gbl.Site.FromString 00011 00012 class RpcHv(Regime): 00013 """ 00014 Regime frontend class with simple prescribed interface, 00015 takes the cfg argument into this dict and no args in call. 00016 This allows the frontend to be entirely generic. 00017 """ 00018 srcs = property( lambda self:RpcHvSource( DCS(self['source']) )) 00019 scraper = property( lambda self:RpcHvScraper(self.srcs, self.target, self )) 00020 faker = property( lambda self:RpcHvFaker(self.srcs,self )) 00021 00022 00023 00024 class RpcHvSource(list): 00025 def __init__(self, srcdb): 00026 """ 00027 :param srcdb: source DB instance of :py:class:`Scraper.base.DCS` 00028 00029 List of source SA classes that map tables/joins in srcdb 00030 Three sites for RPC HVs 00031 00032 """ 00033 dtn = SourceContext(table="DBNS_RPC_HV_Vmon",ksite="kDayaBay",ksubsite="kRPC") 00034 self.append(srcdb.kls(dtn) ) 00035 dtn = SourceContext(table="LANS_RPC_HV_Vmon",ksite="kLingAo",ksubsite="kRPC") 00036 self.append(srcdb.kls(dtn) ) 00037 dtn = SourceContext(table="FARS_RPC_HV_Vmon",ksite="kFar",ksubsite="kRPC") 00038 self.append(srcdb.kls(dtn) ) 00039 00040 00041 class RpcHvScraper(Scraper): 00042 00043 def changed(self, sv ): 00044 """ 00045 :param sv: source vector instance :py:class:`Scraper.base.sourcevector.SourceVector` 00046 00047 Decide if sufficient change to propagate based on differences between the first and last elements of `SourceVector` instance argument 00048 """ 00049 00050 p = self._detectordict( sv[0] ) 00051 c = self._detectordict( sv[-1] ) 00052 site = p.pop('site') 00053 det = p.pop('det')['det'] 00054 for label in sorted(p.keys()): 00055 pv = p[label] 00056 cv = c[label] 00057 if abs(pv['voltage']-cv['voltage']) > self.threshold: 00058 return True 00059 return False 00060 00061 def propagate(self, sv ): 00062 """ 00063 :param sv: source vector instance :py:class:`Scraper.base.sourcevector.SourceVector` 00064 00065 Yield write ready DybDbi target dicts to base class, note that a single source vector 00066 instance is yielding multiple target dicts. The keys of the target dict must match 00067 the specified attributes of the ``DybDbi`` target class. 00068 00069 Here the output is based entirely on the last element of the source vector. A smarter 00070 implementation might average the first and last to smooth variations. 00071 The python ``yield`` command makes it possible to iterate over a what is returned by 00072 a function/method. 00073 00074 ETW Aug 2012: write voltage from sv[0], NOT sv[-1] 00075 """ 00076 00077 dd = self._detectordict(sv[0]) 00078 n = 0 00079 site = dd.pop('site') 00080 siteval = site['site'] 00081 det = dd.pop('det') 00082 detval = det['det'] 00083 ksite = self._getsite(siteval) 00084 detnum = 7 00085 for (label,sign),v in sorted(dd.items()): 00086 if (sign > 0): 00087 vp = dd[label,1] 00088 vn = dd[label,-1] 00089 vpos = vp['voltage'] 00090 vneg = vn['voltage'] 00091 d = dict(LocationId=label,VoltagePos=vpos,VoltageNeg=vneg) 00092 log.info("Writing out LocationId={}, VoltagePos={}, VoltageNeg={}".format(label,vpos,vneg)) 00093 n += 1 00094 yield d 00095 log.debug("yielded %s target dicts for %s " % ( n, sv )) 00096 00097 00098 def seed(self, sc): 00099 """ 00100 Used for seeding target DB when testing into empty tables 00101 00102 :param sc: source class, potentially different seeds will be needed 00103 for each source that feeds into a single target 00104 """ 00105 00106 scstr = str(sc) 00107 00108 if scstr.find("DBNS_RPC") > 0: 00109 return dict(LocationId="F00",VoltagePos=0,VoltageNeg=0) 00110 if scstr.find("LANS_RPC") > 0: 00111 return dict(LocationId="F00",VoltagePos=0,VoltageNeg=0) 00112 if scstr.find("FARS_RPC") > 0: 00113 return dict(LocationId="F00",VoltagePos=0,VoltageNeg=0) 00114 00115 def _detectordict(self,inst): 00116 """ 00117 :param inst: SQLAlchemy source instance 00118 00119 Examines source instance, extracting detector name, DCS detector id, and values into a dict. 00120 """ 00121 00122 dd={} 00123 inststr = str(inst) 00124 sitestr = inststr[1:4] 00125 detstr = inststr[6:9] 00126 dd['site'] = {'site':sitestr} 00127 dd['det'] = {'det':detstr} 00128 00129 for k,v in inst.asdict.items(): 00130 if k in 'id date_time'.split(): 00131 continue 00132 if v is None: 00133 v = -999 00134 sign = k.find("P") 00135 if (sign > 0): 00136 kp = 1 00137 else: 00138 kp = -1 00139 if (k[5] == 'F'): 00140 kshort = k[5:6]+k[7:9] 00141 else: 00142 kshort = 'T'+k[8:10] 00143 kk = (kshort,kp) 00144 qty,kk = ('voltage',kk) 00145 if dd.has_key(kk): 00146 dd[kk].update({qty:v}) 00147 else: 00148 dd[kk] = {qty:v} 00149 return dd 00150 00151 def _getsite(self,site): 00152 """ 00153 Returns ksite number given string input 00154 """ 00155 00156 if site == 'DBN': 00157 return SiteFromString("DayaBay") 00158 elif site == 'LAN': 00159 return SiteFromString("LingAo") 00160 elif site == 'FAR': 00161 return SiteFromString("Far") 00162 else: 00163 msg = "Do not recognize site...must be DBNS, LANS, or FARS" 00164 log.fatal(msg) 00165 raise Exception(msg) 00166 return -1 00167 00168 class RpcHvFaker(Faker): 00169 """ 00170 Creates fake instances and inserts them into sourcedb 00171 """ 00172 def fake(self, inst, id , dt ): 00173 """ 00174 Invoked from base class call method, 00175 set attributes of source instance to form a fake 00176 00177 :param inst: source instance 00178 :param id: id to assign to the instance instance 00179 """ 00180 # fakefn=lambda (l,c,r),qty:l*100 + c*10 + r if qty == "voltage" else 1 00181 # for k,v in inst.asdict.items(): 00182 # if k in 'id P_id'.split(): 00183 # setattr( inst, k, id ) 00184 # elif k in 'date_time P_date_time'.split(): 00185 # setattr( inst, k, dt ) 00186 # else: 00187 # qty,kk = ('pw',k[2:]) if k.startswith('P_') else ('voltage',k) 00188 # lcr = self.lcr_matcher(kk) 00189 # setattr( inst , k, fakefn( lcr, qty) ) 00190 00191 00192 # if __name__ == '__main__': 00193 # pass 00194