CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
app_utils.py
Go to the documentation of this file.
1 #! /usr/bin/python
2 # coding: utf-8
3 '''
4 Helper functions for CherryPy application ``browse_db.py``.
5 
6 Author: Albertas Gimbutas, Vilnius University (LT)
7 e-mail: albertasgim@gmail.com
8 '''
9 
10 import sqlite3
11 import re
12 from os import getcwd, listdir
13 from os.path import join
14 from urllib import quote
15 
16 
17 renaming = {
18  'MessageLogger': 'Miscellanea', 'FourVector': 'Generic',
19  'Castor': 'Castor Calorimeter', 'RPCDigisV': 'Resistive Plate Chambers',
20  'GlobalRecHitsV': 'Miscellanea: Sim.', 'Top': 'Top', 'HLTJETMET': 'JetMet',
21  'GlobalDigisV': 'Miscellanea: Sim.', 'L1TEMU': 'Level 1 Trigger',
22  'TrackerRecHitsV': 'Tracking System', 'MuonDTHitsV': 'Muon Objects',
23  'EcalDigisV': 'Ecal Calorimeter', 'EcalHitsV': 'Ecal Calorimeter',
24  'Muons': 'Muon Objects', 'DT': 'Drift Tubes', 'TrackerDigisV': 'Tracking System',
25  'Pixel': 'Tracking System', 'EcalPreshower': 'Ecal Calorimeter',
26  'EgammaV': 'Photons', 'AlCaEcalPi0': 'Alca', 'SusyExo': 'SusyExo',
27  'MuonDTDigisV': 'Muon Objects', 'TauRelVal': 'Tau',
28  'HcalHitsV': 'Hcal Calorimeter', 'RPC': 'Resistive Plate Chambers',
29  'EcalRecHitsV': 'Ecal Calorimeter', 'EgOffline': 'EGamma',
30  'MuonCSCDigisV': 'Muon Objects', 'ParticleFlow': 'Miscellanea',
31  'Info': 'Miscellanea', 'Tracking': 'Tracking',
32  'NoiseRatesV': 'Miscellanea: Sim.', 'Generator': 'Miscellanea: Sim.',
33  'Btag': 'B Tagging', 'Higgs': 'Higgs', 'GlobalHitsV': 'Miscellanea: Sim.',
34  'HcalRecHitsV': 'Hcal Calorimeter', 'TrackerHitsV': 'Tracking System',
35  'CSC': 'Cathode Strip Chambers', 'Muon,HLTMonMuon': 'Muon',
36  'Hcal': 'Hcal Calorimeter', 'TauOffline': 'Tau',
37  'HeavyFlavor': 'HeavyFlavor', 'JetMET': 'Jet', 'Physics': 'Miscellanea',
38  'CaloTowersV': 'Hcal Calorimeter', 'SiStrip': 'Tracking System',
39  'EcalClusterV': 'Ecal Calorimeter', 'HLTEgammaValidation': 'EGamma',
40  'EcalPhiSym': 'Alca', 'L1T': 'Level 1 Trigger', 'MixingV': 'Miscellanea: Sim.',
41  'FourVector_Val': 'Generic', 'EcalEndcap': 'Ecal Calorimeter',
42  'TauOnline': 'Tau', 'Egamma': 'Photons', 'HcalIsoTrack': 'Alca',
43  'EcalBarrel': 'Ecal Calorimeter'
44 }
45 
46 
47 def get_img_path(filename, path):
48  '''Returns image path for https://cmsweb.cern.ch/dqm histogram
49  visualisation service'''
50  run = int(re.findall('_R(\d*)__', filename)[0])
51  parts = [e.rstrip('.root') for e in filename.split('__')]
52  path = path.replace('Run summary/', '')
53  return 'archive/%s/%s/%s/%s/%s' % (run, parts[1], parts[2], parts[3], path)
54 
55 
56 def get_img_url(path, f1, f2=None, w=250, h=250):
57  '''Returns full URL of histogram (or histogram overlay) image for
58  https://cmsweb.cern.ch/dqm visualisation service.'''
59  base = 'https://cmsweb.cern.ch/dqm/relval/plotfairy'
60  if not f2:
61  return '%s/%s?w=%s;h=%s' % (base, get_img_path(f1, path), w, h)
62  return '%s/overlay?obj=%s;obj=%s;w=%s;h=%s' % (base,
63  get_img_path(f1, path), get_img_path(f2, path), w, h)
64 
65 
66 def get_dataset_name(name):
67  '''Returns extracted dataset name from the given ROOT filename.'''
68  if re.search('RelVal', name):
69  run = str(int(re.findall('_R(\d{9})_', name)[0]))
70  ds = re.findall('GR_R_\d*_V\d*C?_(?:RelVal)?_([\w\d]*-v\d+)_', name)[0]
71  else:
72  run, ds = re.findall('R(\d{9})__([\w\d]*)__CMSSW_', name)[0:1]
73  return '_'.join([ds, str(int(run))])
74 
75 
76 def get_release(name):
77  '''Returns extracted release from the given ROOT filename.'''
78  return re.findall('R\d{9}__([\w\d_-]*)__DQM.root', name)[0]
79 
80 
81 def get_stats(c, threshold, dir_ranges):
82  '''Returns ``successes``, ``fails``, ``nulls`` for the given dir_ranges.'''
83  successes, nulls, fails = 0, 0, 0
84  for from_id, till_id in dir_ranges:
85  c.execute('''SELECT count(*) FROM HistogramComparison
86  WHERE p_value >= 0 AND p_value > ? AND
87  id >= ? and id <= ?''', (threshold, from_id, till_id))
88  successes += c.fetchone()[0]
89  c.execute('''SELECT count(*) FROM HistogramComparison WHERE
90  p_value < 0 AND id >= ? AND id <= ?''', (from_id, till_id))
91  nulls += c.fetchone()[0]
92  c.execute('''SELECT count(*) FROM HistogramComparison
93  WHERE p_value >= 0 AND p_value <= ? AND
94  id >= ? AND id <= ?''', (threshold, from_id, till_id))
95  fails += c.fetchone()[0]
96  return successes, nulls, fails
97 
98 
99 def get_percentage(successes, nulls, fails):
100  '''Converts integers ``successes``, ``nulls`` and ``fails`` to percents.'''
101  if successes is None:
102  return None, None, None
103  total = successes + fails + nulls
104  if not total:
105  return None, None, None
106  success = round(100. * successes / total, 2)
107  null = round(100. * nulls / total, 2)
108  fail = round(100. * fails / total, 2)
109  return success, null, fail
110 
111 
112 def get_folders(c, file_id, filename, dir_id, threshold): # TODO: If folder [Egamma|JetMet] analyse their subdirs
113  '''Returns file folder stats for one "summary table" column.'''
114  ds_name = get_dataset_name(filename)
115  c.execute('''SELECT name, from_histogram_id, till_histogram_id FROM
116  Directory WHERE parent_id=?''', (dir_id,))
117  dirs = c.fetchall()
118  file_folders = dict()
119  total_successes, total_nulls, total_fails = 0, 0, 0
120  for name, from_id, till_id in dirs:
121  successes, nulls, fails = get_stats(c, threshold, ((from_id, till_id),))
122  total_successes += successes
123  total_nulls += nulls
124  total_fails += fails
125  if file_folders.has_key(name):
126  file_folders[name].append([file_id, ds_name, successes, nulls, fails])
127  else:
128  file_folders[name] = [file_id, ds_name, successes, nulls, fails]
129  return [('Summary', [file_id, ds_name, total_successes, total_nulls, total_fails])] + file_folders.items()
130 
131 
132 def join_ranges(ranges, elem):
133  '''To do less DB calls, joins [(from_id, till_id), ...] ranges.'''
134  if type(ranges) == tuple:
135  ranges = [ranges]
136  if ranges[-1][-1] + 1 == elem[0]:
137  ranges[-1] = (ranges[-1][0], elem[1])
138  else:
139  ranges.append(elem)
140  return ranges
141 
142 
144  '''Returns all ``ReleaseComparisons`` found on database.'''
145  c.execute('SELECT title, statistical_test FROM ReleaseComparison')
146  return c.fetchall()
147 
148 
149 def db_list_with_releases(path='.'):
150  '''Returns available database list and their releases.'''
151  db_list = [db for db in listdir(path) if db.endswith('.db')]
152  db_list_with_releases = []
153  for db in db_list:
154  conn = sqlite3.connect(join(path, db))
155  releases = get_release_list(conn.cursor())
156  db_list_with_releases.append((db[:-3], releases))
157  conn.close()
158  return db_list_with_releases
159 
160 # ------------------- Template Context generators --------------------
161 
162 def get_release_summary_stats(c, release_title, st_test, threshold=1e-5):
163  '''Returns context for ``release_summary.html`` template.'''
164  ## Summary
165  context = dict()
166  c.execute('''SELECT release1, release2, id FROM ReleaseComparison
167  WHERE title = ? AND statistical_test = ?''', (release_title, st_test))
168  context['release1'], context['release2'], release_comp_id = c.fetchone()
169 
170  # All directory ranges
171  c.execute('''SELECT from_histogram_id, till_histogram_id FROM Directory
172  WHERE id IN (SELECT directory_id FROM RootFileComparison
173  WHERE release_comparison_id = ?)''', (release_comp_id,))
174  dir_ranges = c.fetchall()
175 
176  if len(dir_ranges) > 1:
177  dir_ranges = reduce(join_ranges, dir_ranges)
178 
179  context['successes'], context['nulls'], context['fails'], = get_stats(c, threshold, dir_ranges)
180 
181  context['total'] = context['successes'] + context['fails'] + context['nulls']
182  if context['total']:
183  context['success'], context['null'], context['fail'] = \
184  get_percentage(context['successes'], context['nulls'], context['fails'])
185 
186  ## Data needed for the all the statistics:
187  c.execute('''SELECT id, filename1, directory_id FROM RootFileComparison
188  WHERE release_comparison_id = ?''', (release_comp_id,))
189  files = c.fetchall()
190 
191  ## folders: [(folder_name, [folder: (file_id, filename, success, null, fail)]), ...]
192  folders = dict()
193  for file_id, filename, dir_id in files:
194  # file_folders: [(folder_name, [(file_id, file_name, success, null, fail)]), ...]
195  file_folders = get_folders(c, file_id, filename, dir_id, threshold)
196  for folder_name, file_folder_stats in file_folders:
197  if folders.has_key(folder_name):
198  # Add folder stats
199  folders[folder_name].append(file_folder_stats)
200  # Update folder summary
201  folders[folder_name][0][2] += file_folder_stats[2]
202  folders[folder_name][0][3] += file_folder_stats[3]
203  folders[folder_name][0][4] += file_folder_stats[4]
204  else:
205  folder_summary = [None, 'Summary', file_folder_stats[2],
206  file_folder_stats[3], file_folder_stats[4]]
207  folders[folder_name] = [folder_summary, file_folder_stats]
208 
209  ## Calculate ratios
210  folders = [('Summary', folders.pop('Summary'))] + sorted(folders.items(), key=lambda x: x[0])
211  for folder, file_stats in folders:
212  # Insert N/A if histo is missing
213  if len(file_stats) != len(files)+1:
214  for i, file_ in enumerate(files):
215  if file_[0] != file_stats[i][0]:
216  file_stats = file_stats[:i] + [[None, "N/A", None, None, None]] + file_stats[i:]
217  # Count the ratios
218  for i, stats in enumerate(file_stats):
219  stats[2], stats[3], stats[4] = get_percentage(*stats[2:5])
220  context['folders'] = folders
221 
222 
223  ## Select Summary Barchart, Detailed Barchart
224  for folder in folders:
225  print folder
226  # detailed_ratios: (name, success_ratio)
227  # summary_ratios: (name, success_ratio)
228 
229 
230  ## Summary Barchart
231  # TODO: optimise not to fetch from DB again.
232  c.execute('''SELECT name, from_histogram_id, till_histogram_id FROM Directory
233  WHERE parent_id IN (SELECT directory_id FROM RootFileComparison
234  WHERE release_comparison_id = ?)''', (release_comp_id,))
235  lvl3_dir_ranges = c.fetchall()
236 
237  cum_lvl3_dir_ranges = dict()
238  for name, from_id, till_id in lvl3_dir_ranges:
239  if cum_lvl3_dir_ranges.has_key(name):
240  cum_lvl3_dir_ranges[name].append((from_id, till_id))
241  else:
242  cum_lvl3_dir_ranges[name] = [(from_id, till_id)]
243 
244  # Fetch stats
245  summary_stats = dict()
246  detailed_stats = dict()
247  for name, ranges in cum_lvl3_dir_ranges.iteritems():
248  successes, nulls, fails = get_stats(c, threshold, ranges)
249  if detailed_stats.has_key(name):
250  detailed_stats[name][0] += successes
251  detailed_stats[name][1] += nulls
252  detailed_stats[name][2] += fails
253  else:
254  detailed_stats[name] = [successes, nulls, fails]
255  if renaming.has_key(name):
256  if summary_stats.has_key(renaming[name]):
257  summary_stats[renaming[name]][0] += successes
258  summary_stats[renaming[name]][1] += nulls
259  summary_stats[renaming[name]][2] += fails
260  else:
261  summary_stats[renaming[name]] = [successes, nulls, fails]
262 
263  # Calculate ratio
264  summary_ratios = []
265  for name, stats in summary_stats.iteritems():
266  total = sum(stats)
267  if total:
268  ratio = float(stats[0]) / sum(stats)
269  summary_ratios.append((name, ratio))
270  detailed_ratios = []
271  for name, stats in detailed_stats.iteritems():
272  total = sum(stats)
273  if total:
274  ratio = float(stats[0]) / sum(stats)
275  detailed_ratios.append((name, ratio))
276 
277  context['summary_ratios'] = sorted(summary_ratios, key=lambda x: x[0])
278  context['detailed_ratios'] = sorted(detailed_ratios, key=lambda x: x[0])
279  return context
280 
281 
282 def get_directory_summary_stats(c, url_args, file_id, threshold):
283  '''Returns context for ``directory_summary.html`` template.'''
284  context = dict()
285  c.execute('''SELECT directory_id, filename1, filename2 FROM RootFileComparison
286  WHERE id = ?''', (file_id,))
287  dir_id, f1, f2 = c.fetchone()
288  context['release1'] = get_release(f1)
289  context['release2'] = get_release(f2)
290  if not url_args:
291  dir_name = get_dataset_name(f1)
292  else:
293  #### Select DQMData/Run directory.
294  directory_names = []
295 
296  for dir_name in url_args:
297  c.execute('''SELECT id, name FROM Directory WHERE name = ? AND
298  parent_id = ?''', (dir_name, dir_id))
299  dir_id, name = c.fetchone()
300  directory_names.append(name)
301  context['parent_name'] = '/'.join(directory_names)
302 
303  ## Select stats
304  c.execute('''SELECT from_histogram_id, till_histogram_id FROM
305  Directory WHERE id = ?''', (dir_id,))
306  ranges = c.fetchone()
307  successes, nulls, fails = get_stats(c, threshold, (ranges,))
308  success, null, fail = get_percentage(successes, nulls, fails)
309  context.update({
310  'successes': successes, 'nulls': nulls, 'fails': fails,
311  'success': success, 'null': null, 'fail': fail,
312  'total': successes + nulls + fails, 'dir_name': dir_name
313  })
314  # subdirs: name, total, success, fail, null
315  c.execute('''SELECT name, from_histogram_id, till_histogram_id FROM Directory
316  WHERE parent_id = ?''', (dir_id,))
317  subdirs = c.fetchall()
318  subdir_stats = []
319  for name, from_id, till_id in subdirs:
320  successes, nulls, fails = get_stats(c, threshold, [(from_id, till_id,)])
321  success, null, fail = get_percentage(successes, nulls, fails)
322  subdir_stats.append((name, successes + nulls + fails, successes,
323  nulls, fails, success, null, fail))
324  context['subdirs'] = sorted(subdir_stats, key=lambda x: x[4], reverse=True)
325 
326  # histograms: name, p_value
327  c.execute('''SELECT name, p_value FROM HistogramComparison
328  WHERE directory_id = ?''', (dir_id,))
329  failed_histos = []
330  successful_histos = []
331  null_histos = []
332  for name, p_value in c.fetchall():
333  path = quote('%s/%s' % ('/'.join(url_args), name))
334  url1 = get_img_url(path, f1)
335  url2 = get_img_url(path, f2)
336  overlay = get_img_url(path, f1, f2)
337  if p_value < 0:
338  null_histos.append((name, p_value, url1, url2, overlay))
339  elif p_value <= threshold:
340  failed_histos.append((name, p_value, url1, url2, overlay))
341  else:
342  successful_histos.append((name, p_value, url1, url2, overlay))
343 
344  context['failed_histos'] = sorted(failed_histos, key=lambda x: x[1], reverse=True)
345  context['null_histos'] = null_histos
346  context['successful_histos'] = sorted(successful_histos, key=lambda x: x[1], reverse=True)
347  return context
def get_img_url
Definition: app_utils.py:56
def get_release_summary_stats
Definition: app_utils.py:162
def db_list_with_releases
Definition: app_utils.py:149
def get_release
Definition: app_utils.py:76
def get_img_path
Definition: app_utils.py:47
def get_dataset_name
Definition: app_utils.py:66
def get_percentage
Definition: app_utils.py:99
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def get_directory_summary_stats
Definition: app_utils.py:282
def get_release_list
Definition: app_utils.py:143