60{
63
66 string opera;
67 string name;
69
70 try {
71
72 JParser<> zap(
"Auxiliary program for histogram operations.");
73
74 zap[
'f'] =
make_field(inputFile,
"<input file>:<object name>");
76 JOpera::Add(),
77 JOpera::add(),
78 JOpera::Subtract(),
79 JOpera::subtract(),
80 JOpera::Multiply(),
81 JOpera::multiply(),
82 JOpera::Divide(),
83 JOpera::divide(),
84 JOpera::efficiency(),
85 JOpera::stdev(),
86 JOpera::Replace();
89 << "\n\t\"" << JOpera::SAME_AS_OPERATION() << "\" -> same as operation; or"
90 << "\n\t\"" << JOpera::SAME_AS_INPUT() << "\" -> same as input; else"
91 << "\n\t as specified") = JOpera::SAME_AS_OPERATION();
93
94 zap(argc, argv);
95 }
96 catch(const exception &error) {
97 FATAL(error.what() << endl);
98 }
99
100
102
103 for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
104
105 DEBUG(
"Input: " << *input << endl);
106
108
109 if (dir == NULL) {
110 ERROR(
"File: " << input->getFullFilename() <<
" not opened." << endl);
111 continue;
112 }
113
114 const TRegexp regexp(input->getObjectName());
115
116 TIter iter(dir->GetListOfKeys());
117
118 for (TKey* key; (
key = (TKey*) iter.Next()) != NULL; ) {
119
120 const TString tag(
key->GetName());
121
122 DEBUG(
"Key: " << tag <<
" match = " << tag.Contains(regexp) << endl);
123
124
125
126 if (tag.Contains(regexp) &&
isTObject(key)) {
127
129
130 if (dynamic_cast<TH3*>(p) == NULL) {
131 FATAL(
"Object " << p->GetName() <<
" not compatible with histogram operations." << endl);
132 }
133
134 listOfObjects.push_back(p);
135 }
136 }
137 }
138
139
140 TH3* h3 = NULL;
141
142 if (listOfObjects.size() == 0) {
143
144 FATAL(
"Number of histograms " << listOfObjects.size() <<
" = 0." << endl);
145
146 } else if (listOfObjects.size() == 1 && (opera == JOpera::Add() ||
147 opera == JOpera::Subtract() ||
148 opera == JOpera::Multiply() ||
149 opera == JOpera::Divide() ||
150 opera == JOpera::Replace())) {
151
152
153
154 TH3* h1 = dynamic_cast<TH3*>(listOfObjects[0]);
155 TF2*
f1 =
dynamic_cast<TF2*
>(h1->GetListOfFunctions()->First());
156
157 if (f1 == NULL) {
158 FATAL(h1->GetName() <<
" has no associated function." << endl);
159 }
160
161 NOTICE(h1->GetName() <<
' ' << opera <<
' ' <<
f1->GetName() << endl);
162
163 if (name == JOpera::SAME_AS_OPERATION())
164 h3 = (TH3*) h1->Clone(opera.c_str());
165 else if (name == JOpera::SAME_AS_INPUT())
166 h3 = (TH3*) h1->Clone(h1->GetName());
167 else
168 h3 = (TH3*) h1->Clone(name.c_str());
169
170 if (opera == JOpera::Add()) {
171
172 h3->Add (f1, +1.0);
173
174 } else if (opera == JOpera::Subtract()) {
175
176 h3->Add (f1, -1.0);
177
178 } else if (opera == JOpera::Multiply()) {
179
180 h3->Multiply(f1);
181
182 } else if (opera == JOpera::Divide()) {
183
184 h3->Divide (f1);
185
186 } else if (opera == JOpera::Replace()) {
187
188 h3->Reset();
189 h3->Fill(0.0, 0.0, 0.0);
190 h3->Add (f1);
191 }
192
193 } else if (listOfObjects.size() == 2) {
194
195 TH3* h1 = dynamic_cast<TH3*>(listOfObjects[0]);
196 TH3* h2 = dynamic_cast<TH3*>(listOfObjects[1]);
197
198 NOTICE(h1->GetName() <<
' ' << opera <<
' ' << h2->GetName() << endl);
199
200 if (name == JOpera::SAME_AS_OPERATION())
201 h3 = (TH3*) h1->Clone(opera.c_str());
202 else if (name == JOpera::SAME_AS_INPUT())
203 h3 = (TH3*) h1->Clone(h1->GetName());
204 else
205 h3 = (TH3*) h1->Clone(name.c_str());
206
207 if (opera == JOpera::Add()) {
208
209 h3->Add (h1, h2, +1.0, +1.0);
210
211 } else if (opera == JOpera::Subtract()) {
212
213 h3->Add (h1, h2, +1.0, -1.0);
214
215 } else if (opera == JOpera::Multiply()) {
216
217 h3->Multiply(h1, h2, +1.0, +1.0);
218
219 } else if (opera == JOpera::Divide()) {
220
221 h3->Divide (h1, h2, +1.0, +1.0);
222
223 } else if (opera == JOpera::add() ||
224 opera == JOpera::subtract() ||
225 opera == JOpera::multiply() ||
226 opera == JOpera::divide()) {
227
228 for (Int_t i1 = 1; i1 <= h1->GetNbinsX(); ++i1) {
229 for (Int_t i2 = 1; i2 <= h1->GetNbinsY(); ++i2) {
230 for (Int_t i3 = 1; i3 <= h1->GetNbinsZ(); ++i3) {
231
232 const Double_t
x = h1->GetXaxis()->GetBinCenter(i1);
233 const Double_t
y = h1->GetYaxis()->GetBinCenter(i2);
234 const Double_t z = h1->GetZaxis()->GetBinCenter(i3);
235
236 const Int_t j1 = h2->GetXaxis()->FindBin(x);
237 const Int_t j2 = h2->GetYaxis()->FindBin(y);
238 const Int_t j3 = h2->GetYaxis()->FindBin(z);
239
240 const Double_t w1 = h1->GetBinContent(i1,i2,i3);
241 const Double_t w2 = h2->GetBinContent(j1,j2,j3);
242
243 Double_t w3 = 0.0;
244
245 if (opera == JOpera::add()) {
246
247 w3 = w1 + w2;
248
249 } else if (opera == JOpera::subtract()) {
250
251 w3 = w1 - w2;
252
253 } else if (opera == JOpera::multiply()) {
254
255 w3 = w1 * w2;
256
257 } else if (opera == JOpera::divide()) {
258
259 if (w2 == 0.0) {
260 ERROR(
"Bin " << h2->GetName() <<
"[" << j1 <<
"," << j2 <<
"] empty." << endl);
261 continue;
262 }
263
264 w3 = w1 / w2;
265 }
266
267 h3->SetBinContent(i1, i2, i3, w3);
268 }
269 }
270 }
271
272 } else if (opera == JOpera::efficiency() ||
273 opera == JOpera::stdev() ||
274 opera == JOpera::sqrt()) {
275
276 for (Int_t i1 = 1; i1 <= h1->GetNbinsX(); ++i1) {
277 for (Int_t i2 = 1; i2 <= h1->GetNbinsY(); ++i2) {
278 for (Int_t i3 = 1; i3 <= h1->GetNbinsZ(); ++i3) {
279
280 const Double_t y1 = h1->GetBinContent(i1,i2,i3);
281 const Double_t y2 = h2->GetBinContent(i1,i2,i3);
282
283 Double_t w1 = h1->GetBinError(i1,i2,i3);
284 Double_t w2 = h2->GetBinError(i1,i2,i3);
285
286 Double_t y3 = 0.0;
287 Double_t w3 = 0.0;
288
289 if (opera == JOpera::efficiency()) {
290
291 if (y2 == 0.0) {
292 ERROR(
"Bin " << h2->GetName() <<
"[" << i1 <<
"," << i2 <<
"] empty." << endl);
293 continue;
294 }
295
296 y3 = y1 / y2;
297
298 if (y1 != 0.0 &&
299 y2 != 0.0) {
300
301 w1 /= y1;
302 w2 /= y2;
303
304 w3 = y3 * fabs(y3 - 1.0) * sqrt(w1*w1 + w2*w2);
305 }
306
307 } else if (opera == JOpera::stdev()) {
308
309 w3 = sqrt(w1*w1 + w2*w2);
310
311 if (w3 != 0.0) {
312 y3 = (y1 - y2) / w3;
313 w3 = 0.0;
314 }
315
316 } else if (opera == JOpera::sqrt()) {
317
318 y3 = (y1+y2) * (y1-y2);
319
320 if (y3 < 0.0)
321 y3 = -sqrt(-y3);
322 else
323 y3 = +sqrt(+y3);
324
325 w3 = 0.0;
326 }
327
328 h3->SetBinContent(i1, i2, i3, y3);
329 h3->SetBinError (i1, i2, i3, w3);
330 }
331 }
332 }
333 }
334
335 } else if (opera == JOpera::Add() ||
336 opera == JOpera::Multiply()) {
337
339
340 TH3* h1 = dynamic_cast<TH3*>(*i);
341
342 NOTICE(h1->GetName() <<
' ' << opera << endl);
343
344 if (h3 == NULL) {
345
346 if (name == JOpera::SAME_AS_OPERATION())
347 h3 = (TH3*) h1->Clone(opera.c_str());
348 else if (name == JOpera::SAME_AS_INPUT())
349 h3 = (TH3*) h1->Clone(h1->GetName());
350 else
351 h3 = (TH3*) h1->Clone(name.c_str());
352
353 } else {
354
355 if (opera == JOpera::Add()) {
356
357 h3->Add (h3, h1, +1.0, +1.0);
358
359 } else if (opera == JOpera::Multiply()) {
360
361 h3->Multiply(h3, h1, +1.0, +1.0);
362 }
363 }
364 }
365
366 } else {
367
368 FATAL(
"Incompatible number of histograms " << listOfObjects.size() <<
" with option " << opera << endl);
369 }
370
371 if (h3 != NULL) {
372
374
375 h3->Write();
376
377 out.Write();
378 out.Close();
379 }
380}
#define DEBUG(A)
Message macros.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Utility class to parse command line options.
const JPolynome f1(1.0, 2.0, 3.0)
Function.
TDirectory * getDirectory(const JRootObjectID &id)
Get TDirectory pointer.
bool isTObject(const TKey *key)
Check if given key corresponds to a TObject.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).