File indexing completed on 2025-12-17 09:22:12
0001
0002
0003
0004 #include "PHG4TpcElectronDrift.h"
0005 #include "PHG4TpcDistortion.h"
0006 #include "PHG4TpcPadPlane.h" // for PHG4TpcPadPlane
0007 #include "TpcClusterBuilder.h"
0008
0009 #include <trackbase/ClusHitsVerbosev1.h>
0010 #include <trackbase/TpcDefs.h>
0011 #include <trackbase/TrkrCluster.h>
0012 #include <trackbase/TrkrClusterContainer.h>
0013 #include <trackbase/TrkrClusterContainerv4.h>
0014 #include <trackbase/TrkrDefs.h>
0015 #include <trackbase/TrkrHit.h> // for TrkrHit
0016 #include <trackbase/TrkrHitSet.h>
0017 #include <trackbase/TrkrHitSetContainerv1.h>
0018 #include <trackbase/TrkrHitTruthAssoc.h> // for TrkrHitTruthA...
0019 #include <trackbase/TrkrHitTruthAssocv1.h>
0020 #include <trackbase/TrkrHitv2.h>
0021
0022 #include <g4tracking/TrkrTruthTrackContainerv1.h>
0023 #include <g4tracking/TrkrTruthTrackv1.h>
0024
0025 #include <g4detectors/PHG4TpcGeom.h>
0026 #include <g4detectors/PHG4TpcGeomContainer.h>
0027
0028 #include <g4main/PHG4Hit.h>
0029 #include <g4main/PHG4HitContainer.h>
0030 #include <g4main/PHG4Particlev3.h>
0031 #include <g4main/PHG4TruthInfoContainer.h>
0032
0033 #include <phparameter/PHParameterInterface.h> // for PHParameterIn...
0034 #include <phparameter/PHParameters.h>
0035 #include <phparameter/PHParametersContainer.h>
0036
0037 #include <pdbcalbase/PdbParameterMapContainer.h>
0038
0039 #include <fun4all/Fun4AllReturnCodes.h>
0040 #include <fun4all/Fun4AllServer.h>
0041 #include <fun4all/SubsysReco.h> // for SubsysReco
0042
0043 #include <phool/PHCompositeNode.h>
0044 #include <phool/PHDataNode.h> // for PHDataNode
0045 #include <phool/PHIODataNode.h>
0046 #include <phool/PHNode.h> // for PHNode
0047 #include <phool/PHNodeIterator.h>
0048 #include <phool/PHObject.h> // for PHObject
0049 #include <phool/PHRandomSeed.h>
0050 #include <phool/getClass.h>
0051 #include <phool/phool.h> // for PHWHERE
0052
0053 #include <TFile.h>
0054 #include <TH1.h>
0055 #include <TH2.h>
0056 #include <TNtuple.h>
0057 #include <TSystem.h>
0058
0059 #include <gsl/gsl_randist.h>
0060 #include <gsl/gsl_rng.h> // for gsl_rng_alloc
0061
0062 #include <array>
0063 #include <cassert>
0064 #include <cmath> // for sqrt, abs, NAN
0065 #include <cstdlib> // for exit
0066 #include <format>
0067 #include <iostream>
0068 #include <map> // for _Rb_tree_cons...
0069 #include <utility> // for pair
0070
0071 namespace
0072 {
0073 template <class T>
0074 constexpr T square(const T &x)
0075 {
0076 return x * x;
0077 }
0078 }
0079
0080 PHG4TpcElectronDrift::PHG4TpcElectronDrift(const std::string &name)
0081 : SubsysReco(name)
0082 , PHParameterInterface(name)
0083 , temp_hitsetcontainer(new TrkrHitSetContainerv1)
0084 , single_hitsetcontainer(new TrkrHitSetContainerv1)
0085 {
0086 InitializeParameters();
0087 RandomGenerator.reset(gsl_rng_alloc(gsl_rng_mt19937));
0088 set_seed(PHRandomSeed());
0089 }
0090
0091
0092 int PHG4TpcElectronDrift::Init(PHCompositeNode *topNode)
0093 {
0094 padplane->Init(topNode);
0095 event_num = 0;
0096 return Fun4AllReturnCodes::EVENT_OK;
0097 }
0098
0099
0100 int PHG4TpcElectronDrift::InitRun(PHCompositeNode *topNode)
0101 {
0102 PHNodeIterator iter(topNode);
0103
0104
0105 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0106 if (!dstNode)
0107 {
0108 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
0109 exit(1);
0110 }
0111 auto *runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
0112 auto *parNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "PAR"));
0113 const std::string paramnodename = "G4CELLPARAM_" + detector;
0114 const std::string geonodename = "G4CELLPAR_" + detector;
0115 const std::string tpcgeonodename = "G4GEO_" + detector;
0116 hitnodename = "G4HIT_" + detector;
0117 PHG4HitContainer *g4hit = findNode::getClass<PHG4HitContainer>(topNode, hitnodename);
0118 if (!g4hit)
0119 {
0120 std::cout << Name() << " Could not locate G4HIT node " << hitnodename << std::endl;
0121 topNode->print();
0122 gSystem->Exit(1);
0123 exit(1);
0124 }
0125
0126 hitsetcontainer = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
0127 if (!hitsetcontainer)
0128 {
0129 PHNodeIterator dstiter(dstNode);
0130 auto *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0131 if (!DetNode)
0132 {
0133 DetNode = new PHCompositeNode("TRKR");
0134 dstNode->addNode(DetNode);
0135 }
0136
0137 hitsetcontainer = new TrkrHitSetContainerv1;
0138 auto *newNode = new PHIODataNode<PHObject>(hitsetcontainer, "TRKR_HITSET", "PHObject");
0139 DetNode->addNode(newNode);
0140 }
0141
0142 hittruthassoc = findNode::getClass<TrkrHitTruthAssoc>(topNode, "TRKR_HITTRUTHASSOC");
0143 if (!hittruthassoc)
0144 {
0145 PHNodeIterator dstiter(dstNode);
0146 auto *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0147 if (!DetNode)
0148 {
0149 DetNode = new PHCompositeNode("TRKR");
0150 dstNode->addNode(DetNode);
0151 }
0152
0153 hittruthassoc = new TrkrHitTruthAssocv1;
0154 auto *newNode = new PHIODataNode<PHObject>(hittruthassoc, "TRKR_HITTRUTHASSOC", "PHObject");
0155 DetNode->addNode(newNode);
0156 }
0157
0158 truthtracks = findNode::getClass<TrkrTruthTrackContainer>(topNode, "TRKR_TRUTHTRACKCONTAINER");
0159 if (!truthtracks)
0160 {
0161 PHNodeIterator dstiter(dstNode);
0162 auto *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0163 if (!DetNode)
0164 {
0165 DetNode = new PHCompositeNode("TRKR");
0166 dstNode->addNode(DetNode);
0167 }
0168
0169 truthtracks = new TrkrTruthTrackContainerv1();
0170 auto *newNode = new PHIODataNode<PHObject>(truthtracks, "TRKR_TRUTHTRACKCONTAINER", "PHObject");
0171 DetNode->addNode(newNode);
0172 }
0173
0174 truthclustercontainer = findNode::getClass<TrkrClusterContainer>(topNode, "TRKR_TRUTHCLUSTERCONTAINER");
0175 if (!truthclustercontainer)
0176 {
0177 PHNodeIterator dstiter(dstNode);
0178 auto *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0179 if (!DetNode)
0180 {
0181 DetNode = new PHCompositeNode("TRKR");
0182 dstNode->addNode(DetNode);
0183 }
0184
0185 truthclustercontainer = new TrkrClusterContainerv4;
0186 auto *newNode = new PHIODataNode<PHObject>(truthclustercontainer, "TRKR_TRUTHCLUSTERCONTAINER", "PHObject");
0187 DetNode->addNode(newNode);
0188 }
0189
0190 seggeonodename = "TPCGEOMCONTAINER";
0191 seggeo = findNode::getClass<PHG4TpcGeomContainer>(topNode, seggeonodename);
0192 assert(seggeo);
0193
0194
0195 PHG4TpcGeom *layergeom = seggeo->GetLayerCellGeom(20);
0196
0197 tpc_length = 2 * (layergeom->get_max_driftlength() + layergeom->get_CM_halfwidth());
0198
0199 UpdateParametersWithMacro();
0200 PHNodeIterator runIter(runNode);
0201 auto *RunDetNode = dynamic_cast<PHCompositeNode *>(runIter.findFirst("PHCompositeNode", detector));
0202 if (!RunDetNode)
0203 {
0204 RunDetNode = new PHCompositeNode(detector);
0205 runNode->addNode(RunDetNode);
0206 }
0207 SaveToNodeTree(RunDetNode, paramnodename);
0208
0209
0210 PHNodeIterator parIter(parNode);
0211 auto *ParDetNode = dynamic_cast<PHCompositeNode *>(parIter.findFirst("PHCompositeNode", detector));
0212 if (!ParDetNode)
0213 {
0214 ParDetNode = new PHCompositeNode(detector);
0215 parNode->addNode(ParDetNode);
0216 }
0217 PutOnParNode(ParDetNode, geonodename);
0218
0219
0220 PHNodeIterator tpcpariter(ParDetNode);
0221 auto *tpcparams = findNode::getClass<PHParametersContainer>(ParDetNode, tpcgeonodename);
0222 if (!tpcparams)
0223 {
0224 const std::string runparamname = "G4GEOPARAM_" + detector;
0225 auto *tpcpdbparams = findNode::getClass<PdbParameterMapContainer>(RunDetNode, runparamname);
0226 if (tpcpdbparams)
0227 {
0228 tpcparams = new PHParametersContainer(detector);
0229 if (Verbosity())
0230 {
0231 tpcpdbparams->print();
0232 }
0233 tpcparams->CreateAndFillFrom(tpcpdbparams, detector);
0234 ParDetNode->addNode(new PHDataNode<PHParametersContainer>(tpcparams, tpcgeonodename));
0235 }
0236 else
0237 {
0238 std::cout << "PHG4TpcElectronDrift::InitRun - failed to find " << runparamname << " in order to initialize " << tpcgeonodename << ". Aborting run ..." << std::endl;
0239 return Fun4AllReturnCodes::ABORTRUN;
0240 }
0241 }
0242 assert(tpcparams);
0243
0244 if (Verbosity())
0245 {
0246 tpcparams->Print();
0247 }
0248 const PHParameters *tpcparam = tpcparams->GetParameters(0);
0249 assert(tpcparam);
0250
0251 diffusion_long = get_double_param("diffusion_long");
0252 added_smear_sigma_long = get_double_param("added_smear_long");
0253 diffusion_trans = get_double_param("diffusion_trans");
0254 if (zero_bfield)
0255 {
0256 diffusion_trans *= zero_bfield_diffusion_factor;
0257 }
0258 added_smear_sigma_trans = get_double_param("added_smear_trans");
0259
0260
0261
0262
0263
0264
0265 double Ne_dEdx = 1.56;
0266 double Ne_NTotal = 43;
0267 double Ne_frac = tpcparam->get_double_param("Ne_frac");
0268
0269 double Ar_dEdx = 2.44;
0270 double Ar_NTotal = 94;
0271 double Ar_frac = tpcparam->get_double_param("Ar_frac");
0272
0273 double CF4_dEdx = 7;
0274 double CF4_NTotal = 100;
0275 double CF4_frac = tpcparam->get_double_param("CF4_frac");
0276
0277 double N2_dEdx = 2.127;
0278 double N2_NTotal = 25;
0279 double N2_frac = tpcparam->get_double_param("N2_frac");
0280
0281 double isobutane_dEdx = 5.93;
0282 double isobutane_NTotal = 195;
0283 double isobutane_frac = tpcparam->get_double_param("isobutane_frac");
0284
0285 if (m_use_PDG_gas_params)
0286 {
0287 Ne_dEdx = 1.446;
0288 Ne_NTotal = 40;
0289
0290 Ar_dEdx = 2.525;
0291 Ar_NTotal = 97;
0292
0293 CF4_dEdx = 6.382;
0294 CF4_NTotal = 120;
0295 }
0296
0297 double Tpc_NTot = (Ne_NTotal * Ne_frac) + (Ar_NTotal * Ar_frac) + (CF4_NTotal * CF4_frac) + (N2_NTotal * N2_frac) + (isobutane_NTotal * isobutane_frac);
0298
0299 double Tpc_dEdx = (Ne_dEdx * Ne_frac) + (Ar_dEdx * Ar_frac) + (CF4_dEdx * CF4_frac) + (N2_dEdx * N2_frac) + (isobutane_dEdx * isobutane_frac);
0300
0301 electrons_per_gev = (Tpc_NTot / Tpc_dEdx) * 1e6;
0302
0303
0304 min_time = 0.0;
0305 max_time = layergeom->get_max_driftlength() / layergeom->get_drift_velocity_sim() + layergeom->get_extended_readout_time();
0306 min_active_radius = get_double_param("min_active_radius");
0307 max_active_radius = get_double_param("max_active_radius");
0308
0309 if (Verbosity() > 0)
0310 {
0311 std::cout << PHWHERE << " drift velocity " << layergeom->get_drift_velocity_sim() << " extended_readout_time " << layergeom->get_extended_readout_time() << " max time cutoff " << max_time << std::endl;
0312 }
0313
0314 auto *se = Fun4AllServer::instance();
0315 dlong = new TH1F("difflong", "longitudinal diffusion", 100, diffusion_long - diffusion_long / 2., diffusion_long + diffusion_long / 2.);
0316 se->registerHisto(dlong);
0317 dtrans = new TH1F("difftrans", "transversal diffusion", 100, diffusion_trans - diffusion_trans / 2., diffusion_trans + diffusion_trans / 2.);
0318 se->registerHisto(dtrans);
0319
0320 do_ElectronDriftQAHistos = false;
0321 if (do_ElectronDriftQAHistos)
0322 {
0323 hitmapstart = new TH2F("hitmapstart", "g4hit starting X-Y locations", 1560, -78, 78, 1560, -78, 78);
0324 hitmapend = new TH2F("hitmapend", "g4hit final X-Y locations", 1560, -78, 78, 1560, -78, 78);
0325 hitmapstart_z = new TH2F("hitmapstart_z", "g4hit starting Z-R locations", 2000, -100, 100, 780, 0, 78);
0326 hitmapend_z = new TH2F("hitmapend_z", "g4hit final Z-R locations", 2000, -100, 100, 780, 0, 78);
0327 z_startmap = new TH2F("z_startmap", "g4hit starting Z vs. R locations", 2000, -100, 100, 780, 0, 78);
0328 deltaphi = new TH2F("deltaphi", "Total delta phi; phi (rad);#Delta phi (rad)", 600, -M_PI, M_PI, 1000, -.2, .2);
0329 deltaRphinodiff = new TH2F("deltaRphinodiff", "Total delta R*phi, no diffusion; r (cm);#Delta R*phi (cm)", 600, 20, 80, 1000, -3, 5);
0330 deltaphivsRnodiff = new TH2F("deltaphivsRnodiff", "Total delta phi vs. R; phi (rad);#Delta phi (rad)", 600, 20, 80, 1000, -.2, .2);
0331 deltaz = new TH2F("deltaz", "Total delta z; z (cm);#Delta z (cm)", 1000, 0, 100, 1000, -.5, 5);
0332 deltaphinodiff = new TH2F("deltaphinodiff", "Total delta phi (no diffusion, only SC distortion); phi (rad);#Delta phi (rad)", 600, -M_PI, M_PI, 1000, -.2, .2);
0333 deltaphinodist = new TH2F("deltaphinodist", "Total delta phi (no SC distortion, only diffusion); phi (rad);#Delta phi (rad)", 600, -M_PI, M_PI, 1000, -.2, .2);
0334 deltar = new TH2F("deltar", "Total Delta r; r (cm);#Delta r (cm)", 580, 20, 78, 1000, -3, 5);
0335 deltarnodiff = new TH2F("deltarnodiff", "Delta r (no diffusion, only SC distortion); r (cm);#Delta r (cm)", 580, 20, 78, 1000, -2, 5);
0336 deltarnodist = new TH2F("deltarnodist", "Delta r (no SC distortion, only diffusion); r (cm);#Delta r (cm)", 580, 20, 78, 1000, -2, 5);
0337 ratioElectronsRR = new TH1F("ratioElectronsRR", "Ratio of electrons reach readout vs all in acceptance", 1561, -0.0325, 1.0465);
0338 }
0339
0340 if (Verbosity())
0341 {
0342
0343 m_outf.reset(new TFile("nt_out.root", "recreate"));
0344 nt = new TNtuple("nt", "electron drift stuff", "hit:ts:tb:tsig:rad:zstart:zfinal");
0345 nthit = new TNtuple("nthit", "TrkrHit collecting", "layer:phipad:zbin:neffelectrons");
0346 ntfinalhit = new TNtuple("ntfinalhit", "TrkrHit collecting", "layer:phipad:zbin:neffelectrons");
0347 ntpad = new TNtuple("ntpad", "electron by electron pad centroid", "layer:phigem:phiclus:zgem:zclus");
0348 se->registerHisto(nt);
0349 se->registerHisto(nthit);
0350 se->registerHisto(ntpad);
0351 }
0352
0353 padplane->InitRun(topNode);
0354
0355
0356 if (Verbosity())
0357 {
0358 const auto range = seggeo->get_begin_end();
0359 std::cout << "PHG4TpcElectronDrift::InitRun - layers: " << std::distance(range.first, range.second) << std::endl;
0360 int counter = 0;
0361 for (auto layeriter = range.first; layeriter != range.second; ++layeriter)
0362 {
0363 const auto radius = layeriter->second->get_radius();
0364 std::cout << std::format("{:.3f} ", radius);
0365 if (++counter == 8)
0366 {
0367 counter = 0;
0368 std::cout << std::endl;
0369 }
0370 }
0371 std::cout << std::endl;
0372 }
0373
0374 if (record_ClusHitsVerbose)
0375 {
0376
0377 mClusHitsVerbose = findNode::getClass<ClusHitsVerbosev1>(topNode, "Trkr_TruthClusHitsVerbose");
0378 if (!mClusHitsVerbose)
0379 {
0380 PHNodeIterator dstiter(dstNode);
0381 auto *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", "TRKR"));
0382 if (!DetNode)
0383 {
0384 DetNode = new PHCompositeNode("TRKR");
0385 dstNode->addNode(DetNode);
0386 }
0387 mClusHitsVerbose = new ClusHitsVerbosev1();
0388 auto *newNode = new PHIODataNode<PHObject>(mClusHitsVerbose, "Trkr_TruthClusHitsVerbose", "PHObject");
0389 DetNode->addNode(newNode);
0390 }
0391 }
0392
0393 return Fun4AllReturnCodes::EVENT_OK;
0394 }
0395
0396 int PHG4TpcElectronDrift::process_event(PHCompositeNode *topNode)
0397 {
0398 truth_track = nullptr;
0399
0400 m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0401 if (!m_tGeometry)
0402 {
0403 std::cout << PHWHERE << "ActsGeometry not found on node tree. Exiting" << std::endl;
0404 return Fun4AllReturnCodes::ABORTRUN;
0405 }
0406
0407 PHG4TpcGeom *layergeom = seggeo->GetLayerCellGeom(20);
0408
0409 if (truth_clusterer.needs_input_nodes())
0410 {
0411 truth_clusterer.set_input_nodes(truthclustercontainer, m_tGeometry,
0412 seggeo, mClusHitsVerbose);
0413 }
0414
0415 static constexpr unsigned int print_layer = 18;
0416
0417
0418 if (m_distortionMap)
0419 {
0420 m_distortionMap->load_event(event_num);
0421 }
0422
0423
0424 auto *g4hit = findNode::getClass<PHG4HitContainer>(topNode, hitnodename);
0425 if (!g4hit)
0426 {
0427 std::cout << "Could not locate g4 hit node " << hitnodename << std::endl;
0428 gSystem->Exit(1);
0429 }
0430 PHG4TruthInfoContainer *truthinfo =
0431 findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
0432
0433 PHG4HitContainer::ConstRange hit_begin_end = g4hit->getHits();
0434 unsigned int count_g4hits = 0;
0435
0436
0437
0438
0439 double ihit = 0;
0440 unsigned int dump_interval = 5000;
0441 unsigned int dump_counter = 0;
0442
0443 int trkid = -1;
0444
0445 PHG4Hit *prior_g4hit = nullptr;
0446
0447
0448
0449 for (auto hiter = hit_begin_end.first; hiter != hit_begin_end.second; ++hiter)
0450 {
0451 count_g4hits++;
0452 dump_counter++;
0453
0454 const double t0 = std::fmax(hiter->second->get_t(0), hiter->second->get_t(1));
0455 if (t0 > max_time)
0456 {
0457 continue;
0458 }
0459
0460 int trkid_new = hiter->second->get_trkid();
0461 if (trkid != trkid_new)
0462 {
0463 prior_g4hit = nullptr;
0464 if (truth_track)
0465 {
0466 truth_clusterer.cluster_hits(truth_track);
0467 }
0468 trkid = trkid_new;
0469
0470 if (Verbosity() > 1000)
0471 {
0472 std::cout << " New track : " << trkid << " is embed? : ";
0473 }
0474
0475 if (truthinfo->isEmbeded(trkid))
0476 {
0477 truth_track = truthtracks->getTruthTrack(trkid, truthinfo);
0478 truth_clusterer.b_collect_hits = true;
0479 if (Verbosity() > 1000)
0480 {
0481 std::cout << " YES embedded" << std::endl;
0482 }
0483 }
0484 else
0485 {
0486 truth_track = nullptr;
0487 truth_clusterer.b_collect_hits = false;
0488 if (Verbosity() > 1000)
0489 {
0490 std::cout << " NOT embedded" << std::endl;
0491 }
0492 }
0493 }
0494
0495
0496 if (truth_clusterer.b_collect_hits)
0497 {
0498 if (prior_g4hit)
0499 {
0500
0501 if (std::abs(prior_g4hit->get_x(0) - hiter->second->get_x(0)) > max_g4hitstep || std::abs(prior_g4hit->get_y(0) - hiter->second->get_y(0)) > max_g4hitstep)
0502 {
0503 if (truth_track)
0504 {
0505 truth_clusterer.cluster_hits(truth_track);
0506 }
0507 }
0508 }
0509 prior_g4hit = hiter->second;
0510 }
0511
0512
0513
0514
0515
0516
0517 double eion = hiter->second->get_eion();
0518 unsigned int n_electrons = gsl_ran_poisson(RandomGenerator.get(), eion * electrons_per_gev);
0519
0520
0521 if (Verbosity() > 100)
0522 {
0523 std::cout << " new hit with t0, " << t0 << " g4hitid " << hiter->first
0524 << " eion " << eion << " n_electrons " << n_electrons
0525 << " entry z " << hiter->second->get_z(0) << " exit z "
0526 << hiter->second->get_z(1) << " avg z"
0527 << (hiter->second->get_z(0) + hiter->second->get_z(1)) / 2.0
0528 << std::endl;
0529 }
0530
0531 if (n_electrons == 0)
0532 {
0533 continue;
0534 }
0535
0536 if (Verbosity() > 100)
0537 {
0538 std::cout << std::endl
0539 << "electron drift: g4hit " << hiter->first << " created electrons: "
0540 << n_electrons << " from " << eion * 1000000 << " keV" << std::endl;
0541 std::cout << " entry x,y,z = " << hiter->second->get_x(0) << " "
0542 << hiter->second->get_y(0) << " " << hiter->second->get_z(0)
0543 << " radius " << sqrt(pow(hiter->second->get_x(0), 2) + pow(hiter->second->get_y(0), 2)) << std::endl;
0544 std::cout << " exit x,y,z = " << hiter->second->get_x(1) << " "
0545 << hiter->second->get_y(1) << " " << hiter->second->get_z(1)
0546 << " radius " << sqrt(pow(hiter->second->get_x(1), 2) + pow(hiter->second->get_y(1), 2)) << std::endl;
0547 }
0548
0549 int notReachingReadout = 0;
0550
0551 for (unsigned int i = 0; i < n_electrons; i++)
0552 {
0553
0554
0555
0556
0557 const double f = gsl_ran_flat(RandomGenerator.get(), 0.0, 1.0);
0558
0559 const double x_start = hiter->second->get_x(0) + f * (hiter->second->get_x(1) - hiter->second->get_x(0));
0560 const double y_start = hiter->second->get_y(0) + f * (hiter->second->get_y(1) - hiter->second->get_y(0));
0561 const double z_start = hiter->second->get_z(0) + f * (hiter->second->get_z(1) - hiter->second->get_z(0));
0562 const double t_start = hiter->second->get_t(0) + f * (hiter->second->get_t(1) - hiter->second->get_t(0));
0563
0564 unsigned int side = 0;
0565 if (z_start > 0)
0566 {
0567 side = 1;
0568 }
0569
0570 const double r_sigma = diffusion_trans * sqrt(tpc_length / 2. - std::abs(z_start));
0571 const double rantrans =
0572 gsl_ran_gaussian(RandomGenerator.get(), r_sigma) +
0573 gsl_ran_gaussian(RandomGenerator.get(), added_smear_sigma_trans);
0574
0575 const double t_path = (tpc_length / 2. - std::abs(z_start)) / layergeom->get_drift_velocity_sim();
0576 const double t_sigma = diffusion_long * sqrt(tpc_length / 2. - std::abs(z_start)) / layergeom->get_drift_velocity_sim();
0577 const double rantime =
0578 gsl_ran_gaussian(RandomGenerator.get(), t_sigma) +
0579 gsl_ran_gaussian(RandomGenerator.get(), added_smear_sigma_long) / layergeom->get_drift_velocity_sim();
0580 double t_final = t_start + t_path + rantime;
0581
0582 if (t_final < min_time || t_final > max_time)
0583 {
0584 continue;
0585 }
0586
0587 double z_final;
0588 if (z_start < 0)
0589 {
0590 z_final = -tpc_length / 2. + t_final * layergeom->get_drift_velocity_sim();
0591 }
0592 else
0593 {
0594 z_final = tpc_length / 2. - t_final * layergeom->get_drift_velocity_sim();
0595 }
0596
0597 const double radstart = std::sqrt(square(x_start) + square(y_start));
0598 const double phistart = std::atan2(y_start, x_start);
0599 const double ranphi = gsl_ran_flat(RandomGenerator.get(), -M_PI, M_PI);
0600
0601 double x_final = x_start + rantrans * std::cos(ranphi);
0602 double y_final = y_start + rantrans * std::sin(ranphi);
0603
0604 double rad_final = sqrt(square(x_final) + square(y_final));
0605 double phi_final = atan2(y_final, x_final);
0606
0607 if (do_ElectronDriftQAHistos)
0608 {
0609 z_startmap->Fill(z_start, radstart);
0610 deltaphinodist->Fill(phistart, rantrans / rad_final);
0611 deltarnodist->Fill(radstart, rantrans);
0612 }
0613
0614 if (m_distortionMap)
0615 {
0616
0617 const double reaches = m_distortionMap->get_reaches_readout(radstart, phistart, z_start);
0618 if (reaches < thresholdforreachesreadout)
0619 {
0620 notReachingReadout++;
0621 continue;
0622 }
0623
0624 const double r_distortion = m_distortionMap->get_r_distortion(radstart, phistart, z_start);
0625 const double phi_distortion = m_distortionMap->get_rphi_distortion(radstart, phistart, z_start) / radstart;
0626 const double z_distortion = m_distortionMap->get_z_distortion(radstart, phistart, z_start);
0627
0628 rad_final += r_distortion;
0629 phi_final += phi_distortion;
0630 z_final += z_distortion;
0631 if (z_start < 0)
0632 {
0633 t_final = (z_final + tpc_length / 2.0) / layergeom->get_drift_velocity_sim();
0634 }
0635 else
0636 {
0637 t_final = (tpc_length / 2.0 - z_final) / layergeom->get_drift_velocity_sim();
0638 }
0639
0640 x_final = rad_final * std::cos(phi_final);
0641 y_final = rad_final * std::sin(phi_final);
0642
0643
0644
0645
0646 if (do_ElectronDriftQAHistos)
0647 {
0648 const double phi_final_nodiff = phistart + phi_distortion;
0649 const double rad_final_nodiff = radstart + r_distortion;
0650 deltarnodiff->Fill(radstart, rad_final_nodiff - radstart);
0651 deltaphinodiff->Fill(phistart, phi_final_nodiff - phistart);
0652 deltaphivsRnodiff->Fill(radstart, phi_final_nodiff - phistart);
0653 deltaRphinodiff->Fill(radstart, rad_final_nodiff * phi_final_nodiff - radstart * phistart);
0654
0655
0656 hitmapstart->Fill(x_start, y_start);
0657 hitmapend->Fill(x_final, y_final);
0658 hitmapstart_z->Fill(z_start, radstart);
0659 hitmapend_z->Fill(z_final, rad_final);
0660 deltar->Fill(radstart, rad_final - radstart);
0661 deltaphi->Fill(phistart, phi_final - phistart);
0662 deltaz->Fill(z_start, z_distortion);
0663 }
0664 }
0665
0666
0667 if (rad_final < min_active_radius - 2.0 || rad_final > max_active_radius + 1.0)
0668 {
0669
0670 continue;
0671 }
0672
0673 if (Verbosity() > 1000)
0674
0675 {
0676 std::cout << "electron " << i << " g4hitid " << hiter->first << " f " << f << std::endl;
0677 std::cout << "radstart " << radstart << " x_start: " << x_start
0678 << ", y_start: " << y_start
0679 << ",z_start: " << z_start
0680 << " t_start " << t_start
0681 << " t_path " << t_path
0682 << " t_sigma " << t_sigma
0683 << " rantime " << rantime
0684 << std::endl;
0685
0686 std::cout << " rad_final " << rad_final << " x_final " << x_final
0687 << " y_final " << y_final
0688 << " z_final " << z_final << " t_final " << t_final
0689 << " zdiff " << z_final - z_start << std::endl;
0690 }
0691
0692 if (Verbosity() > 0)
0693 {
0694 assert(nt);
0695 nt->Fill(ihit, t_start, t_final, t_sigma, rad_final, z_start, z_final);
0696 }
0697 padplane->MapToPadPlane(truth_clusterer, single_hitsetcontainer.get(),
0698 temp_hitsetcontainer.get(), hittruthassoc, x_final, y_final, t_final,
0699 side, hiter, ntpad, nthit);
0700 }
0701
0702 if (do_ElectronDriftQAHistos)
0703 {
0704 ratioElectronsRR->Fill((double) (n_electrons - notReachingReadout) / n_electrons);
0705 }
0706
0707 TrkrHitSetContainer::ConstRange single_hitset_range = single_hitsetcontainer->getHitSets(TrkrDefs::TrkrId::tpcId);
0708 for (TrkrHitSetContainer::ConstIterator single_hitset_iter = single_hitset_range.first;
0709 single_hitset_iter != single_hitset_range.second;
0710 ++single_hitset_iter)
0711 {
0712
0713 TrkrDefs::hitsetkey node_hitsetkey = single_hitset_iter->first;
0714 const unsigned int layer = TrkrDefs::getLayer(node_hitsetkey);
0715 const int sector = TpcDefs::getSectorId(node_hitsetkey);
0716 const int side = TpcDefs::getSide(node_hitsetkey);
0717
0718 if (Verbosity() > 8)
0719 {
0720 std::cout << " hitsetkey " << node_hitsetkey << " layer " << layer << " sector " << sector << " side " << side << std::endl;
0721 }
0722
0723 TrkrHitSet::ConstRange single_hit_range = single_hitset_iter->second->getHits();
0724 for (TrkrHitSet::ConstIterator single_hit_iter = single_hit_range.first;
0725 single_hit_iter != single_hit_range.second;
0726 ++single_hit_iter)
0727 {
0728 TrkrDefs::hitkey single_hitkey = single_hit_iter->first;
0729
0730
0731
0732 hittruthassoc->addAssoc(node_hitsetkey, single_hitkey, hiter->first);
0733 if (Verbosity() > 100)
0734 {
0735 std::cout << " adding assoc for node_hitsetkey " << node_hitsetkey << " single_hitkey " << single_hitkey << " g4hitkey " << hiter->first << std::endl;
0736 }
0737 }
0738 }
0739
0740
0741
0742
0743 if (dump_counter >= dump_interval || count_g4hits == g4hit->size())
0744 {
0745
0746
0747 double eg4hit = 0.0;
0748 TrkrHitSetContainer::ConstRange temp_hitset_range = temp_hitsetcontainer->getHitSets(TrkrDefs::TrkrId::tpcId);
0749 for (TrkrHitSetContainer::ConstIterator temp_hitset_iter = temp_hitset_range.first;
0750 temp_hitset_iter != temp_hitset_range.second;
0751 ++temp_hitset_iter)
0752 {
0753
0754 TrkrDefs::hitsetkey node_hitsetkey = temp_hitset_iter->first;
0755 const unsigned int layer = TrkrDefs::getLayer(node_hitsetkey);
0756 const int sector = TpcDefs::getSectorId(node_hitsetkey);
0757 const int side = TpcDefs::getSide(node_hitsetkey);
0758 if (Verbosity() > 100)
0759 {
0760 std::cout << "PHG4TpcElectronDrift: temp_hitset with key: " << node_hitsetkey << " in layer " << layer
0761 << " with sector " << sector << " side " << side << std::endl;
0762 }
0763
0764
0765 TrkrHitSetContainer::Iterator node_hitsetit = hitsetcontainer->findOrAddHitSet(node_hitsetkey);
0766
0767
0768 TrkrHitSet::ConstRange temp_hit_range = temp_hitset_iter->second->getHits();
0769 for (TrkrHitSet::ConstIterator temp_hit_iter = temp_hit_range.first;
0770 temp_hit_iter != temp_hit_range.second;
0771 ++temp_hit_iter)
0772 {
0773 TrkrDefs::hitkey temp_hitkey = temp_hit_iter->first;
0774 TrkrHit *temp_tpchit = temp_hit_iter->second;
0775 if (Verbosity() > 10 && layer == print_layer)
0776 {
0777 std::cout << " temp_hitkey " << temp_hitkey << " layer " << layer << " pad " << TpcDefs::getPad(temp_hitkey)
0778 << " z bin " << TpcDefs::getTBin(temp_hitkey)
0779 << " energy " << temp_tpchit->getEnergy() << " eg4hit " << eg4hit << std::endl;
0780
0781 eg4hit += temp_tpchit->getEnergy();
0782
0783
0784 }
0785
0786
0787 TrkrHit *node_hit = node_hitsetit->second->getHit(temp_hitkey);
0788 if (!node_hit)
0789 {
0790
0791 node_hit = new TrkrHitv2();
0792 node_hitsetit->second->addHitSpecificKey(temp_hitkey, node_hit);
0793 }
0794
0795
0796 node_hit->addEnergy(temp_tpchit->getEnergy());
0797
0798 }
0799
0800 if (Verbosity() > 100 && layer == print_layer)
0801 {
0802 std::cout << " ihit " << ihit << " collected energy = " << eg4hit << std::endl;
0803 }
0804
0805 }
0806
0807
0808 temp_hitsetcontainer->Reset();
0809
0810
0811 dump_counter = 0;
0812 }
0813
0814 ++ihit;
0815
0816 single_hitsetcontainer->Reset();
0817
0818 }
0819
0820 if (truth_track)
0821 {
0822 truth_clusterer.cluster_hits(truth_track);
0823 }
0824 truth_clusterer.clear_hitsetkey_cnt();
0825
0826 if (Verbosity() > 20)
0827 {
0828 std::cout << "From PHG4TpcElectronDrift: hitsetcontainer printout at end:" << std::endl;
0829
0830 TrkrHitSetContainer::ConstRange hitset_range = hitsetcontainer->getHitSets(TrkrDefs::TrkrId::tpcId);
0831 for (TrkrHitSetContainer::ConstIterator hitset_iter = hitset_range.first;
0832 hitset_iter != hitset_range.second;
0833 ++hitset_iter)
0834 {
0835
0836 TrkrDefs::hitsetkey hitsetkey = hitset_iter->first;
0837 const unsigned int layer = TrkrDefs::getLayer(hitsetkey);
0838 if (layer != print_layer)
0839 {
0840 continue;
0841 }
0842 const int sector = TpcDefs::getSectorId(hitsetkey);
0843 const int side = TpcDefs::getSide(hitsetkey);
0844
0845 std::cout << "PHG4TpcElectronDrift: hitset with key: " << hitsetkey << " in layer " << layer << " with sector " << sector << " side " << side << std::endl;
0846
0847
0848 TrkrHitSet *hitset = hitset_iter->second;
0849 TrkrHitSet::ConstRange hit_range = hitset->getHits();
0850 for (TrkrHitSet::ConstIterator hit_iter = hit_range.first;
0851 hit_iter != hit_range.second;
0852 ++hit_iter)
0853 {
0854 TrkrDefs::hitkey hitkey = hit_iter->first;
0855 TrkrHit *tpchit = hit_iter->second;
0856 std::cout << " hitkey " << hitkey << " pad " << TpcDefs::getPad(hitkey) << " z bin " << TpcDefs::getTBin(hitkey)
0857 << " energy " << tpchit->getEnergy() << std::endl;
0858 }
0859 }
0860 }
0861
0862 if (Verbosity() > 1000)
0863 {
0864 std::cout << "From PHG4TpcElectronDrift: hittruthassoc dump:" << std::endl;
0865 hittruthassoc->identify();
0866
0867 hittruthassoc->identify();
0868 }
0869
0870 ++event_num;
0871
0872 if (Verbosity() > 500)
0873 {
0874 std::cout << " TruthTrackContainer results at end of event in PHG4TpcElectronDrift::process_event " << std::endl;
0875 truthtracks->identify();
0876 }
0877
0878 if (Verbosity() > 800)
0879 {
0880 truth_clusterer.print(truthtracks);
0881 truth_clusterer.print_file(truthtracks, "drift_clusters.txt");
0882 }
0883
0884 return Fun4AllReturnCodes::EVENT_OK;
0885 }
0886
0887 int PHG4TpcElectronDrift::End(PHCompositeNode * )
0888 {
0889 if (Verbosity() > 0)
0890 {
0891 assert(m_outf);
0892 assert(nt);
0893 assert(ntpad);
0894 assert(nthit);
0895 assert(ntfinalhit);
0896
0897 m_outf->cd();
0898 nt->Write();
0899 ntpad->Write();
0900 nthit->Write();
0901 ntfinalhit->Write();
0902 m_outf->Close();
0903 }
0904 if (do_ElectronDriftQAHistos)
0905 {
0906 EDrift_outf.reset(new TFile("ElectronDriftQA.root", "recreate"));
0907 EDrift_outf->cd();
0908 deltar->Write();
0909 deltaphi->Write();
0910 deltaz->Write();
0911 deltarnodist->Write();
0912 deltaphinodist->Write();
0913 deltarnodiff->Write();
0914 deltaphinodiff->Write();
0915 deltaRphinodiff->Write();
0916 deltaphivsRnodiff->Write();
0917 hitmapstart->Write();
0918 hitmapend->Write();
0919 hitmapstart_z->Write();
0920 hitmapend_z->Write();
0921 z_startmap->Write();
0922 ratioElectronsRR->Write();
0923 EDrift_outf->Close();
0924 }
0925 return Fun4AllReturnCodes::EVENT_OK;
0926 }
0927
0928 void PHG4TpcElectronDrift::set_seed(const unsigned int seed)
0929 {
0930 gsl_rng_set(RandomGenerator.get(), seed);
0931 }
0932
0933 void PHG4TpcElectronDrift::SetDefaultParameters()
0934 {
0935
0936
0937
0938
0939
0940 set_default_double_param("diffusion_long", 0.014596);
0941 set_default_double_param("diffusion_trans", 0.005313);
0942 set_default_double_param("Ne_frac", 0.00);
0943 set_default_double_param("Ar_frac", 0.75);
0944 set_default_double_param("CF4_frac", 0.20);
0945 set_default_double_param("N2_frac", 0.00);
0946 set_default_double_param("isobutane_frac", 0.05);
0947 set_default_double_param("min_active_radius", 30.);
0948 set_default_double_param("max_active_radius", 78.);
0949
0950
0951
0952 set_default_double_param("added_smear_trans", 0.0);
0953 set_default_double_param("added_smear_long", 0.0);
0954
0955 return;
0956 }
0957
0958 void PHG4TpcElectronDrift::setTpcDistortion(PHG4TpcDistortion *distortionMap)
0959 {
0960 m_distortionMap.reset(distortionMap);
0961 }
0962
0963 void PHG4TpcElectronDrift::registerPadPlane(PHG4TpcPadPlane *inpadplane)
0964 {
0965 if (Verbosity())
0966 {
0967 std::cout << "Registering padplane " << std::endl;
0968 }
0969 padplane.reset(inpadplane);
0970 padplane->Detector(Detector());
0971 padplane->UpdateInternalParameters();
0972 if (Verbosity())
0973 {
0974 std::cout << "padplane registered and parameters updated" << std::endl;
0975 }
0976
0977 return;
0978 }
0979
0980 void PHG4TpcElectronDrift::set_flag_threshold_distortion(bool setflag, float setthreshold)
0981 {
0982 std::cout << std::format("The logical status of threshold is now {}! and the value is set to {}", setflag, setthreshold)
0983 << std::endl
0984 << std::endl
0985 << std::endl;
0986 do_getReachReadout = setflag;
0987 thresholdforreachesreadout = setthreshold;
0988 }