CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
jetHtPlotter.cc
Go to the documentation of this file.
1 // C++ includes
2 #include <iostream> // Input/output stream. Needed for cout.
3 #include <vector>
4 
5 // Root includes
6 #include "TFile.h"
7 #include "TString.h"
8 #include "TH1D.h"
9 #include "TProfile.h"
10 #include "TGraphErrors.h"
11 #include "TLegend.h"
12 #include "TLine.h"
13 #include "TSystem.h"
14 #include "TMath.h"
15 #include "TLatex.h"
16 
17 // AllInOneTool includes
18 #include "Options.h"
19 
20 // Include a drawing helper class
21 #include "JetHtPlotConfiguration.h"
22 #include "JDrawer.h"
23 
24 // Maximum number of compared files implemented in current code
25 const int kMaxFiles = 4;
26 
27 /*
28  * Draw a histogram to canvas
29  *
30  * Arguments:
31  * TH1D *histogram[kMaxFiles] = Input histogram and comparison histogram
32  * const char *saveName = Name given for saved figures
33  * bool saveFigures = True: Save figures to file, False: Do not save figures
34  * TString comment[kMaxFiles] = Text written to legend
35  * int legendPosition = Position index of legend: 0 = Right top, 1 = Middle bottom
36  * bool normalize = Normalize the distributions to one so that shapes can be compared
37  * bool logScale = Use logarithmic scale for y-axis
38  * int color[kMaxFiles] = Color used for each files
39  */
40 void drawSingleHistogram(TH1D *histogram[kMaxFiles],
41  const char *saveName,
42  bool saveFigures,
43  TString comment[kMaxFiles],
44  int legendPosition,
45  bool normalize,
46  bool logScale,
47  int color[kMaxFiles]) {
48  // Create and setup the histogram drawer
49  JDrawer *drawer = new JDrawer();
50  drawer->SetLogY(logScale);
51  drawer->SetTopMargin(0.08);
52 
53  // The first histogram in the array is always included, draw it
54  histogram[0]->SetLineColor(color[0]);
55  if (normalize)
56  histogram[0]->Scale(1.0 / histogram[0]->Integral());
57  drawer->DrawHistogram(histogram[0]);
58 
59  // Draw all the remaining histograms in the array. Calculate how many were drawn
60  int nHistograms = 1;
61  for (int iFile = 1; iFile < kMaxFiles; iFile++) {
62  if (histogram[iFile]) {
63  nHistograms++;
64  histogram[iFile]->SetLineColor(color[iFile]);
65  if (normalize)
66  histogram[iFile]->Scale(1.0 / histogram[iFile]->Integral());
67  histogram[iFile]->Draw("Same");
68  }
69  }
70 
71  // Create a legend with size depending on the number of histograms
72  double legendX1 = 0.6;
73  double legendY1 = 0.9 - 0.07 * nHistograms;
74  double legendX2 = 0.9;
75  double legendY2 = 0.9;
76  if (legendPosition == 1) {
77  legendX1 = 0.35;
78  legendY1 = 0.4 - 0.07 * nHistograms + 0.07 * (nHistograms / 4);
79  legendX2 = 0.65;
80  legendY2 = 0.4 + 0.07 * (nHistograms / 4);
81  }
82  TLegend *legend = new TLegend(legendX1, legendY1, legendX2, legendY2);
83  legend->SetFillStyle(0);
84  legend->SetBorderSize(0);
85  legend->SetTextSize(0.05);
86  legend->SetTextFont(62);
87 
88  // Add all the histograms to the legend and draw it
89  legend->AddEntry(histogram[0], comment[0], "l");
90  for (int iFile = 1; iFile < kMaxFiles; iFile++) {
91  if (histogram[iFile]) {
92  legend->AddEntry(histogram[iFile], comment[iFile], "l");
93  }
94  }
95  legend->Draw();
96 
97  // Save the drawn figure to a file
98  if (saveFigures)
99  gPad->GetCanvas()->SaveAs(Form("output/%s.pdf", saveName));
100 }
101 
102 /*
103  * Find a good range for the y-axes of the histograms
104  *
105  * Arguments:
106  * TH1D *histogram[kMaxFiles] = Histogram array from which the Y-axis range is searched
107  *
108  * return:
109  * Tuple containing the minimum and maximum zoom for the histogram Y-axis
110  */
111 std::tuple<double, double> findHistogramYaxisRange(TH1D *histogram[kMaxFiles]) {
112  // Find the smallest minimum and largest maximum from the histograms
113  double minValue = histogram[0]->GetMinimum();
114  double maxValue = histogram[0]->GetMaximum();
115 
116  double newMinValue, newMaxValue;
117 
118  for (int iFile = 1; iFile < kMaxFiles; iFile++) {
119  if (histogram[iFile]) {
120  newMinValue = histogram[iFile]->GetMinimum();
121  newMaxValue = histogram[iFile]->GetMaximum();
122 
123  if (newMinValue < minValue)
124  minValue = newMinValue;
125  if (newMaxValue > maxValue)
126  maxValue = newMaxValue;
127  }
128  }
129 
130  // Add some margin below the minimum and over the maximum
131  double margin = 0.075;
132  double totalSpan = maxValue - minValue;
133  minValue = minValue - margin * totalSpan;
134  if (minValue < 0)
135  minValue = 0;
136  maxValue = maxValue + margin * totalSpan;
137 
138  // Return the minimum and maximum values
139  return std::make_tuple(minValue, maxValue);
140 }
141 
142 /*
143  * Construct vectors of ptHat files and the ptHat value in each of those files
144  *
145  * Arguments:
146  * const char* inputFile = File containing the list of ptHat separated files and ptHat bin in each file
147  *
148  * return:
149  * Tuple containing list of runs, luminosities, and histogram names within the validation files
150  */
151 std::tuple<std::vector<std::string>, std::vector<int>> ptHatFilesAndValues(const char *inputFile) {
152  // Create vectors for ptHat files and values
153  std::vector<std::string> ptHatFileList;
154  std::vector<int> ptHatList;
155 
156  // Helper variables to read the file
157  std::string lineInFile;
158 
159  // Open the input file for reading
160  std::ifstream ptHatFile(inputFile);
161 
162  // Go through the file line by line. Each line has one file and information about the ptHat in the file.
163  while (std::getline(ptHatFile, lineInFile)) {
164  auto stringStream = std::istringstream{lineInFile};
165  auto wordString = std::string{};
166 
167  // Find the file name and ptHat in that file
168  stringStream >> wordString;
169  ptHatFileList.push_back(wordString);
170  stringStream >> wordString;
171  ptHatList.push_back(std::stoi(wordString));
172  }
173 
174  // After all the vectors are filled, return them
175  return std::make_tuple(ptHatFileList, ptHatList);
176 }
177 
178 /*
179  * Get a selected histogram combining different pThat bins
180  */
181 TH1 *ptHatCombinedHistogram(std::vector<TFile *> ptHatFiles, std::vector<int> ptHatValues, const char *histogramName) {
182  // Weight for bins: 30to50 50to80 80to120 120to170 170to300 300to470 470to600
183  double ptHatWeights[] = {
184  138800000,
185  19110000,
186  2735000,
187  466200,
188  117200,
189  7763,
190  641.0,
191  // 600to800 800to1000 1000to1400 1400to1800 1800to2400 2400to3200 3200toInf
192  185.7,
193  32.02,
194  9.375,
195  0.8384,
196  0.1133,
197  0.006746,
198  0.0001623};
199  const int nPtHat = 14;
200  int ptHatBoundaries[] = {30, 50, 80, 120, 170, 300, 470, 600, 800, 1000, 1400, 1800, 2400, 3200};
201 
202  TFile *openFile = ptHatFiles.at(0);
203  TH1 *combinedHistogram = (TH1 *)openFile->Get(histogramName)->Clone(Form("%sClone", histogramName));
204  TH1 *currentHistogram;
205  combinedHistogram->Reset("ICES");
206  int ptHatIndex = -1;
207 
208  const int nFiles = ptHatFiles.size();
209 
210  for (int iFile = 0; iFile < nFiles; iFile++) {
211  ptHatIndex = -1;
212  for (int iPtHat = 0; iPtHat < nPtHat; iPtHat++) {
213  if (ptHatValues.at(iFile) == ptHatBoundaries[iPtHat]) {
214  ptHatIndex = iPtHat;
215  break;
216  }
217  }
218 
219  if (ptHatIndex < 0) {
220  std::cout << "Could not find pT hat boundary " << ptHatValues.at(iFile) << " for file " << ptHatFiles.at(iFile)
221  << std::endl;
222  std::cout << "Please check your input! It needs to be in the form <fileName> <ptHatBoundary>" << std::endl;
223  return nullptr;
224  }
225 
226  openFile = ptHatFiles.at(iFile);
227  currentHistogram = (TH1 *)openFile->Get(histogramName);
228  combinedHistogram->Add(currentHistogram, ptHatWeights[ptHatIndex]);
229  }
230 
231  return combinedHistogram;
232 }
233 
234 /*
235  * Construct vectors of runs, luminosities, and histogram names within the validation files from an input file
236  * containing a list of runs and luminosities attached to each one
237  *
238  * Arguments:
239  * const char* inputFile = File containing the run and luminosity lists
240  * const char* iovListMode = List mode for IOVs. Tells if every run in the IOV list is it's own IOV or a border run in a set of runs for IOV.
241  *
242  * return:
243  * Tuple containing list of runs, luminosities, histogram names and legend strings within the validation files
244  */
245 std::tuple<std::vector<int>, std::vector<double>, std::vector<TString>, std::vector<TString>> runAndLumiLists(
246  const char *inputFile, const char *iovListMode) {
247  // Create vectors for each list
248  std::vector<int> iovVector;
249  std::vector<double> lumiPerIov;
250  std::vector<TString> iovNames;
251  std::vector<TString> iovLegend;
252 
253  // Helper variables to read the file
254  std::string lineInFile;
255  int thisIov;
256  double thisLumi;
257 
258  // Load the iovList
259  std::ifstream iovList(inputFile);
260 
261  // Go through the file line by line. Each line has an IOV boundary and luminosity for this IOV.
262  while (std::getline(iovList, lineInFile)) {
263  // Read the iov and luminosity from the file
264  std::istringstream lineStream(lineInFile);
265  lineStream >> thisIov;
266  lineStream >> thisLumi;
267 
268  // Push the extracted numbers to vectors
269  iovVector.push_back(thisIov);
270  lumiPerIov.push_back(thisLumi);
271  }
272 
273  // Create names for the different IOV:s
274  for (std::vector<int>::size_type i = 1; i < iovVector.size(); i++) {
275  iovNames.push_back(Form("iov%d-%d", iovVector.at(i - 1), iovVector.at(i) - 1));
276  }
277 
278  // For the legend naming, use just the run if specified in iovListMode
279  TString listModeParser = iovListMode;
280  if (listModeParser.EqualTo("iov", TString::kIgnoreCase)) {
281  for (std::vector<int>::size_type i = 1; i < iovVector.size(); i++) {
282  iovLegend.push_back(Form("IOV %d-%d", iovVector.at(i - 1), iovVector.at(i) - 1));
283  }
284  } else {
285  for (std::vector<int>::size_type i = 0; i < iovVector.size() - 1; i++) {
286  iovLegend.push_back(Form("Run %d", iovVector.at(i)));
287  }
288  }
289 
290  // Add the iov integrated histograms after the histograms per IOV
291  iovNames.push_back("all");
292  iovNames.push_back("central");
293  iovLegend.push_back("All");
294  iovLegend.push_back("Central");
295 
296  // After all the vectors are filled, return them
297  return std::make_tuple(iovVector, lumiPerIov, iovNames, iovLegend);
298 }
299 
300 /*
301  * Scale the x-axis of a given graph by integrated luminosity. The error on x-axis represents the luminosity of each run.
302  *
303  * Arguments:
304  * TGraphErrors *runGraph = Graph containing dxy or dz error trends as a function of run index
305  * std::vector<double> lumiPerIov = Vector showing luminosities for each run. Indices must match with the graph
306  * bool skipMissingRuns = If there is no data for a run in the runlist, do not assign luminosity for it
307  *
308  * Return: std::vector<double> New luminosity list where skipped runs are set to zero
309  *
310  */
311 std::vector<double> scaleGraphByLuminosity(TGraphErrors *runGraph,
312  std::vector<double> lumiPerIov,
313  bool skipMissingRuns) {
314  // Read the number of runs from the graph by run number
315  int nRuns = runGraph->GetN();
316 
317  // Helper variables
318  std::vector<double> xAxisValues, yAxisValues, xAxisErrors, yAxisErrors;
319 
320  int iRun = 0;
321  int offset = 0;
322  double lumiFactor = 1000; // Scale factor value to have luminosity expressed in fb^-1
323 
324  double runIndex, yValue;
325  double xValue = 0;
326  double epsilon = 1e-5;
327 
328  std::vector<double> lumiPerIovWithSkips;
329 
330  // Loop over all runs, remove zeros and for runs with content, replace x-axis index by luminosity
331  while (iRun < nRuns) {
332  runGraph->GetPoint(iRun, runIndex, yValue);
333 
334  if (lumiPerIov.at(iRun + offset) == 0 || (yValue < epsilon && skipMissingRuns)) {
335  nRuns--;
336  runGraph->RemovePoint(iRun);
337  offset++;
338 
339  // Fill vector where lumi for skipped runs is set to zero
340  lumiPerIovWithSkips.push_back(0);
341  } else {
342  xValue += lumiPerIov.at(iRun + offset) / lumiFactor;
343  xAxisValues.push_back(xValue - (lumiPerIov.at(iRun + offset) / (lumiFactor * 2)));
344  xAxisErrors.push_back(lumiPerIov.at(iRun + offset) / (lumiFactor * 2));
345  yAxisValues.push_back(yValue);
346  yAxisErrors.push_back(runGraph->GetErrorY(iRun));
347 
348  // Fill vector where lumi for skipped runs is set to zero
349  lumiPerIovWithSkips.push_back(lumiPerIov.at(iRun + offset));
350 
351  iRun++;
352  }
353  } // Loop over all runs in original histogram
354 
355  // Delete remaining old content and replace it with new one calculated from luminosities
356  runGraph->GetHistogram()->Delete();
357  runGraph->SetHistogram(nullptr);
358  for (int iRun = 0; iRun < nRuns; iRun++) {
359  runGraph->SetPoint(iRun, xAxisValues.at(iRun), yAxisValues.at(iRun));
360  runGraph->SetPointError(iRun, xAxisErrors.at(iRun), yAxisErrors.at(iRun));
361  }
362 
363  return lumiPerIovWithSkips;
364 }
365 
366 /*
367  * Get the total luminosity upto a given run
368  *
369  * std::vector<double> lumiPerIov = Vector containing luminosity information
370  * std::vector<int> iovVector = Vector containing run information
371  * in runNumber = Run upto which the luminosity is calculated
372  */
373 double luminosityBeforeRun(std::vector<double> lumiPerIov, std::vector<int> iovVector, int runNumber) {
374  double lumiFactor = 1000; // Scale factor value to have luminosity expressed in fb^-1
375 
376  int nRuns = lumiPerIov.size();
377  double luminosityBefore = 0;
378 
379  for (int iRun = 0; iRun < nRuns; iRun++) {
380  if (runNumber <= iovVector.at(iRun))
381  return luminosityBefore;
382 
383  luminosityBefore += lumiPerIov.at(iRun) / lumiFactor;
384  }
385 
386  return luminosityBefore;
387 }
388 
389 /*
390  * Macro for plotting figures for the study of jet HT sample
391  */
392 void jetHtPlotter(std::string configurationFileName) {
393  // ======================================================
394  // ================== Configuration =====================
395  // ======================================================
396 
397  JetHtPlotConfiguration *configurationGiver = new JetHtPlotConfiguration();
398  configurationGiver->readJsonFile(configurationFileName);
399  //configurationGiver->printConfiguration();
400 
401  enum enumHistogramType { kDz, kDzError, kDxy, kDxyError, knHistogramTypes };
402  TString histogramName[knHistogramTypes] = {"dz", "dzerr", "dxy", "dxyerr"};
403  TString histogramXaxis[knHistogramTypes] = {
404  "d_{z} (#mum)", "#sigma(d_{z}) (#mum)", "d_{xy} (#mum)", "#sigma(d_{xy}) (#mum)"};
405  enum enumProfileType {
406  kDzErrorVsPt,
407  kDzErrorVsPhi,
408  kDzErrorVsEta,
409  kDxyErrorVsPt,
410  kDxyErrorVsPhi,
411  kDxyErrorVsEta,
412  kDzErrorVsPtWide,
413  kDxyErrorVsPtWide,
414  knProfileTypes
415  };
416  enum enumTrendType { kDzErrorTrend, kDxyErrorTrend, knTrendTypes };
417  TString profileName[knProfileTypes] = {"dzErrVsPt",
418  "dzErrVsPhi",
419  "dzErrVsEta",
420  "dxyErrVsPt",
421  "dxyErrVsPhi",
422  "dxyErrVsEta",
423  "dzErrVsPtWide",
424  "dxyErrVsPtWide"};
425  TString profileXaxis[knProfileTypes] = {
426  "p_{T} (GeV)", "#varphi", "#eta", "p_{T} (GeV)", "#varphi", "#eta", "p_{T} bin", "p_{T} bin"};
427  TString profileYaxis[knProfileTypes] = {"d_{z}", "d_{z}", "d_{z}", "d_{xy}", "d_{xy}", "d_{xy}", "d_{z}", "d_{xy}"};
428  TString trendName[] = {"dzErr", "dxyErr"};
429  bool drawHistogram[knHistogramTypes];
430  bool drawProfile[knProfileTypes];
431  bool drawTrend[knTrendTypes];
432 
433  bool drawTrackQA = configurationGiver->drawTrackQA(); // Draw track and vertex QA figures
434  drawHistogram[kDz] = configurationGiver->drawHistogram(kDz); // Draw the dz histograms
435  drawHistogram[kDzError] = configurationGiver->drawHistogram(kDzError); // Draw the dz error histograms
436  drawProfile[kDzErrorVsPt] = configurationGiver->drawProfile(kDzErrorVsPt); // Draw mean dz error as a function of pT
437  drawProfile[kDzErrorVsPhi] =
438  configurationGiver->drawProfile(kDzErrorVsPhi); // Draw mean dz error as a function of phi
439  drawProfile[kDzErrorVsEta] =
440  configurationGiver->drawProfile(kDzErrorVsEta); // Draw mean dz error as a function of eta
441  drawProfile[kDzErrorVsPtWide] =
442  configurationGiver->drawProfile(kDzErrorVsPtWide); // Draw mean dz error in wide pT bins
443  drawHistogram[kDxy] = configurationGiver->drawHistogram(kDxy); // Draw the dxy histograms
444  drawHistogram[kDxyError] = configurationGiver->drawHistogram(kDxyError); // Draw the dxy error histograms
445  drawProfile[kDxyErrorVsPt] =
446  configurationGiver->drawProfile(kDxyErrorVsPt); // Draw the dxy error as a function of pT
447  drawProfile[kDxyErrorVsPhi] =
448  configurationGiver->drawProfile(kDxyErrorVsPhi); // Draw the dxy error as a function of phi
449  drawProfile[kDxyErrorVsEta] =
450  configurationGiver->drawProfile(kDxyErrorVsEta); // Draw the dxy error as a function of eta
451  drawProfile[kDxyErrorVsPtWide] =
452  configurationGiver->drawProfile(kDxyErrorVsPtWide); // Draw mean dxy error in wide pT bins
453  bool drawReferenceProfile = configurationGiver->drawReferenceProfile(); // Draw reference profile to single IOV plots
454  bool drawCentralEtaSummaryProfile =
455  configurationGiver->drawCentralEtaSummaryProfile(); // Draw central eta histograms to all runs summary profiles
456  drawTrend[kDzErrorTrend] = configurationGiver->drawTrend(kDzErrorTrend); // Draw the trend plots for dz errors
457  drawTrend[kDxyErrorTrend] = configurationGiver->drawTrend(kDxyErrorTrend); // Draw the trend plots for dxy errors
458 
459  const int nMaxLegendColumns = 3;
460  double profileLegendShiftTotalX =
461  configurationGiver->profileLegendShiftTotalX(); // Total legend position shift in x-direction for profile plots
462  double profileLegendShiftTotalY =
463  configurationGiver->profileLegendShiftTotalY(); // Total legend position shift in y-direction for profile plots
464  double profileLegendShiftColumnX[nMaxLegendColumns];
465  double profileLegendShiftColumnY[nMaxLegendColumns];
466  for (int iColumn = 0; iColumn < nMaxLegendColumns; iColumn++) {
467  profileLegendShiftColumnX[iColumn] = configurationGiver->profileLegendShiftColumnX(
468  iColumn); // Columnwise legend position shift in x-direction for profile plots
469  profileLegendShiftColumnY[iColumn] = configurationGiver->profileLegendShiftColumnY(
470  iColumn); // Columnwise legend position shift in x-direction for profile plots
471  }
472  double profileLegendTextSize = configurationGiver->profileLegendTextSize(); // Legend text size for profile plots
473  int profileLegendTextFont = configurationGiver->profileLegendTextFont(); // Legend text font for profile plots
474  TString legendTextForAllRuns =
475  configurationGiver->legendTextForAllRuns(); // Legend text referring to all runs in the file
476 
477  double trendLegendShiftTotalX =
478  configurationGiver->trendLegendShiftTotalX(); // Total legend position shift in x-direction for trend plots
479  double trendLegendShiftTotalY =
480  configurationGiver->trendLegendShiftTotalY(); // Total legend position shift in y-direction for trend plots
481  double trendLegendTextSize = configurationGiver->trendLegendTextSize(); // Legend text size for trend plots
482  int trendLegendTextFont = configurationGiver->trendLegendTextFont(); // Legend text font for trend plots
483 
484  bool drawTrendTag = configurationGiver->drawTrendTag(); // Draw manual tags to the trend plots
485  std::vector<std::string> trendTagText = configurationGiver->trendTagText(); // Drawn tag texts for trend plots
486  std::vector<double> trendTagPositionX = configurationGiver->trendTagPositionX(); // Trend tag x-positions
487  std::vector<double> trendTagPositionY = configurationGiver->trendTagPositionY(); // Trend tag y-positions
488  double trendTagTextSize = configurationGiver->trendTagTextSize(); // Tag text size for trend plots
489  int trendTagTextFont = configurationGiver->trendTagTextFont(); // Tag text font for trend plots
490 
491  int trendCanvasHeight = configurationGiver->trendCanvasHeight(); // Canvas height for trend plots
492  int trendCanvasWidth = configurationGiver->trendCanvasWidth(); // Canvas width for trend plots
493  double trendMarginLeft = configurationGiver->trendMarginLeft(); // Left margin in trend plots
494  double trendMarginRight = configurationGiver->trendMarginRight(); // Right margin in trend plots
495  double trendMarginTop = configurationGiver->trendMarginTop(); // Top margin in trend plots
496  double trendMarginBottom = configurationGiver->trendMarginBottom(); // Bottom margin in trend plots
497  double trendTitleOffsetX = configurationGiver->trendTitleOffsetX(); // x-axis title offset in trend plots
498  double trendTitleOffsetY = configurationGiver->trendTitleOffsetY(); // y-axis title offset in trend plots
499  double trendTitleSizeX = configurationGiver->trendTitleSizeX(); // x-axis title size in trend plots
500  double trendTitleSizeY = configurationGiver->trendTitleSizeY(); // y-axis title size in trend plots
501  double trendLabelOffsetX = configurationGiver->trendLabelOffsetX(); // x-axis label offset in trend plots
502  double trendLabelOffsetY = configurationGiver->trendLabelOffsetY(); // y-axis label offset in trend plots
503  double trendLabelSizeX = configurationGiver->trendLabelSizeX(); // x-axis label size in trend plots
504  double trendLabelSizeY = configurationGiver->trendLabelSizeY(); // y-axis label size in trend plots
505 
506  bool drawPlotsForEachIOV =
507  configurationGiver
508  ->drawPlotsForEachIOV(); // True = Draw profile and histogram plots for every IOV. False = only draw average over all runs
509  bool useLuminosityForTrends =
510  configurationGiver
511  ->useLuminosityForTrends(); // True = Draw trends as a function of luminosity. False = Draw trends as a function of run index
512  bool skipRunsWithNoData =
513  configurationGiver
514  ->skipRunsWithNoData(); // True = Do not draw empty space if run in list is missing data. False = Draw empty space
515 
516  int colors[] = {kBlue, kRed, kGreen + 2, kMagenta, kCyan, kViolet + 3, kOrange, kPink - 7, kSpring + 3, kAzure - 7};
517  int nIovInOnePlot = configurationGiver->nIovInOnePlot(); // Define how many iov:s are drawn to the same plot
518 
519  double profileZoomLow[knProfileTypes];
520  double profileZoomHigh[knProfileTypes];
521  double trendZoomLow[knTrendTypes];
522  double trendZoomHigh[knTrendTypes];
523 
524  for (int iProfile = 0; iProfile < knProfileTypes; iProfile++) {
525  profileZoomLow[iProfile] = configurationGiver->profileZoomLow(iProfile);
526  profileZoomHigh[iProfile] = configurationGiver->profileZoomHigh(iProfile);
527  }
528  for (int iTrend = 0; iTrend < knTrendTypes; iTrend++) {
529  trendZoomLow[iTrend] = configurationGiver->trendZoomLow(iTrend);
530  trendZoomHigh[iTrend] = configurationGiver->trendZoomHigh(iTrend);
531  }
532 
533  const std::vector<double> widePtBinBorders = configurationGiver->widePtBinBorders();
534  const int nWidePtBins = widePtBinBorders.size();
535 
536  bool normalizeQAplots = configurationGiver->normalizeQAplots(); // Divide in QA plot yield by its integral
537  bool saveFigures = true;
538  const char *saveComment = configurationGiver->saveComment();
539 
540  int compareFiles = configurationGiver->nInputFiles();
541  if (compareFiles == 0)
542  return; // Cannot do plotting without files!
543  if (compareFiles > kMaxFiles)
544  compareFiles = kMaxFiles; // Four is maximum number of files in current implementation
545 
546  // If we have more then one file, we should not draw more than one IOV per plot and plot all the files instead
547  if (compareFiles > 1)
548  nIovInOnePlot = 1;
549 
550  // Read the input file names. If file names end with .txt, they are assumed to be lists of files in different ptHat bins
551  TString inputFileName[kMaxFiles];
552  bool loadFromList[kMaxFiles] = {false, false, false, false};
553  TString legendComment[kMaxFiles];
554  int fileColor[kMaxFiles];
555  int fileMarkerStyle[kMaxFiles];
556  int fileMarkerSize[kMaxFiles];
557  bool copyErrorColor[kMaxFiles];
558 
559  for (int iFile = 0; iFile < kMaxFiles; iFile++) {
560  inputFileName[iFile] = configurationGiver->inputFile(iFile);
561  if (inputFileName[iFile].EndsWith("txt"))
562  loadFromList[iFile] = true;
563  legendComment[iFile] = configurationGiver->legendComment(iFile); // Text written to the legend for each file
564  fileColor[iFile] = configurationGiver->markerColor(iFile); // Color of markers related to this file
565  fileMarkerStyle[iFile] = configurationGiver->markerStyle(iFile); // Style for markers related to this file
566  fileMarkerSize[iFile] = configurationGiver->markerSize(iFile); // Size for markers related to this file
567  copyErrorColor[iFile] =
568  configurationGiver->copyErrorColor(iFile); // Copy the marker color for error bars for this file
569  }
570 
571  // Prepare an IOV list that can be used with the slide generation script
572  bool makeIovListForSlides = configurationGiver->makeIovListForSlides();
573  const char *iovListForSlides = configurationGiver->iovListForSlides();
574 
575  // Helper variable to ensure that each IOV is added exactly once to the list
576  int profileIndexForIovList = 0;
577  for (int iProfile = 0; iProfile < knProfileTypes; iProfile++) {
578  if (drawProfile[iProfile]) {
579  profileIndexForIovList = iProfile;
580  break;
581  }
582  }
583 
584  TString plotTitle = " "; // Title given to the plot
585 
586  // Year boundary runs
587  bool drawYearLines = configurationGiver->drawYearLines(); // Draw lines between data taking years
588  std::vector<int> linePosition = configurationGiver->runsForLines(); // Positions of the above lines
589  int yearLineColor = configurationGiver->yearLineColor(); // Color of the above lines
590  int yearLineWidth = configurationGiver->yearLineWidth(); // Width of the above lines
591  int yearLineStyle = configurationGiver->yearLineStyle(); // Style of the above lines
592 
593  // ======================================================
594  // ================ Configuration done ==================
595  // ======================================================
596 
597  // =======================================================
598  // Make sure that the output folder for figures exists
599  // =======================================================
600 
601  if (saveFigures) {
602  TString outputFolderStatus = gSystem->GetFromPipe("if [ -d output ]; then echo true; else echo false; fi");
603  if (outputFolderStatus == "false") {
604  gSystem->Exec("mkdir output");
605  }
606  }
607 
608  // ===============================================================
609  // Read different ptHat files for combining those with weights
610  // ===============================================================
611 
612  // List for all the different ptHat files to be combined
613  std::vector<std::string> ptHatFileNameList[kMaxFiles];
614  std::vector<TFile *> ptHatFileList[kMaxFiles];
615  std::vector<int> ptHatList[kMaxFiles];
616  int nFiles;
617 
618  for (int iInput = 0; iInput < kMaxFiles; iInput++) {
619  if (loadFromList[iInput]) {
620  std::tie(ptHatFileNameList[iInput], ptHatList[iInput]) = ptHatFilesAndValues(inputFileName[iInput]);
621 
622  // Open all files
623  nFiles = ptHatFileNameList[iInput].size();
624  for (int iFile = 0; iFile < nFiles; iFile++) {
625  ptHatFileList[iInput].push_back(TFile::Open(ptHatFileNameList[iInput].at(iFile).data()));
626  }
627  }
628  }
629 
630  // ===============================================
631  // Read the run and luminosity list
632  // ===============================================
633 
634  // Luminosity per run file
635  const char *iovAndLumiFile = configurationGiver->lumiPerIovFile();
636  const char *iovListMode = configurationGiver->iovListMode();
637 
638  // Create a vector for a new iovList
639  std::vector<int> iovVector;
640  std::vector<double> lumiPerIov;
641  std::vector<double> lumiPerIovWithSkips;
642  std::vector<TString> iovNames;
643  std::vector<TString> iovLegend;
644 
645  std::tie(iovVector, lumiPerIov, iovNames, iovLegend) = runAndLumiLists(iovAndLumiFile, iovListMode);
646 
647  // For the IOV legend, remove the two last entries and replace them with user defined names
648  iovLegend.pop_back();
649  iovLegend.pop_back();
650  iovLegend.push_back(legendTextForAllRuns);
651  iovLegend.push_back(Form("%s |#eta| < 1", legendTextForAllRuns.Data()));
652 
653  // ===============================================
654  // IOV list for slides
655  // ===============================================
656 
657  // If we are preparing an iov list for slides, make a file for that
658  std::ofstream iovFileForSlides;
659  if (makeIovListForSlides)
660  iovFileForSlides.open(iovListForSlides);
661 
662  // ===============================================
663  // Create histograms and read them from a file
664  // ===============================================
665 
666  // Open the input files
667  TFile *inputFile[kMaxFiles];
668  for (int iFile = 0; iFile < kMaxFiles; iFile++) {
669  if (compareFiles > iFile && !loadFromList[iFile])
670  inputFile[iFile] = TFile::Open(inputFileName[iFile]);
671  }
672 
673  // Define the histograms that will be read from the file
674  const int nIov = iovNames.size();
675  TH1D *hVertex[kMaxFiles];
676  TH1D *hTracksPerVertex[kMaxFiles];
677  TH1D *hTrackPt[kMaxFiles];
678  TH1D *hTrackEta[kMaxFiles];
679  TH1D *hTrackPhi[kMaxFiles];
680  TH1D *jetHtHistograms[kMaxFiles][knHistogramTypes][nIov];
681  TProfile *jetHtProfiles[kMaxFiles][knProfileTypes][nIov];
682  TGraphErrors *gBigTrend[kMaxFiles][knTrendTypes][nWidePtBins];
683 
684  // Initialize everything to NULL
685  for (int iFile = 0; iFile < kMaxFiles; iFile++) {
686  hVertex[iFile] = nullptr;
687  hTracksPerVertex[iFile] = nullptr;
688  hTrackPt[iFile] = nullptr;
689  hTrackEta[iFile] = nullptr;
690  hTrackPhi[iFile] = nullptr;
691  for (int iIov = 0; iIov < nIov; iIov++) {
692  for (int iHistogramType = 0; iHistogramType < knHistogramTypes; iHistogramType++) {
693  jetHtHistograms[iFile][iHistogramType][iIov] = nullptr;
694  } // histogram type loop
695  for (int iProfileType = 0; iProfileType < knProfileTypes; iProfileType++) {
696  jetHtProfiles[iFile][iProfileType][iIov] = nullptr;
697  } // profile type loop
698  } // iov loop for reading histograms from file
699  for (int iTrend = 0; iTrend < knTrendTypes; iTrend++) {
700  for (int iWidePt = 0; iWidePt < nWidePtBins; iWidePt++) {
701  gBigTrend[iFile][iTrend][iWidePt] = nullptr;
702  } // Trend loop
703  } // Wide pT bin loop
704  } // file loop
705 
706  // Read the histograms from the file
707  for (int iFile = 0; iFile < compareFiles; iFile++) {
708  if (loadFromList[iFile]) {
709  // Alternative loading for ptHat combined values
710 
711  hVertex[iFile] = (TH1D *)ptHatCombinedHistogram(ptHatFileList[iFile], ptHatList[iFile], "jetHTAnalyzer/all_nvtx");
712  hTracksPerVertex[iFile] =
713  (TH1D *)ptHatCombinedHistogram(ptHatFileList[iFile], ptHatList[iFile], "jetHTAnalyzer/h_ntrks");
714  hTrackPt[iFile] =
715  (TH1D *)ptHatCombinedHistogram(ptHatFileList[iFile], ptHatList[iFile], "jetHTAnalyzer/h_probePt");
716  hTrackEta[iFile] =
717  (TH1D *)ptHatCombinedHistogram(ptHatFileList[iFile], ptHatList[iFile], "jetHTAnalyzer/h_probeEta");
718  hTrackPhi[iFile] =
719  (TH1D *)ptHatCombinedHistogram(ptHatFileList[iFile], ptHatList[iFile], "jetHTAnalyzer/h_probePhi");
720  for (int iIov = nIov - 2; iIov < nIov - 1; iIov++) {
721  for (int iHistogramType = 0; iHistogramType < knHistogramTypes; iHistogramType++) {
722  if (drawHistogram[iHistogramType]) {
723  jetHtHistograms[iFile][iHistogramType][iIov] = (TH1D *)ptHatCombinedHistogram(
724  ptHatFileList[iFile],
725  ptHatList[iFile],
726  Form("jetHTAnalyzer/%s_%s", iovNames.at(iIov).Data(), histogramName[iHistogramType].Data()));
727  } // if for drawing histogram
728  } // histogram type loop
729  for (int iProfileType = 0; iProfileType < knProfileTypes; iProfileType++) {
730  if (drawProfile[iProfileType] || (drawTrend[kDzErrorTrend] && iProfileType == kDzErrorVsPtWide) ||
731  (drawTrend[kDxyErrorTrend] && iProfileType == kDxyErrorVsPtWide)) {
732  jetHtProfiles[iFile][iProfileType][iIov] = (TProfile *)ptHatCombinedHistogram(
733  ptHatFileList[iFile],
734  ptHatList[iFile],
735  Form("jetHTAnalyzer/%s_%s", iovNames.at(iIov).Data(), profileName[iProfileType].Data()));
736  } // if for drawing profile
737  } // profile type loop
738  } // iov loop for reading histograms from file
739 
740  } else {
741  // Regular histogram loading
742 
743  hVertex[iFile] = (TH1D *)inputFile[iFile]->Get("jetHTAnalyzer/all_nvtx");
744  hTracksPerVertex[iFile] = (TH1D *)inputFile[iFile]->Get("jetHTAnalyzer/h_ntrks");
745  hTrackPt[iFile] = (TH1D *)inputFile[iFile]->Get("jetHTAnalyzer/h_probePt");
746  hTrackEta[iFile] = (TH1D *)inputFile[iFile]->Get("jetHTAnalyzer/h_probeEta");
747  hTrackPhi[iFile] = (TH1D *)inputFile[iFile]->Get("jetHTAnalyzer/h_probePhi");
748  for (int iIov = 0; iIov < nIov; iIov++) {
749  for (int iHistogramType = 0; iHistogramType < knHistogramTypes; iHistogramType++) {
750  if (drawHistogram[iHistogramType]) {
751  jetHtHistograms[iFile][iHistogramType][iIov] = (TH1D *)inputFile[iFile]->Get(
752  Form("jetHTAnalyzer/%s_%s", iovNames.at(iIov).Data(), histogramName[iHistogramType].Data()));
753  } // if for drawing histogram
754  } // histogram type loop
755  for (int iProfileType = 0; iProfileType < knProfileTypes; iProfileType++) {
756  if (drawProfile[iProfileType] || (drawTrend[kDzErrorTrend] && iProfileType == kDzErrorVsPtWide) ||
757  (drawTrend[kDxyErrorTrend] && iProfileType == kDxyErrorVsPtWide)) {
758  jetHtProfiles[iFile][iProfileType][iIov] = (TProfile *)inputFile[iFile]->Get(
759  Form("jetHTAnalyzer/%s_%s", iovNames.at(iIov).Data(), profileName[iProfileType].Data()));
760  } // if for drawing profile
761  } // profile type loop
762  } // iov loop for reading histograms from file
763  } // Regular histogram loading
764  } // Loop over files
765 
766  // Collect the information for the trend graphs
767  const int nRuns = iovVector.size() - 1;
768  double yValueDz[nRuns];
769  double yErrorDz[nRuns];
770  double yValueDxy[nRuns];
771  double yErrorDxy[nRuns];
772  double xValue[nRuns];
773  double xError[nRuns];
774  TString commentEntry = "";
775  if (drawTrend[kDzErrorTrend] || drawTrend[kDxyErrorTrend]) {
776  for (int iFile = 0; iFile < compareFiles; iFile++) {
777  for (int iWidePt = 0; iWidePt < nWidePtBins; iWidePt++) {
778  for (int iRun = 0; iRun < nRuns; iRun++) {
779  xValue[iRun] = iRun;
780  xError[iRun] = 0;
781  if (jetHtProfiles[iFile][kDzErrorVsPtWide][iRun] == nullptr) {
782  yValueDz[iRun] = 0;
783  yErrorDz[iRun] = 0;
784  } else {
785  yValueDz[iRun] = jetHtProfiles[iFile][kDzErrorVsPtWide][iRun]->GetBinContent(iWidePt + 1);
786  yErrorDz[iRun] = jetHtProfiles[iFile][kDzErrorVsPtWide][iRun]->GetBinError(iWidePt + 1);
787  }
788  if (jetHtProfiles[iFile][kDxyErrorVsPtWide][iRun] == nullptr) {
789  yValueDxy[iRun] = 0;
790  yErrorDxy[iRun] = 0;
791  } else {
792  yValueDxy[iRun] = jetHtProfiles[iFile][kDxyErrorVsPtWide][iRun]->GetBinContent(iWidePt + 1);
793  yErrorDxy[iRun] = jetHtProfiles[iFile][kDxyErrorVsPtWide][iRun]->GetBinError(iWidePt + 1);
794  }
795  } // Run loop
796 
797  gBigTrend[iFile][kDzErrorTrend][iWidePt] = new TGraphErrors(nRuns, xValue, yValueDz, xError, yErrorDz);
798  gBigTrend[iFile][kDxyErrorTrend][iWidePt] = new TGraphErrors(nRuns, xValue, yValueDxy, xError, yErrorDxy);
799 
800  // Change x-axis to processed luminosity
801  if (useLuminosityForTrends) {
802  lumiPerIovWithSkips =
803  scaleGraphByLuminosity(gBigTrend[iFile][kDzErrorTrend][iWidePt], lumiPerIov, skipRunsWithNoData);
804  scaleGraphByLuminosity(gBigTrend[iFile][kDxyErrorTrend][iWidePt], lumiPerIov, skipRunsWithNoData);
805  }
806 
807  } // Wide pT bin loop
808  } // File loop
809  } // If for drawing trends
810 
811  // ===============================================
812  // Draw the plots
813  // ===============================================
814 
815  JDrawer *drawer = new JDrawer();
816  TLegend *legend[nMaxLegendColumns];
817  int columnOrder[nMaxLegendColumns];
818  bool noIovFound = true;
819  bool canvasDrawn;
820  bool doNotDrawEta;
821  double minZoomY, maxZoomY;
822  int nDrawnHistograms, nLeftLegend, nRightLegend;
823  double legendX1, legendX2, legendY1, legendY2;
824  int iLegend = 0;
825  int skipColor = 0;
826  int nNullHistograms;
827  int iHistogram;
828  TString legendString;
829  TH1D *histogramSearchArray[kMaxFiles];
830  for (int iFile = 0; iFile < kMaxFiles; iFile++) {
831  histogramSearchArray[iFile] = nullptr;
832  }
833 
834  // Draw track and vertex histograms
835  if (drawTrackQA) {
837  hVertex, Form("vertex%s", saveComment), saveFigures, legendComment, 0, normalizeQAplots, false, fileColor);
838  drawSingleHistogram(hTracksPerVertex,
839  Form("tracksPerVertex%s", saveComment),
840  saveFigures,
841  legendComment,
842  0,
843  normalizeQAplots,
844  false,
845  fileColor);
847  hTrackPt, Form("trackPt%s", saveComment), saveFigures, legendComment, 0, normalizeQAplots, true, fileColor);
849  hTrackEta, Form("trackEta%s", saveComment), saveFigures, legendComment, 1, normalizeQAplots, false, fileColor);
851  hTrackPhi, Form("trackPhi%s", saveComment), saveFigures, legendComment, 1, normalizeQAplots, false, fileColor);
852  }
853 
854  // Draw dz and dxy histograms
855  for (int iIov = 0; iIov < nIov; iIov++) {
856  if (!drawPlotsForEachIOV && iIov < nIov - 2)
857  continue;
858  for (int iHistogramType = 0; iHistogramType < knHistogramTypes; iHistogramType++) {
859  if (drawHistogram[iHistogramType]) {
860  double legendX1 = 0.6;
861  double legendY1 = 0.9 - 0.07 * compareFiles;
862  double legendX2 = 0.9;
863  double legendY2 = 0.9;
864  if (iHistogramType == kDxy || iHistogramType == kDz) {
865  legendX1 = 0.4;
866  legendY1 = 0.4 - 0.07 * compareFiles + 0.07 * (compareFiles / 4);
867  legendX2 = 0.7;
868  legendY2 = 0.4 + 0.07 * (compareFiles / 4);
869  }
870 
871  legend[0] = new TLegend(legendX1, legendY1, legendX2, legendY2);
872  legend[0]->SetFillStyle(0);
873  legend[0]->SetBorderSize(0);
874  legend[0]->SetTextSize(0.05);
875  legend[0]->SetTextFont(62);
876 
877  if (jetHtHistograms[0][iHistogramType][iIov] != nullptr) {
878  for (int iFile = 0; iFile < compareFiles; iFile++) {
879  histogramSearchArray[iFile] = jetHtHistograms[iFile][iHistogramType][iIov];
880  }
881 
882  std::tie(minZoomY, maxZoomY) = findHistogramYaxisRange(histogramSearchArray);
883  jetHtHistograms[0][iHistogramType][iIov]->GetYaxis()->SetRangeUser(minZoomY, maxZoomY);
884  jetHtHistograms[0][iHistogramType][iIov]->SetLineColor(fileColor[0]);
885 
886  drawer->DrawHistogram(jetHtHistograms[0][iHistogramType][iIov],
887  histogramXaxis[iHistogramType],
888  "Tracks",
889  iovLegend.at(iIov).Data());
890  legend[0]->AddEntry(jetHtHistograms[0][iHistogramType][iIov], legendComment[0], "l");
891 
892  for (int iFile = 1; iFile < compareFiles; iFile++) {
893  if (jetHtHistograms[iFile][iHistogramType][iIov] != nullptr) {
894  jetHtHistograms[iFile][iHistogramType][iIov]->SetLineColor(fileColor[iFile]);
895  jetHtHistograms[iFile][iHistogramType][iIov]->Draw("same");
896  legend[0]->AddEntry(jetHtHistograms[iFile][iHistogramType][iIov], legendComment[iFile], "l");
897  }
898  }
899 
900  legend[0]->Draw();
901 
902  // Save the figures
903  if (saveFigures) {
904  gPad->GetCanvas()->SaveAs(Form(
905  "output/%s%s_%s.pdf", histogramName[iHistogramType].Data(), saveComment, iovNames.at(iIov).Data()));
906  }
907 
908  } else {
909  std::cout << "No histogram found for: "
910  << Form("%s_%s", iovNames.at(iIov).Data(), histogramName[iHistogramType].Data()) << std::endl;
911  }
912  } // if for drawing histogram
913  } // histogram type loop
914  }
915 
916  // Draw dz and dxy profiles
917  for (int iProfileType = 0; iProfileType < knProfileTypes; iProfileType++) {
918  if (drawProfile[iProfileType]) {
919  // Set the style for IOV integrated histograms
920  for (int iFile = 0; iFile < compareFiles; iFile++) {
921  jetHtProfiles[iFile][iProfileType][nIov - 2]->SetLineColor(fileColor[iFile]);
922  jetHtProfiles[iFile][iProfileType][nIov - 2]->SetLineWidth(2);
923  jetHtProfiles[iFile][iProfileType][nIov - 2]->SetLineStyle(2);
924  jetHtProfiles[iFile][iProfileType][nIov - 2]->GetYaxis()->SetRangeUser(profileZoomLow[iProfileType],
925  profileZoomHigh[iProfileType]);
926  }
927 
928  // Drawing plots for each IOV.
929  if (drawPlotsForEachIOV) {
930  for (int iIov = 0; iIov < nIov - 2; iIov = iIov + nIovInOnePlot) {
931  noIovFound = true;
932  iLegend = 0;
933  canvasDrawn = false;
934  nNullHistograms = 0;
935 
936  // If we have more than one file, draw all files to the same figure. Otherwise use the nIovInOnePlot variable for the single file.
937  // Set up the IOV:s or files to be drawn to the current plot
938  for (int iFile = 0; iFile < compareFiles; iFile++) {
939  skipColor = 0;
940  for (int iSamePlot = 0; iSamePlot < nIovInOnePlot; iSamePlot++) {
941  if (iIov + iSamePlot >= nIov - 2)
942  break; // Do not draw again all or central references
943  if (jetHtProfiles[iFile][iProfileType][iIov + iSamePlot] != nullptr) {
944  if (nIovInOnePlot > 1) {
945  if (colors[iFile + iSamePlot] == fileColor[0])
946  skipColor++;
947  jetHtProfiles[iFile][iProfileType][iIov + iSamePlot]->SetLineColor(colors[skipColor + iSamePlot]);
948  } else {
949  jetHtProfiles[iFile][iProfileType][iIov + iSamePlot]->SetLineColor(fileColor[iFile + iSamePlot]);
950  }
951  jetHtProfiles[iFile][iProfileType][iIov + iSamePlot]->SetLineWidth(2);
952  noIovFound = false;
953  } else {
954  std::cout << "No histogram found for: "
955  << Form("%s_%s", iovNames.at(iIov).Data(), profileName[iProfileType].Data()) << std::endl;
956  nNullHistograms++;
957  }
958  }
959  }
960 
961  if (noIovFound)
962  continue;
963 
964  // Setup legends. There are four different configuration.
965  // 1) Draw several files in one plot, include reference distribution from all runs
966  // 2) Draw several files in one plot, do not include reference distribution from all runs
967  // 3) Draw several IOVs in one plot, include reference distribution from all runs
968  // 4) Draw several IOVs in one plot, do not include reference distribution from all runs
969  // Each setup needs slightly different configuration for the legends to look good
970 
971  // First determine the number of drawns histograms and how many of them should be drawn to left and right, if the legend is split
972  nDrawnHistograms = drawReferenceProfile * compareFiles + nIovInOnePlot * compareFiles - nNullHistograms;
973  nLeftLegend = TMath::Ceil(nDrawnHistograms / 2.0);
974  nRightLegend = TMath::Floor(nDrawnHistograms / 2.0);
975 
976  // Make adjustments to the number of drawn histograms in some special cases
977  if (!drawReferenceProfile) {
978  if (compareFiles > 1) {
979  nLeftLegend = 1;
980  nRightLegend = nDrawnHistograms;
981  }
982  if (nIovInOnePlot > 1) {
983  if (nLeftLegend > nRightLegend) {
984  nRightLegend++;
985  } else {
986  nLeftLegend++;
987  }
988  }
989  }
990 
991  // The order of columns changes for different configurations. Define it here
992  columnOrder[0] = 0;
993  columnOrder[1] = 1;
994  columnOrder[2] = 2;
995  if (compareFiles > 1) {
996  columnOrder[0] = 1;
997  columnOrder[1] = 2;
998  columnOrder[2] = 0;
999  if (!drawReferenceProfile) {
1000  columnOrder[0] = 1;
1001  columnOrder[1] = 0;
1002  columnOrder[2] = 2;
1003  }
1004  }
1005 
1006  // Define three different legends. Their position is determined by the specific configuration
1007  legendX1 = 0.19 + 0.24 * drawReferenceProfile * (compareFiles > 1) + profileLegendShiftTotalX +
1008  profileLegendShiftColumnX[columnOrder[0]];
1009  legendY1 = 0.9 - (profileLegendTextSize + 0.02) * nLeftLegend + profileLegendShiftTotalY +
1010  profileLegendShiftColumnY[columnOrder[0]];
1011  legendX2 = 0.41 + 0.24 * drawReferenceProfile * (compareFiles > 1) + profileLegendShiftTotalX +
1012  profileLegendShiftColumnX[columnOrder[0]];
1013  legendY2 = 0.9 + profileLegendShiftTotalY + profileLegendShiftColumnY[columnOrder[0]];
1014  ;
1015  legend[0] = new TLegend(legendX1, legendY1, legendX2, legendY2);
1016  legend[0]->SetFillStyle(0);
1017  legend[0]->SetBorderSize(0);
1018  legend[0]->SetTextSize(profileLegendTextSize);
1019  legend[0]->SetTextFont(profileLegendTextFont);
1020 
1021  legendX1 = 0.55 - 0.24 * !drawReferenceProfile * (compareFiles > 1) + profileLegendShiftTotalX +
1022  profileLegendShiftColumnX[columnOrder[1]];
1023  legendY1 = 0.9 - (profileLegendTextSize + 0.02) * nRightLegend + profileLegendShiftTotalY +
1024  profileLegendShiftColumnY[columnOrder[1]];
1025  legendX2 = 0.77 - 0.24 * !drawReferenceProfile * (compareFiles > 1) + profileLegendShiftTotalX +
1026  profileLegendShiftColumnX[columnOrder[1]];
1027  legendY2 = 0.9 + profileLegendShiftTotalY + profileLegendShiftColumnY[columnOrder[1]];
1028  legend[1] = new TLegend(legendX1, legendY1, legendX2, legendY2);
1029  legend[1]->SetFillStyle(0);
1030  legend[1]->SetBorderSize(0);
1031  legend[1]->SetTextSize(profileLegendTextSize);
1032  legend[1]->SetTextFont(profileLegendTextFont);
1033 
1034  legendX1 = 0.13 + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[2]];
1035  legendY1 = 0.9 - (profileLegendTextSize + 0.02) * nLeftLegend + profileLegendShiftTotalY +
1036  profileLegendShiftColumnY[columnOrder[2]];
1037  legendX2 = 0.49 + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[2]];
1038  legendY2 = 0.9 + profileLegendShiftTotalY + profileLegendShiftColumnY[columnOrder[2]];
1039  legend[2] = new TLegend(legendX1, legendY1, legendX2, legendY2);
1040  legend[2]->SetFillStyle(0);
1041  legend[2]->SetBorderSize(0);
1042  legend[2]->SetTextSize(profileLegendTextSize);
1043  legend[2]->SetTextFont(profileLegendTextFont);
1044 
1045  // First, draw the reference over all runs to the plot
1046  if (drawReferenceProfile) {
1047  for (int iFile = 0; iFile < compareFiles; iFile++) {
1048  if (jetHtProfiles[iFile][iProfileType][nIov - 2] != nullptr) {
1049  if (!canvasDrawn) {
1050  drawer->DrawHistogram(jetHtProfiles[iFile][iProfileType][nIov - 2],
1051  profileXaxis[iProfileType],
1052  Form("#LT#sigma(%s)#GT (#mum)", profileYaxis[iProfileType].Data()),
1053  " ",
1054  "HIST,C");
1055  canvasDrawn = true;
1056  } else {
1057  jetHtProfiles[iFile][iProfileType][nIov - 2]->Draw("same,HIST,C");
1058  }
1059  legendString = legendTextForAllRuns.Data();
1060  if (nIovInOnePlot > 1)
1061  legendString.Append(Form(" (%s)", legendComment[iFile].Data()));
1062  legend[0]->AddEntry(jetHtProfiles[iFile][iProfileType][nIov - 2], legendString.Data(), "l");
1063  legend[2]->AddEntry((TObject *)nullptr, Form("%s:", legendComment[iFile].Data()), "");
1064  }
1065  }
1066  }
1067 
1068  // If we draw several histograms per IOV, add the alignment to the legend if not included in the reference
1069  if (!drawReferenceProfile && (nIovInOnePlot > 1)) {
1070  legend[0]->AddEntry((TObject *)nullptr, legendComment[0].Data(), "");
1071  }
1072 
1073  // Draw defined number of different IOVs to the plot
1074  for (int iFile = 0; iFile < compareFiles; iFile++) {
1075  iHistogram = 0; // This variable takes into account null histograms in case of legend splitting
1076  for (int iSamePlot = 0; iSamePlot < nIovInOnePlot; iSamePlot++) {
1077  if (iIov + iSamePlot >= nIov - 2)
1078  break; // Do not draw again all or central references
1079  if (jetHtProfiles[iFile][iProfileType][iIov + iSamePlot] != nullptr) {
1080  if (!canvasDrawn) {
1081  drawer->DrawHistogram(jetHtProfiles[iFile][iProfileType][iIov + iSamePlot],
1082  profileXaxis[iProfileType],
1083  Form("#LT#sigma(%s)#GT (#mum)", profileYaxis[iProfileType].Data()),
1084  " ");
1085  canvasDrawn = true;
1086  } else {
1087  jetHtProfiles[iFile][iProfileType][iIov + iSamePlot]->Draw("same");
1088  }
1089 
1090  // Different legend texts if drawing several files or several IOVs in one plot
1091  if (compareFiles > 1) {
1092  legendString = iovLegend.at(iIov + iSamePlot).Data();
1093  if (!drawReferenceProfile)
1094  legendString.Append(Form(" (%s)", legendComment[iFile].Data()));
1095  legend[1]->AddEntry(jetHtProfiles[iFile][iProfileType][iIov + iSamePlot], legendString.Data(), "l");
1096  } else {
1097  if (iHistogram + 1 == nLeftLegend)
1098  iLegend = 1;
1099  legend[iLegend]->AddEntry(
1100  jetHtProfiles[iFile][iProfileType][iIov + iSamePlot], iovLegend.at(iIov + iSamePlot), "l");
1101  }
1102  iHistogram++;
1103  }
1104  }
1105  }
1106 
1107  // Draw the legends
1108  legend[0]->Draw();
1109  legend[1]->Draw();
1110  if (drawReferenceProfile && compareFiles > 1)
1111  legend[2]->Draw();
1112 
1113  // Save the figures
1114  if (saveFigures) {
1115  gPad->GetCanvas()->SaveAs(Form("output/%s%s_iov%d-%d.pdf",
1116  profileName[iProfileType].Data(),
1117  saveComment,
1118  iovVector.at(iIov),
1119  iovVector.at(std::min(iIov + nIovInOnePlot, nIov - 2)) - 1));
1120  }
1121 
1122  // Add the current IOV to the IOV list to be used with the slide generation script
1123  if (makeIovListForSlides && (iProfileType == profileIndexForIovList)) {
1124  iovFileForSlides << Form("%d-%d",
1125  iovVector.at(iIov),
1126  iovVector.at(std::min(iIov + nIovInOnePlot, nIov - 2)) - 1)
1127  << "\n";
1128  }
1129 
1130  } // iov loop for drawing
1131  } // if for drawing profiles for each IOV
1132 
1133  // First, setup the legends for the all runs plots
1134  doNotDrawEta = (!drawCentralEtaSummaryProfile || iProfileType == kDxyErrorVsEta || iProfileType == kDzErrorVsEta);
1135 
1136  // The order of columns changes for different configurations. Define it here
1137  columnOrder[0] = 1;
1138  columnOrder[1] = 2;
1139  columnOrder[2] = 0;
1140  if (doNotDrawEta) {
1141  columnOrder[0] = 1;
1142  columnOrder[1] = 0;
1143  columnOrder[2] = 2;
1144  }
1145 
1146  // Define three different legends. Their position is determined by the specific configuration
1147  legendX1 = 0.48 + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[0]];
1148  legendY1 = 0.9 - (profileLegendTextSize + 0.02) * compareFiles + profileLegendShiftTotalY +
1149  profileLegendShiftColumnY[columnOrder[0]];
1150  legendX2 = 0.7 + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[0]];
1151  legendY2 = 0.9 + profileLegendShiftTotalY + profileLegendShiftColumnY[columnOrder[0]];
1152  legend[0] = new TLegend(legendX1, legendY1, legendX2, legendY2);
1153  legend[0]->SetFillStyle(0);
1154  legend[0]->SetBorderSize(0);
1155  legend[0]->SetTextSize(profileLegendTextSize);
1156  legend[0]->SetTextFont(profileLegendTextFont);
1157 
1158  legendX1 = 0.65 - 0.25 * doNotDrawEta + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[1]];
1159  legendY1 = 0.9 - (profileLegendTextSize + 0.02) * compareFiles + profileLegendShiftTotalY +
1160  profileLegendShiftColumnY[columnOrder[1]];
1161  legendX2 = 0.87 - 0.25 * doNotDrawEta + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[1]];
1162  legendY2 = 0.9 + profileLegendShiftTotalY + profileLegendShiftColumnY[columnOrder[1]];
1163  legend[1] = new TLegend(legendX1, legendY1, legendX2, legendY2);
1164  legend[1]->SetFillStyle(0);
1165  legend[1]->SetBorderSize(0);
1166  legend[1]->SetTextSize(profileLegendTextSize);
1167  legend[1]->SetTextFont(profileLegendTextFont);
1168 
1169  legendX1 = 0.18 + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[2]];
1170  legendY1 = 0.9 - (profileLegendTextSize + 0.02) * compareFiles + profileLegendShiftTotalY +
1171  profileLegendShiftColumnY[columnOrder[2]];
1172  legendX2 = 0.54 + profileLegendShiftTotalX + profileLegendShiftColumnX[columnOrder[2]];
1173  legendY2 = 0.9 + profileLegendShiftTotalY + profileLegendShiftColumnY[columnOrder[2]];
1174  legend[2] = new TLegend(legendX1, legendY1, legendX2, legendY2);
1175  legend[2]->SetFillStyle(0);
1176  legend[2]->SetBorderSize(0);
1177  legend[2]->SetTextSize(profileLegendTextSize);
1178  legend[2]->SetTextFont(profileLegendTextFont);
1179 
1180  // First, draw histograms from all runs to the plot
1181  canvasDrawn = false;
1182  for (int iFile = 0; iFile < compareFiles; iFile++) {
1183  if (jetHtProfiles[iFile][iProfileType][nIov - 2] != nullptr) {
1184  jetHtProfiles[iFile][iProfileType][nIov - 2]->SetLineStyle(
1185  1); // Reset the line style after IOV specific plots
1186  if (!canvasDrawn) {
1187  drawer->DrawHistogram(jetHtProfiles[iFile][iProfileType][nIov - 2],
1188  profileXaxis[iProfileType],
1189  Form("#LT#sigma(%s)#GT (#mum)", profileYaxis[iProfileType].Data()),
1190  plotTitle);
1191  canvasDrawn = true;
1192  } else {
1193  jetHtProfiles[iFile][iProfileType][nIov - 2]->Draw("same");
1194  }
1195  legendString = legendTextForAllRuns.Data();
1196  if (doNotDrawEta)
1197  legendString.Append(Form(" (%s)", legendComment[iFile].Data()));
1198  legend[1]->AddEntry(jetHtProfiles[iFile][iProfileType][nIov - 2], legendString.Data(), "l");
1199  legend[2]->AddEntry((TObject *)nullptr, Form("%s:", legendComment[iFile].Data()), "");
1200  }
1201  }
1202 
1203  // If there is no canvas, nothing can be done. Break out of the if-statement
1204  if (!canvasDrawn)
1205  break;
1206 
1207  // If we want to draw the central eta as reference, draw them as a dashed line
1208  if (!doNotDrawEta) {
1209  for (int iFile = 0; iFile < compareFiles; iFile++) {
1210  if (jetHtProfiles[iFile][iProfileType][nIov - 1] != nullptr) {
1211  jetHtProfiles[iFile][iProfileType][nIov - 1]->SetLineColor(fileColor[iFile]);
1212  jetHtProfiles[iFile][iProfileType][nIov - 1]->SetLineWidth(2);
1213  jetHtProfiles[iFile][iProfileType][nIov - 1]->SetLineStyle(2);
1214  jetHtProfiles[iFile][iProfileType][nIov - 1]->Draw("same,HIST,C");
1215  legend[0]->AddEntry(jetHtProfiles[iFile][iProfileType][nIov - 1], "|#eta| < 1", "l");
1216  }
1217  }
1218  }
1219 
1220  legend[1]->Draw();
1221  if (!doNotDrawEta) {
1222  legend[0]->Draw();
1223  legend[2]->Draw();
1224  }
1225 
1226  // Save the figures
1227  if (saveFigures) {
1228  gPad->GetCanvas()->SaveAs(Form("output/%s%s_allIovs.pdf", profileName[iProfileType].Data(), saveComment));
1229  }
1230  } // if for drawing profile
1231  } // profile type loop
1232 
1233  // Close the output file
1234  if (makeIovListForSlides)
1235  iovFileForSlides.close();
1236 
1237  // Trend plots
1238  TLegend *trendLegend;
1239  drawer->SetCanvasSize(trendCanvasWidth, trendCanvasHeight);
1240  drawer->SetLeftMargin(trendMarginLeft);
1241  drawer->SetRightMargin(trendMarginRight);
1242  drawer->SetTopMargin(trendMarginTop);
1243  drawer->SetBottomMargin(trendMarginBottom);
1244  drawer->SetTitleOffsetX(trendTitleOffsetX);
1245  drawer->SetTitleOffsetY(trendTitleOffsetY);
1246  drawer->SetTitleSizeX(trendTitleSizeX);
1247  drawer->SetTitleSizeY(trendTitleSizeY);
1248  drawer->SetLabelOffsetX(trendLabelOffsetX);
1249  drawer->SetLabelOffsetY(trendLabelOffsetY);
1250  drawer->SetLabelSizeX(trendLabelSizeX);
1251  drawer->SetLabelSizeY(trendLabelSizeY);
1252  double lumiX;
1253  TLine *lumiLine;
1254 
1255  // Writed for adding tags to trend plots
1256  TLatex *tagWriter = new TLatex();
1257  tagWriter->SetTextFont(trendTagTextFont);
1258  tagWriter->SetTextSize(trendTagTextSize);
1259 
1260  TString xTitle = "Run index";
1261  if (useLuminosityForTrends)
1262  xTitle = "Delivered luminosity (1/fb)";
1263 
1264  for (int iTrend = 0; iTrend < knTrendTypes; iTrend++) {
1265  if (!drawTrend[iTrend])
1266  continue;
1267  for (int iWidePt = 0; iWidePt < nWidePtBins; iWidePt++) {
1268  legendX1 = 0.65 + trendLegendShiftTotalX;
1269  legendY1 = 0.83 - (profileLegendTextSize + 0.02) * compareFiles + trendLegendShiftTotalY;
1270  legendX2 = 0.9 + trendLegendShiftTotalX;
1271  legendY2 = 0.9 + trendLegendShiftTotalY;
1272  trendLegend = new TLegend(legendX1, legendY1, legendX2, legendY2);
1273  trendLegend->SetFillStyle(0);
1274  trendLegend->SetBorderSize(0);
1275  trendLegend->SetTextSize(trendLegendTextSize);
1276  trendLegend->SetTextFont(trendLegendTextFont);
1277  trendLegend->SetHeader(
1278  Form("%s error trend for p_{T} > %.0f GeV", profileYaxis[iTrend + 6].Data(), widePtBinBorders.at(iWidePt)));
1279 
1280  for (int iFile = 0; iFile < compareFiles; iFile++) {
1281  gBigTrend[iFile][iTrend][iWidePt]->SetMarkerColor(fileColor[iFile]);
1282  gBigTrend[iFile][iTrend][iWidePt]->SetMarkerStyle(fileMarkerStyle[iFile]);
1283  gBigTrend[iFile][iTrend][iWidePt]->SetMarkerSize(fileMarkerSize[iFile]);
1284  if (copyErrorColor[iFile])
1285  gBigTrend[iFile][iTrend][iWidePt]->SetLineColor(fileColor[iFile]);
1286 
1287  if (iFile == 0) {
1288  drawer->DrawGraphCustomAxes(gBigTrend[iFile][iTrend][iWidePt],
1289  0,
1290  nRuns,
1291  trendZoomLow[iTrend],
1292  trendZoomHigh[iTrend],
1293  xTitle,
1294  Form("#LT #sigma(%s) #GT", profileYaxis[iTrend + 6].Data()),
1295  " ",
1296  "ap");
1297  } else {
1298  gBigTrend[iFile][iTrend][iWidePt]->Draw("p,same");
1299  }
1300 
1301  trendLegend->AddEntry(gBigTrend[iFile][iTrend][iWidePt], legendComment[iFile].Data(), "p");
1302 
1303  } // File loop
1304 
1305  trendLegend->Draw();
1306 
1307  // Draw lines for different data taking years
1308  if (drawYearLines) {
1309  for (int thisRun : linePosition) {
1310  lumiX = luminosityBeforeRun(lumiPerIovWithSkips, iovVector, thisRun);
1311  lumiLine = new TLine(lumiX, trendZoomLow[iTrend], lumiX, trendZoomHigh[iTrend]);
1312  lumiLine->SetLineColor(yearLineColor);
1313  lumiLine->SetLineWidth(yearLineWidth);
1314  lumiLine->SetLineStyle(yearLineStyle);
1315  lumiLine->Draw();
1316  }
1317  }
1318 
1319  // Draw all defined tags
1320  if (drawTrendTag) {
1321  for (std::vector<std::string>::size_type iTag = 0; iTag < trendTagText.size(); iTag++) {
1322  tagWriter->DrawLatexNDC(
1323  trendTagPositionX.at(iTag), trendTagPositionY.at(iTag), trendTagText.at(iTag).c_str());
1324  }
1325  }
1326 
1327  // Save the figures
1328  if (saveFigures) {
1329  gPad->GetCanvas()->SaveAs(Form(
1330  "output/%sTrendPtOver%.0f%s.pdf", trendName[iTrend].Data(), widePtBinBorders.at(iWidePt), saveComment));
1331  }
1332 
1333  } // Wide pT loop
1334  } // Trend type loop
1335 }
1336 
1337 /*
1338  * Main program
1339  */
1340 int main(int argc, char **argv) {
1341  //==== Read command line arguments =====
1343  options.helper(argc, argv);
1344  options.parser(argc, argv);
1345 
1346  // Run the program
1347  jetHtPlotter(options.config);
1348 }
std::vector< std::string > trendTagText() const
bool drawProfile(const int iProfile) const
double profileLegendShiftColumnY(const int iColumn) const
std::vector< double > trendTagPositionX() const
void SetCanvasSize(int width, int height)
Definition: JDrawer.h:962
std::vector< int > runsForLines() const
void SetLabelOffsetX(double offset)
Definition: JDrawer.h:788
double trendZoomLow(const int iTrend) const
void SetLeftMargin(double margin)
Definition: JDrawer.h:749
void SetLabelSizeY(double size)
Definition: JDrawer.h:797
void drawSingleHistogram(TH1D *histogram[kMaxFiles], const char *saveName, bool saveFigures, TString comment[kMaxFiles], int legendPosition, bool normalize, bool logScale, int color[kMaxFiles])
Definition: jetHtPlotter.cc:40
bool copyErrorColor(const int iFile) const
int markerStyle(const int iFile) const
void jetHtPlotter(std::string configurationFileName)
uint16_t size_type
std::tuple< std::vector< std::string >, std::vector< int > > ptHatFilesAndValues(const char *inputFile)
const char * iovListForSlides() const
double trendZoomHigh(const int iTrend) const
double luminosityBeforeRun(std::vector< double > lumiPerIov, std::vector< int > iovVector, int runNumber)
const int kMaxFiles
Definition: jetHtPlotter.cc:25
void SetLabelSizeX(double size)
Definition: JDrawer.h:794
void SetTitleOffsetY(double offset)
Definition: JDrawer.h:779
void SetTitleSizeX(double size)
Definition: JDrawer.h:782
void DrawGraphCustomAxes(TGraph *graph, double xlow, double xhigh, double ylow, double yhigh, const char *xTitle="", const char *yTitle="", const char *title="", const char *drawOption="")
Definition: JDrawer.h:421
bool drawTrend(const int iTrend) const
std::string legendComment(const int iComment) const
void SetTopMargin(double margin)
Definition: JDrawer.h:758
void SetTitleSizeY(double size)
Definition: JDrawer.h:785
void SetBottomMargin(double margin)
Definition: JDrawer.h:755
Double_t margin
bool drawHistogram(const int iHistogram) const
TH1 * ptHatCombinedHistogram(std::vector< TFile *> ptHatFiles, std::vector< int > ptHatValues, const char *histogramName)
int markerColor(const int iFile) const
std::vector< double > scaleGraphByLuminosity(TGraphErrors *runGraph, std::vector< double > lumiPerIov, bool skipMissingRuns)
const char * lumiPerIovFile() const
void SetRightMargin(double margin)
Definition: JDrawer.h:752
int markerSize(const int iFile) const
double profileLegendShiftColumnX(const int iColumn) const
std::tuple< double, double > findHistogramYaxisRange(TH1D *histogram[kMaxFiles])
void SetLogY(bool log=true)
Definition: JDrawer.h:876
std::string legendTextForAllRuns() const
float normalize(float in)
Definition: MLPFModel.cc:207
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
Definition: colors.py:1
const char * iovListMode() const
void SetLabelOffsetY(double offset)
Definition: JDrawer.h:791
void SetTitleOffsetX(double offset)
Definition: JDrawer.h:776
int main(int argc, char **argv)
double profileZoomHigh(const int iProfile) const
const char * saveComment() const
void DrawHistogram(TH1 *histo, const char *xTitle, const char *yTitle, const char *title="", const char *drawOption="")
Definition: JDrawer.h:271
std::tuple< std::vector< int >, std::vector< double >, std::vector< TString >, std::vector< TString > > runAndLumiLists(const char *inputFile, const char *iovListMode)
std::vector< double > widePtBinBorders() const
void readJsonFile(const std::string fileName)
std::vector< double > trendTagPositionY() const
double profileZoomLow(const int iProfile) const
T * Get(Args... args)
Definition: Trend.h:122
std::string inputFile(const int iFile) const