Jpp  15.0.1-rc.2-highQE
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JOpera2D.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 "TH2.h"
12 #include "TF2.h"
13 #include "TProfile2D.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 2D 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  *
51  * If only one histogram is specified, the operation applies to the histogram and the first associated function.\n
52  * Only the quoted ROOT operations and the additional operation Replace are then allowed.\n
53  * The option Replace will replace the histogram contents by the function value.
54  *
55  * \author mdejong
56  */
57 int main(int argc, char **argv)
58 {
59  using namespace std;
60  using namespace JPP;
61 
62  vector<JRootObjectID> inputFile;
63  string outputFile;
64  string opera;
65  string name;
66  int debug;
67 
68  try {
69 
70  JParser<> zap("Auxiliary program for histogram operations.");
71 
72  zap['f'] = make_field(inputFile, "<input file>:<object name>");
73  zap['u'] = make_field(opera) =
74  JOpera::Add(),
75  JOpera::add(),
76  JOpera::Subtract(),
77  JOpera::subtract(),
78  JOpera::Multiply(),
79  JOpera::multiply(),
80  JOpera::Divide(),
81  JOpera::divide(),
82  JOpera::efficiency(),
83  JOpera::stdev(),
84  JOpera::Replace();
85  zap['o'] = make_field(outputFile, "ROOT file with histogram(s)") = "opera.root";
86  zap['O'] = make_field(name, MAKE_STRING("histogram name;"
87  << "\n\"" << JOpera::SAME_AS_OPERATION() << "\" -> same as operation; or"
88  << "\n\"" << JOpera::SAME_AS_INPUT() << "\" -> same as input; else"
89  << "\nas specified")) = JOpera::SAME_AS_OPERATION();
90  zap['d'] = make_field(debug) = 1;
91 
92  zap(argc, argv);
93  }
94  catch(const exception &error) {
95  FATAL(error.what() << endl);
96  }
97 
98 
99  vector<TObject*> listOfObjects;
100 
101  for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
102 
103  DEBUG("Input: " << *input << endl);
104 
105  TDirectory* dir = getDirectory(*input);
106 
107  if (dir == NULL) {
108  ERROR("File: " << input->getFullFilename() << " not opened." << endl);
109  continue;
110  }
111 
112  const TRegexp regexp(input->getObjectName());
113 
114  TIter iter(dir->GetListOfKeys());
115 
116  for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
117 
118  const TString tag(key->GetName());
119 
120  DEBUG("Key: " << tag << " match = " << tag.Contains(regexp) << endl);
121 
122  // option match
123 
124  if (tag.Contains(regexp)) {
125 
126  TObject* p = key->ReadObj();
127 
128  if (dynamic_cast<TH2*>(p) == NULL) {
129  FATAL("Object " << p->GetName() << " not compatible with histogram operations." << endl);
130  }
131 
132  listOfObjects.push_back(p);
133  }
134  }
135  }
136 
137 
138  TH2* h3 = NULL;
139 
140  if (listOfObjects.size() == 0) {
141 
142  FATAL("Number of histograms " << listOfObjects.size() << " = 0." << endl);
143 
144  } else if (listOfObjects.size() == 1 && (opera == JOpera::Add() ||
145  opera == JOpera::Subtract() ||
146  opera == JOpera::Multiply() ||
147  opera == JOpera::Divide() ||
148  opera == JOpera::Replace())) {
149 
150  // operation between histogram contents and first associated function
151 
152  TH2* h1 = dynamic_cast<TH2*>(listOfObjects[0]);
153  TF2* f1 = dynamic_cast<TF2*>(h1->GetListOfFunctions()->First());
154 
155  if (f1 == NULL) {
156  FATAL(h1->GetName() << " has no associated function." << endl);
157  }
158 
159  NOTICE(h1->GetName() << ' ' << opera << ' ' << f1->GetName() << endl);
160 
161  if (name == JOpera::SAME_AS_OPERATION())
162  h3 = (TH2*) h1->Clone(opera.c_str());
163  else if (name == JOpera::SAME_AS_INPUT())
164  h3 = (TH2*) h1->Clone(h1->GetName());
165  else
166  h3 = (TH2*) h1->Clone(name.c_str());
167 
168  if (opera == JOpera::Add()) {
169 
170  h3->Add (f1, +1.0);
171 
172  } else if (opera == JOpera::Subtract()) {
173 
174  h3->Add (f1, -1.0);
175 
176  } else if (opera == JOpera::Multiply()) {
177 
178  h3->Multiply(f1);
179 
180  } else if (opera == JOpera::Divide()) {
181 
182  h3->Divide (f1);
183 
184  } else if (opera == JOpera::Replace()) {
185 
186  h3->Reset();
187  h3->Fill(0.0, 0.0, 0.0); // ensure one entry for drawing after reset
188  h3->Add (f1);
189  }
190 
191  } else if (listOfObjects.size() == 2) {
192 
193  TH2* h1 = dynamic_cast<TH2*>(listOfObjects[0]);
194  TH2* h2 = dynamic_cast<TH2*>(listOfObjects[1]);
195 
196  NOTICE(h1->GetName() << ' ' << opera << ' ' << h2->GetName() << endl);
197 
198  if (name == JOpera::SAME_AS_OPERATION())
199  h3 = (TH2*) h1->Clone(opera.c_str());
200  else if (name == JOpera::SAME_AS_INPUT())
201  h3 = (TH2*) h1->Clone(h1->GetName());
202  else
203  h3 = (TH2*) h1->Clone(name.c_str());
204 
205  if (opera == JOpera::Add()) {
206 
207  h3->Add (h1, h2, +1.0, +1.0);
208 
209  } else if (opera == JOpera::Subtract()) {
210 
211  h3->Add (h1, h2, +1.0, -1.0);
212 
213  } else if (opera == JOpera::Multiply()) {
214 
215  h3->Multiply(h1, h2, +1.0, +1.0);
216 
217  } else if (opera == JOpera::Divide()) {
218 
219  h3->Divide (h1, h2, +1.0, +1.0);
220 
221  } else if (opera == JOpera::add() ||
222  opera == JOpera::subtract() ||
223  opera == JOpera::multiply() ||
224  opera == JOpera::divide()) {
225 
226  for (Int_t i1 = 1; i1 <= h1->GetNbinsX(); ++i1) {
227  for (Int_t i2 = 1; i2 <= h1->GetNbinsY(); ++i2) {
228 
229  const Double_t x = h1->GetXaxis()->GetBinCenter(i1);
230  const Double_t y = h1->GetYaxis()->GetBinCenter(i2);
231 
232  const Int_t j1 = h2->GetXaxis()->FindBin(x);
233  const Int_t j2 = h2->GetYaxis()->FindBin(y);
234 
235  const Double_t w1 = h1->GetBinContent(i1,i2);
236  const Double_t w2 = h2->GetBinContent(j1,j2);
237 
238  Double_t w3 = 0.0;
239 
240  if (opera == JOpera::add()) {
241 
242  w3 = w1 + w2;
243 
244  } else if (opera == JOpera::subtract()) {
245 
246  w3 = w1 - w2;
247 
248  } else if (opera == JOpera::multiply()) {
249 
250  w3 = w1 * w2;
251 
252  } else if (opera == JOpera::divide()) {
253 
254  if (w2 == 0.0) {
255  ERROR("Bin " << h2->GetName() << "[" << j1 << "," << j2 << "] empty." << endl);
256  continue;
257  }
258 
259  w3 = w1 / w2;
260  }
261 
262  h3->SetBinContent(i1, i2, w3);
263  }
264  }
265 
266  } else if (opera == JOpera::efficiency() ||
267  opera == JOpera::stdev() ||
268  opera == JOpera::sqrt()) {
269 
270  for (Int_t i1 = 1; i1 <= h1->GetNbinsX(); ++i1) {
271  for (Int_t i2 = 1; i2 <= h1->GetNbinsY(); ++i2) {
272 
273  const Double_t y1 = h1->GetBinContent(i1,i2);
274  const Double_t y2 = h2->GetBinContent(i1,i2);
275 
276  Double_t w1 = h1->GetBinError(i1,i2);
277  Double_t w2 = h2->GetBinError(i1,i2);
278 
279  Double_t y3 = 0.0;
280  Double_t w3 = 0.0;
281 
282  if (opera == JOpera::efficiency()) {
283 
284  if (y2 == 0.0) {
285  ERROR("Bin " << h2->GetName() << "[" << i1 << "," << i2 << "] empty." << endl);
286  continue;
287  }
288 
289  y3 = y1 / y2;
290 
291  if (y1 != 0.0 &&
292  y2 != 0.0) {
293 
294  w1 /= y1;
295  w2 /= y2;
296 
297  w3 = y3 * fabs(y3 - 1.0) * sqrt(w1*w1 + w2*w2);
298  }
299 
300  } else if (opera == JOpera::stdev()) {
301 
302  w3 = sqrt(w1*w1 + w2*w2);
303 
304  if (w3 != 0.0) {
305  y3 = (y1 - y2) / w3;
306  w3 = 0.0;
307  }
308 
309  } else if (opera == JOpera::sqrt()) {
310 
311  y3 = (y1+y2) * (y1-y2);
312 
313  if (y3 < 0.0)
314  y3 = -sqrt(-y3);
315  else
316  y3 = +sqrt(+y3);
317 
318  w3 = 0.0;
319  }
320 
321  h3->SetBinContent(i1, i2, y3);
322  h3->SetBinError (i1, i2, w3);
323  }
324  }
325  }
326 
327  } else if (opera == JOpera::Add() ||
328  opera == JOpera::Multiply()) {
329 
330  for (vector<TObject*>::iterator i = listOfObjects.begin(); i != listOfObjects.end(); ++i) {
331 
332  TH2* h1 = dynamic_cast<TH2*>(*i);
333 
334  NOTICE(h1->GetName() << ' ' << opera << endl);
335 
336  if (h3 == NULL) {
337 
338  if (name == JOpera::SAME_AS_OPERATION())
339  h3 = (TH2*) h1->Clone(opera.c_str());
340  else if (name == JOpera::SAME_AS_INPUT())
341  h3 = (TH2*) h1->Clone(h1->GetName());
342  else
343  h3 = (TH2*) h1->Clone(name.c_str());
344 
345  } else {
346 
347  if (opera == JOpera::Add()) {
348 
349  h3->Add (h3, h1, +1.0, +1.0);
350 
351  } else if (opera == JOpera::Multiply()) {
352 
353  h3->Multiply(h3, h1, +1.0, +1.0);
354  }
355  }
356  }
357 
358  } else {
359 
360  FATAL("Incompatible number of histograms " << listOfObjects.size() << " with option " << opera << endl);
361  }
362 
363  if (h3 != NULL) {
364 
365  TFile out(outputFile.c_str(), "recreate");
366 
367  h3->Write();
368 
369  out.Write();
370  out.Close();
371  }
372 }
Utility class to parse command line options.
Definition: JParser.hh:1500
int main(int argc, char *argv[])
Definition: Main.cc:15
stdev
then echo Enter input within $TIMEOUT_S seconds echo n User name
Definition: JCookie.sh:42
Definition: JRoot.hh:19
then for HISTOGRAM in h0 h1
Definition: JMatrixNZ.sh:71
string outputFile
#define MAKE_STRING(A)
Make string.
Definition: JPrint.hh:142
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1961
#define NOTICE(A)
Definition: JMessage.hh:64
#define ERROR(A)
Definition: JMessage.hh:66
int debug
debug level
Definition: JSirene.cc:63
General purpose messaging.
#define FATAL(A)
Definition: JMessage.hh:67
Utility class to parse command line options.
then usage $script< input_file >< detector_file > fi set_variable OUTPUT_DIR set_variable SELECTOR JDAQTimesliceL1 set_variable DEBUG case set_variable DEBUG
TDirectory * getDirectory(const JRootObjectID &id)
Get TDirectory pointer.