LDMX Software
HcalSimpleDigiAndRecProducer.cxx
1#include "Hcal/HcalSimpleDigiAndRecProducer.h"
2
5
6namespace hcal {
7
10 input_coll_name_ = ps.getParameter<std::string>("input_coll_name");
11 input_pass_name_ = ps.getParameter<std::string>("input_pass_name");
12 output_coll_name_ = ps.getParameter<std::string>("output_coll_name");
13 mev_per_mip_ = ps.getParameter<double>("mev_per_mip");
14 pe_per_mip_ = ps.getParameter<double>("pe_per_mip");
15 attenuation_length_ = ps.getParameter<double>("attenuation_length");
16 readout_threshold_ = ps.getParameter<int>("readout_threshold");
17 mean_noise_ = ps.getParameter<double>("mean_noise");
18 position_resolution_smear_ =
19 std::make_unique<std::normal_distribution<double>>(
20 0.0, ps.getParameter<double>("position_resolution"));
21}
22
24 noiseGenerator_ = std::make_unique<ldmx::NoiseGenerator>(mean_noise_, false);
25 // hard-code this number, create noise hits for non-zero PEs!
26 noiseGenerator_->setNoiseThreshold(1);
30 noiseGenerator_->seedGenerator(
31 rseed.getSeed("HcalSimpleDigiAndRecProducer::NoiseGenerator"));
32 rng_.seed(rseed.getSeed("HcalSimpleDigiAndRecProducer"));
33}
34
36 const auto& hcalGeometry = getCondition<ldmx::HcalGeometry>(
38
39 std::vector<ldmx::HcalHit> hcalRecHits;
40
41 auto simHits{event.getCollection<ldmx::SimCalorimeterHit>(input_coll_name_,
42 input_pass_name_)};
43 std::unordered_map<unsigned int, std::vector<const ldmx::SimCalorimeterHit*>>
44 hits_by_id{};
45 // Important, has to be a reference so that we don't take the address of a
46 // variable that goes out of scope!
47 for (const auto& hit : simHits) {
48 auto id{hit.getID()};
49 auto found{hits_by_id.find(id)};
50 if (found == hits_by_id.end()) {
51 hits_by_id[id] = std::vector<const ldmx::SimCalorimeterHit*>{&hit};
52 } else {
53 hits_by_id[id].push_back(&hit);
54 }
55 }
56 for (const auto& [barID, simhits_in_bar] : hits_by_id) {
57 ldmx::HcalHit& recHit = hcalRecHits.emplace_back();
58 double edep{};
59 double time{};
60 std::vector<double> pos{0, 0, 0};
61 for (auto hit : simhits_in_bar) {
62 edep += hit->getEdep();
63 double edep_hit = hit->getEdep();
64 time += hit->getTime() * edep_hit;
65 auto hitPos{hit->getPosition()};
66 pos[0] += hitPos[0] * edep_hit;
67 pos[1] += hitPos[1] * edep_hit;
68 pos[2] += hitPos[2] * edep_hit;
69 }
70 ldmx::HcalID hitID{barID};
71
72 // Position smearing
73 double mean_pe{(edep / mev_per_mip_) * pe_per_mip_};
74 double xpos{pos[0] / edep};
75 double ypos{pos[1] / edep};
76 double zpos{pos[2] / edep};
77 time /= edep;
78
79 auto orientation{hcalGeometry.getScintillatorOrientation(barID)};
80 double half_total_width{
81 hcalGeometry.getHalfTotalWidth(hitID.section(), hitID.layer())};
82 double scint_bar_length{hcalGeometry.getScintillatorLength(hitID)};
83
84 auto stripCenter{hcalGeometry.getStripCenterPosition(hitID)};
85 if (hitID.section() == ldmx::HcalID::HcalSection::BACK) {
86 double distance_along_bar =
87 (orientation ==
88 ldmx::HcalGeometry::ScintillatorOrientation::horizontal)
89 ? xpos
90 : ypos;
91 if (orientation ==
92 ldmx::HcalGeometry::ScintillatorOrientation::horizontal) {
93 ypos = stripCenter.y();
94 xpos += (*position_resolution_smear_)(rng_);
95 } else {
96 xpos = stripCenter.x();
97 ypos += (*position_resolution_smear_)(rng_);
98 }
99 zpos = stripCenter.z();
100 // Attenuation
101 mean_pe *= exp(1. / attenuation_length_);
102 double mean_pe_close =
103 mean_pe * exp(-1. *
104 ((half_total_width - distance_along_bar) /
105 (scint_bar_length * 0.5)) /
106 attenuation_length_);
107 double mean_pe_far =
108 mean_pe * exp(-1. *
109 ((half_total_width + distance_along_bar) /
110 (scint_bar_length * 0.5)) /
111 attenuation_length_);
112 int PE_close{
113 std::poisson_distribution<int>(mean_pe_close + mean_noise_)(rng_)};
114 int PE_far{
115 std::poisson_distribution<int>(mean_pe_far + mean_noise_)(rng_)};
116 recHit.setPE(PE_close + PE_far);
117 recHit.setMinPE(std::min(PE_close, PE_far));
118 } else {
119 // Side HCAL, no attenuation business since single ended readout
120 int PE{std::poisson_distribution<int>(mean_pe + mean_noise_)(rng_)};
121 recHit.setPE(PE);
122 recHit.setMinPE(PE);
123
124 // Checks orientation of side Hcal bars, sets center positions and add
125 // smearing along bar orientation axis
126 if (orientation ==
127 ldmx::HcalGeometry::ScintillatorOrientation::horizontal) {
128 xpos += (*position_resolution_smear_)(rng_);
129 ypos = stripCenter.y();
130 zpos = stripCenter.z();
131 } else if (orientation ==
132 ldmx::HcalGeometry::ScintillatorOrientation::vertical) {
133 xpos = stripCenter.x();
134 ypos += (*position_resolution_smear_)(rng_);
135 zpos = stripCenter.z();
136 } else if (orientation ==
137 ldmx::HcalGeometry::ScintillatorOrientation::depth) {
138 xpos = stripCenter.x();
139 ypos = stripCenter.y();
140 zpos += (*position_resolution_smear_)(rng_);
141 } else {
142 xpos = stripCenter.x();
143 ypos = stripCenter.y();
144 zpos = stripCenter.z();
145 ldmx_log(warn) << "Bar orientation not found. Hit" << hitID.raw()
146 << "positioned at bar center.";
147 }
148 }
149
150 recHit.setID(hitID.raw());
151 recHit.setXPos(xpos);
152 recHit.setNoise(false);
153 recHit.setYPos(ypos);
154 recHit.setZPos(zpos);
155 recHit.setTime(time);
156 recHit.setSection(hitID.section());
157 recHit.setStrip(hitID.strip());
158 recHit.setLayer(hitID.layer());
159 recHit.setEnergy(edep);
160 recHit.setOrientation(static_cast<int>(orientation));
161 }
162 event.add(output_coll_name_, hcalRecHits);
163}
164
165} // namespace hcal
166
167DECLARE_PRODUCER_NS(hcal, HcalSimpleDigiAndRecProducer);
#define DECLARE_PRODUCER_NS(NS, CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Class that stores Stores reconstructed hit information from the HCAL.
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:42
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:29
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:57
Stores simulated calorimeter hit information.