LDMX Software
TrigScintDigiProducer.cxx
2
3#include <iostream>
4
5#include "Framework/Exception/Exception.h"
7
8namespace trigscint {
9
10TrigScintDigiProducer::TrigScintDigiProducer(const std::string &name,
11 framework::Process &process)
12 : Producer(name, process) {}
13
14void TrigScintDigiProducer::configure(
16 // Configure this instance of the producer
17 stripsPerArray_ = parameters.getParameter<int>("number_of_strips");
18 numberOfArrays_ = parameters.getParameter<int>("number_of_arrays");
19 meanNoise_ = parameters.getParameter<double>("mean_noise");
20 mevPerMip_ = parameters.getParameter<double>("mev_per_mip");
21 pePerMip_ = parameters.getParameter<double>("pe_per_mip");
22 inputCollection_ = parameters.getParameter<std::string>("input_collection");
23 inputPassName_ = parameters.getParameter<std::string>("input_pass_name");
24 outputCollection_ = parameters.getParameter<std::string>("output_collection");
25 verbose_ = parameters.getParameter<bool>("verbose");
26
27 random_ =
28 std::make_unique<TRandom3>(parameters.getParameter<int>("randomSeed"));
29
30 noiseGenerator_ = std::make_unique<ldmx::NoiseGenerator>(meanNoise_, false);
31 noiseGenerator_->setNoiseThreshold(1);
32}
33
34ldmx::TrigScintID TrigScintDigiProducer::generateRandomID(int module) {
35 ldmx::TrigScintID tempID(module, random_->Integer(stripsPerArray_));
36 if (module >= TrigScintSection::NUM_SECTIONS) {
37 // Throw an exception
38 std::cout << "WARNING [TrigScintDigiProducer::generateRandomID]: "
39 "TrigScintSection is not known"
40 << std::endl;
41 }
42
43 return tempID;
44}
45
46void TrigScintDigiProducer::produce(framework::Event &event) {
47 // Need to handle seeding on the first event
48 if (!noiseGenerator_->hasSeed()) {
49 const auto &rseed = getCondition<framework::RandomNumberSeedService>(
51 noiseGenerator_->seedGenerator(
52 rseed.getSeed("TrigScintDigiProducer::NoiseGenerator"));
53 }
54
55 std::map<ldmx::TrigScintID, int> cellPEs;
56 std::map<ldmx::TrigScintID, int> cellMinPEs;
57 std::map<ldmx::TrigScintID, float> Xpos, Ypos, Zpos, Edep, Time, beamFrac;
58 std::set<ldmx::TrigScintID> noiseHitIDs;
59
60 auto numRecHits{0};
61
62 // looper over sim hits and aggregate energy depositions for each detID
63 const auto simHits{event.getCollection<ldmx::SimCalorimeterHit>(
64 inputCollection_, inputPassName_)};
65 auto particleMap{event.getMap<int, ldmx::SimParticle>("SimParticles")};
66
67 int module{-1};
68 for (const auto &simHit : simHits) {
69 ldmx::TrigScintID id(simHit.getID());
70
71 // Just set the module ID to use for noise hits here. Given that
72 // we are currently processing a single module at a time, setting
73 // it within the loop shouldn't matter.
74 module = id.module();
75 std::vector<float> position = simHit.getPosition();
76
77 if (verbose_) {
78 std::cout << id << std::endl;
79 }
80
81 // check if hits is from beam electron and, if so, add to beamFrac
82 for (int i = 0; i < simHit.getNumberOfContribs(); i++) {
83 auto contrib = simHit.getContrib(i);
84 if (verbose_) {
85 std::cout << "contrib " << i << " trackID: " << contrib.trackID
86 << " pdgID: " << contrib.pdgCode << " edep: " << contrib.edep
87 << std::endl;
88 std::cout << "\t particle id: "
89 << particleMap[contrib.trackID].getPdgID()
90 << " particle status: "
91 << particleMap[contrib.trackID].getGenStatus() << std::endl;
92 }
93 if (particleMap[contrib.trackID].getPdgID() == 11 &&
94 particleMap[contrib.trackID].getGenStatus() == 1) {
95 if (beamFrac.find(id) == beamFrac.end())
96 beamFrac[id] = contrib.edep;
97 else
98 beamFrac[id] += contrib.edep;
99 }
100 }
101
102 // for now, we take am energy weighted average of the hit in each stip to
103 // simulate the hit position. AJW: these should be dropped, they are likely
104 // to lead to a problem since we can't measure them anyway except roughly y
105 // and z, which is encoded in the ids.
106 if (Edep.find(id) == Edep.end()) {
107 // first hit, initialize
108 Edep[id] = simHit.getEdep();
109 Time[id] = simHit.getTime() * simHit.getEdep();
110 Xpos[id] = position[0] * simHit.getEdep();
111 Ypos[id] = position[1] * simHit.getEdep();
112 Zpos[id] = position[2] * simHit.getEdep();
113 numRecHits++;
114
115 } else {
116 // not first hit, aggregate, and store the largest radius hit
117 Xpos[id] += position[0] * simHit.getEdep();
118 Ypos[id] += position[1] * simHit.getEdep();
119 Zpos[id] += position[2] * simHit.getEdep();
120 Edep[id] += simHit.getEdep();
121 // AJW: need to figure out a better way to model this...
122 Time[id] += simHit.getTime() * simHit.getEdep();
123 }
124 }
125
126 // Create the container to hold the digitized trigger scintillator hits.
127 std::vector<ldmx::TrigScintHit> trigScintHits;
128
129 // loop over detIDs and simulate number of PEs
130 for (std::map<ldmx::TrigScintID, float>::iterator it = Edep.begin();
131 it != Edep.end(); ++it) {
132 ldmx::TrigScintID id(it->first);
133
134 double depEnergy = Edep[id];
135 Time[id] = Time[id] / Edep[id];
136 Xpos[id] = Xpos[id] / Edep[id];
137 Ypos[id] = Ypos[id] / Edep[id];
138 Zpos[id] = Zpos[id] / Edep[id];
139 double meanPE = depEnergy / mevPerMip_ * pePerMip_;
140 cellPEs[id] = random_->Poisson(meanPE + meanNoise_);
141
142 // If a cell has a PE count above threshold, persit the hit.
143 if (cellPEs[id] >= 1) {
145 hit.setID(id.raw());
146 hit.setPE(cellPEs[id]);
147 hit.setMinPE(cellMinPEs[id]);
148 hit.setAmplitude(cellPEs[id]);
149 hit.setEnergy(depEnergy);
150 hit.setTime(Time[id]);
151 hit.setXPos(Xpos[id]);
152 hit.setYPos(Ypos[id]);
153 hit.setZPos(Zpos[id]);
154 hit.setModuleID(module);
155 hit.setBarID(id.bar()); // getFieldValue("bar"));
156 hit.setNoise(false);
157 hit.setBeamEfrac(beamFrac[id] / depEnergy);
158
159 trigScintHits.push_back(hit);
160 }
161
162 if (verbose_) {
163 std::cout << id << std::endl;
164 std::cout << "Edep: " << Edep[id] << std::endl;
165 std::cout << "numPEs: " << cellPEs[id] << std::endl;
166 std::cout << "time: " << Time[id] << std::endl;
167 std::cout << "z: " << Zpos[id] << std::endl;
168 std::cout << "\t X: " << Xpos[id] << "\t Y: " << Ypos[id]
169 << "\t Z: " << Zpos[id] << std::endl;
170 } // end verbose
171 }
172
173 // ------------------------------- Noise simulation -----------------------//
174 // ------------------------------------------------------------------------//
175 // only simulating for single array until
176 // all arrays are merged into one collection
177 int numEmptyCells = stripsPerArray_ - numRecHits;
178 std::vector<double> noiseHits_PE =
179 noiseGenerator_->generateNoiseHits(numEmptyCells);
180
181 ldmx::TrigScintID tempID;
182
183 for (auto &noiseHitPE : noiseHits_PE) {
185 // generate random ID from remaining cells
186 do {
187 tempID = generateRandomID(module);
188 } while (Edep.find(tempID) != Edep.end() ||
189 noiseHitIDs.find(tempID) != noiseHitIDs.end());
190
191 ldmx::TrigScintID noiseID = tempID;
192
193 noiseHitIDs.insert(noiseID);
194 hit.setID(noiseID.raw());
195 hit.setPE(noiseHitPE);
196 hit.setMinPE(noiseHitPE);
197 hit.setAmplitude(noiseHitPE);
198 hit.setEnergy(0.);
199 hit.setTime(0.);
200 hit.setXPos(0.);
201 hit.setYPos(0.);
202 hit.setZPos(0.);
203 hit.setModuleID(module);
204 hit.setBarID(noiseID.bar());
205 hit.setNoise(true);
206 hit.setBeamEfrac(0.);
207
208 trigScintHits.push_back(hit);
209 }
210 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
211 // - -
212
213 event.add(outputCollection_, trigScintHits);
214}
215} // namespace trigscint
216
217DECLARE_PRODUCER_NS(trigscint, TrigScintDigiProducer);
#define DECLARE_PRODUCER_NS(NS, CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Conditions object for random number seeds.
Class that performs digitization of simulated trigger sctintillator.
Implements an event buffer system for storing event data.
Definition Event.h:41
Class which represents the process under execution.
Definition Process.h:36
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
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 setAmplitude(float amplitude)
Set the amplitude of the hit, which is proportional to the signal in the calorimeter cell without sam...
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.
RawValue raw() const
Definition DetectorID.h:68
void setMinPE(float minpe)
Set the minimum number of photoelectrons estimated for this hit.
Definition HcalHit.h:126
Stores simulated calorimeter hit information.
Class representing a simulated particle.
Definition SimParticle.h:23
void setPE(const float PE)
Set hit pe.
void setBarID(const int barID)
Set hit bar ID.
void setBeamEfrac(const float beamEfrac)
Set beam energy fraction of hit.
void setModuleID(const int moduleID)
Set hit module ID.
Class that defines the detector ID of the trigger scintillator.
Definition TrigScintID.h:14
int bar() const
Get the value of the bar field from the ID.
Definition TrigScintID.h:64