Jpp  debug
the software that should make you happy
JOpera3D.cc
Go to the documentation of this file.
1 
2 #include <string>
3 #include <iostream>
4 #include <iomanip>
5 #include <vector>
6 #include <cmath>
7 
8 #include "TROOT.h"
9 #include "TFile.h"
10 #include "TKey.h"
11 #include "TH3.h"
12 #include "TF3.h"
13 #include "TProfile3D.h"
14 #include "TString.h"
15 #include "TRegexp.h"
16 
17 #include "JGizmo/JRootObjectID.hh"
18 #include "JGizmo/JGizmoToolkit.hh"
19 
20 #include "Jeep/JParser.hh"
21 #include "Jeep/JMessage.hh"
22 
23 
24 /**
25  * \file
26  * Auxiliary program for operations on 3D histograms.\n
27  * The option <tt>-f</tt> corresponds to <tt><file name>:<object name></tt>.
28  *
29  * Possible operations (option <tt>-u <operation></tt>:
30  * - Add\n
31  * ROOT addition of histograms;
32  * - add\n
33  * Addition of histograms by look up of corresponding bin in second histogram;
34  * - Subtract\n
35  * ROOT subtraction of histograms;
36  * - subtract\n
37  * Subtraction of histograms by look up of corresponding bin in second histogram;
38  * - Multiply\n
39  * ROOT multiplication of histograms;
40  * - multiply\n
41  * Multiplication of histograms by look up of corresponding bin in second histogram;
42  * - Divide\n
43  * ROOT division of histograms;
44  * - divide\n
45  * Division of histograms by look up of corresponding bin in second histogram;
46  * - efficiency\n
47  * Like "Divide", but with correction for errors;
48  * - stdev\n
49  * Standard deviation;
50  * - Replace\n
51  * Replace histogram contents by function value;
52  *
53  * If only one histogram is specified, the operation applies to the histogram and the first associated function.\n
54  * Only the quoted ROOT operations and the additional operation Replace are then allowed.\n
55  * The option Replace will replace the histogram contents by the function value.
56  *
57  * \author mdejong
58  */
59 int main(int argc, char **argv)
60 {
61  using namespace std;
62  using namespace JPP;
63 
64  vector<JRootObjectID> inputFile;
65  string outputFile;
66  string opera;
67  string name;
68  int debug;
69 
70  try {
71 
72  JParser<> zap("Auxiliary program for histogram operations.");
73 
74  zap['f'] = make_field(inputFile, "<input file>:<object name>");
75  zap['u'] = make_field(opera) =
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();
87  zap['o'] = make_field(outputFile, "ROOT file with histogram(s)") = "opera.root";
88  zap['O'] = make_field(name, "histogram name:"
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();
92  zap['d'] = make_field(debug) = 1;
93 
94  zap(argc, argv);
95  }
96  catch(const exception &error) {
97  FATAL(error.what() << endl);
98  }
99 
100 
101  vector<TObject*> listOfObjects;
102 
103  for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
104 
105  DEBUG("Input: " << *input << endl);
106 
107  TDirectory* dir = getDirectory(*input);
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  // option match
125 
126  if (tag.Contains(regexp) && isTObject(key)) {
127 
128  TObject* p = key->ReadObj();
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  // operation between histogram contents and first associated function
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); // ensure one entry for drawing after reset
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 
338  for (vector<TObject*>::iterator i = listOfObjects.begin(); i != listOfObjects.end(); ++i) {
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 
373  TFile out(outputFile.c_str(), "recreate");
374 
375  h3->Write();
376 
377  out.Write();
378  out.Close();
379  }
380 }
string outputFile
General purpose messaging.
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
#define ERROR(A)
Definition: JMessage.hh:66
#define NOTICE(A)
Definition: JMessage.hh:64
#define FATAL(A)
Definition: JMessage.hh:67
int debug
debug level
Definition: JSirene.cc:69
int main(int argc, char **argv)
Definition: JOpera3D.cc:59
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:2158
Utility class to parse command line options.
Definition: JParser.hh:1714
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).
Definition: JSTDTypes.hh:14
Definition: JRoot.hh:19