LDMX Software
HcalGeometryVerfifier.cxx
1#include <cmath>
2#include <sstream>
3
4#include "DQM/HcalGeometryVerifier.h"
8namespace dqm {
9
12 hcal_sim_hits_collection_ = parameters.get<std::string>("sim_coll_name");
13 hcal_rec_hits_collection_ = parameters.get<std::string>("rec_coll_name");
14 hcal_sim_hits_pass_name_ = parameters.get<std::string>("sim_pass_name");
15 hcal_rec_hits_pass_name_ = parameters.get<std::string>("rec_pass_name");
16 stop_on_error_ = parameters.get<bool>("stop_on_error");
17 tolerance_ = parameters.get<double>("tolerance_");
18}
20 const auto hcal_sim_hits = event.getCollection<ldmx::SimCalorimeterHit>(
21 hcal_sim_hits_collection_, hcal_sim_hits_pass_name_);
22 const auto hcal_rec_hits = event.getCollection<ldmx::HcalHit>(
23 hcal_rec_hits_collection_, hcal_rec_hits_pass_name_);
24
25 for (const auto& hit : hcal_sim_hits) {
26 const ldmx::HcalID id{static_cast<unsigned int>(hit.getID())};
27 const auto position{hit.getPosition()};
28 auto ok{hitOk(id, {position[0], position[1], position[2]})};
29 histograms_.fill("passes_sim", ok);
30 switch (id.section()) {
31 case ldmx::HcalID::HcalSection::BACK:
32 histograms_.fill("passes_sim_back", ok);
33 break;
34 case ldmx::HcalID::HcalSection::TOP:
35 histograms_.fill("passes_sim_top", ok);
36 break;
37 case ldmx::HcalID::HcalSection::BOTTOM:
38 histograms_.fill("passes_sim_bottom", ok);
39 break;
40 case ldmx::HcalID::HcalSection::LEFT:
41 histograms_.fill("passes_sim_left", ok);
42 break;
43 case ldmx::HcalID::HcalSection::RIGHT:
44 histograms_.fill("passes_sim_right", ok);
45 break;
46 }
47 }
48 for (const auto& hit : hcal_rec_hits) {
49 const ldmx::HcalID id{static_cast<unsigned int>(hit.getID())};
50 auto ok{hitOk(id, {hit.getXPos(), hit.getYPos(), hit.getZPos()})};
51 histograms_.fill("passes_rec", ok);
52 switch (id.section()) {
53 case ldmx::HcalID::HcalSection::BACK:
54 histograms_.fill("passes_rec_back", ok);
55 break;
56 case ldmx::HcalID::HcalSection::TOP:
57 histograms_.fill("passes_rec_top", ok);
58 break;
59 case ldmx::HcalID::HcalSection::BOTTOM:
60 histograms_.fill("passes_rec_bottom", ok);
61 break;
62 case ldmx::HcalID::HcalSection::LEFT:
63 histograms_.fill("passes_rec_left", ok);
64 break;
65 case ldmx::HcalID::HcalSection::RIGHT:
66 histograms_.fill("passes_rec_right", ok);
67 break;
68 }
69 }
70
71} // Analyze
72bool HcalGeometryVerifier::hitOk(const ldmx::HcalID id,
73 const std::array<double, 3>& position) {
74 const auto& geometry = getCondition<ldmx::HcalGeometry>(
76 auto [index_along, index_across, index_through]{determineIndices(id)};
77 const auto center_vec = geometry.getStripCenterPosition(id);
78 const std::array<double, 3> center{center_vec.X(), center_vec.Y(),
79 center_vec.Z()};
80 const auto length{geometry.getScintillatorLength(id)};
81 bool outside_bounds_along{
82 std::abs(position[index_along] - center[index_along]) >
83 length / 2 + tolerance_};
84
85 const auto width{geometry.getScintillatorWidth()};
86 bool outside_bounds_across{
87 std::abs(position[index_across] - center[index_across]) >
88 width / 2 + tolerance_};
89
90 const auto thickness{geometry.getScintillatorThickness()};
91 bool outside_bounds_through{
92 std::abs(position[index_through] - center[index_through]) >
93 thickness / 2 + tolerance_};
94
95 if (outside_bounds_along || outside_bounds_across || outside_bounds_through) {
96 std::stringstream ss;
97 if (tolerance_ < 1) {
98 // Assume tolerance_ is of form 1e-N
99 //
100 // Set precision so it will be clear if it is a floating point precision
101 // issue or a problem
102 ss.precision(-std::log10(tolerance_) + 1);
103 }
104 ss << std::boolalpha;
105 double x{position[0]};
106 double y{position[1]};
107 double z{position[2]};
108 ss << id << " has hit position at (" << x << ", " << y << ", " << z
109 << ")\nwhich is not within the bounds of the Hcal strip center ("
110 << center[0] << ", " << center[1] << ", " << center[2]
111 << ") with tolerance_ " << tolerance_ << std::endl;
112 ss << "Position along the bar: " << position[index_along] << " outside "
113 << center[index_along] << " +- " << length / 2 << "? "
114 << outside_bounds_along << std::endl;
115 ss << "Position across the bar: " << position[index_across] << " outside "
116 << center[index_across] << " +- " << width / 2 << "? "
117 << outside_bounds_across << std::endl;
118 ss << "Position through the bar: " << position[index_through] << " outside "
119 << center[index_through] << " +- " << thickness / 2 << "? "
120 << outside_bounds_through << std::endl;
121
122 if (stop_on_error_) {
123 EXCEPTION_RAISE("InvalidPosition", ss.str());
124 } else {
125 ldmx_log(warn) << ss.str();
126 }
127 return false;
128 }
129 return true;
130}
131std::array<int, 3> HcalGeometryVerifier::determineIndices(
132 const ldmx::HcalID id) {
133 const auto& geometry = getCondition<ldmx::HcalGeometry>(
135 const auto orientation{geometry.getScintillatorOrientation(id)};
136 const auto is_lr{id.section() == ldmx::HcalID::HcalSection::LEFT ||
137 id.section() == ldmx::HcalID::HcalSection::RIGHT};
138
139 int index_along{};
140 int index_across{};
141 int index_through{};
142 if (id.section() == ldmx::HcalID::HcalSection::BACK) {
143 index_through = 2; // z
144 if (orientation ==
145 ldmx::HcalGeometry::ScintillatorOrientation::horizontal) {
146 index_along = 0; // x
147 index_across = 1; // y
148 } else {
149 index_across = 0; // x
150 index_along = 1; // y
151 }
152 } else if (geometry.hasSide3DReadout()) {
153 switch (orientation) {
154 case ldmx::HcalGeometry::ScintillatorOrientation::horizontal:
155 index_across = 2; // z
156 index_along = 0; // x
157 index_through = 1; // y
158 // Horizontal bar in side hcal -> x length, z width, y thick
159 break;
160 case ldmx::HcalGeometry::ScintillatorOrientation::vertical:
161 // Vertical bar in side hcal -> y length, z width, x thick
162 index_across = 2; // z
163 index_along = 1; // y
164 index_through = 0; // x
165 break;
166 case ldmx::HcalGeometry::ScintillatorOrientation::depth:
167 index_along = 2; // z
168 if (is_lr) {
169 // Depth bar in side hcal (LR) -> z length, x thick, y width
170 index_through = 0; // x
171 index_across = 1; // y
172 } else {
173 // Depth bar in side hcal (TB) -> z length, y thick, x width
174 index_through = 1; // y
175 index_across = 0; // x
176 }
177 break;
178 }
179 } else {
180 // v12 Side hcal
181 index_across = 2; // z
182 if (orientation ==
183 ldmx::HcalGeometry::ScintillatorOrientation::horizontal) {
184 index_along = 0; // x
185 index_through = 1; // y
186 } else {
187 index_along = 1; // y
188 index_through = 0; // x
189 }
190 }
191 return {index_along, index_across, index_through};
192}
193} // namespace dqm
#define DECLARE_ANALYZER(CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
Class that translates HCal ID into positions of strip hits.
Class that stores Stores reconstructed hit information from the HCAL.
Class which stores simulated calorimeter hit information.
void configure(framework::config::Parameters &parameters) override
Callback for the EventProcessor to configure itself from the given set of parameters.
void analyze(const framework::Event &event) override
Process the event and make histograms or summaries.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
HistogramPool histograms_
helper object for making and filling histograms
Implements an event buffer system for storing event data.
Definition Event.h:40
void fill(const std::string &name, const T &val)
Fill a 1D histogram.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
static constexpr const char * CONDITIONS_OBJECT_NAME
Conditions object: The name of the python configuration calling this class (Hcal/python/HcalGeometry....
Stores reconstructed hit information from the HCAL.
Definition HcalHit.h:24
Implements detector ids for HCal subdetector.
Definition HcalID.h:19
Stores simulated calorimeter hit information.