Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

rcHouseKeeping.py

00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2002
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__ = "Housekeeping FITS file generation class for RunControl"
00012 __author__   = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__     = ("$Date: 2005/03/03 19:52:37 $").split(' ')[1]
00014 __version__  = "$Revision: 2.4 $"
00015 __release__  = "$Name: R04-12-00 $"
00016 __credits__  = "SLAC"
00017 
00018 import LATTE.copyright_SLAC
00019 
00020 import              os
00021 from cfitsio import *
00022 import              time
00023 from struct import  unpack
00024 import              threading
00025 import              operator
00026 import              calendar
00027 import logging as log
00028 
00029 MODE_CREATE = 0
00030 MODE_READONLY = 2
00031 
00032 TEM_ENV_REGS = 0
00033 AEM_ENV_REGS = 1
00034 
00035 HSK_VERSION_STR = '1.0'
00036 
00037 TEM_ENV_REG_LIST = [
00038                     'tkr_biasdac',
00039                     'cal_biasdac',
00040                     'adc_tkr_digital_2_5v',
00041                     'adc_tkr_digital_2_5i',
00042                     'adc_tkr_analog_a_1_5v',
00043                     'adc_tkr_analog_a_1_5i',
00044                     'adc_tkr_analog_b_2_5v',
00045                     'adc_tkr_analog_b_2_5i',
00046                     'adc_tkr_bias_v',
00047                     'adc_tkr_bias_i',
00048                     'adc_cal_digital_3_3v',
00049                     'adc_cal_digital_3_3i',
00050                     'adc_cal_analog_3_3v',
00051                     'adc_cal_analog_3_3i',
00052                     'adc_cal_bias_v',
00053                     'adc_cal_bias_i',
00054                     'adc_tem_digital_3_3v',
00055                     'adc_tem_digital_3_3i',
00056                     'adc_afee0_t0',
00057                     'adc_afee0_t1',
00058                     'adc_afee1_t0',
00059                     'adc_afee1_t1',
00060                     'adc_afee2_t0',
00061                     'adc_afee2_t1',
00062                     'adc_afee3_t0',
00063                     'adc_afee3_t1',
00064                     'adc_tkr_c0_t0',
00065                     'adc_tkr_c0_t1',
00066                     'adc_tkr_c1_t0',
00067                     'adc_tkr_c1_t1',
00068                     'adc_tkr_c2_t0',
00069                     'adc_tkr_c2_t1',
00070                     'adc_tkr_c3_t0',
00071                     'adc_tkr_c3_t1',
00072                     'adc_tkr_c4_t0',
00073                     'adc_tkr_c4_t1',
00074                     'adc_tkr_c5_t0',
00075                     'adc_tkr_c5_t1',
00076                     'adc_tkr_c6_t0',
00077                     'adc_tkr_c6_t1',
00078                     'adc_tkr_c7_t0',
00079                     'adc_tkr_c7_t1',
00080                     'sat_cal_lrs_ctr_0',
00081                     'sat_cal_lrs_ctr_1',
00082                     'sat_tkr_lrs_ctr_0',
00083                     'sat_tkr_lrs_ctr_1',
00084                     'sat_tkr_lrs_ctr_2',
00085                     'sat_tkr_lrs_ctr_3',
00086                     'sat_deadtime_lrs_ctr'
00087                     ]
00088 
00089 AEM_ENV_REG_LIST = [
00090                     'env_free_00',
00091                     'env_free_01',
00092                     'env_free_02',
00093                     'env_free_03',
00094                     'env_free_04',
00095                     'env_free_05',
00096                     'env_free_06',
00097                     'env_free_07',
00098                     'env_free_08',
00099                     'env_free_09',
00100                     'env_free_10',
00101                     'env_free_11',
00102                     ]
00103 
00104 class rcHouseKeeping(object):
00105   def __init__(self, lat, latFilename, mode=MODE_CREATE, tableSize=1000, flushInterval=0):
00106     self.__lat = lat
00107     self.__latFilename = latFilename
00108     self.__threadQuit = 0
00109     self.__threadPause = 0
00110     self.__envRegs = []
00111     self.__envUnits = []
00112     self.__envNames = []
00113     self.__updateInterval = 1.0 # default to 1 second
00114     self.__sampleCount = 0
00115     self.__envValues = []
00116     self.__envTStamps = []
00117     self.__tableSize = tableSize
00118     self.__fptr = None
00119     self.__mode = mode
00120     self.__flushInterval = flushInterval
00121     self.__status = 0
00122     self.__fileName = None
00123     self.__filePath = None
00124 
00125   def initialize(self, filePath=None, fileName=None, compress=0):
00126     if self.__mode == MODE_CREATE:
00127       if filePath is not None or fileName is not None:
00128         if fileName is None:
00129           ts   = time.strftime('%y%m%d%H%M%S', time.gmtime())
00130           self.__fileName = getFileNameFromTS(ts)
00131           self.__timestamp = int(time.time())
00132         else:
00133           self.__fileName = fileName
00134           try:
00135             self.__timestamp = int(calendar.timegm(
00136                           time.strptime(self.__fileName.split('.',1)[0][3:], '%y%m%d%H%M%S')
00137                         ))
00138           except:
00139             self.__timestamp = 0
00140         if compress: self.__fileName += '.gz'
00141         if filePath is None:
00142           self.__filePath = ""
00143         else:
00144           self.__filePath = filePath
00145       fname = os.path.join(self.__filePath, self.__fileName)
00146       (self.__status, self.__fptr) = cfitsio.fits_create_file(fname)
00147       if self.__status != 0:
00148         raise IOError, "fits_create_file: %s filename=%s" % (cfitsio.fits_get_errstatus(self.__status), fname)
00149       naxis = 0
00150       naxes = []
00151       self.__status = cfitsio.fits_create_img(self.__fptr, cfitsio.SHORT_IMG, naxis, naxes)
00152       if self.__status != 0:
00153         raise IOError, "fits_create_img: %s" % cfitsio.fits_get_errstatus(self.__status)
00154       comment1 = "Housekeeping data file"
00155       status = cfitsio.fits_write_comment(self.__fptr, " ")
00156       status = cfitsio.fits_write_comment(self.__fptr, comment1)
00157       self.__status = cfitsio.fits_write_key_str(self.__fptr, "HSK_VER", HSK_VERSION_STR, "Housekeeping File Version")
00158       self.checkStatus("fits_write_key_str", self.__status)
00159       self.__status = cfitsio.fits_write_key_str(self.__fptr, "SCHEMA", self.__latFilename, "Schema File Name")
00160       self.checkStatus("fits_write_key_str", self.__status)
00161       self.__status = cfitsio.fits_write_key_lng(self.__fptr, "TIMESTMP",
00162                                                   self.__timestamp, "Housekeeping Timestamp")
00163       self.__tablenum = 0
00164     elif self.__mode == MODE_READONLY:
00165       pass
00166     else:
00167       raise RuntimeError, "Invalid Housekeeping mode"
00168 
00169   def createNewTable(self):
00170     tfields = len(self.__envNames) + 1
00171     ttype = ['timestamp'] + self.__envNames
00172     tform = ['1D'] +  ['1V'] * (tfields - 1)
00173     tunit = ['seconds'] + self.__envUnits
00174     extname='Environmental Quantities'
00175     self.__status = cfitsio.fits_create_tbl(self.__fptr, cfitsio.BINARY_TBL,
00176                         self.__tableSize, tfields, ttype, tform, tunit, extname)
00177     if self.__status != 0:
00178       raise IOError, "fits_create_tbl: %s" % cfitsio.fits_get_errstatus(self.__status)
00179     self.__status = cfitsio.fits_write_key_lng(self.__fptr, "RECCOUNT",
00180                                                 0, "Record Count")
00181     if self.__status != 0:
00182       raise IOError, "fits_write_key_lng: %s" % cfitsio.fits_get_errstatus(self.__status)
00183     #for i in range(tfields):
00184     #  hdrLabel = "TDISP%d" % (i+1)
00185     #  if i == 0:
00186     #    hdrValue = "F10.3"
00187     #  else:
00188     #    hdrValue = "I12.1"
00189 
00190     hdrLabel = "TDISP1"
00191     hdrValue = "F10.3"
00192 
00193     self.__status = cfitsio.fits_write_key_str(self.__fptr, hdrLabel, hdrValue, "")
00194     self.checkStatus("fits_write_key_str", self.__status)
00195     self.__rownum = 1
00196     self.__tablenum += 1
00197 
00198   def write(self):
00199     if self.__tablenum == 0:
00200       self.createNewTable()
00201     elif self.__rownum > self.__tableSize:
00202       self.__status = cfitsio.fits_update_key_lng(self.__fptr, "RECCOUNT",
00203                                                  self.__rownum - 1, "Record Count")
00204       if self.__status != 0:
00205         raise IOError, "fits_update_key_lng: %s" % cfitsio.fits_get_errstatus(self.__status)
00206       if self.__flushInterval > 0:
00207           self.__status = cfitsio.fits_flush_file(self.__fptr)
00208           if self.__status != 0:
00209             raise IOError, "fits_flush_file: %s" % cfitsio.fits_get_errstatus(self.__status)
00210       self.createNewTable()
00211 
00212 
00213     colNum = 1
00214     recTstamp = max(self.__envTStamps)
00215     self.__status = cfitsio.fits_write_col_dbl(self.__fptr, colNum, self.__rownum,
00216                                                1, 1, [recTstamp])
00217     if self.__status != 0:
00218       raise IOError, "fits_write_col_dbl: %s" % cfitsio.fits_get_errstatus(self.__status)
00219     for value in self.__envValues:
00220       colNum += 1
00221       self.__status = cfitsio.fits_write_col_lng(self.__fptr, colNum, self.__rownum,
00222                                                  1, [value])
00223       if self.__status != 0:
00224         raise IOError, "fits_write_col_lng %s" % cfitsio.fits_get_errstatus(self.__status)
00225 
00226     if (self.__flushInterval > 0) and (self.__rownum % self.__flushInterval == 0):
00227       self.__status = cfitsio.fits_update_key_lng(self.__fptr, "RECCOUNT",
00228                                                 self.__rownum, "Record Count")
00229       if self.__status != 0:
00230         raise IOError, "fits_update_key_lng: %s" % cfitsio.fits_get_errstatus(self.__status)
00231       self.__status = cfitsio.fits_flush_buffer(self.__fptr, 0)
00232       if self.__status != 0:
00233         raise IOError, "fits_flush_buffer: %s" % cfitsio.fits_get_errstatus(self.__status)
00234     self.__rownum +=1
00235 
00236 
00237   def moveToHDU(self, tablenum):
00238     (self.__status, hdutype) = cfitsio.fits_movabs_hdu(self.__fptr, tablenum)
00239     if self.__status != 0:
00240       return self.__status
00241     (self.__status, self.__eventCount, comment) = cfitsio.fits_read_key_lng(self.__fptr, 'RECCOUNT')
00242     if self.__status != 0:
00243       raise IOError, "fits_read_key_lng: %s" % cfitsio.fits_get_errstatus(self.__status)
00244     return self.__status
00245 
00246 
00247   def read(self):
00248     self.__rownum += 1
00249     if self.__rownum > self.__eventCount:
00250       self.__tablenum += 1
00251       status = self.moveToHDU(self.__tablenum)
00252       if status != 0:
00253         return None
00254       self.__rownum = 1
00255     (self.__status, event_size, heap_addr) = cfitsio.fits_read_descript(self.__fptr, 1, self.__rownum)
00256     if self.__status != 0:
00257       raise IOError, "fits_read_descript: %s" % cfitsio.fits_get_errstatus(self.__status)
00258     (self.__status, dat) = cfitsio.fits_read_col_byt(self.__fptr, 1, self.__rownum, 1, event_size, None)
00259     if self.__status != 0:
00260       raise IOError, "fits_read_col_byt: %s" % cfitsio.fits_get_errstatus(self.__status)
00261     return dat
00262 
00263 
00264   def close(self):
00265     if self.__fptr is not None:
00266       if self.__mode != MODE_READONLY:
00267         if self.__tablenum > 0:
00268           self.__status = cfitsio.fits_update_key_lng(self.__fptr, "RECCOUNT",
00269                                                     self.__rownum - 1, "Event Count")
00270           if self.__status != 0:
00271             raise IOError, "fits_update_key_lng: %s" % cfitsio.fits_get_errstatus(self.__status)
00272       self.__status = cfitsio.fits_close_file(self.__fptr)
00273       if self.__status != 0:
00274         raise IOError, "fits_close_file: %s" % cfitsio.fits_get_errstatus(self.__status)
00275 
00276   def setFlushInterval(self, flushInterval):
00277     self.__flushInterval = flushInterval
00278 
00279   def getStatus(self):
00280     return self.__status
00281 
00282   def getFileName(self, full=0):
00283     if self.__filePath is None or self.__fileName is None:
00284       return None
00285     elif full:
00286       return os.path.join(self.__filePath, self.__fileName)
00287     else:
00288       return self.__fileName
00289 
00290   def setEnvRegs(self, regList, componentId=None):
00291     self.__envRegs = []
00292     self.__envUnits = []
00293     self.__envNames = []
00294     self.addEnvRegs(regList, componentId)
00295 
00296   def addEnvRegs(self, regList, componentId=None):
00297     if operator.isNumberType(regList):
00298       if regList == TEM_ENV_REGS:
00299         if componentId is None:
00300           raise RuntimeError, "Please specify from which TEM " \
00301                               "the environment values are going to be collected."
00302         if not self.__lat.existsTEM(componentId):
00303           raise RuntimeError, "TEM[%d] node not found in LAT hierarchy" % componentId
00304         tem = self.__lat.TEM[componentId]
00305         if not tem.existsTIC():
00306           raise RuntimeError, "GTIC node not found in LAT hierarchy"
00307         regNode  = tem.TIC
00308         regNames = TEM_ENV_REG_LIST
00309       elif regList == AEM_ENV_REGS:
00310         if not self.__lat.existsAEM():
00311           raise RuntimeError, "AEM node not found in LAT hierarchy"
00312         aem = self.__lat.AEM
00313         if not aem.existsAEQ():
00314           raise RuntimeError, "GAEQ node not found in LAT hierarchy"
00315         regNode = aem.AEQ
00316         regNames = AEM_ENV_REG_LIST
00317       else:
00318         raise RuntimeError, "Invalid register template id: %d" % regList
00319       regList = []
00320       for regName in regNames:
00321         reg = regNode.regs[regName]
00322         regList.append(regNode.regs[regName])
00323     self.__envRegs += regList
00324     for reg in self.__envRegs:
00325       node = reg.getNode()
00326       ids = str(node.getIdTuple())
00327       if ids[-2] == ',':
00328         ids = ids[:-2] + ids[-1]
00329       self.__envNames.append(self.getRegLabel(reg))
00330       self.__envUnits.append(reg.getEGU().units())
00331 
00332   def setUpdateInterval(self, updateInterval):
00333     self.__updateInterval = updateInterval
00334 
00335   def stop(self):
00336     self.__threadQuit = 1
00337     if self.__envThread.isAlive():
00338       self.__envThread.join()
00339     self.close()
00340 
00341   def pause(self):
00342     self.__threadPause = 1
00343 
00344   def resume(self):
00345     self.__threadPause = 0
00346 
00347   def getRegLabel(self, reg):
00348     node = reg.getNode()
00349     ids = str(node.getIdTuple())
00350     if ids[-2] == ',':
00351       ids = ids[:-2] + ids[-1]
00352     return node.getName() + ids + "." + reg.getName()
00353 
00354 
00355 
00356   def getSampleCount(self):
00357     return self.__sampleCount
00358 
00359   def getEnvNames(self):
00360     return self.__envNames
00361 
00362   def getCachedValues(self):
00363     return self.__envValues
00364 
00365   def getCachedValue(self, reg, bypass=1, strVal=0):
00366     regName = reg.getName()
00367     regLabel = self.getRegLabel(reg)
00368     if regLabel in self.__envNames:
00369       val = self.__envValues[self.__envNames.index(regLabel)]
00370       if bypass == 0:
00371         if self.__mode != MODE_READONLY:
00372           val = reg.getEGU().egu(val)
00373         if strVal == 1:
00374           val = '%8.2f' %val + "%-2s" %reg.getEGU().units()
00375       else:
00376         if self.__mode == MODE_READONLY:
00377           val = reg.getEGU().raw(val)
00378         if strVal == 1:
00379           val = str(val)
00380       return val
00381     else:
00382       #print regName, "not found in", self.__envNames
00383       return None
00384 
00385   def getEnvQuantities(self, regList, bypass=0):
00386     values = []
00387     tstamps = []
00388     for reg in regList:
00389       if reg.isCommand() or reg.isWriteOnly() or reg.isNoDirectAccess():
00390         raise RuntimeError, "Invalid environmental quantity register: %s" % reg.getName()
00391       try:
00392         value = reg.get(bypass)
00393       except:
00394         value = 0
00395       tstamp = reg.getTimeStamp()
00396       name = reg.getName()
00397       values.append(value)
00398       tstamps.append(tstamp)
00399     return (values, tstamps)
00400 
00401   def updateValues(self): #revisit
00402      if self.__mode == MODE_READONLY:
00403        (values, tstamps) = self.getEnvQuantities(self.__envRegs, bypass=0)
00404        self.__envValues = values
00405      else:
00406        (values, tstamps) = self.getEnvQuantities(self.__envRegs, bypass=1)
00407        self.__envValues = map(long, values)
00408      self.__envTStamps = tstamps
00409      if self.__fptr is not None:
00410        self.write()
00411      self.__sampleCount += 1
00412 
00413   def start(self):
00414     self.__threadQuit = 0
00415     self.__envThread = threading.Thread(target=self.run,name="HouseKeeping")
00416     self.__envThread.start()
00417     # Let the thread get at least one measurement
00418     time.sleep(1)
00419 
00420   def run(self):
00421     if len(self.__envRegs) == 0:
00422       if self.__lat.existsTEM(0):
00423         self.addEnvRegs(TEM_ENV_REGS, 0)
00424       if self.__lat.existsAEM():
00425         self.addEnvRegs(AEM_ENV_REGS)
00426       if not self.__lat.existsTEM(0) and not self.__lat.existsAEM():
00427         #Probably in GASU mode, exit the thread
00428         return
00429     while(not self.__threadQuit):
00430       # get data here
00431       if not self.__threadPause:
00432         self.updateValues()
00433       t0 = time.time()
00434       while (time.time() - t0 < self.__updateInterval):
00435         time.sleep(.001)
00436         if self.__threadQuit:
00437           break
00438 
00439   def checkStatus(self, cfitsio_function, status):
00440     if status != 0:
00441       raise IOError, "%s: %s" % (cfitsio_function, cfitsio.fits_get_errstatus(status))
00442 
00443 # ---- End rcHouseKeeping -----
00444 
00445 def getFileNameFromTS(ts):
00446     return "env" + ts + ".fits"
00447 

Generated on Fri Jul 21 13:26:31 2006 for LATTE R04-12-00 by doxygen 1.4.3