File indexing completed on 2025-12-16 09:21:49
0001 #include "SvtxTruthEval.h"
0002
0003 #include "BaseTruthEval.h"
0004
0005 #include <g4main/PHG4Hit.h>
0006 #include <g4main/PHG4HitContainer.h>
0007 #include <g4main/PHG4TruthInfoContainer.h>
0008
0009 #include <g4main/PHG4Particle.h>
0010
0011 #include <micromegas/MicromegasDefs.h>
0012
0013 #include <trackbase/ActsGeometry.h>
0014 #include <trackbase/InttDefs.h>
0015 #include <trackbase/MvtxDefs.h>
0016 #include <trackbase/TpcDefs.h>
0017 #include <trackbase/TrkrClusterv1.h>
0018 #include <trackbase/TrkrDefs.h>
0019
0020 #include <g4detectors/PHG4CylinderGeom.h> // for PHG4CylinderGeom
0021 #include <g4detectors/PHG4CylinderGeomContainer.h>
0022 #include <g4detectors/PHG4TpcGeom.h>
0023 #include <g4detectors/PHG4TpcGeomContainer.h>
0024
0025 #include <mvtx/CylinderGeom_Mvtx.h>
0026 #include <mvtx/CylinderGeom_MvtxHelper.h>
0027
0028 #include <intt/CylinderGeomIntt.h>
0029 #include <intt/CylinderGeomInttHelper.h>
0030
0031 #include <phool/PHCompositeNode.h>
0032 #include <phool/getClass.h>
0033 #include <phool/phool.h> // for PHWHERE
0034
0035 #include <phparameter/PHParameters.h>
0036 #include <phparameter/PHParametersContainer.h>
0037
0038 #include <TVector3.h>
0039
0040 #include <algorithm>
0041 #include <cassert>
0042 #include <cmath> // for sqrt, fabs
0043 #include <cstdlib> // for abs
0044 #include <iostream>
0045 #include <limits>
0046 #include <map>
0047 #include <set>
0048 #include <utility>
0049
0050 SvtxTruthEval::SvtxTruthEval(PHCompositeNode* topNode)
0051 : _basetrutheval(topNode)
0052 {
0053 get_node_pointers(topNode);
0054 }
0055
0056 SvtxTruthEval::~SvtxTruthEval()
0057 {
0058 if (_verbosity > 1)
0059 {
0060 if ((_errors > 0) || (_verbosity > 1))
0061 {
0062 std::cout << "SvtxTruthEval::~SvtxTruthEval() - Error Count: " << _errors << std::endl;
0063 }
0064 }
0065 }
0066
0067 void SvtxTruthEval::next_event(PHCompositeNode* topNode)
0068 {
0069 _cache_all_truth_hits.clear();
0070 _cache_all_truth_hits_g4particle.clear();
0071 _cache_all_truth_clusters_g4particle.clear();
0072 _cache_get_innermost_truth_hit.clear();
0073 _cache_get_outermost_truth_hit.clear();
0074 _cache_get_primary_particle_g4hit.clear();
0075
0076 _basetrutheval.next_event(topNode);
0077
0078 get_node_pointers(topNode);
0079 }
0080
0081
0082 std::set<PHG4Hit*> SvtxTruthEval::all_truth_hits()
0083 {
0084 if (!has_node_pointers())
0085 {
0086 ++_errors;
0087 return std::set<PHG4Hit*>();
0088 }
0089
0090 if (_do_cache)
0091 {
0092 if (!_cache_all_truth_hits.empty())
0093 {
0094 return _cache_all_truth_hits;
0095 }
0096 }
0097
0098
0099
0100
0101 std::set<PHG4Hit*> truth_hits;
0102
0103
0104 if (_g4hits_svtx)
0105 {
0106 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_svtx->getHits().first;
0107 g4iter != _g4hits_svtx->getHits().second;
0108 ++g4iter)
0109 {
0110 PHG4Hit* g4hit = g4iter->second;
0111 truth_hits.insert(g4hit);
0112 }
0113 }
0114
0115
0116 if (_g4hits_tracker)
0117 {
0118 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_tracker->getHits().first;
0119 g4iter != _g4hits_tracker->getHits().second;
0120 ++g4iter)
0121 {
0122 PHG4Hit* g4hit = g4iter->second;
0123 truth_hits.insert(g4hit);
0124 }
0125 }
0126
0127
0128 if (_g4hits_maps)
0129 {
0130 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_maps->getHits().first;
0131 g4iter != _g4hits_maps->getHits().second;
0132 ++g4iter)
0133 {
0134 PHG4Hit* g4hit = g4iter->second;
0135 truth_hits.insert(g4hit);
0136 }
0137 }
0138
0139
0140 if (_g4hits_mms)
0141 {
0142 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_mms->getHits().first;
0143 g4iter != _g4hits_mms->getHits().second;
0144 ++g4iter)
0145 {
0146 PHG4Hit* g4hit = g4iter->second;
0147 truth_hits.insert(g4hit);
0148 }
0149 }
0150
0151 if (_do_cache)
0152 {
0153 _cache_all_truth_hits = truth_hits;
0154 }
0155
0156 return truth_hits;
0157 }
0158
0159 std::set<PHG4Hit*> SvtxTruthEval::all_truth_hits(PHG4Particle* particle)
0160 {
0161 if (!has_node_pointers())
0162 {
0163 ++_errors;
0164 return std::set<PHG4Hit*>();
0165 }
0166
0167 if (_strict)
0168 {
0169 assert(particle);
0170 }
0171 else if (!particle)
0172 {
0173 ++_errors;
0174 return std::set<PHG4Hit*>();
0175 }
0176
0177 if (_cache_all_truth_hits_g4particle.empty())
0178 {
0179 FillTruthHitsFromParticleCache();
0180 }
0181
0182 if (_do_cache)
0183 {
0184 std::map<PHG4Particle*, std::set<PHG4Hit*>>::iterator iter =
0185 _cache_all_truth_hits_g4particle.find(particle);
0186 if (iter != _cache_all_truth_hits_g4particle.end())
0187 {
0188 return iter->second;
0189 }
0190 }
0191
0192
0193 std::set<PHG4Hit*> truth_hits;
0194 return truth_hits;
0195 }
0196
0197 void SvtxTruthEval::FillTruthHitsFromParticleCache()
0198 {
0199 std::multimap<const int, PHG4Hit*> temp_clusters_from_particles;
0200
0201 if (_g4hits_svtx)
0202 {
0203 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_svtx->getHits().first;
0204 g4iter != _g4hits_svtx->getHits().second;
0205 ++g4iter)
0206 {
0207 PHG4Hit* g4hit = g4iter->second;
0208 temp_clusters_from_particles.insert(std::make_pair(g4hit->get_trkid(), g4hit));
0209 }
0210 }
0211
0212
0213 if (_g4hits_tracker)
0214 {
0215 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_tracker->getHits().first;
0216 g4iter != _g4hits_tracker->getHits().second;
0217 ++g4iter)
0218 {
0219 PHG4Hit* g4hit = g4iter->second;
0220 temp_clusters_from_particles.insert(std::make_pair(g4hit->get_trkid(), g4hit));
0221 }
0222 }
0223
0224
0225 if (_g4hits_maps)
0226 {
0227 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_maps->getHits().first;
0228 g4iter != _g4hits_maps->getHits().second;
0229 ++g4iter)
0230 {
0231 PHG4Hit* g4hit = g4iter->second;
0232 temp_clusters_from_particles.insert(std::make_pair(g4hit->get_trkid(), g4hit));
0233 }
0234 }
0235
0236
0237 if (_g4hits_mms)
0238 {
0239 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_mms->getHits().first;
0240 g4iter != _g4hits_mms->getHits().second;
0241 ++g4iter)
0242 {
0243 PHG4Hit* g4hit = g4iter->second;
0244 temp_clusters_from_particles.insert(std::make_pair(g4hit->get_trkid(), g4hit));
0245 }
0246 }
0247
0248 PHG4TruthInfoContainer::ConstRange range = _truthinfo->GetParticleRange();
0249 for (PHG4TruthInfoContainer::ConstIterator iter = range.first;
0250 iter != range.second; ++iter)
0251 {
0252 PHG4Particle* g4particle = iter->second;
0253 std::set<PHG4Hit*> truth_hits;
0254 std::multimap<const int, PHG4Hit*>::const_iterator lower_bound = temp_clusters_from_particles.lower_bound(g4particle->get_track_id());
0255 std::multimap<const int, PHG4Hit*>::const_iterator upper_bound = temp_clusters_from_particles.upper_bound(g4particle->get_track_id());
0256 std::multimap<const int, PHG4Hit*>::const_iterator cfp_iter;
0257 for (cfp_iter = lower_bound; cfp_iter != upper_bound; ++cfp_iter)
0258 {
0259 PHG4Hit* g4hit = cfp_iter->second;
0260 truth_hits.insert(g4hit);
0261 }
0262 _cache_all_truth_hits_g4particle.insert(std::make_pair(g4particle, truth_hits));
0263 }
0264 }
0265
0266 std::map<TrkrDefs::cluskey, std::shared_ptr<TrkrCluster>> SvtxTruthEval::all_truth_clusters(PHG4Particle* particle)
0267 {
0268 using output_type_t = std::map<TrkrDefs::cluskey, std::shared_ptr<TrkrCluster>>;
0269 if (!has_node_pointers())
0270 {
0271 ++_errors;
0272 return output_type_t();
0273 }
0274
0275 if (_strict)
0276 {
0277 assert(particle);
0278 }
0279 else if (!particle)
0280 {
0281 ++_errors;
0282 return output_type_t();
0283 }
0284
0285 if (_do_cache)
0286 {
0287 const auto iter = _cache_all_truth_clusters_g4particle.find(particle);
0288 if (iter != _cache_all_truth_clusters_g4particle.end())
0289 {
0290 return iter->second;
0291 }
0292 }
0293
0294 if (_verbosity > 1)
0295 {
0296 std::cout << PHWHERE << " Truth clustering for particle " << particle->get_track_id() << std::endl;
0297 };
0298
0299
0300 std::set<PHG4Hit*> g4hits = all_truth_hits(particle);
0301
0302 float ng4hits = g4hits.size();
0303 if (ng4hits == 0)
0304 {
0305 return output_type_t();
0306 }
0307
0308
0309 output_type_t truth_clusters;
0310
0311
0312
0313
0314 unsigned int layer;
0315 for (layer = 0; layer < _nlayers_maps + _nlayers_intt + _nlayers_tpc + _nlayers_mms; ++layer)
0316 {
0317 float gx = std::numeric_limits<float>::quiet_NaN();
0318 float gy = std::numeric_limits<float>::quiet_NaN();
0319 float gz = std::numeric_limits<float>::quiet_NaN();
0320 float gt = std::numeric_limits<float>::quiet_NaN();
0321 float gedep = std::numeric_limits<float>::quiet_NaN();
0322
0323 std::vector<PHG4Hit*> contributing_hits;
0324 std::vector<double> contributing_hits_energy;
0325 std::vector<std::vector<double>> contributing_hits_entry;
0326 std::vector<std::vector<double>> contributing_hits_exit;
0327 LayerClusterG4Hits(g4hits, contributing_hits, contributing_hits_energy, contributing_hits_entry, contributing_hits_exit, layer, gx, gy, gz, gt, gedep);
0328 if (!(gedep > 0))
0329 {
0330 continue;
0331 }
0332
0333
0334
0335 TrkrDefs::cluskey ckey;
0336 if (layer >= _nlayers_maps + _nlayers_intt && layer < _nlayers_maps + _nlayers_intt + _nlayers_tpc)
0337 {
0338 unsigned int side = 0;
0339 if (gz > 0)
0340 {
0341 side = 1;
0342 }
0343
0344 unsigned int sector = 0;
0345 ckey = TpcDefs::genClusKey(layer, sector, side, iclus);
0346 }
0347 else if (layer < _nlayers_maps)
0348 {
0349 unsigned int stave = 0;
0350 unsigned int chip = 0;
0351 unsigned int strobe = 0;
0352 ckey = MvtxDefs::genClusKey(layer, stave, chip, strobe, iclus);
0353 }
0354 else if (layer >= _nlayers_maps && layer < _nlayers_maps + _nlayers_intt)
0355 {
0356
0357 unsigned int ladderzid = 0;
0358 unsigned int ladderphiid = 0;
0359 uint16_t crossing = 0;
0360 ckey = InttDefs::genClusKey(layer, ladderzid, ladderphiid, crossing, iclus);
0361 }
0362 else if (layer >= _nlayers_maps + _nlayers_intt + _nlayers_tpc)
0363 {
0364 unsigned int tile = 0;
0365 MicromegasDefs::SegmentationType segtype;
0366 segtype = MicromegasDefs::SegmentationType::SEGMENTATION_PHI;
0367 TrkrDefs::hitsetkey hkey = MicromegasDefs::genHitSetKey(layer, segtype, tile);
0368 ckey = TrkrDefs::genClusKey(hkey, iclus);
0369 }
0370 else
0371 {
0372 std::cout << PHWHERE << "Bad layer number: " << layer << std::endl;
0373 continue;
0374 }
0375
0376 auto clus = std::make_shared<TrkrClusterv1>();
0377 iclus++;
0378
0379
0380 unsigned int adc_value = getAdcValue(gedep);
0381
0382 clus->setAdc(adc_value);
0383 clus->setPosition(0, gx);
0384 clus->setPosition(1, gy);
0385 clus->setPosition(2, gz);
0386 clus->setGlobal();
0387
0388
0389 for (auto& contributing_hit : contributing_hits)
0390 {
0391 _truth_cluster_truth_hit_map.insert(std::make_pair(ckey, contributing_hit));
0392 }
0393
0394
0395 float g4phisize = std::numeric_limits<float>::quiet_NaN();
0396 float g4zsize = std::numeric_limits<float>::quiet_NaN();
0397 G4ClusterSize(ckey, layer, contributing_hits_entry, contributing_hits_exit, g4phisize, g4zsize);
0398
0399 for (int i1 = 0; i1 < 3; ++i1)
0400 {
0401 for (int i2 = 0; i2 < 3; ++i2)
0402 {
0403 clus->setSize(i1, i2, 0.0);
0404 clus->setError(i1, i2, 0.0);
0405 }
0406 }
0407 clus->setError(0, 0, gedep);
0408 clus->setSize(1, 1, g4phisize);
0409 clus->setSize(2, 2, g4zsize);
0410 clus->setError(1, 1, g4phisize / std::sqrt(12));
0411 clus->setError(2, 2, g4zsize / std::sqrt(12.0));
0412
0413 truth_clusters.insert(std::make_pair(ckey, clus));
0414
0415 }
0416
0417 if (_do_cache)
0418 {
0419 _cache_all_truth_clusters_g4particle.insert(std::make_pair(particle, truth_clusters));
0420 }
0421
0422 return truth_clusters;
0423 }
0424
0425 void SvtxTruthEval::LayerClusterG4Hits(const std::set<PHG4Hit*>& truth_hits, std::vector<PHG4Hit*>& contributing_hits, std::vector<double>& contributing_hits_energy, std::vector<std::vector<double>>& contributing_hits_entry, std::vector<std::vector<double>>& contributing_hits_exit, float layer, float& x, float& y, float& z, float& t, float& e)
0426 {
0427 bool use_geo = true;
0428
0429
0430
0431 float gx = 0.0;
0432 float gy = 0.0;
0433 float gz = 0.0;
0434 float gr = 0.0;
0435 float gt = 0.0;
0436 float gwt = 0.0;
0437
0438 if (layer >= _nlayers_maps + _nlayers_intt && layer < _nlayers_maps + _nlayers_intt + _nlayers_tpc)
0439 {
0440
0441
0442
0443
0444
0445
0446 PHG4TpcGeom* GeoLayer = _tpc_geom_container->GetLayerCellGeom(layer);
0447
0448
0449 float rbin = GeoLayer->get_radius() - GeoLayer->get_thickness() / 2.0;
0450 float rbout = GeoLayer->get_radius() + GeoLayer->get_thickness() / 2.0;
0451
0452 if (_verbosity > 1)
0453 {
0454 std::cout << " TruthEval::LayerCluster hits for layer " << layer << " with rbin " << rbin << " rbout " << rbout << std::endl;
0455 }
0456
0457
0458 for (auto *this_g4hit : truth_hits)
0459 {
0460 float rbegin = std::sqrt(this_g4hit->get_x(0) * this_g4hit->get_x(0) + this_g4hit->get_y(0) * this_g4hit->get_y(0));
0461 float rend = std::sqrt(this_g4hit->get_x(1) * this_g4hit->get_x(1) + this_g4hit->get_y(1) * this_g4hit->get_y(1));
0462
0463
0464
0465 float xl[2];
0466 float yl[2];
0467 float zl[2];
0468
0469 if (rbegin < rend)
0470 {
0471 xl[0] = this_g4hit->get_x(0);
0472 yl[0] = this_g4hit->get_y(0);
0473 zl[0] = this_g4hit->get_z(0);
0474 xl[1] = this_g4hit->get_x(1);
0475 yl[1] = this_g4hit->get_y(1);
0476 zl[1] = this_g4hit->get_z(1);
0477 }
0478 else
0479 {
0480 xl[0] = this_g4hit->get_x(1);
0481 yl[0] = this_g4hit->get_y(1);
0482 zl[0] = this_g4hit->get_z(1);
0483 xl[1] = this_g4hit->get_x(0);
0484 yl[1] = this_g4hit->get_y(0);
0485 zl[1] = this_g4hit->get_z(0);
0486 std::swap(rbegin, rend);
0487
0488 }
0489
0490
0491 if (rbegin < rbin && rend < rbin)
0492 {
0493 continue;
0494 }
0495 if (rbegin > rbout && rend > rbout)
0496 {
0497 continue;
0498 }
0499
0500 if (_verbosity > 1)
0501 {
0502 std::cout << " keep g4hit with rbegin " << rbegin << " rend " << rend
0503 << " xbegin " << xl[0] << " xend " << xl[1]
0504 << " ybegin " << yl[0] << " yend " << yl[1]
0505 << " zbegin " << zl[0] << " zend " << zl[1]
0506 << std::endl;
0507 }
0508
0509 float xin = xl[0];
0510 float yin = yl[0];
0511 float zin = zl[0];
0512 float xout = xl[1];
0513 float yout = yl[1];
0514 float zout = zl[1];
0515
0516 float local_t = std::numeric_limits<float>::quiet_NaN();
0517
0518 if (rbegin < rbin)
0519 {
0520
0521 local_t = line_circle_intersection(xl, yl, zl, rbin);
0522 if (local_t > 0)
0523 {
0524 xin = xl[0] + local_t * (xl[1] - xl[0]);
0525 yin = yl[0] + local_t * (yl[1] - yl[0]);
0526 zin = zl[0] + local_t * (zl[1] - zl[0]);
0527 }
0528 }
0529
0530 if (rend > rbout)
0531 {
0532
0533 local_t = line_circle_intersection(xl, yl, zl, rbout);
0534 if (local_t > 0)
0535 {
0536 xout = xl[0] + local_t * (xl[1] - xl[0]);
0537 yout = yl[0] + local_t * (yl[1] - yl[0]);
0538 zout = zl[0] + local_t * (zl[1] - zl[0]);
0539 }
0540 }
0541
0542 double rin = std::sqrt(xin * xin + yin * yin);
0543 double rout = std::sqrt(xout * xout + yout * yout);
0544
0545
0546 double efrac = this_g4hit->get_edep() * (rout - rin) / (rend - rbegin);
0547 gx += (xin + xout) * 0.5 * efrac;
0548 gy += (yin + yout) * 0.5 * efrac;
0549 gz += (zin + zout) * 0.5 * efrac;
0550 gt += this_g4hit->get_avg_t() * efrac;
0551 gr += (rin + rout) * 0.5 * efrac;
0552 gwt += efrac;
0553
0554 if (_verbosity > 1)
0555 {
0556 std::cout << " rin " << rin << " rout " << rout
0557 << " xin " << xin << " xout " << xout << " yin " << yin << " yout " << yout << " zin " << zin << " zout " << zout
0558 << " edep " << this_g4hit->get_edep()
0559 << " this_edep " << efrac << std::endl;
0560 std::cout << " xavge " << (xin + xout) * 0.5 << " yavge " << (yin + yout) * 0.5 << " zavge " << (zin + zout) * 0.5 << " ravge " << (rin + rout) * 0.5
0561 << std::endl;
0562 }
0563
0564
0565 std::vector<double> entry_loc;
0566 entry_loc.push_back(xin);
0567 entry_loc.push_back(yin);
0568 entry_loc.push_back(zin);
0569 std::vector<double> exit_loc;
0570 exit_loc.push_back(xout);
0571 exit_loc.push_back(yout);
0572 exit_loc.push_back(zout);
0573
0574
0575 contributing_hits.push_back(this_g4hit);
0576 contributing_hits_energy.push_back(this_g4hit->get_edep() * (zout - zin) / (zl[1] - zl[0]));
0577 contributing_hits_entry.push_back(entry_loc);
0578 contributing_hits_exit.push_back(exit_loc);
0579
0580 }
0581
0582 if (gwt == 0)
0583 {
0584 e = gwt;
0585 return;
0586 }
0587
0588 gx /= gwt;
0589 gy /= gwt;
0590 gz /= gwt;
0591 gr = (rbin + rbout) * 0.5;
0592 gt /= gwt;
0593
0594 if (_verbosity > 1)
0595 {
0596 std::cout << " weighted means: gx " << gx << " gy " << gy << " gz " << gz << " gr " << gr << " e " << gwt << std::endl;
0597 }
0598
0599 if (use_geo)
0600 {
0601
0602
0603 float rentry = 999.0;
0604 float xentry = 999.0;
0605 float yentry = 999.0;
0606 float zentry = 999.0;
0607 float rexit = -999.0;
0608 float xexit = -999.0;
0609 float yexit = -999.0;
0610 float zexit = -999.0;
0611
0612 for (unsigned int ientry = 0; ientry < contributing_hits_entry.size(); ++ientry)
0613 {
0614 float tmpx = contributing_hits_entry[ientry][0];
0615 float tmpy = contributing_hits_entry[ientry][1];
0616 float tmpr = std::sqrt(tmpx * tmpx + tmpy * tmpy);
0617
0618 if (tmpr < rentry)
0619 {
0620 rentry = tmpr;
0621 xentry = contributing_hits_entry[ientry][0];
0622 yentry = contributing_hits_entry[ientry][1];
0623 zentry = contributing_hits_entry[ientry][2];
0624 }
0625
0626 tmpx = contributing_hits_exit[ientry][0];
0627 tmpy = contributing_hits_exit[ientry][1];
0628 tmpr = std::sqrt(tmpx * tmpx + tmpy * tmpy);
0629
0630 if (tmpr > rexit)
0631 {
0632 rexit = tmpr;
0633 xexit = contributing_hits_exit[ientry][0];
0634 yexit = contributing_hits_exit[ientry][1];
0635 zexit = contributing_hits_exit[ientry][2];
0636 }
0637 }
0638
0639 float geo_r = (rentry + rexit) * 0.5;
0640 float geo_x = (xentry + xexit) * 0.5;
0641 float geo_y = (yentry + yexit) * 0.5;
0642 float geo_z = (zentry + zexit) * 0.5;
0643
0644 if (rexit > 0)
0645 {
0646 gx = geo_x;
0647 gy = geo_y;
0648 gz = geo_z;
0649 gr = geo_r;
0650 }
0651
0652 if (_verbosity > 1)
0653 {
0654 std::cout << " rentry " << rentry << " rexit " << rexit
0655 << " xentry " << xentry << " xexit " << xexit << " yentry " << yentry << " yexit " << yexit << " zentry " << zentry << " zexit " << zexit << std::endl;
0656
0657 std::cout << " geometric means: geo_x " << geo_x << " geo_y " << geo_y << " geo_z " << geo_z << " geo r " << geo_r << " e " << gwt << std::endl
0658 << std::endl;
0659 }
0660 }
0661
0662 }
0663 else
0664 {
0665
0666 for (auto *this_g4hit : truth_hits)
0667 {
0668 if (this_g4hit->get_layer() != (unsigned int) layer)
0669 {
0670 continue;
0671 }
0672
0673 gx = this_g4hit->get_avg_x();
0674 gy = this_g4hit->get_avg_y();
0675 gz = this_g4hit->get_avg_z();
0676 gt = this_g4hit->get_avg_t();
0677 gwt += this_g4hit->get_edep();
0678
0679
0680 std::vector<double> entry_loc;
0681 entry_loc.push_back(this_g4hit->get_x(0));
0682 entry_loc.push_back(this_g4hit->get_y(0));
0683 entry_loc.push_back(this_g4hit->get_z(0));
0684 std::vector<double> exit_loc;
0685 exit_loc.push_back(this_g4hit->get_x(1));
0686 exit_loc.push_back(this_g4hit->get_y(1));
0687 exit_loc.push_back(this_g4hit->get_z(1));
0688
0689
0690 contributing_hits.push_back(this_g4hit);
0691 contributing_hits_energy.push_back(this_g4hit->get_edep());
0692 contributing_hits_entry.push_back(entry_loc);
0693 contributing_hits_exit.push_back(exit_loc);
0694 }
0695 }
0696
0697 x = gx;
0698 y = gy;
0699 z = gz;
0700 t = gt;
0701 e = gwt;
0702
0703 return;
0704 }
0705
0706 void SvtxTruthEval::G4ClusterSize(TrkrDefs::cluskey ckey, unsigned int layer, const std::vector<std::vector<double>> &contributing_hits_entry, const std::vector<std::vector<double>> &contributing_hits_exit, float& g4phisize, float& g4zsize)
0707 {
0708
0709 double inner_radius = 100.;
0710 double inner_x = std::numeric_limits<double>::quiet_NaN();
0711 double inner_y = std::numeric_limits<double>::quiet_NaN();
0712 double inner_z = std::numeric_limits<double>::quiet_NaN();
0713
0714 double outer_radius = 0.;
0715 double outer_x = std::numeric_limits<double>::quiet_NaN();
0716 double outer_y = std::numeric_limits<double>::quiet_NaN();
0717 double outer_z = std::numeric_limits<double>::quiet_NaN();
0718
0719 for (unsigned int ihit = 0; ihit < contributing_hits_entry.size(); ++ihit)
0720 {
0721 double rad1 = std::sqrt(pow(contributing_hits_entry[ihit][0], 2) + pow(contributing_hits_entry[ihit][1], 2));
0722 if (rad1 < inner_radius)
0723 {
0724 inner_radius = rad1;
0725 inner_x = contributing_hits_entry[ihit][0];
0726 inner_y = contributing_hits_entry[ihit][1];
0727 inner_z = contributing_hits_entry[ihit][2];
0728 }
0729
0730 double rad2 = std::sqrt(pow(contributing_hits_exit[ihit][0], 2) + pow(contributing_hits_exit[ihit][1], 2));
0731 if (rad2 > outer_radius)
0732 {
0733 outer_radius = rad2;
0734 outer_x = contributing_hits_exit[ihit][0];
0735 outer_y = contributing_hits_exit[ihit][1];
0736 outer_z = contributing_hits_exit[ihit][2];
0737 }
0738 }
0739
0740 double inner_phi = atan2(inner_y, inner_x);
0741 double outer_phi = atan2(outer_y, outer_x);
0742 double avge_z = (outer_z + inner_z) / 2.0;
0743
0744 unsigned int side = 0;
0745 if (avge_z < 0)
0746 {
0747 side = 1;
0748 }
0749
0750
0751
0752 double sigmas = 2.0;
0753
0754 double radius = (inner_radius + outer_radius) / 2.;
0755 if (radius > 28 && radius < 80)
0756 {
0757 PHG4TpcGeom* layergeom = _tpc_geom_container->GetLayerCellGeom(layer);
0758
0759 double tpc_max_driftlength = layergeom->get_max_driftlength();
0760 double drift_velocity = layergeom->get_drift_velocity_sim();
0761
0762
0763
0764 double diffusion_trans = 0.006;
0765 double phidiffusion = diffusion_trans * std::sqrt(tpc_max_driftlength - fabs(avge_z));
0766
0767 double added_smear_trans = 0.085;
0768 double gem_spread = 0.04;
0769
0770 if (outer_phi < inner_phi)
0771 {
0772 std::swap(outer_phi, inner_phi);
0773 }
0774
0775
0776 double g4max_phi = outer_phi + sigmas * std::sqrt(pow(phidiffusion, 2) + pow(added_smear_trans, 2) + pow(gem_spread, 2)) / radius;
0777 double g4min_phi = inner_phi - sigmas * std::sqrt(pow(phidiffusion, 2) + pow(added_smear_trans, 2) + pow(gem_spread, 2)) / radius;
0778
0779 unsigned int phibinwidth = 1;
0780 if(std::isnan(g4min_phi) || std::isnan(g4max_phi))
0781 {
0782 if (_verbosity > 1)
0783 {
0784 std::cout << " g4min_phi " << g4min_phi << " g4max_phi " << g4max_phi << std::endl;
0785 std::cout << " outer_phi " << outer_phi << " inner_phi " << inner_phi << " radius " << radius << std::endl;
0786 }
0787 }
0788 else
0789 {
0790
0791 unsigned int phibinmin = layergeom->get_phibin(g4min_phi, side);
0792 unsigned int phibinmax = layergeom->get_phibin(g4max_phi, side);
0793 phibinwidth = phibinmax - phibinmin + 1;
0794 }
0795 g4phisize = (double) phibinwidth * layergeom->get_phistep() * layergeom->get_radius();
0796
0797
0798
0799 double g4max_z = 0;
0800 double g4min_z = 0;
0801
0802 outer_z = fabs(outer_z);
0803 inner_z = fabs(inner_z);
0804
0805 double diffusion_long = 0.015;
0806 double zdiffusion = diffusion_long * std::sqrt(tpc_max_driftlength - fabs(avge_z));
0807 double zshaping_lead = 32.0 * drift_velocity;
0808 double zshaping_tail = 48.0 * drift_velocity;
0809 double added_smear_long = 0.105;
0810
0811
0812 if (outer_z < inner_z)
0813 {
0814 std::swap(outer_z, inner_z);
0815 }
0816 g4max_z = outer_z + sigmas * std::sqrt(pow(zdiffusion, 2) + pow(added_smear_long, 2) + pow(zshaping_lead, 2));
0817 g4min_z = inner_z - sigmas * std::sqrt(pow(zdiffusion, 2) + pow(added_smear_long, 2) + pow(zshaping_tail, 2));
0818
0819
0820 unsigned int binmin = layergeom->get_zbin(g4min_z);
0821 unsigned int binmax = layergeom->get_zbin(g4max_z);
0822 if (binmax < binmin)
0823 {
0824 std::swap(binmax, binmin);
0825 }
0826 unsigned int binwidth = binmax - binmin + 1;
0827
0828
0829 g4zsize = (double) binwidth * layergeom->get_zstep();
0830 }
0831 else if (radius > 6 && radius < 20)
0832 {
0833
0834
0835 CylinderGeomIntt* layergeom = dynamic_cast<CylinderGeomIntt*>(_intt_geom_container->GetLayerGeom(layer));
0836
0837
0838 double world_inner[3] = {inner_x, inner_y, inner_z};
0839 TVector3 world_inner_vec = {inner_x, inner_y, inner_z};
0840
0841 int segment_z_bin;
0842 int segment_phi_bin;
0843 layergeom->find_indices_from_world_location(segment_z_bin, segment_phi_bin, world_inner);
0844
0845 TrkrDefs::hitsetkey hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0846 auto surf = _tgeometry->maps().getSiliconSurface(hitsetkey);
0847 TVector3 local_inner_vec = CylinderGeomInttHelper::get_local_from_world_coords(surf, _tgeometry, world_inner);
0848 double yin = local_inner_vec[1];
0849 double zin = local_inner_vec[2];
0850 int strip_y_index;
0851 int strip_z_index;
0852 layergeom->find_strip_index_values(segment_z_bin, yin, zin, strip_y_index, strip_z_index);
0853
0854
0855 double world_outer[3] = {outer_x, outer_y, outer_z};
0856 TVector3 world_outer_vec = {outer_x, outer_y, outer_z};
0857
0858 layergeom->find_indices_from_world_location(segment_z_bin, segment_phi_bin, world_outer);
0859 TrkrDefs::hitsetkey ohitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0860 auto osurf = _tgeometry->maps().getSiliconSurface(ohitsetkey);
0861 TVector3 local_outer_vec = CylinderGeomInttHelper::get_local_from_world_coords(osurf, _tgeometry, world_outer_vec);
0862 double yout = local_outer_vec[1];
0863 double zout = local_outer_vec[2];
0864 int strip_y_index_out;
0865 int strip_z_index_out;
0866 layergeom->find_strip_index_values(segment_z_bin, yout, zout, strip_y_index_out, strip_z_index_out);
0867
0868 int strips = abs(strip_y_index_out - strip_y_index) + 1;
0869 int cols = abs(strip_z_index_out - strip_z_index) + 1;
0870
0871 double strip_width = (double) strips * layergeom->get_strip_y_spacing();
0872 double strip_length = (double) cols * layergeom->get_strip_z_spacing();
0873
0874 g4phisize = strip_width;
0875 g4zsize = strip_length;
0876
0877
0878
0879
0880
0881
0882 }
0883 else if (radius > 80)
0884 {
0885
0886 g4phisize = 300e-04;
0887 g4zsize = 300e-04;
0888 }
0889 else
0890 {
0891 unsigned int stave;
0892 unsigned int stave_outer;
0893 unsigned int chip;
0894 unsigned int chip_outer;
0895 int row;
0896 int row_outer;
0897 int column;
0898 int column_outer;
0899
0900
0901 double max_diffusion_radius = 25.0e-4;
0902 double min_diffusion_radius = 8.0e-4;
0903
0904 CylinderGeom_Mvtx* layergeom = dynamic_cast<CylinderGeom_Mvtx*>(_mvtx_geom_container->GetLayerGeom(layer));
0905
0906 TVector3 world_inner = {inner_x, inner_y, inner_z};
0907 std::vector<double> world_inner_vec = {world_inner[0], world_inner[1], world_inner[2]};
0908 layergeom->get_sensor_indices_from_world_coords(world_inner_vec, stave, chip);
0909 TrkrDefs::hitsetkey ihitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0910 auto isurf = _tgeometry->maps().getSiliconSurface(ihitsetkey);
0911 TVector3 local_inner = CylinderGeom_MvtxHelper::get_local_from_world_coords(isurf, _tgeometry, world_inner);
0912
0913 TVector3 world_outer = {outer_x, outer_y, outer_z};
0914 std::vector<double> world_outer_vec = {world_outer[0], world_outer[1], world_outer[2]};
0915 layergeom->get_sensor_indices_from_world_coords(world_outer_vec, stave_outer, chip_outer);
0916 TrkrDefs::hitsetkey ohitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0917 auto osurf = _tgeometry->maps().getSiliconSurface(ohitsetkey);
0918 TVector3 local_outer = CylinderGeom_MvtxHelper::get_local_from_world_coords(osurf, _tgeometry, world_outer);
0919
0920 double diff = max_diffusion_radius * 0.6;
0921 if (local_outer[0] < local_inner[0])
0922 {
0923 diff = -diff;
0924 }
0925 local_outer[0] += diff;
0926 local_inner[0] -= diff;
0927
0928 double diff_outer = min_diffusion_radius * 0.6;
0929 if (local_outer[2] < local_inner[2])
0930 {
0931 diff_outer = -diff_outer;
0932 }
0933 local_outer[2] += diff_outer;
0934 local_inner[2] -= diff_outer;
0935
0936 layergeom->get_pixel_from_local_coords(local_inner, row, column);
0937 layergeom->get_pixel_from_local_coords(local_outer, row_outer, column_outer);
0938
0939 if (row_outer < row)
0940 {
0941 std::swap(row_outer, row);
0942 }
0943 unsigned int rows = row_outer - row + 1;
0944 g4phisize = (double) rows * layergeom->get_pixel_x();
0945
0946 if (column_outer < column)
0947 {
0948 std::swap(column_outer, column);
0949 }
0950 unsigned int columns = column_outer - column + 1;
0951 g4zsize = (double) columns * layergeom->get_pixel_z();
0952
0953
0954
0955
0956
0957
0958 }
0959 }
0960
0961 std::set<PHG4Hit*> SvtxTruthEval::get_truth_hits_from_truth_cluster(TrkrDefs::cluskey ckey)
0962 {
0963 std::set<PHG4Hit*> g4hit_set;
0964
0965 std::pair<std::multimap<TrkrDefs::cluskey, PHG4Hit*>::iterator,
0966 std::multimap<TrkrDefs::cluskey, PHG4Hit*>::iterator>
0967 ret = _truth_cluster_truth_hit_map.equal_range(ckey);
0968
0969 for (std::multimap<TrkrDefs::cluskey, PHG4Hit*>::iterator jter = ret.first; jter != ret.second; ++jter)
0970 {
0971 g4hit_set.insert(jter->second);
0972 }
0973
0974 return g4hit_set;
0975 }
0976
0977 PHG4Hit* SvtxTruthEval::get_innermost_truth_hit(PHG4Particle* particle)
0978 {
0979 if (!has_node_pointers())
0980 {
0981 ++_errors;
0982 return nullptr;
0983 }
0984
0985 if (_strict)
0986 {
0987 assert(particle);
0988 }
0989 else if (!particle)
0990 {
0991 ++_errors;
0992 return nullptr;
0993 }
0994
0995 PHG4Hit* innermost_hit = nullptr;
0996 float innermost_radius = std::numeric_limits<float>::max();
0997
0998 std::set<PHG4Hit*> truth_hits = all_truth_hits(particle);
0999 for (auto *candidate : truth_hits)
1000 {
1001 float x = candidate->get_x(0);
1002 float y = candidate->get_y(0);
1003 float r = std::sqrt(x * x + y * y);
1004 if (r < innermost_radius)
1005 {
1006 innermost_radius = r;
1007 innermost_hit = candidate;
1008 }
1009 }
1010
1011 return innermost_hit;
1012 }
1013
1014 PHG4Hit* SvtxTruthEval::get_outermost_truth_hit(PHG4Particle* particle)
1015 {
1016 if (!has_node_pointers())
1017 {
1018 ++_errors;
1019 return nullptr;
1020 }
1021
1022 if (_strict)
1023 {
1024 assert(particle);
1025 }
1026 else if (!particle)
1027 {
1028 ++_errors;
1029 return nullptr;
1030 }
1031
1032 PHG4Hit* outermost_hit = nullptr;
1033 float outermost_radius = std::numeric_limits<float>::min();
1034
1035 if (_do_cache)
1036 {
1037 std::map<PHG4Particle*, PHG4Hit*>::iterator iter =
1038 _cache_get_outermost_truth_hit.find(particle);
1039 if (iter != _cache_get_outermost_truth_hit.end())
1040 {
1041 return iter->second;
1042 }
1043 }
1044
1045 std::set<PHG4Hit*> truth_hits = all_truth_hits(particle);
1046 for (auto *candidate : truth_hits)
1047 {
1048 float x = candidate->get_x(1);
1049 float y = candidate->get_y(1);
1050 float r = std::sqrt(x * x + y * y);
1051 if (r > outermost_radius)
1052 {
1053 outermost_radius = r;
1054 outermost_hit = candidate;
1055 }
1056 }
1057 if (_do_cache)
1058 {
1059 _cache_get_outermost_truth_hit.insert(std::make_pair(particle, outermost_hit));
1060 }
1061
1062 return outermost_hit;
1063 }
1064
1065 PHG4Particle* SvtxTruthEval::get_particle(PHG4Hit* g4hit)
1066 {
1067 return _basetrutheval.get_particle(g4hit);
1068 }
1069
1070 int SvtxTruthEval::get_embed(PHG4Particle* particle)
1071 {
1072 return _basetrutheval.get_embed(particle);
1073 }
1074
1075 PHG4VtxPoint* SvtxTruthEval::get_vertex(PHG4Particle* particle)
1076 {
1077 return _basetrutheval.get_vertex(particle);
1078 }
1079
1080 bool SvtxTruthEval::is_primary(PHG4Particle* particle)
1081 {
1082 return _basetrutheval.is_primary(particle);
1083 }
1084
1085 PHG4Particle* SvtxTruthEval::get_primary_particle(PHG4Hit* g4hit)
1086 {
1087 if (!has_node_pointers())
1088 {
1089 ++_errors;
1090 return nullptr;
1091 }
1092
1093 if (_strict)
1094 {
1095 assert(g4hit);
1096 }
1097 else if (!g4hit)
1098 {
1099 ++_errors;
1100 return nullptr;
1101 }
1102
1103 if (_do_cache)
1104 {
1105 std::map<PHG4Hit*, PHG4Particle*>::iterator iter =
1106 _cache_get_primary_particle_g4hit.find(g4hit);
1107 if (iter != _cache_get_primary_particle_g4hit.end())
1108 {
1109 return iter->second;
1110 }
1111 }
1112
1113 PHG4Particle* primary = _basetrutheval.get_primary_particle(g4hit);
1114
1115 if (_do_cache)
1116 {
1117 _cache_get_primary_particle_g4hit.insert(std::make_pair(g4hit, primary));
1118 }
1119
1120 if (_strict)
1121 {
1122 assert(primary);
1123 }
1124 else if (!primary)
1125 {
1126 ++_errors;
1127 }
1128
1129 return primary;
1130 }
1131
1132 PHG4Particle* SvtxTruthEval::get_primary_particle(PHG4Particle* particle)
1133 {
1134 return _basetrutheval.get_primary_particle(particle);
1135 }
1136
1137 PHG4Particle* SvtxTruthEval::get_particle(const int trackid)
1138 {
1139 return _basetrutheval.get_particle(trackid);
1140 }
1141
1142 bool SvtxTruthEval::is_g4hit_from_particle(PHG4Hit* g4hit, PHG4Particle* particle)
1143 {
1144 return _basetrutheval.is_g4hit_from_particle(g4hit, particle);
1145 }
1146
1147 bool SvtxTruthEval::are_same_particle(PHG4Particle* p1, PHG4Particle* p2)
1148 {
1149 return _basetrutheval.are_same_particle(p1, p2);
1150 }
1151
1152 bool SvtxTruthEval::are_same_vertex(PHG4VtxPoint* vtx1, PHG4VtxPoint* vtx2)
1153 {
1154 return _basetrutheval.are_same_vertex(vtx1, vtx2);
1155 }
1156
1157 void SvtxTruthEval::get_node_pointers(PHCompositeNode* topNode)
1158 {
1159 _tgeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
1160 _truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
1161
1162 _g4hits_mms = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_MICROMEGAS");
1163 _g4hits_svtx = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_TPC");
1164 _g4hits_tracker = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_INTT");
1165 _g4hits_maps = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_MVTX");
1166
1167 _mms_geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MICROMEGAS_FULL");
1168 _tpc_geom_container = findNode::getClass<PHG4TpcGeomContainer>(topNode, "TPCGEOMCONTAINER");
1169 _intt_geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
1170 _mvtx_geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
1171
1172 return;
1173 }
1174
1175 bool SvtxTruthEval::has_node_pointers()
1176 {
1177 if (_strict)
1178 {
1179 assert(_truthinfo);
1180 }
1181 else if (!_truthinfo)
1182 {
1183 return false;
1184 }
1185
1186 if (_strict)
1187 {
1188 assert(_g4hits_mms || _g4hits_svtx || _g4hits_tracker || _g4hits_maps);
1189 }
1190 else if (!_g4hits_mms && !_g4hits_svtx && !_g4hits_tracker && !_g4hits_maps)
1191 {
1192 return false;
1193 }
1194
1195 return true;
1196 }
1197
1198 float SvtxTruthEval::line_circle_intersection(float x[], float y[], float z[], float radius)
1199 {
1200
1201
1202
1203
1204
1205
1206
1207
1208 float A = (x[1] - x[0]) * (x[1] - x[0]) + (y[1] - y[0]) * (y[1] - y[0]);
1209 float B = 2.0 * x[0] * (x[1] - x[0]) + 2.0 * y[0] * (y[1] - y[0]);
1210 float C = x[0] * x[0] + y[0] * y[0] - radius * radius;
1211 float tup = (-B + std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
1212 float tdn = (-B - std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
1213
1214
1215 float t;
1216 if (tdn >= -0.0e-4 && tdn <= 1.0004)
1217 {
1218 t = tdn;
1219 }
1220 else if (tup >= -0.0e-4 && tup <= 1.0004)
1221 {
1222 t = tup;
1223 }
1224 else
1225 {
1226 std::cout << PHWHERE << " **** Oops! No valid solution for tup or tdn, tdn = " << tdn << " tup = " << tup << std::endl;
1227 std::cout << " radius " << radius << " rbegin " << std::sqrt(x[0] * x[0] + y[0] * y[0]) << " rend " << std::sqrt(x[1] * x[1] + y[1] * y[1]) << std::endl;
1228 std::cout << " x0 " << x[0] << " x1 " << x[1] << std::endl;
1229 std::cout << " y0 " << y[0] << " y1 " << y[1] << std::endl;
1230 std::cout << " z0 " << z[0] << " z1 " << z[1] << std::endl;
1231 std::cout << " A " << A << " B " << B << " C " << C << std::endl;
1232
1233 t = -1;
1234 }
1235
1236 return t;
1237 }
1238
1239 unsigned int SvtxTruthEval::getAdcValue(double gedep)
1240 {
1241
1242
1243
1244 double Ne_dEdx = 1.56;
1245 double CF4_dEdx = 7.00;
1246 double Ne_NTotal = 43;
1247 double CF4_NTotal = 100;
1248 double Tpc_NTot = 0.5 * Ne_NTotal + 0.5 * CF4_NTotal;
1249 double Tpc_dEdx = 0.5 * Ne_dEdx + 0.5 * CF4_dEdx;
1250 double Tpc_ElectronsPerKeV = Tpc_NTot / Tpc_dEdx;
1251 double electrons_per_gev = Tpc_ElectronsPerKeV * 1e6;
1252
1253 double gem_amplification = 1400;
1254 double input_electrons = gedep * electrons_per_gev * gem_amplification;
1255
1256
1257 double ChargeToPeakVolts = 20;
1258 double ADCSignalConversionGain = ChargeToPeakVolts * 1.60e-04 * 2.4;
1259 double adc_input_voltage = input_electrons * ADCSignalConversionGain;
1260 unsigned int adc_output = (unsigned int) (adc_input_voltage * 1024.0 / 2200.0);
1261 adc_output = std::min<unsigned int>(adc_output, 1023);
1262
1263 return adc_output;
1264 }