Jpp  master_rocky
the software that should make you happy
JTestKolmogorov_2D.hh
Go to the documentation of this file.
1 #ifndef __JCOMPAREHISTOGRAMS__JTESTKOLMOGOROV_2D__
2 #define __JCOMPAREHISTOGRAMS__JTESTKOLMOGOROV_2D__
3 
4 #include <istream>
5 #include <ostream>
6 
9 
10 #include "TMath.h"
11 #include "TH2.h"
12 
13 
14 /**
15  * \author rgruiz, bjung
16  */
17 namespace JCOMPAREHISTOGRAMS {}
18 namespace JPP { using namespace JCOMPAREHISTOGRAMS; }
19 
20 namespace JCOMPAREHISTOGRAMS {
21 
22  /**
23  * Implementation of the Kolmogorov test for 2D histograms.\n
24  * This class is derived from the abstract class JTest_t(). For a general description of the implementation of this and other tests derived from JTest_t(), see its documentation.\n
25  * This test compares two 2D histograms. If the parameter `slice` equals x, X y or Y, the histograms are sliced along the corresponding axis, and the Kolmogorov test is applied to each slice.\n
26  * If `slice` equals n or N, the histograms are not sliced, and JKolmogorovTest_2D() is applied.\n
27  * The input parameter `threshold`, is used to evaluate whether the test is passed or failed for each slice or for the full 2D distribution.\n
28  * The parameter `threshold` should therefore be a real value between 0 and 1.
29  */
31  public JTest_t
32  {
33  public:
34 
35  /**
36  * Default constructor.
37  */
39  JTest_t("KS_2D", "p-Value(KS)")
40  {}
41 
42 
43  /**
44  * Applies Kolmogorov test for two ROOT TH2 histograms.
45  *
46  * \param o1 First histogram
47  * \param o2 Second histogram
48  */
49  void test(const TObject* o1, const TObject* o2) override
50  {
51  using namespace std;
52  using namespace JPP;
53 
54  const TH2* h1 = dynamic_cast<const TH2*>(o1);
55  const TH2* h2 = dynamic_cast<const TH2*>(o2);
56 
57  if (h1 == NULL || h2 == NULL) {
58  THROW(JValueOutOfRange, "JTestKolmogorov_2D::test(): Could not cast given TObjects to TH2.");
59  }
60 
61  const int n1x = h1->GetNbinsX();
62  const int n2x = h2->GetNbinsX();
63  const int n1y = h1->GetNbinsY();
64  const int n2y = h2->GetNbinsY();
65 
66  if(n1x != n2x || n1y != n2y)
67  THROW(JValueOutOfRange, "JTestKolmogorov_2D::test(): Histograms with different bining. The objects: " <<
68  h1->GetName() << " and " << h2->GetName() << " can not be compared." << endl);
69 
70  if(h1->Integral() == 0 || h2->Integral() == 0) {
71  THROW(JValueOutOfRange, "JTestKolmogorov_2D::test(): Empty histogram: " <<
72  h1->GetName() << " and " << h2->GetName() << " can not be compared." << endl);
73  }
74 
75  const double s1 = 1./h1->Integral();
76  const double s2 = 1./h2->Integral();
77 
78  TH2* h3 = (TH2*) h1->Clone(h1->GetName() == h2->GetName() ?
79  MAKE_CSTRING(h1->GetName() << "_" << testName) :
80  MAKE_CSTRING(h1->GetName() << "_VS_" << h2->GetName() << "_" << testName));
81 
82  double ew1, ew2, w1 = 0, w2 = 0;
83 
84  for (int i = 1; i <= n1x; ++i) {
85  for (int j = 1; j <= n1y; ++j) {
86  ew1 = h1->GetBinError(i,j);
87  ew2 = h2->GetBinError(i,j);
88  w1 += ew1*ew1;
89  w2 += ew2*ew2;
90  }
91  }
92 
93  bool afunc1 = false;
94  bool afunc2 = false;
95 
96  double esum1 = 0, esum2 = 0;
97 
98  if (w1 > 0) {
99  esum1 = 1./s1/s1/w1;
100  } else {
101  afunc1 = true;
102  }
103 
104  if (w2 > 0) {
105  esum2 = 1./s2/s2/w2;
106  } else {
107  afunc2 = true;
108  }
109 
110  if (afunc2 && afunc1) {
111  THROW(JValueOutOfRange, "JTestKolmogorov_2D::test(): Errors are zero for both histograms");
112  }
113 
114  double c1 = 0, c2 = 0;
115 
116  double dmax1 = 0;
117 
118  for (int i=1 ; i<=n1x ; ++i){
119  for (int j=1 ; j<=n1y ; ++j){
120 
121  c1 += s1*h1->GetBinContent(i,j);
122  c2 += s2*h2->GetBinContent(i,j);
123 
124  double d = TMath::Abs(c1-c2)*TMath::Sqrt(esum1*esum2/(esum1+esum2));
125 
126  dmax1 = TMath::Max(dmax1,TMath::Abs(c1-c2));
127 
128  h3->Fill(i,j,d);
129  }
130  }
131 
132  c1 = 0, c2 = 0;
133 
134  double dmax2 = 0;
135 
136  for (int j=1 ; j<=n1y ; ++j){
137  for (int i=1 ; i<=n1x ; ++i){
138 
139  c1 += s1*h1->GetBinContent(i,j);
140  c2 += s2*h2->GetBinContent(i,j);
141 
142  double d = TMath::Abs(c1-c2)*TMath::Sqrt(esum1*esum2/(esum1+esum2));
143 
144  dmax2 = TMath::Max(dmax2,TMath::Abs(c1-c2));
145 
146  h3->Fill(i,j,d);
147  }
148  }
149 
150  double dmax = 0.5*(dmax1+dmax2);
151 
152  double z;
153 
154  if (afunc1) {
155  z = dmax*TMath::Sqrt(esum2);
156  } else if (afunc2) {
157  z = dmax*TMath::Sqrt(esum1);
158  } else {
159  z = dmax*TMath::Sqrt(esum1*esum2/(esum1+esum2));
160  }
161 
162  const double pValue = TMath::KolmogorovProb(z);
163 
164  for (int i=1 ; i<=n1x ; ++i) {
165  for (int j=1 ; j<=n1y ; ++j) {
166  h3->SetBinContent(i,j,TMath::KolmogorovProb(0.5 * h3->GetBinContent(i,j)));
167  }
168  }
169 
170  const bool passed = (pValue > threshold);
171 
172  const JResultTitle title(testName, resultType, passed, pValue);
173 
174  h3->SetTitle(title.getTitle().c_str());
175  h3->GetZaxis()->SetTitle(resultType.c_str());
176 
177  const JTestResult r (testName,
178  JRootObjectID(MAKE_STRING(h1->GetDirectory()->GetPath() << h1->GetName())),
179  JRootObjectID(MAKE_STRING(h2->GetDirectory()->GetPath() << h1->GetName())),
180  resultType, pValue, threshold, h3, passed);
181 
182  this->push_back(r);
183  }
184 
185 
186  /**
187  * Read test parameters from input.
188  *
189  * \param in input stream
190  * \return input stream
191  */
192  std::istream& read(std::istream& in) override
193  {
194  using namespace JPP;
195 
196  in >> threshold;
197 
198  if (threshold < 0.0 || threshold > 1.0) {
199  THROW(JValueOutOfRange, "JTestKolmogorov_2D::read(): Invalid threshold value " << threshold);
200  }
201 
202  return in >> threshold;
203  }
204 
205 
206  private:
207 
208  double threshold; //!< threshold p-value to decide if test is passed.
209  };
210 }
211 
212 #endif
TCanvas * c1
Global variables to handle mouse events.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
#define MAKE_CSTRING(A)
Make C-string.
Definition: JPrint.hh:72
#define MAKE_STRING(A)
Make string.
Definition: JPrint.hh:63
Class dedicated to standardize the title of the graphical objects produced by the JTest_t() derived c...
Definition: JResultTitle.hh:26
std::string getTitle() const
Returns a standard string to be used as title of a graphical root object.
Definition: JResultTitle.hh:57
Implementation of the Kolmogorov test for 2D histograms.
void test(const TObject *o1, const TObject *o2) override
Applies Kolmogorov test for two ROOT TH2 histograms.
std::istream & read(std::istream &in) override
Read test parameters from input.
double threshold
threshold p-value to decide if test is passed.
Interface to read input and write output for TObject tests.
Definition: JTest_t.hh:42
const std::string resultType
test result type
Definition: JTest_t.hh:181
const std::string testName
test name
Definition: JTest_t.hh:180
Auxiliary class to handle file name, ROOT directory and object name.
Exception for accessing a value in a collection that is outside of its range.
Definition: JException.hh:180
JSqrt< JF1_t > Sqrt(const JF1_t &f1)
Square root of function.
Definition: JMathlib.hh:2136
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
data_type r[M+1]
Definition: JPolint.hh:868
int j
Definition: JPolint.hh:792
Definition: JSTDTypes.hh:14
Structure containing the result of the test.
Definition: JTestResult.hh:30
Definition: JRoot.hh:19