Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JTestKolmogorov_t.hh
Go to the documentation of this file.
1 #ifndef __JTESTKOLMOGOROV_T__
2 #define __JTESTKOLMOGOROV_T__
3 
4 #include <istream>
5 #include <ostream>
7 
8 /**
9  * \author rgruiz
10  */
11 
12 /**
13  * Implementation of the different Kolmogorov-related tests.
14  */
16 {
17 public:
18  /**
19  * Default constructor.
20  */
22 
23  /**
24  * Kolmogorov test for 1D histograms.\n
25  * The input parameter threshold, is used to evaluate whether the test is passed or failed.\n
26  * The evaluation is done by comparing the threshold value with the result of the Kolmogorov test. The output of a Kolmogorov test is a p-value.\n
27  * The parameter threshold should therefore be a real value between 0 and 1.
28  *
29  * \param h1 First histogram
30  * \param h2 Second historgram
31  * \param threshold p-value
32  * \param parameterName Name of the parameter used to test the histograms
33  * \param testName Name of the test used to compare the histograms
34  *
35  * \return Test result
36  */
37  JTestResult JKolmogorovTest(TH1* h1, TH1* h2, double threshold, std::string testName, std::string parameterName) {
38 
39  using namespace std;
40  using namespace JPP;
41 
42  int n1 = h1 -> GetNbinsX();
43  int n2 = h2 -> GetNbinsX();
44 
45  if(n1 != n2)
46  ERROR("Histograms with different bining. The objects: " << h1 -> GetName() << " can not be compared." << endl);
47 
48  TH2D* h3 = (TH2D*)h1->Clone(h1->GetName()==h2->GetName() ?
49  MAKE_CSTRING(to_string(h1->GetName())) :
50  MAKE_CSTRING(to_string(h1->GetName()) + "_VS_" + to_string(h2->GetName())));
51 
52  bool afunc1 = false;
53  bool afunc2 = false;
54  double s1 = 1./h1->Integral();
55  double s2 = 1./h2->Integral();
56 
57  double ew1, ew2, w1 = 0, w2 = 0;
58 
59  for (int bin = 1; bin <= n1; ++bin){
60  ew1 = h1->GetBinError(bin);
61  ew2 = h2->GetBinError(bin);
62  w1 += ew1*ew1;
63  w2 += ew2*ew2;
64  }
65 
66  double esum1 = 0, esum2 = 0;
67  if (w1 > 0)
68  esum1 = 1./s1/s1/w1;
69  else
70  afunc1 = true;
71  if (w2 > 0)
72  esum2 = 1./s2/s2/w2;
73  else
74  afunc2 = true;
75  if (afunc2 && afunc1) {
76  ERROR("Errors are zero for both histograms\n");
77  }
78 
79  double c1 = 0, c2 = 0;
80 
81  double dmax = 0;
82  for (int bin=1 ; bin<=n1 ; ++bin){
83  c1 += s1*h1->GetBinContent(bin);
84  c2 += s2*h2->GetBinContent(bin);
85  double d = TMath::Abs(c1-c2)*TMath::Sqrt(esum1*esum2/(esum1+esum2));
86  double p = TMath::KolmogorovProb(d);
87  h3->SetBinContent(bin,p);
88  dmax = TMath::Max(dmax,TMath::Abs(c1-c2));
89  }
90 
91  double z;
92 
93  if (afunc1)
94  z = dmax*TMath::Sqrt(esum2);
95  else if (afunc2)
96  z = dmax*TMath::Sqrt(esum1);
97  else
98  z = dmax*TMath::Sqrt(esum1*esum2/(esum1+esum2));
99 
100  double pValue = TMath::KolmogorovProb(z);
101 
102  bool passed;
103 
104  (pValue < threshold ? passed = false : passed = true);
105 
106  JResultTitle title(testName, parameterName, passed , pValue);
107 
108  h3->SetTitle(title.getTitle().c_str());
109 
110  JTestResult r (testName,
111  string (h1->GetDirectory()->GetPath()).append(h1->GetName()),
112  string (h2->GetDirectory()->GetPath()).append(h2->GetName()),
113  h1->GetDirectory()->GetFile()->GetName(),
114  h2->GetDirectory()->GetFile()->GetName(),
115  parameterName, pValue, threshold, h3, passed);
116 
117  return r;
118  };
119 
120 
121  /**
122  * Kolmogorov test for sliced 2D histograms.\n
123  * The histograms are sliced along the axis specified by the slice parameter. A slice per bin is made.\n
124  * For each of the slices, the input parameter threshold is used to evaluate whether the test is passed or failed.\n
125  * The evaluation is done by comparing the threshold value with the result of the Kolmogorov test. The output of the Kolmogorov test is a p-value.\n
126  * The parameter threshold should therefore be a real value between 0 and 1.
127  * The fraction of failed tests is compared to the input parameter failuresThreshold. If this fraction is larger than failuresThreshold, the test fails.
128  *
129  * \param h1 First histogram
130  * \param h2 Second histogram
131  * \param threshold Threshold value for the test result
132  * \param failuresThreshold Threshold value for the test result
133  * \param parameterName Name of the parameter used to test the histograms
134  * \param testName Name of the test used to compare the histograms
135  * \param slice The axis along which the histogram is sliced.
136  *
137  * \return Test result.
138  */
139  JTestResult JKolmogorovTestSlice(TH2* h1, TH2* h2, double threshold, double failuresThreshold, std::string testName, std::string parameterName, char slice) {
140 
141  using namespace std;
142  using namespace JPP;
143 
144  int nFailures = 0;
145 
146  JTestResult r;
147 
148  if(slice == 'x' || slice == 'X'){
149 
150  int nSlices1 = h1->GetNbinsX();
151  int nSlices2 = h2->GetNbinsX();
152 
153  TH1* h3 = h1->ProjectionX(h1->GetName()==h2->GetName() ?
154  MAKE_CSTRING(to_string(h1->GetName())) :
155  MAKE_CSTRING(to_string(h1->GetName()) + "_VS_" + to_string(h2->GetName())));
156 
157  if(nSlices1 != nSlices2)
158  ERROR("Histograms with different binning. The objects: " << h1->GetName() << " and " << h2->GetName() << " can not be compared." << endl);
159 
160  for (int i=1 ; i<=nSlices1 ; ++i){
161 
162  std::string sliceName = MAKE_STRING(h1->GetName() + to_string("_") + to_string(i));
163 
164  TH1D* s1 = h1->ProjectionY (sliceName.c_str(),i,i);
165  TH1D* s2 = h2->ProjectionY (sliceName.c_str(),i,i);
166 
167  double p = s1 -> KolmogorovTest (s2);
168 
169  bool passed;
170 
171  (p < threshold ? passed = false : passed = true);
172 
173  if (!passed) nFailures++;
174 
175  h3->SetBinContent(i,p);
176 
177  }
178 
179  bool passed;
180 
181  (nFailures/nSlices1 > failuresThreshold ? passed = false : passed = true);
182 
183  JResultTitle title(testName, parameterName, passed , nFailures);
184 
185  h3->SetTitle(title.getTitle().c_str());
186 
187  r = JTestResult (testName,
188  string (h1->GetDirectory()->GetPath()).append(h1->GetName()),
189  string (h2->GetDirectory()->GetPath()).append(h2->GetName()),
190  h1->GetDirectory()->GetFile()->GetName(),
191  h2->GetDirectory()->GetFile()->GetName(),
192  parameterName, nFailures, failuresThreshold, h3, passed);
193 
194  }else if (slice == 'y' || slice == 'Y'){
195 
196  int nSlices1 = h1->GetNbinsY();
197  int nSlices2 = h2->GetNbinsY();
198 
199  TH1* h3 = h1->ProjectionY(h1->GetName()==h2->GetName() ?
200  MAKE_CSTRING(to_string(h1->GetName())) :
201  MAKE_CSTRING(to_string(h1->GetName()) + "_VS_" + to_string(h2->GetName())));
202 
203  if(nSlices1 != nSlices2)
204  ERROR("Histograms with different binning. The objects: " << h1->GetName() << " can not be compared." << endl);
205 
206  for (int i=1 ; i<=nSlices1 ; ++i){
207 
208  std::string sliceName = MAKE_STRING(h1->GetName() + to_string("_") + to_string(i));
209 
210  TH1D* s1 = h1->ProjectionX (sliceName.c_str(),i,i);
211  TH1D* s2 = h2->ProjectionX (sliceName.c_str(),i,i);
212 
213  double p = s1 -> KolmogorovTest (s2);
214 
215  bool passed;
216 
217  (p < threshold ? passed = false : passed = true);
218 
219  if (!passed) nFailures++;
220 
221  h3->SetBinContent(i,p);
222  }
223 
224  bool passed;
225 
226  (nFailures/nSlices1 > failuresThreshold ? passed = false : passed = true);
227 
228  JResultTitle title(testName, parameterName, passed , nFailures);
229 
230  h3->SetTitle(title.getTitle().c_str());
231 
232  r = JTestResult (testName,
233  string (h1->GetDirectory()->GetPath()).append(h1->GetName()),
234  string (h2->GetDirectory()->GetPath()).append(h2->GetName()),
235  h1->GetDirectory()->GetFile()->GetName(),
236  h2->GetDirectory()->GetFile()->GetName(),
237  parameterName, nFailures, failuresThreshold, h3, passed);
238 
239  }
240 
241  return r;
242  };
243 
244 
245 
246  /**
247  * Kolmogorov test for 2D histograms.\n
248  * The input parameter threshold, is used to evaluate whether the test is passed or failed.\n
249  * The evaluation is done by comparing the threshold value with the result of the Kolmogorov test. The output of a Kolmogorov test is a p-value.\n
250  * The parameter threshold should therefore be a real value between 0 and 1.
251  *
252  * \param h1 First histogram
253  * \param h2 Second historgram
254  * \param threshold p-value
255  * \param parameterName Name of the parameter used to test the histograms
256  * \param testName Name of the test used to compare the histograms
257  *
258  * \return Test result
259  */
260  JTestResult JKolmogorovTest2D(TH2* h1, TH2* h2, double threshold, std::string testName, std::string parameterName) {
261 
262  using namespace std;
263  using namespace JPP;
264 
265  int n1x = h1 -> GetNbinsX();
266  int n2x = h2 -> GetNbinsX();
267  int n1y = h1 -> GetNbinsY();
268  int n2y = h2 -> GetNbinsY();
269 
270  if(n1x != n2x || n1y != n2y)
271  ERROR("Histograms with different bining. The objects: " << h1 -> GetName() << " can not be compared." << endl);
272 
273  if(h1->Integral()==0 || h2->Integral()==0)
274  ERROR("Empty histogram: " << h1 -> GetName() << " can not be compared." << endl);
275 
276  double s1 = 1./h1->Integral();
277  double s2 = 1./h2->Integral();
278 
279  TH2D* h3 = (TH2D*)h1->Clone(h1->GetName()==h2->GetName() ?
280  MAKE_CSTRING(to_string(h1->GetName())) :
281  MAKE_CSTRING(to_string(h1->GetName()) + "_VS_" + to_string(h2->GetName())));
282 
283  bool afunc1 = false;
284  bool afunc2 = false;
285 
286  double ew1, ew2, w1 = 0, w2 = 0;
287 
288  for (int i = 1; i <= n1x; ++i){
289  for (int j = 1; j <= n1y; ++j){
290  ew1 = h1->GetBinError(i,j);
291  ew2 = h2->GetBinError(i,j);
292  w1 += ew1*ew1;
293  w2 += ew2*ew2;
294  }
295  }
296 
297  double esum1 = 0, esum2 = 0;
298  if (w1 > 0)
299  esum1 = 1./s1/s1/w1;
300  else
301  afunc1 = true;
302  if (w2 > 0)
303  esum2 = 1./s2/s2/w2;
304  else
305  afunc2 = true;
306  if (afunc2 && afunc1) {
307  ERROR("Errors are zero for both histograms\n");
308  }
309 
310  double c1 = 0, c2 = 0;
311 
312  double dmax1 = 0;
313  for (int i=1 ; i<=n1x ; ++i){
314  for (int j=1 ; j<=n1y ; ++j){
315  c1 += s1*h1->GetBinContent(i,j);
316  c2 += s2*h2->GetBinContent(i,j);
317  double d = TMath::Abs(c1-c2)*TMath::Sqrt(esum1*esum2/(esum1+esum2));
318  h3->Fill(i,j,d);
319  dmax1 = TMath::Max(dmax1,TMath::Abs(c1-c2));
320  }
321  }
322 
323  c1 = 0, c2 = 0;
324 
325  double dmax2 = 0;
326  for (int j=1 ; j<=n1y ; ++j){
327  for (int i=1 ; i<=n1x ; ++i){
328  c1 += s1*h1->GetBinContent(i,j);
329  c2 += s2*h2->GetBinContent(i,j);
330  double d = TMath::Abs(c1-c2)*TMath::Sqrt(esum1*esum2/(esum1+esum2));
331  h3->Fill(i,j,d);
332  dmax1 = TMath::Max(dmax2,TMath::Abs(c1-c2));
333  }
334  }
335 
336  double dmax = 0.5*(dmax1+dmax2);
337  double z;
338 
339  if (afunc1)
340  z = dmax*TMath::Sqrt(esum2);
341  else if (afunc2)
342  z = dmax*TMath::Sqrt(esum1);
343  else
344  z = dmax*TMath::Sqrt(esum1*esum2/(esum1+esum2));
345 
346  double pValue = TMath::KolmogorovProb(z);
347 
348  for (int i=1 ; i<=n1x ; ++i){
349  for (int j=1 ; j<=n1y ; ++j){
350  h3->SetBinContent(i,j,TMath::KolmogorovProb(0.5 * h3->GetBinContent(i,j)));
351  }
352  }
353 
354  bool passed;
355 
356  (pValue < threshold ? passed = false : passed = true);
357 
358  JResultTitle title(testName, parameterName, passed , pValue);
359 
360  h3->SetTitle(title.getTitle().c_str());
361 
362  JTestResult r (testName,
363  string (h1->GetDirectory()->GetPath()).append(h1->GetName()),
364  string (h2->GetDirectory()->GetPath()).append(h2->GetName()),
365  h1->GetDirectory()->GetFile()->GetName(),
366  h2->GetDirectory()->GetFile()->GetName(),
367  parameterName, pValue, threshold, h3, passed);
368 
369  return r;
370  };
371 };
372 
373 #endif
Implementation of the different Kolmogorov-related tests.
Class dedicated to standardize the title of the graphical objects produced by the JTest_t() derived c...
Definition: JTest_t.hh:22
#define MAKE_CSTRING(A)
Make C-string.
Definition: JPrint.hh:151
then for HISTOGRAM in h0 h1
Definition: JMatrixNZ.sh:69
data_type r[M+1]
Definition: JPolint.hh:742
JTestResult JKolmogorovTestSlice(TH2 *h1, TH2 *h2, double threshold, double failuresThreshold, std::string testName, std::string parameterName, char slice)
Kolmogorov test for sliced 2D histograms.
Structure containing the result of the test.
Definition: JTest_t.hh:164
#define MAKE_STRING(A)
Make string.
Definition: JPrint.hh:142
#define ERROR(A)
Definition: JMessage.hh:66
JTestResult JKolmogorovTest(TH1 *h1, TH1 *h2, double threshold, std::string testName, std::string parameterName)
Kolmogorov test for 1D histograms.
std::string getTitle()
Returns a standard string to be used as title of a graphical root object.
Definition: JTest_t.hh:67
TCanvas * c1
Global variables to handle mouse events.
then JMuonMCEvt f $INPUT_FILE o $INTERMEDIATE_FILE d
Definition: JMuonPath.sh:45
std::string to_string(const T &value)
Convert value to string.
JTestResult JKolmogorovTest2D(TH2 *h1, TH2 *h2, double threshold, std::string testName, std::string parameterName)
Kolmogorov test for 2D histograms.
JTestKolmogorov_t()
Default constructor.
int j
Definition: JPolint.hh:666