/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 """ 00002 """ 00003 import os, logging 00004 import random 00005 from datetime import datetime, timedelta 00006 from pprint import pformat 00007 00008 from base import Regime, Averager, Faker, DCS, SourceContext 00009 00010 log = logging.getLogger(__name__) 00011 00012 class AdLid(Regime): 00013 """ 00014 Regime frontend class with simple prescribed interface, 00015 takes the cfg argument into this dict and no args in call 00016 ... allowing the frontend to be entirely generic 00017 """ 00018 srcs = property( lambda self:AdLidSource( DCS(self['source']) )) 00019 averager = property( lambda self:AdLidAverager(self.srcs, self.target, self )) 00020 faker = property( lambda self:AdLidFaker(self.srcs,self )) 00021 00022 00023 class AdPhysLogical(dict): 00024 """ 00025 Placeholder dict until physical to logical via DB lookup is worked out 00026 """ 00027 def __call__(self, physad ): 00028 assert physad in self 00029 return self[physad] 00030 00031 00032 class AdLidSource(list): 00033 """ 00034 A list of SQLAlchemy dynamic classes 00035 """ 00036 def __init__(self, srcdb ): 00037 """Coordinates of source table/joins""" 00038 00039 apl = AdPhysLogical( ## place holder for testing, accurate as of Nov 30, 2011. 00040 AD1=("kDayaBay","kAD1"), 00041 AD2=("kDayaBay","kAD2"), 00042 AD3=("kLingAo" ,"kAD1"), 00043 AD4=("kFar" ,"kAD1"), 00044 AD5=("kFar" ,"kAD2"), 00045 AD6=("kFar" ,"kAD3"), 00046 AD7=("kSAB" ,"kAD1"), 00047 AD8=("kSAB" ,"kAD2"), 00048 ) 00049 00050 physads = ("AD1","AD2","AD3","AD4","AD5","AD6","AD7","AD8",) 00051 #physads = ("AD1",) 00052 for physad in physads: 00053 ksite, ksubsite = apl( physad ) 00054 dtn = SourceContext(table="%s_LidSensor" % physad , ksite=ksite , ksubsite=ksubsite ) 00055 self.append( srcdb.kls(dtn) ) 00056 00057 00058 class AdLidAverager(Averager): 00059 """ 00060 Specialization of generic averager for AD Lid Sensor tables 00061 """ 00062 def changed(self, sv ): 00063 return False 00064 00065 def propagate(self, sv ): 00066 """ 00067 yields one or more target dicts ready for writing to target DB 00068 00069 NB Averager performs group_by queries within time bins 00070 that can yield no results 00071 00072 """ 00073 aggl=sv[-1].aggd 00074 assert type(aggl) == list , "expect list when using aggregate_group_by %r " % aggl 00075 if len(aggl) == 0: 00076 log.debug("empty query tcursor %s " % repr(sv.tcursor) ) 00077 for aggd in aggl: 00078 if aggd['NSamples']==0: 00079 log.warn("AdLidAverager NSamples zero, yielding dummy ") 00080 yield self._dummy_dict() 00081 else: 00082 yield aggd 00083 00084 def seed(self, sc): 00085 """ 00086 Used for seeding target DB when testing into empty tables 00087 00088 :param sc: source class, potentially different seeds will be needed 00089 for each source that feeds into a single target 00090 00091 """ 00092 kls = self.target.kls ## the genDbi target class 00093 keys = kls.SpecKeys().aslist() 00094 return dict(zip(keys,map(lambda _:0, keys))) ## state dict with all values 0 00095 00096 def _dummy_dict(self, v=-1): 00097 """ 00098 target dict with all values `v` 00099 """ 00100 kls = self.target.kls 00101 keys = kls.SpecKeys().aslist() 00102 return dict(zip(keys,map(lambda _:v, keys))) 00103 00104 00105 class AdLidFaker(Faker): 00106 def fake(self, inst, id , dt=None ): 00107 """ 00108 Invoked from base class, sets source instance attributes to form a fake 00109 00110 :param inst: source instance 00111 :param id: id to assign to the instance 00112 00113 Note that **not** setting the `id` attribute allows AUTOINCREMENT to kick in and 00114 can avoid SQLAlchemy IntegrityError from duplicate keys. 00115 00116 """ 00117 if dt==None: 00118 dt = datetime.now() 00119 for k,v in inst.asdict.items(): 00120 if k == 'id': 00121 pass 00122 #setattr( inst, k, id ) 00123 elif k == 'date_time': 00124 setattr( inst, k, dt ) 00125 else: 00126 if k.startswith('Ultrasonic'): 00127 setattr( inst, k, random.gauss(2000, 5) ) 00128 elif k.startswith('Capacitance'): 00129 setattr( inst, k, random.gauss(200, 10) ) 00130 elif k.startswith('Temp_'): 00131 setattr( inst, k, random.gauss(22.7, 0.1) ) 00132 elif k.startswith('Tilt'): 00133 setattr( inst, k, random.gauss(0, 0.1) ) 00134 else: 00135 setattr( inst, k, 0 ); 00136 00137 00138 if __name__ == '__main__': 00139 pass 00140 00141 from base.parser import Parser 00142 cfg = Parser.config("adlid_averager") 00143 reg = cfg.regcls 00144 irg = reg(cfg) 00145 print irg.srcs 00146 assert len(irg.srcs) > 0, "no source classes " 00147 00148 00149 00150 00151