LDMX Software
Objects.cxx
2
3namespace eventdisplay {
4
6
8 // packages of event objects to be passed to event display manager
9 sim_objects_ = new TEveElementList("Simulation Objects");
10 rec_objects_ = new TEveElementList("Reconstruction Objects");
11}
12
13void Objects::SetSimThresh(double simThresh) {
14 simThresh_ = simThresh;
15 TEveElement* spHits = 0;
16 spHits = sim_objects_->FindChild("SimParticles leaving ECAL");
17 TEveElement::List_i sim;
18
19 for (sim = spHits->BeginChildren(); sim != spHits->EndChildren(); sim++) {
20 TEveElement* el = *sim;
21 ldmx::SimTrackerHit* sp = (ldmx::SimTrackerHit*)el->GetSourceObject();
22 std::vector<double> pVec = sp->getMomentum();
23 double p = pow(pow(pVec[0], 2) + pow(pVec[1], 2) + pow(pVec[2], 2), 0.5);
24 if (p < simThresh_) {
25 el->SetRnrSelf(kFALSE);
26 } else {
27 el->SetRnrSelf(kTRUE);
28 }
29 }
30}
31
33 TEveElement* clusters = rec_objects_->FindChild("ECAL Clusters");
34 if (clusters == 0) {
35 std::cout << "[ Objects ] : No clusters to color!" << std::endl;
36 return;
37 }
38
39 int theColor = 0;
40 TEveElement::List_i cluster;
41 for (cluster = clusters->BeginChildren(); cluster != clusters->EndChildren();
42 cluster++) {
43 TEveElement* el = *cluster;
44 TEveElement::List_i hit;
45 Int_t color = 0;
46 if (!el->IsPickable()) {
47 color = 19;
48 } else if (theColor < 9) {
49 color = colors_[theColor];
50 theColor++;
51 } else {
52 Int_t ci = 200 * r_.Rndm();
53 color = ci;
54 std::cout
55 << "[ Objects ] : Using random colors to fill in extra clusters."
56 << std::endl;
57 }
58
59 for (hit = el->BeginChildren(); hit != el->EndChildren(); hit++) {
60 TEveElement* elChild = *hit;
61 elChild->SetMainColor(color);
62 }
63 }
64}
65
66void Objects::draw(std::vector<ldmx::EcalHit> hits) {
67 TEveRGBAPalette* palette = new TEveRGBAPalette(0, 500.0);
68
69 std::sort(hits.begin(), hits.end(),
70 [](const ldmx::EcalHit& a, const ldmx::EcalHit& b) {
71 return a.getEnergy() < b.getEnergy();
72 });
73
74 auto ecal_hits = new TEveElementList("ECAL RecHits");
75 for (const ldmx::EcalHit& hit : hits) {
76 double energy = hit.getEnergy();
77
78 if (energy == 0) {
79 continue;
80 }
81
82 TString digiName;
83 digiName.Form("%1.5g MeV", energy);
84
85 const UChar_t* rgb = palette->ColorFromValue(energy);
86 TColor* aColor = new TColor();
87 Int_t color = aColor->GetColor((Int_t)rgb[0], (Int_t)rgb[1], (Int_t)rgb[2]);
88
89 TEveGeoShape* ecalDigiHit = EveShapeDrawer::getInstance().drawHexPrism(
90 DetectorGeometry::getInstance().getHexPrism(ldmx::EcalID(hit.getID())),
91 0, 0, 0, color, 0, digiName);
92
93 ecal_hits->AddElement(ecalDigiHit);
94 }
95
96 ecal_hits->SetPickableRecursively(1);
97
98 rec_objects_->AddElement(ecal_hits);
99}
100
101void Objects::draw(std::vector<ldmx::HcalHit> hits) {
102 TEveRGBAPalette* palette = new TEveRGBAPalette(0, 100.0);
103
104 std::sort(hits.begin(), hits.end(),
105 [](const ldmx::HcalHit& a, const ldmx::HcalHit& b) {
106 return a.getEnergy() < b.getEnergy();
107 });
108
109 auto hcal_hits = new TEveElementList("HCAL Rec Hits");
110 for (const ldmx::HcalHit& hit : hits) {
111 int pe = hit.getPE();
112 if (pe == 0) {
113 continue;
114 }
115
116 ldmx::HcalID id(hit.getID());
117
118 const UChar_t* rgb = palette->ColorFromValue(pe);
119 TColor* aColor = new TColor();
120 Int_t color = aColor->GetColor((Int_t)rgb[0], (Int_t)rgb[1], (Int_t)rgb[2]);
121
122 TString digiName;
123 digiName.Form("%d PEs, Section %d, Layer %d, Bar %d, Z %1.5g", pe,
124 id.section(), id.layer(), id.strip(), hit.getZPos());
125
126 BoundingBox hcal_hit_bb =
128 TEveGeoShape* hcalDigiHit = EveShapeDrawer::getInstance().drawRectPrism(
129 hcal_hit_bb, 0, 0, 0, color, 0, digiName);
130
131 if (hcalDigiHit) {
132 if (hit.isNoise()) {
133 hcalDigiHit->SetRnrSelf(0);
134 }
135 hcal_hits->AddElement(hcalDigiHit);
136 } // successfully created hcal digi hit
137
138 } // loop through sorted hit list
139
140 hcal_hits->SetPickableRecursively(1);
141 rec_objects_->AddElement(hcal_hits);
142}
143
144void Objects::draw(std::vector<ldmx::EcalCluster> clusters) {
145 TEveRGBAPalette* palette = new TEveRGBAPalette(0, 4000.0);
146
147 auto eve_clusters = new TEveElementList("Ecal Clusters");
148 int iC = 0;
149 for (const ldmx::EcalCluster& cluster : clusters) {
150 TString clusterName;
151 clusterName.Form("ECAL Cluster %d", iC);
152
153 TEveElement* ecalCluster = new TEveElementList(clusterName);
154
155 double energy = cluster.getEnergy();
156 std::vector<unsigned int> clusterHitIDs = cluster.getHitIDs();
157
158 int numHits = clusterHitIDs.size();
159
160 for (int iHit = 0; iHit < numHits; iHit++) {
161 ldmx::EcalID id(clusterHitIDs.at(iHit));
162
163 const UChar_t* rgb = palette->ColorFromValue(energy);
164 TColor* aColor = new TColor();
165 Int_t color =
166 aColor->GetColor((Int_t)rgb[0], (Int_t)rgb[1], (Int_t)rgb[2]);
167
168 TEveGeoShape* ecalDigiHit = EveShapeDrawer::getInstance().drawHexPrism(
169 DetectorGeometry::getInstance().getHexPrism(id), 0, 0, 0, color, 0,
170 "RecHit");
171 ecalCluster->AddElement(ecalDigiHit);
172
173 if (numHits < 2) {
174 ecalCluster->SetPickableRecursively(0);
175 } else {
176 ecalCluster->SetPickableRecursively(1);
177 }
178 }
179 eve_clusters->AddElement(ecalCluster);
180 iC++;
181 }
182
183 eve_clusters->SetPickable(1);
184 rec_objects_->AddElement(eve_clusters);
185}
186
187void Objects::draw(std::vector<ldmx::SimTrackerHit> hits) {
188 // need at least one hit for subdet ID
189 if (hits.empty()) return;
190
191 // get id for determining subdet
192 ldmx::DetectorID id(hits.at(0).getID());
193
194 if (id.subdet() == ldmx::SubdetectorIDType::SD_TRACKER_RECOIL) {
195 // recoil tracker ID
196 int iter = 0;
197 auto recoil_tracker_hits = new TEveElementList("Recoil Tracker Hits");
198 for (const ldmx::SimTrackerHit& hit : hits) {
199 std::vector<float> xyzPos = hit.getPosition();
200 double energy = hit.getEdep();
201
202 TString recoilName;
203 recoilName.Form("Recoil Hit %d", iter);
204
205 TEveGeoShape* recoilHit = EveShapeDrawer::getInstance().drawRectPrism(
206 DetectorGeometry::getInstance().getBoundingBox(hit), 0, 0,
207 DetectorGeometry::getInstance().getRotAngle(hit.getLayerID(),
208 hit.getModuleID()) *
209 180 / M_PI,
210 kRed + 1, 0, recoilName);
211 recoil_tracker_hits->AddElement(recoilHit);
212
213 iter++;
214 }
215 sim_objects_->AddElement(recoil_tracker_hits);
216 } else if (id.subdet() == ldmx::SubdetectorIDType::SD_SIM_SPECIAL) {
217 // scoring plane ID
218
219 std::sort(hits.begin(), hits.end(),
220 [](const ldmx::SimTrackerHit& a, const ldmx::SimTrackerHit& b) {
221 return a.getTrackID() < b.getTrackID();
222 });
223
224 auto lastUniqueEntry =
225 std::unique(hits.begin(), hits.end(),
227 return a.getTrackID() == b.getTrackID();
228 });
229
230 hits.erase(lastUniqueEntry, hits.end());
231
232 auto leaving_ecal_sim_particles =
233 new TEveElementList("SimParticles leaving ECAL");
234 for (const ldmx::SimTrackerHit& spHit : hits) {
235 std::vector<double> pVec = spHit.getMomentum();
236 double p = pow(pow(pVec[0], 2) + pow(pVec[1], 2) + pow(pVec[2], 2), 0.5);
237
238 double E = spHit.getEnergy();
239
240 std::vector<float> simStart = spHit.getPosition();
241 std::vector<double> simDir = pVec;
242 double rCheck =
243 pow(pow(simDir[0], 2) + pow(simDir[1], 2) + pow(simDir[2], 2), 0.5);
244
245 double scale = 1;
246 double largest = 0;
247 if (abs(simDir[0]) > 3500.0) {
248 scale = 500.0 / abs(simDir[0]);
249 largest = simDir[0];
250 }
251 if (abs(simDir[1]) > 3500.0 && abs(simDir[1]) > largest) {
252 scale = 500.0 / abs(simDir[1]);
253 largest = simDir[1];
254 }
255 if (abs(simDir[2]) > 3500.0 && abs(simDir[2]) > 3500) {
256 scale = 500.0 / abs(simDir[2]);
257 }
258
259 double r = pow(pow(scale * (simDir[0]), 2) + pow(scale * (simDir[1]), 2) +
260 pow(scale * (simDir[2]), 2),
261 0.5);
262 signed int pdgID = spHit.getPdgID();
263
264 TEveArrow* simArr =
265 new TEveArrow(scale * simDir[0], scale * simDir[1], scale * simDir[2],
266 simStart[0], simStart[1], simStart[2]);
267
268 simArr->SetMainColor(kBlack);
269 simArr->SetTubeR(60 * 0.02 / r);
270 simArr->SetConeL(100 * 0.02 / r);
271 simArr->SetConeR(150 * 0.02 / r);
272 simArr->SetPickable(kTRUE);
273 if (p < simThresh_) {
274 simArr->SetRnrSelf(kFALSE);
275 }
276
277 TString name;
278 name.Form("PDG = %d, p = %1.5g MeV/c", pdgID, p);
279 simArr->SetElementName(name);
280 leaving_ecal_sim_particles->AddElement(simArr);
281 }
282
283 sim_objects_->AddElement(leaving_ecal_sim_particles);
284 } else {
285 EXCEPTION_RAISE("NotImp",
286 "SimTrackerHit drawing not implemented for subdet " +
287 std::to_string(int(id.subdet())));
288 }
289}
290
291void Objects::draw(std::vector<ldmx::SimCalorimeterHit> hits) {
292 // need at least one hit for subdet ID
293 if (hits.empty()) return;
294
295 // get id for determining subdet
296 ldmx::DetectorID id(hits.at(0).getID());
297
298 TEveRGBAPalette* palette = new TEveRGBAPalette(0, 100.0);
299
300 std::sort(
301 hits.begin(), hits.end(),
302 [](const ldmx::SimCalorimeterHit& a, const ldmx::SimCalorimeterHit& b) {
303 return a.getEdep() < b.getEdep();
304 });
305
306 if (id.subdet() == ldmx::SubdetectorIDType::SD_HCAL) {
307 auto hcal_hits = new TEveElementList("HCAL Sim Hits");
308 for (const ldmx::SimCalorimeterHit& hit : hits) {
309 ldmx::HcalID id(hit.getID());
310
311 float edep = hit.getEdep();
312
313 const UChar_t* rgb = palette->ColorFromValue(edep);
314 TColor* aColor = new TColor();
315 Int_t color =
316 aColor->GetColor((Int_t)rgb[0], (Int_t)rgb[1], (Int_t)rgb[2]);
317
318 auto position{hit.getPosition()};
319
320 TString digiName;
321 digiName.Form("%.2f MeV, Section %d, Layer %d, Bar %d, Z %1.5g",
322 hit.getEdep(), id.section(), id.layer(), id.strip(),
323 position.at(2));
324
325 TEveGeoShape* eve_hit = EveShapeDrawer::getInstance().drawRectPrism(
326 position.at(0), position.at(1), position.at(2), 50., 50., 10., 0, 0,
327 0, color, 0, digiName);
328
329 if (eve_hit) {
330 hcal_hits->AddElement(eve_hit);
331 } // successfully created hcal digi hit
332
333 } // loop through sorted hit list
334
335 hcal_hits->SetPickableRecursively(1);
336 sim_objects_->AddElement(hcal_hits);
337
338 } else if (id.subdet() == ldmx::SubdetectorIDType::SD_ECAL) {
339 auto ecal_hits = new TEveElementList("ECAL Sim Hits");
340 for (const ldmx::SimCalorimeterHit& hit : hits) {
341 ldmx::EcalID id(hit.getID());
342
343 float edep = hit.getEdep();
344
345 const UChar_t* rgb = palette->ColorFromValue(edep);
346 TColor* aColor = new TColor();
347 Int_t color =
348 aColor->GetColor((Int_t)rgb[0], (Int_t)rgb[1], (Int_t)rgb[2]);
349
350 TString digiName;
351 digiName.Form("%.2f MeV, Module %d, Layer %d, Cell %d", hit.getEdep(),
352 id.module(), id.layer(), id.cell());
353
354 auto position{hit.getPosition()};
355
356 TEveGeoShape* eve_hit = EveShapeDrawer::getInstance().drawHexPrism(
357 position.at(0), position.at(1), position.at(2), 0, 0, 0, 1., 2.,
358 color, 0, digiName);
359
360 if (eve_hit) {
361 ecal_hits->AddElement(eve_hit);
362 } // successfully created hcal digi hit
363
364 } // loop through sorted hit list
365
366 ecal_hits->SetPickableRecursively(1);
367 sim_objects_->AddElement(ecal_hits);
368
369 } else {
370 EXCEPTION_RAISE("NotImp",
371 "SimCalorimeterHit drawing not implemented for subdet " +
372 std::to_string(int(id.subdet())));
373 }
374}
375
376void Objects::draw(std::map<int, ldmx::SimParticle> particles) {
377 static const std::map<int, char*> translation = {
378 {int(ldmx::SimParticle::ProcessType::unknown), "unknown"},
379 {int(ldmx::SimParticle::ProcessType::annihil), "annihil"},
380 {int(ldmx::SimParticle::ProcessType::compt), "compt"},
381 {int(ldmx::SimParticle::ProcessType::conv), "conv"},
382 {int(ldmx::SimParticle::ProcessType::electronNuclear), "electronNuclear"},
383 {int(ldmx::SimParticle::ProcessType::eBrem), "eBrem"},
384 {int(ldmx::SimParticle::ProcessType::eIoni), "eIoni"},
385 {int(ldmx::SimParticle::ProcessType::msc), "msc"},
386 {int(ldmx::SimParticle::ProcessType::phot), "phot"},
387 {int(ldmx::SimParticle::ProcessType::photonNuclear), "photonNuclear"},
388 {int(ldmx::SimParticle::ProcessType::GammaToMuPair), "GammaToMuPair"},
389 {int(ldmx::SimParticle::ProcessType::eDarkBrem), "eDarkBrem"}};
390
391 TString eve_list_name;
392 eve_list_name.Form("SimParticles above %.1f MeV", simThresh_);
393 auto sim_particles = new TEveElementList(eve_list_name);
394
395 for (auto const& [track_id, particle] : particles) {
396 // skip if KE is less than threshold
397 if (particle.getEnergy() - particle.getMass() < simThresh_) continue;
398
399 std::vector<double> pVec = particle.getMomentum();
400 double p =
401 pow(pow(pVec.at(0), 2) + pow(pVec.at(1), 2) + pow(pVec.at(2), 2), 0.5);
402
403 std::vector<double> simStart = particle.getVertex();
404 std::vector<double> simEnd = particle.getEndPoint();
405 std::vector<double> simDir = {0., 0., 0.};
406 for (int i = 0; i < 3; i++) simDir[i] = simEnd.at(i) - simStart.at(i);
407
408 TEveArrow* simArr =
409 new TEveArrow(simDir.at(0), simDir.at(1), simDir.at(2), simStart.at(0),
410 simStart.at(1), simStart.at(2));
411
412 double r = pow(pow((simDir.at(0)), 2) + pow((simDir.at(1)), 2) +
413 pow((simDir.at(2)), 2),
414 0.5);
415
416 simArr->SetMainColor(kBlack);
417 simArr->SetTubeR(60 * 0.02 / r);
418 simArr->SetConeL(100 * 0.02 / r);
419 simArr->SetConeR(150 * 0.02 / r);
420 simArr->SetPickable(kTRUE);
421
422 int parent_id = 0; // for primaries
423 if (not particle.getParents().empty())
424 parent_id = particle.getParents().at(0);
425
426 TString name;
427 name.Form("PDG = %d, p = %1.5g MeV/c from track ID %d via %s process",
428 particle.getPdgID(), p, parent_id,
429 translation.at(particle.getProcessType()));
430 simArr->SetElementName(name);
431 sim_particles->AddElement(simArr);
432 }
433
434 sim_objects_->AddElement(sim_particles);
435}
436
437} // namespace eventdisplay
std::vector< std::pair< double, double > > BoundingBox
@type BoundingBox
static const DetectorGeometry & getInstance()
Get the single instance of this class.
BoundingBox getBoundingBox(const ldmx::HcalHit &hit) const
Calculate real space coordinates from detector location.
TEveGeoShape * drawRectPrism(Double_t xPos, Double_t yPos, Double_t zPos, Double_t dX, Double_t dY, Double_t dZ, Double_t xRot, Double_t yRot, Double_t zRot, Int_t color, Int_t transparency, TString name)
Draw a rectangular prism.
TEveGeoShape * drawHexPrism(Double_t xPos, Double_t yPos, Double_t zPos, Double_t xRot, Double_t yRot, Double_t zRot, Double_t h, Double_t r, Int_t color, Int_t transparency, TString name)
Draw a hexagonal prism.
static EveShapeDrawer & getInstance()
Get Instance of Drawer.
Objects()
Constructor Defines new necessary objects.
Definition Objects.cxx:5
double simThresh_
threshold for sim particles to be drawn
Definition Objects.h:127
void ColorClusters()
Colors ecal clusters according to colors_.
Definition Objects.cxx:32
TEveElement * rec_objects_
Eve Element containing reco objects that aren't hits.
Definition Objects.h:124
void SetSimThresh(double simThresh)
Sets the energy threshold for a sim particle to be drawn.
Definition Objects.cxx:13
TRandom r_
random number generator for colors if we go over the ones in
Definition Objects.h:134
TEveElement * sim_objects_
Eve Element containing all hits.
Definition Objects.h:122
void Initialize()
Defines new Eve Element Lists for the event objects.
Definition Objects.cxx:7
std::vector< Color_t > colors_
list of colors to use with ecal clusters
Definition Objects.h:130
void draw(T o)
Not implemented.
Definition Objects.h:61
Defines a 32-bit packed ID for uniquely identifying hits and detector components.
Definition DetectorID.h:35
Stores cluster information from the ECal.
Definition EcalCluster.h:20
Stores reconstructed hit information from the ECAL.
Definition EcalHit.h:19
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
Definition EcalID.h:20
Stores reconstructed hit information from the HCAL.
Definition HcalHit.h:23
Implements detector ids for HCal subdetector.
Definition HcalID.h:19
Stores simulated calorimeter hit information.
Represents a simulated tracker hit in the simulation.
std::vector< double > getMomentum() const
Get the XYZ momentum of the particle at the position at which the hit took place [MeV].