LDMX Software
HistogramPoolTest.cxx
Go to the documentation of this file.
1
8#include <catch2/catch_test_macros.hpp>
9#include <catch2/matchers/catch_matchers.hpp> // IWYU pragma: keep
10
11#include "Framework/HistogramPool.h"
12#include "TFile.h" //to open and check root files
13
15
20TDirectory* cantCreateDir() {
21 throw std::runtime_error("NOFILEGIVEN");
22 return nullptr;
23}
24
33TEST_CASE("HistogramPool Functions", "[Framework][functionality]") {
34 const char* test_file = "/tmp/test_histogram_pool.root";
35
36 SECTION("exception on request") {
38 // raise exception from get_directory
39 REQUIRE_THROWS_WITH(test_pool.create("dne", "foo", 10, 0.0, 1.0),
40 "NOFILEGIVEN");
41 }
42
43 SECTION("creation on request") {
44 TFile* histogram_file{nullptr};
45 auto open_on_request = [&histogram_file, &test_file]() -> TDirectory* {
46 if (histogram_file == nullptr) {
47 histogram_file = TFile::Open(test_file, "recreate");
48 }
49 return histogram_file->mkdir("histo_directory");
50 };
51 HistogramPool test_pool{open_on_request};
52 // test_file has not been opened yet
53 REQUIRE(histogram_file == nullptr);
54 test_pool.create("h", "bla", 10, 0, 1);
55 // test_file exists with histo_directory/ inside of it
56 REQUIRE(histogram_file != nullptr);
57 CHECK(histogram_file->Get("histo_directory") != nullptr);
58 histogram_file->Write();
59 // test_file exists with histo_directory/h inside of it
60 CHECK(histogram_file->Get("histo_directory/h") != nullptr);
61 }
62
63 SECTION("separate pools") {
64 TFile histogram_file{test_file, "recreate"};
65 HistogramPool test_pool_1{[&histogram_file]() {
66 static TDirectory* d{histogram_file.mkdir("p1")};
67 return d;
68 }};
69 HistogramPool test_pool_2{[&histogram_file]() {
70 static TDirectory* d{histogram_file.mkdir("p2")};
71 return d;
72 }};
73 CHECK(histogram_file.Get("p1") == nullptr);
74 CHECK(histogram_file.Get("p2") == nullptr);
75 test_pool_1.create("h", "bar", 10, 0, 1);
76 CHECK(histogram_file.Get("p1") != nullptr);
77 CHECK(histogram_file.Get("p2") == nullptr);
78 test_pool_2.create("h", "buz", 10, 0, 10);
79 CHECK(histogram_file.Get("p1") != nullptr);
80 CHECK(histogram_file.Get("p2") != nullptr);
81 histogram_file.Write();
82 // test_file exists with
83 // p1/h -> 10 bins between 0 and 1
84 // p2/h -> 10 bins between 0 and 10
85 auto h1 = dynamic_cast<TH1F*>(histogram_file.Get("p1/h"));
86 auto h2 = dynamic_cast<TH1F*>(histogram_file.Get("p2/h"));
87 REQUIRE(h1 != nullptr);
88 REQUIRE(h2 != nullptr);
89 CHECK(h1->GetNbinsX() == 10);
90 CHECK(h2->GetNbinsX() == 10);
91 CHECK(h1->GetBinLowEdge(10) == 0.9);
92 CHECK(h2->GetBinLowEdge(10) == 9);
93 }
94
95 // different types of creation
96 SECTION("different types of histograms") {
97 TFile histogram_file{test_file, "recreate"};
98 HistogramPool test_pool{[&histogram_file]() {
99 static TDirectory* d{histogram_file.mkdir("p")};
100 return d;
101 }};
102 std::vector<std::string> cats{"one", "two", "three"};
103
104 test_pool.create("h1_1", "foo", 10, 0, 1);
105 test_pool.create("h1_2", "bar", {0.0, 0.5, 0.8, 1.0}, true);
106 test_pool.create("h1_3", "", cats);
107
108 test_pool.create("h2_1", "baz", 5, -5, 5, "foo", 10, -5, 5);
109 test_pool.create("h2_2", "baz", {-5.0, -1.0, 0.0, 1.0, 5.0}, "foo",
110 {0.0, 1.0, 5.0});
111 test_pool.create("h2_3", "", cats, "", cats);
112
113 test_pool.setWeight(0.75);
114 test_pool.fill("h1_2", 0.75);
115 test_pool.fillw("h1_2", 0.1, 0.5);
116 test_pool.fill("h1_2", 0.75);
117 test_pool.setWeight(1);
118
119 test_pool.fill("h1_3", "one");
120 // "one" again because categories are zero-indexed into bins
121 test_pool.fill("h1_3", 0);
122 // "two" because categories are zero-indexed into bins
123 test_pool.fill("h1_3", 1);
124 // "three" into third bin
125 test_pool.fill("h1_3", "three");
126 // unknown category auto-expands Nbins when
127 // doing categorical axes
128 // test_pool.fill("h1_3", "four");
129
130 test_pool.fill("h2_3", "one", "two");
131
132 histogram_file.Write();
133
134 auto h1_1 = dynamic_cast<TH1F*>(histogram_file.Get("p/h1_1"));
135 REQUIRE(h1_1 != nullptr);
136 CHECK(h1_1->GetNbinsX() == 10);
137 CHECK(h1_1->GetBinLowEdge(1) == 0.0);
138 CHECK(h1_1->GetBinLowEdge(11) == 1.0);
139 REQUIRE(h1_1->GetSumw2() != nullptr);
140 CHECK(h1_1->GetSumw2()->fN == 0);
141
142 auto h1_2 = dynamic_cast<TH1F*>(histogram_file.Get("p/h1_2"));
143 REQUIRE(h1_2 != nullptr);
144 CHECK(h1_2->GetNbinsX() == 3);
145 CHECK(h1_2->GetBinLowEdge(1) == 0.0);
146 CHECK(h1_2->GetBinLowEdge(2) == 0.5);
147 CHECK(h1_2->GetBinLowEdge(3) == 0.8);
148 CHECK(h1_2->GetBinLowEdge(4) == 1.0);
149 CHECK(h1_2->GetBinContent(1) == 0.5);
150 CHECK(h1_2->GetBinContent(2) == 2 * 0.75);
151 REQUIRE(h1_2->GetSumw2() != nullptr);
152 CHECK(h1_2->GetSumw2()->fN == 5);
153 CHECK(h1_2->GetSumw2()->At(1) == 0.25);
154 CHECK(h1_2->GetSumw2()->At(2) == 0.75 * 0.75 * 2);
155
156 auto h1_3 = dynamic_cast<TH1F*>(histogram_file.Get("p/h1_3"));
157 REQUIRE(h1_3 != nullptr);
158 CHECK(h1_3->GetNbinsX() == 3);
159
160 CHECK(h1_3->GetBinContent(0) == 0); // under
161 CHECK(h1_3->GetBinContent(1) == 2); // one
162 CHECK(h1_3->GetBinContent(2) == 1); // two
163 CHECK(h1_3->GetBinContent(3) == 1); // three
164 CHECK(h1_3->GetBinContent(4) == 0); // over
165
166 auto h2_1 = dynamic_cast<TH2F*>(histogram_file.Get("p/h2_1"));
167 REQUIRE(h2_1 != nullptr);
168 CHECK(h2_1->GetNbinsX() == 5);
169 CHECK(h2_1->GetNbinsY() == 10);
170
171 auto h2_2 = dynamic_cast<TH2F*>(histogram_file.Get("p/h2_2"));
172 REQUIRE(h2_2 != nullptr);
173 CHECK(h2_2->GetNbinsX() == 4);
174 CHECK(h2_2->GetNbinsY() == 2);
175
176 auto h2_3 = dynamic_cast<TH2F*>(histogram_file.Get("p/h2_3"));
177 REQUIRE(h2_3 != nullptr);
178 CHECK(h2_3->GetBinContent(1, 2) == 1);
179 }
180}
TEST_CASE("HistogramPool Functions", "[Framework][functionality]")
Test for HistogramPool.
TDirectory * cantCreateDir()
mock exception like the case where configuration did not provide a histogram file
Class for holding an EventProcessor's histogram pointers and making sure that they all end up in the ...
void create(const config::Parameters &p)
Create a histogram from the input configuration parameters.