00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2004 00004 # by 00005 # The Board of Trustees of the 00006 # Leland Stanford Junior University. 00007 # All rights reserved. 00008 # 00009 00010 __facility__ = "Online" 00011 __abstract__ = "GLAST LAT Housekeeping server infrastructure" 00012 __author__ = "Jim Panetta <panetta@slac.stanford.edu> SLAC - GLAST I&T" 00013 __date__ = "07/28/04" 00014 __version__ = "$Revision: 1.9 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 from LATTE.monitoring.HskReceiver import HskCfgTextReceiver 00021 from LATTE.client.gOptions import Options 00022 00023 import logging 00024 import gc,sys 00025 from linecache import * 00026 import time 00027 import qt 00028 from sihippo import Observer 00029 import sihippo 00030 00031 second = 1 00032 minute = 60 * second 00033 hour = minute * 60 00034 day = hour * 24 00035 era = 10**9 00036 00037 timeFmt = '%H:%M:%S' 00038 dataFile = None 00039 timeDepth = 2*hour 00040 00041 class QtReceiver(qt.QObject,HskCfgTextReceiver): 00042 00043 class TrendUpdateEvent(qt.QCustomEvent): 00044 def __init__(self,trendMap): 00045 qt.QCustomEvent.__init__(self,qt.QEvent.MaxUser-20) 00046 self.trendMap = trendMap 00047 00048 def __init__(self, flatFile, startTime, trendList): 00049 HskCfgTextReceiver.__init__(self, flatFile, startTime, trendList) 00050 qt.QObject.__init__(self) 00051 00052 def process(self,trendMap): 00053 qt.QApplication.postEvent(self,QtReceiver.TrendUpdateEvent(trendMap)) 00054 00055 def customEvent(self,event): 00056 self.emit(qt.PYSIGNAL('TrendUpdate(trendMap)'),(event.trendMap,)) 00057 00058 00059 00060 class TrendPlotter(qt.QWidget): 00061 def __init__(self,keyList,*args): 00062 qt.QWidget.__init__(self,*args) 00063 00064 self.__ntuples = {} 00065 self.__plots = {} 00066 self.__views = {} 00067 self.__gen = {} 00068 self.__defaultDepth = 500 # assuming 1 hz data rate 00069 self.__defaultLabels = ['Time',''] 00070 00071 self.__dynamic = True 00072 self.__keyList = keyList 00073 00074 self.grid = qt.QGridLayout(self,3,2) 00075 self.grid.setAutoAdd(1) 00076 self.true = True 00077 00078 def isDynamic(self): 00079 return self.__dynamic 00080 def setDynamic(self,bool): 00081 self.__dynamic=bool 00082 00083 def addPlot(self, key): 00084 labels = self.__defaultLabels 00085 depth = self.__defaultDepth 00086 name = self.__keyList[key] 00087 00088 # Create the Circular buffer to store the data 00089 ntc = sihippo.NTupleController.instance() 00090 nt = ntc.createCircularBuffer(labels) 00091 nt.reserve(depth) 00092 nt.setTitle(name) 00093 nt.setName(name) 00094 00095 # Create the Plot 00096 dc = sihippo.DisplayController.instance() 00097 plot=dc.createDisplay('XY Plot',nt,labels) 00098 # plot = dc.createDisplay('Strip Chart',nt,labels) 00099 00100 # kludge so that the range is initialized, and autoscales when we need. 00101 plot.setRange('x',0,1) 00102 plot.setAutoRanging('x',True) 00103 00104 # Add the time axis observer 00105 gen = TimeAxisGen() 00106 gen.setPlotter(plot, key) 00107 plot.addObserver(gen) 00108 00109 # Add the plot to the screen 00110 view = sihippo.QtViewWidget(self) 00111 view.setPlotter(plot) 00112 view.setDoubleBuffering(1) 00113 view.resize(200,100) 00114 view.setMinimumSize(qt.QSize(100,50)) 00115 # self.grid.addWidget(view) 00116 view.show() 00117 00118 # Maintain a reference to the created objects to prevent garbage collection 00119 self.__ntuples[key] = nt 00120 self.__plots[key] = plot 00121 self.__views[key] = view 00122 self.__gen[key] = gen 00123 00124 def update(self, trendMap): 00125 # if not self.true: return 00126 self.true=False 00127 # trendMap has timestamp, val1, val2, val3... 00128 timeStamp = trendMap['TimeStamp'] 00129 for key in trendMap: 00130 if key == 'TimeStamp': continue 00131 if key not in self.__views.keys() and self.__dynamic: 00132 self.addPlot(key) 00133 if key not in self.__views.keys(): 00134 return 00135 x=timeStamp 00136 y=trendMap[key] 00137 if y is None: 00138 continue 00139 self.__ntuples[key].addRow([x,y]) 00140 00141 class TimeAxisGen ( Observer ) : 00142 __labelFmt = '%Y/%m/%d' 00143 __tickFmt = '%H:%M' 00144 __stepSet = [ 1*second, 5*second, 10*second, 30*second, 00145 1*minute, 2*minute, 5*minute, 10*minute, 15*minute, 20*minute, 30*minute, 00146 1*hour, 2*hour, 6*hour, 12*hour, 00147 1*day, 3*day, 7*day, 30*day, 90*day, 180*day, 364*day, 00148 era] 00149 00150 def setPlotter ( self, plotter, name ) : 00151 self.plotter = plotter 00152 self.name = name 00153 self.__goodStep = 0 00154 00155 def update ( self, obs ) : 00156 # return 00157 lowTime = self.plotter.getLowRangeOnX() 00158 highTime = self.plotter.getHighRangeOnX() 00159 00160 if ((highTime - lowTime)/TimeAxisGen.__stepSet[self.__goodStep]) < 1: 00161 # print "reset of goodStep", self.name, self.__goodStep , highTime, lowTime, ((highTime - lowTime)/TimeAxisGen.__stepSet[self.__goodStep]) 00162 self.__goodStep -= 1 00163 if ((highTime - lowTime)/TimeAxisGen.__stepSet[self.__goodStep]) > 6: 00164 # print self.name, highTime, lowTime, ((highTime - lowTime)/TimeAxisGen.__stepSet[self.__goodStep]) 00165 step = 0 00166 while ((highTime - lowTime)/TimeAxisGen.__stepSet[step]) > 5: 00167 # print "step:", step 00168 step += 1 00169 self.__goodStep = step 00170 step = TimeAxisGen.__stepSet[self.__goodStep] 00171 00172 lowTick = lowTime - (lowTime % step) + step 00173 values = [] 00174 values.append( lowTick ) 00175 00176 labels = [] 00177 labels.append( time.strftime(TimeAxisGen.__tickFmt, time.localtime(lowTick)) ) 00178 tick = lowTick 00179 tick += step 00180 while tick < highTime: 00181 values.append ( tick ) 00182 labels.append ( time.strftime(TimeAxisGen.__tickFmt, time.localtime(tick)) ) 00183 tick += step 00184 00185 self.plotter.setAutoTicksOnX( False ) 00186 self.plotter.setTicksOnX( values, labels ) 00187 00188 # REALLY REALLY don't do this: 00189 # setLabel calls "notifyObservers", which brings us back here... 00190 # xlabel = time.strftime(TimeAxisGen.__labelFmt, time.localtime(highTime)) 00191 # self.plotter.setLabel( 'x', xlabel ) 00192 00193 def memget(): 00194 import win32pdh 00195 hq = win32pdh.OpenQuery() 00196 # ch = win32pdh.AddCounter(hq, "\\\\gitow1\\Process(python)\\Private Bytes") 00197 ch = win32pdh.AddCounter(hq, "\\\\gitow1\\Process(python#1)\\Private Bytes") 00198 win32pdh.CollectQueryData(hq) 00199 type, val =win32pdh.GetFormattedCounterValue(ch,win32pdh.PDH_FMT_LONG) 00200 return val 00201 00202 def startup(): 00203 # print memget() 00204 logging.basicConfig() 00205 logging.root.setLevel(logging.DEBUG) 00206 gc.set_debug(gc.DEBUG_LEAK) 00207 print "Garbage collection: ", gc.isenabled()#, gc.get_objects() 00208 00209 def startQT(dataFile, startTime, keyList): 00210 import sys 00211 00212 app=qt.QApplication(sys.argv) 00213 r=QtReceiver(dataFile, startTime, keyList.keys()) 00214 00215 gui=TrendPlotter(keyList) 00216 gui.connect(r,qt.PYSIGNAL('TrendUpdate(trendMap)'),gui.update) 00217 00218 app.connect(app,qt.SIGNAL("lastWindowClosed()"), 00219 app,qt.SLOT("quit()")) 00220 00221 app.setMainWidget(gui) 00222 gui.show() 00223 00224 r.setReceiving(1) 00225 app.exec_loop() 00226 r.shutdown() 00227 00228 def usage(): 00229 return """ 00230 00231 HskGuiReceiver Usage: 00232 00233 Mandatory options: 00234 --dataFile define the flat file that contains housekeeping data. 00235 00236 Optional options: 00237 --timeDepth define the time depth of the housekeeping plots. Default is 2 hours. 00238 Units are in seconds 00239 --keyFile define the file of variables to plot 00240 Note: keyFile format is "KEY : Plot title" 00241 00242 Example: 00243 $ HskGuiReceiver --dataFile c:\TEMP\lat-elf11.dat --timeDepth 3600 --keyFile keys.dat 00244 00245 """ 00246 00247 00248 if __name__ == '__main__': 00249 startup() 00250 00251 # Options, first list mandatory, second list optional 00252 options = Options(['dataFile'], ['timeDepth', 'keyFile']) 00253 try: 00254 options.parse() 00255 except Exception, msg: 00256 options.usage() 00257 raise Exception, msg 00258 00259 dataFile = options.dataFile 00260 if options.timeDepth is not None: 00261 timeDepth = int(options.timeDepth) 00262 else: 00263 timeDepth = 2*hour 00264 startTime = time.time() - timeDepth 00265 00266 if options.keyFile is not None: 00267 keyFile = options.keyFile 00268 from HskReceiver import parseKeyFile 00269 keyList = parseKeyFile(keyFile) 00270 else: # really really basic set of histos. 00271 keyList = {'LHKAEMDAQB33V':'AEM DAQ board 3.3 V', 00272 'LHKAEMFR11T' :'AEM Free board 11 Temp', 00273 'LHKAEMDAQBT' :'AEM DAQ board Temp', 00274 'LHKAEMFR11V1' :'AEM Free 11 HV 1', 00275 'LHKAEMFR11V2' :'AEM Free 11 HV 2', 00276 'LHKAEMFR11VD' :'AEM Free 11 VDD', 00277 } 00278 00279 startQT(dataFile, startTime, keyList) 00280