File indexing completed on 2025-08-06 08:18:34
0001 #include "PHTruthClustering.h"
0002
0003 #include <globalvertex/SvtxVertexMap.h>
0004 #include <globalvertex/SvtxVertex_v1.h>
0005
0006
0007 #include <trackbase/TrkrClusterContainerv4.h>
0008 #include <trackbase/TrkrClusterHitAssoc.h>
0009 #include <trackbase/TrkrClusterv2.h>
0010 #include <trackbase/ActsGeometry.h>
0011 #include <trackbase/TrkrDefs.h> // for hitkey, getLayer
0012 #include <trackbase/TrkrHit.h>
0013 #include <trackbase/TrkrHitSet.h>
0014 #include <trackbase/InttDefs.h>
0015 #include <trackbase/MvtxDefs.h>
0016 #include <trackbase/TpcDefs.h>
0017
0018 #include <micromegas/MicromegasDefs.h>
0019
0020 #include <g4main/PHG4TruthInfoContainer.h>
0021 #include <g4main/PHG4VtxPoint.h>
0022 #include <g4main/PHG4Particle.h>
0023 #include <g4main/PHG4Hit.h>
0024 #include <g4main/PHG4HitContainer.h>
0025
0026 #include <g4detectors/PHG4TpcCylinderGeom.h>
0027 #include <g4detectors/PHG4TpcCylinderGeomContainer.h>
0028 #include <g4detectors/PHG4CylinderGeom.h> // for PHG4CylinderGeom
0029 #include <g4detectors/PHG4CylinderGeomContainer.h>
0030
0031 #include <mvtx/CylinderGeom_Mvtx.h>
0032 #include <mvtx/CylinderGeom_MvtxHelper.h>
0033 #include <intt/CylinderGeomIntt.h>
0034 #include <intt/CylinderGeomInttHelper.h>
0035
0036 #include <phool/PHCompositeNode.h>
0037 #include <phool/PHIODataNode.h> // for PHIODataNode
0038 #include <phool/PHNode.h> // for PHNode
0039 #include <phool/PHNodeIterator.h>
0040 #include <phool/PHObject.h> // for PHObject
0041 #include <phool/getClass.h>
0042 #include <phool/phool.h> // for PHWHERE
0043 #include <phool/PHRandomSeed.h>
0044 #include <phool/getClass.h>
0045
0046 #include <fun4all/Fun4AllReturnCodes.h>
0047
0048
0049 #include <gsl/gsl_randist.h>
0050 #include <gsl/gsl_rng.h>
0051
0052 #include <TVector3.h>
0053 #include <TMatrixFfwd.h> // for TMatrixF
0054
0055
0056
0057 #include <iostream> // for operator<<, basic_ostream
0058 #include <set> // for _Rb_tree_iterator, set
0059 #include <utility> // for pair
0060
0061 class PHCompositeNode;
0062
0063 using namespace std;
0064
0065 PHTruthClustering::PHTruthClustering(const std::string& name)
0066 : SubsysReco(name)
0067 {
0068 }
0069
0070 PHTruthClustering::~PHTruthClustering()
0071 {
0072
0073 }
0074
0075 int PHTruthClustering::InitRun(PHCompositeNode* topNode)
0076 {
0077 int ret = GetNodes(topNode);
0078 if (ret != Fun4AllReturnCodes::EVENT_OK) return ret;
0079
0080 for(unsigned int layer = 0; layer < _nlayers_maps; ++layer)
0081 {
0082 clus_err_rphi[layer] = mvtx_clus_err_rphi;
0083 clus_err_z[layer] = mvtx_clus_err_z;
0084 }
0085 for(unsigned int layer = _nlayers_maps; layer < _nlayers_maps + _nlayers_intt; ++layer)
0086 {
0087 clus_err_rphi[layer] = intt_clus_err_rphi;
0088 clus_err_z[layer] = intt_clus_err_z;
0089 }
0090 for(unsigned int layer = _nlayers_maps + _nlayers_intt; layer < _nlayers_maps + _nlayers_intt + 16; ++layer)
0091 {
0092 clus_err_rphi[layer] = tpc_inner_clus_err_rphi;
0093 clus_err_z[layer] = tpc_inner_clus_err_z;
0094 }
0095 for(unsigned int layer = _nlayers_maps + _nlayers_intt + 16; layer < _nlayers_maps + _nlayers_intt +_nlayers_tpc; ++layer)
0096 {
0097 clus_err_rphi[layer] = tpc_outer_clus_err_rphi;
0098 clus_err_z[layer] = tpc_outer_clus_err_z;
0099 }
0100 for(unsigned int layer = _nlayers_maps + _nlayers_intt +_nlayers_tpc; layer < _nlayers_maps + _nlayers_intt +_nlayers_tpc + 1; ++layer)
0101 {
0102 clus_err_rphi[layer] = mms_layer55_clus_err_rphi;
0103 clus_err_z[layer] = mms_layer55_clus_err_z;
0104 }
0105
0106 for(unsigned int layer = _nlayers_maps + _nlayers_intt +_nlayers_tpc + 1; layer < _nlayers_maps + _nlayers_intt +_nlayers_tpc + 2; ++layer)
0107 {
0108 clus_err_rphi[layer] = mms_layer56_clus_err_rphi;
0109 clus_err_z[layer] = mms_layer56_clus_err_z;
0110 }
0111
0112 if(Verbosity() > 3)
0113 {
0114 for(unsigned int layer = 0; layer < _nlayers_maps + _nlayers_intt +_nlayers_tpc + 2; ++layer)
0115 std::cout << " layer " << layer << " clus_err _rphi " << clus_err_rphi[layer] << " clus_err_z " << clus_err_z[layer] << std::endl;
0116 }
0117
0118 return Fun4AllReturnCodes::EVENT_OK;
0119 }
0120
0121 int PHTruthClustering::process_event(PHCompositeNode* topNode)
0122 {
0123 if (Verbosity() > 0)
0124 cout << "Filling truth cluster node " << endl;
0125
0126
0127 auto m_clusterlist = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER_TRUTH");
0128 if (!m_clusterlist)
0129 {
0130 cout << PHWHERE << " ERROR: Can't find TRKR_CLUSTER_TRUTH" << endl;
0131 return Fun4AllReturnCodes::ABORTRUN;
0132 }
0133
0134 PHG4TruthInfoContainer* truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
0135 PHG4TruthInfoContainer::ConstRange range = truthinfo->GetParticleRange();
0136 for (PHG4TruthInfoContainer::ConstIterator iter = range.first;
0137 iter != range.second;
0138 ++iter)
0139 {
0140 PHG4Particle* g4particle = iter->second;
0141
0142 float gtrackID = g4particle->get_track_id();
0143
0144
0145 if(_primary_clusters_only && gtrackID < 0) continue;
0146
0147 float gflavor = g4particle->get_pid();
0148
0149 int gembed = 0;
0150 bool is_primary = false;
0151 if (g4particle->get_parent_id() == 0)
0152 {
0153
0154 is_primary = true;
0155 gembed = truthinfo->isEmbeded(g4particle->get_track_id());
0156 }
0157 else
0158 {
0159 PHG4Particle* primary = truthinfo->GetPrimaryParticle(g4particle->get_primary_id());
0160 gembed = truthinfo->isEmbeded(primary->get_track_id());
0161 }
0162
0163 if(Verbosity() > 0)
0164 cout << PHWHERE << " PHG4Particle ID " << gtrackID << " gflavor " << gflavor << " is_primary " << is_primary
0165 << " gembed " << gembed << endl;
0166
0167
0168 auto truth_clusters = all_truth_clusters(g4particle);
0169
0170
0171 if(Verbosity() > 0) std::cout << " Truth cluster summary for g4particle " << g4particle->get_track_id() << " by layer: " << std::endl;
0172 for ( const auto& [ckey, gclus]:truth_clusters )
0173 {
0174 float gx = gclus->getX();
0175 float gy = gclus->getY();
0176 float gz = gclus->getZ();
0177 float ng4hits = gclus->getAdc();
0178
0179 TVector3 gpos(gx, gy, gz);
0180 float gr = sqrt(gx*gx+gy*gy);
0181 float gphi = gpos.Phi();
0182 float geta = gpos.Eta();
0183
0184 float gphisize = gclus->getSize(1,1);
0185 float gzsize = gclus->getSize(2,2);
0186
0187 const unsigned int trkrId = TrkrDefs::getTrkrId(ckey);
0188
0189 if(Verbosity() > 0)
0190 {
0191 const unsigned int layer = TrkrDefs::getLayer( ckey );
0192 std::cout << PHWHERE << " **** truth: layer " << layer << " truth cluster key " << ckey << " ng4hits " << ng4hits << std::endl;
0193 std::cout << " gr " << gr << " gx " << gx << " gy " << gy << " gz " << gz
0194 << " gphi " << gphi << " geta " << geta << " gphisize " << gphisize << " gzsize " << gzsize << endl;
0195 }
0196
0197 if(trkrId == TrkrDefs::tpcId)
0198 {
0199
0200 m_clusterlist->addClusterSpecifyKey(ckey, gclus);
0201 }
0202 }
0203 }
0204
0205
0206 for(const auto& hitsetkey:_reco_cluster_map->getHitSetKeys())
0207 {
0208 auto range_A = _reco_cluster_map->getClusters(hitsetkey);
0209 unsigned int trkrid = TrkrDefs::getTrkrId(hitsetkey);
0210
0211
0212 if(trkrid == TrkrDefs::tpcId) continue;
0213
0214 for( auto clusIter = range_A.first; clusIter != range_A.second; ++clusIter ){
0215 TrkrDefs::cluskey cluskey = clusIter->first;
0216
0217
0218 TrkrCluster* cluster = (TrkrCluster*) clusIter->second->CloneMe();
0219
0220 unsigned int layer = TrkrDefs::getLayer(cluskey);
0221 if (Verbosity() >= 3)
0222 {
0223 std::cout << PHWHERE <<" copying cluster in layer " << layer << " from reco clusters to truth clusters " << std::endl;;
0224 cluster->identify();
0225 }
0226
0227 m_clusterlist->addClusterSpecifyKey(cluskey, cluster);
0228 }
0229 }
0230
0231 if(Verbosity() >=3)
0232 {
0233 std::cout << "Final TRKR_CLUSTER_TRUTH clusters:";
0234 m_clusterlist->identify();
0235 }
0236
0237 return Fun4AllReturnCodes::EVENT_OK;
0238 }
0239
0240
0241 std::map<TrkrDefs::cluskey, TrkrCluster* > PHTruthClustering::all_truth_clusters(PHG4Particle* particle)
0242 {
0243
0244 std::set<PHG4Hit*> g4hits = all_truth_hits(particle);
0245
0246 if(Verbosity() > 3)
0247 std::cout << PHWHERE << " Truth clustering for particle " << particle->get_track_id() << " with ng4hits " << g4hits.size() << std::endl;;
0248
0249
0250
0251 std::map<TrkrDefs::cluskey, TrkrCluster*> truth_clusters;
0252 if(g4hits.empty()) return truth_clusters;
0253
0254
0255
0256 unsigned int layer;
0257 for(layer = 0; layer < _nlayers_maps + _nlayers_intt + _nlayers_tpc +_nlayers_mms; ++layer)
0258 {
0259 float gx = NAN;
0260 float gy = NAN;
0261 float gz = NAN;
0262 float gt = NAN;
0263 float gedep = NAN;
0264
0265 std::vector<PHG4Hit*> contributing_hits;
0266 std::vector<double> contributing_hits_energy;
0267 std::vector<std::vector<double>> contributing_hits_entry;
0268 std::vector<std::vector<double>> contributing_hits_exit;
0269 LayerClusterG4Hits(g4hits, contributing_hits, contributing_hits_energy, contributing_hits_entry, contributing_hits_exit, layer, gx, gy, gz, gt, gedep);
0270 if(!(gedep > 0)) continue;
0271
0272
0273
0274 TrkrDefs::cluskey ckey;
0275 if(layer >= _nlayers_maps + _nlayers_intt && layer < _nlayers_maps + _nlayers_intt + _nlayers_tpc)
0276 {
0277 unsigned int side = 0;
0278 if(gz > 0) side = 1;
0279
0280 unsigned int sector = getTpcSector(gx, gy);
0281 ckey = TpcDefs::genClusKey(layer, sector, side, iclus);
0282 }
0283 else if(layer < _nlayers_maps)
0284 {
0285 unsigned int stave = 0;
0286 unsigned int chip = 0;
0287 unsigned int strobe = 0;
0288 ckey = MvtxDefs::genClusKey(layer, stave, chip, strobe, iclus);
0289 }
0290 else if(layer >= _nlayers_maps && layer < _nlayers_maps + _nlayers_intt)
0291 {
0292
0293 unsigned int ladderzid = 0;
0294 unsigned int ladderphiid = 0;
0295 int crossing = 0;
0296 ckey = InttDefs::genClusKey(layer, ladderzid, ladderphiid,crossing,iclus);
0297 }
0298 else if(layer >= _nlayers_maps + _nlayers_intt + _nlayers_tpc)
0299 {
0300 unsigned int tile = 0;
0301 MicromegasDefs::SegmentationType segtype;
0302 segtype = MicromegasDefs::SegmentationType::SEGMENTATION_PHI;
0303 TrkrDefs::hitsetkey hkey = MicromegasDefs::genHitSetKey(layer, segtype, tile);
0304 ckey = TrkrDefs::genClusKey(hkey, iclus);
0305 }
0306 else
0307 {
0308 std::cout << PHWHERE << "Bad layer number: " << layer << std::endl;
0309 continue;
0310 }
0311
0312 auto clus = new TrkrClusterv2;
0313 iclus++;
0314
0315
0316 unsigned int adc_output = getAdcValue(gedep);
0317
0318 clus->setAdc(adc_output);
0319 clus->setPosition(0, gx);
0320 clus->setPosition(1, gy);
0321 clus->setPosition(2, gz);
0322 clus->setGlobal();
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 float g4phisize = NAN;
0334 float g4zsize = NAN;
0335 G4ClusterSize(ckey, layer, contributing_hits_entry, contributing_hits_exit, g4phisize, g4zsize);
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346 double clusphi = atan2(gy, gx);
0347
0348 TMatrixF DIM(3, 3);
0349 DIM[0][0] = 0.0;
0350 DIM[0][1] = 0.0;
0351 DIM[0][2] = 0.0;
0352 DIM[1][0] = 0.0;
0353 DIM[1][1] = pow(0.5 * g4phisize, 2);
0354 DIM[1][2] = 0.0;
0355 DIM[2][0] = 0.0;
0356 DIM[2][1] = 0.0;
0357 DIM[2][2] = pow(0.5 * g4zsize,2);
0358
0359 TMatrixF ERR(3, 3);
0360 ERR[0][0] = 0.0;
0361 ERR[0][1] = 0.0;
0362 ERR[0][2] = 0.0;
0363 ERR[1][0] = 0.0;
0364 ERR[1][1] = pow(clus_err_rphi[layer], 2);
0365 ERR[1][2] = 0.0;
0366 ERR[2][0] = 0.0;
0367 ERR[2][1] = 0.0;
0368 ERR[2][2] = pow(clus_err_z[layer], 2);
0369
0370 TMatrixF ROT(3, 3);
0371 ROT[0][0] = cos(clusphi);
0372 ROT[0][1] = -sin(clusphi);
0373 ROT[0][2] = 0.0;
0374 ROT[1][0] = sin(clusphi);
0375 ROT[1][1] = cos(clusphi);
0376 ROT[1][2] = 0.0;
0377 ROT[2][0] = 0.0;
0378 ROT[2][1] = 0.0;
0379 ROT[2][2] = 1.0;
0380
0381 TMatrixF ROT_T(3, 3);
0382 ROT_T.Transpose(ROT);
0383
0384 TMatrixF COVAR_DIM(3, 3);
0385 COVAR_DIM = ROT * DIM * ROT_T;
0386
0387 clus->setSize(0, 0, COVAR_DIM[0][0]);
0388 clus->setSize(0, 1, COVAR_DIM[0][1]);
0389 clus->setSize(0, 2, COVAR_DIM[0][2]);
0390 clus->setSize(1, 0, COVAR_DIM[1][0]);
0391 clus->setSize(1, 1, COVAR_DIM[1][1]);
0392 clus->setSize(1, 2, COVAR_DIM[1][2]);
0393 clus->setSize(2, 0, COVAR_DIM[2][0]);
0394 clus->setSize(2, 1, COVAR_DIM[2][1]);
0395 clus->setSize(2, 2, COVAR_DIM[2][2]);
0396
0397
0398 TMatrixF COVAR_ERR(3, 3);
0399 COVAR_ERR = ROT * ERR * ROT_T;
0400
0401 clus->setError(0, 0, COVAR_ERR[0][0]);
0402 clus->setError(0, 1, COVAR_ERR[0][1]);
0403 clus->setError(0, 2, COVAR_ERR[0][2]);
0404 clus->setError(1, 0, COVAR_ERR[1][0]);
0405 clus->setError(1, 1, COVAR_ERR[1][1]);
0406 clus->setError(1, 2, COVAR_ERR[1][2]);
0407 clus->setError(2, 0, COVAR_ERR[2][0]);
0408 clus->setError(2, 1, COVAR_ERR[2][1]);
0409 clus->setError(2, 2, COVAR_ERR[2][2]);
0410
0411 if(Verbosity() > 0)
0412 {
0413 std::cout << " layer " << layer << " cluskey " << ckey << " cluster phi " << clusphi << " local cluster error rphi " << clus_err_rphi[layer]
0414 << " z " << clus_err_z[layer] << std::endl;
0415 if(Verbosity() > 10)
0416 {
0417 std::cout << " global covariance matrix:" << std::endl;
0418 for(int i1=0;i1<3;++i1)
0419 for(int i2=0;i2<3;++i2)
0420 std::cout << " " << i1 << " " << i2 << " cov " << clus->getError(i1,i2) << std::endl;
0421 }
0422 }
0423
0424 truth_clusters.insert(std::make_pair(ckey, clus));
0425
0426 }
0427
0428 return truth_clusters;
0429 }
0430
0431 void PHTruthClustering::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)
0432 {
0433 bool use_geo = true;
0434
0435
0436
0437 float gx = 0.0;
0438 float gy = 0.0;
0439 float gz = 0.0;
0440 float gr = 0.0;
0441 float gt = 0.0;
0442 float gwt = 0.0;
0443
0444 if (layer >= _nlayers_maps + _nlayers_intt && layer < _nlayers_maps + _nlayers_intt + _nlayers_tpc)
0445 {
0446
0447
0448
0449
0450
0451
0452 PHG4TpcCylinderGeom* GeoLayer = _tpc_geom_container->GetLayerCellGeom(layer);
0453
0454
0455 float rbin = GeoLayer->get_radius() - GeoLayer->get_thickness() / 2.0;
0456 float rbout = GeoLayer->get_radius() + GeoLayer->get_thickness() / 2.0;
0457
0458 if(Verbosity() > 3)
0459 cout << " PHTruthClustering::LayerCluster hits for layer " << layer << " with rbin " << rbin << " rbout " << rbout << endl;
0460
0461
0462 for (std::set<PHG4Hit*>::iterator iter = truth_hits.begin();
0463 iter != truth_hits.end();
0464 ++iter)
0465 {
0466
0467 PHG4Hit* this_g4hit = *iter;
0468 float rbegin = sqrt(this_g4hit->get_x(0) * this_g4hit->get_x(0) + this_g4hit->get_y(0) * this_g4hit->get_y(0));
0469 float rend = sqrt(this_g4hit->get_x(1) * this_g4hit->get_x(1) + this_g4hit->get_y(1) * this_g4hit->get_y(1));
0470
0471
0472
0473 float xl[2];
0474 float yl[2];
0475 float zl[2];
0476
0477 if (rbegin < rend)
0478 {
0479 xl[0] = this_g4hit->get_x(0);
0480 yl[0] = this_g4hit->get_y(0);
0481 zl[0] = this_g4hit->get_z(0);
0482 xl[1] = this_g4hit->get_x(1);
0483 yl[1] = this_g4hit->get_y(1);
0484 zl[1] = this_g4hit->get_z(1);
0485 }
0486 else
0487 {
0488 xl[0] = this_g4hit->get_x(1);
0489 yl[0] = this_g4hit->get_y(1);
0490 zl[0] = this_g4hit->get_z(1);
0491 xl[1] = this_g4hit->get_x(0);
0492 yl[1] = this_g4hit->get_y(0);
0493 zl[1] = this_g4hit->get_z(0);
0494 swap(rbegin, rend);
0495
0496 }
0497
0498
0499 if (rbegin < rbin && rend < rbin)
0500 continue;
0501 if (rbegin > rbout && rend > rbout)
0502 continue;
0503
0504
0505 if(Verbosity() > 3)
0506 {
0507 cout << " keep g4hit with rbegin " << rbegin << " rend " << rend
0508 << " xbegin " << xl[0] << " xend " << xl[1]
0509 << " ybegin " << yl[0] << " yend " << yl[1]
0510 << " zbegin " << zl[0] << " zend " << zl[1]
0511 << endl;
0512 }
0513
0514
0515 float xin = xl[0];
0516 float yin = yl[0];
0517 float zin = zl[0];
0518 float xout = xl[1];
0519 float yout = yl[1];
0520 float zout = zl[1];
0521
0522 float time = std::numeric_limits<float>::quiet_NaN();
0523
0524 if (rbegin < rbin)
0525 {
0526
0527 time = line_circle_intersection(xl, yl, zl, rbin);
0528 if (time > 0)
0529 {
0530 xin = xl[0] + time * (xl[1] - xl[0]);
0531 yin = yl[0] + time * (yl[1] - yl[0]);
0532 zin = zl[0] + time * (zl[1] - zl[0]);
0533 }
0534 }
0535
0536 if (rend > rbout)
0537 {
0538
0539 time = line_circle_intersection(xl, yl, zl, rbout);
0540 if (time > 0)
0541 {
0542 xout = xl[0] + time * (xl[1] - xl[0]);
0543 yout = yl[0] + time * (yl[1] - yl[0]);
0544 zout = zl[0] + time * (zl[1] - zl[0]);
0545 }
0546 }
0547
0548 double rin = sqrt(xin*xin + yin*yin);
0549 double rout = sqrt(xout*xout + yout*yout);
0550
0551
0552 double efrac = this_g4hit->get_edep() * (rout - rin) / (rend - rbegin);
0553 gx += (xin + xout) * 0.5 * efrac;
0554 gy += (yin + yout) * 0.5 * efrac;
0555 gz += (zin + zout) * 0.5 * efrac;
0556 gt += this_g4hit->get_avg_t() * efrac;
0557 gr += (rin + rout) * 0.5 * efrac;
0558 gwt += efrac;
0559
0560 if(Verbosity() > 3)
0561 {
0562 cout << " rin " << rin << " rout " << rout
0563 << " xin " << xin << " xout " << xout << " yin " << yin << " yout " << yout << " zin " << zin << " zout " << zout
0564 << " edep " << this_g4hit->get_edep()
0565 << " this_edep " << efrac << endl;
0566 cout << " xavge " << (xin+xout) * 0.5 << " yavge " << (yin+yout) * 0.5 << " zavge " << (zin+zout) * 0.5 << " ravge " << (rin+rout) * 0.5
0567 << endl;
0568 }
0569
0570
0571 std::vector<double> entry_loc;
0572 entry_loc.push_back(xin);
0573 entry_loc.push_back(yin);
0574 entry_loc.push_back(zin);
0575 std::vector<double> exit_loc;
0576 exit_loc.push_back(xout);
0577 exit_loc.push_back(yout);
0578 exit_loc.push_back(zout);
0579
0580
0581 contributing_hits.push_back(this_g4hit);
0582 contributing_hits_energy.push_back( this_g4hit->get_edep() * (zout - zin) / (zl[1] - zl[0]) );
0583 contributing_hits_entry.push_back(entry_loc);
0584 contributing_hits_exit.push_back(exit_loc);
0585
0586 }
0587
0588 if(gwt == 0)
0589 {
0590 e = gwt;
0591 return;
0592 }
0593
0594 gx /= gwt;
0595 gy /= gwt;
0596 gz /= gwt;
0597 gr = (rbin + rbout) * 0.5;
0598 gt /= gwt;
0599
0600 if(Verbosity() > 3)
0601 {
0602 cout << " weighted means: gx " << gx << " gy " << gy << " gz " << gz << " gr " << gr << " e " << gwt << endl;
0603 }
0604
0605 if(use_geo)
0606 {
0607
0608
0609 float rentry = 999.0;
0610 float xentry = 999.0;
0611 float yentry = 999.0;
0612 float zentry = 999.0;
0613 float rexit = - 999.0;
0614 float xexit = -999.0;
0615 float yexit = -999.0;
0616 float zexit = -999.0;
0617
0618 for(unsigned int ientry = 0; ientry < contributing_hits_entry.size(); ++ientry)
0619 {
0620 float tmpx = contributing_hits_entry[ientry][0];
0621 float tmpy = contributing_hits_entry[ientry][1];
0622 float tmpr = sqrt(tmpx*tmpx + tmpy*tmpy);
0623
0624 if(tmpr < rentry)
0625 {
0626 rentry = tmpr;
0627 xentry = contributing_hits_entry[ientry][0];
0628 yentry = contributing_hits_entry[ientry][1];
0629 zentry = contributing_hits_entry[ientry][2];
0630 }
0631
0632 tmpx = contributing_hits_exit[ientry][0];
0633 tmpy = contributing_hits_exit[ientry][1];
0634 tmpr = sqrt(tmpx*tmpx + tmpy*tmpy);
0635
0636 if(tmpr > rexit)
0637 {
0638 rexit = tmpr;
0639 xexit = contributing_hits_exit[ientry][0];
0640 yexit = contributing_hits_exit[ientry][1];
0641 zexit = contributing_hits_exit[ientry][2];
0642 }
0643 }
0644
0645 float geo_r = (rentry+rexit)*0.5;
0646 float geo_x = (xentry+xexit)*0.5;
0647 float geo_y = (yentry+yexit)*0.5;
0648 float geo_z = (zentry+zexit)*0.5;
0649
0650 if(rexit > 0)
0651 {
0652 gx = geo_x;
0653 gy = geo_y;
0654 gz = geo_z;
0655 gr = geo_r;
0656 }
0657
0658
0659 if(Verbosity() > 3)
0660 {
0661 cout << " rentry " << rentry << " rexit " << rexit
0662 << " xentry " << xentry << " xexit " << xexit << " yentry " << yentry << " yexit " << yexit << " zentry " << zentry << " zexit " << zexit << endl;
0663
0664 cout << " geometric means: geo_x " << geo_x << " geo_y " << geo_y << " geo_z " << geo_z << " geo r " << geo_r << " e " << gwt << endl << endl;
0665 }
0666 }
0667
0668 }
0669 else
0670 {
0671
0672 for (std::set<PHG4Hit*>::iterator iter = truth_hits.begin();
0673 iter != truth_hits.end();
0674 ++iter)
0675 {
0676
0677 PHG4Hit* this_g4hit = *iter;
0678
0679 if(this_g4hit->get_layer() != (unsigned int) layer) continue;
0680
0681 gx = this_g4hit->get_avg_x();
0682 gy = this_g4hit->get_avg_y();
0683 gz = this_g4hit->get_avg_z();
0684 gt = this_g4hit->get_avg_t();
0685 gwt += this_g4hit->get_edep();
0686
0687
0688 std::vector<double> entry_loc;
0689 entry_loc.push_back(this_g4hit->get_x(0));
0690 entry_loc.push_back(this_g4hit->get_y(0));
0691 entry_loc.push_back(this_g4hit->get_z(0));
0692 std::vector<double> exit_loc;
0693 exit_loc.push_back(this_g4hit->get_x(1));
0694 exit_loc.push_back(this_g4hit->get_y(1));
0695 exit_loc.push_back(this_g4hit->get_z(1));
0696
0697
0698 contributing_hits.push_back(this_g4hit);
0699 contributing_hits_energy.push_back( this_g4hit->get_edep() );
0700 contributing_hits_entry.push_back(entry_loc);
0701 contributing_hits_exit.push_back(exit_loc);
0702 }
0703 }
0704
0705 x = gx;
0706 y = gy;
0707 z = gz;
0708 t = gt;
0709 e = gwt;
0710
0711 return;
0712 }
0713
0714 void PHTruthClustering::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)
0715 {
0716
0717
0718 double inner_radius = 100.;
0719 double inner_x = NAN;
0720 double inner_y = NAN;
0721 double inner_z = NAN;;
0722
0723 double outer_radius = 0.;
0724 double outer_x = NAN;
0725 double outer_y = NAN;
0726 double outer_z = NAN;
0727
0728 for(unsigned int ihit=0;ihit<contributing_hits_entry.size(); ++ihit)
0729 {
0730 double rad1 = sqrt(pow(contributing_hits_entry[ihit][0], 2) + pow(contributing_hits_entry[ihit][1], 2));
0731 if(rad1 < inner_radius)
0732 {
0733 inner_radius = rad1;
0734 inner_x = contributing_hits_entry[ihit][0];
0735 inner_y = contributing_hits_entry[ihit][1];
0736 inner_z = contributing_hits_entry[ihit][2];
0737 }
0738
0739 double rad2 = sqrt(pow(contributing_hits_exit[ihit][0], 2) + pow(contributing_hits_exit[ihit][1], 2));
0740 if(rad2 > outer_radius)
0741 {
0742 outer_radius = rad2;
0743 outer_x = contributing_hits_exit[ihit][0];
0744 outer_y = contributing_hits_exit[ihit][1];
0745 outer_z = contributing_hits_exit[ihit][2];
0746 }
0747 }
0748
0749 double inner_phi = atan2(inner_y, inner_x);
0750 double outer_phi = atan2(outer_y, outer_x);
0751 double avge_z = (outer_z + inner_z) / 2.0;
0752
0753
0754
0755 double sigmas = 2.0;
0756
0757 double radius = (inner_radius + outer_radius)/2.;
0758 if(radius > 28 && radius < 80)
0759 {
0760 PHG4TpcCylinderGeom*layergeom = _tpc_geom_container->GetLayerCellGeom(layer);
0761
0762 double tpc_length = 211.0;
0763 double drift_velocity = 8.0 / 1000.0;
0764
0765
0766
0767 double diffusion_trans = 0.006;
0768 double phidiffusion = diffusion_trans * sqrt(tpc_length / 2. - fabs(avge_z));
0769
0770 double added_smear_trans = 0.085;
0771 double gem_spread = 0.04;
0772
0773 if(outer_phi < inner_phi) swap(outer_phi, inner_phi);
0774
0775
0776 double g4max_phi = outer_phi + sigmas * sqrt( pow(phidiffusion, 2) + pow(added_smear_trans, 2) + pow(gem_spread, 2) ) / radius;
0777 double g4min_phi = inner_phi - sigmas * sqrt( pow(phidiffusion, 2) + pow(added_smear_trans, 2) + pow(gem_spread, 2) ) / radius;
0778
0779
0780 unsigned int phibinmin = layergeom->get_phibin(g4min_phi);
0781 unsigned int phibinmax = layergeom->get_phibin(g4max_phi);
0782 unsigned int phibinwidth = phibinmax - phibinmin + 1;
0783 g4phisize = (double) phibinwidth * layergeom->get_phistep() * layergeom->get_radius();
0784
0785
0786
0787 double g4max_z = 0;
0788 double g4min_z = 0;
0789
0790 outer_z = fabs(outer_z);
0791 inner_z = fabs(inner_z);
0792
0793 double diffusion_long = 0.015;
0794 double zdiffusion = diffusion_long * sqrt(tpc_length / 2. - fabs(avge_z)) ;
0795 double zshaping_lead = 32.0 * drift_velocity;
0796 double zshaping_tail = 48.0 * drift_velocity;
0797 double added_smear_long = 0.105;
0798
0799
0800 if(outer_z < inner_z) swap(outer_z, inner_z);
0801 g4max_z = outer_z + sigmas*sqrt(pow(zdiffusion,2) + pow(added_smear_long,2) + pow(zshaping_lead, 2));
0802 g4min_z = inner_z - sigmas*sqrt(pow(zdiffusion,2) + pow(added_smear_long,2) + pow(zshaping_tail, 2));
0803
0804
0805 unsigned int binmin = layergeom->get_zbin(g4min_z);
0806 unsigned int binmax = layergeom->get_zbin(g4max_z);
0807 if(binmax < binmin) swap(binmax, binmin);
0808 unsigned int binwidth = binmax - binmin + 1;
0809
0810
0811 g4zsize = (double) binwidth * layergeom->get_zstep();
0812 }
0813 else if(radius > 5 && radius < 20)
0814 {
0815
0816
0817 CylinderGeomIntt *layergeom = dynamic_cast<CylinderGeomIntt *>(_intt_geom_container->GetLayerGeom(layer));
0818
0819
0820 double world_inner[3] = {inner_x, inner_y, inner_z};
0821 TVector3 world_inner_vec = {inner_x, inner_y, inner_z};
0822
0823 int segment_z_bin, segment_phi_bin;
0824 layergeom->find_indices_from_world_location(segment_z_bin, segment_phi_bin, world_inner);
0825 auto hitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0826 auto surf = _tgeometry->maps().getSiliconSurface(hitsetkey);
0827 TVector3 local_inner_vec = CylinderGeomInttHelper::get_local_from_world_coords(surf, _tgeometry, world_inner_vec);
0828 double yin = local_inner_vec[1];
0829 double zin = local_inner_vec[2];
0830 int strip_y_index, strip_z_index;
0831 layergeom->find_strip_index_values(segment_z_bin, yin, zin, strip_y_index, strip_z_index);
0832
0833
0834 double world_outer[3] = {outer_x, outer_y, outer_z};
0835 TVector3 world_outer_vec = {outer_x, outer_y, outer_z};
0836
0837 layergeom->find_indices_from_world_location(segment_z_bin, segment_phi_bin, world_outer);
0838 auto outerhitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0839 auto outersurf = _tgeometry->maps().getSiliconSurface(outerhitsetkey);
0840 TVector3 local_outer_vec = CylinderGeomInttHelper::get_local_from_world_coords(outersurf,_tgeometry, world_outer_vec);
0841 double yout = local_outer_vec[1];
0842 double zout = local_outer_vec[2];
0843 int strip_y_index_out, strip_z_index_out;
0844 layergeom->find_strip_index_values(segment_z_bin, yout, zout, strip_y_index_out, strip_z_index_out);
0845
0846 int strips = abs(strip_y_index_out - strip_y_index) + 1;
0847 int cols = abs(strip_z_index_out - strip_z_index) + 1;
0848
0849
0850 double strip_width = (double) strips * layergeom->get_strip_y_spacing();
0851 double strip_length = (double) cols * layergeom->get_strip_z_spacing();
0852
0853 g4phisize = strip_width;
0854 g4zsize = strip_length;
0855
0856
0857
0858
0859
0860
0861 }
0862 else if(radius > 80)
0863 {
0864
0865 g4phisize = 300e-04;
0866 g4zsize = 300e-04;
0867 }
0868 else
0869 {
0870 unsigned int stave, stave_outer;
0871 unsigned int chip, chip_outer;
0872 int row, row_outer;
0873 int column, column_outer;
0874
0875
0876 double max_diffusion_radius = 25.0e-4;
0877 double min_diffusion_radius = 8.0e-4;
0878
0879 CylinderGeom_Mvtx *layergeom = dynamic_cast<CylinderGeom_Mvtx *>(_mvtx_geom_container->GetLayerGeom(layer));
0880
0881 TVector3 world_inner = {inner_x, inner_y, inner_z};
0882 std::vector<double> world_inner_vec = { world_inner[0], world_inner[1], world_inner[2] };
0883 layergeom->get_sensor_indices_from_world_coords(world_inner_vec, stave, chip);
0884 auto ihitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0885 auto isurf = _tgeometry->maps().getSiliconSurface(ihitsetkey);
0886 TVector3 local_inner = CylinderGeom_MvtxHelper::get_local_from_world_coords(isurf,_tgeometry, world_inner);
0887
0888 TVector3 world_outer = {outer_x, outer_y, outer_z};
0889 std::vector<double> world_outer_vec = { world_outer[0], world_outer[1], world_outer[2] };
0890 layergeom->get_sensor_indices_from_world_coords(world_outer_vec, stave_outer, chip_outer);
0891 auto ohitsetkey = TrkrDefs::getHitSetKeyFromClusKey(ckey);
0892 auto osurf = _tgeometry->maps().getSiliconSurface(ohitsetkey);
0893 TVector3 local_outer = CylinderGeom_MvtxHelper::get_local_from_world_coords(osurf,_tgeometry, world_outer);
0894
0895 double diff = max_diffusion_radius * 0.6;
0896 if(local_outer[0] < local_inner[0]) {diff = -diff;}
0897 local_outer[0] += diff;
0898 local_inner[0] -= diff;
0899
0900 double diff_outer = min_diffusion_radius * 0.6;
0901 if(local_outer[2] < local_inner[2]) {diff_outer = -diff_outer;}
0902 local_outer[2] += diff_outer;
0903 local_inner[2] -= diff_outer;
0904
0905 layergeom->get_pixel_from_local_coords(local_inner, row, column);
0906 layergeom->get_pixel_from_local_coords(local_outer, row_outer, column_outer);
0907
0908 if(row_outer < row) swap(row_outer, row);
0909 unsigned int rows = row_outer - row + 1;
0910 g4phisize = (double) rows * layergeom->get_pixel_x();
0911
0912 if(column_outer < column) swap(column_outer, column);
0913 unsigned int columns = column_outer - column + 1;
0914 g4zsize = (double) columns * layergeom->get_pixel_z();
0915
0916
0917
0918
0919
0920
0921
0922 }
0923 }
0924
0925 std::set<PHG4Hit*> PHTruthClustering::all_truth_hits(PHG4Particle* particle)
0926 {
0927 std::set<PHG4Hit*> truth_hits;
0928
0929
0930 if (_g4hits_svtx)
0931 {
0932 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_svtx->getHits().first;
0933 g4iter != _g4hits_svtx->getHits().second;
0934 ++g4iter)
0935 {
0936 PHG4Hit* g4hit = g4iter->second;
0937 if (g4hit->get_trkid() == particle->get_track_id())
0938 {
0939 truth_hits.insert(g4hit);
0940 }
0941 }
0942 }
0943
0944
0945 if (_g4hits_tracker)
0946 {
0947 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_tracker->getHits().first;
0948 g4iter != _g4hits_tracker->getHits().second;
0949 ++g4iter)
0950 {
0951 PHG4Hit* g4hit = g4iter->second;
0952 if (g4hit->get_trkid() == particle->get_track_id())
0953 {
0954 truth_hits.insert(g4hit);
0955 }
0956 }
0957 }
0958
0959
0960 if (_g4hits_maps)
0961 {
0962 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_maps->getHits().first;
0963 g4iter != _g4hits_maps->getHits().second;
0964 ++g4iter)
0965 {
0966 PHG4Hit* g4hit = g4iter->second;
0967 if (g4hit->get_trkid() == particle->get_track_id())
0968 {
0969 truth_hits.insert(g4hit);
0970 }
0971 }
0972 }
0973
0974
0975 if (_g4hits_mms)
0976 {
0977 for (PHG4HitContainer::ConstIterator g4iter = _g4hits_mms->getHits().first;
0978 g4iter != _g4hits_mms->getHits().second;
0979 ++g4iter)
0980 {
0981 PHG4Hit* g4hit = g4iter->second;
0982 if (g4hit->get_trkid() == particle->get_track_id())
0983 {
0984 truth_hits.insert(g4hit);
0985 }
0986 }
0987 }
0988
0989 return truth_hits;
0990 }
0991
0992 float PHTruthClustering::line_circle_intersection(float x[], float y[], float z[], float radius)
0993 {
0994
0995
0996
0997
0998
0999
1000
1001
1002 float A = (x[1] - x[0]) * (x[1] - x[0]) + (y[1] - y[0]) * (y[1] - y[0]);
1003 float B = 2.0 * x[0] * (x[1] - x[0]) + 2.0 * y[0] * (y[1] - y[0]);
1004 float C = x[0] * x[0] + y[0] * y[0] - radius * radius;
1005 float tup = (-B + sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
1006 float tdn = (-B - sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
1007
1008
1009 float t;
1010 if (tdn >= -0.0e-4 && tdn <= 1.0004)
1011 t = tdn;
1012 else if (tup >= -0.0e-4 && tup <= 1.0004)
1013 t = tup;
1014 else
1015 {
1016 cout << PHWHERE << " **** Oops! No valid solution for tup or tdn, tdn = " << tdn << " tup = " << tup << endl;
1017 cout << " radius " << radius << " rbegin " << sqrt(x[0] * x[0] + y[0] * y[0]) << " rend " << sqrt(x[1] * x[1] + y[1] * y[1]) << endl;
1018 cout << " x0 " << x[0] << " x1 " << x[1] << endl;
1019 cout << " y0 " << y[0] << " y1 " << y[1] << endl;
1020 cout << " z0 " << z[0] << " z1 " << z[1] << endl;
1021 cout << " A " << A << " B " << B << " C " << C << endl;
1022
1023 t = -1;
1024 }
1025
1026 return t;
1027 }
1028 unsigned int PHTruthClustering::getTpcSector(double x, double y)
1029 {
1030 double phi = atan2(y, x);
1031 unsigned int sector = (int) (12.0 * (phi + M_PI) / (2.0 * M_PI) );
1032 return sector;
1033 }
1034
1035 unsigned int PHTruthClustering::getAdcValue(double gedep)
1036 {
1037
1038
1039
1040 double Ne_dEdx = 1.56;
1041 double CF4_dEdx = 7.00;
1042 double Ne_NTotal = 43;
1043 double CF4_NTotal = 100;
1044 double Tpc_NTot = 0.5*Ne_NTotal + 0.5*CF4_NTotal;
1045 double Tpc_dEdx = 0.5*Ne_dEdx + 0.5*CF4_dEdx;
1046 double Tpc_ElectronsPerKeV = Tpc_NTot / Tpc_dEdx;
1047 double electrons_per_gev = Tpc_ElectronsPerKeV * 1e6;
1048
1049 double gem_amplification = 1400;
1050 double input_electrons = gedep * electrons_per_gev * gem_amplification;
1051
1052
1053 double ChargeToPeakVolts = 20;
1054 double ADCSignalConversionGain = ChargeToPeakVolts * 1.60e-04 * 2.4;
1055 double adc_input_voltage = input_electrons * ADCSignalConversionGain;
1056 unsigned int adc_output = (unsigned int) (adc_input_voltage * 1024.0 / 2200.0);
1057 if (adc_output > 1023) adc_output = 1023;
1058
1059 return adc_output;
1060 }
1061
1062 int PHTruthClustering::GetNodes(PHCompositeNode* topNode)
1063 {
1064 _tgeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
1065 _g4truth_container = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
1066 if (!_g4truth_container)
1067 {
1068 cerr << PHWHERE << " ERROR: Can't find node G4TruthInfo" << endl;
1069 return Fun4AllReturnCodes::ABORTEVENT;
1070 }
1071
1072 _g4hits_mms = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_MICROMEGAS");
1073 _g4hits_svtx = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_TPC");
1074 _g4hits_tracker = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_INTT");
1075 _g4hits_maps = findNode::getClass<PHG4HitContainer>(topNode, "G4HIT_MVTX");
1076
1077 _mms_geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MICROMEGAS_FULL");
1078 _tpc_geom_container = findNode::getClass<PHG4TpcCylinderGeomContainer>(topNode, "CYLINDERCELLGEOM_SVTX");
1079 _intt_geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
1080 _mvtx_geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_MVTX");
1081
1082
1083 PHNodeIterator iter(topNode);
1084
1085 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
1086 if (!dstNode)
1087 {
1088 cout << PHWHERE << "DST Node missing, doing nothing." << endl;
1089 return Fun4AllReturnCodes::ABORTRUN;
1090 }
1091
1092 auto trkrclusters = findNode::getClass<TrkrClusterContainer>(dstNode, "TRKR_CLUSTER_TRUTH");
1093 if (!trkrclusters)
1094 {
1095 PHNodeIterator dstiter(dstNode);
1096 PHCompositeNode *DetNode =
1097 dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
1098 if (!DetNode)
1099 {
1100 DetNode = new PHCompositeNode("TRKR");
1101 dstNode->addNode(DetNode);
1102 }
1103
1104 trkrclusters = new TrkrClusterContainerv4;
1105 PHIODataNode<PHObject> *TrkrClusterContainerNode =
1106 new PHIODataNode<PHObject>(trkrclusters, "TRKR_CLUSTER_TRUTH", "PHObject");
1107 DetNode->addNode(TrkrClusterContainerNode);
1108 }
1109
1110 _reco_cluster_map = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_CLUSTER");
1111 if (!_reco_cluster_map)
1112 {
1113 cerr << PHWHERE << " ERROR: Can't find node TRKR_CLUSTER" << endl;
1114 return Fun4AllReturnCodes::ABORTEVENT;
1115 }
1116
1117 return Fun4AllReturnCodes::EVENT_OK;
1118 }
1119
1120 int PHTruthClustering::End(PHCompositeNode * )
1121 {
1122 return Fun4AllReturnCodes::EVENT_OK;
1123 }