CMS 3D CMS Logo

Trend.cc
Go to the documentation of this file.
1 #include <cassert> // you may want to replace all assertions by clear error messages
2 #include <cstdlib>
3 
4 #include <vector>
5 #include <iostream>
6 #include <fstream>
7 #include <string>
8 
9 #include "TLine.h"
10 #include "TLatex.h"
11 #include "TString.h"
12 #include "TGraphErrors.h"
13 #include "TH1.h"
14 
15 #include "Alignment/OfflineValidation/plugins/ColorParser.C"
16 #include "Alignment/OfflineValidation/plugins/StyleParser.C"
18 
19 using namespace std;
20 namespace fs = boost::filesystem;
21 namespace pt = boost::property_tree;
22 
23 Run2Lumi::Run2Lumi(fs::path file, int first, int last, float convertUnit)
24  : firstRun(first), lastRun(last), convertUnit(convertUnit) {
25  cout << __func__ << endl;
26  assert(first < last);
27 
28  cout << file << endl;
29  assert(fs::exists(file));
30 
31  ifstream f(file);
32  int run;
33  while (f >> run >> runs[run])
34  ;
35  f.close();
36 }
37 
38 float Run2Lumi::operator()(int run1, int run2) const
39 
40 {
41  float sum = 0.;
42  for (auto& run : runs) {
43  if (run.first < run1)
44  continue;
45  if (run.first >= run2)
46  break;
47  sum += run.second;
48  }
49  return sum / convertUnit; // conversion from e.g. /pb to /fb
50 }
51 
52 float Run2Lumi::operator()(int run) const { return operator()(firstRun, run); }
53 
54 float Run2Lumi::operator()() const { return operator()(firstRun, lastRun); }
55 
56 template <typename T>
57 void CopyStyle(T* objIn, T* objOut) {
58  objOut->SetLineColor(objIn->GetLineColor());
59  objOut->SetMarkerColor(objIn->GetMarkerColor());
60  objOut->SetFillColorAlpha(objIn->GetFillColor(), 0.2); // TODO??
61 
62  objOut->SetLineStyle(objIn->GetLineStyle());
63  objOut->SetMarkerStyle(objIn->GetMarkerStyle());
64  objOut->SetFillStyle(objIn->GetFillStyle());
65 
66  objOut->SetLineWidth(objIn->GetLineWidth());
67  objOut->SetMarkerSize(objIn->GetMarkerSize());
68 }
69 
70 TGraph* Run2Lumi::operator()(TGraph* gIn) const {
71  assert(gIn != nullptr);
72 
73  vector<float> x, y, ex, ey;
74  int n = gIn->GetN();
75  for (int i = 0; i < n - 1; ++i) {
76  int currentRun = gIn->GetPointX(i);
77  if (currentRun < firstRun)
78  continue;
79  if (currentRun >= lastRun)
80  break;
81 
82  int nextRun = gIn->GetPointX(i + 1);
83 
84  auto lumi_edge = operator()(firstRun, currentRun), lumi_width = operator()(currentRun, nextRun);
85  x.push_back(lumi_edge + lumi_width / 2);
86  ex.push_back(lumi_width / 2);
87 
88  auto point = gIn->GetPointY(i), error = gIn->GetErrorY(i);
89  y.push_back(point);
90  ey.push_back(error);
91  }
92 
93  auto N = x.size();
94  assert(N == y.size() && N == ex.size() && N == ey.size());
95  TGraph* gOut = new TGraphErrors(N, x.data(), y.data(), ex.data(), ey.data());
96  gOut->SetTitle(gIn->GetTitle());
97  CopyStyle(gIn, gOut);
98  return gOut;
99 }
100 
101 TH1* Run2Lumi::operator()(TH1* hIn) const {
102  vector<float> edges, contents, errors;
103  edges.push_back(0);
104  int N = hIn->GetNbinsX();
105  for (int i = 1; i <= N; ++i) {
106  auto nextRun = hIn->GetBinLowEdge(i + 1);
107  if (nextRun < firstRun)
108  continue;
109  if (nextRun >= lastRun)
110  break;
111 
112  edges.push_back(operator()(nextRun));
113 
114  auto content = hIn->GetBinContent(i), error = hIn->GetBinError(i);
115  contents.push_back(content);
116  errors.push_back(error);
117  }
118 
119  N = edges.size() - 1;
120  TString name = hIn->GetName();
121  name += "_byLumi";
122  TH1* hOut = new TH1F(name, hIn->GetTitle(), N, edges.data());
123  for (int i = 1; i <= N; ++i) {
124  hOut->SetBinContent(i, contents[i - 1]);
125  hOut->SetBinError(i, errors[i - 1]);
126  }
127  CopyStyle(hIn, hOut);
128  return hOut;
129 }
130 
131 Trend::Trend(const char* name,
132  const char* dir,
133  const char* title,
134  const char* ytitle,
135  float ymin,
136  float ymax,
137  pt::ptree& json,
138  const Run2Lumi& GetLumiFunctor,
139  const char* lumiAxisType)
140  : c(name, title, 2000, 800),
141  outputDir(Form("%s", dir)),
142  lgd(0.7, 0.65, 0.97, 0.89, "", "NDC"),
143  JSON(json),
144  GetLumi(GetLumiFunctor),
145  lumiType(lumiAxisType) {
146  cout << __func__ << endl;
147 
148  if (JSON.count("CMSlabel"))
149  CMS = Form("#scale[1.1]{#bf{CMS}} #it{%s}", JSON.get<string>("CMSlabel").data());
150 
151  if (JSON.get_child("trends").count("TitleCanvas"))
152  lumi = Form("#scale[0.8]{%s}", JSON.get_child("trends").get<string>("TitleCanvas").data());
153 
154  assert(ymin < ymax);
155  float xmax = GetLumi(GetLumi.firstRun, GetLumi.lastRun);
156  if (JSON.get_child("trends").count("plotUnit"))
157  plotUnit = JSON.get_child("trends").get<string>("plotUnit");
158  const char* axistitles = Form(";%s luminosity [%s^{-1} ];%s", lumiType, plotUnit.c_str(), ytitle);
159  auto frame = c.DrawFrame(0., ymin, xmax, ymax, axistitles);
160  frame->GetYaxis()->SetTitleOffset(0.8);
161  frame->GetYaxis()->SetTickLength(0.01);
162  frame->GetXaxis()->SetLabelSize(fontsize);
163  frame->GetXaxis()->SetTitleSize(fontsize);
164  frame->GetYaxis()->SetLabelSize(fontsize);
165  frame->GetYaxis()->SetTitleSize(fontsize);
166  lgd.SetTextSize(fontsize);
167  cout << "frame->GetXaxis()->GetLabelSize() = " << frame->GetXaxis()->GetLabelSize() << endl;
168  cout << "frame->GetXaxis()->GetTitleSize() = " << frame->GetXaxis()->GetTitleSize() << endl;
169 
170  if (ymax > 0 && ymin < 0) {
171  cout << "Plotting horizontal line at zero" << endl;
172  TLine l;
173  l.SetLineColor(kBlack);
174  l.SetLineStyle(kDashed);
175  l.DrawLine(0., 0., xmax, 0.);
176  }
177 
178  c.SetTicks(1, 1);
179  c.SetRightMargin(0.015);
180  c.SetLeftMargin(0.07);
181  c.SetTopMargin(0.07);
182 
183  // plot vertical lines (typically pixel template transitions)
184  pt::ptree lines = JSON.get_child("trends.lines");
185  for (auto& type : lines) {
186  auto line = type.second.get_child_optional("line");
187  auto runs = type.second.get_child_optional("runs");
188  if (!line || !runs)
189  continue;
190 
191  auto v = new TLine;
192 
193  auto style = line->get_optional<string>("style");
194  if (style)
195  v->SetLineStyle(StyleParser(*style));
196 
197  auto color = line->get_optional<string>("color");
198  if (color)
199  v->SetLineColor(ColorParser(*color));
200 
201  auto width = line->get_optional<int>("width");
202  if (width)
203  v->SetLineWidth(*width);
204 
205  auto title = line->get_optional<string>("title");
206  if (title)
207  lgd.AddEntry(v, title->c_str(), "l");
208 
209  for (auto& run : *runs) {
210  auto currentRun = run.second.get_value<int>();
211 
212  auto lumi = GetLumi(GetLumi.firstRun, currentRun);
213  //cout << currentRun << '\t' << lumi << endl;
214  if (lumi > 0)
215  v->DrawLine(lumi, ymin, lumi, ymax);
216  }
217  }
218 }
219 
220 void Trend::operator()(TObject* obj, TString drawOpt, TString lgdOpt, bool fullRange) {
221  cout << __func__ << endl;
222  c.cd();
223 
224  TString classname = obj->ClassName();
225  if (classname.Contains("TGraph")) {
226  auto g = dynamic_cast<TGraph*>(obj);
227  int n = g->GetN();
228  cout << g->GetPointX(n - 1) << ' ' << GetLumi.lastRun;
229  if (fullRange) {
230  cout << " -> adding one point" << endl;
231  g->Set(n);
232  g->SetPoint(n, GetLumi.lastRun, 0);
233  } else
234  cout << " -> hole between end of graph and right edge" << endl;
235  g = GetLumi(g);
236  g->Draw("same" + drawOpt);
237  } else if (classname.Contains("TH1")) {
238  auto h = dynamic_cast<TH1*>(obj);
239  // TODO: full range?
240  h = GetLumi(h);
241  h->Draw("same" + drawOpt);
242  } else {
243  cerr << "No implementation for `" << classname << "`\n";
244  exit(EXIT_FAILURE);
245  }
246 
247  TString name = c.GetName();
248  name.ReplaceAll("vs_run", "vs_lumi");
249  c.SetName(name);
250 
251  TString title = obj->GetTitle();
252  if (title == "")
253  return;
254  lgd.AddEntry(obj, "", lgdOpt);
255 }
256 
258  cout << __func__ << endl;
259 
260  c.cd();
261  lgd.Draw();
262 
263  float l = c.GetLeftMargin(), t = c.GetTopMargin(), r = c.GetRightMargin(), lumiTextOffset = 0.2;
264 
265  TLatex latex;
266  latex.SetNDC();
267  latex.SetTextFont(42);
268 
269  latex.SetTextAlign(11);
270  latex.DrawLatex(l, 1 - t + lumiTextOffset * t, CMS);
271 
272  latex.SetTextAlign(31);
273  latex.DrawLatex(1 - r, 1 - t + lumiTextOffset * t, lumi);
274 
275  // plot labels
276  latex.SetTextAlign(13);
277  auto totLumi = GetLumi();
278  assert(totLumi > 0);
279  auto posY = 0.88;
280  pt::ptree lines = JSON.get_child("trends.lines");
281  for (auto& type : lines) {
282  auto labels = type.second.get_child_optional("labels");
283  auto runs = type.second.get_child_optional("runs");
284  if (!labels || !runs)
285  continue;
286 
287  auto runIt = runs->begin();
288  auto labelIt = labels->begin();
289  while (runIt != runs->end() && labelIt != labels->end()) {
290  auto currentRun = runIt->second.get_value<int>();
291  auto label = labelIt->second.get_value<string>();
292 
293  auto lumi = max(GetLumi(currentRun), (float)0.01);
294  auto posX = l + (lumi / totLumi) / (l + 1 + r) + 0.02;
295  cout << currentRun << setw(20) << label << setw(20) << lumi << setw(20) << posX << endl;
296  label = "#scale[0.8]{" + label + "}";
297  latex.DrawLatex(posX, posY, label.c_str());
298 
299  ++runIt;
300  ++labelIt;
301  }
302  posY -= 0.06;
303  }
304 
305  c.RedrawAxis();
306  c.SaveAs(Form("%s/%s.pdf", outputDir, c.GetName()), Form("Title:%s", c.GetTitle()));
307 }
nlohmann::json json
Definition: Trend.h:22
void operator()(TObject *obj, TString drawOpt, TString lgdOpt, bool fullRange=true)
Definition: Trend.cc:220
const char * lumiType
Definition: Trend.h:92
Run2Lumi(boost::filesystem::path file, int first, int last, float convertUnit)
Definition: Trend.cc:23
assert(be >=bs)
const int lastRun
last run (excluded!), starting at the max lumi on the x-axis of the trend
Definition: Trend.h:23
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
float fontsize
Definition: Trend.h:84
std::map< int, float > runs
couples of run and corresponding luminosity
Definition: Trend.h:28
float operator()() const
Sums luminosity for [firstRun, lastRun[.
Definition: Trend.cc:54
char const * label
TCanvas c
Definition: Trend.h:86
Struct holding legacy CMS convention for process types.
std::string plotUnit
Definition: Trend.h:82
Definition: style.py:1
const boost::property_tree::ptree JSON
contains coordinate for vertical lines
Definition: Trend.h:90
const char * outputDir
Definition: Trend.h:87
double f[11][100]
#define N
Definition: blowfish.cc:9
const int firstRun
first run, starting at lumi = 0 on the x-axis of the trend
Definition: Trend.h:23
const float convertUnit
Definition: Trend.h:25
Trend(const char *name, const char *dir, const char *title, const char *ytitle, float ymin, float ymax, boost::property_tree::ptree &json, const Run2Lumi &GetLumiFunctor, const char *lumiAxisType)
< constructor, prepares canvas and frame
Definition: Trend.cc:131
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
const Run2Lumi & GetLumi
functor to get luminosity for given subrange
Definition: Trend.h:91
~Trend()
Definition: Trend.cc:257
firstRun
Definition: dataset.py:940
Definition: errors.py:1
TLegend lgd
Definition: Trend.h:88
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
long double T
void CopyStyle(T *objIn, T *objOut)
Definition: Trend.cc:57
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
float lumiTextOffset
Definition: CMS_lumi.h:24
def exit(msg="")