forked from cms-tsg-fog/RateMon
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathErrorPrinter.py
More file actions
212 lines (181 loc) · 10.1 KB
/
ErrorPrinter.py
File metadata and controls
212 lines (181 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#######################################################
# File: ErrorPrinter
# Author: Nathaniel Carl Rupprecht Charlie Mueller
# Date Created: July 9, 2015
#
# Dependencies: None
#
# Data Type Key:
# { a, b, c, ... } -- denotes a tuple
# [ key ] <object> -- denotes a dictionary of keys associated with objects
# ( object ) -- denotes a list of objects
#######################################################
import array
from ROOT import gROOT, TCanvas, TF1, TGraph, TGraphErrors, TPaveStats, gPad, gStyle, TLegend, TFile, TLine, TLatex, TH1D
#prints bad LS in JSON format
def formatJSON(lumisection_list):
list = "["
minLS = lumisection_list[0]
maxLS = minLS
for i in range(1,len(lumisection_list)):
if lumisection_list[i] > lumisection_list[i-1] + 1:
list = list+"["+str(minLS)+","+str(maxLS)+"], "
minLS = lumisection_list[i]
maxLS = minLS
else:
maxLS = lumisection_list[i]
if list == "[": list = "[["+str(minLS)+","+str(maxLS)+"]]"
else: list = list+"["+str(minLS)+","+str(maxLS)+"]]"
return list
# Class ErrorPrinter:
# Has member variables representing the runs, triggers, and lumisections that were irregular.
# Is able to output this information to an error file
class ErrorPrinter:
# Default constructor for ErrorPrinter class
def __init__(self):
self.run_trig_ls = {} # [ runNumber ] [ triggerName ] ( LS )
self.run_ls_trig = {} # [ runNumber ] [ LS ] ( triggerName )
self.run_allLs = {} # [runNumber][triggerName] (LS)
self.steamData = {} # [ prediction, min predict, max predict, actual, error ]
self.saveDirectory = "" #directory where output txt files are saved
gStyle.SetOptStat(0)
# Use: Outputs information to a file
def outputErrors(self):
# Output all kinds of info to a file
rootFileName = "%s/CertificationSummaries.root" % (self.saveDirectory)
rootFile = TFile(rootFileName,"RECREATE")
print "\nWriting summary root file %s" % (rootFileName)
sortedRuns = sorted(self.run_trig_ls)
try:
fileName = "CertificationSummary_run"+str(sortedRuns[0])+"_run"+str(sortedRuns[-1])+".txt"
file = open(self.saveDirectory+"/"+fileName, 'w') # come up with a name based on something about the runs
print "\nCertification Summary txt file: %s/%s \n" % (self.saveDirectory,fileName)
except:
print "Error writing certification summary ."
return
for runNumber in sortedRuns:
file.write("Run Number: %s\n" % (runNumber))
file.write("\n")
file.write(" TRIGGERS: BAD LUMIECTION(S) \n")
file.write("\n")
totalErrs = 0
badLumiList = {}
badLumiListSorted = {}
for triggerName in sorted(self.run_trig_ls[runNumber]):
file.write(" %s: " % (triggerName))
list = formatJSON(sorted(self.run_trig_ls[runNumber][triggerName]))
file.write(list+"\n")
for LS in sorted(self.run_trig_ls[runNumber][triggerName]):
if badLumiList.has_key(LS): badLumiList[LS] += 1
else: badLumiList[LS] = 1
file.write("\n")
totalLumis = len( self.run_allLs[runNumber][self.run_allLs[runNumber].keys()[0]] )
minLumi = min( self.run_allLs[runNumber][self.run_allLs[runNumber].keys()[0]] )
maxLumi = max( self.run_allLs[runNumber][self.run_allLs[runNumber].keys()[0]] )
# maxNumBadPaths = sorted(badLumiListSorted.keys(), reverse =True)[0]
maxNumBadPaths = len( self.run_allLs[runNumber] )
canvas = TCanvas("can", "can", 1000, 600)
canvas.SetName("Certification Summary of Run %s" % runNumber)
canvas.SetGridx(1);
canvas.SetGridy(1);
summaryHist = TH1D("Certification_Summary_of_Run%s" % (runNumber), "Run %s" % (runNumber), (totalLumis+2), (minLumi-1), (maxLumi+1))
summaryHist.GetXaxis().SetTitle("LS")
summaryHist.GetYaxis().SetTitle("Number of bad paths")
summaryHist.SetMaximum(1.2 * maxNumBadPaths)
#sort the dict so the number of bad triggers is now the key
for LS in sorted(badLumiList.keys(), key=badLumiList.__getitem__, reverse =True):
summaryHist.Fill(LS,badLumiList[LS])
if badLumiListSorted.has_key(badLumiList[LS]):
badLumiListSorted[badLumiList[LS]].append(LS)
else:
badLumiListSorted[badLumiList[LS]] = [LS]
testVariable = 0
file.write(" # OF BAD PATHS : LUMISECTION(S)\n")
file.write("\n")
for numBadTrigs in sorted(badLumiListSorted.keys(), reverse =True):
testVariable += numBadTrigs*(len(sorted(badLumiListSorted[numBadTrigs])))
file.write(" %s : %s\n"%(numBadTrigs, sorted(badLumiListSorted[numBadTrigs])))
totalErrs += len(sorted(badLumiListSorted[numBadTrigs]))
maxLine = TLine(minLumi-1, maxNumBadPaths, maxLumi+1, maxNumBadPaths)
maxLine.SetLineStyle(9)
maxLine.SetLineColor(2)
maxLine.SetLineWidth(2)
summaryHist.Draw("hist")
summaryHist.SetLineColor(4)
summaryHist.SetFillColor(4)
summaryHist.SetFillStyle(3004)
canvas.Update()
latex = TLatex()
latex.SetNDC()
latex.SetTextColor(1)
latex.SetTextAlign(11)
latex.SetTextFont(62)
latex.SetTextSize(0.05)
latex.DrawLatex(0.15, 0.84, "CMS")
latex.SetTextSize(0.035)
latex.SetTextFont(52)
latex.DrawLatex(0.15, 0.80, "Rate Monitoring")
canvas.Update()
maxLine.Draw("same")
canvas.Update()
canvas.Modified()
canvas.Write()
canvas.Print("%s/CertificationSummary_run%s.png" % (self.saveDirectory, runNumber), "png")
fractionBadLumis = 100.*float(totalErrs)/float(totalLumis)
fractionBadRun = 100.*summaryHist.Integral()/float((totalLumis+2) * maxNumBadPaths)
file.write("\n")
file.write("BAD LS SUMMARY: \n")
file.write("\n---- Total bad LS: %s ( bad LS: >= 1 trigger(s) deviating more than 3 sigma from prediction )\n" % (totalErrs))
file.write("---- Total LS: %s\n" % (totalLumis))
file.write("---- Fraction bad LS: %s\n" % (fractionBadLumis))
fractionBadpaths = (100.*(float(testVariable)/(float(totalLumis*maxNumBadPaths))))
totalPossPaths = float(totalLumis*maxNumBadPaths)
totalBadPaths = float(testVariable)
file.write("\n")
file.write("BAD PATH SUMMARY: \n")
file.write("\n")
file.write("---- Total Bad Paths: %.1f\n" % (totalBadPaths))
file.write("---- Total Possible Paths: %.1f\n" % (totalPossPaths))
file.write("---- Fraction that are Bad Paths: %.1f\n" % (float(fractionBadpaths)))
file.write("\n")
file.write("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n")
file.close()
rootFile.Close()
def outputSteamErrors(self):
try:
file = open("OutSteamErrors.err", 'w') # come up with a better name for this too sometime
print "Opening OutSteamErrors.err for Steam comparison error dump."
except:
print "Error: could non open file to output steam data."
TriggersInError = []
file.write("\nTrigger and Prediction Data: \n\n")
file.write("***********************************************************\n\n\n")
# self.steamData -> [ prediction, min predict, max predict, actual, error ]
for triggerName in sorted(self.steamData):
fitpred = self.steamData[triggerName][0] # The prediction based on the fit function we created
steampred = self.steamData[triggerName][3] # The prediction based on the steam .csv file
steamerr = self.steamData[triggerName][4] # The error based on the steam .csv file
upper = steampred + steamerr # The upper error range on the steam data
lower = steampred - steamerr # The lower error range on the steam data
high = self.steamData[triggerName][1] # The upper error prediction based on the uncertainty of our fit
low = self.steamData[triggerName][2] # The lower error prediction based on the uncertainty of our fit
file.write("%s: STEAM prediction range: %s - %s\n" % (triggerName, lower, upper))
file.write(" Predicted value (from fit): %s \n" % (str(fitpred)))
file.write(" Uncertainty in fit yeilds range: %s - %s\n" % ( str(low), str(high) ) )
if self.steamData[triggerName][0] <= upper and lower <= self.steamData[triggerName][0] :
file.write(" This is fine.\n\n")
else:
file.write(" ---> Prediction does not fall within steam uncertainty")
if (fitpred < lower and high > lower) or (fitpred > upper and low < upper):
file.write(", but uncertainty in the fit can explain this discrepancy.\n\n")
else:
file.write("\n----- ERROR: Not in acceptable range. -----\n\n")
TriggersInError.append(triggerName)
file.write("\n\n***********************************************************\nSUMMARY of TRIGGERS in ERROR:")
if len(TriggersInError) == 0:
file.write(" No errors. All triggers we could check were good.\n")
else: file.write("\n")
for triggerName in TriggersInError:
file.write(" " + triggerName + "\n")
file.close()
## ----------- End class ErrorPrinter ----------- #