File indexing completed on 2025-08-06 08:18:02
0001
0002
0003 #include <torch/script.h>
0004
0005 #include "TpcClusterizer.h"
0006
0007 #include "LaserEventInfo.h"
0008
0009 #include "TrainingHits.h"
0010 #include "TrainingHitsContainer.h"
0011
0012 #include <trackbase/ClusHitsVerbosev1.h>
0013 #include <trackbase/TpcDefs.h>
0014 #include <trackbase/TrkrClusterContainerv4.h>
0015 #include <trackbase/TrkrClusterHitAssocv3.h>
0016 #include <trackbase/TrkrClusterv3.h>
0017 #include <trackbase/TrkrClusterv4.h>
0018 #include <trackbase/TrkrClusterv5.h>
0019 #include <trackbase/TrkrDefs.h> // for hitkey, getLayer
0020 #include <trackbase/TrkrHit.h>
0021 #include <trackbase/TrkrHitSet.h>
0022 #include <trackbase/TrkrHitSetContainer.h>
0023 #include <trackbase/alignmentTransformationContainer.h>
0024
0025 #include <trackbase/RawHit.h>
0026 #include <trackbase/RawHitSet.h>
0027 #include <trackbase/RawHitSetContainer.h>
0028 #include <trackbase/RawHitSet.h>
0029
0030 #include <fun4all/Fun4AllReturnCodes.h>
0031 #include <fun4all/SubsysReco.h> // for SubsysReco
0032
0033 #include <g4detectors/PHG4TpcCylinderGeom.h>
0034 #include <g4detectors/PHG4TpcCylinderGeomContainer.h>
0035
0036 #include <Acts/Definitions/Units.hpp>
0037 #include <Acts/Surfaces/Surface.hpp>
0038
0039 #include <phool/PHCompositeNode.h>
0040 #include <phool/PHIODataNode.h> // for PHIODataNode
0041 #include <phool/PHNode.h> // for PHNode
0042 #include <phool/PHNodeIterator.h>
0043 #include <phool/PHObject.h> // for PHObject
0044 #include <phool/getClass.h>
0045 #include <phool/phool.h> // for PHWHERE
0046
0047 #include <TMatrixFfwd.h> // for TMatrixF
0048 #include <TMatrixT.h> // for TMatrixT, ope...
0049 #include <TMatrixTUtils.h> // for TMatrixTRow
0050
0051 #include <TFile.h>
0052
0053 #include <array>
0054 #include <cmath> // for sqrt, cos, sin
0055 #include <iostream>
0056 #include <limits>
0057 #include <map> // for _Rb_tree_cons...
0058 #include <string>
0059 #include <utility> // for pair
0060 #include <vector>
0061
0062 #include <pthread.h>
0063
0064 namespace
0065 {
0066 template <class T>
0067 inline constexpr T square(const T &x)
0068 {
0069 return x * x;
0070 }
0071
0072 using assoc = std::pair<TrkrDefs::cluskey, TrkrDefs::hitkey>;
0073
0074 struct ihit
0075 {
0076 unsigned short iphi = 0;
0077 unsigned short it = 0;
0078 unsigned short adc = 0;
0079 unsigned short edge = 0;
0080 };
0081
0082 using vec_dVerbose = std::vector<std::vector<std::pair<int, int>>>;
0083
0084
0085 bool gen_hits = false;
0086 bool use_nn = false;
0087 const int nd = 5;
0088 torch::jit::script::Module module_pos;
0089
0090 struct thread_data
0091 {
0092 PHG4TpcCylinderGeom *layergeom = nullptr;
0093 TrkrHitSet *hitset = nullptr;
0094 RawHitSet *rawhitset = nullptr;
0095 ActsGeometry *tGeometry = nullptr;
0096 unsigned int layer = 0;
0097 int side = 0;
0098 unsigned int sector = 0;
0099 float radius = 0;
0100 float drift_velocity = 0;
0101 unsigned short pads_per_sector = 0;
0102 float phistep = 0;
0103 float pedestal = 0;
0104 float seed_threshold = 0;
0105 float edge_threshold = 0;
0106 float min_err_squared = 0;
0107 float min_clus_size = 0;
0108 float min_adc_sum = 0;
0109 bool do_assoc = true;
0110 bool do_wedge_emulation = true;
0111 bool do_singles = true;
0112 bool do_split = true;
0113 int FixedWindow = 0;
0114 unsigned short phibins = 0;
0115 unsigned short phioffset = 0;
0116 unsigned short tbins = 0;
0117 unsigned short toffset = 0;
0118 unsigned short maxHalfSizeT = 0;
0119 unsigned short maxHalfSizePhi = 0;
0120 double m_tdriftmax = 0;
0121 double sampa_tbias = 0;
0122 std::vector<assoc> association_vector;
0123 std::vector<TrkrCluster *> cluster_vector;
0124 std::vector<TrainingHits *> v_hits;
0125 int verbosity = 0;
0126 bool fillClusHitsVerbose = false;
0127 vec_dVerbose phivec_ClusHitsVerbose;
0128 vec_dVerbose zvec_ClusHitsVerbose;
0129 };
0130
0131 pthread_mutex_t mythreadlock;
0132
0133 void remove_hit(double adc, int phibin, int tbin, int edge, std::multimap<unsigned short, ihit> &all_hit_map, std::vector<std::vector<unsigned short>> &adcval)
0134 {
0135 using hit_iterator = std::multimap<unsigned short, ihit>::iterator;
0136 std::pair<hit_iterator, hit_iterator> iterpair = all_hit_map.equal_range(adc);
0137 hit_iterator it = iterpair.first;
0138 for (; it != iterpair.second; ++it)
0139 {
0140 if (it->second.iphi == phibin && it->second.it == tbin)
0141 {
0142 all_hit_map.erase(it);
0143 break;
0144 }
0145 }
0146 if (edge)
0147 {
0148 adcval[phibin][tbin] = USHRT_MAX;
0149 }
0150 else
0151 {
0152 adcval[phibin][tbin] = 0;
0153 }
0154 }
0155
0156 void remove_hits(std::vector<ihit> &ihit_list, std::multimap<unsigned short, ihit> &all_hit_map, std::vector<std::vector<unsigned short>> &adcval)
0157 {
0158 for (auto &iter : ihit_list)
0159 {
0160 unsigned short adc = iter.adc;
0161 unsigned short phibin = iter.iphi;
0162 unsigned short tbin = iter.it;
0163 unsigned short edge = iter.edge;
0164 remove_hit(adc, phibin, tbin, edge, all_hit_map, adcval);
0165 }
0166 }
0167
0168 void find_t_range(int phibin, int tbin, const thread_data &my_data, const std::vector<std::vector<unsigned short>> &adcval, int &tdown, int &tup, int &touch, int &edge)
0169 {
0170 const int FitRangeT = (int) my_data.maxHalfSizeT;
0171 const int NTBinsMax = (int) my_data.tbins;
0172 const int FixedWindow = (int) my_data.FixedWindow;
0173 tup = 0;
0174 tdown = 0;
0175 if (FixedWindow != 0)
0176 {
0177 tup = FixedWindow;
0178 tdown = FixedWindow;
0179 if (tbin + tup >= NTBinsMax)
0180 {
0181 tup = NTBinsMax - tbin - 1;
0182 edge++;
0183 }
0184 if ((tbin - tdown) <= 0)
0185 {
0186 tdown = tbin;
0187 edge++;
0188 }
0189 return;
0190 }
0191 for (int it = 0; it < FitRangeT; it++)
0192 {
0193 int ct = tbin + it;
0194
0195 if (ct <= 0 || ct >= NTBinsMax)
0196 {
0197
0198 edge++;
0199 break;
0200 }
0201
0202 if (adcval[phibin][ct] <= 0)
0203 {
0204 break;
0205 }
0206 if (adcval[phibin][ct] == USHRT_MAX)
0207 {
0208 touch++;
0209 break;
0210 }
0211 if (my_data.do_split)
0212 {
0213
0214 if (ct < NTBinsMax - 4)
0215 {
0216 if (adcval[phibin][ct] + adcval[phibin][ct + 1] <
0217 adcval[phibin][ct + 2] + adcval[phibin][ct + 3])
0218 {
0219 tup = it + 1;
0220 touch++;
0221 break;
0222 }
0223 }
0224 }
0225 tup = it;
0226 }
0227 for (int it = 0; it < FitRangeT; it++)
0228 {
0229 int ct = tbin - it;
0230 if (ct <= 0 || ct >= NTBinsMax)
0231 {
0232
0233 edge++;
0234 break;
0235 }
0236 if (adcval[phibin][ct] <= 0)
0237 {
0238 break;
0239 }
0240 if (adcval[phibin][ct] == USHRT_MAX)
0241 {
0242 touch++;
0243 break;
0244 }
0245 if (my_data.do_split)
0246 {
0247 if (ct > 4)
0248 {
0249 if (adcval[phibin][ct] + adcval[phibin][ct - 1] <
0250 adcval[phibin][ct - 2] + adcval[phibin][ct - 3])
0251 {
0252 tdown = it + 1;
0253 touch++;
0254 break;
0255 }
0256 }
0257 }
0258 tdown = it;
0259 }
0260 return;
0261 }
0262
0263 void find_phi_range(int phibin, int tbin, const thread_data &my_data, const std::vector<std::vector<unsigned short>> &adcval, int &phidown, int &phiup, int &touch, int &edge)
0264 {
0265 int FitRangePHI = (int) my_data.maxHalfSizePhi;
0266 int NPhiBinsMax = (int) my_data.phibins;
0267 const int FixedWindow = (int) my_data.FixedWindow;
0268 phidown = 0;
0269 phiup = 0;
0270 if (FixedWindow != 0)
0271 {
0272 phiup = FixedWindow;
0273 phidown = FixedWindow;
0274 if (phibin + phiup >= NPhiBinsMax)
0275 {
0276 phiup = NPhiBinsMax - phibin - 1;
0277 edge++;
0278 }
0279 if (phibin - phidown <= 0)
0280 {
0281 phidown = phibin;
0282 edge++;
0283 }
0284 return;
0285 }
0286 for (int iphi = 0; iphi < FitRangePHI; iphi++)
0287 {
0288 int cphi = phibin + iphi;
0289 if (cphi < 0 || cphi >= NPhiBinsMax)
0290 {
0291
0292 edge++;
0293 break;
0294 }
0295
0296
0297 if (adcval[cphi][tbin] <= 0)
0298 {
0299
0300 break;
0301 }
0302 if (adcval[cphi][tbin] == USHRT_MAX)
0303 {
0304 touch++;
0305 break;
0306 }
0307 if (my_data.do_split)
0308 {
0309 if (cphi < NPhiBinsMax - 4)
0310 {
0311 if (adcval[cphi][tbin] + adcval[cphi + 1][tbin] <
0312 adcval[cphi + 2][tbin] + adcval[cphi + 3][tbin])
0313 {
0314 phiup = iphi + 1;
0315 touch++;
0316 break;
0317 }
0318 }
0319 }
0320 phiup = iphi;
0321 }
0322
0323 for (int iphi = 0; iphi < FitRangePHI; iphi++)
0324 {
0325 int cphi = phibin - iphi;
0326 if (cphi < 0 || cphi >= NPhiBinsMax)
0327 {
0328
0329 edge++;
0330 break;
0331 }
0332
0333 if (adcval[cphi][tbin] <= 0)
0334 {
0335
0336 break;
0337 }
0338 if (adcval[cphi][tbin] == USHRT_MAX)
0339 {
0340 touch++;
0341 break;
0342 }
0343 if (my_data.do_split)
0344 {
0345 if (cphi > 4)
0346 {
0347 if (adcval[cphi][tbin] + adcval[cphi - 1][tbin] <
0348 adcval[cphi - 2][tbin] + adcval[cphi - 3][tbin])
0349 {
0350 phidown = iphi + 1;
0351 touch++;
0352 break;
0353 }
0354 }
0355 }
0356 phidown = iphi;
0357 }
0358 return;
0359 }
0360
0361 int is_hit_isolated(int iphi, int it, int NPhiBinsMax, int NTBinsMax, const std::vector<std::vector<unsigned short>> &adcval)
0362 {
0363
0364
0365
0366
0367 int isosum = 0;
0368 int isophimin = iphi - 1;
0369 if (isophimin < 0)
0370 {
0371 isophimin = 0;
0372 }
0373 int isophimax = iphi + 1;
0374 if (!(isophimax < NPhiBinsMax))
0375 {
0376 isophimax = NPhiBinsMax - 1;
0377 }
0378 int isotmin = it - 1;
0379 if (isotmin < 0)
0380 {
0381 isotmin = 0;
0382 }
0383 int isotmax = it + 1;
0384 if (!(isotmax < NTBinsMax))
0385 {
0386 isotmax = NTBinsMax - 1;
0387 }
0388 for (int isophi = isophimin; isophi <= isophimax; isophi++)
0389 {
0390 for (int isot = isotmin; isot <= isotmax; isot++)
0391 {
0392 if (isophi == iphi && isot == it)
0393 {
0394 continue;
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 isosum += adcval[isophi][isot];
0408
0409
0410
0411
0412
0413
0414 }
0415 }
0416 int isiso = 0;
0417 if (isosum == 0)
0418 {
0419 isiso = 1;
0420 }
0421 return isiso;
0422 }
0423
0424 void get_cluster(int phibin, int tbin, const thread_data &my_data, const std::vector<std::vector<unsigned short>> &adcval, std::vector<ihit> &ihit_list, int &touch, int &edge)
0425 {
0426
0427
0428
0429 int tup = 0;
0430 int tdown = 0;
0431 find_t_range(phibin, tbin, my_data, adcval, tdown, tup, touch, edge);
0432
0433 for (int it = tbin - tdown; it <= (tbin + tup); it++)
0434 {
0435 int phiup = 0;
0436 int phidown = 0;
0437 find_phi_range(phibin, it, my_data, adcval, phidown, phiup, touch, edge);
0438 for (int iphi = (phibin - phidown); iphi <= (phibin + phiup); iphi++)
0439 {
0440 if (adcval[iphi][it] > 0 && adcval[iphi][it] != USHRT_MAX)
0441 {
0442 if (my_data.do_singles)
0443 {
0444 if (is_hit_isolated(iphi, it, (int) my_data.phibins, (int) my_data.tbins, adcval))
0445 {
0446 continue;
0447 }
0448 }
0449 ihit hit;
0450 hit.iphi = iphi;
0451 hit.it = it;
0452
0453 hit.adc = adcval[iphi][it];
0454 if (touch > 0)
0455 {
0456 if ((iphi == (phibin - phidown)) ||
0457 (iphi == (phibin + phiup)))
0458 {
0459 hit.edge = 1;
0460 }
0461 }
0462 ihit_list.push_back(hit);
0463 }
0464 }
0465 }
0466 return;
0467 }
0468
0469 void calc_cluster_parameter(const int iphi_center, const int it_center,
0470 const std::vector<ihit> &ihit_list, thread_data &my_data, int ntouch, int nedge)
0471 {
0472
0473
0474
0475
0476
0477
0478
0479 double t_sum = 0.0;
0480
0481 double adc_sum = 0.0;
0482 double t2_sum = 0.0;
0483
0484
0485 double iphi_sum = 0.0;
0486 double iphi2_sum = 0.0;
0487
0488 double radius = my_data.layergeom->get_radius();
0489
0490 int phibinhi = -1;
0491 int phibinlo = 666666;
0492 int tbinhi = -1;
0493 int tbinlo = 666666;
0494 int clus_size = ihit_list.size();
0495 int max_adc = 0;
0496 if (clus_size <= my_data.min_clus_size)
0497 {
0498 return;
0499 }
0500
0501
0502 TrainingHits *training_hits = nullptr;
0503 if (gen_hits)
0504 {
0505 training_hits = new TrainingHits;
0506 assert(training_hits);
0507 training_hits->radius = radius;
0508 training_hits->phi = my_data.layergeom->get_phicenter(iphi_center + my_data.phioffset, my_data.side);
0509 double center_t = my_data.layergeom->get_zcenter(it_center + my_data.toffset) + my_data.sampa_tbias;
0510 training_hits->z = (my_data.m_tdriftmax - center_t) * my_data.tGeometry->get_drift_velocity();
0511 if (my_data.side == 0)
0512 {
0513 training_hits->z = -training_hits->z;
0514 }
0515 training_hits->phistep = my_data.layergeom->get_phistep();
0516 training_hits->zstep = my_data.layergeom->get_zstep() * my_data.tGeometry->get_drift_velocity();
0517 training_hits->layer = my_data.layer;
0518 training_hits->ntouch = ntouch;
0519 training_hits->nedge = nedge;
0520 training_hits->v_adc.fill(0);
0521 }
0522
0523
0524 std::vector<TrkrDefs::hitkey> hitkeyvec;
0525
0526
0527 std::map<int, unsigned int> m_phi{};
0528 std::map<int, unsigned int> m_z{};
0529
0530 for (auto iter : ihit_list)
0531 {
0532 int iphi = iter.iphi + my_data.phioffset;
0533 int it = iter.it + my_data.toffset;
0534 double adc = iter.adc;
0535
0536 if (adc <= 0)
0537 {
0538 continue;
0539 }
0540
0541 if (adc > max_adc)
0542 {
0543 max_adc = adc;
0544 }
0545
0546 if (iphi > phibinhi)
0547 {
0548 phibinhi = iphi;
0549 }
0550
0551 if (iphi < phibinlo)
0552 {
0553 phibinlo = iphi;
0554 }
0555
0556 if (it > tbinhi)
0557 {
0558 tbinhi = it;
0559 }
0560
0561 if (it < tbinlo)
0562 {
0563 tbinlo = it;
0564 }
0565
0566
0567
0568
0569
0570
0571
0572
0573 iphi_sum += iphi * adc;
0574 iphi2_sum += square(iphi) * adc;
0575
0576
0577 double t = my_data.layergeom->get_zcenter(it);
0578 t_sum += t * adc;
0579 t2_sum += square(t) * adc;
0580
0581 adc_sum += adc;
0582
0583 if (my_data.fillClusHitsVerbose)
0584 {
0585 auto pnew = m_phi.try_emplace(iphi, adc);
0586 if (!pnew.second)
0587 {
0588 pnew.first->second += adc;
0589 }
0590
0591 pnew = m_z.try_emplace(it, adc);
0592 if (!pnew.second)
0593 {
0594 pnew.first->second += adc;
0595 }
0596 }
0597
0598
0599 TrkrDefs::hitkey hitkey = TpcDefs::genHitKey(iphi, it);
0600
0601 hitkeyvec.push_back(hitkey);
0602
0603
0604 if (gen_hits && training_hits)
0605 {
0606 int iphi_diff = iter.iphi - iphi_center;
0607 int it_diff = iter.it - it_center;
0608 if (std::abs(iphi_diff) <= nd && std::abs(it_diff) <= nd)
0609 {
0610 training_hits->v_adc[(iphi_diff + nd) * (2 * nd + 1) + (it_diff + nd)] = adc;
0611 }
0612 }
0613 }
0614
0615 if (adc_sum < my_data.min_adc_sum)
0616 {
0617 hitkeyvec.clear();
0618 return;
0619 }
0620
0621
0622 double clusiphi = iphi_sum / adc_sum;
0623 double clusphi = my_data.layergeom->get_phi(clusiphi, my_data.side);
0624
0625 float clusx = radius * cos(clusphi);
0626 float clusy = radius * sin(clusphi);
0627 double clust = t_sum / adc_sum;
0628
0629 double zdriftlength = clust * my_data.tGeometry->get_drift_velocity();
0630
0631 double clusz = my_data.m_tdriftmax * my_data.tGeometry->get_drift_velocity() - zdriftlength;
0632 if (my_data.side == 0)
0633 {
0634 clusz = -clusz;
0635 }
0636
0637 const double phi_cov = (iphi2_sum / adc_sum - square(clusiphi)) * pow(my_data.layergeom->get_phistep(), 2);
0638 const double t_cov = t2_sum / adc_sum - square(clust);
0639
0640
0641 TrkrDefs::hitsetkey tpcHitSetKey = TpcDefs::genHitSetKey(my_data.layer, my_data.sector, my_data.side);
0642 Acts::Vector3 global(clusx, clusy, clusz);
0643 TrkrDefs::subsurfkey subsurfkey = 0;
0644
0645 Surface surface = my_data.tGeometry->get_tpc_surface_from_coords(
0646 tpcHitSetKey,
0647 global,
0648 subsurfkey);
0649
0650 if (!surface)
0651 {
0652
0653
0654 hitkeyvec.clear();
0655 return;
0656 }
0657
0658
0659
0660 const double phi_err_square = (phibinhi == phibinlo) ? 9*(square(radius * my_data.layergeom->get_phistep()) / 12) : square(radius) * phi_cov / (adc_sum * 0.14);
0661
0662 const double t_err_square = (tbinhi == tbinlo) ? 9*(square(my_data.layergeom->get_zstep()) / 12) : t_cov / (adc_sum * 0.14);
0663
0664 char tsize = tbinhi - tbinlo + 1;
0665 char phisize = phibinhi - phibinlo + 1;
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676 clust = clust + my_data.sampa_tbias;
0677
0678
0679 global *= Acts::UnitConstants::cm;
0680
0681 Acts::Vector3 local = surface->transform(my_data.tGeometry->geometry().getGeoContext()).inverse() * global;
0682 local /= Acts::UnitConstants::cm;
0683
0684
0685
0686 TrkrCluster *clus_base = nullptr;
0687 bool b_made_cluster{false};
0688
0689
0690
0691 if (sqrt(phi_err_square) > my_data.min_err_squared)
0692 {
0693 auto clus = new TrkrClusterv5;
0694
0695 clus_base = clus;
0696 clus->setAdc(adc_sum);
0697 clus->setMaxAdc(max_adc);
0698 clus->setEdge(nedge);
0699 clus->setPhiSize(phisize);
0700 clus->setZSize(tsize);
0701 clus->setSubSurfKey(subsurfkey);
0702 clus->setOverlap(ntouch);
0703 clus->setLocalX(local(0));
0704 clus->setLocalY(clust);
0705 clus->setPhiError(sqrt(phi_err_square));
0706 clus->setZError(sqrt(t_err_square * pow(my_data.tGeometry->get_drift_velocity(), 2)));
0707 my_data.cluster_vector.push_back(clus);
0708 b_made_cluster = true;
0709 }
0710
0711 if (use_nn && clus_base && training_hits)
0712 {
0713 try
0714 {
0715
0716 std::vector<torch::jit::IValue> inputs;
0717 inputs.emplace_back(torch::stack({torch::from_blob(std::vector<float>(training_hits->v_adc.begin(), training_hits->v_adc.end()).data(), {1, 2 * nd + 1, 2 * nd + 1}, torch::kFloat32),
0718 torch::full({1, 2 * nd + 1, 2 * nd + 1}, std::clamp((training_hits->layer - 7) / 16, 0, 2), torch::kFloat32),
0719 torch::full({1, 2 * nd + 1, 2 * nd + 1}, training_hits->z / radius, torch::kFloat32)},
0720 1));
0721
0722
0723 at::Tensor ten_pos = module_pos.forward(inputs).toTensor();
0724 float nn_phi = training_hits->phi + std::clamp(ten_pos[0][0][0].item<float>(), -(float) nd, (float) nd) * training_hits->phistep;
0725 float nn_z = training_hits->z + std::clamp(ten_pos[0][1][0].item<float>(), -(float) nd, (float) nd) * training_hits->zstep;
0726 float nn_x = radius * std::cos(nn_phi);
0727 float nn_y = radius * std::sin(nn_phi);
0728 Acts::Vector3 nn_global(nn_x, nn_y, nn_z);
0729 nn_global *= Acts::UnitConstants::cm;
0730 Acts::Vector3 nn_local = surface->transform(my_data.tGeometry->geometry().geoContext).inverse() * nn_global;
0731 nn_local /= Acts::UnitConstants::cm;
0732 float nn_t = my_data.m_tdriftmax - std::fabs(nn_z) / my_data.tGeometry->get_drift_velocity();
0733 clus_base->setLocalX(nn_local(0));
0734 clus_base->setLocalY(nn_t);
0735 }
0736 catch (const c10::Error &e)
0737 {
0738 std::cout << PHWHERE << "Error: Failed to execute NN modules" << std::endl;
0739 }
0740 }
0741
0742 if (my_data.fillClusHitsVerbose && b_made_cluster)
0743 {
0744
0745 my_data.phivec_ClusHitsVerbose.push_back(std::vector<std::pair<int, int>>{});
0746 my_data.zvec_ClusHitsVerbose.push_back(std::vector<std::pair<int, int>>{});
0747
0748 auto &vphi = my_data.phivec_ClusHitsVerbose.back();
0749 auto &vz = my_data.zvec_ClusHitsVerbose.back();
0750
0751 for (auto &entry : m_phi)
0752 {
0753 vphi.push_back({entry.first, entry.second});
0754 }
0755 for (auto &entry : m_z)
0756 {
0757 vz.push_back({entry.first, entry.second});
0758 }
0759 }
0760
0761
0762
0763 if (my_data.do_assoc)
0764 {
0765
0766 uint32_t index = my_data.cluster_vector.size() - 1;
0767 for (unsigned int &i : hitkeyvec)
0768 {
0769 my_data.association_vector.emplace_back(index, i);
0770 }
0771 if (gen_hits && training_hits)
0772 {
0773 training_hits->cluskey = TrkrDefs::genClusKey(tpcHitSetKey, index);
0774 }
0775 }
0776 hitkeyvec.clear();
0777 if (gen_hits && training_hits)
0778 {
0779 my_data.v_hits.emplace_back(training_hits);
0780 }
0781
0782 }
0783
0784 void ProcessSectorData(thread_data *my_data)
0785 {
0786 const auto &pedestal = my_data->pedestal;
0787 const auto &phibins = my_data->phibins;
0788 const auto &phioffset = my_data->phioffset;
0789 const auto &tbins = my_data->tbins;
0790 const auto &toffset = my_data->toffset;
0791 const auto &layer = my_data->layer;
0792
0793
0794 std::vector<std::vector<unsigned short>> adcval(phibins, std::vector<unsigned short>(tbins, 0));
0795 std::multimap<unsigned short, ihit> all_hit_map;
0796 std::vector<ihit> hit_vect;
0797
0798 int tbinmax = tbins;
0799 int tbinmin = 0;
0800 if (my_data->do_wedge_emulation)
0801 {
0802 if (layer >= 7 && layer < 22)
0803 {
0804 int etacut = (tbins / 2.) - ((50 + (layer - 7)) / 105.5) * (tbins / 2.);
0805 tbinmin = etacut;
0806 tbinmax -= etacut;
0807 }
0808 if (layer >= 22 && layer <= 48)
0809 {
0810 int etacut = (tbins / 2.) - ((65 + ((40.5 / 26) * (layer - 22))) / 105.5) * (tbins / 2.);
0811 tbinmin = etacut;
0812 tbinmax -= etacut;
0813 }
0814 }
0815
0816 if (my_data->hitset != nullptr)
0817 {
0818 TrkrHitSet *hitset = my_data->hitset;
0819 TrkrHitSet::ConstRange hitrangei = hitset->getHits();
0820
0821 for (TrkrHitSet::ConstIterator hitr = hitrangei.first;
0822 hitr != hitrangei.second;
0823 ++hitr)
0824 {
0825 if (TpcDefs::getPad(hitr->first) - phioffset < 0)
0826 {
0827
0828 continue;
0829 }
0830 if (TpcDefs::getTBin(hitr->first) - toffset < 0)
0831 {
0832
0833 }
0834 unsigned short phibin = TpcDefs::getPad(hitr->first) - phioffset;
0835 unsigned short tbin = TpcDefs::getTBin(hitr->first) - toffset;
0836 unsigned short tbinorg = TpcDefs::getTBin(hitr->first);
0837 if (phibin >= phibins)
0838 {
0839
0840 continue;
0841 }
0842 if (tbin >= tbins)
0843 {
0844
0845 continue;
0846 }
0847 if (tbinorg > tbinmax || tbinorg < tbinmin)
0848 {
0849 continue;
0850 }
0851 float_t fadc = (hitr->second->getAdc()) - pedestal;
0852 unsigned short adc = 0;
0853 if (fadc > 0)
0854 {
0855 adc = (unsigned short) fadc;
0856 }
0857 if (phibin >= phibins)
0858 {
0859 continue;
0860 }
0861 if (tbin >= tbins)
0862 {
0863 continue;
0864 }
0865
0866 if (adc > 0)
0867 {
0868 if (adc > (my_data->seed_threshold))
0869 {
0870 ihit thisHit;
0871
0872 thisHit.iphi = phibin;
0873 thisHit.it = tbin;
0874 thisHit.adc = adc;
0875 thisHit.edge = 0;
0876 all_hit_map.insert(std::make_pair(adc, thisHit));
0877 }
0878 if (adc > my_data->edge_threshold)
0879 {
0880 adcval[phibin][tbin] = (unsigned short) adc;
0881 }
0882 }
0883 }
0884 }
0885 else if (my_data->rawhitset != nullptr)
0886 {
0887 RawHitSet *hitset = my_data->rawhitset;
0888
0889
0890
0891
0892
0893
0894 for (int nphi = 0; nphi < phibins; nphi++)
0895 {
0896 if (hitset->size(nphi) == 0)
0897 {
0898 continue;
0899 }
0900
0901 int pindex = 0;
0902 for (unsigned int nt = 0; nt < hitset->size(nphi); nt++)
0903 {
0904 unsigned short val = (*(hitset->getHits(nphi)))[nt];
0905
0906 if (val == 0)
0907 {
0908 pindex++;
0909 }
0910 else
0911 {
0912 if (nt == 0)
0913 {
0914 if (val > 5)
0915 {
0916 ihit thisHit;
0917 thisHit.iphi = nphi;
0918 thisHit.it = pindex;
0919 thisHit.adc = val;
0920 thisHit.edge = 0;
0921 all_hit_map.insert(std::make_pair(val, thisHit));
0922 }
0923 adcval[nphi][pindex++] = val;
0924 }
0925 else
0926 {
0927 if (((*(hitset->getHits(nphi)))[nt - 1] == 0) && ((*(hitset->getHits(nphi)))[nt + 1] == 0))
0928 {
0929 pindex += val;
0930 }
0931 else
0932 {
0933 if (val > 5)
0934 {
0935 ihit thisHit;
0936 thisHit.iphi = nphi;
0937 thisHit.it = pindex;
0938 thisHit.adc = val;
0939 thisHit.edge = 0;
0940 all_hit_map.insert(std::make_pair(val, thisHit));
0941 }
0942 adcval[nphi][pindex++] = val;
0943 }
0944 }
0945 }
0946 }
0947 }
0948 }
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971 while (all_hit_map.size() > 0)
0972 {
0973
0974 auto iter = all_hit_map.rbegin();
0975 if (iter == all_hit_map.rend())
0976 {
0977 break;
0978 }
0979 ihit hiHit = iter->second;
0980 int iphi = hiHit.iphi;
0981 int it = hiHit.it;
0982 unsigned short edge = hiHit.edge;
0983 double adc = hiHit.adc;
0984 if (my_data->do_singles)
0985 {
0986 if (is_hit_isolated(iphi, it, (int) my_data->phibins, (int) my_data->tbins, adcval))
0987 {
0988 remove_hit(adc, iphi, it, edge, all_hit_map, adcval);
0989 continue;
0990 }
0991 }
0992
0993
0994
0995
0996 std::vector<ihit> ihit_list;
0997 int ntouch = 0;
0998 int nedge = 0;
0999 get_cluster(iphi, it, *my_data, adcval, ihit_list, ntouch, nedge);
1000
1001 if (my_data->FixedWindow > 0)
1002 {
1003
1004 int wphibinhi = -1;
1005 int wphibinlo = 666666;
1006 int wtbinhi = -1;
1007 int wtbinlo = 666666;
1008 for (auto witer : ihit_list)
1009 {
1010 int wiphi = witer.iphi + my_data->phioffset;
1011 int wit = witer.it + my_data->toffset;
1012 double wadc = witer.adc;
1013 if (wadc <= 0)
1014 {
1015 continue;
1016 }
1017 if (wiphi > wphibinhi)
1018 {
1019 wphibinhi = wiphi;
1020 }
1021 if (wiphi < wphibinlo)
1022 {
1023 wphibinlo = wiphi;
1024 }
1025 if (wit > wtbinhi)
1026 {
1027 wtbinhi = wit;
1028 }
1029 if (wit < wtbinlo)
1030 {
1031 wtbinlo = wit;
1032 }
1033 }
1034 char wtsize = wtbinhi - wtbinlo + 1;
1035 char wphisize = wphibinhi - wphibinlo + 1;
1036
1037
1038 if (ihit_list.size() > (0.5 * pow((2 * my_data->FixedWindow + 1), 2)) ||
1039 wphisize >= (2 * my_data->FixedWindow + 1) ||
1040 wtsize >= (2 * my_data->FixedWindow + 1))
1041 {
1042 int window_cache = my_data->FixedWindow;
1043
1044 my_data->FixedWindow = 0;
1045
1046 ihit_list.clear();
1047 get_cluster(iphi, it, *my_data, adcval, ihit_list, ntouch, nedge);
1048
1049 my_data->FixedWindow = window_cache;
1050 }
1051 }
1052 if (ihit_list.size() <= 1)
1053 {
1054 remove_hits(ihit_list, all_hit_map, adcval);
1055 ihit_list.clear();
1056 remove_hit(adc, iphi, it, edge, all_hit_map, adcval);
1057 }
1058
1059
1060
1061
1062 calc_cluster_parameter(iphi, it, ihit_list, *my_data, ntouch, nedge);
1063 remove_hits(ihit_list, all_hit_map, adcval);
1064 ihit_list.clear();
1065 }
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078 }
1079 void *ProcessSector(void *threadarg)
1080 {
1081 auto my_data = static_cast<thread_data *>(threadarg);
1082 ProcessSectorData(my_data);
1083 pthread_exit(nullptr);
1084 }
1085 }
1086
1087 TpcClusterizer::TpcClusterizer(const std::string &name)
1088 : SubsysReco(name)
1089 , m_training(nullptr)
1090 {
1091 }
1092
1093 bool TpcClusterizer::is_in_sector_boundary(int phibin, int sector, PHG4TpcCylinderGeom *layergeom) const
1094 {
1095 bool reject_it = false;
1096
1097
1098 int PhiBins = layergeom->get_phibins();
1099 int PhiBinsSector = PhiBins / 12;
1100
1101 double radius = layergeom->get_radius();
1102 double PhiBinSize = 2.0 * radius * M_PI / (double) PhiBins;
1103
1104
1105 int sector_lo = sector * PhiBinsSector;
1106 int sector_hi = sector_lo + PhiBinsSector - 1;
1107
1108 int sector_fiducial_bins = (int) (SectorFiducialCut / PhiBinSize);
1109
1110 if (phibin < sector_lo + sector_fiducial_bins || phibin > sector_hi - sector_fiducial_bins)
1111 {
1112 reject_it = true;
1113
1114
1115
1116
1117
1118
1119 }
1120
1121 return reject_it;
1122 }
1123
1124 int TpcClusterizer::InitRun(PHCompositeNode *topNode)
1125 {
1126 PHNodeIterator iter(topNode);
1127
1128
1129 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
1130 if (!dstNode)
1131 {
1132 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
1133 return Fun4AllReturnCodes::ABORTRUN;
1134 }
1135
1136
1137 auto trkrclusters = findNode::getClass<TrkrClusterContainer>(dstNode, "TRKR_CLUSTER");
1138 if (!trkrclusters)
1139 {
1140 PHNodeIterator dstiter(dstNode);
1141 PHCompositeNode *DetNode =
1142 dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
1143 if (!DetNode)
1144 {
1145 DetNode = new PHCompositeNode("TRKR");
1146 dstNode->addNode(DetNode);
1147 }
1148
1149 trkrclusters = new TrkrClusterContainerv4;
1150 PHIODataNode<PHObject> *TrkrClusterContainerNode =
1151 new PHIODataNode<PHObject>(trkrclusters, "TRKR_CLUSTER", "PHObject");
1152 DetNode->addNode(TrkrClusterContainerNode);
1153 }
1154
1155 auto clusterhitassoc = findNode::getClass<TrkrClusterHitAssoc>(topNode, "TRKR_CLUSTERHITASSOC");
1156 if (!clusterhitassoc)
1157 {
1158 PHNodeIterator dstiter(dstNode);
1159 PHCompositeNode *DetNode =
1160 dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
1161 if (!DetNode)
1162 {
1163 DetNode = new PHCompositeNode("TRKR");
1164 dstNode->addNode(DetNode);
1165 }
1166
1167 clusterhitassoc = new TrkrClusterHitAssocv3;
1168 PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(clusterhitassoc, "TRKR_CLUSTERHITASSOC", "PHObject");
1169 DetNode->addNode(newNode);
1170 }
1171
1172 auto training_container = findNode::getClass<TrainingHitsContainer>(dstNode, "TRAINING_HITSET");
1173 if (!training_container)
1174 {
1175 PHNodeIterator dstiter(dstNode);
1176 PHCompositeNode *DetNode =
1177 dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
1178 if (!DetNode)
1179 {
1180 DetNode = new PHCompositeNode("TRKR");
1181 dstNode->addNode(DetNode);
1182 }
1183
1184 training_container = new TrainingHitsContainer;
1185 PHIODataNode<PHObject> *TrainingHitsContainerNode =
1186 new PHIODataNode<PHObject>(training_container, "TRAINING_HITSET", "PHObject");
1187 DetNode->addNode(TrainingHitsContainerNode);
1188 }
1189
1190 gen_hits = _store_hits || _use_nn;
1191 use_nn = _use_nn;
1192 if (use_nn)
1193 {
1194 const char *offline_main = std::getenv("OFFLINE_MAIN");
1195 assert(offline_main);
1196 std::string net_model = std::string(offline_main) + "/share/tpc/net_model.pt";
1197 try
1198 {
1199
1200 module_pos = torch::jit::load(net_model);
1201 std::cout << PHWHERE << "Load NN module: " << net_model << std::endl;
1202 }
1203 catch (const c10::Error &e)
1204 {
1205 std::cout << PHWHERE << "Error: Cannot load module " << net_model << std::endl;
1206 exit(1);
1207 }
1208 }
1209 else
1210 {
1211 std::cout << PHWHERE << "Use traditional clustering" << std::endl;
1212 }
1213
1214 if (record_ClusHitsVerbose)
1215 {
1216
1217 mClusHitsVerbose = findNode::getClass<ClusHitsVerbosev1>(topNode, "Trkr_SvtxClusHitsVerbose");
1218 if (!mClusHitsVerbose)
1219 {
1220 PHNodeIterator dstiter(dstNode);
1221 auto DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
1222 if (!DetNode)
1223 {
1224 DetNode = new PHCompositeNode("TRKR");
1225 dstNode->addNode(DetNode);
1226 }
1227 mClusHitsVerbose = new ClusHitsVerbosev1();
1228 auto newNode = new PHIODataNode<PHObject>(mClusHitsVerbose, "Trkr_SvtxClusHitsVerbose", "PHObject");
1229 DetNode->addNode(newNode);
1230 }
1231 }
1232 auto geom =
1233 findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
1234 if (!geom)
1235 {
1236 std::cout << PHWHERE << "ERROR: Can't find node CYLINDERCELLGEOM_SVTX" << std::endl;
1237 return Fun4AllReturnCodes::ABORTRUN;
1238 }
1239
1240 AdcClockPeriod = geom->GetFirstLayerCellGeom()->get_zstep();
1241
1242 return Fun4AllReturnCodes::EVENT_OK;
1243 }
1244
1245 int TpcClusterizer::process_event(PHCompositeNode *topNode)
1246 {
1247
1248
1249
1250 alignmentTransformationContainer::use_alignment = false;
1251
1252
1253
1254 if (Verbosity() > 1000)
1255 {
1256 std::cout << "TpcClusterizer::Process_Event" << std::endl;
1257 }
1258
1259 PHNodeIterator iter(topNode);
1260 PHCompositeNode *dstNode = static_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
1261 if (!dstNode)
1262 {
1263 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
1264 return Fun4AllReturnCodes::ABORTRUN;
1265 }
1266 if (!do_read_raw)
1267 {
1268
1269 m_hits = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
1270 if (!m_hits)
1271 {
1272 std::cout << PHWHERE << "ERROR: Can't find node TRKR_HITSET" << std::endl;
1273 return Fun4AllReturnCodes::ABORTRUN;
1274 }
1275 }
1276 else
1277 {
1278
1279 m_rawhits = findNode::getClass<RawHitSetContainer>(topNode, "TRKR_RAWHITSET");
1280 if (!m_rawhits)
1281 {
1282 std::cout << PHWHERE << "ERROR: Can't find node TRKR_HITSET" << std::endl;
1283 return Fun4AllReturnCodes::ABORTRUN;
1284 }
1285 }
1286
1287
1288 LaserEventInfo *laserInfo = findNode::getClass<LaserEventInfo>(topNode, "LaserEventInfo");
1289 if (m_rejectEvent && laserInfo && laserInfo->isLaserEvent())
1290 {
1291 return Fun4AllReturnCodes::EVENT_OK;
1292 }
1293
1294
1295 m_clusterlist = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
1296 if (!m_clusterlist)
1297 {
1298 std::cout << PHWHERE << " ERROR: Can't find TRKR_CLUSTER." << std::endl;
1299 return Fun4AllReturnCodes::ABORTRUN;
1300 }
1301
1302
1303 m_clusterhitassoc = findNode::getClass<TrkrClusterHitAssoc>(topNode, "TRKR_CLUSTERHITASSOC");
1304 if (!m_clusterhitassoc)
1305 {
1306 std::cout << PHWHERE << " ERROR: Can't find TRKR_CLUSTERHITASSOC" << std::endl;
1307 return Fun4AllReturnCodes::ABORTRUN;
1308 }
1309
1310
1311 m_training = findNode::getClass<TrainingHitsContainer>(topNode, "TRAINING_HITSET");
1312 if (!m_training)
1313 {
1314 std::cout << PHWHERE << " ERROR: Can't find TRAINING_HITSET." << std::endl;
1315 return Fun4AllReturnCodes::ABORTRUN;
1316 }
1317
1318 PHG4TpcCylinderGeomContainer *geom_container =
1319 findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
1320 if (!geom_container)
1321 {
1322 std::cout << PHWHERE << "ERROR: Can't find node CYLINDERCELLGEOM_SVTX" << std::endl;
1323 return Fun4AllReturnCodes::ABORTRUN;
1324 }
1325
1326 m_tGeometry = findNode::getClass<ActsGeometry>(topNode,
1327 "ActsGeometry");
1328 if (!m_tGeometry)
1329 {
1330 std::cout << PHWHERE
1331 << "ActsGeometry not found on node tree. Exiting"
1332 << std::endl;
1333 return Fun4AllReturnCodes::ABORTRUN;
1334 }
1335
1336
1337
1338
1339 TrkrHitSetContainer::ConstRange hitsetrange;
1340 RawHitSetContainer::ConstRange rawhitsetrange;
1341 int num_hitsets = 0;
1342
1343 if (!do_read_raw)
1344 {
1345 hitsetrange = m_hits->getHitSets(TrkrDefs::TrkrId::tpcId);
1346 num_hitsets = std::distance(hitsetrange.first, hitsetrange.second);
1347 }
1348 else
1349 {
1350 rawhitsetrange = m_rawhits->getHitSets(TrkrDefs::TrkrId::tpcId);
1351 num_hitsets = std::distance(rawhitsetrange.first, rawhitsetrange.second);
1352 }
1353
1354
1355 struct thread_pair_t
1356 {
1357 pthread_t thread{};
1358 thread_data data;
1359 };
1360
1361
1362 std::vector<thread_pair_t> threads;
1363 threads.reserve(num_hitsets);
1364
1365 pthread_attr_t attr;
1366 pthread_attr_init(&attr);
1367 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1368
1369 if (pthread_mutex_init(&mythreadlock, nullptr) != 0)
1370 {
1371 std::cout << std::endl
1372 << " mutex init failed" << std::endl;
1373 return 1;
1374 }
1375
1376
1377 if (!do_read_raw)
1378 {
1379 for (TrkrHitSetContainer::ConstIterator hitsetitr = hitsetrange.first;
1380 hitsetitr != hitsetrange.second;
1381 ++hitsetitr)
1382 {
1383
1384 TrkrHitSet *hitset = hitsetitr->second;
1385 unsigned int layer = TrkrDefs::getLayer(hitsetitr->first);
1386 int side = TpcDefs::getSide(hitsetitr->first);
1387 unsigned int sector = TpcDefs::getSectorId(hitsetitr->first);
1388 PHG4TpcCylinderGeom *layergeom = geom_container->GetLayerCellGeom(layer);
1389
1390
1391 thread_pair_t &thread_pair = threads.emplace_back();
1392 if (mClusHitsVerbose)
1393 {
1394 thread_pair.data.fillClusHitsVerbose = true;
1395 };
1396
1397 thread_pair.data.layergeom = layergeom;
1398 thread_pair.data.hitset = hitset;
1399 thread_pair.data.rawhitset = nullptr;
1400 thread_pair.data.layer = layer;
1401 thread_pair.data.pedestal = pedestal;
1402 thread_pair.data.seed_threshold = seed_threshold;
1403 thread_pair.data.edge_threshold = edge_threshold;
1404 thread_pair.data.sector = sector;
1405 thread_pair.data.side = side;
1406 thread_pair.data.do_assoc = do_hit_assoc;
1407 thread_pair.data.do_wedge_emulation = do_wedge_emulation;
1408 thread_pair.data.do_singles = do_singles;
1409 thread_pair.data.tGeometry = m_tGeometry;
1410 thread_pair.data.maxHalfSizeT = MaxClusterHalfSizeT;
1411 thread_pair.data.maxHalfSizePhi = MaxClusterHalfSizePhi;
1412 thread_pair.data.sampa_tbias = m_sampa_tbias;
1413 thread_pair.data.verbosity = Verbosity();
1414 thread_pair.data.do_split = do_split;
1415 thread_pair.data.FixedWindow = do_fixed_window;
1416 thread_pair.data.min_err_squared = min_err_squared;
1417 thread_pair.data.min_clus_size = min_clus_size;
1418 thread_pair.data.min_adc_sum = min_adc_sum;
1419 unsigned short NPhiBins = (unsigned short) layergeom->get_phibins();
1420 unsigned short NPhiBinsSector = NPhiBins / 12;
1421 unsigned short NTBins = 0;
1422 if (is_reco)
1423 {
1424 NTBins = NZBinsSide;
1425 }
1426 else
1427 {
1428 NTBins = (unsigned short) layergeom->get_zbins();
1429 }
1430 unsigned short NTBinsSide = NTBins;
1431 unsigned short NTBinsMin = 0;
1432 unsigned short PhiOffset = NPhiBinsSector * sector;
1433 unsigned short TOffset = NTBinsMin;
1434
1435 m_tdriftmax = AdcClockPeriod * NZBinsSide;
1436 thread_pair.data.m_tdriftmax = m_tdriftmax;
1437
1438 thread_pair.data.phibins = NPhiBinsSector;
1439 thread_pair.data.phioffset = PhiOffset;
1440 thread_pair.data.tbins = NTBinsSide;
1441 thread_pair.data.toffset = TOffset;
1442
1443 thread_pair.data.radius = layergeom->get_radius();
1444 thread_pair.data.drift_velocity = m_tGeometry->get_drift_velocity();
1445 thread_pair.data.pads_per_sector = 0;
1446 thread_pair.data.phistep = 0;
1447 int rc;
1448 rc = pthread_create(&thread_pair.thread, &attr, ProcessSector, (void *) &thread_pair.data);
1449
1450 if (rc)
1451 {
1452 std::cout << "Error:unable to create thread," << rc << std::endl;
1453 }
1454 if (do_sequential)
1455 {
1456 int rc2 = pthread_join(thread_pair.thread, nullptr);
1457 if (rc2)
1458 {
1459 std::cout << "Error:unable to join," << rc2 << std::endl;
1460 }
1461
1462
1463 const auto &data(thread_pair.data);
1464 const auto hitsetkey = TpcDefs::genHitSetKey(data.layer, data.sector, data.side);
1465
1466
1467 for (uint32_t index = 0; index < data.cluster_vector.size(); ++index)
1468 {
1469
1470 const auto ckey = TrkrDefs::genClusKey(hitsetkey, index);
1471
1472
1473 auto cluster = data.cluster_vector[index];
1474
1475
1476 m_clusterlist->addClusterSpecifyKey(ckey, cluster);
1477
1478 if (mClusHitsVerbose)
1479 {
1480 for (auto &hit : data.phivec_ClusHitsVerbose[index])
1481 {
1482 mClusHitsVerbose->addPhiHit(hit.first, hit.second);
1483 }
1484 for (auto &hit : data.zvec_ClusHitsVerbose[index])
1485 {
1486 mClusHitsVerbose->addZHit(hit.first, hit.second);
1487 }
1488 mClusHitsVerbose->push_hits(ckey);
1489 }
1490 }
1491
1492
1493 for (const auto &[index, hkey] : thread_pair.data.association_vector)
1494 {
1495
1496 const auto ckey = TrkrDefs::genClusKey(hitsetkey, index);
1497
1498
1499 m_clusterhitassoc->addAssoc(ckey, hkey);
1500 }
1501 }
1502
1503 }
1504 }
1505 else
1506 {
1507 for (RawHitSetContainer::ConstIterator hitsetitr = rawhitsetrange.first;
1508 hitsetitr != rawhitsetrange.second;
1509 ++hitsetitr)
1510 {
1511
1512
1513
1514
1515 RawHitSet *hitset = hitsetitr->second;
1516 unsigned int layer = TrkrDefs::getLayer(hitsetitr->first);
1517 int side = TpcDefs::getSide(hitsetitr->first);
1518 unsigned int sector = TpcDefs::getSectorId(hitsetitr->first);
1519 PHG4TpcCylinderGeom *layergeom = geom_container->GetLayerCellGeom(layer);
1520
1521
1522 thread_pair_t &thread_pair = threads.emplace_back();
1523
1524 thread_pair.data.layergeom = layergeom;
1525 thread_pair.data.hitset = nullptr;
1526 thread_pair.data.rawhitset = hitset;
1527 thread_pair.data.layer = layer;
1528 thread_pair.data.pedestal = pedestal;
1529 thread_pair.data.sector = sector;
1530 thread_pair.data.side = side;
1531 thread_pair.data.do_assoc = do_hit_assoc;
1532 thread_pair.data.do_wedge_emulation = do_wedge_emulation;
1533 thread_pair.data.tGeometry = m_tGeometry;
1534 thread_pair.data.maxHalfSizeT = MaxClusterHalfSizeT;
1535 thread_pair.data.maxHalfSizePhi = MaxClusterHalfSizePhi;
1536 thread_pair.data.sampa_tbias = m_sampa_tbias;
1537 thread_pair.data.verbosity = Verbosity();
1538
1539 unsigned short NPhiBins = (unsigned short) layergeom->get_phibins();
1540 unsigned short NPhiBinsSector = NPhiBins / 12;
1541 unsigned short NTBins = (unsigned short) layergeom->get_zbins();
1542 unsigned short NTBinsSide = NTBins;
1543 unsigned short NTBinsMin = 0;
1544 unsigned short PhiOffset = NPhiBinsSector * sector;
1545 unsigned short TOffset = NTBinsMin;
1546
1547 m_tdriftmax = AdcClockPeriod * NZBinsSide;
1548 thread_pair.data.m_tdriftmax = m_tdriftmax;
1549
1550 thread_pair.data.phibins = NPhiBinsSector;
1551 thread_pair.data.phioffset = PhiOffset;
1552 thread_pair.data.tbins = NTBinsSide;
1553 thread_pair.data.toffset = TOffset;
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578 int rc = 0;
1579
1580 rc = pthread_create(&thread_pair.thread, &attr, ProcessSector, (void *) &thread_pair.data);
1581
1582
1583
1584 if (rc)
1585 {
1586 std::cout << "Error:unable to create thread," << rc << std::endl;
1587 }
1588
1589 if (do_sequential)
1590 {
1591 int rc2 = pthread_join(thread_pair.thread, nullptr);
1592 if (rc2)
1593 {
1594 std::cout << "Error:unable to join," << rc2 << std::endl;
1595 }
1596
1597
1598 const auto &data(thread_pair.data);
1599 const auto hitsetkey = TpcDefs::genHitSetKey(data.layer, data.sector, data.side);
1600
1601
1602 for (uint32_t index = 0; index < data.cluster_vector.size(); ++index)
1603 {
1604
1605 const auto ckey = TrkrDefs::genClusKey(hitsetkey, index);
1606
1607
1608 auto cluster = data.cluster_vector[index];
1609
1610
1611 m_clusterlist->addClusterSpecifyKey(ckey, cluster);
1612 }
1613
1614
1615 for (const auto &[index, hkey] : thread_pair.data.association_vector)
1616 {
1617
1618 const auto ckey = TrkrDefs::genClusKey(hitsetkey, index);
1619
1620
1621 m_clusterhitassoc->addAssoc(ckey, hkey);
1622 }
1623 }
1624
1625 }
1626 }
1627
1628 pthread_attr_destroy(&attr);
1629
1630
1631 if (!do_sequential)
1632 {
1633 for (const auto &thread_pair : threads)
1634 {
1635 int rc2 = pthread_join(thread_pair.thread, nullptr);
1636 if (rc2)
1637 {
1638 std::cout << "Error:unable to join," << rc2 << std::endl;
1639 }
1640
1641
1642 const auto &data(thread_pair.data);
1643 const auto hitsetkey = TpcDefs::genHitSetKey(data.layer, data.sector, data.side);
1644
1645
1646 for (uint32_t index = 0; index < data.cluster_vector.size(); ++index)
1647 {
1648
1649 const auto ckey = TrkrDefs::genClusKey(hitsetkey, index);
1650
1651
1652 auto cluster = data.cluster_vector[index];
1653
1654
1655
1656 m_clusterlist->addClusterSpecifyKey(ckey, cluster);
1657
1658 if (mClusHitsVerbose)
1659 {
1660 for (auto &hit : data.phivec_ClusHitsVerbose[index])
1661 {
1662 mClusHitsVerbose->addPhiHit(hit.first, (float) hit.second);
1663 }
1664 for (auto &hit : data.zvec_ClusHitsVerbose[index])
1665 {
1666 mClusHitsVerbose->addZHit(hit.first, (float) hit.second);
1667 }
1668 mClusHitsVerbose->push_hits(ckey);
1669 }
1670 }
1671
1672
1673 for (const auto &[index, hkey] : thread_pair.data.association_vector)
1674 {
1675
1676 const auto ckey = TrkrDefs::genClusKey(hitsetkey, index);
1677
1678
1679 m_clusterhitassoc->addAssoc(ckey, hkey);
1680 }
1681
1682 for (auto v_hit : thread_pair.data.v_hits)
1683 {
1684 if (_store_hits)
1685 {
1686 m_training->v_hits.emplace_back(*v_hit);
1687 }
1688 delete v_hit;
1689 }
1690 }
1691 }
1692
1693
1694 alignmentTransformationContainer::use_alignment = true;
1695
1696 if (Verbosity() > 0)
1697 {
1698 std::cout << "TPC Clusterizer found " << m_clusterlist->size() << " Clusters " << std::endl;
1699 }
1700 return Fun4AllReturnCodes::EVENT_OK;
1701 }
1702
1703 int TpcClusterizer::End(PHCompositeNode * )
1704 {
1705 return Fun4AllReturnCodes::EVENT_OK;
1706 }