LDMX Software
HcalSimpleDigiAndRecProducer.cxx
1#include "Hcal/HcalSimpleDigiAndRecProducer.h"
2
4#include "DetDescr/HcalID.h"
8
9namespace hcal {
10
13 input_coll_name_ = ps.get<std::string>("input_coll_name");
14 input_pass_name_ = ps.get<std::string>("input_pass_name");
15 output_coll_name_ = ps.get<std::string>("output_coll_name");
16 mev_per_mip_ = ps.get<double>("mev_per_mip");
17 pe_per_mip_ = ps.get<double>("pe_per_mip");
18 attenuation_length_ = ps.get<double>("attenuation_length");
19 readout_threshold_ = ps.get<int>("readout_threshold");
20 mean_noise_ = ps.get<double>("mean_noise");
21 position_resolution_smear_ =
22 std::make_unique<std::normal_distribution<double>>(
23 0.0, ps.get<double>("position_resolution"));
24}
25
27 noise_generator_ = std::make_unique<ldmx::NoiseGenerator>(mean_noise_, false);
28 // hard-code this number, create noise hits_ for non-zero PEs!
29 noise_generator_->setNoiseThreshold(1);
33 noise_generator_->seedGenerator(
34 rseed.getSeed("HcalSimpleDigiAndRecProducer::NoiseGenerator"));
35 rng_.seed(rseed.getSeed("HcalSimpleDigiAndRecProducer"));
36}
37
39 const auto& hcal_geometry = getCondition<ldmx::HcalGeometry>(
41
42 std::vector<ldmx::HcalHit> hcal_rec_hits;
43
44 auto sim_hits{event.getCollection<ldmx::SimCalorimeterHit>(input_coll_name_,
45 input_pass_name_)};
46 std::unordered_map<unsigned int, std::vector<const ldmx::SimCalorimeterHit*>>
47 hits_by_id{};
48 // Important, has to be a reference so that we don't take the address of a
49 // variable that goes out of scope!
50 for (const auto& hit : sim_hits) {
51 auto id{hit.getID()};
52 auto found{hits_by_id.find(id)};
53 if (found == hits_by_id.end()) {
54 hits_by_id[id] = std::vector<const ldmx::SimCalorimeterHit*>{&hit};
55 } else {
56 hits_by_id[id].push_back(&hit);
57 }
58 }
59 for (const auto& [barID, simhits_in_bar] : hits_by_id) {
60 ldmx::HcalHit& rec_hit = hcal_rec_hits.emplace_back();
61 double edep{};
62 double time{};
63 std::vector<double> pos{0, 0, 0};
64 for (auto hit : simhits_in_bar) {
65 edep += hit->getEdep();
66 double edep_hit = hit->getEdep();
67 time += hit->getTime() * edep_hit;
68 auto hit_pos{hit->getPosition()};
69 pos[0] += hit_pos[0] * edep_hit;
70 pos[1] += hit_pos[1] * edep_hit;
71 pos[2] += hit_pos[2] * edep_hit;
72 }
73 ldmx::HcalID hit_id{barID};
74
75 // Position smearing
76 double mean_pe{(edep / mev_per_mip_) * pe_per_mip_};
77 double xpos{pos[0] / edep};
78 double ypos{pos[1] / edep};
79 double zpos{pos[2] / edep};
80 time /= edep;
81
82 auto orientation{hcal_geometry.getScintillatorOrientation(barID)};
83 double half_total_width{
84 hcal_geometry.getHalfTotalWidth(hit_id.section(), hit_id.layer())};
85 double scint_bar_length{hcal_geometry.getScintillatorLength(hit_id)};
86
87 auto strip_center{hcal_geometry.getStripCenterPosition(hit_id)};
88 if (hcal_geometry.isDoubleEnded(hit_id.section())) {
89 double distance_along_bar =
90 hcal_geometry.hasExplicitLayout()
91 ? hcal_geometry.getDistanceAlongBar(hit_id, xpos, ypos, zpos)
92 : (orientation ==
93 ldmx::HcalGeometry::ScintillatorOrientation::horizontal)
94 ? xpos
95 : ypos;
96 if (orientation ==
97 ldmx::HcalGeometry::ScintillatorOrientation::horizontal) {
98 ypos = strip_center.y();
99 xpos += (*position_resolution_smear_)(rng_);
100 } else {
101 xpos = strip_center.x();
102 ypos += (*position_resolution_smear_)(rng_);
103 }
104 zpos = strip_center.z();
105 // Attenuation
106 mean_pe *= exp(1. / attenuation_length_);
107 double mean_pe_close =
108 mean_pe * exp(-1. *
109 ((half_total_width - distance_along_bar) /
110 (scint_bar_length * 0.5)) /
111 attenuation_length_);
112 double mean_pe_far =
113 mean_pe * exp(-1. *
114 ((half_total_width + distance_along_bar) /
115 (scint_bar_length * 0.5)) /
116 attenuation_length_);
117 int pe_close{
118 std::poisson_distribution<int>(mean_pe_close + mean_noise_)(rng_)};
119 int pe_far{
120 std::poisson_distribution<int>(mean_pe_far + mean_noise_)(rng_)};
121 rec_hit.setPE(pe_close + pe_far);
122 rec_hit.setMinPE(std::min(pe_close, pe_far));
123 } else {
124 // Side HCAL, no attenuation business since single ended readout
125 int pe{std::poisson_distribution<int>(mean_pe + mean_noise_)(rng_)};
126 rec_hit.setPE(pe);
127 rec_hit.setMinPE(pe);
128
129 // Checks orientation of side Hcal bars, sets center positions and add
130 // smearing along bar orientation axis
131 if (orientation ==
132 ldmx::HcalGeometry::ScintillatorOrientation::horizontal) {
133 xpos += (*position_resolution_smear_)(rng_);
134 ypos = strip_center.y();
135 zpos = strip_center.z();
136 } else if (orientation ==
137 ldmx::HcalGeometry::ScintillatorOrientation::vertical) {
138 xpos = strip_center.x();
139 ypos += (*position_resolution_smear_)(rng_);
140 zpos = strip_center.z();
141 } else if (orientation ==
142 ldmx::HcalGeometry::ScintillatorOrientation::depth) {
143 xpos = strip_center.x();
144 ypos = strip_center.y();
145 zpos += (*position_resolution_smear_)(rng_);
146 } else {
147 xpos = strip_center.x();
148 ypos = strip_center.y();
149 zpos = strip_center.z();
150 ldmx_log(warn) << "Bar orientation not found. Hit" << hit_id.raw()
151 << "positioned at bar center.";
152 }
153 }
154
155 rec_hit.setID(hit_id.raw());
156 rec_hit.setXPos(xpos);
157 rec_hit.setNoise(false);
158 rec_hit.setYPos(ypos);
159 rec_hit.setZPos(zpos);
160 rec_hit.setTime(time);
161 rec_hit.setSection(hit_id.section());
162 rec_hit.setStrip(hit_id.strip());
163 rec_hit.setLayer(hit_id.layer());
164 rec_hit.setEnergy(edep);
165 rec_hit.setOrientation(static_cast<int>(orientation));
166 }
167 event.add(output_coll_name_, hcal_rec_hits);
168}
169
170} // namespace hcal
171
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer 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 that defines an HCal sensitive detector.
Conditions object for random number seeds.
Class which stores simulated calorimeter hit information.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
Implements an event buffer system for storing event data.
Definition Event.h:40
System for consistent seeding of random number generators.
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.
uint64_t getSeed(const std::string &name) const
Access a given seed by name.
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
void produce(framework::Event &event) override
Process the event and put new data products into it.
void onNewRun(const ldmx::RunHeader &runHeader) override
Callback for the EventProcessor to take any necessary action when the run being processed changes.
void configure(framework::config::Parameters &ps) override
Callback for the EventProcessor to configure itself from the given set of parameters.
void setYPos(float ypos)
Set the Y position of the hit [mm].
void setID(int id)
Set the detector ID.
void setZPos(float zpos)
Set the Z position of the hit [mm].
void setXPos(float xpos)
Set the X position of the hit [mm].
void setTime(float time)
Set the time of the hit [ns].
void setEnergy(float energy)
Set the calorimetric energy of the hit, corrected for sampling factors [MeV].
void setNoise(bool yes)
Set if this hit is a noise hit.
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
void setSection(int section)
Set the section for this hit.
Definition HcalHit.h:166
void setMinPE(float minpe)
Set the minimum number of photoelectrons estimated for this hit.
Definition HcalHit.h:160
void setOrientation(int orientation)
Set if the bar is orientied in X / Y / Z meanig 0 / 1 / 2, respectively.
Definition HcalHit.h:234
void setStrip(int strip)
Set the strip for this hit.
Definition HcalHit.h:178
void setLayer(int layer)
Set the layer for this hit.
Definition HcalHit.h:172
void setPE(float pe)
Set the number of photoelectrons estimated for this hit.
Definition HcalHit.h:153
Implements detector ids for HCal subdetector.
Definition HcalID.h:19
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:68
Stores simulated calorimeter hit information.