CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
create_public_lumi_plots.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 ######################################################################
4 ## File: create_public_lumi_plots.py
5 ######################################################################
6 
7 import sys
8 import os
9 import commands
10 import time
11 import datetime
12 import calendar
13 import copy
14 import math
15 import optparse
16 import ConfigParser
17 import cjson
18 
19 import numpy as np
20 
21 import matplotlib
22 matplotlib.use('Agg')
23 from matplotlib import pyplot as plt
24 # FIX FIX FIX
25 # This fixes a well-know bug with stepfilled logarithmic histograms in
26 # Matplotlib.
27 from RecoLuminosity.LumiDB.mpl_axes_hist_fix import hist
28 if matplotlib.__version__ != '1.0.1':
29  print >> sys.stderr, \
30  "ERROR The %s script contains a hard-coded bug-fix " \
31  "for Matplotlib 1.0.1. The Matplotlib version loaded " \
32  "is %s" % (__file__, matplotlib.__version__)
33  sys.exit(1)
34 matplotlib.axes.Axes.hist = hist
35 # FIX FIX FIX end
36 
37 from RecoLuminosity.LumiDB.public_plots_tools import ColorScheme
38 from RecoLuminosity.LumiDB.public_plots_tools import LatexifyUnits
39 from RecoLuminosity.LumiDB.public_plots_tools import AddLogo
40 from RecoLuminosity.LumiDB.public_plots_tools import InitMatplotlib
41 from RecoLuminosity.LumiDB.public_plots_tools import SavePlot
42 from RecoLuminosity.LumiDB.public_plots_tools import FONT_PROPS_SUPTITLE
43 from RecoLuminosity.LumiDB.public_plots_tools import FONT_PROPS_TITLE
44 from RecoLuminosity.LumiDB.public_plots_tools import FONT_PROPS_AX_TITLE
45 from RecoLuminosity.LumiDB.public_plots_tools import FONT_PROPS_TICK_LABEL
46 
47 try:
48  import debug_hook
49  import pdb
50 except ImportError:
51  pass
52 
53 ######################################################################
54 
55 # Some global constants. Not nice, but okay.
56 DATE_FMT_STR_LUMICALC = "%m/%d/%y %H:%M:%S"
57 DATE_FMT_STR_LUMICALC_DAY = "%m/%d/%y"
58 DATE_FMT_STR_OUT = "%Y-%m-%d %H:%M"
59 DATE_FMT_STR_AXES = "%-d %b"
60 DATE_FMT_STR_CFG = "%Y-%m-%d"
61 NUM_SEC_IN_LS = 2**18 / 11246.
62 
63 KNOWN_ACCEL_MODES = ["PROTPHYS", "IONPHYS", "PAPHYS",
64  "2013_amode_bug_workaround"]
65 LEAD_SCALE_FACTOR = 82. / 208.
66 
67 ######################################################################
68 
70  """Holds info from one line of lumiCalc lumibyls output."""
71 
72  def __init__(self, line, json_file_name=None):
73 
74  # Decode the comma-separated line from lumiCalc.
75  line_split = line.split(",")
76  tmp = line_split[0].split(":")
77  self.run_number = int(tmp[0])
78  self.fill_number = int(tmp[1])
79  tmp = line_split[1].split(":")
80  self.ls = int(tmp[0])
81  tmp = line_split[2]
82  self.timestamp = datetime.datetime.strptime(tmp, DATE_FMT_STR_LUMICALC)
83  # NOTE: Convert from ub^{-1} to b^{-1}.
84  scale_factor = 1.e6
85  self.lum_del = scale_factor * float(line_split[5])
86  self.lum_rec = scale_factor * float(line_split[6])
87 
88  # Adding lum_cert for the data certification information
89  if json_file_name:
90  addcertls = bool(checkCertification(self.run_number, self.ls))
91  if addcertls:
92  self.lum_cert = scale_factor * float(line_split[6])
93  else:
94  self.lum_cert = 0.
95  else:
96  self.lum_cert = 0.
97 
98  # End of __init__().
99 
100  # End of class LumiDataPoint.
101 
102 ######################################################################
103 
105  """A supposedly coherent block of LumiDataPoints.
106 
107  NOTE: No checks on duplicates, sorting, etc.
108 
109  """
110 
111  scale_factors = {
112  "fb^{-1}" : 1.e-15,
113  "pb^{-1}" : 1.e-12,
114  "nb^{-1}" : 1.e-9,
115  "ub^{-1}" : 1.e-6,
116  "mb^{-1}" : 1.e-3,
117  "b^{-1}" : 1.,
118  "Hz/fb" : 1.e-15,
119  "Hz/pb" : 1.e-12,
120  "Hz/nb" : 1.e-9,
121  "Hz/ub" : 1.e-6,
122  "Hz/mb" : 1.e-3,
123  "Hz/b" : 1.
124  }
125 
126  def __init__(self, data_point=None):
127  if not data_point:
128  self.data_points = []
129  else:
130  self.data_points = [data_point]
131  # End of __init__().
132 
133  def __iadd__(self, other):
134  self.data_points.extend(other.data_points)
135  # End of __iadd__().
136  return self
137 
138  def __lt__(self, other):
139  # End of __lt__().
140  return self.time_mid() < other.time_mid()
141 
142  def add(self, new_point):
143  self.data_points.append(new_point)
144  # End of add().
145 
146  def copy(self):
147  # End of copy().
148  return copy.deepcopy(self)
149 
150  def is_empty(self):
151  # End of is_empty().
152  return not len(self.data_points)
153 
154  def lum_del_tot(self, units="b^{-1}"):
155  res = sum([i.lum_del for i in self.data_points])
156  res *= LumiDataBlock.scale_factors[units]
157  # End of lum_del_tot().
158  return res
159 
160  def lum_rec_tot(self, units="b^{-1}"):
161  res = sum([i.lum_rec for i in self.data_points])
162  res *= LumiDataBlock.scale_factors[units]
163  # End of lum_rec_tot().
164  return res
165 
166  def lum_cert_tot(self, units="b^{-1}"):
167  res = sum([i.lum_cert for i in self.data_points])
168  res *= LumiDataBlock.scale_factors[units]
169  # End of lum_cert_tot().
170  return res
171 
172  def max_inst_lum(self, units="Hz/b"):
173  res = 0.
174  if len(self.data_points):
175  res = max([i.lum_del for i in self.data_points])
176  res /= NUM_SEC_IN_LS
177  res *= LumiDataBlock.scale_factors[units]
178  # End of max_inst_lum().
179  return res
180 
181  def straighten(self):
182  self.data_points.sort()
183  # End of straighten().
184 
185  def time_begin(self):
186  res = min([i.timestamp for i in self.data_points])
187  # End of time_begin().
188  return res
189 
190  def time_end(self):
191  res = max([i.timestamp for i in self.data_points])
192  # End of time_end().
193  return res
194 
195  def time_mid(self):
196  delta = self.time_end() - self.time_begin()
197  delta_sec = delta.days * 24 * 60 * 60 + delta.seconds
198  res = self.time_begin() + datetime.timedelta(seconds=.5*delta_sec)
199  # End of time_mid().
200  return res
201 
202  # End of class LumiDataBlock.
203 
204 ######################################################################
205 
207  """A collection of LumiDataBlocks."""
208 
209  def __init__(self, data_block=None):
210  if not data_block:
211  self.data_blocks = []
212  else:
213  self.data_blocks = [data_block]
214  # End of __init__().
215 
216  def __len__(self):
217  # End of __len__().
218  return len(self.data_blocks)
219 
220  def add(self, new_block):
221  self.data_blocks.append(new_block)
222  # End of add().
223 
224  def sort(self):
225  self.data_blocks.sort()
226  # End of sort().
227 
228  def time_begin(self):
229  res = datetime.datetime.max
230  if len(self.data_blocks):
231  res = min([i.time_begin() for i in self.data_blocks])
232  # End of time_begin().
233  return res
234 
235  def time_end(self):
236  res = datetime.datetime.min
237  if len(self.data_blocks):
238  res = max([i.time_end() for i in self.data_blocks])
239  # End of time_end().
240  return res
241 
242  def times(self):
243  res = [i.time_mid() for i in self.data_blocks]
244  # End of times().
245  return res
246 
247  def lum_del(self, units="b^{-1}"):
248  res = [i.lum_del_tot(units) for i in self.data_blocks]
249  # End of lum_del().
250  return res
251 
252  def lum_rec(self, units="b^{-1}"):
253  res = [i.lum_rec_tot(units) for i in self.data_blocks]
254  # End of lum_rec().
255  return res
256 
257  def lum_cert(self, units="b^{-1}"):
258  res = [i.lum_cert_tot(units) for i in self.data_blocks]
259  # End of lum_cert().
260  return res
261 
262  def lum_del_tot(self, units="b^{-1}"):
263  # End of lum_del().
264  return sum(self.lum_del(units))
265 
266  def lum_rec_tot(self, units="b^{-1}"):
267  # End of lum_rec().
268  return sum(self.lum_rec(units))
269 
270  def lum_cert_tot(self, units="b^{-1}"):
271  # End of lum_cert().
272  return sum(self.lum_cert(units))
273 
274  def lum_inst_max(self, units="Hz/b"):
275  res = [i.max_inst_lum(units) for i in self.data_blocks]
276  # End of lum_inst_max().
277  return res
278 
279  # End of class LumiDataBlockCollection.
280 
281 ######################################################################
282 
283 def CacheFilePath(cache_file_dir, day=None):
284  cache_file_path = os.path.abspath(cache_file_dir)
285  if day:
286  cache_file_name = "lumicalc_cache_%s.csv" % day.isoformat()
287  cache_file_path = os.path.join(cache_file_path, cache_file_name)
288  return cache_file_path
289 
290 ######################################################################
291 
292 def AtMidnight(datetime_in):
293  res = datetime.datetime.combine(datetime_in.date(), datetime.time())
294  # End of AtMidnight().
295  return res
296 
297 ######################################################################
298 
299 def AtMidWeek(datetime_in):
300  # NOTE: The middle of the week is on Thursday according to our
301  # definition
302  tmp = datetime_in.date()
303  date_tmp = tmp - \
304  datetime.timedelta(days=tmp.weekday()) + \
305  datetime.timedelta(days=3)
306  res = datetime.datetime.combine(date_tmp, datetime.time())
307  # End of AtMidWeek().
308  return res
309 
310 ######################################################################
311 
312 def GetUnits(year, accel_mode, mode):
313 
314  units_spec = {
315  "PROTPHYS" : {
316  2010 : {
317  "cum_day" : "pb^{-1}",
318  "cum_week" : "pb^{-1}",
319  "cum_year" : "pb^{-1}",
320  "max_inst" : "Hz/ub",
321  },
322  2011 : {
323  "cum_day" : "pb^{-1}",
324  "cum_week" : "pb^{-1}",
325  "cum_year" : "fb^{-1}",
326  "max_inst" : "Hz/nb",
327  },
328  2012 : {
329  "cum_day" : "pb^{-1}",
330  "cum_week" : "fb^{-1}",
331  "cum_year" : "fb^{-1}",
332  "max_inst" : "Hz/nb",
333  },
334  2013 : {
335  "cum_day" : "pb^{-1}",
336  "cum_week" : "pb^{-1}",
337  "cum_year" : "pb^{-1}",
338  "max_inst" : "Hz/ub",
339  }
340  },
341  "IONPHYS" : {
342  2011 : {
343  "cum_day" : "ub^{-1}",
344  "cum_week" : "ub^{-1}",
345  "cum_year" : "ub^{-1}",
346  "max_inst" : "Hz/mb",
347  }
348  },
349  "PAPHYS" : {
350  2013 : {
351  "cum_day" : "nb^{-1}",
352  "cum_week" : "nb^{-1}",
353  "cum_year" : "nb^{-1}",
354  "max_inst" : "Hz/mb",
355  }
356  }
357  }
358 
359  units = None
360 
361  try:
362  units = units_spec[accel_mode][year][mode]
363  except KeyError:
364  if mode == "cum_day":
365  units = "pb^{-1}"
366  elif mode == "cum_week":
367  units = "pb^{-1}"
368  elif mode == "cum_year":
369  units = "fb^{-1}"
370  elif mode == "max_inst":
371  units = "Hz/ub"
372 
373  # DEBUG DEBUG DEBUG
374  assert not units is None
375  # DEBUG DEBUG DEBUG end
376 
377  # End of GetUnits().
378  return units
379 
380 ######################################################################
381 
383  # DEBUG DEBUG DEBUG
384  assert amodetag in ["IONPHYS", "PAPHYS"]
385  # DEBUG DEBUG DEBUG end
386 
387  res = LEAD_SCALE_FACTOR
388  if amodetag == "PAPHYS":
389  res = math.sqrt(res)
390 
391  # End of GetEnergyPerNucleonScaleFactor().
392  return res
393 
394 ######################################################################
395 
396 def NumDaysInYear(year):
397  """Returns the number of days in the given year."""
398 
399  date_lo = datetime.date(year, 1, 1)
400  date_hi = datetime.date(year + 1, 1, 1)
401  num_days = (date_hi - date_lo).days
402 
403  # End of NumDaysInYear().
404  return num_days
405 
406 ######################################################################
407 
408 def GetXLocator(ax):
409  """Pick a DateLocator based on the range of the x-axis."""
410  (x_lo, x_hi) = ax.get_xlim()
411  num_days = x_hi - x_lo
412  min_num_ticks = min(num_days, 5)
413  locator = matplotlib.dates.AutoDateLocator(minticks=min_num_ticks,
414  maxticks=None)
415  # End of GetLocator().
416  return locator
417 
418 ######################################################################
419 
420 def TweakPlot(fig, ax, (time_begin, time_end),
421  add_extra_head_room=False):
422 
423  # Fiddle with axes ranges etc.
424  ax.relim()
425  ax.autoscale_view(False, True, True)
426  for label in ax.get_xticklabels():
427  label.set_ha("right")
428  label.set_rotation(30.)
429 
430  # Bit of magic here: increase vertical scale by one tick to make
431  # room for the legend.
432  if add_extra_head_room:
433  y_ticks = ax.get_yticks()
434  (y_min, y_max) = ax.get_ylim()
435  is_log = (ax.get_yscale() == "log")
436  y_max_new = y_max
437  if is_log:
438  tmp = y_ticks[-1] / y_ticks[-2]
439  y_max_new = y_max * math.pow(tmp, add_extra_head_room)
440  else:
441  tmp = y_ticks[-1] - y_ticks[-2]
442  y_max_new = y_max + add_extra_head_room * tmp
443  ax.set_ylim(y_min, y_max_new)
444 
445  # Add a second vertical axis on the right-hand side.
446  ax_sec = ax.twinx()
447  ax_sec.set_ylim(ax.get_ylim())
448  ax_sec.set_yscale(ax.get_yscale())
449 
450  for ax_tmp in fig.axes:
451  for sub_ax in [ax_tmp.xaxis, ax_tmp.yaxis]:
452  for label in sub_ax.get_ticklabels():
453  label.set_font_properties(FONT_PROPS_TICK_LABEL)
454 
455  ax.set_xlim(time_begin, time_end)
456 
457  locator = GetXLocator(ax)
458  ax.xaxis.set_major_locator(locator)
459  formatter = matplotlib.dates.DateFormatter(DATE_FMT_STR_AXES)
460  ax.xaxis.set_major_formatter(formatter)
461 
462  fig.subplots_adjust(top=.85, bottom=.14, left=.13, right=.91)
463  # End of TweakPlot().
464 
465 ######################################################################
466 
467 def checkCertification(run_number, ls):
468  """Check if this run and LS are certified as good and return a boolean parameter."""
469  try:
470  ls_ranges = certification_data[run_number]
471  for ranges in ls_ranges:
472  if (ls >= ranges[0]) and (ls <= ranges[1]):
473  return True
474  except KeyError:
475  return False
476 
477  return False
478 
479 ######################################################################
480 
481 def loadCertificationJSON(json_file_name):
482 
483  full_file = open(json_file_name, "r")
484  full_file_content = ["".join(l) for l in full_file.readlines()]
485  full_object = cjson.decode(full_file_content[0])
486 
487  # Now turn this into a dictionary for easier handling.
488  tmp = full_object.keys()
489  tmp = [int(i) for i in tmp]
490  run_list = sorted(tmp)
491  certification_data = {}
492  for run in run_list:
493  ls_ranges = full_object.get(str(run), None)
494  certification_data[run] = ls_ranges
495 
496  return certification_data
497 
498 ######################################################################
499 
500 if __name__ == "__main__":
501 
502  desc_str = "This script creates the official CMS luminosity plots " \
503  "based on the output from the lumiCalc family of scripts."
504  arg_parser = optparse.OptionParser(description=desc_str)
505  arg_parser.add_option("--ignore-cache", action="store_true",
506  help="Ignore all cached lumiCalc results " \
507  "and re-query lumiCalc. " \
508  "(Rebuilds the cache as well.)")
509  (options, args) = arg_parser.parse_args()
510  if len(args) != 1:
511  print >> sys.stderr, \
512  "ERROR Need exactly one argument: a config file name"
513  sys.exit(1)
514  config_file_name = args[0]
515  ignore_cache = options.ignore_cache
516 
517  cfg_defaults = {
518  "lumicalc_flags" : "",
519  "date_end" : None,
520  "color_schemes" : "Joe, Greg",
521  "beam_energy" : None,
522  "beam_fluctuation" : None,
523  "verbose" : False,
524  "oracle_connection" : None,
525  "json_file" : None
526  }
527  cfg_parser = ConfigParser.SafeConfigParser(cfg_defaults)
528  if not os.path.exists(config_file_name):
529  print >> sys.stderr, \
530  "ERROR Config file '%s' does not exist" % config_file_name
531  sys.exit(1)
532  cfg_parser.read(config_file_name)
533 
534  # Which color scheme to use for drawing the plots.
535  color_scheme_names_tmp = cfg_parser.get("general", "color_schemes")
536  color_scheme_names = [i.strip() for i in color_scheme_names_tmp.split(",")]
537  # Where to store cache files containing the lumiCalc output.
538  cache_file_dir = cfg_parser.get("general", "cache_dir")
539  # Flag to turn on verbose output.
540  verbose = cfg_parser.getboolean("general", "verbose")
541 
542  # Some details on how to invoke lumiCalc.
543  lumicalc_script = cfg_parser.get("general", "lumicalc_script")
544  lumicalc_flags_from_cfg = cfg_parser.get("general", "lumicalc_flags")
545  accel_mode = cfg_parser.get("general", "accel_mode")
546  # Check if we know about this accelerator mode.
547  if not accel_mode in KNOWN_ACCEL_MODES:
548  print >> sys.stderr, \
549  "ERROR Unknown accelerator mode '%s'" % \
550  accel_mode
551 
552  # WORKAROUND WORKAROUND WORKAROUND
553  amodetag_bug_workaround = False
554  if accel_mode == "2013_amode_bug_workaround":
555  amodetag_bug_workaround = True
556  accel_mode = "PAPHYS"
557  # WORKAROUND WORKAROUND WORKAROUND end
558 
559  beam_energy_tmp = cfg_parser.get("general", "beam_energy")
560  # If no beam energy specified, use the default(s) for this
561  # accelerator mode.
562  beam_energy = None
563  beam_energy_from_cfg = None
564  if not beam_energy_tmp:
565  print "No beam energy specified --> using defaults for '%s'" % \
566  accel_mode
567  beam_energy_from_cfg = False
568  else:
569  beam_energy_from_cfg = True
570  beam_energy = float(beam_energy_tmp)
571 
572  beam_fluctuation_tmp = cfg_parser.get("general", "beam_fluctuation")
573  # If no beam energy fluctuation specified, use the default for
574  # this accelerator mode.
575  beam_fluctuation = None
576  beam_fluctuation_from_cfg = None
577  if not beam_fluctuation_tmp:
578  print "No beam energy fluctuation specified --> using the defaults to '%s'" % \
579  accel_mode
580  beam_fluctuation_from_cfg = False
581  else:
582  beam_fluctuation_from_cfg = True
583  beam_fluctuation = float(beam_fluctuation_tmp)
584 
585  # Overall begin and end dates of all data to include.
586  tmp = cfg_parser.get("general", "date_begin")
587  date_begin = datetime.datetime.strptime(tmp, DATE_FMT_STR_CFG).date()
588  tmp = cfg_parser.get("general", "date_end")
589  date_end = None
590  if tmp:
591  date_end = datetime.datetime.strptime(tmp, DATE_FMT_STR_CFG).date()
592  # If no end date is given, use today.
593  today = datetime.datetime.utcnow().date()
594  if not date_end:
595  print "No end date given --> using today"
596  date_end = today
597  # If end date lies in the future, truncate at today.
598  if date_end > today:
599  print "End date lies in the future --> using today instead"
600  date_end = today
601  # If end date is before start date, give up.
602  if date_end < date_begin:
603  print >> sys.stderr, \
604  "ERROR End date before begin date (%s < %s)" % \
605  (date_end.isoformat(), date_begin.isoformat())
606  sys.exit(1)
607 
608  # If an Oracle connection string is specified, use direct Oracle
609  # access. Otherwise access passes through the Frontier
610  # cache. (Fine, but much slower to receive the data.)
611  oracle_connection_string = cfg_parser.get("general", "oracle_connection")
612  use_oracle = (len(oracle_connection_string) != 0)
613 
614  # If a JSON file is specified, use the JSON file to add in the
615  # plot data certified as good for physics.
616  json_file_name = cfg_parser.get("general", "json_file")
617  if len(json_file_name) < 1:
618  json_file_name = None
619  if json_file_name:
620  if not os.path.exists(json_file_name):
621  print >> sys.stderr, \
622  "ERROR Requested JSON file '%s' is not available" % json_file_name
623  sys.exit(1)
624  print "Using JSON file '%s' for certified data" % json_file_name
625  else:
626  if verbose:
627  print "No JSON file specified, filling only standard lumi plot."
628 
629  ##########
630 
631  certification_data = None
632  if json_file_name:
633  certification_data = loadCertificationJSON(json_file_name)
634 
635  ##########
636 
637  # Map accelerator modes (as fed to lumiCalc) to particle type
638  # strings to be used in plot titles etc.
639  particle_type_strings = {
640  "PROTPHYS" : "pp",
641  "IONPHYS" : "PbPb",
642  "PAPHYS" : "pPb"
643  }
644  particle_type_str = particle_type_strings[accel_mode]
645 
646  beam_energy_defaults = {
647  "PROTPHYS" : {2010 : 3500.,
648  2011 : 3500.,
649  2012 : 4000.,
650  2013 : 1380.1},
651  "IONPHYS" : {2010 : 3500.,
652  2011 : 3500.},
653  "PAPHYS" : {2013 : 4000.}
654  }
655  beam_fluctuation_defaults = {
656  "PROTPHYS" : {2010 : .15,
657  2011 : .15,
658  2012 : .15,
659  2013 : .15},
660  "IONPHYS" : {2010 : .15,
661  2011 : .15},
662  "PAPHYS" : {2013 : .15}
663  }
664 
665  ##########
666 
667  # Environment parameter for access to the Oracle DB.
668  if use_oracle:
669  os.putenv("TNS_ADMIN", "/afs/cern.ch/cms/lumi/DB")
670 
671  ##########
672 
673  # Tell the user what's going to happen.
674  print "Using configuration from file '%s'" % config_file_name
675  if ignore_cache:
676  print "Ignoring all cached lumiCalc results (and rebuilding the cache)"
677  else:
678  print "Using cached lumiCalc results from %s" % \
679  CacheFilePath(cache_file_dir)
680  print "Using color schemes '%s'" % ", ".join(color_scheme_names)
681  print "Using lumiCalc script '%s'" % lumicalc_script
682  print "Using additional lumiCalc flags from configuration: '%s'" % \
683  lumicalc_flags_from_cfg
684  print "Selecting data for accelerator mode '%s'" % accel_mode
685  if beam_energy_from_cfg:
686  print "Selecting data for beam energy %.0f GeV" % beam_energy
687  else:
688  print "Selecting data for default beam energy for '%s' from:" % accel_mode
689  for (key, val) in beam_energy_defaults[accel_mode].iteritems():
690  print " %d : %.1f GeV" % (key, val)
691  if beam_fluctuation_from_cfg:
692  print "Using beam energy fluctuation of +/- %.0f%%" % \
693  (100. * beam_fluctuation)
694  else:
695  print "Using default beam energy fluctuation for '%s' from:" % accel_mode
696  for (key, val) in beam_fluctuation_defaults[accel_mode].iteritems():
697  print " %d : +/- %.0f%%" % (key, 100. * val)
698  if use_oracle:
699  print "Using direct access to the Oracle luminosity database"
700  else:
701  print "Using access to the luminosity database through the Frontier cache"
702 
703  ##########
704 
705  # See if the cache file dir exists, otherwise try to create it.
706  path_name = CacheFilePath(cache_file_dir)
707  if not os.path.exists(path_name):
708  if verbose:
709  print "Cache file path does not exist: creating it"
710  try:
711  os.makedirs(path_name)
712  except Exception, err:
713  print >> sys.stderr, \
714  "ERROR Could not create cache dir: %s" % path_name
715  sys.exit(1)
716 
717  ##########
718 
720 
721  ##########
722 
723  week_begin = date_begin.isocalendar()[1]
724  week_end = date_end.isocalendar()[1]
725  year_begin = date_begin.isocalendar()[0]
726  year_end = date_end.isocalendar()[0]
727  # DEBUG DEBUG DEBUG
728  assert year_end >= year_begin
729  # DEBUG DEBUG DEBUG end
730  print "Building a list of days to include in the plots"
731  print " first day to consider: %s (%d, week %d)" % \
732  (date_begin.isoformat(), year_begin, week_begin)
733  print " last day to consider: %s (%d, week %d)" % \
734  (date_end.isoformat(), year_end, week_end)
735  num_days = (date_end - date_begin).days + 1
736  days = [date_begin + datetime.timedelta(days=i) for i in xrange(num_days)]
737  years = range(year_begin, year_end + 1)
738  weeks = []
739  day_cur = date_begin
740  while day_cur <= date_end:
741  year = day_cur.isocalendar()[0]
742  week = day_cur.isocalendar()[1]
743  weeks.append((year, week))
744  day_cur += datetime.timedelta(days=7)
745  if num_days <= 7:
746  year = date_end.isocalendar()[0]
747  week = date_end.isocalendar()[1]
748  weeks.append((year, week))
749  weeks = list(set(weeks))
750  weeks.sort()
751 
752  # Figure out the last day we want to read back from the cache.
753  # NOTE: The above checking ensures that date_end is <= today, so
754  # the below only assumes that we're never more than two days
755  # behind on our luminosity numbers.
756  last_day_from_cache = min(today - datetime.timedelta(days=2), date_end)
757  if verbose:
758  print "Last day for which the cache will be used: %s" % \
759  last_day_from_cache.isoformat()
760 
761  # First run lumiCalc. Once for each day to be included in the
762  # plots.
763  print "Running lumiCalc for all requested days"
764  for day in days:
765  print " %s" % day.isoformat()
766  use_cache = (not ignore_cache) and (day <= last_day_from_cache)
767  cache_file_path = CacheFilePath(cache_file_dir, day)
768  cache_file_tmp = cache_file_path.replace(".csv", "_tmp.csv")
769  if (not os.path.exists(cache_file_path)) or (not use_cache):
770  date_begin_str = day.strftime(DATE_FMT_STR_LUMICALC)
771  date_begin_day_str = day.strftime(DATE_FMT_STR_LUMICALC_DAY)
772  date_end_str = (day + datetime.timedelta(days=1)).strftime(DATE_FMT_STR_LUMICALC)
773  date_previous_str = (day - datetime.timedelta(days=1)).strftime(DATE_FMT_STR_LUMICALC)
774  if not beam_energy_from_cfg:
775  year = day.isocalendar()[0]
776  beam_energy = beam_energy_defaults[accel_mode][year]
777  if not beam_fluctuation_from_cfg:
778  year = day.isocalendar()[0]
779  beam_fluctuation = beam_fluctuation_defaults[accel_mode][year]
780 
781  # WORKAROUND WORKAROUND WORKAROUND
782  # Trying to work around the issue with the unfilled
783  # accelerator mode in the RunInfo database.
784  if amodetag_bug_workaround:
785  # Don't use the amodetag in this case. Scary, but
786  # works for the moment.
787  lumicalc_flags = "%s --without-checkforupdate " \
788  "--beamenergy %.1f " \
789  "--beamfluctuation %.2f " \
790  "lumibyls" % \
791  (lumicalc_flags_from_cfg,
792  beam_energy, beam_fluctuation)
793  else:
794  # This is the way things should be.
795  lumicalc_flags = "%s --without-checkforupdate " \
796  "--beamenergy %.1f " \
797  "--beamfluctuation %.2f " \
798  "--amodetag %s " \
799  "lumibyls" % \
800  (lumicalc_flags_from_cfg,
801  beam_energy, beam_fluctuation,
802  accel_mode)
803  # WORKAROUND WORKAROUND WORKAROUND end
804 
805  lumicalc_flags = lumicalc_flags.strip()
806  lumicalc_cmd = "%s %s" % (lumicalc_script, lumicalc_flags)
807  if use_oracle:
808  lumicalc_cmd = "%s %s" % (lumicalc_cmd, oracle_connection_string)
809  cmd = "%s --begin '%s' --end '%s' -o %s" % \
810  (lumicalc_cmd, date_previous_str, date_end_str, cache_file_tmp)
811  if verbose:
812  print " running lumicalc as '%s'" % cmd
813  (status, output) = commands.getstatusoutput(cmd)
814  # BUG BUG BUG
815  # Trying to track down the bad-cache problem.
816  output_0 = copy.deepcopy(output)
817  # BUG BUG BUG end
818  if status != 0:
819  # This means 'no qualified data found'.
820  if ((status >> 8) == 13 or (status >> 8) == 14):
821  # If no data is found it never writes the output
822  # file. So for days without data we would keep
823  # querying the database in vain every time the
824  # script runs. To avoid this we just write a dummy
825  # cache file for such days.
826  if verbose:
827  print "No lumi data for %s, " \
828  "writing dummy cache file to avoid re-querying the DB" % \
829  day.isoformat()
830  dummy_file = open(cache_file_tmp, "w")
831  dummy_file.write("Run:Fill,LS,UTCTime,Beam Status,E(GeV),Delivered(/ub),Recorded(/ub),avgPU\r\n")
832  dummy_file.close()
833  else:
834  print >> sys.stderr, \
835  "ERROR Problem running lumiCalc: %s" % output
836  sys.exit(1)
837 
838  # BUG BUG BUG
839  # This works around a bug in lumiCalc where sometimes not
840  # all data for a given day is returned. The work-around is
841  # to ask for data from two days and then filter out the
842  # unwanted day.
843  lines_to_be_kept = []
844  lines_ori = open(cache_file_tmp).readlines()
845  for line in lines_ori:
846  if (date_begin_day_str in line) or ("Delivered" in line):
847  lines_to_be_kept.append(line)
848  newfile = open(cache_file_path, "w")
849  newfile.writelines(lines_to_be_kept)
850  newfile.close()
851  # BUG BUG BUG end
852 
853  if verbose:
854  print " CSV file for the day written to %s" % \
855  cache_file_path
856  else:
857  if verbose:
858  print " cache file for %s exists" % day.isoformat()
859 
860  # Now read back all lumiCalc results.
861  print "Reading back lumiCalc results"
862  lumi_data_by_day = {}
863  for day in days:
864  print " %s" % day.isoformat()
865  cache_file_path = CacheFilePath(cache_file_dir, day)
866  lumi_data_day = LumiDataBlock()
867  try:
868  in_file = open(cache_file_path)
869  lines = in_file.readlines()
870  if not len(lines):
871  if verbose:
872  print " skipping empty file for %s" % day.isoformat()
873  else:
874  # DEBUG DEBUG DEBUG
875  assert lines[0] == "Run:Fill,LS,UTCTime,Beam Status,E(GeV),Delivered(/ub),Recorded(/ub),avgPU\r\n"
876  # DEBUG DEBUG DEBUG end
877  for line in lines[1:]:
878  lumi_data_day.add(LumiDataPoint(line, json_file_name))
879  in_file.close()
880  except IOError, err:
881  print >> sys.stderr, \
882  "ERROR Could not read lumiCalc results from file '%s': %s" % \
883  (cache_file_path, str(err))
884  sys.exit(1)
885  # Only store data if there actually is something to store.
886  if not lumi_data_day.is_empty():
887  lumi_data_by_day[day] = lumi_data_day
888 
889  ##########
890 
891  # Bunch lumiCalc data together into weeks.
892  print "Combining lumiCalc data week-by-week"
893  lumi_data_by_week = {}
894  for (day, lumi) in lumi_data_by_day.iteritems():
895  year = day.isocalendar()[0]
896  week = day.isocalendar()[1]
897  try:
898  lumi_data_by_week[year][week] += lumi
899  except KeyError:
900  try:
901  lumi_data_by_week[year][week] = lumi.copy()
902  except KeyError:
903  lumi_data_by_week[year] = {week: lumi.copy()}
904 
905  lumi_data_by_week_per_year = {}
906  for (year, tmp_lumi) in lumi_data_by_week.iteritems():
907  for (week, lumi) in tmp_lumi.iteritems():
908  try:
909  lumi_data_by_week_per_year[year].add(lumi)
910  except KeyError:
911  lumi_data_by_week_per_year[year] = LumiDataBlockCollection(lumi)
912 
913  # Bunch lumiCalc data together into years.
914  print "Combining lumiCalc data year-by-year"
915  lumi_data_by_year = {}
916  for (day, lumi) in lumi_data_by_day.iteritems():
917  year = day.isocalendar()[0]
918  try:
919  lumi_data_by_year[year] += lumi
920  except KeyError:
921  lumi_data_by_year[year] = lumi.copy()
922 
923  lumi_data_by_day_per_year = {}
924  for (day, lumi) in lumi_data_by_day.iteritems():
925  year = day.isocalendar()[0]
926  try:
927  lumi_data_by_day_per_year[year].add(lumi)
928  except KeyError:
929  lumi_data_by_day_per_year[year] = LumiDataBlockCollection(lumi)
930 
931  ##########
932 
933  # Now dump a lot of info to the user.
934  sep_line = 50 * "-"
935  print sep_line
936  units = GetUnits(years[-1], accel_mode, "cum_day")
937  print "Delivered lumi day-by-day (%s):" % units
938  print sep_line
939  for day in days:
940  tmp_str = " - (no data, presumably no lumi either)"
941  try:
942  tmp = lumi_data_by_day[day].lum_del_tot(units)
943  helper_str = ""
944  if (tmp < .1) and (tmp > 0.):
945  helper_str = " (non-zero but very small)"
946  tmp_str = "%6.1f%s" % (tmp, helper_str)
947  except KeyError:
948  pass
949  print " %s: %s" % (day.isoformat(), tmp_str)
950  print sep_line
951  units = GetUnits(years[-1], accel_mode, "cum_week")
952  print "Delivered lumi week-by-week (%s):" % units
953  print sep_line
954  for (year, week) in weeks:
955  tmp_str = " - (no data, presumably no lumi either)"
956  try:
957  tmp = lumi_data_by_week[year][week].lum_del_tot(units)
958  helper_str = ""
959  if (tmp < .1) and (tmp > 0.):
960  helper_str = " (non-zero but very small)"
961  tmp_str = "%6.1f%s" % (tmp, helper_str)
962  except KeyError:
963  pass
964  print " %d-%2d: %s" % (year, week, tmp_str)
965  print sep_line
966  units = GetUnits(years[-1], accel_mode, "cum_year")
967  print "Delivered lumi year-by-year (%s):" % units
968  print sep_line
969  for year in years:
970  tmp_str = " - (no data, presumably no lumi either)"
971  try:
972  tmp = lumi_data_by_year[year].lum_del_tot(units)
973  helper_str = ""
974  if (tmp < .01) and (tmp > 0.):
975  helper_str = " (non-zero but very small)"
976  tmp_str = "%5.2f%s" % (tmp, helper_str)
977  except KeyError:
978  pass
979  print " %4d: %s" % \
980  (year, tmp_str)
981  print sep_line
982 
983  ##########
984 
985  if not len(lumi_data_by_day_per_year):
986  print >> sys.stderr, "ERROR No lumi found?"
987  sys.exit(1)
988 
989  ##########
990 
991  # And this is where the plotting starts.
992  print "Drawing things..."
993  ColorScheme.InitColors()
994 
995  #------------------------------
996  # Create the per-day delivered-lumi plots.
997  #------------------------------
998 
999  for year in years:
1000 
1001  print " daily lumi plots for %d" % year
1002 
1003  if not beam_energy_from_cfg:
1004  beam_energy = beam_energy_defaults[accel_mode][year]
1005  cms_energy = 2. * beam_energy
1006  cms_energy_str = "???"
1007  if accel_mode == "PROTPHYS":
1008  width = 0
1009  if year == 2013:
1010  width = 2
1011  cms_energy_str = "%.*f TeV" % (width, 1.e-3 * cms_energy)
1012  elif accel_mode in ["IONPHYS", "PAPHYS"]:
1013  cms_energy_str = "%.2f TeV/nucleon" % \
1014  (1.e-3 * GetEnergyPerNucleonScaleFactor(accel_mode) * cms_energy)
1015 
1016  lumi_data = lumi_data_by_day_per_year[year]
1017  lumi_data.sort()
1018 
1019  # NOTE: Tweak the time range a bit to force the bins to be
1020  # drawn from midday to midday.
1021  day_lo = AtMidnight(lumi_data.time_begin()) - \
1022  datetime.timedelta(seconds=12*60*60)
1023  day_hi = AtMidnight(lumi_data.time_end()) + \
1024  datetime.timedelta(seconds=12*60*60)
1025 
1026  #----------
1027 
1028  # Build the histograms.
1029  bin_edges = np.linspace(matplotlib.dates.date2num(day_lo),
1030  matplotlib.dates.date2num(day_hi),
1031  (day_hi - day_lo).days + 1)
1032  times_tmp = [AtMidnight(i) for i in lumi_data.times()]
1033  times = [matplotlib.dates.date2num(i) for i in times_tmp]
1034  # Delivered and recorded luminosity integrated per day.
1035  units = GetUnits(year, accel_mode, "cum_day")
1036  weights_del = lumi_data.lum_del(units)
1037  weights_rec = lumi_data.lum_rec(units)
1038  # Cumulative versions of the above.
1039  units = GetUnits(year, accel_mode, "cum_year")
1040  weights_del_for_cum = lumi_data.lum_del(units)
1041  weights_rec_for_cum = lumi_data.lum_rec(units)
1042  weights_cert_for_cum = lumi_data.lum_cert(units)
1043  # Maximum instantaneous delivered luminosity per day.
1044  units = GetUnits(year, accel_mode, "max_inst")
1045  weights_del_inst = lumi_data.lum_inst_max(units)
1046 
1047  # Figure out the time window of the data included for the plot
1048  # subtitles.
1049  time_begin = datetime.datetime.combine(lumi_data.time_begin(),
1050  datetime.time()) - \
1051  datetime.timedelta(days=.5)
1052  time_end = datetime.datetime.combine(lumi_data.time_end(),
1053  datetime.time()) + \
1054  datetime.timedelta(days=.5)
1055  str_begin = None
1056  str_end = None
1057  if sum(weights_del) > 0.:
1058  str_begin = lumi_data.time_begin().strftime(DATE_FMT_STR_OUT)
1059  str_end = lumi_data.time_end().strftime(DATE_FMT_STR_OUT)
1060 
1061  #----------
1062 
1063  # Loop over all color schemes.
1064  for color_scheme_name in color_scheme_names:
1065 
1066  color_scheme = ColorScheme(color_scheme_name)
1067  color_fill_del = color_scheme.color_fill_del
1068  color_fill_rec = color_scheme.color_fill_rec
1069  color_fill_cert = color_scheme.color_fill_cert
1070  color_fill_peak = color_scheme.color_fill_peak
1071  color_line_del = color_scheme.color_line_del
1072  color_line_rec = color_scheme.color_line_rec
1073  color_line_cert = color_scheme.color_line_cert
1074  color_line_peak = color_scheme.color_line_peak
1075  logo_name = color_scheme.logo_name
1076  file_suffix = color_scheme.file_suffix
1077 
1078  fig = plt.figure()
1079 
1080  #----------
1081 
1082  for type in ["lin", "log"]:
1083  is_log = (type == "log")
1084  log_setting = False
1085  if is_log:
1086  min_val = min(weights_del_inst)
1087  exp = math.floor(math.log10(min_val))
1088  log_setting = math.pow(10., exp)
1089 
1090  fig.clear()
1091  ax = fig.add_subplot(111)
1092 
1093  units = GetUnits(year, accel_mode, "max_inst")
1094 
1095  # Figure out the maximum instantaneous luminosity.
1096  max_inst = max(weights_del_inst)
1097 
1098  if sum(weights_del) > 0.:
1099 
1100  ax.hist(times, bin_edges, weights=weights_del_inst,
1101  histtype="stepfilled",
1102  log=log_setting,
1103  facecolor=color_fill_peak, edgecolor=color_line_peak,
1104  label="Max. inst. lumi.: %.2f %s" % \
1105  (max_inst, LatexifyUnits(units)))
1106 
1107  tmp_leg = ax.legend(loc="upper left",
1108  bbox_to_anchor=(0.025, 0., 1., .97),
1109  frameon=False)
1110  tmp_leg.legendHandles[0].set_visible(False)
1111  for t in tmp_leg.get_texts():
1112  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1113 
1114  # Set titles and labels.
1115  fig.suptitle(r"CMS Peak Luminosity Per Day, " \
1116  "%s, %d, $\mathbf{\sqrt{s} =}$ %s" % \
1117  (particle_type_str, year, cms_energy_str),
1118  fontproperties=FONT_PROPS_SUPTITLE)
1119  ax.set_title("Data included from %s to %s UTC \n" % \
1120  (str_begin, str_end),
1121  fontproperties=FONT_PROPS_TITLE)
1122  ax.set_xlabel(r"Date (UTC)", fontproperties=FONT_PROPS_AX_TITLE)
1123  ax.set_ylabel(r"Peak Delivered Luminosity (%s)" % \
1124  LatexifyUnits(units),
1125  fontproperties=FONT_PROPS_AX_TITLE)
1126 
1127  # Add the logo.
1128  AddLogo(logo_name, ax)
1129  TweakPlot(fig, ax, (time_begin, time_end), True)
1130 
1131  log_suffix = ""
1132  if is_log:
1133  log_suffix = "_log"
1134  SavePlot(fig, "peak_lumi_per_day_%s_%d%s%s" % \
1135  (particle_type_str.lower(), year,
1136  log_suffix, file_suffix))
1137 
1138  #----------
1139 
1140  # The lumi-per-day plot.
1141  for type in ["lin", "log"]:
1142  is_log = (type == "log")
1143  log_setting = False
1144  if is_log:
1145  min_val = min(weights_rec)
1146  exp = math.floor(math.log10(min_val))
1147  log_setting = math.pow(10., exp)
1148 
1149  fig.clear()
1150  ax = fig.add_subplot(111)
1151 
1152  units = GetUnits(year, accel_mode, "cum_day")
1153 
1154  # Figure out the maximum delivered and recorded luminosities.
1155  max_del = max(weights_del)
1156  max_rec = max(weights_rec)
1157 
1158  if sum(weights_del) > 0.:
1159 
1160  ax.hist(times, bin_edges, weights=weights_del,
1161  histtype="stepfilled",
1162  log=log_setting,
1163  facecolor=color_fill_del, edgecolor=color_line_del,
1164  label="LHC Delivered, max: %.1f %s/day" % \
1165  (max_del, LatexifyUnits(units)))
1166  ax.hist(times, bin_edges, weights=weights_rec,
1167  histtype="stepfilled",
1168  log=log_setting,
1169  facecolor=color_fill_rec, edgecolor=color_line_rec,
1170  label="CMS Recorded, max: %.1f %s/day" % \
1171  (max_rec, LatexifyUnits(units)))
1172  leg = ax.legend(loc="upper left", bbox_to_anchor=(0.125, 0., 1., 1.01),
1173  frameon=False)
1174  for t in leg.get_texts():
1175  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1176  # Set titles and labels.
1177  fig.suptitle(r"CMS Integrated Luminosity Per Day, " \
1178  "%s, %d, $\mathbf{\sqrt{s} =}$ %s" % \
1179  (particle_type_str, year, cms_energy_str),
1180  fontproperties=FONT_PROPS_SUPTITLE)
1181  ax.set_title("Data included from %s to %s UTC \n" % \
1182  (str_begin, str_end),
1183  fontproperties=FONT_PROPS_TITLE)
1184  ax.set_xlabel(r"Date (UTC)", fontproperties=FONT_PROPS_AX_TITLE)
1185  ax.set_ylabel(r"Integrated Luminosity (%s/day)" % \
1186  LatexifyUnits(units),
1187  fontproperties=FONT_PROPS_AX_TITLE)
1188 
1189  # Add the logo.
1190  AddLogo(logo_name, ax)
1191  TweakPlot(fig, ax, (time_begin, time_end), True)
1192 
1193  log_suffix = ""
1194  if is_log:
1195  log_suffix = "_log"
1196  SavePlot(fig, "int_lumi_per_day_%s_%d%s%s" % \
1197  (particle_type_str.lower(), year,
1198  log_suffix, file_suffix))
1199 
1200  #----------
1201 
1202  # Now for the cumulative plot.
1203  units = GetUnits(year, accel_mode, "cum_year")
1204 
1205  # Figure out the totals.
1206  min_del = min(weights_del_for_cum)
1207  tot_del = sum(weights_del_for_cum)
1208  tot_rec = sum(weights_rec_for_cum)
1209  tot_cert = sum(weights_cert_for_cum)
1210 
1211  for type in ["lin", "log"]:
1212  is_log = (type == "log")
1213  log_setting = False
1214  if is_log:
1215  min_val = min(weights_del_for_cum)
1216  exp = math.floor(math.log10(min_val))
1217  log_setting = math.pow(10., exp)
1218 
1219  fig.clear()
1220  ax = fig.add_subplot(111)
1221 
1222  if sum(weights_del) > 0.:
1223 
1224  ax.hist(times, bin_edges, weights=weights_del_for_cum,
1225  histtype="stepfilled", cumulative=True,
1226  log=log_setting,
1227  facecolor=color_fill_del, edgecolor=color_line_del,
1228  label="LHC Delivered: %.2f %s" % \
1229  (tot_del, LatexifyUnits(units)))
1230  ax.hist(times, bin_edges, weights=weights_rec_for_cum,
1231  histtype="stepfilled", cumulative=True,
1232  log=log_setting,
1233  facecolor=color_fill_rec, edgecolor=color_line_rec,
1234  label="CMS Recorded: %.2f %s" % \
1235  (tot_rec, LatexifyUnits(units)))
1236  if sum(weights_cert_for_cum) > 0.:
1237  ax.hist(times, bin_edges, weights=weights_cert_for_cum,
1238  histtype="stepfilled", cumulative=True,
1239  log=log_setting,
1240  facecolor=color_fill_cert, edgecolor=color_line_cert,
1241  label="CMS Validated: %.2f %s" % \
1242  (tot_cert, LatexifyUnits(units)))
1243  leg = ax.legend(loc="upper left",
1244  bbox_to_anchor=(0.125, 0., 1., 1.01),
1245  frameon=False)
1246  for t in leg.get_texts():
1247  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1248 
1249  # Set titles and labels.
1250  fig.suptitle(r"CMS Integrated Luminosity, " \
1251  r"%s, %d, $\mathbf{\sqrt{s} =}$ %s" % \
1252  (particle_type_str, year, cms_energy_str),
1253  fontproperties=FONT_PROPS_SUPTITLE)
1254  ax.set_title("Data included from %s to %s UTC \n" % \
1255  (str_begin, str_end),
1256  fontproperties=FONT_PROPS_TITLE)
1257  ax.set_xlabel(r"Date (UTC)", fontproperties=FONT_PROPS_AX_TITLE)
1258  ax.set_ylabel(r"Total Integrated Luminosity (%s)" % \
1259  LatexifyUnits(units),
1260  fontproperties=FONT_PROPS_AX_TITLE)
1261 
1262  # Add "CMS Preliminary" to the plot.
1263  if json_file_name:
1264  ax.text(0.05, 0.7, "CMS Preliminary",
1265  verticalalignment="center", horizontalalignment="left",
1266  transform = ax.transAxes, fontsize=15)
1267 
1268  # Add the logo.
1269  AddLogo(logo_name, ax)
1270  TweakPlot(fig, ax, (time_begin, time_end),
1271  add_extra_head_room=is_log)
1272 
1273  log_suffix = ""
1274  if is_log:
1275  log_suffix = "_log"
1276  SavePlot(fig, "int_lumi_per_day_cumulative_%s_%d%s%s" % \
1277  (particle_type_str.lower(), year,
1278  log_suffix, file_suffix))
1279 
1280  #------------------------------
1281  # Create the per-week delivered-lumi plots.
1282  #------------------------------
1283 
1284  for year in years:
1285 
1286  print " weekly lumi plots for %d" % year
1287 
1288  if not beam_energy_from_cfg:
1289  beam_energy = beam_energy_defaults[accel_mode][year]
1290  cms_energy = 2. * beam_energy
1291  cms_energy_str = "???"
1292  if accel_mode == "PROTPHYS":
1293  width = 0
1294  if year == 2013:
1295  width = 2
1296  cms_energy_str = "%.*f TeV" % (width, 1.e-3 * cms_energy)
1297  elif accel_mode in ["IONPHYS", "PAPHYS"]:
1298  cms_energy_str = "%.2f TeV/nucleon" % \
1299  (1.e-3 * GetEnergyPerNucleonScaleFactor(accel_mode) * cms_energy)
1300 
1301  lumi_data = lumi_data_by_week_per_year[year]
1302  lumi_data.sort()
1303 
1304  # NOTE: Tweak the time range a bit to force the bins to be
1305  # split at the middle of the weeks.
1306  week_lo = AtMidWeek(lumi_data.time_begin()) - \
1307  datetime.timedelta(days=3, seconds=12*60*60)
1308  week_hi = AtMidWeek(lumi_data.time_end()) + \
1309  datetime.timedelta(days=3, seconds=12*60*60)
1310 
1311  #----------
1312 
1313  # Build the histograms.
1314  num_weeks = week_hi.isocalendar()[1] - week_lo.isocalendar()[1] + 1
1315  bin_edges = np.linspace(matplotlib.dates.date2num(week_lo),
1316  matplotlib.dates.date2num(week_hi),
1317  num_weeks)
1318  times_tmp = [AtMidWeek(i) for i in lumi_data.times()]
1319  times = [matplotlib.dates.date2num(i) for i in times_tmp]
1320  # Delivered and recorded luminosity integrated per week.
1321  units = GetUnits(year, accel_mode, "cum_week")
1322  weights_del = lumi_data.lum_del(units)
1323  weights_rec = lumi_data.lum_rec(units)
1324  # Cumulative versions of the above.
1325  units = GetUnits(year, accel_mode, "cum_year")
1326  weights_del_for_cum = lumi_data.lum_del(units)
1327  weights_rec_for_cum = lumi_data.lum_rec(units)
1328  # Maximum instantaneous delivered luminosity per week.
1329  units = GetUnits(year, accel_mode, "max_inst")
1330  weights_del_inst = lumi_data.lum_inst_max(units)
1331 
1332  # Figure out the time window of the data included for the plot
1333  # subtitles.
1334  str_begin = None
1335  str_end = None
1336  if sum(weights_del) > 0.:
1337  str_begin = lumi_data.time_begin().strftime(DATE_FMT_STR_OUT)
1338  str_end = lumi_data.time_end().strftime(DATE_FMT_STR_OUT)
1339 
1340  #----------
1341 
1342  # Loop over all color schemes.
1343  for color_scheme_name in color_scheme_names:
1344 
1345  print " color scheme '%s'" % color_scheme_name
1346 
1347  color_scheme = ColorScheme(color_scheme_name)
1348  color_fill_del = color_scheme.color_fill_del
1349  color_fill_rec = color_scheme.color_fill_rec
1350  color_fill_peak = color_scheme.color_fill_peak
1351  color_line_del = color_scheme.color_line_del
1352  color_line_rec = color_scheme.color_line_rec
1353  color_line_peak = color_scheme.color_line_peak
1354  logo_name = color_scheme.logo_name
1355  file_suffix = color_scheme.file_suffix
1356 
1357  fig = plt.figure()
1358 
1359  #----------
1360 
1361  for type in ["lin", "log"]:
1362  is_log = (type == "log")
1363  log_setting = False
1364  if is_log:
1365  min_val = min(weights_del_inst)
1366  exp = math.floor(math.log10(min_val))
1367  log_setting = math.pow(10., exp)
1368 
1369  fig.clear()
1370  ax = fig.add_subplot(111)
1371 
1372  units = GetUnits(year, accel_mode, "max_inst")
1373 
1374  # Figure out the maximum instantaneous luminosity.
1375  max_inst = max(weights_del_inst)
1376 
1377  if sum(weights_del) > 0.:
1378 
1379  ax.hist(times, bin_edges, weights=weights_del_inst,
1380  histtype="stepfilled",
1381  log=log_setting,
1382  facecolor=color_fill_peak, edgecolor=color_line_peak,
1383  label="Max. inst. lumi.: %.2f %s" % \
1384  (max_inst, LatexifyUnits(units)))
1385 
1386  tmp_leg = ax.legend(loc="upper left",
1387  bbox_to_anchor=(0.025, 0., 1., .97),
1388  frameon=False)
1389  tmp_leg.legendHandles[0].set_visible(False)
1390  for t in tmp_leg.get_texts():
1391  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1392 
1393  # Set titles and labels.
1394  fig.suptitle(r"CMS Peak Luminosity Per Week, " \
1395  "%s, %d, $\mathbf{\sqrt{s} =}$ %s" % \
1396  (particle_type_str, year, cms_energy_str),
1397  fontproperties=FONT_PROPS_SUPTITLE)
1398  ax.set_title("Data included from %s to %s UTC \n" % \
1399  (str_begin, str_end),
1400  fontproperties=FONT_PROPS_TITLE)
1401  ax.set_xlabel(r"Date (UTC)",
1402  fontproperties=FONT_PROPS_AX_TITLE)
1403  ax.set_ylabel(r"Peak Delivered Luminosity (%s)" % \
1404  LatexifyUnits(units),
1405  fontproperties=FONT_PROPS_AX_TITLE)
1406 
1407  # Add the logo.
1408  AddLogo(logo_name, ax)
1409  TweakPlot(fig, ax, (week_lo, week_hi), True)
1410 
1411  log_suffix = ""
1412  if is_log:
1413  log_suffix = "_log"
1414  SavePlot(fig, "peak_lumi_per_week_%s_%d%s%s" % \
1415  (particle_type_str.lower(), year,
1416  log_suffix, file_suffix))
1417 
1418  #----------
1419 
1420  # The lumi-per-week plot.
1421  for type in ["lin", "log"]:
1422  is_log = (type == "log")
1423  log_setting = False
1424  if is_log:
1425  min_val = min(weights_rec)
1426  exp = math.floor(math.log10(min_val))
1427  log_setting = math.pow(10., exp)
1428 
1429  fig.clear()
1430  ax = fig.add_subplot(111)
1431 
1432  units = GetUnits(year, accel_mode, "cum_week")
1433 
1434  # Figure out the maximum delivered and recorded luminosities.
1435  max_del = max(weights_del)
1436  max_rec = max(weights_rec)
1437 
1438  if sum(weights_del) > 0.:
1439 
1440  ax.hist(times, bin_edges, weights=weights_del,
1441  histtype="stepfilled",
1442  log=log_setting,
1443  facecolor=color_fill_del, edgecolor=color_line_del,
1444  label="LHC Delivered, max: %.1f %s/week" % \
1445  (max_del, LatexifyUnits(units)))
1446  ax.hist(times, bin_edges, weights=weights_rec,
1447  histtype="stepfilled",
1448  log=log_setting,
1449  facecolor=color_fill_rec, edgecolor=color_line_rec,
1450  label="CMS Recorded, max: %.1f %s/week" % \
1451  (max_rec, LatexifyUnits(units)))
1452  leg = ax.legend(loc="upper left", bbox_to_anchor=(0.125, 0., 1., 1.01),
1453  frameon=False)
1454  for t in leg.get_texts():
1455  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1456 
1457  # Set titles and labels.
1458  fig.suptitle(r"CMS Integrated Luminosity Per Week, " \
1459  "%s, %d, $\mathbf{\sqrt{s} =}$ %s" % \
1460  (particle_type_str, year, cms_energy_str),
1461  fontproperties=FONT_PROPS_SUPTITLE)
1462  ax.set_title("Data included from %s to %s UTC \n" % \
1463  (str_begin, str_end),
1464  fontproperties=FONT_PROPS_TITLE)
1465  ax.set_xlabel(r"Date (UTC)", fontproperties=FONT_PROPS_AX_TITLE)
1466  ax.set_ylabel(r"Integrated Luminosity (%s/week)" % \
1467  LatexifyUnits(units),
1468  fontproperties=FONT_PROPS_AX_TITLE)
1469 
1470  # Add the logo.
1471  AddLogo(logo_name, ax)
1472  TweakPlot(fig, ax, (week_lo, week_hi), True)
1473 
1474  log_suffix = ""
1475  if is_log:
1476  log_suffix = "_log"
1477  SavePlot(fig, "int_lumi_per_week_%s_%d%s%s" % \
1478  (particle_type_str.lower(), year,
1479  log_suffix, file_suffix))
1480 
1481  #----------
1482 
1483  # Now for the cumulative plot.
1484  units = GetUnits(year, accel_mode, "cum_year")
1485 
1486  # Figure out the totals.
1487  min_del = min(weights_del_for_cum)
1488  tot_del = sum(weights_del_for_cum)
1489  tot_rec = sum(weights_rec_for_cum)
1490 
1491  for type in ["lin", "log"]:
1492  is_log = (type == "log")
1493  log_setting = False
1494  if is_log:
1495  min_val = min(weights_del_for_cum)
1496  exp = math.floor(math.log10(min_val))
1497  log_setting = math.pow(10., exp)
1498 
1499  fig.clear()
1500  ax = fig.add_subplot(111)
1501 
1502  if sum(weights_del) > 0.:
1503 
1504  ax.hist(times, bin_edges, weights=weights_del_for_cum,
1505  histtype="stepfilled", cumulative=True,
1506  log=log_setting,
1507  facecolor=color_fill_del, edgecolor=color_line_del,
1508  label="LHC Delivered: %.2f %s" % \
1509  (tot_del, LatexifyUnits(units)))
1510  ax.hist(times, bin_edges, weights=weights_rec_for_cum,
1511  histtype="stepfilled", cumulative=True,
1512  log=log_setting,
1513  facecolor=color_fill_rec, edgecolor=color_line_rec,
1514  label="CMS Recorded: %.2f %s" % \
1515  (tot_rec, LatexifyUnits(units)))
1516  leg = ax.legend(loc="upper left", bbox_to_anchor=(0.125, 0., 1., 1.01),
1517  frameon=False)
1518  for t in leg.get_texts():
1519  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1520 
1521  # Set titles and labels.
1522  fig.suptitle(r"CMS Integrated Luminosity, " \
1523  r"%s, %d, $\mathbf{\sqrt{s} =}$ %s" % \
1524  (particle_type_str, year, cms_energy_str),
1525  fontproperties=FONT_PROPS_SUPTITLE)
1526  ax.set_title("Data included from %s to %s UTC \n" % \
1527  (str_begin, str_end),
1528  fontproperties=FONT_PROPS_TITLE)
1529  ax.set_xlabel(r"Date (UTC)", fontproperties=FONT_PROPS_AX_TITLE)
1530  ax.set_ylabel(r"Total Integrated Luminosity (%s)" % \
1531  LatexifyUnits(units),
1532  fontproperties=FONT_PROPS_AX_TITLE)
1533 
1534  # Add the logo.
1535  AddLogo(logo_name, ax)
1536  TweakPlot(fig, ax, (week_lo, week_hi),
1537  add_extra_head_room=is_log)
1538 
1539  log_suffix = ""
1540  if is_log:
1541  log_suffix = "_log"
1542  SavePlot(fig, "int_lumi_per_week_cumulative_%s_%d%s%s" % \
1543  (particle_type_str.lower(), year,
1544  log_suffix, file_suffix))
1545 
1546  plt.close()
1547 
1548  #----------
1549 
1550  # Now the cumulative plot showing all years together.
1551  if len(years) > 1:
1552  print " cumulative luminosity for %s together" % ", ".join([str(i) for i in years])
1553 
1554  def PlotAllYears(lumi_data_by_day_per_year, mode):
1555  """Mode 1: years side-by-side, mode 2: years overlaid."""
1556 
1557  units = GetUnits(years[-1], accel_mode, "cum_year")
1558 
1559  scale_factor_2010 = 100.
1560 
1561  # Loop over all color schemes and plot.
1562  for color_scheme_name in color_scheme_names:
1563 
1564  print " color scheme '%s'" % color_scheme_name
1565 
1566  color_scheme = ColorScheme(color_scheme_name)
1567  color_by_year = color_scheme.color_by_year
1568  logo_name = color_scheme.logo_name
1569  file_suffix = color_scheme.file_suffix
1570 
1571  for type in ["lin", "log"]:
1572  is_log = (type == "log")
1573 
1574  if mode == 1:
1575  aspect_ratio = matplotlib.figure.figaspect(1. / 2.5)
1576  fig = plt.figure(figsize=aspect_ratio)
1577  else:
1578  fig = plt.figure()
1579  ax = fig.add_subplot(111)
1580 
1581  time_begin_ultimate = lumi_data_by_day_per_year[years[0]].time_begin()
1582  str_begin_ultimate = time_begin_ultimate.strftime(DATE_FMT_STR_OUT)
1583  for (year_index, year) in enumerate(years):
1584 
1585  lumi_data = lumi_data_by_day_per_year[year]
1586  lumi_data.sort()
1587  times_tmp = [AtMidnight(i) for i in lumi_data.times()]
1588  # For the plots showing all years overlaid, shift
1589  # all but the first year forward.
1590  # NOTE: Years list is supposed to be sorted.
1591  if mode == 2:
1592  if year_index > 0:
1593  for y in years[:year_index]:
1594  num_days = NumDaysInYear(y)
1595  time_shift = datetime.timedelta(days=num_days)
1596  times_tmp = [(i - time_shift) \
1597  for i in times_tmp]
1598  times = [matplotlib.dates.date2num(i) for i in times_tmp]
1599  # DEBUG DEBUG DEBUG
1600  for i in xrange(len(times) - 1):
1601  assert times[i] < times[i + 1]
1602  # DEBUG DEBUG DEBUG end
1603  weights_del = lumi_data.lum_del(units)
1604  weights_del_cum = [0.] * len(weights_del)
1605  tot_del = 0.
1606  for (i, val) in enumerate(weights_del):
1607  tot_del += val
1608  weights_del_cum[i] = tot_del
1609  if not beam_energy_from_cfg:
1610  beam_energy = beam_energy_defaults[accel_mode][year]
1611  cms_energy = 2. * beam_energy
1612  cms_energy_str = "???"
1613  if accel_mode == "PROTPHYS":
1614  width = 0
1615  if year == 2013:
1616  width = 2
1617  cms_energy_str = "%.*f TeV" % \
1618  (width, 1.e-3 * cms_energy)
1619  elif accel_mode in ["IONPHYS", "PAPHYS"]:
1620  cms_energy_str = "%.2f TeV/nucleon" % \
1621  (1.e-3 * GetEnergyPerNucleonScaleFactor(accel_mode) * cms_energy)
1622 
1623  # NOTE: Special case for 2010.
1624  label = None
1625  if year == 2010:
1626  label = r"%d, %s, %.1f %s" % \
1627  (year, cms_energy_str,
1628  1.e3 * tot_del,
1629  LatexifyUnits("pb^{-1}"))
1630  else:
1631  label = r"%d, %s, %.1f %s" % \
1632  (year, cms_energy_str, tot_del,
1633  LatexifyUnits(units))
1634 
1635  # NOTE: Special case for 2010
1636  weights_tmp = None
1637  if year == 2010:
1638  weights_tmp = [scale_factor_2010 * i \
1639  for i in weights_del_cum]
1640  else:
1641  weights_tmp = weights_del_cum
1642  ax.plot(times, weights_tmp,
1643  color=color_by_year[year],
1644  marker="none", linestyle="solid",
1645  linewidth=4,
1646  label=label)
1647  if is_log:
1648  ax.set_yscale("log")
1649 
1650  # NOTE: Special case for 2010.
1651  if year == 2010:
1652  ax.annotate(r"$\times$ %.0f" % scale_factor_2010,
1653  xy=(times[-1], weights_tmp[-1]),
1654  xytext=(5., -2.),
1655  xycoords="data", textcoords="offset points")
1656 
1657  # BUG BUG BUG
1658  # Needs work...
1659  time_begin = lumi_data.time_begin()
1660  time_end = lumi_data.time_end()
1661  str_begin = time_begin.strftime(DATE_FMT_STR_OUT)
1662  str_end = time_end.strftime(DATE_FMT_STR_OUT)
1663  if mode == 1:
1664  time_begin = datetime.datetime(years[0], 1, 1, 0, 0, 0)
1665  time_end = datetime.datetime(years[-1], 12, 31, 23, 59,59)
1666  else:
1667  time_begin = datetime.datetime(years[0], 1, 1, 0, 0, 0)
1668  time_end = datetime.datetime(years[0], 12, 31, 23, 59,59)
1669  # BUG BUG BUG end
1670 
1671  num_cols = None
1672  if mode == 1:
1673  num_cols = len(years)
1674  tmp_x = 0.095
1675  tmp_y = .95
1676  else:
1677  num_cols = 1
1678  tmp_x = 0.175
1679  tmp_y = 1.01
1680  leg = ax.legend(loc="upper left", bbox_to_anchor=(tmp_x, 0., 1., tmp_y),
1681  frameon=False, ncol=num_cols)
1682  for t in leg.get_texts():
1683  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1684 
1685  # Set titles and labels.
1686  fig.suptitle(r"CMS Integrated Luminosity, %s" % particle_type_str,
1687  fontproperties=FONT_PROPS_SUPTITLE)
1688  ax.set_title("Data included from %s to %s UTC \n" % \
1689 # (str_begin, str_end),
1690  (str_begin_ultimate, str_end),
1691  fontproperties=FONT_PROPS_TITLE)
1692  ax.set_xlabel(r"Date (UTC)", fontproperties=FONT_PROPS_AX_TITLE)
1693  ax.set_ylabel(r"Total Integrated Luminosity (%s)" % \
1694  LatexifyUnits(units),
1695  fontproperties=FONT_PROPS_AX_TITLE)
1696 
1697  # Add the logo.
1698  zoom = 1.7
1699  if mode == 1:
1700  zoom = .95
1701  AddLogo(logo_name, ax, zoom=zoom)
1702  extra_head_room = 0
1703  if is_log:
1704  if mode == 1:
1705  extra_head_room = 1
1706  elif mode == 2:
1707  extra_head_room = 2
1708 # TweakPlot(fig, ax, (time_begin, time_end),
1709  TweakPlot(fig, ax, (time_begin_ultimate, time_end),
1710  add_extra_head_room=extra_head_room)
1711 
1712  log_suffix = ""
1713  if is_log:
1714  log_suffix = "_log"
1715  SavePlot(fig, "int_lumi_cumulative_%s_%d%s%s" % \
1716  (particle_type_str.lower(), mode,
1717  log_suffix, file_suffix))
1718 
1719  for mode in [1, 2]:
1720  print " mode %d" % mode
1721  PlotAllYears(lumi_data_by_day_per_year, mode)
1722 
1723  plt.close()
1724 
1725  #----------
1726 
1727  # Now the peak lumi plot showing all years together.
1728  if len(years) > 1:
1729  print " peak luminosity for %s together" % ", ".join([str(i) for i in years])
1730 
1731  units = GetUnits(years[-1], accel_mode, "max_inst")
1732 
1733  scale_factor_2010 = 10.
1734 
1735  # Loop over all color schemes and plot.
1736  for color_scheme_name in color_scheme_names:
1737 
1738  print " color scheme '%s'" % color_scheme_name
1739 
1740  color_scheme = ColorScheme(color_scheme_name)
1741  color_by_year = color_scheme.color_by_year
1742  logo_name = color_scheme.logo_name
1743  file_suffix = color_scheme.file_suffix
1744 
1745  for type in ["lin", "log"]:
1746  is_log = (type == "log")
1747 
1748  aspect_ratio = matplotlib.figure.figaspect(1. / 2.5)
1749  fig = plt.figure(figsize=aspect_ratio)
1750  ax = fig.add_subplot(111)
1751 
1752  time_begin_ultimate = lumi_data_by_day_per_year[years[0]].time_begin()
1753  str_begin_ultimate = time_begin_ultimate.strftime(DATE_FMT_STR_OUT)
1754  for (year_index, year) in enumerate(years):
1755 
1756  lumi_data = lumi_data_by_day_per_year[year]
1757  lumi_data.sort()
1758  times_tmp = [AtMidnight(i) for i in lumi_data.times()]
1759  times = [matplotlib.dates.date2num(i) for i in times_tmp]
1760  # DEBUG DEBUG DEBUG
1761  for i in xrange(len(times) - 1):
1762  assert times[i] < times[i + 1]
1763  # DEBUG DEBUG DEBUG end
1764  weights_inst = lumi_data.lum_inst_max(units)
1765  max_inst = max(weights_inst)
1766  if not beam_energy_from_cfg:
1767  beam_energy = beam_energy_defaults[accel_mode][year]
1768  cms_energy = 2. * beam_energy
1769  cms_energy_str = "???"
1770  if accel_mode == "PROTPHYS":
1771  width = 0
1772  if year == 2013:
1773  width = 2
1774  cms_energy_str = "%.*f TeV" % \
1775  (width, 1.e-3 * cms_energy)
1776  elif accel_mode in ["IONPHYS", "PAPHYS"]:
1777  cms_energy_str = "%.2f TeV/nucleon" % \
1778  (1.e-3 * GetEnergyPerNucleonScaleFactor(accel_mode) * cms_energy)
1779 
1780  # NOTE: Special case for 2010.
1781  label = None
1782  if year == 2010:
1783  label = r"%d, %s, max. %.1f %s" % \
1784  (year, cms_energy_str,
1785  1.e3 * max_inst,
1786  LatexifyUnits("Hz/ub"))
1787  else:
1788  label = r"%d, %s, max. %.1f %s" % \
1789  (year, cms_energy_str, max_inst,
1790  LatexifyUnits(units))
1791 
1792  # NOTE: Special case for 2010
1793  weights_tmp = None
1794  if year == 2010:
1795  weights_tmp = [scale_factor_2010 * i \
1796  for i in weights_inst]
1797  else:
1798  weights_tmp = weights_inst
1799  ax.plot(times, weights_tmp,
1800  color=color_by_year[year],
1801  marker=".", markersize=8.,
1802  linestyle="none",
1803  label=label)
1804  if is_log:
1805  ax.set_yscale("log")
1806 
1807  # NOTE: Special case for 2010.
1808  if year == 2010:
1809  ax.annotate(r"$\times$ %.0f" % scale_factor_2010,
1810  xy=(times[-1], max(weights_tmp)),
1811  xytext=(5., -2.),
1812  xycoords="data", textcoords="offset points")
1813 
1814  # BUG BUG BUG
1815  # Needs work...
1816  time_begin = lumi_data.time_begin()
1817  time_end = lumi_data.time_end()
1818  str_begin = time_begin.strftime(DATE_FMT_STR_OUT)
1819  str_end = time_end.strftime(DATE_FMT_STR_OUT)
1820  time_begin = datetime.datetime(years[0], 1, 1, 0, 0, 0)
1821  time_end = datetime.datetime(years[-1], 12, 31, 23, 59,59)
1822  # BUG BUG BUG end
1823 
1824  num_cols = None
1825  num_cols = len(years) - 2
1826  tmp_x = .09
1827  tmp_y = .97
1828  leg = ax.legend(loc="upper left",
1829  bbox_to_anchor=(tmp_x, 0., 1., tmp_y),
1830  labelspacing=.2,
1831  columnspacing=.2,
1832  frameon=False, ncol=num_cols)
1833  for t in leg.get_texts():
1834  t.set_font_properties(FONT_PROPS_TICK_LABEL)
1835 
1836  # Set titles and labels.
1837  fig.suptitle(r"CMS Peak Luminosity Per Day, %s" % particle_type_str,
1838  fontproperties=FONT_PROPS_SUPTITLE)
1839  ax.set_title("Data included from %s to %s UTC \n" % \
1840 # (str_begin, str_end),
1841  (str_begin_ultimate, str_end),
1842  fontproperties=FONT_PROPS_TITLE)
1843  ax.set_xlabel(r"Date (UTC)", fontproperties=FONT_PROPS_AX_TITLE)
1844  ax.set_ylabel(r"Peak Delivered Luminosity (%s)" % \
1845  LatexifyUnits(units),
1846  fontproperties=FONT_PROPS_AX_TITLE)
1847 
1848  # Add the logo.
1849  zoom = .97
1850  AddLogo(logo_name, ax, zoom=zoom)
1851  head_room = 2.
1852  if is_log:
1853  head_room = 2.
1854 # TweakPlot(fig, ax, (time_begin, time_end),
1855  TweakPlot(fig, ax, (time_begin_ultimate, time_end),
1856  add_extra_head_room=head_room)
1857 
1858  log_suffix = ""
1859  if is_log:
1860  log_suffix = "_log"
1861  SavePlot(fig, "peak_lumi_%s%s%s" % \
1862  (particle_type_str.lower(),
1863  log_suffix, file_suffix))
1864 
1865  #----------
1866 
1867  plt.close()
1868 
1869  ##########
1870 
1871  print "Done"
1872 
1873 ######################################################################
void add(const std::vector< const T * > &source, std::vector< const T * > &dest)
T min(T a, T b)
Definition: MathUtil.h:58
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
list object
Definition: dbtoconf.py:77
double split
Definition: MVATrainer.cc:139
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run