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