File indexing completed on 2025-12-17 09:22:13
0001 #include "TpcClusterBuilder.h"
0002
0003 #include <trackbase/ClusHitsVerbosev1.h>
0004 #include <trackbase/TpcDefs.h>
0005 #include <trackbase/TrkrClusterContainer.h>
0006 #include <trackbase/TrkrClusterv4.h>
0007 #include <trackbase/TrkrHitSet.h>
0008 #include <trackbase/TrkrHitSetContainerv1.h>
0009 #include <trackbase/TrkrHitv2.h> // for TrkrHit
0010
0011 #include <g4detectors/PHG4TpcGeom.h>
0012 #include <g4detectors/PHG4TpcGeomContainer.h>
0013
0014 #include <g4tracking/TrkrTruthTrack.h>
0015 #include <g4tracking/TrkrTruthTrackContainer.h>
0016
0017
0018
0019 #include <algorithm>
0020 #include <cmath> // for sqrt, cos, sin
0021 #include <format>
0022 #include <ios>
0023 #include <iostream>
0024 #include <limits>
0025 #include <map> // for _Rb_tree_cons...
0026 #include <set>
0027
0028 namespace
0029 {
0030 template <class T>
0031 constexpr T square(const T& x)
0032 {
0033 return x * x;
0034 }
0035 }
0036
0037 void TpcClusterBuilder::cluster_hits(TrkrTruthTrack* track)
0038 {
0039
0040 TrkrHitSetContainer::ConstRange hitsetrange;
0041 hitsetrange = m_hits->getHitSets(TrkrDefs::TrkrId::tpcId);
0042
0043
0044
0045
0046
0047 for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first;
0048 hitsetitr != hitsetrange.second;
0049 ++hitsetitr)
0050 {
0051
0052 TrkrDefs::hitsetkey hitsetkey = hitsetitr->first;
0053 TrkrHitSet* hitset = hitsetitr->second;
0054 unsigned int layer = TrkrDefs::getLayer(hitsetitr->first);
0055 int side = TpcDefs::getSide(hitsetitr->first);
0056 unsigned int sector = TpcDefs::getSectorId(hitsetitr->first);
0057 PHG4TpcGeom* layergeom = geom_container->GetLayerCellGeom(layer);
0058
0059
0060 unsigned short NPhiBins = (unsigned short) layergeom->get_phibins();
0061 unsigned short NPhiBinsSector = NPhiBins / 12;
0062 unsigned short NTBins = (unsigned short) layergeom->get_zbins();
0063 unsigned short NTBinsSide = NTBins;
0064 unsigned short NTBinsMin = 0;
0065 unsigned short PhiOffset = NPhiBinsSector * sector;
0066 unsigned short TOffset = NTBinsMin;
0067 AdcClockPeriod = layergeom->get_zstep();
0068 double m_tdriftmax = AdcClockPeriod * NTBins / 2.0;
0069
0070 unsigned short phibins = NPhiBinsSector;
0071 unsigned short phioffset = PhiOffset;
0072 unsigned short tbins = NTBinsSide;
0073 unsigned short toffset = TOffset;
0074
0075
0076 double t_sum = 0.0;
0077 double adc_sum = 0.0;
0078
0079
0080 double iphi_sum = 0.0;
0081
0082
0083
0084 double radius = layergeom->get_radius();
0085
0086 int phibinhi = -1;
0087 int phibinlo = std::numeric_limits<int>::max();
0088 int tbinhi = -1;
0089 int tbinlo = std::numeric_limits<int>::max();
0090
0091 auto ihit_list = hitset->getHits();
0092
0093 const int iphi_max = phioffset + phibins;
0094 const int it_max = toffset + tbins;
0095
0096 double sum_adc{0.};
0097
0098
0099 for (auto iter = ihit_list.first; iter != ihit_list.second; ++iter)
0100 {
0101 int iphi = TpcDefs::getPad(iter->first);
0102 int it = TpcDefs::getTBin(iter->first);
0103 if (iphi < phioffset || iphi > iphi_max || it < toffset || it > it_max)
0104 {
0105 continue;
0106 }
0107 sum_adc += iter->second->getAdc();
0108 }
0109 const double threshold = sum_adc * m_pixel_thresholdrat;
0110
0111
0112 std::set<int> v_iphi;
0113 std::set<int> v_it;
0114 std::map<int, unsigned int> m_iphi;
0115 std::map<int, unsigned int> m_it;
0116 std::map<int, unsigned int> m_iphiCut;
0117 std::map<int, unsigned int> m_itCut;
0118 for (auto iter = ihit_list.first; iter != ihit_list.second; ++iter)
0119 {
0120 unsigned int adc = iter->second->getAdc();
0121 if (adc <= 0)
0122 {
0123 continue;
0124 }
0125 int iphi = TpcDefs::getPad(iter->first);
0126 int it = TpcDefs::getTBin(iter->first);
0127 if (iphi < phioffset || iphi > iphi_max)
0128 {
0129 std::cout << "WARNING phibin out of range: " << iphi << " | " << phibins << std::endl;
0130 continue;
0131 }
0132 if (it < toffset || it > it_max)
0133 {
0134 std::cout << "WARNING z bin out of range: " << it << " | " << tbins << std::endl;
0135 continue;
0136 }
0137 if (adc < threshold)
0138 {
0139 if (mClusHitsVerbose)
0140 {
0141 auto pnew = m_iphiCut.try_emplace(iphi, adc);
0142 if (!pnew.second)
0143 {
0144 pnew.first->second += adc;
0145 }
0146
0147 pnew = m_itCut.try_emplace(it, adc);
0148 if (!pnew.second)
0149 {
0150 pnew.first->second += adc;
0151 }
0152 }
0153 continue;
0154 }
0155
0156 v_iphi.insert(iphi);
0157 v_it.insert(it);
0158
0159
0160 auto pnew = m_iphi.try_emplace(iphi, adc);
0161 if (!pnew.second)
0162 {
0163 pnew.first->second += adc;
0164 }
0165 pnew = m_it.try_emplace(it, adc);
0166 if (!pnew.second)
0167 {
0168 pnew.first->second += adc;
0169 }
0170
0171 phibinhi = std::max(iphi, phibinhi);
0172 phibinlo = std::min(iphi, phibinlo);
0173 tbinhi = std::max(it, tbinhi);
0174 tbinlo = std::min(it, tbinlo);
0175
0176 iphi_sum += iphi * adc;
0177
0178
0179
0180 double t = layergeom->get_zcenter(it);
0181 t_sum += t * adc;
0182
0183
0184 adc_sum += adc;
0185 }
0186 if (mClusHitsVerbose)
0187 {
0188 if (verbosity > 10)
0189 {
0190 for (auto& hit : m_iphi)
0191 {
0192 std::cout << " m_phi(" << hit.first << " : " << hit.second << ") ";
0193 }
0194 }
0195
0196
0197
0198
0199
0200
0201 for (auto& hit : m_iphi)
0202 {
0203 mClusHitsVerbose->addPhiHit(hit.first, hit.second);
0204 }
0205 for (auto& hit : m_it)
0206 {
0207 mClusHitsVerbose->addZHit(hit.first, hit.second);
0208 }
0209 for (auto& hit : m_iphiCut)
0210 {
0211 mClusHitsVerbose->addPhiCutHit(hit.first, hit.second);
0212 }
0213 for (auto& hit : m_itCut)
0214 {
0215 mClusHitsVerbose->addZCutHit(hit.first, hit.second);
0216 }
0217 }
0218
0219
0220 double clusiphi = iphi_sum / adc_sum;
0221 double clusphi = layergeom->get_phi(clusiphi, side);
0222
0223 float clusx = radius * cos(clusphi);
0224 float clusy = radius * sin(clusphi);
0225 double clust = t_sum / adc_sum;
0226 double zdriftlength = clust * m_tGeometry->get_drift_velocity();
0227
0228 double clusz = m_tdriftmax * m_tGeometry->get_drift_velocity() - zdriftlength;
0229 if (side == 0)
0230 {
0231 clusz = -clusz;
0232 }
0233
0234 char tsize = tbinhi - tbinlo + 1;
0235 char phisize = phibinhi - phibinlo + 1;
0236
0237 if (tsize < 0 && verbosity > 1)
0238 {
0239 std::cout << " FIXME z4 tsize: " << ((int) tsize) << " " << tbinlo << " to " << tbinhi << std::endl;
0240 }
0241
0242
0243
0244
0245
0246
0247
0248 if (false)
0249 {
0250 if ((int) phisize > 10 || (int) tsize > 8)
0251 {
0252 int _size_phi = ((int) phisize);
0253 int _nbins_phi = v_iphi.size();
0254 int _delta_phi = abs(_size_phi - _nbins_phi);
0255 int _size_z = ((int) tsize);
0256 int _nbins_z = v_it.size();
0257 int _delta_z = abs(_size_z - _nbins_z);
0258
0259
0260 std::cout << " x|" << _delta_phi << "|" << _delta_z
0261 << "| new node FIXME A1 layer(" << layer
0262 << ") (nset:size) phi("
0263 << _nbins_phi << ":" << _size_phi << ") z("
0264 << _nbins_z << ":" << _size_z << ") "
0265 << "trkId(" << track->getTrackid() << ") trkpT(" << track->getPt() << ")"
0266 << std::endl;
0267 if (phisize > 10)
0268 {
0269 std::cout << " iphi-from-(";
0270 int _prev = -1;
0271 double tempsum = 0.;
0272 for (auto _ : v_iphi)
0273 {
0274 if (_prev == -1)
0275 {
0276 std::cout << _ << "): ";
0277 }
0278 else
0279 {
0280 int _diff = ((int) _ - _prev - 1);
0281 if (_diff != 0)
0282 {
0283 std::cout << ">" << _diff << ">";
0284 }
0285 }
0286
0287 double _rat = (float) m_iphi[_] / (float) adc_sum;
0288 std::cout << std::format("{:.2f}", _rat) << " ";
0289 tempsum += _rat;
0290 _prev = _;
0291 }
0292 if (tempsum < 0.999)
0293 {
0294 std::cout << " Z3 sumphirat: " << tempsum;
0295 }
0296 std::cout << std::endl;
0297 }
0298 if (tsize > 8)
0299 {
0300 int _prev = -1;
0301 double tempsum = 0.;
0302 std::cout << " iz-from-(";
0303 for (auto _ : v_it)
0304 {
0305 if (_prev == -1)
0306 {
0307 std::cout << _ << "): ";
0308 }
0309 else
0310 {
0311 int _diff = ((int) _ - _prev - 1);
0312 if (_diff != 0)
0313 {
0314 std::cout << ">" << _diff << ">";
0315 }
0316 }
0317
0318 double _rat = (float) m_it[_] / (float) adc_sum;
0319 std::cout << std::format("{:.2f}", _rat) << " ";
0320 tempsum += _rat;
0321 _prev = _;
0322 }
0323 if (tempsum < 0.999)
0324 {
0325 std::cout << " Z3 sumzrat: " << tempsum;
0326 }
0327 }
0328 std::cout << std::endl;
0329 }
0330 }
0331
0332
0333 Acts::Vector3 global(clusx, clusy, clusz);
0334 TrkrDefs::subsurfkey subsurfkey = 0;
0335
0336 Surface surface = m_tGeometry->get_tpc_surface_from_coords(
0337 hitsetkey, global, subsurfkey);
0338
0339 if (!surface)
0340 {
0341 if (verbosity)
0342 {
0343 std::cout << "Can't find the surface! with hitsetkey " << ((int) hitsetkey) << std::endl;
0344 }
0345
0346 continue;
0347 }
0348
0349
0350 clust = clust + m_sampa_tbias;
0351
0352 global *= Acts::UnitConstants::cm;
0353
0354 Acts::Vector3 local = surface->transform(m_tGeometry->geometry().getGeoContext()).inverse() * global;
0355 local /= Acts::UnitConstants::cm;
0356
0357 auto* cluster = new TrkrClusterv4;
0358 cluster->setAdc(adc_sum);
0359
0360
0361 cluster->setPhiSize(phisize);
0362 cluster->setZSize(tsize);
0363 cluster->setSubSurfKey(subsurfkey);
0364 cluster->setLocalX(local(0));
0365 cluster->setLocalY(clust);
0366
0367
0368 auto empl = hitsetkey_cnt.try_emplace(hitsetkey, 0);
0369 if (!empl.second)
0370 {
0371 empl.first->second += 1;
0372 }
0373 TrkrDefs::cluskey cluskey = TrkrDefs::genClusKey(hitsetkey, hitsetkey_cnt[hitsetkey]);
0374 m_clusterlist->addClusterSpecifyKey(cluskey, cluster);
0375
0376 track->addCluster(cluskey);
0377 if (mClusHitsVerbose)
0378 {
0379 mClusHitsVerbose->push_hits(cluskey);
0380
0381 }
0382 }
0383 m_hits->Reset();
0384 }
0385
0386
0387
0388
0389
0390
0391 void TpcClusterBuilder::addhitset(
0392 TrkrDefs::hitsetkey hitsetkey,
0393 TrkrDefs::hitkey hitkey,
0394 float neffelectrons)
0395 {
0396
0397
0398 if (!b_collect_hits)
0399 {
0400 return;
0401 }
0402
0403
0404
0405 TrkrHitSetContainer::Iterator hitsetit = m_hits->findOrAddHitSet(hitsetkey);
0406
0407 TrkrHit* hit = nullptr;
0408 hit = hitsetit->second->getHit(hitkey);
0409 if (!hit)
0410 {
0411
0412 hit = new TrkrHitv2();
0413 hitsetit->second->addHitSpecificKey(hitkey, hit);
0414 }
0415
0416 hit->addEnergy(neffelectrons);
0417 }
0418
0419 void TpcClusterBuilder::clear_hitsetkey_cnt()
0420 {
0421 hitsetkey_cnt.clear();
0422 }
0423
0424 void TpcClusterBuilder::print(TrkrTruthTrackContainer* truth_tracks, int nclusprint) const
0425 {
0426 std::cout << " ------------- content of TrkrTruthTrackContainer ---------- " << std::endl;
0427 auto& tmap = truth_tracks->getMap();
0428 std::cout << " Number of tracks: xyz db : " << tmap.size() << std::endl;
0429 for (auto& _pair : tmap)
0430 {
0431 auto& track = _pair.second;
0432 std::cout << std::format("id({:2d}) phi:eta:pt(", static_cast<int>(track->getTrackid()))
0433 << std::format("{:5.2f}:{:5.2f}:{:5.2f}", track->getPhi(), track->getPseudoRapidity(), track->getPt())
0434 << ") nclusters(" << track->getClusters().size() << ") ";
0435 if (verbosity <= 10)
0436 {
0437 std::cout << std::endl;
0438 }
0439 else
0440 {
0441 int nclus = 0;
0442 for (auto cluskey : track->getClusters())
0443 {
0444 std::cout << " "
0445 << ((int) TrkrDefs::getHitSetKeyFromClusKey(cluskey)) << ":index(" << ((int) TrkrDefs::getClusIndex(cluskey)) << ")";
0446 ++nclus;
0447 if (nclusprint > 0 && nclus >= nclusprint)
0448 {
0449 std::cout << " ... ";
0450 break;
0451 }
0452 }
0453 }
0454 }
0455 std::cout << " ----- end of tracks in TrkrrTruthTrackContainer ------ " << std::endl;
0456 }
0457
0458 void TpcClusterBuilder::print_file(
0459 TrkrTruthTrackContainer* truth_tracks, const std::string& ofile_name)
0460 {
0461 std::ofstream fout;
0462 fout.open(ofile_name.c_str());
0463 fout << " ------------- content of TrkrTruthTrackContainer ---------- " << std::endl;
0464 auto& tmap = truth_tracks->getMap();
0465 fout << " Number of tracks: " << tmap.size() << std::endl;
0466 for (auto& _pair : tmap)
0467 {
0468 auto& track = _pair.second;
0469 fout << " id( " << track->getTrackid() << ") phi:eta:pt(" << track->getPhi() << ":" << track->getPseudoRapidity() << ":" << track->getPt() << ") nclusters("
0470 << track->getClusters().size() << ") ";
0471
0472 for (auto cluskey : track->getClusters())
0473 {
0474 auto* C = m_clusterlist->findCluster(cluskey);
0475 fout << " "
0476 << ((int) TrkrDefs::getHitSetKeyFromClusKey(cluskey)) << ":" << ((int) TrkrDefs::getClusIndex(cluskey)) << "->adc:X:phisize:Y:zsize("
0477 << C->getAdc() << ":"
0478 << C->getLocalX() << ":"
0479 << C->getPhiSize() << ":"
0480 << C->getLocalY() << ":"
0481 << C->getZSize() << ") ";
0482
0483 }
0484 fout << std::endl;
0485 }
0486 fout << " ----- end of tracks in TrkrrTruthTrackContainer ------ " << std::endl;
0487 fout.close();
0488 }
0489
0490 void TpcClusterBuilder::set_input_nodes(
0491 TrkrClusterContainer* _truth_cluster_container, ActsGeometry* ActsGeometry, PHG4TpcGeomContainer* _geom_container, ClusHitsVerbosev1* _clushitsverbose)
0492 {
0493 m_clusterlist = _truth_cluster_container;
0494 m_tGeometry = ActsGeometry;
0495 geom_container = _geom_container;
0496 mClusHitsVerbose = _clushitsverbose;
0497 m_needs_input_nodes = false;
0498 };