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  assert(first < last);
26 
27  assert(fs::exists(file));
28 
29  ifstream f(file);
30  int run;
31  while (f >> run >> runs[run])
32  ;
33  f.close();
34 }
35 
36 float Run2Lumi::operator()(int run1, int run2) const
37 
38 {
39  float sum = 0.;
40  for (auto& run : runs) {
41  if (run.first < run1)
42  continue;
43  if (run.first >= run2)
44  break;
45  sum += run.second;
46  }
47  return sum / convertUnit; // conversion from e.g. /pb to /fb
48 }
49 
50 float Run2Lumi::operator()(int run) const { return operator()(firstRun, run); }
51 
52 float Run2Lumi::operator()() const { return operator()(firstRun, lastRun); }
53 
54 template <typename T>
55 void CopyStyle(T* objIn, T* objOut) {
56  objOut->SetLineColor(objIn->GetLineColor());
57  objOut->SetLineColor(objIn->GetMarkerColor());
58  objOut->SetMarkerColor(objIn->GetMarkerColor());
59  objOut->SetFillColorAlpha(objIn->GetFillColor(), 0.2); // TODO??
60 
61  objOut->SetLineStyle(objIn->GetLineStyle());
62  objOut->SetMarkerStyle(objIn->GetMarkerStyle());
63  objOut->SetFillStyle(objIn->GetFillStyle());
64 
65  objOut->SetLineWidth(objIn->GetLineWidth());
66  objOut->SetMarkerSize(objIn->GetMarkerSize());
67 }
68 
69 TGraph* Run2Lumi::operator()(TGraph* gIn) const {
70  assert(gIn != nullptr);
71 
72  vector<float> x, y, ex, ey;
73  int n = gIn->GetN();
74  for (int i = 0; i < n - 1; ++i) {
75  int currentRun = gIn->GetPointX(i);
76  if (currentRun < firstRun)
77  continue;
78  if (currentRun >= lastRun)
79  break;
80 
81  int nextRun = gIn->GetPointX(i + 1);
82 
83  auto lumi_edge = operator()(firstRun, currentRun), lumi_width = operator()(currentRun, nextRun);
84  x.push_back(lumi_edge + lumi_width / 2);
85  ex.push_back(lumi_width / 2);
86 
87  auto point = gIn->GetPointY(i), error = gIn->GetErrorY(i);
88  y.push_back(point);
89  ey.push_back(error);
90  }
91 
92  auto N = x.size();
93  assert(N == y.size() && N == ex.size() && N == ey.size());
94  TGraph* gOut = new TGraphErrors(N, x.data(), y.data(), ex.data(), ey.data());
95  gOut->SetTitle(gIn->GetTitle());
96  CopyStyle(gIn, gOut);
97  return gOut;
98 }
99 
100 TH1* Run2Lumi::operator()(TH1* hIn) const {
101  vector<float> edges, contents, errors;
102  edges.push_back(0);
103  int N = hIn->GetNbinsX();
104  for (int i = 1; i <= N; ++i) {
105  auto nextRun = hIn->GetBinLowEdge(i + 1);
106  if (nextRun < firstRun)
107  continue;
108  if (nextRun >= lastRun)
109  break;
110 
111  edges.push_back(operator()(nextRun));
112 
113  auto content = hIn->GetBinContent(i), error = hIn->GetBinError(i);
114  contents.push_back(content);
115  errors.push_back(error);
116  }
117 
118  N = edges.size() - 1;
119  TString name = hIn->GetName();
120  name += "_byLumi";
121  TH1* hOut = new TH1F(name, hIn->GetTitle(), N, edges.data());
122  for (int i = 1; i <= N; ++i) {
123  hOut->SetBinContent(i, contents[i - 1]);
124  hOut->SetBinError(i, errors[i - 1]);
125  }
126  CopyStyle(hIn, hOut);
127  return hOut;
128 }
129 
130 Trend::Trend(const char* name,
131  const char* dir,
132  const char* title,
133  const char* ytitle,
134  float ymin,
135  float ymax,
136  pt::ptree& json,
137  const Run2Lumi& GetLumiFunctor,
138  const char* lumiAxisType)
139  : c(name, title, 2000, 800),
140  outputDir(Form("%s", dir)),
141  lgd(0.7, 0.65, 0.97, 0.89, "", "NDC"),
142  JSON(json),
143  GetLumi(GetLumiFunctor),
144  lumiType(lumiAxisType) {
145  if (JSON.count("CMSlabel"))
146  CMS = Form("#scale[1.1]{#bf{CMS}} #it{%s}", JSON.get<string>("CMSlabel").data());
147 
148  if (JSON.get_child("trends").count("TitleCanvas"))
149  lumi = Form("#scale[0.8]{%s}", JSON.get_child("trends").get<string>("TitleCanvas").data());
150 
151  assert(ymin < ymax);
152  float xmax = GetLumi(GetLumi.firstRun, GetLumi.lastRun);
153  if (JSON.get_child("trends").count("plotUnit"))
154  plotUnit = JSON.get_child("trends").get<string>("plotUnit");
155  const char* axistitles = Form(";%s luminosity [%s^{-1} ];%s", lumiType, plotUnit.c_str(), ytitle);
156  auto frame = c.DrawFrame(0., ymin, xmax, ymax, axistitles);
157  frame->GetYaxis()->SetTitleOffset(0.8);
158  frame->GetYaxis()->SetTickLength(0.01);
159  frame->GetXaxis()->SetLabelSize(fontsize);
160  frame->GetXaxis()->SetTitleSize(fontsize);
161  frame->GetYaxis()->SetLabelSize(fontsize);
162  frame->GetYaxis()->SetTitleSize(fontsize);
163  lgd.SetTextSize(fontsize);
164 
165  if (ymax > 0 && ymin < 0) {
166  TLine l;
167  l.SetLineColor(kBlack);
168  l.SetLineStyle(kDashed);
169  l.DrawLine(0., 0., xmax, 0.);
170  }
171 
172  c.SetTicks(1, 1);
173  c.SetRightMargin(0.015);
174  c.SetLeftMargin(0.07);
175  c.SetTopMargin(0.07);
176 
177  // plot vertical lines (typically pixel template transitions)
178  pt::ptree lines = JSON.get_child("trends.lines");
179  for (auto& type : lines) {
180  auto line = type.second.get_child_optional("line");
181  auto runs = type.second.get_child_optional("runs");
182  if (!line || !runs)
183  continue;
184 
185  auto v = new TLine;
186 
187  auto style = line->get_optional<string>("style");
188  if (style)
189  v->SetLineStyle(StyleParser(*style));
190 
191  auto color = line->get_optional<string>("color");
192  if (color)
193  v->SetLineColor(ColorParser(*color));
194 
195  auto width = line->get_optional<int>("width");
196  if (width)
197  v->SetLineWidth(*width);
198 
199  auto title = line->get_optional<string>("title");
200  if (title)
201  lgd.AddEntry(v, title->c_str(), "l");
202 
203  for (auto& run : *runs) {
204  auto currentRun = run.second.get_value<int>();
205 
206  auto lumi = GetLumi(GetLumi.firstRun, currentRun);
207 
208  if (lumi > 0)
209  v->DrawLine(lumi, ymin, lumi, ymax);
210  }
211  }
212 }
213 
214 void Trend::operator()(TObject* obj, TString drawOpt, TString lgdOpt, bool fullRange) {
215  c.cd();
216 
217  TString classname = obj->ClassName();
218  if (classname.Contains("TGraph")) {
219  auto g = dynamic_cast<TGraph*>(obj);
220  int n = g->GetN();
221 
222  if (fullRange) {
223  g->Set(n);
224  g->SetPoint(n, GetLumi.lastRun, 0);
225  }
226  g = GetLumi(g);
227  g->Draw("same" + drawOpt);
228  } else if (classname.Contains("TH1")) {
229  auto h = dynamic_cast<TH1*>(obj);
230  // TODO: full range?
231  h = GetLumi(h);
232  h->Draw("same" + drawOpt);
233  } else {
234  cerr << "No implementation for `" << classname << "`\n";
235  exit(EXIT_FAILURE);
236  }
237 
238  TString name = c.GetName();
239  name.ReplaceAll("vs_run", "vs_lumi");
240  c.SetName(name);
241 
242  TString title = obj->GetTitle();
243  if (title == "")
244  return;
245  lgd.AddEntry(obj, "", lgdOpt);
246 }
247 
249  c.cd();
250  lgd.Draw();
251 
252  float l = c.GetLeftMargin(), t = c.GetTopMargin(), r = c.GetRightMargin(), lumiTextOffset = 0.2;
253 
254  TLatex latex;
255  latex.SetNDC();
256  latex.SetTextFont(42);
257 
258  latex.SetTextAlign(11);
259  latex.DrawLatex(l, 1 - t + lumiTextOffset * t, CMS);
260 
261  latex.SetTextAlign(31);
262  latex.DrawLatex(1 - r, 1 - t + lumiTextOffset * t, lumi);
263 
264  // plot labels
265  latex.SetTextAlign(13);
266  auto totLumi = GetLumi();
267  assert(totLumi > 0);
268  auto posY = 0.88;
269  pt::ptree lines = JSON.get_child("trends.lines");
270  for (auto& type : lines) {
271  auto labels = type.second.get_child_optional("labels");
272  auto runs = type.second.get_child_optional("runs");
273  if (!labels || !runs)
274  continue;
275 
276  auto runIt = runs->begin();
277  auto labelIt = labels->begin();
278  while (runIt != runs->end() && labelIt != labels->end()) {
279  auto currentRun = runIt->second.get_value<int>();
280  auto label = labelIt->second.get_value<string>();
281 
282  auto lumi = max(GetLumi(currentRun), (float)0.01);
283  auto posX = l + (lumi / totLumi) / (l + 1 + r) + 0.02;
284 
285  label = "#scale[0.8]{" + label + "}";
286  latex.DrawLatex(posX, posY, label.c_str());
287 
288  ++runIt;
289  ++labelIt;
290  }
291  posY -= 0.06;
292  }
293 
294  c.RedrawAxis();
295  c.SaveAs(Form("%s/%s.pdf", outputDir, c.GetName()), Form("Title:%s", c.GetTitle()));
296  c.SaveAs(Form("%s/%s.png", outputDir, c.GetName()), Form("Title:%s", c.GetTitle()));
297 }
Definition: Trend.h:22
void operator()(TObject *obj, TString drawOpt, TString lgdOpt, bool fullRange=true)
Definition: Trend.cc:214
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
nlohmann::json json
float operator()() const
Sums luminosity for [firstRun, lastRun[.
Definition: Trend.cc:52
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]
float operator()(int run) const
Sums luminosity for [firstRun, run[.
Definition: Trend.cc:50
#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:130
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:80
const Run2Lumi & GetLumi
functor to get luminosity for given subrange
Definition: Trend.h:91
~Trend()
Definition: Trend.cc:248
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:55
*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="")