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