ATLAS Offline Software
Loading...
Searching...
No Matches
dq_defect_info_table.py
Go to the documentation of this file.
1#! /usr/bin/env python
2
3from argparse import ArgumentParser
4from os import listdir, makedirs
5from os.path import dirname, exists, join as pjoin
6from pkg_resources import resource_filename
7from shutil import copy2
8from textwrap import dedent
9
10from genshi import HTML
11from genshi.output import HTMLSerializer, encode
12from genshi.template import MarkupTemplate
13
14from DQUtils import fetch_iovs
15from DQUtils.general import timer
16from DQUtils.logger import init_logger; init_logger(verbose=2)
17from DQUtils.lumi import fetch_lumi_inputs, compute_lumi_many_channels
18
19from DQDefects import DefectsDB
20
21from IPython.Shell import IPShellEmbed; ip = IPShellEmbed(["-pdb"])
22
23GRAPH_URL = "http://atlasdqm.web.cern.ch/atlasdqm/defect_graph/HEAD"
24
25
28headings = [
29 ("", "V"),
30 ("", "T"),
31 ("", "U"),
32 ("", "B"),
33 ("name_with_url", "Name"),
34 ("description", "Description"),
35 ("nruns", "# Runs"),
36 ("latest_run", "Latest Run"),
37 ("rec_lb_frac", "Potentially Recoverable LB %"),
38 ("lumi", HTML("Luminosity (pb<sup>-1</sup>)")),
39 #("nlumi", "nlumi"),
40 #("nlumi_rec", "nlumi"),
41]
42
43heading_names, heading_titles = zip(*headings)
44
45content_string = "".join("<td>{{d.{0}}}</td>".format(x)
46 for x in heading_names if x)
47
49 """
50 A defect instance. Forms a row in the table.
51 """
52 def __init__(self, name, description, iovs, virtual, intolerable, lumi):
53 if description == name:
54 # Don't bother pretending that there is a description if it is just
55 # equal to the name
56 description = ""
57
58 (self.name, self.description, self.iovs, self.lumi, self.virtual,
59 self.intolerable) = (
60 name, description, iovs, lumi / 1e6, virtual, intolerable)
61 self.nlumi = sum(iov.length for iov in iovs
62 if iov.since.run == iov.until.run)
63 self.nlumi_rec = sum(iov.length for iov in iovs
64 if iov.recoverable and iov.since.run == iov.until.run)
65 if self.nlumi and self.nlumi_rec:
66 self.rec_lb_frac = "{0:.0%}".format(self.nlumi_rec / self.nlumi)
67 else:
68 self.rec_lb_frac = "-"
69
70 self.users = set(iov.user for iov in iovs)
71 self.users -= set(["sys:virtual"]) # exclude the "virtual" user.
72 self.bots = set(u for u in self.users if u.startswith("sys:"))
73 self.users -= self.bots
74
75 runs = iovs.runs
76 self.nruns = len(runs) if runs else "-"
77 self.latest_run = max(runs) if runs else "-"
78 self.lumi = "{0:.3f}".format(self.lumi) if runs else "-"
79
80 @property
81 def name_with_url(self):
82 if self.virtual or self.intolerable:
83 return '<a href="{0}/{1}.svg">{1}</a>'.format(GRAPH_URL, self.name)
84 else:
85 return "{0}".format(self.name)
86
87 @property
88 def content(self):
89 td = '<td class="icon {class_}"><span>{0}</span></td>'
90 bot_cls = user_cls = ""
91 if len(self.users) == 1: user_cls = "user"
92 if len(self.users) > 1: user_cls = "users"
93 if len(self.bots): bot_cls = "bots"
94
95 virt_class = "virtual" if self.virtual else "primary"
96 tol_class = "intolerable" if self.intolerable else "tolerable"
97 virt_sort = 1 if self.virtual else 0
98 tol_sort = 1 if self.virtual else 0
99
100 c = [
101 td.format(virt_sort, class_=virt_class),
102 td.format(tol_sort, class_=tol_class),
103 td.format(", ".join(self.users), class_=user_cls),
104 td.format(", ".join(self.bots), class_=bot_cls),
105 content_string.format(d=self)
106 ]
107 return "".join(c)
108
109def build_table(**kwargs):
110 """
111 Build the HTML content
112 """
113 path = resource_filename("DQDefects.data", "table.html")
114 with open(path) as fd:
115 template = MarkupTemplate(fd, path)
116
117 stream = template.generate(HTML=HTML, **kwargs)
118 serializer = HTMLSerializer(doctype="html5")
119 content = encode(serializer(stream))
120 return content
121
122def build_defects(descriptions, virtuals, intolerables, lbs, lumis, all_defects):
123
124 with timer("Sort defects by channel"):
125 dbc = all_defects.by_channel
126
127 with timer("Compute luminosities"):
128 lumi_by_defect = compute_lumi_many_channels(lbs, lumis, all_defects)
129
130 defects = []
131
132 for name, description in sorted(descriptions.iteritems()):
133 virtual, intolerable = name in virtuals, name in intolerables
134 defect = Defect(name, description, dbc[name], virtual, intolerable,
135 lumi_by_defect.get(name, 0))
136 defects.append(defect)
137
138 defects.sort(key=lambda d: (d.virtual, not d.intolerable))
139
140 return defects
141
142def copy_art(target_dir):
143 art_base = dirname(resource_filename("DQDefects.data", "table.html"))
144
145 for filename in listdir(art_base):
146 _, _, ext = filename.rpartition(".")
147 if ext.lower() not in ("png", "js", "css"):
148 continue
149 copy2(pjoin(art_base, filename), pjoin(target_dir, filename))
150
151def main():
152 d = DefectsDB()
153
154 iov_range = None, None #
155 iov_range = 185000 << 32, 185500 << 32
156 #iov_range = 177682 << 32, 200000 << 32
157
158 with timer("Fetch defect info"):
159 all_defects = d.retrieve(*iov_range)
160
161 with timer("fetch peripheral information"):
162 descriptions = d.all_defect_descriptions
163 intolerable = d.get_intolerable_defects()
164 virtual = d.virtual_defect_names
165
166 with timer("Fetch lumi inputs"):
167 lbs, lumis = fetch_lumi_inputs(iov_range, "ONLINE")
168
169 d = build_defects(descriptions, virtual, intolerable, lbs, lumis, all_defects)
170
171 target_dir = "/afs/cern.ch/user/p/pwaller/www/defects/test"
172 art_dir = pjoin(target_dir, "extern")
173
174 if not exists(art_dir):
175 makedirs(art_dir)
176
177 copy_art(art_dir)
178
179 content = build_table(headings=heading_titles, defects=d)
180 with open(pjoin(target_dir, "test.html"), "w") as fd:
181 fd.write(content)
182
183
184if __name__ == "__main__":
185 main()
#define max(a, b)
Definition cfImp.cxx:41
__init__(self, name, description, iovs, virtual, intolerable, lumi)
STL class.
bool exists(const std::string &filename)
does a file exist
build_defects(descriptions, virtuals, intolerables, lbs, lumis, all_defects)
std::string dirname(std::string name)
Definition utils.cxx:200