Public Member Functions | |
def | __init__ |
def | initialize |
def | execute |
def | finalize |
def | initializeCalibTable |
def | initializeCalib |
def | updateCalibration |
def | updateAdCalibration |
def | getAdCalibHists |
def | getPmtDistance |
def | timeToAdPmt |
def | updateWaterShieldCalibration |
def | calibTableLine |
def | writeCalibTable |
Public Attributes | |
StatsPath | |
OutputTableName | |
IsDryAd | |
SetDefaultCalib | |
SourcePosition | |
cableSvc | |
statsSvc | |
pmtGeomSvc |
Definition at line 25 of file Tools.py.
def CalibParam::Tools::PmtTableWriterAlg::__init__ | ( | self, | ||
name | ||||
) |
Definition at line 27 of file Tools.py.
00027 : 00028 DybPythonAlg.__init__(self,name) 00029 # Properties 00030 self.StatsPath = "/file0/pmtCalibLeadingEdge" 00031 self.OutputTableName = "pmtCalibTable.txt" 00032 self.IsDryAd = False 00033 self.SetDefaultCalib = True 00034 self.SourcePosition = [0.,0.,0.] 00035 return 00036 def initialize(self):
def CalibParam::Tools::PmtTableWriterAlg::initialize | ( | self | ) |
Definition at line 37 of file Tools.py.
00037 : 00038 status = DybPythonAlg.initialize(self) 00039 if status.isFailure(): return status 00040 self.info("initializing") 00041 00042 # Initialize services 00043 self.cableSvc = self.svc('ICableSvc','StaticCableSvc') 00044 if self.cableSvc == None: 00045 self.error("Failed to get StaticCableSvc") 00046 return FAILURE 00047 self.statsSvc = self.svc('IStatisticsSvc','StatisticsSvc') 00048 if self.statsSvc == None: 00049 self.error("Failed to get StatisticsSvc") 00050 return FAILURE 00051 self.pmtGeomSvc = self.svc('IPmtGeomInfoSvc','PmtGeomInfoSvc') 00052 if self.pmtGeomSvc == None: 00053 self.error("Failed to get PmtGeomInfoSvc") 00054 return FAILURE 00055 return status 00056 def execute(self):
def CalibParam::Tools::PmtTableWriterAlg::execute | ( | self | ) |
def CalibParam::Tools::PmtTableWriterAlg::finalize | ( | self | ) |
Definition at line 61 of file Tools.py.
00061 : 00062 self.info("finalizing") 00063 # Generate the PMT calibration table, and write to file 00064 # Step 1: initialize the table 00065 pmtCalibList = self.initializeCalibTable() 00066 self.info("I initialized the table") #tmp 00067 # Step 2: incorporate data using the current calibration statistics 00068 status = self.updateCalibration(pmtCalibList) 00069 if not status.isSuccess(): return status 00070 # Step 3: Print out the table 00071 self.writeCalibTable(pmtCalibList) 00072 status = DybPythonAlg.finalize(self) 00073 return status 00074 def initializeCalibTable(self):
def CalibParam::Tools::PmtTableWriterAlg::initializeCalibTable | ( | self | ) |
Definition at line 75 of file Tools.py.
00075 : 00076 # Initialize table of PMT calibrations 00077 context = Context() 00078 context.SetSite(Site.kAll) 00079 context.SetDetId(DetectorId.kAll) 00080 svcMode = ServiceMode(context, 0) # Dummy ServiceMode 00081 adPmts = self.cableSvc.adPmtSensors(svcMode) 00082 poolPmts = self.cableSvc.poolPmtSensors(svcMode) 00083 adPmtCalibList = [] 00084 for adPmt in adPmts: 00085 pmtCalib = PmtCalibData() 00086 pmtCalib.m_pmtId = adPmt 00087 if self.SetDefaultCalib: self.initializeCalib(pmtCalib) 00088 adPmtCalibList.append( pmtCalib ) 00089 poolPmtCalibList = [] 00090 for poolPmt in poolPmts: 00091 pmtCalib = PmtCalibData() 00092 pmtCalib.m_pmtId = poolPmt 00093 if self.SetDefaultCalib: self.initializeCalib(pmtCalib) 00094 poolPmtCalibList.append( pmtCalib ) 00095 pmtCalibList = adPmtCalibList + poolPmtCalibList 00096 return pmtCalibList 00097 def initializeCalib(self, pmtCalib):
def CalibParam::Tools::PmtTableWriterAlg::initializeCalib | ( | self, | ||
pmtCalib | ||||
) |
Definition at line 98 of file Tools.py.
00098 : 00099 # Initialize using an approximate default calibration 00100 pmtCalib.m_status = PmtCalibData.kGood 00101 pmtCalib.m_speHigh = 20.0 00102 pmtCalib.m_sigmaSpeHigh = 0.0 00103 pmtCalib.m_speLow = 2.0 00104 pmtCalib.m_timeOffset = 0.0 00105 pmtCalib.m_timeSpread = 0.0 00106 pmtCalib.m_efficiency = 1.0 00107 pmtCalib.m_prePulseProb = 0.0 00108 pmtCalib.m_afterPulseProb = 0.0 00109 pmtCalib.m_darkRate = 0.0 00110 def updateCalibration(self, pmtCalibList):
def CalibParam::Tools::PmtTableWriterAlg::updateCalibration | ( | self, | ||
pmtCalibList | ||||
) |
Definition at line 111 of file Tools.py.
00111 : 00112 # Process the calibration statistics and update the 00113 # calibration parameters 00114 detDirs = self.statsSvc.getSubFolders(self.StatsPath) 00115 for detDir in detDirs: 00116 detector = Detector(detDir) 00117 if( detector.site() == Site.kUnknown 00118 or detector.detectorId() == DetectorId.kUnknown ): 00119 self.error("Unknown detector: "+detDir) 00120 return FAILURE 00121 else: 00122 self.info("Processing: "+detDir) 00123 # Find the PMT IDs that are in the current detector 00124 pmtCalibs = [] 00125 for pmtCalib in pmtCalibList: 00126 pmtId = pmtCalib.m_pmtId 00127 if (pmtId.site() == detector.site() 00128 and pmtId.detectorId() == detector.detectorId()): 00129 pmtCalibs.append(pmtCalib) 00130 if detector.isAD(): 00131 status = self.updateAdCalibration(detector, pmtCalibs) 00132 if not status.isSuccess(): return status 00133 elif detector.isWaterShield(): 00134 status = self.updateWaterShieldCalibration(detector, pmtCalibs) 00135 if not status.isSuccess(): return status 00136 return SUCCESS 00137 def updateAdCalibration(self, detector, pmtCalibList):
def CalibParam::Tools::PmtTableWriterAlg::updateAdCalibration | ( | self, | ||
detector, | ||||
pmtCalibList | ||||
) |
Definition at line 138 of file Tools.py.
00138 : 00139 print "I am in updateAdCalibration" #tmp 00140 # Loop over the pmts and process calibration stats 00141 meanTimeOffset = 0.0 00142 nMeanTimeOffset = 0 00143 relativeEfficiency = {} 00144 for ring in range(1,9): relativeEfficiency[ring] = [] 00145 for pmtCalib in pmtCalibList: 00146 00147 pmtId = pmtCalib.m_pmtId 00148 if pmtId.ring() < 1: continue # Skip 2-inch calib pmts 00149 # Get the calibration histograms for this pmt 00150 [occupancyH, tdcOffsetH, adcMeanH, adcSigmaH] = self.getAdCalibHists(pmtId) 00151 if occupancyH==None or tdcOffsetH==None or adcMeanH==None: 00152 self.error("Failed to get calibration histograms for " 00153 +detector.detName()) 00154 return FAILURE 00155 occupancy = occupancyH.GetBinContent(pmtId.column()) 00156 occupancyUncert = occupancyH.GetBinError(pmtId.column()) 00157 tdcOffset = tdcOffsetH.GetBinContent(pmtId.column()) 00158 tdcOffsetUncert = tdcOffsetH.GetBinError(pmtId.column()) 00159 adcMean = adcMeanH.GetBinContent(pmtId.column()) 00160 adcMeanUncert = adcMeanH.GetBinError(pmtId.column()) 00161 adcReso = adcSigmaH.GetBinContent(pmtId.column()) 00162 adcResoUncert = adcSigmaH.GetBinError(pmtId.column()) 00163 # Update PMT status 00164 pmtCalib.m_status = PmtCalibData.kUnknown 00165 if( occupancy < 0.01 or occupancyUncert > 0.1 ): 00166 pmtCalib.m_status += PmtCalibData.kBadEfficiency 00167 if( tdcOffsetUncert > 20.0 ): 00168 pmtCalib.m_status += PmtCalibData.kBadTiming 00169 if( adcMean < 10.0 or adcMean > 50.0 or adcMeanUncert > 4.0 ): 00170 pmtCalib.m_status += PmtCalibData.kBadGain 00171 # If no problems found, PMT is good 00172 if( pmtCalib.m_status == PmtCalibData.kUnknown ): 00173 pmtCalib.m_status = PmtCalibData.kGood 00174 # Convert time offset to nanoseconds 00175 tdcToNs = 1.5625 00176 lightTravelTime = self.timeToAdPmt(self.SourcePosition, pmtId) 00177 timeOffset = -tdcOffset * tdcToNs - lightTravelTime 00178 timeSpread = tdcOffsetUncert*tdcToNs 00179 pmtCalib.m_timeOffset = timeOffset 00180 pmtCalib.m_timeSpread = timeSpread 00181 # wangzhe: comment out temporarily 00182 # pmtCalib.m_efficiency = -math.log(1 - occupancy) 00183 # wz 00184 pmtCalib.m_speHigh = adcMean 00185 pmtCalib.m_sigmaSpeHigh = adcReso 00186 # FIXME: need dedicated Low-gain calibration: 00187 # According to DocDB 5038, for dry run it is set to 19.5 00188 pmtCalib.m_speLow = adcMean / 19.5 00189 # Update mean time 00190 if not (pmtCalib.m_status & PmtCalibData.kBadTiming): 00191 meanTimeOffset += timeOffset 00192 nMeanTimeOffset += 1 00193 # Update mean efficiency by ring 00194 if not (pmtCalib.m_status & PmtCalibData.kBadEfficiency): 00195 relativeEfficiency[pmtId.ring()].append(pmtCalib.m_efficiency) 00196 # Adjust timing offset so mean over detector is zero 00197 if nMeanTimeOffset != 0: 00198 meanTimeOffset /= nMeanTimeOffset 00199 for pmtCalib in pmtCalibList: 00200 pmtId = pmtCalib.m_pmtId 00201 if pmtId.ring() < 1: continue # Skip 2-inch calib pmts 00202 pmtCalib.m_timeOffset -= meanTimeOffset 00203 # Adjust the relative efficiency according to the mean for each ring 00204 meanEfficiency = {} 00205 for ring in relativeEfficiency.keys(): 00206 relEff = relativeEfficiency[ring] 00207 meanEfficiency[ring] = 0 00208 if len(relEff) > 0: 00209 meanEfficiency[ring] = sum(relEff)/len(relEff) 00210 for pmtCalib in pmtCalibList: 00211 pmtId = pmtCalib.m_pmtId 00212 if pmtId.ring() < 1: continue # Skip 2-inch calib pmts 00213 if meanEfficiency[pmtId.ring()] != 0: #jpochoa 00214 pmtCalib.m_efficiency /= meanEfficiency[pmtId.ring()] 00215 else: 00216 pmtCalib.m_efficiency = -1 00217 00218 00219 00220 return SUCCESS 00221 def getAdCalibHists(self, pmtId):
def CalibParam::Tools::PmtTableWriterAlg::getAdCalibHists | ( | self, | ||
pmtId | ||||
) |
Definition at line 222 of file Tools.py.
00222 : 00223 # Return the calibration histograms for this PMT 00224 path = self.StatsPath + "/" + pmtId.detName() 00225 path += "/ring_%d" % pmtId.ring() 00226 occupancyH = self.statsSvc.get(path + "/occupancy") 00227 tdcOffsetH = self.statsSvc.get(path + "/tdcOffset") 00228 if self.StatsPath=="/file0/pmtCalibLeadingEdge": 00229 adcMeanH = self.statsSvc.get(path + "/adcMean") 00230 else: 00231 adcMeanH = self.statsSvc.get(path + "/adcMedian") 00232 adcSigmaH = self.statsSvc.get(path + "/adcSigma") 00233 return [occupancyH, tdcOffsetH, adcMeanH, adcSigmaH] 00234 def getPmtDistance(self, position, pmtId):
def CalibParam::Tools::PmtTableWriterAlg::getPmtDistance | ( | self, | ||
position, | ||||
pmtId | ||||
) |
Definition at line 235 of file Tools.py.
00235 : 00236 "Return the distance from position to the pmt with ID pmtID" 00237 # No Site.kSAB in current geometry tree. Change it to kDayaBay to work around 00238 site = pmtId.site() 00239 if site == Site.kSAB: 00240 site = Site.kDayaBay 00241 tmpPmtId = AdPmtSensor( pmtId.ring(), pmtId.column(), site, pmtId.detectorId() ) 00242 pmtGeomInfo = self.pmtGeomSvc.get( tmpPmtId.fullPackedData() ) 00243 Rpmt = pmtGeomInfo.localPosition() 00244 dR = [position[0] - Rpmt.x(), 00245 position[1] - Rpmt.y(), 00246 position[2] - Rpmt.z()] 00247 return math.sqrt(dR[0]*dR[0] + dR[1]*dR[1] + dR[2]*dR[2]) 00248 def timeToAdPmt(self, position, pmtId):
def CalibParam::Tools::PmtTableWriterAlg::timeToAdPmt | ( | self, | ||
position, | ||||
pmtId | ||||
) |
Definition at line 249 of file Tools.py.
00249 : 00250 "Calculate the light travel time from source to pmt" 00251 dr = self.getPmtDistance(position, pmtId) 00252 lightSpeedInVac = 299.79 * units.mm/units.ns 00253 liquidIndexOfRefrac = 1.45 00254 lightSpeed = lightSpeedInVac 00255 if not self.IsDryAd: 00256 lightSpeed /= liquidIndexOfRefrac 00257 return dr / lightSpeed 00258 00259 def updateWaterShieldCalibration(self, detector, pmtCalibList):
def CalibParam::Tools::PmtTableWriterAlg::updateWaterShieldCalibration | ( | self, | ||
detector, | ||||
pmtCalibList | ||||
) |
Definition at line 260 of file Tools.py.
00260 : 00261 # Update the calib data for this water shield based on calibration data 00262 self.error("Calibration of water shield not implemented") 00263 self.error("I am ignoring this for now") #jpochoa 00264 return SUCCESS #jpochoa 00265 def calibTableLine(self, pmtCalib):
def CalibParam::Tools::PmtTableWriterAlg::calibTableLine | ( | self, | ||
pmtCalib | ||||
) |
Definition at line 266 of file Tools.py.
00266 : 00267 # Write a line for the calibration table 00268 pmtLabel = None 00269 pmtId = pmtCalib.m_pmtId 00270 if pmtId.isAD(): 00271 pmtLabel = "%s-ring%02d-column%02d" % (pmtId.detName(), 00272 pmtId.ring(), 00273 pmtId.column()) 00274 elif pmtId.isWaterShield(): 00275 inward = "in" 00276 if not pmtId.inwardFacing(): inward = "out" 00277 pmtLabel = "%s-wall%02d-spot%02d-%s" % (pmtId.detName(), 00278 pmtId.wallNumber(), 00279 pmtId.wallSpot(), 00280 inward) 00281 line=("%d %30s %2d %7.3f %5.3f %5.3f %7.3f %5.3f %5.3f %5.3f %5.3f %5.3f\n" 00282 % (pmtCalib.m_pmtId.fullPackedData(), 00283 pmtLabel, 00284 pmtCalib.m_status, 00285 pmtCalib.m_speHigh, 00286 pmtCalib.m_sigmaSpeHigh, 00287 pmtCalib.m_speLow, 00288 pmtCalib.m_timeOffset / units.ns, 00289 pmtCalib.m_timeSpread / units.ns, 00290 pmtCalib.m_efficiency, 00291 pmtCalib.m_prePulseProb, 00292 pmtCalib.m_afterPulseProb, 00293 pmtCalib.m_darkRate / units.hertz 00294 ) 00295 ) 00296 return line 00297 def writeCalibTable(self, pmtCalibList):
def CalibParam::Tools::PmtTableWriterAlg::writeCalibTable | ( | self, | ||
pmtCalibList | ||||
) |
Definition at line 298 of file Tools.py.
00298 : 00299 # Write a calibration table using the list of pmt calibrations 00300 tableLines = [] 00301 tableLines.append("# Table of Calibration constants for each channel\n") 00302 tableLines.append("# [pmtID] [description] [status] [speHigh] [sigmaSpe] [speLow] [timeOffset] [timeSpread] [efficiency] [prePulse] [afterPulse] [darkRate]\n") 00303 00304 # sort them by id, otherwise it is out of control 00305 idCalib = {} 00306 for pmtCalib in pmtCalibList: 00307 idCalib[ pmtCalib.m_pmtId.fullPackedData() ] = pmtCalib 00308 00309 for id in sorted( idCalib.keys() ): 00310 pmtCalib = idCalib[id] 00311 line = self.calibTableLine(pmtCalib) 00312 tableLines.append(line) 00313 outFile = open(self.OutputFileName,'w') 00314 outFile.writelines(tableLines) 00315 outFile.close() 00316 00317 00318 # Merge calibration tables def mergeTables(primaryFile, changeMap, outputFile):