Jpp  17.3.2
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JHobbit.cc
Go to the documentation of this file.
1 #include <string>
2 #include <iostream>
3 #include <iomanip>
4 #include <vector>
5 #include <map>
6 
7 #include "TROOT.h"
8 #include "TFile.h"
9 #include "TH1D.h"
10 #include "TH2D.h"
11 #include "TF1.h"
12 #include "TMath.h"
13 #include "TFitResult.h"
14 
15 #include "JLang/JLangToolkit.hh"
16 #include "JSupport/JMeta.hh"
17 #include "JTools/JRange.hh"
18 
19 #include "JDetector/JDetector.hh"
21 #include "JDetector/JTimeRange.hh"
22 
23 #include "Jeep/JPrint.hh"
24 #include "Jeep/JParser.hh"
25 #include "Jeep/JMessage.hh"
26 
27 namespace {
28 
29  /**
30  * Name of histogram with fit results from JCalibrateMuon.cc.
31  */
32  const char* h2_t = "h2";
33 
34  const char* gauss_t = "Gauss"; //!< Gaussian
35  const char* landau_t = "Landau"; //!< Landau
36  const char* emg_t = "EMG"; //!< Exponentially Modified Gaussian
37  const char* breitwigner_t = "BreitWigner"; //!< Breit-Wigner
38 }
39 
40 
41 /**
42  * \file
43  * Program to fit time-residuals histogram in output of JCalibrateMuon.cc.
44  * \author mdejong
45  */
46 int main(int argc, char **argv)
47 {
48  using namespace std;
49  using namespace JPP;
50 
51  vector<string> inputFile;
52  string outputFile;
53  string detectorFile;
54  bool overwriteDetector;
55  string function;
56  JTimeRange T_ns;
57  string option;
58  JTimeRange E_ns;
59  double WMin;
60  int debug;
61 
62  try {
63 
64  JParser<> zap("Program to fit time-residuals histogram in output of JCalibrateMuon.cc.");
65 
66  zap['f'] = make_field(inputFile, "input files (output from JCalibrateMuon).");
67  zap['o'] = make_field(outputFile, "output file.") = "hobbit.root";
68  zap['a'] = make_field(detectorFile, "detector file.");
69  zap['A'] = make_field(overwriteDetector, "overwrite detector file provided through '-a' with correct time offsets.");
70  zap['F'] = make_field(function, "fit function") = gauss_t, landau_t, emg_t, breitwigner_t;
71  zap['T'] = make_field(T_ns, "ROOT fit range around maximum [ns].") = JTimeRange(-7.5,+5.0);
72  zap['O'] = make_field(option, "ROOT fit option, see TH1::Fit.") = "";
73  zap['E'] = make_field(E_ns, "validity range of t0 uncertainty [ns].") = JTimeRange( 0.0, 0.3);
74  zap['W'] = make_field(WMin, "minimal histogram contents.") = 100.0;
75  zap['d'] = make_field(debug) = 1;
76 
77  zap(argc, argv);
78  }
79  catch(const exception &error) {
80  FATAL(error.what() << endl);
81  }
82 
83 
84  if (!T_ns.is_valid()) {
85  FATAL("Invalid fit range [ns] " << T_ns << endl);
86  }
87 
89 
90  try {
91  load(detectorFile, detector);
92  }
93  catch(const JException& error) {
94  FATAL(error);
95  }
96 
97  if (option.find('S') == string::npos) { option += 'S'; }
98  if (option.find('Q') == string::npos && debug < JEEP::debug_t) { option += 'Q'; }
99 
100 
101  TH2D* h2 = NULL;
102 
103  for (vector<string>::const_iterator i = inputFile.begin(); i != inputFile.end(); ++i) {
104 
105  NOTICE("Processing " << *i << endl);
106 
107  TFile in(i->c_str(), "exist");
108 
109  if (!in.IsOpen()) {
110  FATAL("File " << *i << " not opened." << endl);
111  }
112 
113  TH2D* p = dynamic_cast<TH2D*>(in.Get(h2_t));
114 
115  if (p == NULL) {
116  FATAL("File " << *i << " has no histogram <" << h2_t << ">." << endl);
117  }
118 
119  if (h2 == NULL)
120  h2 = (TH2D*) p->Clone();
121  else
122  h2->Add(p);
123 
124  h2->SetDirectory(0);
125 
126  in.Close();
127  }
128 
129  if (h2 == NULL) {
130  FATAL("No histogram <" << h2_t << ">." << endl);
131  }
132 
133  // auxiliary data structure for fit result
134 
135  struct result_type {
136 
137  result_type() :
138  value(0.0),
139  error(0.0)
140  {}
141 
142  result_type(double value,
143  double error) :
144  value(value),
145  error(error)
146  {}
147 
148  double value;
149  double error;
150  };
151 
152  typedef map<int, result_type> map_type; // module index -> fit result
153 
154  map_type zmap;
155 
156 
157  // histogram fit results
158 
159  const TAxis* x_axis = h2->GetXaxis();
160  const TAxis* y_axis = h2->GetYaxis();
161 
162  TH1D h0("h0", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
163  TH1D hc("hc", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
164  TH1D hq("hq", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
165 
166 
167  TFile out(outputFile.c_str(), "recreate");
168 
169  for (int ix = 1; ix <= x_axis->GetNbins(); ++ix) {
170 
171  if (detector[ix - 1].getFloor() == 0) {
172  continue;
173  }
174 
175  TH1D h1(MAKE_CSTRING(detector[ix - 1].getID() << ".1D"), NULL, y_axis->GetNbins(), y_axis->GetXmin(), y_axis->GetXmax());
176 
177  // start values
178 
179  Double_t ymax = 0.0;
180  Double_t x0 = 0.0; // [ns]
181  Double_t sigma = 4.5; // [ns]
182  Double_t W = 0.0;
183 
184  for (int iy = 1; iy <= y_axis->GetNbins(); ++iy) {
185 
186  h1.SetBinContent(iy, h2->GetBinContent(ix,iy));
187  h1.SetBinError (iy, sqrt(h2->GetBinContent(ix,iy)));
188 
189  const Double_t x = h1.GetBinCenter (iy);
190  const Double_t y = h1.GetBinContent(iy);
191 
192  W += y;
193 
194  if (y > ymax) {
195  ymax = y;
196  x0 = x;
197  }
198  }
199 
200  if (W <= WMin) {
201 
202  WARNING("Not enough entries for slice " << ix << ' ' << W << "; skip fit." << endl);
203 
204  continue;
205  }
206 
207 
208  const Double_t xmin = x0 + T_ns.getLowerLimit();
209  const Double_t xmax = x0 + T_ns.getUpperLimit();
210 
211 
212  TF1* f1 = NULL;
213 
214  if (function == gauss_t) {
215 
216  f1 = new TF1(function.c_str(), "[0]*TMath::Gaus(x,[1],[2])");
217 
218  f1->SetParameter(0, ymax);
219  f1->SetParameter(1, x0);
220  f1->SetParameter(2, sigma);
221 
222  } else if (function == landau_t) {
223 
224  f1 = new TF1(function.c_str(), "[0]*TMath::Landau(x,[1],[2])");
225 
226  f1->SetParameter(0, ymax);
227  f1->SetParameter(1, x0);
228  f1->SetParameter(2, sigma);
229 
230  } else if (function == emg_t) {
231 
232  f1 = new TF1(function.c_str(), "[0]*TMath::Exp(0.5*[3]*(2.0*[1]+[3]*[2]*[2]-2.0*x))*TMath::Erfc(([1]+[3]*[2]*[2]-x)/(TMath::Sqrt(2.0)*[2]))");
233 
234  f1->SetParameter(0, ymax);
235  f1->SetParameter(1, x0 - sigma);
236  f1->SetParameter(2, sigma);
237  f1->SetParameter(3, 0.04);
238 
239  } else if (function == breitwigner_t) {
240 
241  f1 = new TF1(function.c_str(), "(x <= [1])*[0]*[2]*TMath::BreitWigner(x,[1],[2])+(x > [1])*[0]*[3]*TMath::BreitWigner(x,[1],[3])");
242 
243  f1->SetParameter(0, ymax);
244  f1->SetParameter(1, x0);
245  f1->SetParameter(2, 15.0);
246  f1->SetParameter(3, 25.0);
247 
248  } else {
249 
250  FATAL("Unknown fit function " << function << endl);
251  }
252 
253 
254  DEBUG("Start values:" << endl);
255 
256  for (int i = 0; i != f1->GetNpar(); ++i) {
257  DEBUG(left << setw(12) << f1->GetParName (i) << ' ' <<
258  SCIENTIFIC(12,5) << f1->GetParameter(i) << endl);
259  }
260 
261  // fit
262 
263  TFitResultPtr result = h1.Fit(f1, option.c_str(), "same", xmin, xmax);
264 
265  if (debug >= notice_t || !result->IsValid()) {
266  cout << "Slice: "
267  << setw(4) << ix << ' '
268  << setw(16) << h1.GetName() << ' '
269  << FIXED(7,3) << f1->GetParameter(1) << " +/- "
270  << FIXED(7,3) << f1->GetParError(1) << ' '
271  << FIXED(7,3) << result->Chi2() << '/'
272  << result->Ndf() << ' '
273  << (result->IsValid() ? "" : "failed") << endl;
274  }
275 
276  if (result->IsValid()) {
277  zmap[ix] = result_type(f1->GetParameter(1), f1->GetParError (1));
278  }
279 
280  if (result->Ndf() > 0) {
281  hc.SetBinContent(ix, result->Chi2() / result->Ndf());
282  }
283  hq.SetBinContent(ix, result->IsValid() ? 1.0 : 0.0);
284 
285  h1.Write();
286 
287  delete f1;
288  }
289 
290 
291  if (!zmap.empty()) {
292 
293  // average time offset
294 
295  double t0 = 0.0;
296 
297  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
298  t0 += i->second.value;
299  }
300 
301  t0 /= zmap.size();
302 
303  NOTICE("Average time offset [ns] " << FIXED(7,2) << t0 << endl);
304 
305  for (map_type::iterator i = zmap.begin(); i != zmap.end(); ++i) {
306  i->second.value -= t0;
307  }
308 
309  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
310  h0.SetBinContent(i->first, i->second.value);
311  h0.SetBinError (i->first, i->second.error);
312  }
313 
314  if (!detector.empty()) {
315 
316  const JRange<int> string(make_array(detector.begin(), detector.end(), &JModule::getString));
317  const JRange<int> floor (make_array(detector.begin(), detector.end(), &JModule::getFloor));
318 
319  TH2D hi("hi", NULL,
320  string.getLength() + 1,
321  string.getLowerLimit() - 0.5,
322  string.getUpperLimit() + 0.5,
323  floor.getLength() + 1,
324  floor.getLowerLimit() - 0.5,
325  floor.getUpperLimit() + 0.5);
326 
327  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
328  hi.SetBinContent(detector[i->first - 1].getString(),
329  detector[i->first - 1].getFloor(),
330  i->second.value);
331  }
332 
333  hi.Write();
334  }
335 
336 
337  if (overwriteDetector) {
338 
339  NOTICE("Store calibration data on file " << detectorFile << endl);
340 
341  detector.comment.add(JMeta(argc, argv));
342 
343  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
344 
345  if (E_ns(i->second.error))
346  detector[i->first - 1].sub(i->second.value);
347  else
348  ERROR("Slice " << setw(4) << i->first << " fit uncertainty " << FIXED(5,2) << i->second.error << " outside specified range (option -E <E_ns>)" << endl);
349  }
350 
351  store(detectorFile, detector);
352  }
353 
354  } else {
355 
356  NOTICE("No calibration results." << endl);
357  }
358 
359  h0 .Write();
360  hc .Write();
361  hq .Write();
362  h2->Write();
363 
364  out.Close();
365 }
Auxiliary class for ROOT I/O of application specific meta data.
Definition: JMeta.hh:70
const double xmax
Definition: JQuadrature.cc:24
Utility class to parse command line options.
Definition: JParser.hh:1517
General exception.
Definition: JException.hh:23
debug
Definition: JMessage.hh:29
T getLowerLimit() const
Get lower limit.
Definition: JRange.hh:202
int main(int argc, char *argv[])
Definition: Main.cc:15
Detector data structure.
Definition: JDetector.hh:89
notice
Definition: JMessage.hh:32
#define MAKE_CSTRING(A)
Make C-string.
Definition: JPrint.hh:136
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:446
string outputFile
Data structure for detector geometry and calibration.
const double sigma[]
Definition: JQuadrature.cc:74
T getLength() const
Get length (difference between upper and lower limit).
Definition: JRange.hh:289
const JPolynome f1(1.0, 2.0, 3.0)
Function.
I/O formatting auxiliaries.
Detector file.
Definition: JHead.hh:226
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1993
const array_type< JValue_t > & make_array(const JValue_t(&array)[N])
Method to create array of values.
Definition: JVectorize.hh:54
return result
Definition: JPolint.hh:764
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
ROOT I/O of application specific meta data.
T getUpperLimit() const
Get upper limit.
Definition: JRange.hh:213
#define NOTICE(A)
Definition: JMessage.hh:64
#define ERROR(A)
Definition: JMessage.hh:66
then awk string
General purpose messaging.
#define FATAL(A)
Definition: JMessage.hh:67
const double xmin
Definition: JQuadrature.cc:23
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
Auxiliary class to define a range between two values.
Utility class to parse command line options.
do set_variable DETECTOR_TXT $WORKDIR detector
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY JAcoustics sh $DETECTOR_ID source JAcousticsToolkit sh CHECK_EXIT_CODE typeset A EMITTERS get_tripods $WORKDIR tripod txt EMITTERS get_transmitters $WORKDIR transmitter txt EMITTERS for EMITTER in
Definition: JCanberra.sh:46
then echo WARNING
Definition: JTuneHV.sh:91
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:484
int debug
debug level
JTOOLS::JRange< double > JTimeRange
Type definition for time range (unit [s]).
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62