Jpp  17.3.2
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JFitL1dtSlices.cc
Go to the documentation of this file.
2 #include "JDetector/JDetector.hh"
4 #include "Jeep/JParser.hh"
5 
6 #include "TF2.h"
7 #include "TFile.h"
8 #include "TH1D.h"
9 #include "TH2D.h"
10 #include "TMath.h"
11 
12 #include <iostream>
13 #include <string>
14 
15 
16 namespace FITL1DTSLICES {
17 
18  /* Calculate the log-poisson
19  *
20  * This function has some assumptions: since the input data from JMonitorL1dt use SN datastream
21  * most background is strongly suppressed. This means many bins on both data and model will
22  * have no entries: n = 0 or nhat = 0. This will result in infinities when calculating the
23  * log-poisson. To avoid the infities the options below are used.
24  * This has been crosschecked with L1 datastream which gives a significant background and the
25  * shapes of the likelihood distributions are similar.
26  */
27  double logPoison(double n, double nhat, double logP_min = -999999.9) {
28  if (nhat < 0.0 || n < 0.0) {
29  FATAL("logPoisson: n (" << n <<") or nhat (" << nhat << ") is < 0.0" << std::endl);
30  }
31  if (n == 0.0 && nhat == 0.0) {
32  return 0.0; // ok.
33  }
34  if (n == 0.0 && nhat > 0.0) {
35  return -1*nhat; // log( lab^0 * e^-lab / 0! ) = log( e^-lab ) = -lab, ok.
36  }
37  if (n >= 0.0 && nhat == 0.0) {
38  return 0.0; // should be -inf, we only consider bins where we expect non-zero entries: no expected entries we throw away.
39  }
40  Double_t poisson = TMath::Poisson(n, nhat);
41  if (poisson == 0) return 0.0; // only when model and data are close enough do we care about their values, so if P=0, do nothing, since we are not in the region we care about.
42  else return TMath::Log(poisson);
43  }
44 
45  double getLogQuality(const TH1D* data, const TH1D* model, int di, double data_bkg = 0.0001, double model_bkg = 0.0001) {
46 
47  double q = 0.0;
48 
49  // If you calculate over the whole histogram you lose bins at edges: only when dt=0 are all N bins considered, everywhere else
50  // either data or model bins get lost at the edge. So integrate over a smaller range:
51  int i_low = data->GetNbinsX() / 4; // Start at a quarter of the hist
52  int i_hgh = data->GetNbinsX() / 4 * 3; // End at three quarters
53  for (int i = i_low; i <= i_hgh; ++i) {
54  double n = data_bkg;
55  double nhat = model_bkg;
56  if (i >= 1 && i <= data->GetNbinsX()) {
57  // Count in bin i for the data
58  n = data->GetBinContent(i);
59  }
60  if (i+di >= 1 && i+di <= model->GetNbinsX()) {
61  // Count in bin i+di for the model
62  nhat = model->GetBinContent(i+di);
63  }
64  double logP = logPoison(n, nhat);
65  q += logP; // Added 0 for when the background is zero in model and data, but then P(n|0) gives inf! So removed overwritten logPmin
66  }
67  return q;
68  }
69 }
70 
71 
72 /**
73  * \file
74  *
75  * Auxiliary program to fit L1dt output data to an L1dt model, both created with JMonitorL1dt
76  *
77  * \author kmelis, lnauta
78  */
79 int main(int argc, char **argv)
80 {
81  using namespace std;
82  using namespace FITL1DTSLICES;
83  using namespace JPP;
84 
85  string inputFile;
86  string modelFile;
87  string outputFile;
88  string detectorFile;
89  double dt_fitrange;
90  int rebin;
91  double TMax_ns;
92  bool normaliseMC;
93  int debug;
94 
95  try {
96 
97  JParser<> zap("Program to calculate log-likelihood distributions between DOM pairs and fit a poly2 to find the shape, used in FitL1dt to find time offsets");
98 
99  zap['f'] = make_field(inputFile, "input file") = "monitor.root";
100  zap['m'] = make_field(modelFile, "model file");
101  zap['o'] = make_field(outputFile, "output file") = "fitslices.root";
102  zap['a'] = make_field(detectorFile, "detector file");
103  zap['T'] = make_field(TMax_ns, "scan range around 0 in data-model comparison [ns]") = 50.0;
104  zap['t'] = make_field(dt_fitrange, "fitrange of polynomial to quality [ns]") = 5.0;
105  zap['r'] = make_field(rebin, "rebin the histograms") = 1;
106  zap['N'] = make_field(normaliseMC, "normalize the MC histogram");
107  zap['d'] = make_field(debug) = 0;
108 
109  if (zap.read(argc, argv) != 0) {
110  return 1;
111  }
112  }
113  catch(const exception &error) {
114  FATAL(error.what() << endl);
115  }
116 
117 
118  const double TSignal_ns = 750.0; // The width of the signal for integrating out the background
119 
121 
122  try {
123  load(detectorFile, detector);
124  }
125  catch(const JException& error) {
126  FATAL(error);
127  }
128 
129 
130  TFile* in = TFile::Open(inputFile.c_str(), "exist");
131  TFile* in_model = TFile::Open(modelFile.c_str(), "exist");
132 
133  if (in == NULL || !in->IsOpen()) {
134  FATAL("File: " << inputFile << " not opened." << endl);
135  }
136  if (in_model == NULL || !in_model->IsOpen()) {
137  FATAL("File: " << modelFile << " not opened." << endl);
138  }
139 
140  TFile out(outputFile.c_str(), "recreate");
141 
142  TH2D h2A("Aij", "Aij", detector.size(), -0.5, detector.size()-0.5, detector.size(), -0.5, detector.size()-0.5);
143  TH2D h2B("Bij", "Bij", detector.size(), -0.5, detector.size()-0.5, detector.size(), -0.5, detector.size()-0.5);
144  TH2D h2C("Cij", "Cij", detector.size(), -0.5, detector.size()-0.5, detector.size(), -0.5, detector.size()-0.5);
145 
146  // The bare histogram can be used for debugging, it contains the actual time offsets.
147  // Histogram Bij contains Bij/2Aij due to a different representation used in the code compared to the mathematical formulation.
148  TH2D h2Bbare("Bij_bare", "Bij_bare", detector.size(), -0.5, detector.size()-0.5, detector.size(), -0.5, detector.size()-0.5);
149  for (JDetector::iterator moduleA = detector.begin(); moduleA != detector.end(); ++moduleA) {
150  const int idom = distance(detector.begin(), moduleA);
151  TString label = Form("%i", moduleA->getID());
152  h2A.GetXaxis()->SetBinLabel(idom+1, label);
153  h2A.GetYaxis()->SetBinLabel(idom+1, label);
154  h2B.GetXaxis()->SetBinLabel(idom+1, label);
155  h2B.GetYaxis()->SetBinLabel(idom+1, label);
156  h2C.GetXaxis()->SetBinLabel(idom+1, label);
157  h2C.GetYaxis()->SetBinLabel(idom+1, label);
158 
159  h2Bbare.GetXaxis()->SetBinLabel(idom+1, label);
160  h2Bbare.GetYaxis()->SetBinLabel(idom+1, label);
161  }
162 
163  for (JDetector::iterator moduleA = detector.begin(); moduleA != detector.end(); ++moduleA) {
164 
165  DEBUG("Module " << moduleA->getID() << endl);
166  const JString title = JString(moduleA->getID());
167  const int idom = distance(detector.begin(), moduleA);
168 
169  // data
170  TH2D* d2s = (TH2D*) in->Get((title + ".2S").c_str());
171  TH1D* d1l = (TH1D*) in->Get((title + ".1L").c_str());
172 
173  if (d2s == NULL || d1l == NULL) {
174  WARNING("No data in data histogram " << title << endl);
175  continue;
176  }
177 
178  // model
179  TH2D* m2s = (TH2D*) in_model->Get((title + ".2S").c_str());
180  TH1D* m1l = (TH1D*) in_model->Get((title + ".1L").c_str());
181 
182  if (m2s == NULL || m1l == NULL) {
183  WARNING("No mata in model histogram " << title << endl);
184  continue;
185  }
186 
187 
188  for (JDetector::iterator moduleB = moduleA; moduleB != detector.end(); ++moduleB) {
189  const int jdom = distance(detector.begin(), moduleB);
190 
191  if (moduleB->getID() == moduleA->getID()) {
192  continue;
193  }
194  if (moduleB->getString() != moduleA->getString()) {
195  continue;
196  }
197 
198  TH1D* d1s = d2s->ProjectionY((title + Form(".%i.d1S", moduleB->getID())).c_str(),
199  d2s->GetXaxis()->FindBin(TString(Form("%i", moduleB->getID()))),
200  d2s->GetXaxis()->FindBin(TString(Form("%i", moduleB->getID()))), "e");
201  TH1D* m1s = m2s->ProjectionY((title + Form(".%i.m1S", moduleB->getID())).c_str(),
202  m2s->GetXaxis()->FindBin(TString(Form("%i", moduleB->getID()))),
203  m2s->GetXaxis()->FindBin(TString(Form("%i", moduleB->getID()))), "e");
204 
205  if (d1s->Integral() <= 0.0 || m1s->Integral() <= 0.0) {
206  continue;
207  }
208 
209  // background fit: data
210  double binCenterMaxBin = d1s->GetXaxis()->GetBinCenter(d1s->GetMaximumBin());
211  double backgroundrate_s = 0.0;
212  int nbins = 0;
213  for (int j = 1; j <= d1s->GetXaxis()->GetNbins(); ++j) {
214  if (fabs(d1s->GetXaxis()->GetBinCenter(j) - binCenterMaxBin) > TSignal_ns ) {
215  backgroundrate_s += d1s->GetBinContent(j);
216  nbins++;
217  }
218  }
219  backgroundrate_s /= nbins;
220 
221  // background fit: model
222  binCenterMaxBin = m1s->GetXaxis()->GetBinCenter(m1s->GetMaximumBin());
223  double backgroundrate_m = 0.0;
224  nbins = 0;
225  for (int j = 1; j <= m1s->GetXaxis()->GetNbins(); ++j) {
226  if (fabs(m1s->GetXaxis()->GetBinCenter(j) - binCenterMaxBin) > TSignal_ns ) {
227  backgroundrate_m += m1s->GetBinContent(j);
228  nbins++;
229  }
230  }
231  backgroundrate_m /= nbins;
232 
233  // scale livetimes and remove background
234  const double Ld = d1l->GetBinContent(d1l->GetXaxis()->FindBin(TString(Form("%i", moduleB->getID()))));
235  const double Lm = m1l->GetBinContent(m1l->GetXaxis()->FindBin(TString(Form("%i", moduleB->getID()))));
236 
237  for (int j = 1; j <= d1s->GetXaxis()->GetNbins(); ++j) {
238  const double y = d1s->GetBinContent(j);
239  const double dy = d1s->GetBinError(j);
240 
241  d1s->SetBinContent(j, y);
242  d1s->SetBinError(j, dy);
243  }
244 
245  // scale the livetime of the model
246  for (int j = 1; j <= m1s->GetXaxis()->GetNbins(); ++j) {
247  const double y = m1s->GetBinContent(j);
248  const double dy = m1s->GetBinError(j);
249 
250  m1s->SetBinContent(j, y * Ld/Lm);
251  m1s->SetBinError(j, dy*Ld/Lm);
252  }
253 
254 
255  if (normaliseMC) {
256  const double scalefactor = d1s->Integral()/m1s->Integral();
257  m1s->Scale(scalefactor);
258  }
259 
260  // rebin
261  d1s->Rebin(rebin);
262  m1s->Rebin(rebin);
263 
264  // write background subtracted, normalised slices
265  d1s->Write();
266  m1s->Write();
267 
268  // get quality
269  int ddt_min = -0.5*TMax_ns; // maximum time shift [ns]
270  int ddt_max = 0.5*TMax_ns; // maximum time shift [ns]
271 
272  TH1D q1((title + Form(".%i.q1", moduleB->getID())).c_str(), (title + Form(".%i.q1", moduleB->getID())).c_str(), (ddt_max-ddt_min)/rebin+1, ddt_min-0.5*rebin, ddt_max+0.5*rebin);
273 
274  for (int di = 1; di <= q1.GetNbinsX(); di++) {
275  q1.SetBinContent(di, getLogQuality(d1s, m1s, (int)(q1.GetBinCenter(di)/rebin), 0.0, 0.0));
276  }
277 
278  // Fit peak with parabola
279  const double dt_fitmid = q1.GetBinCenter(q1.GetMaximumBin());
280 
281  TF1 q1f((title + Form(".%i.q1f", moduleB->getID())).c_str(), "[0]*x*x + [1]*x + [2]", dt_fitmid - dt_fitrange, dt_fitmid + dt_fitrange);
282  q1f.SetParLimits(0, -1e5, 0.0); // Added as to improve fits. Aij should always be l.t. 0 to fit a maximum to the LLH
283 
284  string fitoptions = "R";
285  if (debug < JEEP::debug_t) {
286  fitoptions += " Q";
287  }
288  q1.Fit(&q1f, fitoptions.c_str());
289 
290  // write quality and fit
291  q1.Write();
292 
293  // Fit results to global fit matrix
294  const double Aij = q1f.GetParameter(0);
295  const double Bij = q1f.GetParameter(1);
296  const double Cij = q1f.GetParameter(2);
297 
298  double bareBij = Bij / Aij;
299  if (Aij == 0) bareBij = 0;
300 
301  if (fabs(-0.5*Bij/Aij - dt_fitmid) > 3 || fabs(-0.5*Bij/Aij) > dt_fitrange) {
302  WARNING(" Please check fit of pair " << idom << ", " << jdom << " : " << moduleA->getID() << ", " << moduleB->getID() << endl);
303  WARNING(" DOMpair " << idom << "; " << jdom << " A=" << Aij << " B=" << Bij << " , max at: " << dt_fitmid << " [ns], best fit at " << -0.5*Bij/Aij << " ns " << endl);
304  }
305  DEBUG("DOMpair " << idom << "; " << jdom << " A=" << Aij << " B=" << Bij << " , max at: " << dt_fitmid << " [ns], best fit at " << -0.5*Bij/Aij << " ns " << endl);
306 
307  h2A.SetBinContent(idom+1, jdom+1, Aij);
308  h2A.SetBinContent(jdom+1, idom+1, Aij);
309  h2B.SetBinContent(idom+1, jdom+1, Bij);
310  h2B.SetBinContent(jdom+1, idom+1,-Bij);
311  h2C.SetBinContent(idom+1, jdom+1, Cij);
312  h2C.SetBinContent(jdom+1, idom+1, Cij);
313 
314  h2Bbare.SetBinContent(idom+1, jdom+1, bareBij);
315  h2Bbare.SetBinContent(jdom+1, idom+1, 0);
316  }
317  }
318 
319  out.cd();
320 
321  h2A.Write();
322  h2B.Write();
323  h2C.Write();
324 
325  h2Bbare.Write();
326 
327  out.Close();
328 }
Utility class to parse command line options.
Definition: JParser.hh:1517
General exception.
Definition: JException.hh:23
debug
Definition: JMessage.hh:29
int main(int argc, char *argv[])
Definition: Main.cc:15
Wrapper class around STL string class.
Definition: JString.hh:27
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
Detector data structure.
Definition: JDetector.hh:89
string outputFile
Data structure for detector geometry and calibration.
const int n
Definition: JPolint.hh:697
Detector file.
Definition: JHead.hh:226
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1993
#define FATAL(A)
Definition: JMessage.hh:67
double Poisson(const size_t n, const double mu)
Poisson cumulative density distribition.
int read(const int argc, const char *const argv[])
Parse the program&#39;s command line options.
Definition: JParser.hh:1815
void load(const std::string &file_name, JDetector &detector)
Load detector from input file.
Utility class to parse command line options.
double poisson(const size_t n, const double mu)
Poisson probability density distribition.
int j
Definition: JPolint.hh:703
do set_variable DETECTOR_TXT $WORKDIR detector
KM3NeT DAQ constants, bit handling, etc.
double logPoison(double n, double nhat, double logP_min=-999999.9)
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
int debug
debug level
#define DEBUG(A)
Message macros.
Definition: JMessage.hh:62
double getLogQuality(const TH1D *data, const TH1D *model, int di, double data_bkg=0.0001, double model_bkg=0.0001)