File indexing completed on 2025-08-06 08:19:22
0001 #include "PHG4ParticleGeneratorVectorMeson.h"
0002
0003 #include "PHG4InEvent.h"
0004 #include "PHG4Particlev1.h"
0005
0006 #include <phool/PHCompositeNode.h>
0007 #include <phool/PHDataNode.h> // for PHDataNode
0008 #include <phool/PHNode.h> // for PHNode
0009 #include <phool/PHNodeIterator.h> // for PHNodeIterator
0010 #include <phool/PHObject.h> // for PHObject
0011 #include <phool/PHRandomSeed.h>
0012 #include <phool/getClass.h>
0013 #include <phool/phool.h> // for PHWHERE
0014
0015 #include <TF1.h>
0016 #include <TLorentzVector.h>
0017 #include <TRandom.h> // for TRandom
0018 #include <TRandom3.h>
0019 #include <TSystem.h>
0020
0021 #include <gsl/gsl_randist.h>
0022 #include <gsl/gsl_rng.h> // for gsl_rng_uniform, gsl_rng_uniform_pos
0023
0024 #include <cmath> // for sin, sqrt, cos, M_PI
0025 #include <cstdlib> // for exit
0026 #include <iostream> // for operator<<, basic_ostream, basic_...
0027 #include <utility> // for pair
0028 #include <vector> // for vector, vector<>::const_iterator
0029
0030 class PHG4Particle;
0031
0032 PHG4ParticleGeneratorVectorMeson::PHG4ParticleGeneratorVectorMeson(const std::string &name)
0033 : PHG4ParticleGeneratorBase(name)
0034 {
0035 set_upsilon_1s();
0036 return;
0037 }
0038
0039 PHG4ParticleGeneratorVectorMeson::
0040 ~PHG4ParticleGeneratorVectorMeson()
0041 {
0042 delete trand;
0043 }
0044
0045 void PHG4ParticleGeneratorVectorMeson::add_decay_particles(const std::string &name1, const unsigned int decay_id)
0046 {
0047 if (name1 == "e")
0048 {
0049 add_decay_particles("e+", "e-", decay_id);
0050 }
0051 else if (name1 == "mu")
0052 {
0053 add_decay_particles("mu+", "mu-", decay_id);
0054 }
0055 else
0056 {
0057 std::cout << "Invalid decay " << name1 << ", valid is e or mu" << std::endl;
0058 gSystem->Exit(1);
0059 }
0060 return;
0061 }
0062
0063 void PHG4ParticleGeneratorVectorMeson::add_decay_particles(const std::string &name1, const std::string &name2, const unsigned int decay_id)
0064 {
0065
0066 if ((name1 == "e-" && name2 == "e+") ||
0067 (name1 == "e+" && name2 == "e-") ||
0068 (name1 == "mu+" && name2 == "mu-") ||
0069 (name1 == "mu-" && name2 == "mu+"))
0070 {
0071 decay1_names.insert(std::pair<unsigned int, std::string>(decay_id, name1));
0072 decay2_names.insert(std::pair<unsigned int, std::string>(decay_id, name2));
0073 decay_vtx_offset_x.insert(std::pair<unsigned int, double>(decay_id, 0.));
0074 decay_vtx_offset_y.insert(std::pair<unsigned int, double>(decay_id, 0.));
0075 decay_vtx_offset_z.insert(std::pair<unsigned int, double>(decay_id, 0.));
0076 return;
0077 }
0078 std::cout << "invalid decay channel Y --> " << name1 << " + " << name2 << std::endl;
0079 gSystem->Exit(1);
0080 }
0081
0082 void PHG4ParticleGeneratorVectorMeson::set_decay_vertex_offset(double dx, double dy, double dz, const unsigned int decay_id)
0083 {
0084 decay_vtx_offset_x.find(decay_id)->second = dx;
0085 decay_vtx_offset_y.find(decay_id)->second = dy;
0086 decay_vtx_offset_z.find(decay_id)->second = dz;
0087 return;
0088 }
0089
0090 void PHG4ParticleGeneratorVectorMeson::set_eta_range(const double min, const double max)
0091 {
0092 eta_min = min;
0093 eta_max = max;
0094 return;
0095 }
0096
0097 void PHG4ParticleGeneratorVectorMeson::set_rapidity_range(const double min, const double max)
0098 {
0099 y_min = min;
0100 y_max = max;
0101 return;
0102 }
0103
0104 void PHG4ParticleGeneratorVectorMeson::set_mom_range(const double min, const double max)
0105 {
0106 mom_min = min;
0107 mom_max = max;
0108 return;
0109 }
0110
0111 void PHG4ParticleGeneratorVectorMeson::set_pt_range(const double min, const double max)
0112 {
0113 pt_min = min;
0114 pt_max = max;
0115 return;
0116 }
0117
0118 void PHG4ParticleGeneratorVectorMeson::set_vertex_distribution_function(FUNCTION x, FUNCTION y, FUNCTION z)
0119 {
0120 _vertex_func_x = x;
0121 _vertex_func_y = y;
0122 _vertex_func_z = z;
0123 return;
0124 }
0125
0126 void PHG4ParticleGeneratorVectorMeson::set_vertex_distribution_mean(const double x, const double y, const double z)
0127 {
0128 _vertex_x = x;
0129 _vertex_y = y;
0130 _vertex_z = z;
0131 return;
0132 }
0133
0134 void PHG4ParticleGeneratorVectorMeson::set_vertex_distribution_width(const double x, const double y, const double z)
0135 {
0136 _vertex_width_x = x;
0137 _vertex_width_y = y;
0138 _vertex_width_z = z;
0139 return;
0140 }
0141
0142 void PHG4ParticleGeneratorVectorMeson::set_existing_vertex_offset_vector(const double x, const double y, const double z)
0143 {
0144 _vertex_offset_x = x;
0145 _vertex_offset_y = y;
0146 _vertex_offset_z = z;
0147 return;
0148 }
0149
0150 void PHG4ParticleGeneratorVectorMeson::set_vertex_size_function(FUNCTION r)
0151 {
0152 _vertex_size_func_r = r;
0153 return;
0154 }
0155
0156 void PHG4ParticleGeneratorVectorMeson::set_vertex_size_parameters(const double mean, const double width)
0157 {
0158 _vertex_size_mean = mean;
0159 _vertex_size_width = width;
0160 return;
0161 }
0162
0163 void PHG4ParticleGeneratorVectorMeson::set_decay_types(const std::string &name1, const std::string &name2)
0164 {
0165
0166 static const double mmuon = 105.6583745e-3;
0167
0168 static const double melectron = 0.5109989461e-3;
0169
0170 decay1 = name1;
0171 if (decay1 == "e+" || decay1 == "e-")
0172 {
0173 m1 = melectron;
0174 }
0175 else if (decay1 == "mu+" || decay1 == "mu-")
0176 {
0177 m1 = mmuon;
0178 }
0179 else
0180 {
0181 std::cout << "Do not recognize the decay type " << decay1 << std::endl;
0182 gSystem->Exit(1);
0183 }
0184
0185 decay2 = name2;
0186 if (decay2 == "e+" || decay2 == "e-")
0187 {
0188 m2 = melectron;
0189 }
0190 else if (decay2 == "mu+" || decay2 == "mu-")
0191 {
0192 m2 = mmuon;
0193 }
0194 else
0195 {
0196 std::cout << "Do not recognize the decay type " << decay2 << std::endl;
0197 gSystem->Exit(1);
0198 }
0199
0200 return;
0201 }
0202
0203 int PHG4ParticleGeneratorVectorMeson::InitRun(PHCompositeNode *topNode)
0204 {
0205 if (Verbosity() > 0)
0206 {
0207 std::cout << "PHG4ParticleGeneratorVectorMeson::InitRun started." << std::endl;
0208 }
0209 trand = new TRandom3();
0210 unsigned int iseed = PHRandomSeed();
0211 trand->SetSeed(iseed);
0212 if (_histrand_init)
0213 {
0214 iseed = PHRandomSeed();
0215 gRandom->SetSeed(iseed);
0216 }
0217
0218 fsin = new TF1("fsin", "sin(x)", 0, M_PI);
0219
0220
0221 frap = new TF1("frap", "gaus(0)", y_min, y_max);
0222 frap->SetParameter(0, 1.0);
0223 frap->SetParameter(1, 0.0);
0224 frap->SetParameter(2, 0.8749);
0225
0226
0227 fpt = new TF1("fpt", "2.0*3.14159*x*[0]*pow((1 + x*x/(4*[1]) ),-[2])", pt_min, pt_max);
0228 fpt->SetParameter(0, 72.1);
0229 fpt->SetParameter(1, 26.516);
0230 fpt->SetParameter(2, 10.6834);
0231
0232 ineve = findNode::getClass<PHG4InEvent>(topNode, "PHG4INEVENT");
0233 if (!ineve)
0234 {
0235 PHNodeIterator iter(topNode);
0236 PHCompositeNode *dstNode;
0237 dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0238
0239 ineve = new PHG4InEvent();
0240 PHDataNode<PHObject> *newNode = new PHDataNode<PHObject>(ineve, "PHG4INEVENT", "PHObject");
0241 dstNode->addNode(newNode);
0242 }
0243
0244 if (Verbosity() > 0)
0245 {
0246 std::cout << "PHG4ParticleGeneratorVectorMeson::InitRun endeded." << std::endl;
0247 }
0248 return 0;
0249 }
0250
0251 int PHG4ParticleGeneratorVectorMeson::process_event(PHCompositeNode *topNode)
0252 {
0253 if (!ineve)
0254 {
0255 std::cout << " G4InEvent not found " << std::endl;
0256 }
0257
0258
0259
0260
0261
0262
0263 double pt = 0.0;
0264 if (pt_max != pt_min)
0265 {
0266 pt = fpt->GetRandom();
0267 }
0268 else
0269 {
0270 pt = pt_min;
0271 }
0272
0273
0274 double y = 0.0;
0275 if (y_max != y_min)
0276 {
0277 y = frap->GetRandom();
0278 }
0279 else
0280 {
0281 y = y_min;
0282 }
0283
0284 double phi = (2.0 * M_PI) * gsl_rng_uniform(RandomGenerator());
0285
0286
0287
0288 double mnow = trand->BreitWigner(mass, m_Width);
0289
0290
0291
0292 double mt = sqrt((mnow * mnow) + (pt * pt));
0293 double eta = asinh(sinh(y) * mt / pt);
0294
0295
0296
0297 TLorentzVector vm;
0298 vm.SetPtEtaPhiM(pt, eta, phi, mnow);
0299
0300 int vtxindex = -9;
0301
0302 if (!ReuseExistingVertex(topNode))
0303 {
0304
0305
0306
0307 set_vtx(smearvtx(_vertex_x, _vertex_width_x, _vertex_func_x),
0308 smearvtx(_vertex_y, _vertex_width_y, _vertex_func_y),
0309 smearvtx(_vertex_z, _vertex_width_z, _vertex_func_z));
0310 }
0311 set_vtx(get_vtx_x() + _vertex_offset_x,
0312 get_vtx_y() + _vertex_offset_y,
0313 get_vtx_z() + _vertex_offset_z);
0314
0315 for (auto &it : decay1_names)
0316 {
0317 unsigned int decay_id = it.first;
0318 std::string decay1_name = it.second;
0319 std::string decay2_name;
0320 std::map<unsigned int, std::string>::iterator jt = decay2_names.find(decay_id);
0321 std::map<unsigned int, double>::iterator xt = decay_vtx_offset_x.find(decay_id);
0322 std::map<unsigned int, double>::iterator yt = decay_vtx_offset_y.find(decay_id);
0323 std::map<unsigned int, double>::iterator zt = decay_vtx_offset_z.find(decay_id);
0324
0325 if (jt != decay2_names.end() && xt != decay_vtx_offset_x.end() && yt != decay_vtx_offset_y.end() && zt != decay_vtx_offset_z.end())
0326 {
0327 decay2_name = jt->second;
0328 set_decay_types(decay1_name, decay2_name);
0329 set_existing_vertex_offset_vector(xt->second, yt->second, zt->second);
0330 }
0331 else
0332 {
0333 std::cout << PHWHERE << "Decay particles && vertex info can't be found !!" << std::endl;
0334 exit(1);
0335 }
0336
0337
0338 if ((_vertex_size_width > 0.0) || (_vertex_size_mean != 0.0))
0339 {
0340 _vertex_size_mean = sqrt((get_vtx_x() * get_vtx_x()) +
0341 (get_vtx_y() * get_vtx_y()) +
0342 (get_vtx_z() * get_vtx_z()));
0343 double r = smearvtx(_vertex_size_mean, _vertex_size_width, _vertex_size_func_r);
0344 double x1 = 0.0;
0345 double y1 = 0.0;
0346 double z1 = 0.0;
0347 gsl_ran_dir_3d(RandomGenerator(), &x1, &y1, &z1);
0348 x1 *= r;
0349 y1 *= r;
0350 z1 *= r;
0351 vtxindex = ineve->AddVtx(get_vtx_x() + x1, get_vtx_y() + y1, get_vtx_z() + z1, get_t0());
0352 }
0353 else if (decay_id == 0)
0354 {
0355 vtxindex = ineve->AddVtx(get_vtx_x(), get_vtx_y(), get_vtx_z(), get_t0());
0356 }
0357
0358
0359
0360
0361 double E1 = (mnow * mnow - m2 * m2 + m1 * m1) / (2.0 * mnow);
0362 double p1 = sqrt((mnow * mnow - (m1 + m2) * (m1 + m2)) * (mnow * mnow - (m1 - m2) * (m1 - m2))) / (2.0 * mnow);
0363
0364
0365
0366
0367
0368 double th1 = fsin->GetRandom();
0369
0370 double phi1 = 2.0 * M_PI * gsl_rng_uniform(RandomGenerator());
0371
0372
0373
0374 double px1 = p1 * sin(th1) * cos(phi1);
0375 double py1 = p1 * sin(th1) * sin(phi1);
0376 double pz1 = p1 * cos(th1);
0377 TLorentzVector v1;
0378 v1.SetPxPyPzE(px1, py1, pz1, E1);
0379
0380
0381
0382
0383 double betax = vm.Px() / vm.E();
0384 double betay = vm.Py() / vm.E();
0385 double betaz = vm.Pz() / vm.E();
0386 v1.Boost(betax, betay, betaz);
0387
0388
0389
0390 TLorentzVector v2 = vm - v1;
0391
0392
0393
0394 AddParticle(decay1_name, v1.Px(), v1.Py(), v1.Pz());
0395 AddParticle(decay2_name, v2.Px(), v2.Py(), v2.Pz());
0396
0397
0398
0399 for (std::vector<PHG4Particle *>::const_iterator iter = particlelist_begin(); iter != particlelist_end(); ++iter)
0400 {
0401 PHG4Particle *particle = new PHG4Particlev1(*iter);
0402 SetParticleId(particle, ineve);
0403 ineve->AddParticle(vtxindex, particle);
0404 if (EmbedFlag() != 0)
0405 {
0406 ineve->AddEmbeddedParticle(particle, EmbedFlag());
0407 }
0408 }
0409
0410
0411 if (Verbosity() > 0)
0412 {
0413 ineve->identify();
0414
0415
0416 std::cout << std::endl
0417 << "Output some sanity check info from PHG4ParticleGeneratorVectorMeson:" << std::endl;
0418
0419 std::cout << " Vertex for this event (X,Y,Z) is (" << get_vtx_x() << ", " << get_vtx_y() << ", " << get_vtx_z() << ")" << std::endl;
0420
0421
0422 std::cout << " Decay particle 1:"
0423 << " px " << v1.Px()
0424 << " py " << v1.Py()
0425 << " pz " << v1.Pz()
0426 << " eta " << v1.PseudoRapidity()
0427 << " phi " << v1.Phi()
0428 << " theta " << v1.Theta()
0429 << " pT " << v1.Pt()
0430 << " mass " << v1.M()
0431 << " E " << v1.E()
0432 << std::endl;
0433
0434 std::cout << " Decay particle 2:"
0435 << " px " << v2.Px()
0436 << " py " << v2.Py()
0437 << " pz " << v2.Pz()
0438 << " eta " << v2.PseudoRapidity()
0439 << " phi " << v2.Phi()
0440 << " theta " << v2.Theta()
0441 << " pT " << v2.Pt()
0442 << " mass " << v2.M()
0443 << " E " << v2.E()
0444 << std::endl;
0445
0446
0447 std::cout << " Vector meson input kinematics: mass " << vm.M()
0448 << " px " << vm.Px()
0449 << " py " << vm.Py()
0450 << " pz " << vm.Pz()
0451 << " eta " << vm.PseudoRapidity()
0452 << " y " << vm.Rapidity()
0453 << " pt " << vm.Pt()
0454 << " E " << vm.E()
0455 << std::endl;
0456
0457
0458
0459 TLorentzVector vreco = v1 + v2;
0460
0461 std::cout << " Reco'd vector meson kinematics: mass " << vreco.M()
0462 << " px " << vreco.Px()
0463 << " py " << vreco.Py()
0464 << " pz " << vreco.Pz()
0465 << " eta " << vreco.PseudoRapidity()
0466 << " y " << vreco.Rapidity()
0467 << " pt " << vreco.Pt()
0468 << " E " << vreco.E()
0469 << std::endl;
0470 }
0471 }
0472
0473 ResetParticleList();
0474
0475 return 0;
0476 }
0477
0478 double
0479 PHG4ParticleGeneratorVectorMeson::smearvtx(const double position, const double , FUNCTION dist) const
0480 {
0481 double res = position;
0482 if (dist == Uniform)
0483 {
0484 res = (position - m_Width) + 2 * gsl_rng_uniform_pos(RandomGenerator()) * m_Width;
0485 }
0486 else if (dist == Gaus)
0487 {
0488 res = position + gsl_ran_gaussian(RandomGenerator(), m_Width);
0489 }
0490 return res;
0491 }
0492
0493 void PHG4ParticleGeneratorVectorMeson::set_upsilon_1s()
0494 {
0495
0496 set_mass(9.4603);
0497 set_width(54.02e-6);
0498 }
0499
0500 void PHG4ParticleGeneratorVectorMeson::set_upsilon_2s()
0501 {
0502
0503 set_mass(10.02326);
0504 set_width(31.98e-6);
0505 }
0506
0507 void PHG4ParticleGeneratorVectorMeson::set_upsilon_3s()
0508 {
0509
0510 set_mass(10.3552);
0511 set_width(20.32e-6);
0512 }