Jpp  19.1.0
the software that should make you happy
JTestRuns_Slice2D.hh
Go to the documentation of this file.
1 #ifndef __JCOMPAREHISTOGRAMS__JTESTRUNS_2D__
2 #define __JCOMPAREHISTOGRAMS__JTESTRUNS_2D__
3 
4 #include <istream>
5 #include <ostream>
6 
7 #include "JLang/JException.hh"
8 
11 
12 #include "TH1.h"
13 #include "TH2.h"
14 
15 
16 /**
17  * \author rgruiz, bjung
18  */
19 namespace JCOMPAREHISTOGRAMS {}
20 namespace JPP { using namespace JCOMPAREHISTOGRAMS; }
21 
22 namespace JCOMPAREHISTOGRAMS {
23 
24  /**
25  * Implementation of the Chi2 test for 2D histograms.\n
26  * 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
27  * The parameter `slice` can have the values x, X, y or Y. The histograms are sliced along the corresponding axis, and the runs test is applied to each slice.\n
28  * This test uses the input parameter `threshold` to evaluate whether the test is passed or failed for each slice.\n
29  * The evaluation is done by comparing the threshold value with the result of the runs test.\n
30  * The results for each slice are stored in the results buffer (see JTest_t())
31  */
33  public JTest_t
34  {
35  public:
36 
37  /**
38  * Default constructor.
39  */
41  JTest_t("Runs_2D", "#sigma")
42  {}
43 
44 
45  /**
46  * Tests the statistical compatibility of two ROOT TObjects
47  *
48  * \param o1 First object
49  * \param o2 Second object
50  */
51  void test(const TObject* o1, const TObject* o2) override
52  {
53  using namespace std;
54  using namespace JPP;
55 
56  const TH2* h1 = dynamic_cast<const TH2*>(o1);
57  const TH2* h2 = dynamic_cast<const TH2*>(o2);
58 
59  if (h1 == NULL || h2 == NULL) {
60  THROW(JValueOutOfRange, "JTestKolmogorov_Slice2D::test(): Could not cast given TObjects to TH2.");
61  }
62 
63  TH1* h3 = NULL;
64 
65  const char* const h3name = (h1->GetName() == h2->GetName() ?
66  MAKE_CSTRING(h1->GetName() << "_" << testName << "_" << slice) :
67  MAKE_CSTRING(h1->GetName() << "_VS_" << h2->GetName() << "_" << testName << "_" << slice));
68 
69  int nFailures = 0;
70  int nSlices = 0;
71 
72  if (slice == 'x' || slice == 'X') {
73 
74  const int nSlices1 = h1->GetNbinsX();
75  const int nSlices2 = h2->GetNbinsX();
76 
77  if (nSlices1 != nSlices2) {
78  THROW(JValueOutOfRange, "JTestRuns_Slice2D::test(): Histograms with different binning. The objects: " << h1->GetName() << " and " << h2->GetName() << " can not be compared." << endl);
79  }
80 
81  nSlices = nSlices1;
82 
83  h3 = h1->ProjectionX(h3name);
84 
85  for (int i=1 ; i<=nSlices1 ; ++i){
86 
87  const std::string sliceName = MAKE_STRING(h3->GetName() << "_" << to_string(i));
88 
89  const TH1* s1 = h1->ProjectionY (sliceName.c_str(),i,i);
90  const TH1* s2 = h2->ProjectionY (sliceName.c_str(),i,i);
91 
92  if (!(s1->GetSumOfWeights() > 0 && s2->GetSumOfWeights() > 0)) { continue; }
93 
94  const double R = s1->Integral();
95  const double T = s2->Integral();
96 
97  bool a = ((T/R)*s1->GetBinContent(1) - s2->GetBinContent(1)) < 0;
98 
99  int n = 1;
100  double p = (a ? 1 : 0);
101  double q = (a ? 0 : 1);
102 
103  for (int i = 2 ; i<s1->GetNbinsX() ; ++i){
104 
105  const bool b = ((T/R)*s1->GetBinContent(i) - s2->GetBinContent(i)) < 0;
106 
107  (b ? ++p : ++q);
108 
109  if (b != a){
110  ++n;
111  a=b;
112  }
113  }
114 
115  const double N = 1 + 2*p*q/(p+q) ;
116  const double s = sqrt( 2*p*q*(2*p*q-p-q)/(p+q)/(p+q)/(p+q-1) );
117  const double d = (n-N)/s;
118 
119  if (fabs(d) > threshold) nFailures++;
120 
121  h3->SetBinContent(i,fabs(d));
122  }
123 
124  } else if (slice == 'y' || slice == 'Y') {
125 
126  const int nSlices1 = h1->GetNbinsX();
127  const int nSlices2 = h2->GetNbinsX();
128 
129  if (nSlices1 != nSlices2) {
130  THROW(JValueOutOfRange, "JTestRuns_Slice2D::test(): Histograms with different binning. The objects: " << h1->GetName() << " and " << h2->GetName() << " can not be compared." << endl);
131  }
132 
133  nSlices = nSlices1;
134 
135  h3 = h1->ProjectionY(h3name);
136 
137  for (int i=1 ; i<=nSlices1 ; ++i){
138 
139  const std::string sliceName = MAKE_STRING(h3->GetName() << "_" << to_string(i));
140 
141  const TH1* s1 = h1->ProjectionX (sliceName.c_str(),i,i);
142  const TH1* s2 = h2->ProjectionX (sliceName.c_str(),i,i);
143 
144  if (!(s1->GetSumOfWeights() > 0 && s2->GetSumOfWeights() > 0)) { continue; }
145 
146  const double R = s1->Integral();
147  const double T = s2->Integral();
148 
149  bool a = ((T/R)*s1->GetBinContent(1) - s2->GetBinContent(1)) < 0;
150 
151  int n = 1;
152  double p = (a ? 1 : 0);
153  double q = (a ? 0 : 1);
154 
155  for (int i = 2 ; i<s1->GetNbinsX() ; ++i){
156 
157  const bool b = ((T/R)*s1->GetBinContent(i) - s2->GetBinContent(i)) < 0;
158 
159  (b ? ++p : ++q);
160 
161  if (b != a){
162  ++n;
163  a=b;
164  }
165  }
166 
167  const double N = 1 + 2*p*q/(p+q) ;
168  const double s = sqrt( 2*p*q*(2*p*q-p-q)/(p+q)/(p+q)/(p+q-1) );
169  const double d = (n-N)/s;
170 
171  if (fabs(d) > threshold) nFailures++;
172 
173  h3->SetBinContent(i,fabs(d));
174  }
175  }
176 
177  const bool passed = (nFailures/nSlices < failuresThreshold);
178 
179  const JResultTitle title(testName, resultType, passed , nFailures);
180 
181  h3->SetTitle(title.getTitle().c_str());
182  h3->GetYaxis()->SetTitle(resultType.c_str());
183 
184  const JTestResult r(testName,
185  JRootObjectID(MAKE_STRING(h1->GetDirectory()->GetPath() << h1->GetName())),
186  JRootObjectID(MAKE_STRING(h2->GetDirectory()->GetPath() << h1->GetName())),
187  resultType, nFailures, failuresThreshold, h3, passed);
188 
189  this->push_back(r);
190  }
191 
192 
193  /**
194  * Read test parameters from input.
195  *
196  * \param in input stream
197  * \return input stream
198  */
199  std::istream& read(std::istream& in) override
200  {
201  using namespace JPP;
202 
203  in >> threshold >> failuresThreshold >> slice;
204 
205  if (threshold < 0.0) {
206  THROW(JValueOutOfRange, "JTestRuns_Slice2D::read(): Invalid failuresThreshold value " << failuresThreshold);
207  }
208 
209  if (failuresThreshold < 0.0 || failuresThreshold > 1.0) {
210  THROW(JValueOutOfRange, "JTestRuns_Slice2D::read(): Invalid failuresThreshold value " << failuresThreshold);
211  }
212 
213  if (slice != 'x' && slice != 'X' && slice != 'y' && slice != 'Y') {
214  THROW(JValueOutOfRange, "JTestRuns_Slice2D::read(): Invalid slice option \'" << slice << "\'");
215  }
216 
217  return in;
218  };
219 
220  private:
221 
222  double threshold; //!< threshold value to decide if test is passed.
223  double failuresThreshold; //!< threshold value to decide if test is passed.
224  char slice; //!< Axis to slice. x or X for x-axis, y or Y for y-axis, n or N for None.
225  };
226 }
227 
228 #endif
Exceptions.
#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 Chi2 test for 2D histograms.
double failuresThreshold
threshold value to decide if test is passed.
double threshold
threshold value to decide if test is passed.
char slice
Axis to slice. x or X for x-axis, y or Y for y-axis, n or N for None.
void test(const TObject *o1, const TObject *o2) override
Tests the statistical compatibility of two ROOT TObjects.
std::istream & read(std::istream &in) override
Read test parameters from input.
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
const double a
Definition: JQuadrature.cc:42
std::string to_string(const T &value)
Convert value to string.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
const int n
Definition: JPolint.hh:786
data_type r[M+1]
Definition: JPolint.hh:868
Definition: JSTDTypes.hh:14
Structure containing the result of the test.
Definition: JTestResult.hh:30
Definition: JRoot.hh:19