ra4_draw  4bd0201e3d922d42bd545d4b045ed44db33454a4
plot_maker.cpp
Go to the documentation of this file.
1 
12 #include "core/plot_maker.hpp"
13 
14 #include <functional>
15 #include <mutex>
16 #include <chrono>
17 #include <map>
18 #include <iomanip> // setw
19 
20 #include "TLegend.h"
21 
22 #include "core/utilities.hpp"
23 #include "core/timer.hpp"
24 #include "core/thread_pool.hpp"
25 #include "core/named_func.hpp"
26 #include "core/process.hpp"
27 
28 using namespace std;
29 using namespace PlotOptTypes;
30 
35 
36 using Clock = chrono::steady_clock;
37 
38 namespace{
39  mutex print_mutex;
40 }
41 
45  multithreaded_(true),
46  min_print_(false),
47  figures_(){
48 }
49 
54 void PlotMaker::MakePlots(double luminosity,
55  const string &subdir){
56  GetYields();
57 
58  for(auto &figure: figures_){
59  figure->Print(luminosity, subdir);
60  }
61 }
62 
63 const vector<unique_ptr<Figure> > & PlotMaker::Figures() const{
64  return figures_;
65 }
66 
70  figures_.clear();
71 }
72 
74  auto start_time = Clock::now();
75 
76  auto babies = GetBabies();
77  size_t num_threads = multithreaded_ ? min(babies.size(), static_cast<size_t>(thread::hardware_concurrency())) : 1;
78  cout << "Processing " << babies.size() << " babies with " << num_threads << " threads." << endl;
79 
80  long num_entries = 0;
81 
82  if(multithreaded_ && num_threads>1){
83  vector<future<long> > num_entries_future(babies.size());
84 
85  ThreadPool tp(num_threads);
86  size_t Nbabies = 0;
87  for(const auto &baby: babies){
88  num_entries_future.at(Nbabies) = tp.Push(bind(&PlotMaker::GetYield, this, ref(baby)));
89  ++Nbabies;
90  }
91  size_t Nfiles=0;
92  long printStep=Nbabies/20+1; // Print up to 20 lines of info
93  auto start_entries_time = Clock::now();
94  for(auto& entries: num_entries_future){
95  num_entries += entries.get();
96  Nfiles++;
97  if(min_print_ && ((Nfiles-1)%printStep==0 || Nfiles==Nbabies)){
98  double seconds = chrono::duration<double>(Clock::now()-start_entries_time).count();
99  cout<<"Done "<<setw(log10(Nbabies)+1)<<Nfiles<<"/"<<Nbabies<<" files: "<<setw(10)<<AddCommas(num_entries)
100  <<" entries in "<<HoursMinSec(seconds)<<" -> "<<setw(5)<<RoundNumber(num_entries/1000.,1,seconds)
101  <<" kHz "<<endl;
102  }
103  }
104  }else{
105  for(const auto &baby: babies){
106  num_entries += GetYield(ref(baby));
107  }
108  }
109  auto end_time = Clock::now();
110  double num_seconds = chrono::duration<double>(end_time-start_time).count();
111  if(!min_print_) cout << endl << num_threads << " threads processed "
112  << babies.size() << " babies with "
113  << AddCommas(num_entries) << " events in "
114  << num_seconds << " seconds = "
115  << 0.001*num_entries/num_seconds << " kHz."
116  << endl;
117  cout << endl;
118 }
119 
120 long PlotMaker::GetYield(Baby *baby_ptr){
121  auto start_time = Clock::now();
122  Baby &baby = *baby_ptr;
123  auto activator = baby.Activate();
124  string tag = "";
125  if(baby.FileNames().size() == 1){
126  tag = Basename(*baby.FileNames().cbegin());
127  }else{
128  tag = "Baby for processes";
129  }
130  ostringstream oss;
131  oss << " [";
132  for(auto proc = baby.processes_.cbegin(); proc != baby.processes_.cend(); ++proc){
133  if(proc != baby.processes_.cbegin()) oss << ", ";
134  oss << (*proc)->name_;
135  }
136  oss << "]" << flush;
137  tag += oss.str();
138  {
139  lock_guard<mutex> lock(print_mutex);
140  if(!min_print_) cout << "Processing " << tag << endl;
141  }
142 
143  long num_entries = baby.GetEntries();
144  {
145  lock_guard<mutex> lock(print_mutex);
146  if(!min_print_) cout << tag << " has " << num_entries << " entries." << endl;
147  }
148 
149  vector<pair<const Process*, set<Figure::FigureComponent*> > > proc_figs(baby.processes_.size());
150  size_t iproc = 0;
151  for(const auto &proc: baby.processes_){
152  proc_figs.at(iproc).first = proc;
153  proc_figs.at(iproc).second = GetComponents(proc);
154  ++iproc;
155  }
156 
157  Timer timer(tag, num_entries, 10.);
158  for(long entry = 0; entry < num_entries; ++entry){
159  if(!min_print_) timer.Iterate();
160  baby.GetEntry(entry);
161 
162  for(const auto &proc_fig: proc_figs){
163  if(proc_fig.first->cut_.IsScalar()){
164  if(!proc_fig.first->cut_.GetScalar(baby)) continue;
165  }else{
166  if(!HavePass(proc_fig.first->cut_.GetVector(baby))) continue;
167  }
168  for(const auto &component: proc_fig.second){
169  lock_guard<mutex> lock(component->mutex_);
170  component->RecordEvent(baby);
171  }
172  }
173  }
174 
175  auto end_time = Clock::now();
176  double num_seconds = chrono::duration<double>(end_time - start_time).count();
177  {
178  lock_guard<mutex> lock(print_mutex);
179  if(!min_print_) cout << "Finished processing " << tag << ". "
180  << num_entries << " events in " << num_seconds << " seconds = "
181  << 0.001*num_entries/num_seconds << " kHz. "<< endl;
182  }
183  return num_entries;
184 }
185 
186 set<Baby*> PlotMaker::GetBabies() const{
187  set<Baby*> babies;
188  for(auto &proc: GetProcesses()){
189  for(const auto &baby: proc->Babies()){
190  babies.insert(baby);
191  }
192  }
193  return babies;
194 }
195 
196 set<const Process*> PlotMaker::GetProcesses() const{
197  set<const Process*> processes;
198  for(const auto &figure: figures_){
199  for(const auto &process: figure->GetProcesses()){
200  processes.insert(process);
201  }
202  }
203  return processes;
204 }
205 
206 set<Figure::FigureComponent*> PlotMaker::GetComponents(const Process *process) const{
207  set<Figure::FigureComponent*> figure_components;
208  for(auto &figure: figures_){
209  auto processes = figure->GetProcesses();
210  auto loc = processes.find(process);
211  if(loc == processes.end()) continue;
212  figure_components.insert(figure->GetComponent(process));
213  }
214  return figure_components;
215 }
std::vector< ScalarType > VectorType
Definition: named_func.hpp:16
Definition: timer.hpp:9
TString HoursMinSec(float fseconds)
Definition: utilities.cpp:337
NamedFunc::VectorType VectorType
std::vector< std::unique_ptr< Figure > > figures_
Figures to be produced.
Definition: plot_maker.hpp:47
const std::set< std::string > & FileNames() const
Definition: baby.cpp:1676
Abstract base class for access to ntuple variables.
Definition: baby.hpp:16
const std::vector< std::unique_ptr< Figure > > & Figures() const
Definition: plot_maker.cpp:63
STL namespace.
ScalarType(const Baby &) ScalarFunc
Definition: named_func.hpp:17
TString AddCommas(double num)
Definition: utilities.cpp:351
bool multithreaded_
Definition: plot_maker.hpp:43
double ScalarType
Definition: named_func.hpp:15
VectorType(const Baby &) VectorFunc
Definition: named_func.hpp:18
NamedFunc::VectorFunc VectorFunc
std::set< Figure::FigureComponent * > GetComponents(const Process *process) const
Definition: plot_maker.cpp:206
std::string Basename(const std::string &filename)
Definition: utilities.cpp:38
virtual void GetEntry(long entry)
Change current entry.
Definition: baby.cpp:1285
bool min_print_
Definition: plot_maker.hpp:44
TString RoundNumber(double num, int decimals, double denom=1.)
Definition: utilities.cpp:361
PlotMaker()
Standard constructor.
Definition: plot_maker.cpp:44
chrono::steady_clock Clock
Definition: plot_maker.cpp:36
void Clear()
Empties list of plots to be produced at next PlotMaker::MakePlots call.
Definition: plot_maker.cpp:69
std::set< Baby * > GetBabies() const
Definition: plot_maker.cpp:186
void Iterate()
Definition: timer.cpp:80
std::set< const Process * > GetProcesses() const
Definition: plot_maker.cpp:196
std::unique_ptr< Activator > Activate()
Definition: baby.cpp:2494
long GetEntries() const
Get number of entries in TChain and cache it.
Definition: baby.cpp:1272
long GetYield(Baby *baby_ptr)
Definition: plot_maker.cpp:120
void MakePlots(double luminosity, const std::string &subdir="")
Prints all added plots with given luminosity.
Definition: plot_maker.cpp:54
NamedFunc::ScalarFunc ScalarFunc
bool HavePass(const NamedFunc::VectorType &v)
Definition: named_func.cpp:830
std::set< const Process * > processes_
Definition: baby.hpp:47
NamedFunc::ScalarType ScalarType
void GetYields()
Definition: plot_maker.cpp:73