File indexing completed on 2025-08-06 08:17:54
0001
0002
0003
0004
0005
0006
0007 #include "MvtxClusterizer.h"
0008 #include "CylinderGeom_Mvtx.h"
0009
0010 #include <g4detectors/PHG4CylinderGeom.h>
0011 #include <g4detectors/PHG4CylinderGeomContainer.h>
0012
0013 #include <trackbase/ClusHitsVerbosev1.h>
0014 #include <trackbase/MvtxDefs.h>
0015 #include <trackbase/TrkrClusterContainerv4.h>
0016 #include <trackbase/TrkrClusterHitAssocv3.h>
0017 #include <trackbase/TrkrClusterv3.h>
0018 #include <trackbase/TrkrClusterv4.h>
0019 #include <trackbase/TrkrClusterv5.h>
0020 #include <trackbase/TrkrDefs.h> // for hitkey, getLayer
0021 #include <trackbase/TrkrHitSet.h>
0022 #include <trackbase/TrkrHitSetContainer.h>
0023 #include <trackbase/TrkrHitv2.h>
0024
0025 #include <trackbase/RawHit.h>
0026 #include <trackbase/RawHitSet.h>
0027 #include <trackbase/RawHitSetContainer.h>
0028
0029 #include <fun4all/Fun4AllReturnCodes.h>
0030 #include <fun4all/SubsysReco.h> // for SubsysReco
0031
0032 #include <phool/PHCompositeNode.h>
0033 #include <phool/PHIODataNode.h>
0034 #include <phool/PHNode.h> // for PHNode
0035 #include <phool/PHNodeIterator.h>
0036 #include <phool/PHObject.h> // for PHObject
0037 #include <phool/getClass.h>
0038 #include <phool/phool.h> // for PHWHERE
0039
0040 #include <TMatrixFfwd.h> // for TMatrixF
0041 #include <TMatrixT.h> // for TMatrixT, operator*
0042 #include <TMatrixTUtils.h> // for TMatrixTRow
0043 #include <TVector3.h>
0044
0045 #pragma GCC diagnostic push
0046 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0047 #include <boost/graph/adjacency_list.hpp>
0048 #pragma GCC diagnostic pop
0049
0050 #include <boost/graph/connected_components.hpp>
0051
0052 #include <array>
0053 #include <cmath>
0054 #include <cstdlib> // for exit
0055 #include <iostream>
0056 #include <map> // for multimap<>::iterator
0057 #include <set> // for set, set<>::iterator
0058 #include <string>
0059 #include <vector> // for vector
0060
0061 namespace
0062 {
0063
0064
0065 template <class T>
0066 inline constexpr T square(const T &x)
0067 {
0068 return x * x;
0069 }
0070 }
0071
0072 bool MvtxClusterizer::are_adjacent(
0073 const std::pair<TrkrDefs::hitkey, TrkrHit *> &lhs,
0074 const std::pair<TrkrDefs::hitkey, TrkrHit *> &rhs)
0075 {
0076 if (GetZClustering())
0077 {
0078 return
0079
0080
0081 ( (MvtxDefs::getCol(lhs.first) > MvtxDefs::getCol(rhs.first)) ?
0082 MvtxDefs::getCol(lhs.first)<=MvtxDefs::getCol(rhs.first)+1:
0083 MvtxDefs::getCol(rhs.first)<=MvtxDefs::getCol(lhs.first)+1) &&
0084
0085
0086 ( (MvtxDefs::getRow(lhs.first) > MvtxDefs::getRow(rhs.first)) ?
0087 MvtxDefs::getRow(lhs.first)<=MvtxDefs::getRow(rhs.first)+1:
0088 MvtxDefs::getRow(rhs.first)<=MvtxDefs::getRow(lhs.first)+1);
0089
0090 } else {
0091
0092 return
0093
0094 MvtxDefs::getCol(rhs.first)==MvtxDefs::getCol(lhs.first) &&
0095
0096
0097 ( (MvtxDefs::getRow(lhs.first) > MvtxDefs::getRow(rhs.first)) ?
0098 MvtxDefs::getRow(lhs.first)<=MvtxDefs::getRow(rhs.first)+1:
0099 MvtxDefs::getRow(rhs.first)<=MvtxDefs::getRow(lhs.first)+1);
0100
0101 }
0102 }
0103
0104 bool MvtxClusterizer::are_adjacent(RawHit *lhs, RawHit *rhs)
0105 {
0106 if (GetZClustering())
0107 {
0108 return
0109
0110
0111 ((lhs->getPhiBin() > rhs->getPhiBin()) ?
0112 lhs->getPhiBin() <= rhs->getPhiBin()+1:
0113 rhs->getPhiBin() <= lhs->getPhiBin()+1) &&
0114
0115
0116 ((lhs->getTBin() > rhs->getTBin()) ?
0117 lhs->getTBin() <= rhs->getTBin()+1:
0118 rhs->getTBin() <= lhs->getTBin()+1);
0119
0120 } else {
0121
0122 return
0123
0124
0125 lhs->getPhiBin() == rhs->getPhiBin() &&
0126
0127
0128 ((lhs->getTBin() > rhs->getTBin()) ?
0129 lhs->getTBin() <= rhs->getTBin()+1:
0130 rhs->getTBin() <= lhs->getTBin()+1);
0131
0132 }
0133 }
0134
0135 MvtxClusterizer::MvtxClusterizer(const std::string &name)
0136 : SubsysReco(name)
0137 {
0138 }
0139
0140 int MvtxClusterizer::InitRun(PHCompositeNode *topNode)
0141 {
0142
0143
0144
0145
0146 PHNodeIterator iter(topNode);
0147
0148
0149 PHCompositeNode *dstNode =
0150 dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0151 if (!dstNode)
0152 {
0153 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
0154 return Fun4AllReturnCodes::ABORTRUN;
0155 }
0156 PHNodeIterator iter_dst(dstNode);
0157
0158
0159 PHCompositeNode *svxNode = dynamic_cast<PHCompositeNode *>(
0160 iter_dst.findFirst("PHCompositeNode", "TRKR"));
0161 if (!svxNode)
0162 {
0163 svxNode = new PHCompositeNode("TRKR");
0164 dstNode->addNode(svxNode);
0165 }
0166
0167
0168 auto trkrclusters =
0169 findNode::getClass<TrkrClusterContainer>(dstNode, "TRKR_CLUSTER");
0170 if (!trkrclusters)
0171 {
0172 PHNodeIterator dstiter(dstNode);
0173 PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0174 if (!DetNode)
0175 {
0176 DetNode = new PHCompositeNode("TRKR");
0177 dstNode->addNode(DetNode);
0178 }
0179
0180 trkrclusters = new TrkrClusterContainerv4;
0181 PHIODataNode<PHObject> *TrkrClusterContainerNode =
0182 new PHIODataNode<PHObject>(trkrclusters, "TRKR_CLUSTER", "PHObject");
0183 DetNode->addNode(TrkrClusterContainerNode);
0184 }
0185
0186 auto clusterhitassoc =
0187 findNode::getClass<TrkrClusterHitAssoc>(topNode, "TRKR_CLUSTERHITASSOC");
0188 if (!clusterhitassoc)
0189 {
0190 PHNodeIterator dstiter(dstNode);
0191 PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0192 if (!DetNode)
0193 {
0194 DetNode = new PHCompositeNode("TRKR");
0195 dstNode->addNode(DetNode);
0196 }
0197
0198 clusterhitassoc = new TrkrClusterHitAssocv3;
0199 PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(clusterhitassoc, "TRKR_CLUSTERHITASSOC", "PHObject");
0200 DetNode->addNode(newNode);
0201 }
0202
0203
0204 if (record_ClusHitsVerbose)
0205 {
0206
0207 mClusHitsVerbose = findNode::getClass<ClusHitsVerbose>(topNode, "Trkr_SvtxClusHitsVerbose");
0208 if (!mClusHitsVerbose)
0209 {
0210 PHNodeIterator dstiter(dstNode);
0211 auto DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0212 if (!DetNode)
0213 {
0214 DetNode = new PHCompositeNode("TRKR");
0215 dstNode->addNode(DetNode);
0216 }
0217 mClusHitsVerbose = new ClusHitsVerbosev1();
0218 auto newNode = new PHIODataNode<PHObject>(mClusHitsVerbose, "Trkr_SvtxClusHitsVerbose", "PHObject");
0219 DetNode->addNode(newNode);
0220 }
0221 }
0222
0223
0224
0225
0226
0227 if (Verbosity() > 0)
0228 {
0229 std::cout << "====================== MvtxClusterizer::InitRun() "
0230 "====================="
0231 << std::endl;
0232 std::cout << " Z-dimension Clustering = " << std::boolalpha << m_makeZClustering
0233 << std::noboolalpha << std::endl;
0234 std::cout << "=================================================================="
0235 "========="
0236 << std::endl;
0237 }
0238
0239 return Fun4AllReturnCodes::EVENT_OK;
0240 }
0241
0242 int MvtxClusterizer::process_event(PHCompositeNode *topNode)
0243 {
0244
0245 if (!do_read_raw)
0246 {
0247 m_hits = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
0248 if (!m_hits)
0249 {
0250 std::cout << PHWHERE << "ERROR: Can't find node TRKR_HITSET" << std::endl;
0251 return Fun4AllReturnCodes::ABORTRUN;
0252 }
0253 }
0254 else
0255 {
0256
0257 m_rawhits =
0258 findNode::getClass<RawHitSetContainer>(topNode, "TRKR_RAWHITSET");
0259 if (!m_rawhits)
0260 {
0261 std::cout << PHWHERE << "ERROR: Can't find node TRKR_HITSET" << std::endl;
0262 return Fun4AllReturnCodes::ABORTRUN;
0263 }
0264 }
0265
0266
0267 m_clusterlist =
0268 findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
0269 if (!m_clusterlist)
0270 {
0271 std::cout << PHWHERE << " ERROR: Can't find TRKR_CLUSTER." << std::endl;
0272 return Fun4AllReturnCodes::ABORTRUN;
0273 }
0274
0275
0276 m_clusterhitassoc =
0277 findNode::getClass<TrkrClusterHitAssoc>(topNode, "TRKR_CLUSTERHITASSOC");
0278 if (!m_clusterhitassoc)
0279 {
0280 std::cout << PHWHERE << " ERROR: Can't find TRKR_CLUSTERHITASSOC" << std::endl;
0281 return Fun4AllReturnCodes::ABORTRUN;
0282 }
0283
0284
0285 const auto hitsetkeys = m_clusterlist->getHitSetKeys(TrkrDefs::mvtxId);
0286 for( const auto& hitsetkey:hitsetkeys)
0287 {
0288 m_clusterlist->removeClusters(hitsetkey);
0289 m_clusterhitassoc->removeAssocs(hitsetkey);
0290 }
0291
0292
0293 if (!do_read_raw)
0294 {
0295 ClusterMvtx(topNode);
0296 }
0297 else
0298 {
0299 ClusterMvtxRaw(topNode);
0300 }
0301 PrintClusters(topNode);
0302
0303
0304 return Fun4AllReturnCodes::EVENT_OK;
0305 }
0306
0307 void MvtxClusterizer::ClusterMvtx(PHCompositeNode *topNode)
0308 {
0309 if (Verbosity() > 0)
0310 {
0311 std::cout << "Entering MvtxClusterizer::ClusterMvtx " << std::endl;
0312 }
0313
0314 PHG4CylinderGeomContainer *geom_container =
0315 findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
0316 if (!geom_container)
0317 {
0318 return;
0319 }
0320
0321
0322
0323
0324
0325
0326 TrkrHitSetContainer::ConstRange hitsetrange =
0327 m_hits->getHitSets(TrkrDefs::TrkrId::mvtxId);
0328 for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first;
0329 hitsetitr != hitsetrange.second; ++hitsetitr)
0330 {
0331 TrkrHitSet *hitset = hitsetitr->second;
0332
0333 if (Verbosity() > 0)
0334 {
0335 unsigned int layer = TrkrDefs::getLayer(hitsetitr->first);
0336 unsigned int stave = MvtxDefs::getStaveId(hitsetitr->first);
0337 unsigned int chip = MvtxDefs::getChipId(hitsetitr->first);
0338 unsigned int strobe = MvtxDefs::getStrobeId(hitsetitr->first);
0339 std::cout << "MvtxClusterizer found hitsetkey " << hitsetitr->first
0340 << " layer " << layer << " stave " << stave << " chip " << chip
0341 << " strobe " << strobe << std::endl;
0342 }
0343
0344 if (Verbosity() > 2)
0345 {
0346 hitset->identify();
0347 }
0348
0349
0350 std::vector<std::pair<TrkrDefs::hitkey, TrkrHit *> > hitvec;
0351
0352 TrkrHitSet::ConstRange hitrangei = hitset->getHits();
0353 for (TrkrHitSet::ConstIterator hitr = hitrangei.first;
0354 hitr != hitrangei.second; ++hitr)
0355 {
0356 hitvec.emplace_back(hitr->first, hitr->second);
0357 }
0358 if (Verbosity() > 2)
0359 {
0360 std::cout << "hitvec.size(): " << hitvec.size() << std::endl;
0361 }
0362
0363 if (Verbosity() > 0)
0364 {
0365 for (auto &hit : hitvec)
0366 {
0367 auto hitkey = hit.first;
0368 auto row = MvtxDefs::getRow(hitkey);
0369 auto col = MvtxDefs::getCol(hitkey);
0370 std::cout << " hitkey " << hitkey << " row " << row << " col "
0371 << col << std::endl;
0372 }
0373 }
0374
0375
0376 using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
0377 Graph G;
0378
0379
0380 for (unsigned int i = 0; i < hitvec.size(); i++)
0381 {
0382 for (unsigned int j = 0; j < hitvec.size(); j++)
0383 {
0384 if (are_adjacent(hitvec[i], hitvec[j]))
0385 {
0386 add_edge(i, j, G);
0387 }
0388 }
0389 }
0390
0391
0392
0393
0394 std::vector<int> component(num_vertices(G));
0395
0396
0397 boost::connected_components(G, &component[0]);
0398
0399
0400
0401 std::set<int> cluster_ids;
0402 std::multimap<int, std::pair<TrkrDefs::hitkey, TrkrHit *> > clusters;
0403 for (unsigned int i = 0; i < component.size(); i++)
0404 {
0405 cluster_ids.insert(component[i]);
0406 clusters.insert(make_pair(component[i], hitvec[i]));
0407 }
0408 for (const auto& clusid:cluster_ids)
0409 {
0410 auto clusrange = clusters.equal_range(clusid);
0411 auto ckey = TrkrDefs::genClusKey(hitset->getHitSetKey(), clusid);
0412
0413
0414 std::set<int> phibins;
0415 std::set<int> zbins;
0416 std::map<int, unsigned int> m_phi, m_z;
0417
0418
0419 double locxsum = 0.;
0420 double loczsum = 0.;
0421 const unsigned int nhits =
0422 std::distance(clusrange.first, clusrange.second);
0423
0424 double locclusx = std::numeric_limits<double>::quiet_NaN();
0425 double locclusz = std::numeric_limits<double>::quiet_NaN();
0426
0427
0428 int layer = TrkrDefs::getLayer(ckey);
0429 auto layergeom = dynamic_cast<CylinderGeom_Mvtx *>(geom_container->GetLayerGeom(layer));
0430 if (!layergeom)
0431 {
0432 exit(1);
0433 }
0434
0435 for (auto mapiter = clusrange.first; mapiter != clusrange.second;
0436 ++mapiter)
0437 {
0438
0439 const auto energy = (mapiter->second).second->getAdc();
0440 int col = MvtxDefs::getCol((mapiter->second).first);
0441 int row = MvtxDefs::getRow((mapiter->second).first);
0442 zbins.insert(col);
0443 phibins.insert(row);
0444
0445 if (mClusHitsVerbose)
0446 {
0447 auto pnew = m_phi.try_emplace(row, energy);
0448 if (!pnew.second)
0449 {
0450 pnew.first->second += energy;
0451 }
0452
0453 pnew = m_z.try_emplace(col, energy);
0454 if (!pnew.second)
0455 {
0456 pnew.first->second += energy;
0457 }
0458 }
0459
0460
0461 auto local_coords = layergeom->get_local_coords_from_pixel(row, col);
0462
0463
0464
0465
0466
0467
0468
0469 local_coords.SetY(1e-4);
0470
0471
0472 locxsum += local_coords.X();
0473 loczsum += local_coords.Z();
0474
0475
0476 m_clusterhitassoc->addAssoc(ckey, mapiter->second.first);
0477
0478 }
0479
0480 if (mClusHitsVerbose)
0481 {
0482 if (Verbosity() > 10)
0483 {
0484 for (auto &hit : m_phi)
0485 {
0486 std::cout << " m_phi(" << hit.first << " : " << hit.second << ") "
0487 << std::endl;
0488 }
0489 }
0490 for (auto &hit : m_phi)
0491 {
0492 mClusHitsVerbose->addPhiHit(hit.first, (float) hit.second);
0493 }
0494 for (auto &hit : m_z)
0495 {
0496 mClusHitsVerbose->addZHit(hit.first, (float) hit.second);
0497 }
0498 mClusHitsVerbose->push_hits(ckey);
0499 }
0500
0501
0502 locclusx = locxsum / nhits;
0503 locclusz = loczsum / nhits;
0504
0505 const double pitch = layergeom->get_pixel_x();
0506 const double length = layergeom->get_pixel_z();
0507 const double phisize = phibins.size() * pitch;
0508 const double zsize = zbins.size() * length;
0509
0510 static const double invsqrt12 = 1. / std::sqrt(12);
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522 double phierror = pitch * invsqrt12;
0523
0524 static constexpr std::array<double, 7> scalefactors_phi = {
0525 {0.36, 0.6, 0.37, 0.49, 0.4, 0.37, 0.33}};
0526
0527 if ((phibins.size() == 1 && zbins.size() == 1) ||
0528 (phibins.size() == 2 && zbins.size() == 2))
0529 {
0530 phierror *= scalefactors_phi[0];
0531 }
0532 else if ((phibins.size() == 2 && zbins.size() == 1) ||
0533 (phibins.size() == 2 && zbins.size() == 3))
0534 {
0535 phierror *= scalefactors_phi[1];
0536 }
0537 else if ((phibins.size() == 1 && zbins.size() == 2) ||
0538 (phibins.size() == 3 && zbins.size() == 2))
0539 {
0540 phierror *= scalefactors_phi[2];
0541 }
0542 else if (phibins.size() == 3 && zbins.size() == 3)
0543 {
0544 phierror *= scalefactors_phi[3];
0545 }
0546
0547
0548
0549
0550
0551
0552
0553
0554 static constexpr std::array<double, 4> scalefactors_z = {
0555 {0.47, 0.48, 0.71, 0.55}};
0556 double zerror = length * invsqrt12;
0557 if (zbins.size() == 2 && phibins.size() == 2)
0558 {
0559 zerror *= scalefactors_z[0];
0560 }
0561 else if (zbins.size() == 2 && phibins.size() == 3)
0562 {
0563 zerror *= scalefactors_z[1];
0564 }
0565 else if (zbins.size() == 3 && phibins.size() == 2)
0566 {
0567 zerror *= scalefactors_z[2];
0568 }
0569 else if (zbins.size() == 3 && phibins.size() == 3)
0570 {
0571 zerror *= scalefactors_z[3];
0572 }
0573
0574 if (Verbosity() > 0)
0575 {
0576 std::cout << " MvtxClusterizer: cluskey " << ckey << " layer " << layer
0577 << " rad " << layergeom->get_radius() << " phibins "
0578 << phibins.size() << " pitch " << pitch << " phisize " << phisize
0579 << " zbins " << zbins.size() << " length " << length << " zsize "
0580 << zsize << " local x " << locclusx << " local y " << locclusz
0581 << std::endl;
0582 }
0583
0584 auto clus = std::make_unique<TrkrClusterv5>();
0585 clus->setAdc(nhits);
0586 clus->setMaxAdc(1);
0587 clus->setLocalX(locclusx);
0588 clus->setLocalY(locclusz);
0589 clus->setPhiError(phierror);
0590 clus->setZError(zerror);
0591 clus->setPhiSize(phibins.size());
0592 clus->setZSize(zbins.size());
0593
0594
0595 clus->setSubSurfKey(0);
0596
0597 if (Verbosity() > 2)
0598 {
0599 clus->identify();
0600 }
0601
0602 if (zbins.size() <= 127)
0603 {
0604 m_clusterlist->addClusterSpecifyKey(ckey, clus.release());
0605 }
0606
0607 }
0608 }
0609
0610 if (Verbosity() > 1)
0611 {
0612
0613 m_clusterhitassoc->identify();
0614 }
0615
0616 return;
0617 }
0618
0619 void MvtxClusterizer::ClusterMvtxRaw(PHCompositeNode *topNode)
0620 {
0621 if (Verbosity() > 0)
0622 {
0623 std::cout << "Entering MvtxClusterizer::ClusterMvtx " << std::endl;
0624 }
0625
0626 PHG4CylinderGeomContainer *geom_container =
0627 findNode::getClass<PHG4CylinderGeomContainer>(topNode,
0628 "CYLINDERGEOM_MVTX");
0629 if (!geom_container)
0630 {
0631 return;
0632 }
0633
0634
0635
0636
0637
0638
0639 RawHitSetContainer::ConstRange hitsetrange =
0640 m_rawhits->getHitSets(TrkrDefs::TrkrId::mvtxId);
0641 for (RawHitSetContainer::ConstIterator hitsetitr = hitsetrange.first;
0642 hitsetitr != hitsetrange.second; ++hitsetitr)
0643 {
0644 RawHitSet *hitset = hitsetitr->second;
0645
0646 if (Verbosity() > 0)
0647 {
0648 unsigned int layer = TrkrDefs::getLayer(hitsetitr->first);
0649 unsigned int stave = MvtxDefs::getStaveId(hitsetitr->first);
0650 unsigned int chip = MvtxDefs::getChipId(hitsetitr->first);
0651 unsigned int strobe = MvtxDefs::getStrobeId(hitsetitr->first);
0652 std::cout << "MvtxClusterizer found hitsetkey " << hitsetitr->first
0653 << " layer " << layer << " stave " << stave << " chip " << chip
0654 << " strobe " << strobe << std::endl;
0655 }
0656
0657 if (Verbosity() > 2)
0658 {
0659 hitset->identify();
0660 }
0661
0662
0663 std::vector<RawHit *> hitvec;
0664
0665 RawHitSet::ConstRange hitrangei = hitset->getHits();
0666 for (RawHitSet::ConstIterator hitr = hitrangei.first;
0667 hitr != hitrangei.second; ++hitr)
0668 {
0669 hitvec.push_back((*hitr));
0670 }
0671 if (Verbosity() > 2)
0672 {
0673 std::cout << "hitvec.size(): " << hitvec.size() << std::endl;
0674 }
0675
0676
0677 using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
0678 Graph G;
0679
0680
0681 for (unsigned int i = 0; i < hitvec.size(); i++)
0682 {
0683 for (unsigned int j = 0; j < hitvec.size(); j++)
0684 {
0685 if (are_adjacent(hitvec[i], hitvec[j]))
0686 {
0687 add_edge(i, j, G);
0688 }
0689 }
0690 }
0691
0692
0693
0694
0695 std::vector<int> component(num_vertices(G));
0696
0697
0698 boost::connected_components(G, &component[0]);
0699
0700
0701
0702 std::set<int> cluster_ids;
0703
0704 std::multimap<int, RawHit *> clusters;
0705 for (unsigned int i = 0; i < component.size(); i++)
0706 {
0707 cluster_ids.insert(component[i]);
0708 clusters.emplace(component[i], hitvec[i]);
0709 }
0710
0711
0712 for( const auto& clusid:cluster_ids)
0713 {
0714 auto clusrange = clusters.equal_range(clusid);
0715
0716
0717 auto ckey = TrkrDefs::genClusKey(hitset->getHitSetKey(), clusid);
0718
0719
0720 std::set<int> phibins;
0721 std::set<int> zbins;
0722
0723
0724 double locxsum = 0.;
0725 double loczsum = 0.;
0726 const unsigned int nhits =
0727 std::distance(clusrange.first, clusrange.second);
0728
0729 double locclusx = NAN;
0730 double locclusz = NAN;
0731
0732
0733 int layer = TrkrDefs::getLayer(ckey);
0734 auto layergeom = dynamic_cast<CylinderGeom_Mvtx *>(
0735 geom_container->GetLayerGeom(layer));
0736 if (!layergeom)
0737 {
0738 exit(1);
0739 }
0740
0741 for (auto mapiter = clusrange.first; mapiter != clusrange.second;
0742 ++mapiter)
0743 {
0744
0745 int col = (mapiter->second)->getPhiBin();
0746 int row = (mapiter->second)->getTBin();
0747 zbins.insert(col);
0748 phibins.insert(row);
0749
0750
0751 auto local_coords = layergeom->get_local_coords_from_pixel(row, col);
0752
0753
0754
0755
0756
0757
0758
0759 local_coords.SetY(1e-4);
0760
0761
0762 locxsum += local_coords.X();
0763 loczsum += local_coords.Z();
0764
0765
0766
0767
0768 }
0769
0770
0771 locclusx = locxsum / nhits;
0772 locclusz = loczsum / nhits;
0773
0774 const double pitch = layergeom->get_pixel_x();
0775
0776 const double length = layergeom->get_pixel_z();
0777
0778 const double phisize = phibins.size() * pitch;
0779 const double zsize = zbins.size() * length;
0780
0781 static const double invsqrt12 = 1. / std::sqrt(12);
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793 double phierror = pitch * invsqrt12;
0794
0795 static constexpr std::array<double, 7> scalefactors_phi = {
0796 {0.36, 0.6, 0.37, 0.49, 0.4, 0.37, 0.33}};
0797 if ((phibins.size() == 1 && zbins.size() == 1) ||
0798 (phibins.size() == 2 && zbins.size() == 2))
0799 {
0800 phierror *= scalefactors_phi[0];
0801 }
0802 else if ((phibins.size() == 2 && zbins.size() == 1) ||
0803 (phibins.size() == 2 && zbins.size() == 3))
0804 {
0805 phierror *= scalefactors_phi[1];
0806 }
0807 else if ((phibins.size() == 1 && zbins.size() == 2) ||
0808 (phibins.size() == 3 && zbins.size() == 2))
0809 {
0810 phierror *= scalefactors_phi[2];
0811 }
0812 else if (phibins.size() == 3 && zbins.size() == 3)
0813 {
0814 phierror *= scalefactors_phi[3];
0815 }
0816
0817
0818
0819
0820
0821
0822
0823
0824 static constexpr std::array<double, 4> scalefactors_z = {
0825 {0.47, 0.48, 0.71, 0.55}};
0826 double zerror = length * invsqrt12;
0827
0828 if (zbins.size() == 2 && phibins.size() == 2)
0829 {
0830 zerror *= scalefactors_z[0];
0831 }
0832 else if (zbins.size() == 2 && phibins.size() == 3)
0833 {
0834 zerror *= scalefactors_z[1];
0835 }
0836 else if (zbins.size() == 3 && phibins.size() == 2)
0837 {
0838 zerror *= scalefactors_z[2];
0839 }
0840 else if (zbins.size() == 3 && phibins.size() == 3)
0841 {
0842 zerror *= scalefactors_z[3];
0843 }
0844
0845 if (Verbosity() > 0)
0846 {
0847 std::cout << " MvtxClusterizer: cluskey " << ckey << " layer " << layer
0848 << " rad " << layergeom->get_radius() << " phibins "
0849 << phibins.size() << " pitch " << pitch << " phisize " << phisize
0850 << " zbins " << zbins.size() << " length " << length << " zsize "
0851 << zsize << " local x " << locclusx << " local y " << locclusz
0852 << std::endl;
0853 }
0854
0855 auto clus = std::make_unique<TrkrClusterv5>();
0856 clus->setAdc(nhits);
0857 clus->setMaxAdc(1);
0858 clus->setLocalX(locclusx);
0859 clus->setLocalY(locclusz);
0860 clus->setPhiError(phierror);
0861 clus->setZError(zerror);
0862 clus->setPhiSize(phibins.size());
0863 clus->setZSize(zbins.size());
0864
0865
0866 clus->setSubSurfKey(0);
0867
0868 if (Verbosity() > 2)
0869 {
0870 clus->identify();
0871 }
0872
0873 if (zbins.size() <= 127)
0874 {
0875 m_clusterlist->addClusterSpecifyKey(ckey, clus.release());
0876 }
0877 }
0878 }
0879
0880 if (Verbosity() > 1)
0881 {
0882
0883 m_clusterhitassoc->identify();
0884 }
0885
0886 return;
0887 }
0888
0889 void MvtxClusterizer::PrintClusters(PHCompositeNode *topNode)
0890 {
0891 if (Verbosity() > 0)
0892 {
0893 TrkrClusterContainer *clusterlist =
0894 findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
0895 if (!clusterlist)
0896 {
0897 return;
0898 }
0899
0900 std::cout << "================= After MvtxClusterizer::process_event() "
0901 "===================="
0902 << std::endl;
0903
0904 std::cout << " There are " << clusterlist->size()
0905 << " clusters recorded: " << std::endl;
0906
0907 if (Verbosity() > 3)
0908 {
0909 clusterlist->identify();
0910 }
0911
0912 std::cout << "=================================================================="
0913 "========="
0914 << std::endl;
0915 }
0916
0917 return;
0918 }