00001
00015 #include "GtGunGenTool.h"
00016
00017 #include "GaudiKernel/IRndmGenSvc.h"
00018 #include "GaudiKernel/IParticlePropertySvc.h"
00019 #include "GaudiKernel/ParticleProperty.h"
00020 #include "GaudiKernel/Vector3DTypes.h"
00021
00022 #include "HepMC/GenEvent.h"
00023 #include "HepMC/GenParticle.h"
00024 #include "HepMC/GenVertex.h"
00025
00026 #include "CLHEP/Units/SystemOfUnits.h"
00027 #include "CLHEP/Vector/ThreeVector.h"
00028
00029 using namespace CLHEP;
00030
00031 GtGunGenTool::GtGunGenTool(const std::string& type,
00032 const std::string& name,
00033 const IInterface* parent)
00034 : GaudiTool(type,name,parent)
00035 , m_direction(3,0)
00036 , m_pid(0)
00037 , m_mass(0)
00038 {
00039 declareInterface<IHepMCEventMutator>(this);
00040
00041 declareProperty("ParticleName", m_particleName = "",
00042 "PDG particle name");
00043 declareProperty("ParticlesPerEvent",m_particlesPerEvent = 1,
00044 "Number of particles per event to generate.");
00045 declareProperty("MomentumMode", m_momentumMode = "Fixed","Momentum mode");
00046 declareProperty("Momentum", m_momentum = 1.0*MeV,"Particle momentum");
00047 m_momentum.verifier().setLower(0.*eV);
00048 declareProperty("MomentumSpread", m_momentumSpread = 0,"Momentum spread");
00049 declareProperty("MomentumInterpretation",m_momentumInterpretation = "Momentum","Valid interpretation values are Momentum(default), KineticEnergy, TotalEnergy") ;
00050 declareProperty("DirectionMode", m_directionMode = "Fixed","Direction mode");
00051 m_direction[2] = 1.0;
00052 declareProperty("Direction", m_direction,"Direction");
00053 declareProperty("DirectionSpread", m_directionSpread = 0,"Direction spread for cos(zenith angle)");
00054 declareProperty("PolarizeMode", m_polarizeMode = "None",
00055 "Type of polarization of the particle.");
00056 }
00057
00058 GtGunGenTool::~GtGunGenTool()
00059 {
00060 }
00061
00062 StatusCode GtGunGenTool::initialize()
00063 {
00064 this->GaudiTool::initialize();
00065
00066
00067 IParticlePropertySvc * ppSvc =
00068 svc< IParticlePropertySvc >( "ParticlePropertySvc" , true ) ;
00069 ParticleProperty* particle = 0;
00070
00071
00072 if (m_pid) {
00073 particle = ppSvc->findByStdHepID(m_pid);
00074 if (particle) {
00075 m_mass = particle->mass();
00076 m_particleName = particle->particle();
00077 }
00078 }
00079
00080 if (!particle) {
00081 particle = ppSvc->find(m_particleName);
00082 if (particle) {
00083 m_mass = particle->mass();
00084 m_pid = particle->pdgID();
00085 }
00086 }
00087
00088 if (!particle) {
00089 fatal() << "Failed to find particle named \""
00090 << m_particleName << "\" and with ID "
00091 << m_pid << endreq;
00092 return StatusCode::FAILURE;
00093 }
00094
00095 IRndmGenSvc *rgs = 0;
00096 if (service("RndmGenSvc",rgs,true).isFailure()) {
00097 fatal() << "Failed to get random service" << endreq;
00098 return StatusCode::FAILURE;
00099 }
00100
00101 StatusCode sc;
00102
00103 sc = m_gauss.initialize(rgs, Rndm::Gauss(0,1));
00104 if (sc.isFailure()) {
00105 fatal() << "Failed to initialize gaussian random numbers" << endreq;
00106 return StatusCode::FAILURE;
00107 }
00108 sc = m_uni.initialize(rgs, Rndm::Flat(0,1));
00109 if (sc.isFailure()) {
00110 fatal() << "Failed to initialize uniform random numbers" << endreq;
00111 return StatusCode::FAILURE;
00112 }
00113
00114
00115 Hep3Vector unit(m_direction[0],m_direction[1],m_direction[2]);
00116 unit = unit.unit();
00117 for (int ind=0; ind<3; ++ind) m_direction[ind] = unit[ind];
00118
00119 return StatusCode::SUCCESS;
00120 }
00121
00122 StatusCode GtGunGenTool::finalize()
00123 {
00124
00125 return this->GaudiTool::finalize();
00126 }
00127
00128
00129 StatusCode GtGunGenTool::mutate(HepMC::GenEvent& event)
00130 {
00131 for (int ind=0; ind<m_particlesPerEvent; ++ind) {
00132 if (this->oneVertex(event).isFailure())
00133 return StatusCode::FAILURE;
00134 }
00135 return StatusCode::SUCCESS;
00136 }
00137 StatusCode GtGunGenTool::oneVertex(HepMC::GenEvent& event)
00138 {
00139 CLHEP::Hep3Vector dir;
00140
00141 if (m_directionMode == "Fixed") {
00142 dir.set(m_direction[0],m_direction[1],m_direction[2]);
00143 }
00144 else {
00145
00146 double costh=0;
00147 do {
00148 costh = generateNumber(m_directionMode,1,m_directionSpread);
00149 } while (costh < -1.0||costh > 1.0);
00150
00151 double sinth = sqrt(1-costh*costh);
00152
00153
00154 double phi = generateNumber("Uniform",0.0,360*CLHEP::degree);
00155 double cosphi = cos(phi);
00156 double sinphi = sin(phi);
00157
00158 dir.set(sinth*cosphi,sinth*sinphi,costh);
00159
00160
00161 dir.rotateY(acos(m_direction[2]));
00162
00163 dir.rotateZ(atan2(m_direction[1],m_direction[0]));
00164
00165 }
00166
00167 dir = dir.unit();
00168
00169 double momentum;
00170 do{
00171 momentum = generateNumber(m_momentumMode,m_momentum,m_momentumSpread);
00172 } while (momentum < 0.0);
00173
00174
00175 double energy = sqrt(momentum*momentum + m_mass*m_mass);
00176 if (m_momentumInterpretation == "TotalEnergy") {
00177 energy = momentum ;
00178 if ( energy < m_mass ) {
00179 fatal() << "Cannot set total energy(MeV) = " << energy/CLHEP::MeV
00180 << " of " << m_particleName
00181 << " to be less than particle mass(MeV) = " << m_mass/CLHEP::MeV << endreq;
00182 return StatusCode::FAILURE;
00183 }
00184 momentum = sqrt( (energy+m_mass) * (energy-m_mass) );
00185 }
00186
00187 if (m_momentumInterpretation == "KineticEnergy") {
00188 energy = momentum + m_mass;
00189 momentum = sqrt( (energy+m_mass) * (energy-m_mass) );
00190 }
00191
00192 HepMC::ThreeVector p(momentum*dir);
00193 HepMC::FourVector fourmom(p.x(),p.y(),p.z(),energy);
00194
00195 debug() << m_particleName << " (" << m_pid << ") generated with 4momentum = "
00196 << momentum
00197 << " dir = " << dir
00198 << " momentum(MeV) = " << momentum/CLHEP::MeV
00199 << " energy(MeV) = " << energy/CLHEP::MeV
00200 << " kinetic energy(MeV) = " << (energy-m_mass)/CLHEP::MeV
00201 << endreq;
00202
00203 HepMC::GenParticle* particle = new HepMC::GenParticle(fourmom,m_pid,1);
00204
00205 if (m_polarizeMode == "Random") {
00206 double phi = generateNumber("Uniform",0.0,360*CLHEP::degree);
00207 particle->set_polarization(HepMC::Polarization(0.5*HepMC::HepMC_pi,phi));
00208 }
00209
00210 HepMC::GenVertex* vertex = event.signal_process_vertex();
00211 if (!vertex) {
00212 vertex = new HepMC::GenVertex(HepMC::FourVector(0,0,0,0));
00213 event.set_signal_process_vertex(vertex);
00214 }
00215
00216 vertex->add_particle_out(particle);
00217
00218 return StatusCode::SUCCESS;
00219 }
00220
00221 double GtGunGenTool::generateNumber(const std::string& mode, double mean, double spread)
00222 {
00223 if (mode == "Smeared") {
00224 return m_gauss() * spread + mean;
00225 }
00226 if (mode == "Uniform") {
00227 return (m_uni()*2-1) * spread +mean ;
00228 }
00229 return mean;
00230 }