Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Functions
JHobbit.cc File Reference

Fit output of JGandalf.cc in calibration mode. More...

#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
#include <map>
#include "TROOT.h"
#include "TFile.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TF1.h"
#include "TMath.h"
#include "TFitResult.h"
#include "JLang/JLangToolkit.hh"
#include "JSupport/JMeta.hh"
#include "JDetector/JDetector.hh"
#include "JDetector/JDetectorToolkit.hh"
#include "JDetector/JTimeRange.hh"
#include "Jeep/JPrint.hh"
#include "Jeep/JParser.hh"
#include "Jeep/JMessage.hh"

Go to the source code of this file.

Functions

int main (int argc, char **argv)
 

Detailed Description

Fit output of JGandalf.cc in calibration mode.

Author
mdejong

Definition in file JHobbit.cc.

Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 45 of file JHobbit.cc.

46 {
47  using namespace std;
48  using namespace JPP;
49 
50  vector<string> inputFile;
51  string outputFile;
52  string detectorFile;
53  bool overwriteDetector;
54  string function;
55  JTimeRange T_ns;
56  string option;
57  JTimeRange E_ns;
58  int debug;
59 
60  try {
61 
62  JParser<> zap("Program to fit output of JGandalf.cc in calibration mode.");
63 
64  zap['f'] = make_field(inputFile, "input files (output from JGandalf -c).");
65  zap['o'] = make_field(outputFile, "output file.") = "hobbit.root";
66  zap['a'] = make_field(detectorFile, "detector file.");
67  zap['A'] = make_field(overwriteDetector, "overwrite detector file provided through '-a' with correct time offsets.");
68  zap['F'] = make_field(function, "fit function") = gauss_t, landau_t, emg_t, breitwigner_t;
69  zap['T'] = make_field(T_ns, "ROOT fit range around maximum [ns].") = JTimeRange(-7.5,+5.0);
70  zap['O'] = make_field(option, "ROOT fit option, see TH1::Fit.") = "";
71  zap['E'] = make_field(E_ns, "validity range of t0 uncertainty [ns].") = JTimeRange( 0.0, 0.3);
72  zap['d'] = make_field(debug) = 1;
73 
74  zap(argc, argv);
75  }
76  catch(const exception &error) {
77  FATAL(error.what() << endl);
78  }
79 
80 
81  cout.tie(&cerr);
82 
83  if (!T_ns.is_valid()) {
84  FATAL("Invalid fit range [ns] " << T_ns << endl);
85  }
86 
87  JDetector detector;
88 
89  try {
90  load(detectorFile, detector);
91  }
92  catch(const JException& error) {
93  FATAL(error);
94  }
95 
96  if (option.find('S') == string::npos) { option += 'S'; }
97  if (option.find('Q') == string::npos && debug < JEEP::debug_t) { option += 'Q'; }
98 
99 
100  TH2D* h2 = NULL;
101 
102  for (vector<string>::const_iterator i = inputFile.begin(); i != inputFile.end(); ++i) {
103 
104  NOTICE("Processing " << *i << endl);
105 
106  TFile in(i->c_str(), "exist");
107 
108  if (!in.IsOpen()) {
109  FATAL("File " << *i << " not opened." << endl);
110  }
111 
112  TH2D* p = dynamic_cast<TH2D*>(in.Get(h2_t));
113 
114  if (p == NULL) {
115  FATAL("File " << *i << " has no histogram <" << h2_t << ">." << endl);
116  }
117 
118  if (h2 == NULL)
119  h2 = (TH2D*) p->Clone();
120  else
121  h2->Add(p);
122 
123  h2->SetDirectory(0);
124 
125  in.Close();
126  }
127 
128  if (h2 == NULL) {
129  FATAL("No histogram <" << h2_t << ">." << endl);
130  }
131 
132  // auxiliary data structure for fit result
133 
134  struct result_type {
135 
136  result_type() :
137  value(0.0),
138  error(0.0)
139  {}
140 
141  result_type(double value,
142  double error) :
143  value(value),
144  error(error)
145  {}
146 
147  double value;
148  double error;
149  };
150 
151  typedef map<int, result_type> map_type; // module index -> fit result
152 
153  map_type zmap;
154 
155 
156  // histogram fit results
157 
158  const TAxis* x_axis = h2->GetXaxis();
159  const TAxis* y_axis = h2->GetYaxis();
160 
161  TH1D h0("h0", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
162  TH1D hc("hc", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
163  TH1D hq("hq", NULL, x_axis->GetNbins(), -0.5, x_axis->GetNbins() - 0.5);
164 
165 
166  TFile out(outputFile.c_str(), "recreate");
167 
168  for (int ix = 1; ix <= x_axis->GetNbins(); ++ix) {
169 
170  TH1D h1(MAKE_CSTRING((detector.empty() ? ix : detector[ix - 1].getID()) << ".1D"), NULL, y_axis->GetNbins(), y_axis->GetXmin(), y_axis->GetXmax());
171  //TH1D h1(MAKE_CSTRING(ix << ".1D"), NULL, y_axis->GetNbins(), y_axis->GetXmin(), y_axis->GetXmax());
172 
173  // start values
174 
175  Double_t ymax = 0.0;
176  Double_t x0 = 0.0; // [ns]
177  Double_t sigma = 4.5; // [ns]
178 
179  for (int iy = 1; iy <= y_axis->GetNbins(); ++iy) {
180 
181  h1.SetBinContent(iy, h2->GetBinContent(ix,iy));
182  h1.SetBinError (iy, sqrt(h2->GetBinContent(ix,iy)));
183 
184  const Double_t x = h1.GetBinCenter (iy);
185  const Double_t y = h1.GetBinContent(iy);
186 
187  if (y > ymax) {
188  ymax = y;
189  x0 = x;
190  }
191  }
192 
193 
194  const Double_t xmin = x0 + T_ns.getLowerLimit();
195  const Double_t xmax = x0 + T_ns.getUpperLimit();
196 
197  const Int_t imin = h1.GetXaxis()->FindBin(xmin);
198  const Int_t imax = h1.GetXaxis()->FindBin(xmax);
199 
200 
201  TF1* f1 = NULL;
202 
203  if (function == gauss_t) {
204 
205  f1 = new TF1(function.c_str(), "[0]*TMath::Gaus(x,[1],[2])");
206 
207  f1->SetParameter(0, ymax);
208  f1->SetParameter(1, x0);
209  f1->SetParameter(2, sigma);
210 
211  } else if (function == landau_t) {
212 
213  f1 = new TF1(function.c_str(), "[0]*TMath::Landau(x,[1],[2])");
214 
215  f1->SetParameter(0, ymax);
216  f1->SetParameter(1, x0);
217  f1->SetParameter(2, sigma);
218 
219  } else if (function == emg_t) {
220 
221  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]))");
222 
223  f1->SetParameter(0, ymax);
224  f1->SetParameter(1, x0 - sigma);
225  f1->SetParameter(2, sigma);
226  f1->SetParameter(3, 0.04);
227 
228  } else if (function == breitwigner_t) {
229 
230  f1 = new TF1(function.c_str(), "(x <= [1])*[0]*[2]*TMath::BreitWigner(x,[1],[2])+(x > [1])*[0]*[3]*TMath::BreitWigner(x,[1],[3])");
231 
232  f1->SetParameter(0, ymax);
233  f1->SetParameter(1, x0);
234  f1->SetParameter(2, 15.0);
235  f1->SetParameter(3, 25.0);
236 
237  } else {
238 
239  FATAL("Unknown fit function " << function << endl);
240  }
241 
242 
243  if ((imax - imin) > f1->GetNpar()) {
244 
245  DEBUG("Start values:" << endl);
246 
247  for (int i = 0; i != f1->GetNpar(); ++i) {
248  DEBUG(left << setw(12) << f1->GetParName (i) << ' ' <<
249  SCIENTIFIC(12,5) << f1->GetParameter(i) << endl);
250  }
251 
252  // fit
253 
254  TFitResultPtr result = h1.Fit(f1, option.c_str(), "same", xmin, xmax);
255 
256  if (debug >= notice_t || !result->IsValid()) {
257  cout << "Slice: "
258  << setw(4) << ix << ' '
259  << setw(16) << h1.GetName() << ' '
260  << FIXED(7,3) << f1->GetParameter(1) << " +/- "
261  << FIXED(7,3) << f1->GetParError(1) << ' '
262  << FIXED(7,3) << result->Chi2() << '/'
263  << result->Ndf() << ' '
264  << (result->IsValid() ? "" : "failed") << endl;
265  }
266 
267  zmap[ix] = result_type(f1->GetParameter(1), f1->GetParError (1));
268 
269  if (result->Ndf() > 0) {
270  hc.SetBinContent(ix, result->Chi2() / result->Ndf());
271  }
272  hq.SetBinContent(ix, result->IsValid() ? 1.0 : 0.0);
273 
274  h1.Write();
275 
276  } else {
277 
278  ERROR("Slice: " << setw(4) << ix << " number of data points " << (imax - imin) << " < " << f1->GetNpar() << endl);
279  }
280 
281  delete f1;
282  }
283 
284 
285  if (!zmap.empty()) {
286 
287  // average time offset
288 
289  double t0 = 0.0;
290 
291  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
292  t0 += i->second.value;
293  }
294 
295  t0 /= zmap.size();
296 
297  NOTICE("Average time offset [ns] " << FIXED(7,2) << t0 << endl);
298 
299  for (map_type::iterator i = zmap.begin(); i != zmap.end(); ++i) {
300  i->second.value -= t0;
301  }
302 
303  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
304  h0.SetBinContent(i->first, i->second.value);
305  h0.SetBinError (i->first, i->second.error);
306  }
307 
308  if (!detector.empty()) {
309 
310  const JRange<int> string(detector.begin(), detector.end(), &JModule::getString);
311  const JRange<int> floor (detector.begin(), detector.end(), &JModule::getFloor);
312 
313  TH2D hi("hi", NULL,
314  string.getLength() + 1,
315  string.getLowerLimit() - 0.5,
316  string.getUpperLimit() + 0.5,
317  floor.getLength() + 1,
318  floor.getLowerLimit() - 0.5,
319  floor.getUpperLimit() + 0.5);
320 
321  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
322  hi.SetBinContent(detector[i->first - 1].getString(),
323  detector[i->first - 1].getFloor(),
324  i->second.value);
325  }
326 
327  hi.Write();
328  }
329 
330 
331  if (overwriteDetector) {
332 
333  NOTICE("Store calibration data on file " << detectorFile << endl);
334 
335  detector.comment.add(JMeta(argc, argv));
336 
337  for (map_type::const_iterator i = zmap.begin(); i != zmap.end(); ++i) {
338 
339  if (E_ns(i->second.error))
340  detector[i->first - 1].add(i->second.value);
341  else
342  ERROR("Slice " << setw(4) << i->first << " fit uncertainty " << FIXED(5,2) << i->second.error << " outside specified range (option -E <E_ns>)" << endl);
343  }
344 
345  store(detectorFile, detector);
346  }
347 
348  } else {
349 
350  NOTICE("No calibration results." << endl);
351  }
352 
353  h0 .Write();
354  hc .Write();
355  hq .Write();
356  h2->Write();
357 
358  out.Close();
359 }
Utility class to parse command line options.
Definition: JParser.hh:1410
debug
Definition: JMessage.hh:27
notice
Definition: JMessage.hh:30
#define MAKE_CSTRING(A)
Make C-string.
Definition: JPrint.hh:611
Auxiliary data structure for floating point format specification.
Definition: JPrint.hh:461
string outputFile
JRange< double > JTimeRange
Type definition for time range.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1836
#define NOTICE(A)
Definition: JMessage.hh:62
#define ERROR(A)
Definition: JMessage.hh:64
void load(const JString &file_name, JDetector &detector)
Load detector from input file.
int debug
debug level
Definition: JSirene.cc:59
#define FATAL(A)
Definition: JMessage.hh:65
void store(const JString &file_name, const JDetector &detector)
Store detector to output file.
Auxiliary data structure for floating point format specification.
Definition: JPrint.hh:498
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:60