BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
DummyParticleGun.cxx
Go to the documentation of this file.
1#include "HepPDT/ParticleData.hh"
2#include "HepPDT/ParticleDataTable.hh"
3#include <CLHEP/Random/RandFlat.h>
4#include <CLHEP/Random/RandomEngine.h>
5#include <CLHEP/Vector/LorentzVector.h>
6#include <Gaudi/Functional/Transformer.h>
7#include <Gaudi/Property.h>
8#include <GaudiKernel/IPartPropSvc.h>
9#include <GaudiKernel/SmartIF.h>
10#include <GaudiKernel/StatusCode.h>
11#include <HepMC/GenParticle.h>
12#include <HepMC/GenVertex.h>
13#include <HepMC/SimpleVector.h>
14#include <cmath>
15
16#include "BesRndmGenSvc/IBesRndmGenSvc.h"
17#include "GeneratorObject/McGenEvent.h"
18
19using Gaudi::Functional::Transformer;
20class DummyParticleGun : public Transformer<McGenEventCol( const EventContext& )> {
21public:
22 DummyParticleGun( const std::string& name, ISvcLocator* pSvcLocator )
23 : Transformer( name, pSvcLocator, { "McGenEventLocation", "/Event/Gen" } ) {}
24
25 StatusCode initialize() override {
26 info() << "Initializing DummyParticleGun" << endmsg;
27
28 StatusCode sc = Transformer::initialize();
29 if ( !sc.isSuccess() ) return sc;
30
31 // check args
32 if ( m_parts.size() == 0 )
33 {
34 error() << "No PDG codes specified" << endmsg;
35 return StatusCode::FAILURE;
36 }
37
38 if ( m_p_range.size() != 2 )
39 {
40 error() << "Momentum range must be of size 2" << endmsg;
41 return StatusCode::FAILURE;
42 }
43
44 if ( m_costheta_range.size() != 2 )
45 {
46 error() << "Cos(theta) range must be of size 2" << endmsg;
47 return StatusCode::FAILURE;
48 }
49
50 if ( m_phi_range.size() != 2 )
51 {
52 error() << "Phi range must be of size 2" << endmsg;
53 return StatusCode::FAILURE;
54 }
55
56 // set ranges
57 m_p1 = m_p_range[0];
58 m_p2 = m_p_range[1];
59 m_costheta1 = m_costheta_range[0];
60 m_costheta2 = m_costheta_range[1];
61 m_phi1 = m_phi_range[0];
62 m_phi2 = m_phi_range[1];
63
64 if ( m_p2 <= m_p1 ) m_p2 = m_p1;
65 if ( m_costheta2 <= m_costheta1 ) m_costheta2 = m_costheta1;
66 if ( m_phi2 <= m_phi1 ) m_phi2 = m_phi1;
67
68 // retrieve random enging
69 m_rndm_svc = service<IBesRndmGenSvc>( "BesRndmGenSvc" );
70 if ( !m_rndm_svc )
71 {
72 error() << "Could not get random number service" << endmsg;
73 return StatusCode::FAILURE;
74 }
75
76 m_rndm_engine = m_rndm_svc->GetEngine( "DummyParticleGun" );
77 if ( !m_rndm_engine )
78 {
79 error() << "Could not get random engine" << endmsg;
80 return StatusCode::FAILURE;
81 }
82
83 // retrieve particle data table
84 auto part_prop_svc = service<IPartPropSvc>( "PartPropSvc" );
85 if ( !part_prop_svc )
86 {
87 error() << "Could not get Particle Properties Service" << endmsg;
88 return StatusCode::FAILURE;
89 }
90
91 m_particle_table = part_prop_svc->PDT();
92 if ( !m_particle_table )
93 {
94 error() << "Could not get Particle Data Table" << endmsg;
95 return StatusCode::FAILURE;
96 }
97
98 return StatusCode::SUCCESS;
99 }
100
101 McGenEventCol operator()( const EventContext& ctx ) const override {
102 GenEvent* evt = new GenEvent( 1, 1 );
103
104 // make vertex (0, 0, 0, 0)
105 GenVertex* vtx = new GenVertex();
106 evt->add_vertex( vtx );
107
108 // sample particles
109 for ( auto pdg_code : m_parts.value() )
110 {
111 const HepPDT::ParticleData* part =
112 m_particle_table->particle( HepPDT::ParticleID( abs( pdg_code ) ) );
113
114 double mass = part ? part->mass().value() : 0.0;
115
116 // sample momentum
117 double p = CLHEP::RandFlat::shoot( m_rndm_engine, m_p1, m_p2 );
118 double cos_theta = CLHEP::RandFlat::shoot( m_rndm_engine, m_costheta1, m_costheta2 );
119 double phi = CLHEP::RandFlat::shoot( m_rndm_engine, m_phi1, m_phi2 );
120
121 // calculate px, py, pz
122 double sin_theta = sqrt( 1.0 - cos_theta * cos_theta );
123 double pt = p * sin_theta;
124
125 double px = pt * cos( phi );
126 double py = pt * sin( phi );
127 double pz = p * cos_theta;
128
129 CLHEP::HepLorentzVector p4;
130 p4.setVectM( CLHEP::Hep3Vector( px, py, pz ), mass );
131
132 vtx->add_particle_out( new GenParticle( p4, pdg_code, 1 ) );
133 }
134
135 std::vector<long> seeds{ m_rndm_engine->getSeeds()[0], m_rndm_engine->getSeeds()[1] };
136 evt->set_random_states( seeds );
137
138 // add event to collection
139 McGenEventCol mc_col;
140 mc_col.push_back( new McGenEvent( evt ) );
141 return mc_col;
142 };
143
144private:
145 IntegerArrayProperty m_parts{
146 this, "PdgList", { 11, -11 }, "List of PDG codes to be generated" };
147
148 DoubleArrayProperty m_p_range{
149 this, "PRange", { 0.1, 1.8 }, "Range of momentum to be sampled" };
150
151 DoubleArrayProperty m_costheta_range{
152 this, "CosthetaRange", { -1.0, 1.0 }, "Range of cos(theta) to be sampled" };
153
154 DoubleArrayProperty m_phi_range{
155 this, "PhiRange", { -M_PI, M_PI }, "Range of phi to be sampled" };
156
157 SmartIF<IBesRndmGenSvc> m_rndm_svc;
158
159 CLHEP::HepRandomEngine* m_rndm_engine{ nullptr };
160 HepPDT::ParticleDataTable* m_particle_table{ nullptr };
161
162 double m_p1{ 0.0 };
163 double m_p2{ 0.0 };
164 double m_costheta1{ 0.0 };
165 double m_costheta2{ 0.0 };
166 double m_phi1{ 0.0 };
167 double m_phi2{ 0.0 };
168};
169
DECLARE_COMPONENT(BesBdkRc)
double mass
ObjectVector< McGenEvent > McGenEventCol
#define M_PI
Definition TConstant.h:4
McGenEventCol operator()(const EventContext &ctx) const override
StatusCode initialize() override
DummyParticleGun(const std::string &name, ISvcLocator *pSvcLocator)