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