Jpp 20.0.0-rc.2
the software that should make you happy
Loading...
Searching...
No Matches
JTestSlice2D.hh
Go to the documentation of this file.
1#ifndef __JCOMPAREHISTOGRAMS__JTESTSLICE2D__
2#define __JCOMPAREHISTOGRAMS__JTESTSLICE2D__
3
4#include <memory>
5#include <iostream>
6
7#include "TH1.h"
8#include "TH2.h"
9
10#include "JLang/JException.hh"
11
13
14
15/**
16 * \author bjung
17 */
18namespace JCOMPAREHISTOGRAMS {}
19namespace JPP { using namespace JCOMPAREHISTOGRAMS; }
20
21namespace JCOMPAREHISTOGRAMS {
22
23 /**
24 * Abstract base class for 2D slice tests.
25 * 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
26 * This test uses the input parameter `threshold` to evaluate whether the test is passed or failed for each slice.\n
27 * The evaluation is done by comparing the threshold value with the result of the runs test.\n
28 */
30 public JTest_t
31 {
32 public:
33
34 /**
35 * Constructor.
36 *
37 * \param testName test name
38 * \param resultType result type
39 * \param p pointer to 1D test variant
40 */
41 JTestSlice2D(const std::string& testName,
42 const std::string& resultType,
43 JTest_t* p) :
45 mfp1(&TH2::ProjectionX),
46 mfp2(&TH2::ProjectionY),
47 pTest1D(p),
48 threshold(0.0),
50 slice('x')
51 {
52 using namespace JPP;
53
54 if (!p) {
55 THROW(JNullPointerException, "JTestSlice2D::JTestSlice2D(): Uninitialised 1D test variant");
56 }
57 }
58
59
60 /**
61 * Check if given input histograms have equal binning.
62 *
63 * \param h1 first histogram
64 * \param h2 second histogram
65 */
66 void check(const TH1* h1,
67 const TH1* h2) const
68 {
69 using namespace JPP;
70
71 if (h1 == NULL || h2 == NULL) {
72 THROW(JCastException, "JTestSlice2D::check(): Could not cast given TObjects to TH2.");
73 }
74
75 int nSlices1 = 0;
76 int nSlices2 = 0;
77
78 if (slice == 'x' || slice == 'X') {
79
80 nSlices1 = h1->GetNbinsX();
81 nSlices2 = h2->GetNbinsX();
82
83 } else if (slice == 'y' || slice == 'Y') {
84
85 nSlices1 = h1->GetNbinsY();
86 nSlices2 = h2->GetNbinsY();
87 }
88
89 if (nSlices1 != nSlices2) {
90 THROW(JValueOutOfRange, "JTestSlice2D::configure(): Histograms with different binning. The objects: " << h1->GetName() << " and " << h2->GetName() << " can not be compared");
91 }
92 }
93
94
95 /**
96 * Get projection of given 2D histogram onto sliced axis.
97 *
98 * \param h histogram
99 * \param name name
100 * \param firstBin first bin
101 * \param lastBin last bin
102 * \param option option
103 * \return projection of input histogram on sliced axis
104 */
106 const char* const name = "projection",
107 const Int_t firstBin = 0,
108 const Int_t lastBin = -1,
109 const Option_t* option = "") const
110 {
111 using namespace JPP;
112
113 TH1* hp = (h.*mfp1)(name, firstBin, lastBin, option);
114
115 if (hp != NULL) {
116 return *hp;
117 } else {
118 THROW(JNullPointerException, "JTestSlice2D::getProjectionOntoSlicedAxis(): Projection failed.");
119 }
120 }
121
122
123 /**
124 * Get projection of given 2D histogram onto non-sliced axis.
125 *
126 * \param h histogram
127 * \param name name
128 * \param firstBin first bin
129 * \param lastBin last bin
130 * \param option option
131 * \return projection of input histogram on sliced axis
132 */
133 TH1& getProjection(const TH2& h,
134 const char* const name = "projection",
135 const Int_t firstBin = 0,
136 const Int_t lastBin = -1,
137 const Option_t* option = "") const
138 {
139 using namespace JPP;
140
141 TH1* hp = (h.*mfp2)(name, firstBin, lastBin, option);
142
143 if (hp != NULL) {
144 return *hp;
145 } else {
146 THROW(JNullPointerException, "JTestSlice2D::getProjection(): Projection failed.");
147 }
148 }
149
150
151 /**
152 * Tests the statistical compatibility of two ROOT TObjects
153 *
154 * \param o1 First object
155 * \param o2 Second object
156 */
157 void test(const TObject* o1, const TObject* o2) override
158 {
159 using namespace std;
160 using namespace JPP;
161
162 const TH2* h1 = dynamic_cast<const TH2*>(o1);
163 const TH2* h2 = dynamic_cast<const TH2*>(o2);
164
165 check(h1, h2);
166
167 const char* const h3name = (h1->GetName() == h2->GetName() ?
168 MAKE_CSTRING(h1->GetName() << "_" << testName << "_" << slice) :
169 MAKE_CSTRING(h1->GetName() << "_VS_" << h2->GetName() << "_" << testName << "_" << slice));
170
171 TH1& h3 = getProjectionOntoSlicedAxis(*h1, h3name);
172
173 const int nSlices = h3.GetNbinsX();
174
175 int nFailures = 0;
176
177 for (int i=1 ; i<=nSlices ; ++i){
178
179 const std::string sliceName = MAKE_STRING(h3.GetName() << "_" << to_string(i));
180
181 const TH1& s1 = getProjection(*h1, sliceName.c_str(), i, i);
182 const TH1& s2 = getProjection(*h2, sliceName.c_str(), i, i);
183
184 if (!(s1.GetSumOfWeights() > 0 && s2.GetSumOfWeights() > 0)) { continue; }
185
186 pTest1D->test(&s1, &s2);
187
188 const JTestResult& result1D = pTest1D->back();
189
190 if (!result1D.passed) nFailures++;
191
192 h3.SetBinContent(i, result1D.parameterValue);
193 }
194
195 const bool passed = (nFailures/((double) nSlices) < failuresThreshold);
196
197 const JResultTitle title(testName, resultType, passed , nFailures);
198
199 h3.SetTitle(title.getTitle().c_str());
200 h3.GetYaxis()->SetTitle(resultType.c_str());
201
202 const JTestResult r(testName,
203 JRootObjectID(MAKE_STRING(h1->GetDirectory()->GetPath() << h1->GetName())),
204 JRootObjectID(MAKE_STRING(h2->GetDirectory()->GetPath() << h1->GetName())),
205 resultType, nFailures, failuresThreshold, h3.Clone(), passed);
206
207 this->push_back(r);
208
209 pTest1D->clear();
210 }
211
212
213 /**
214 * Read test parameters from input.
215 *
216 * \param in input stream
217 * \return input stream
218 */
219 std::istream& read(std::istream& in) override
220 {
221 using namespace std;
222 using namespace JPP;
223
224 if (pTest1D) {
225
226 try {
227 in >> (*pTest1D);
228 }
229 catch (const std::exception& error) {
230 THROW(JValueOutOfRange, "JTestSlice2D::read(): Could not read 1D test variant parameters due to the following error:" << endl << error.what());
231 }
232
233 } else {
234 THROW(JNullPointerException, "JTestSlice2D::read(): 1D test variant is not set");
235 }
236
237 in >> failuresThreshold >> slice;
238
240 THROW(JValueOutOfRange, "JTestSlice2D::read(): Invalid failuresThreshold value " << failuresThreshold);
241 }
242
243 if (slice == 'x' || slice == 'X') {
244 mfp1 = &TH2::ProjectionX;
245 mfp2 = &TH2::ProjectionY;
246 } else if (slice == 'y' || slice == 'Y') {
247 mfp1 = &TH2::ProjectionY;
248 mfp2 = &TH2::ProjectionX;
249 } else {
250 THROW(JValueOutOfRange, "JTestSlice2D::read(): Invalid slice option \'" << slice << "\'");
251 }
252
253 return in;
254 };
255
256
257 protected:
258
259 /** Type definition of pointer to `TH2` member function for projection **/
260 typedef TH1D* (TH2::*pFunction)(const char*, Int_t, Int_t, Option_t*) const;
261
262 pFunction mfp1; //!< Pointer to `TH2` member method for projections onto the sliced axis
263 pFunction mfp2; //!< Pointer to `TH2` member method for projections onto the non-sliced axis
264
265 std::unique_ptr<JTest_t> pTest1D; //!< Unique pointer to 1D test variant
266
267 double threshold; //!< threshold value to decide if test has passed.
268 double failuresThreshold; //!< threshold value to decide if test has passed.
269 char slice; //!< Axis to slice. x or X for x-axis, y or Y for y-axis, n or N for None.
270 };
271}
272
273#endif
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
#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...
std::string getTitle() const
Returns a standard string to be used as title of a graphical root object.
Abstract base class for 2D slice tests.
void check(const TH1 *h1, const TH1 *h2) const
Check if given input histograms have equal binning.
pFunction mfp1
Pointer to TH2 member method for projections onto the sliced axis.
pFunction mfp2
Pointer to TH2 member method for projections onto the non-sliced axis.
JTestSlice2D(const std::string &testName, const std::string &resultType, JTest_t *p)
Constructor.
TH1 & getProjectionOntoSlicedAxis(const TH2 &h, const char *const name="projection", const Int_t firstBin=0, const Int_t lastBin=-1, const Option_t *option="") const
Get projection of given 2D histogram onto sliced axis.
std::unique_ptr< JTest_t > pTest1D
Unique pointer to 1D test variant.
TH1 & getProjection(const TH2 &h, const char *const name="projection", const Int_t firstBin=0, const Int_t lastBin=-1, const Option_t *option="") const
Get projection of given 2D histogram onto non-sliced axis.
std::istream & read(std::istream &in) override
Read test parameters from input.
char slice
Axis to slice. x or X for x-axis, y or Y for y-axis, n or N for None.
TH1D *(TH2::*) pFunction(const char *, Int_t, Int_t, Option_t *) const
Type definition of pointer to TH2 member function for projection.
void test(const TObject *o1, const TObject *o2) override
Tests the statistical compatibility of two ROOT TObjects.
double threshold
threshold value to decide if test has passed.
double failuresThreshold
threshold value to decide if test has 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 cast operation.
Exception for null pointer operation.
Exception for accessing a value in a collection that is outside of its range.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Structure containing the result of the test.