-
Notifications
You must be signed in to change notification settings - Fork 0
/
agxmerge.cxx
188 lines (156 loc) · 5.25 KB
/
agxmerge.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Combine histogram files with weights that are computed from the
// specified cross sections. Another ingredient for the weight
// computation, the number of processed events from the sample, is
// automatically looked up from the input files.
//
// Andrei Gaponenko, 2010
#include <string>
#include <stdexcept>
#include <iostream>
#include <cstdlib>
#include <memory>
#include <utility>
#include <sstream>
#include "TFile.h"
#include "TH1.h"
#include "InputFileGetter.h"
#include "RootUtils.h"
#include "FileMergeObjects.h"
#include "getHisto.h"
//================================================================
namespace {
template<class Number>
Number getNumber(const std::string& str) {
std::istringstream is(str);
Number res(0);
if(!(is>>res)) {
throw std::runtime_error("ERROR: expected number, got \""+str+"\"");
}
std::string tmp;
if(is>>tmp) {
throw std::runtime_error("ERROR: trailing garbage after the number: \""+str+"\"");
}
return res;
}
//----------------------------------------------------------------
typedef std::pair<double, std::string> WFPair;
WFPair nextPair(InputFileGetter& fg) {
std::string wstr = fg.get();
std::string filename = fg.get();
if(!wstr.empty() && filename.empty()) {
throw std::runtime_error("ERROR: got weight \"+wstr+\" but no filename");
}
double w = filename.empty() ? 0. : getNumber<double>(wstr);
return make_pair(w, filename);
}
//----------------------------------------------------------------
double getNumEvents(const std::string& filename,
const std::string& refhisto,
unsigned refbin)
{
std::auto_ptr<TH1> hh(getHisto(filename, refhisto));
if((refbin<1u) || (refbin > unsigned(hh->GetNbinsX()))) {
throw std::runtime_error("getNumEvents(): refbin out of range");
}
return hh->GetBinContent(refbin);
}
//----------------------------------------------------------------
double computeWeight(double targetLumi, double xsec, double numEvents) {
// L(target)/L(sample)
return targetLumi * xsec / numEvents;
}
}
//================================================================
std::string usage() {
return
"Usage:\n"
" agxmerge --targetLumi L \\\n"
" --refh path/histo --refbin int \\\n"
" --out outfile.root \\\n"
" xs1 infile1.root xs2 infile2.root ...\n"
"\n"
"or do\n"
"\n"
" agxmerge --targetLumi L \n"
" --refh path/histo --refbin int \\\n"
" --out outfile.root \\\n"
" --stdin\n"
"\n"
"and feed in cross section and file name pairs.\n"
;
}
//================================================================
int main(int argc, char* const argv[]) {
int ret = 1;
TH1::AddDirectory(kFALSE);
for(int i=1; i<argc; ++i) {
if( (argv[i] == std::string("-h")) ||
(argv[i] == std::string("--help")) ) {
std::cout<<usage()<<std::endl;
exit(1);
}
}
if(argc<10) {
std::cerr<<"Too few arguments"<<std::endl;
exit(2);
}
if(std::string(argv[1]) != "--targetLumi") {
std::cerr<<"Wrong arg1: should be \"--targetLumi\""<<std::endl;
exit(2);
}
if(std::string(argv[3]) != "--refh") {
std::cerr<<"Wrong arg3: should be \"--refh\""<<std::endl;
exit(2);
}
if(std::string(argv[5]) != "--refbin") {
std::cerr<<"Wrong arg5: should be \"--refbin\""<<std::endl;
exit(2);
}
if(std::string(argv[7]) != "--out") {
std::cerr<<"Wrong arg7: should be \"--out\""<<std::endl;
exit(2);
}
try {
double targetLumi = getNumber<double>(argv[2]);
const std::string refhisto(argv[4]);
const unsigned refbin(getNumber<unsigned>(argv[6]));
const std::string outfilename(argv[8]);
TFile outfile(outfilename.c_str(), "NEW");
if(!outfile.IsOpen()) {
throw std::runtime_error("Can't open output file \""+std::string(argv[1])+"\"");
}
unsigned const offset = 9; // [8]==outfile
InputFileGetter files(argc - offset, argv + offset);
double xs1 = getNumber<double>(files.get());
const std::string firstInFile = files.get();
if(firstInFile.empty()) {
throw std::runtime_error("ERROR: first input file name is an empty string");
}
double numEvents1 = getNumEvents(firstInFile, refhisto, refbin);
double w1 = computeWeight(targetLumi, xs1, numEvents1);
std::cout<<"L = "<<(numEvents1/xs1)<<" for "<<firstInFile<<std::endl;
FileMergeObjects fo(firstInFile, w1);
for(WFPair inputs = nextPair(files);
!inputs.second.empty();
inputs = nextPair(files) )
{
double numEvents = getNumEvents(inputs.second, refhisto, refbin);
double w = computeWeight(targetLumi, inputs.first, numEvents);
std::cout<<"L = "<<(numEvents/inputs.first)<<" for "<<inputs.second<<std::endl;
fo.addFile(inputs.second, w);
}
std::cout<<"Writing output\t"<<std::endl;
fo.write(&outfile);
std::cout<<"Closing output file \t"<<std::endl;
outfile.Close();
ret = 0;
}
catch(std::exception& e) {
std::cerr<<"ERROR: got std::exception: "<<e.what()<<std::endl;
}
catch(...) {
std::cerr<<"ERROR: got a non-standard exception"<<std::endl;
}
return ret;
}
//================================================================