00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "GtMuoneratorTool.h"
00011
00012 #include "GaudiKernel/IRndmGenSvc.h"
00013
00014 #include "CLHEP/Units/SystemOfUnits.h"
00015 #include "CLHEP/Units/PhysicalConstants.h"
00016
00017 #include "HepMC/GenEvent.h"
00018 #include "HepMC/GenVertex.h"
00019
00020 #include "TH1F.h"
00021 #include "TFile.h"
00022
00023 #include <fstream>
00024 #include <cassert>
00025
00026 using namespace std;
00027 using namespace CLHEP;
00028
00029 GtMuoneratorTool::GtMuoneratorTool(const std::string& type,
00030 const std::string& name,
00031 const IInterface* parent)
00032 : GaudiTool(type,name,parent)
00033 , m_pmratio(0)
00034 , m_Sx(0), m_Sy(0), m_Sz(0), m_Smax(0)
00035 , m_dphi(0)
00036 {
00037 declareInterface<IHepMCEventMutator>(this);
00038
00039 declareProperty("WhichSite",m_whichSite="",
00040 "Which site (DYB, LA, Mid, Far,SAB)");
00041 declareProperty("Rotation",m_rotation=false,
00042 "Set to true to assume rotation for the given site");
00043 declareProperty("MuonFile",m_muonFileName="",
00044 "Name of file giving muons to sample");
00045 declareProperty("RatioFile",m_ratioFileName="",
00046 "Name of file giving mu+/mu- ratio histogram");
00047 declareProperty("Volume",m_volume="rock",
00048 "Volume name (rock, RPC, ADE)");
00049 info() << "Creating GtMuoneratorTool(\"" << type << "\", \"" << name << "\")" << endreq;
00050 }
00051
00052
00053 GtMuoneratorTool::~GtMuoneratorTool()
00054 {
00055 info() << "Destroying GtMuoneratorTool site=" << m_whichSite
00056 << " MuonFile=" << m_muonFileName
00057 << " RatioFile=" << m_ratioFileName
00058 << " Volume=" << m_volume
00059 << endreq;
00060 }
00061
00062 StatusCode GtMuoneratorTool::initialize()
00063 {
00064
00065 m_rgs = 0;
00066 if (service("RndmGenSvc",m_rgs,true).isFailure()) {
00067 fatal() << "Failed to get random service" << endreq;
00068 return StatusCode::FAILURE;
00069 }
00070 if (m_uni.initialize(m_rgs, Rndm::Flat(0,1)).isFailure()) {
00071 fatal() << "Failed to initialize uniform random numbers" << endreq;
00072 return StatusCode::FAILURE;
00073 }
00074
00075
00076 TFile* file = new TFile(m_ratioFileName.c_str(),"read");
00077 if (file->IsZombie()) {
00078 warning() << "Failed to open ROOT file \"" << m_ratioFileName << "\""
00079 << " will fall back to parametrized ratio"
00080 << endreq;
00081 }
00082 else {
00083 m_pmratio = (TH1F*)file->Get("mu_plus_minus_ratio");
00084
00085 if (!m_pmratio) {
00086 error() << "Failed to get \"mu_plus_minus_ratio\" TH1F from ROOT file "
00087 << m_ratioFileName << endreq;
00088 return StatusCode::FAILURE;
00089 }
00090 }
00091
00092 return ReadMuons();
00093 }
00094
00095 static int GetMuPlusMinusRatioParam(double momInGeV)
00096 {
00097 Double_t par[2]={0.5505,0.6745};
00098 Double_t part1=par[0]/(1+(1.1*momInGeV+1)/115);
00099 Double_t part2=0.054*par[1]/(1+(1.1*momInGeV+1)/850);
00100 Double_t part3=(1-par[0])/(1+(1.1*momInGeV-1)/115);
00101 Double_t part4=0.054*(1-par[1])/(1+(1.1*momInGeV-1)/850);
00102 return (part1+part2)/(part3+part4);
00103 }
00104
00105 double GtMuoneratorTool::GetMuPlusMinusRatio(double momInGeV)
00106 {
00107 if (!m_pmratio) return GetMuPlusMinusRatioParam(momInGeV);
00108
00109 int binno = m_pmratio->FindBin(momInGeV);
00110
00111 if(binno>=1&&binno<=m_pmratio->GetNbinsX())
00112 return m_pmratio->GetBinContent(binno);
00113 return 1.4;
00114 }
00115
00116 int GtMuoneratorTool::GetPIDFromMomentum(double momInGeV)
00117 {
00118 double ratio = GetMuPlusMinusRatio(momInGeV);
00119 double prob_mu_plus = ratio/(1.+ratio);
00120
00121 Rndm::Numbers bi;
00122 if (bi.initialize(m_rgs, Rndm::Binomial(1,prob_mu_plus)).isFailure()) {
00123 fatal() << "Failed to initialize uniform random numbers" << endreq;
00124 return StatusCode::FAILURE;
00125 }
00126 int number = bi();
00127 if (number==0) return 13;
00128 return -13;
00129 }
00130
00131 StatusCode GtMuoneratorTool::ReadMuons()
00132 {
00133
00134
00135
00136 Double_t height_RPC = 0.50*CLHEP::m ;
00137 Double_t thick_RPC = 0.056*CLHEP::m + 0.030*CLHEP::m ;
00138 Double_t overlap_RPC= 1.0*CLHEP::m ;
00139 Double_t extra = 0.05*CLHEP::m ;
00140 Double_t width_near = 10.0*CLHEP::m ;
00141 Double_t width_far = 16.0*CLHEP::m ;
00142 Double_t length = 16.0*CLHEP::m ;
00143 Double_t depth = 10.0*CLHEP::m ;
00144 Double_t air_thick = 0.2*CLHEP::m ;
00145 Double_t height_hall= 15.0*CLHEP::m ;
00146 Double_t top_rock_extra = 2*CLHEP::m;
00147 Double_t side_rock_extra= 4*CLHEP::m;
00148
00149 Double_t bottom_rock_extra = 2*CLHEP::m;
00150
00151 Double_t yDim ;
00152 Double_t xDim ;
00153 Double_t zDim;
00154
00155 Double_t zOffset;
00156
00157
00158
00159 Double_t ADsstRadius=2500*CLHEP::mm;
00160
00161 Double_t ADsstHeight=5000*CLHEP::mm;
00162
00163
00164 Double_t ADadeWall=1.0*CLHEP::cm;
00165
00166 Double_t ADadeHead=1.0*CLHEP::cm;
00167
00168 Double_t ADadeFoot=1.0*CLHEP::cm;
00169
00170 Double_t ADadeRadius=ADsstRadius+ADadeWall;
00171
00172 Double_t ADadeHeight=ADadeFoot+ADsstHeight+ADadeHead;
00173
00174 if (m_volume == "rock") {
00175
00176 zDim=depth + height_hall + top_rock_extra + bottom_rock_extra;
00177
00178 zOffset=(height_hall + top_rock_extra - bottom_rock_extra)/2;
00179
00180 xDim = length + 2.*overlap_RPC + 2.*side_rock_extra;
00181
00182 if (m_whichSite == "DYB" || m_whichSite == "LA") {
00183 yDim=width_near + 2.*overlap_RPC + 2.*side_rock_extra;
00184 }
00185 else if (m_whichSite == "Far") {
00186 yDim=width_far + 2.*overlap_RPC + 2.*side_rock_extra;
00187 }
00188 else {
00189
00190 }
00191 }
00192 else if (m_volume == "RPC") {
00193
00194 zDim=height_RPC + thick_RPC + depth + extra + air_thick;
00195
00196 zOffset=(height_RPC + thick_RPC + extra + air_thick)/2. ;
00197
00198 xDim = length + 2.*overlap_RPC + 2.*extra;
00199
00200 if (m_whichSite == "DYB" || m_whichSite == "LA") {
00201 yDim=width_near + 2.*overlap_RPC + 2.*extra;
00202 }
00203 else if (m_whichSite == "Far") {
00204 yDim=width_far + 2.*overlap_RPC + 2.*extra;
00205 }
00206 else {
00207
00208 }
00209 }
00210 else if (m_volume == "ADE") {
00211
00212 zDim=ADadeHeight;
00213
00214 zOffset=0;
00215
00216 xDim= 2*ADadeRadius;
00217
00218 yDim=xDim;
00219 }
00220 else {
00221 cout<<"muon_generator: *** ERROR *** Invalid volume " << m_volume
00222 << " selected. Valid volume names are rock, RPC and ADE"<<endl;
00223 assert(0);
00224 }
00225
00226 Double_t dphi=0;
00227
00228
00229
00230 ifstream infile;
00231 infile.open(m_muonFileName.c_str(), ios_base::in);
00232 if (!infile.is_open()) {
00233 error() << "Failed to open muon flux file \"" << m_muonFileName << "\""
00234 << endreq;
00235 return StatusCode::FAILURE;
00236 }
00237 debug() << "Opened file \"" << m_muonFileName << "\"" << endreq;
00238
00239 if(m_whichSite == "DYB") {
00240 m_detectorDim = Hep3Vector(xDim, yDim, zDim);
00241 m_detectorCenter = Hep3Vector(0, 0, zOffset );
00242 if(m_rotation) {
00243 dphi = 56.7*degree;
00244 }
00245 }
00246 else if(m_whichSite == "CDR") {
00247 m_detectorDim = Hep3Vector(16.06*CLHEP::m, 10.06*CLHEP::m, 10.0*CLHEP::m );
00248 m_detectorCenter = Hep3Vector(0, 0, -5*CLHEP::m );
00249 dphi = 0;
00250 }
00251 else if(m_whichSite == "LA") {
00252 m_detectorDim = Hep3Vector(xDim, yDim, zDim);
00253 m_detectorCenter = Hep3Vector(0, 0, zOffset );
00254 if(m_rotation) {
00255 dphi = 79.6*degree;
00256 }
00257 }
00258 else if(m_whichSite == "Mid") {
00259 error()<<" No implemented yet. "<<endl;
00260 return StatusCode::FAILURE;
00261 }
00262 else if(m_whichSite == "Far") {
00263 m_detectorDim = Hep3Vector(xDim, yDim, zDim);
00264 m_detectorCenter = Hep3Vector(0, 0, zOffset );
00265 if(m_rotation) {
00266 dphi = 60.5*degree;
00267 }
00268 }
00269 else if(m_whichSite == "SAB") {
00270 m_detectorDim = Hep3Vector(5.2*CLHEP::m, 5.2*CLHEP::m, 5.2*CLHEP::m );
00271 m_detectorCenter = Hep3Vector(0, 0, 0 );
00272 dphi = 0;
00273 }
00274 else {
00275
00276 error() <<"muon_generator: *** ERROR *** Invalid site " << m_whichSite
00277 << " selected. Valid site names are Far, Mid, DYB, LA, CDR,SAB"<<endreq;
00278 return StatusCode::FAILURE;
00279 }
00280
00281
00282
00283
00284 Double_t dimx=0, dimy=0, dimz=0;
00285 Double_t xdet=0, ydet=0, zdet=0;
00286
00287 dimx = m_detectorDim.x()/CLHEP::m;
00288 dimy = m_detectorDim.y()/CLHEP::m;
00289 dimz = m_detectorDim.z()/CLHEP::m;
00290 xdet = m_detectorCenter.x()/CLHEP::m;
00291 ydet = m_detectorCenter.y()/CLHEP::m;
00292 zdet = m_detectorCenter.z()/CLHEP::m;
00293 cout<<"The detector dimension is: "
00294 <<dimx<<"*m, "<<dimy<<"*m, "<<dimz<<"*m"<<endl;
00295 cout<<"The detector center is: "
00296 <<xdet<<"*m, "<<ydet<<"*m, "<<zdet<<"*m"<<endl;
00297 cout<<"The detector angle is: "<<dphi<<endl;
00298 cout<<"MAKE SURE the setting is consistent with Geant4 setting!!!"<<endl;
00299
00300 m_Sz = dimx * dimy;
00301 m_Sx = dimy * dimz;
00302 m_Sy = dimx * dimz;
00303 m_Smax = sqrt(m_Sx*m_Sx + m_Sy*m_Sy + m_Sz*m_Sz);
00304 m_dphi = dphi;
00305
00306
00307
00308
00309 Double_t energy, phi, theta, energy0, phi0, theta0;
00310
00311 Double_t flux_of_site;
00312
00313 char tmp[255];
00314 for (int lineNo=0; lineNo<4; lineNo++) {
00315 infile.getline(tmp, 255);
00316 }
00317
00318 infile.getline(tmp,255,':');
00319 infile>>flux_of_site;
00320 infile.getline(tmp,255);
00321
00322 infile.getline(tmp,255);
00323
00324 while (!infile.eof()) {
00325 infile>>energy>>theta>>phi>>energy0>>theta0>>phi0;
00326 m_muonE.push_back(energy*CLHEP::GeV);
00327 m_muonPhi.push_back(phi);
00328 m_muonTheta.push_back(theta);
00329 verbose() << "Loading muon E=" << energy*CLHEP::GeV
00330 << " phi=" << phi
00331 << " theta=" << theta
00332 << endreq;
00333 }
00334
00335 m_muonE.pop_back();
00336 m_muonPhi.pop_back();
00337 m_muonTheta.pop_back();
00338
00339 return StatusCode::SUCCESS;
00340
00341 }
00342
00343
00344 StatusCode GtMuoneratorTool::finalize()
00345 {
00346 return StatusCode::SUCCESS;
00347 }
00348
00349 StatusCode GtMuoneratorTool::mutate(HepMC::GenEvent& event)
00350 {
00351 double pS_z=0, pS_x=0, pS_y=0;
00352 const double PI = 3.1415926;
00353 Hep3Vector direction;
00354 double muon_mass = 0.105658*CLHEP::GeV;
00355 double weight = 1.;
00356 double arandom=0;
00357 int ievent = 0;
00358
00359 do {
00360 ievent = (int)(m_uni() * (m_muonE.size()-1));
00361 debug() << "Pick muon " << ievent << " out of " << m_muonE.size() << endreq;
00362
00363
00364 double theta = PI - PI * m_muonTheta[ievent]/180;
00365 double phi = PI/2 -PI * m_muonPhi[ievent]/180;
00366 if (phi < 0) phi = phi + 2 * PI;
00367
00368
00369
00370
00371 phi = phi + m_dphi;
00372 if(phi > 2 * PI) phi = phi - 2 * PI;
00373 direction.setX(sin(theta) * cos(phi));
00374 direction.setY(sin(theta) * sin(phi));
00375 direction.setZ(cos(theta));
00376
00377
00378 pS_z = m_Sz * abs(direction.z());
00379 pS_x = m_Sx * abs(direction.x());
00380 pS_y = m_Sy * abs(direction.y());
00381
00382 weight = ( pS_z + pS_x + pS_y )/m_Smax;
00383 arandom = m_uni();
00384 } while ( arandom > weight );
00385
00386
00387
00388 double eMuon = m_muonE[ievent];
00389 double pMuon = sqrt(eMuon*eMuon - muon_mass*muon_mass);
00390 Hep3Vector momentum;
00391 momentum.setX(pMuon * direction.x());
00392 momentum.setY(pMuon * direction.y());
00393 momentum.setZ(pMuon * direction.z());
00394
00395 Hep3Vector position;
00396
00397 if( arandom < pS_z/m_Smax) {
00398 position.setX(m_detectorCenter.x() +
00399 (m_uni()-0.5) * m_detectorDim.x());
00400 position.setY(m_detectorCenter.y() +
00401 (m_uni()-0.5) * m_detectorDim.y());
00402 position.setZ(m_detectorCenter.z() + 0.5 * m_detectorDim.z());
00403
00404 }
00405
00406 else if( arandom < (pS_z + pS_x)/m_Smax) {
00407 position.setY( m_detectorCenter.y() +
00408 (m_uni()-0.5) * m_detectorDim.y() );
00409 position.setZ( m_detectorCenter.z() +
00410 (m_uni()-0.5) * m_detectorDim.z() );
00411 if (direction.x() > 0)
00412 position.setX( m_detectorCenter.x() - 0.5 * m_detectorDim.x() );
00413 if (direction.x() < 0)
00414 position.setX( m_detectorCenter.x() + 0.5 * m_detectorDim.x() );
00415 }
00416
00417 else if( arandom < weight) {
00418 position.setX( m_detectorCenter.x() +
00419 (m_uni()-0.5) * m_detectorDim.x() );
00420 position.setZ( m_detectorCenter.z() +
00421 (m_uni()-0.5) * m_detectorDim.z() );
00422 if (direction.y() > 0)
00423 position.setY( m_detectorCenter.y() - 0.5 * m_detectorDim.y() );
00424 if (direction.y() < 0)
00425 position.setY( m_detectorCenter.y() + 0.5 * m_detectorDim.y() );
00426 }
00427
00428
00429 int pid = GetPIDFromMomentum(momentum.mag()/CLHEP::GeV);
00430
00431 HepMC::GenVertex* vertex = new HepMC::GenVertex(HepMC::FourVector(position.x(),
00432 position.y(),
00433 position.z(), 0));
00434
00435 HepMC::FourVector fourmom(momentum.x(), momentum.y(), momentum.z(), eMuon);
00436
00437 debug() << "momentum.mag()=" << momentum.mag()/CLHEP::GeV << " GeV/c "
00438 << "pMuon=" << pMuon/CLHEP::GeV << " GeV/c "
00439 << "eMuon=" << eMuon/CLHEP::GeV << " GeV "
00440 << "muon_mass=" << muon_mass/CLHEP::MeV << " MeV/c^2 "
00441 << "sqrt(e^2-p^2)=" << sqrt(eMuon*eMuon-pMuon*pMuon)
00442 << endreq;
00443
00444 HepMC::GenParticle* particle = new HepMC::GenParticle(fourmom,pid,1);
00445 particle->set_generated_mass(muon_mass);
00446
00447 vertex->add_particle_out(particle);
00448 event.set_signal_process_vertex(vertex);
00449
00450 return StatusCode::SUCCESS;
00451 }
00452