00001
00002
00004
00005
00006 #include "GeneratorInterface/CosmicMuonGenerator/interface/CosmicMuonGenerator.h"
00007
00008 void CosmicMuonGenerator::runCMG(){
00009 initialize();
00010 for (unsigned int iGen=0; iGen<NumberOfEvents; ++iGen){ nextEvent(); }
00011 terminate();
00012 }
00013
00014 void CosmicMuonGenerator::initialize(){
00015 checkIn();
00016 if (NumberOfEvents > 0){
00017 RanGen.SetSeed(RanSeed);
00018
00019 double RadiusTargetEff = RadiusOfTarget;
00020 double Z_DistTargetEff = ZDistOfTarget;
00021 double Z_CentrTargetEff = ZCentrOfTarget;
00022 if(TrackerOnly==true){
00023 RadiusTargetEff = RadiusTracker;
00024 Z_DistTargetEff = Z_DistTracker;
00025 }
00026 Target3dRadius = sqrt(RadiusTargetEff*RadiusTargetEff + Z_DistTargetEff*Z_DistTargetEff) + MinStepSize;
00027 if (Debug) std::cout << " radius of sphere around target = " << Target3dRadius << " mm" << std::endl;
00028 SurfaceRadius = (SurfaceOfEarth+PlugWidth+RadiusTargetEff)*tan(MaxTheta) + Target3dRadius;
00029 if (Debug) std::cout << " starting point radius at Surface + PlugWidth = " << SurfaceRadius << " mm" << std::endl;
00030
00031 OneMuoEvt.PlugVx = PlugVx;
00032 OneMuoEvt.PlugVz = PlugVz;
00033
00034 Cosmics->initialize(MinP, MaxP, MinTheta, MaxTheta, RanSeed, TIFOnly_constant, TIFOnly_linear);
00035
00036 #if ROOT_INTERACTIVE
00037
00038 TH1D* ene = new TH1D("ene","generated energy",210,0.,1050.);
00039 TH1D* the = new TH1D("the","generated theta",90,0.,90.);
00040 TH1D* phi = new TH1D("phi","generated phi",120,0.,360.);
00041 TH3F* ver = new TH3F("ver","Z-X-Y coordinates",50,-25.,25.,20,-10.,10.,20,-10.,10.);
00042 #endif
00043 if (EventDisplay) initEvDis();
00044 std::cout << std::endl;
00045 std::cout << " generating " << NumberOfEvents << " events with random seed " << RanSeed << std::endl;
00046 NotInitialized = false;
00047 }
00048 }
00049
00050 void CosmicMuonGenerator::nextEvent(){
00051
00052 double E = 0.; double Theta = 0.; double Phi = 0.; double RxzV = 0.; double PhiV = 0.;
00053 if (int(Nsel)%100 == 0) std::cout << " generated " << int(Nsel) << " events" << std::endl;
00054
00055 bool notSelected = true;
00056 while (notSelected){
00057 bool badMomentumGenerated = true;
00058 while (badMomentumGenerated){
00059 Cosmics->generate();
00060 E = sqrt(Cosmics->momentum_times_charge()*Cosmics->momentum_times_charge() + MuonMass*MuonMass);
00061 Theta = TMath::ACos( Cosmics->cos_theta() ) ;
00062 Ngen+=1.;
00063 badMomentumGenerated = false;
00064 Phi = RanGen.Rndm()*(MaxPhi-MinPhi) + MinPhi;
00065 }
00066 Norm->events_n100cos(E, Theta);
00067 Ndiced += 1;
00068
00069
00070 double Nver = 0.;
00071 bool badVertexGenerated = true;
00072 while (badVertexGenerated){
00073 RxzV = sqrt(RanGen.Rndm())*SurfaceRadius;
00074 PhiV = RanGen.Rndm()*TwoPi;
00075
00076 double dPhi = Pi; if (RxzV > Target3dRadius) dPhi = asin(Target3dRadius/RxzV);
00077 double rotPhi = PhiV + Pi; if (rotPhi > TwoPi) rotPhi -= TwoPi;
00078 double disPhi = fabs(rotPhi - Phi); if (disPhi > Pi) disPhi = TwoPi - disPhi;
00079 if (disPhi < dPhi) badVertexGenerated = false;
00080 Nver+=1.;
00081 }
00082 Ngen += (Nver-1.);
00083
00084
00085 int id = 13;
00086 if (Cosmics->momentum_times_charge() >0.) id = -13;
00087 double absMom = sqrt(E*E - MuonMass*MuonMass);
00088 double verMom = absMom*cos(Theta);
00089 double horMom = absMom*sin(Theta);
00090 double Px = horMom*sin(Phi);
00091 double Py = -verMom;
00092 double Pz = horMom*cos(Phi);
00093 double Vx = RxzV*sin(PhiV);
00094 double Vy = SurfaceOfEarth + PlugWidth;
00095 double Vz = RxzV*cos(PhiV);
00096 double T0 = (RanGen.Rndm()*(MaxT0-MinT0) + MinT0)*SpeedOfLight;
00097 OneMuoEvt.create(id, Px, Py, Pz, E, MuonMass, Vx, Vy, Vz, T0);
00098
00099 if (goodOrientation()) OneMuoEvt.propagate(ElossScaleFactor, RadiusOfTarget, ZDistOfTarget, ZCentrOfTarget, TrackerOnly, MTCCHalf);
00100
00101 if (OneMuoEvt.hitTarget() && sqrt(OneMuoEvt.e()*OneMuoEvt.e() - MuonMass*MuonMass) > MinP_CMS){
00102 Nsel+=1.;
00103 notSelected = false;
00104 }
00105 }
00106
00107 #if ROOT_INTERACTIVE
00108 ene->Fill(OneMuoEvt.e());
00109 the->Fill((OneMuoEvt.theta()*Rad2Deg));
00110 phi->Fill((OneMuoEvt.phi()*Rad2Deg));
00111 ver->Fill((OneMuoEvt.vz()/1000.),(OneMuoEvt.vx()/1000.),(OneMuoEvt.vy()/1000.));
00112 #endif
00113 if (Debug){
00114 std::cout << "new event" << std::endl;
00115 std::cout << " Px,Py,Pz,E,m = " << OneMuoEvt.px() << ", " << OneMuoEvt.py() << ", "
00116 << OneMuoEvt.pz() << ", " << OneMuoEvt.e() << ", " << OneMuoEvt.m() << " GeV" << std::endl;
00117 std::cout << " Vx,Vy,Vz,t0 = " << OneMuoEvt.vx() << ", " << OneMuoEvt.vy() << ", "
00118 << OneMuoEvt.vz() << ", " << OneMuoEvt.t0() << " mm" << std::endl;
00119 }
00120 if (EventDisplay) displayEv();
00121
00122 }
00123
00124 void CosmicMuonGenerator::terminate(){
00125 if (NumberOfEvents > 0){
00126 std::cout << std::endl;
00127 std::cout << "*********************************************************" << std::endl;
00128 std::cout << "*********************************************************" << std::endl;
00129 std::cout << "*** ***" << std::endl;
00130 std::cout << "*** C O S M I C M U O N S T A T I S T I C S ***" << std::endl;
00131 std::cout << "*** ***" << std::endl;
00132 std::cout << "*********************************************************" << std::endl;
00133 std::cout << "*********************************************************" << std::endl;
00134 std::cout << std::endl;
00135 std::cout << " number of initial cosmic events: " << int(Ngen) << std::endl;
00136 std::cout << " number of actually diced events: " << int(Ndiced) << std::endl;
00137 std::cout << " number of generated and accepted events: " << int(Nsel) << std::endl;
00138 double selEff = Nsel/Ngen;
00139 std::cout << " event selection efficiency: " << selEff*100. << "%" << std::endl;
00140 int n100cos = Norm->events_n100cos(0., 0.);
00141 std::cout << " events with ~100 GeV and 1 - cos(theta) < 1/2pi: " << n100cos << std::endl;
00142 std::cout << std::endl;
00143 std::cout << " momentum range: " << MinP << " ... " << MaxP << " GeV" << std::endl;
00144 std::cout << " theta range: " << MinTheta*Rad2Deg << " ... " << MaxTheta*Rad2Deg << " deg" << std::endl;
00145 std::cout << " phi range: " << MinPhi*Rad2Deg << " ... " << MaxPhi*Rad2Deg << " deg" << std::endl;
00146 std::cout << " time range: " << MinT0 << " ... " << MaxT0 << " ns" << std::endl;
00147 std::cout << " energy loss: " << ElossScaleFactor*100. << "%" << std::endl;
00148 std::cout << std::endl;
00149 double area = 1.e-6*Pi*SurfaceRadius*SurfaceRadius;
00150 std::cout << " area of initial cosmics on Surface + PlugWidth: " << area << " m^2" << std::endl;
00151 std::cout << " depth of CMS detector (from Surface, without PlugWidth)): " << SurfaceOfEarth/1000 << " m" << std::endl;
00152
00153 if(n100cos>0 && MaxTheta<84.26*Deg2Rad){
00154
00155
00156
00157
00158
00159
00160 EventRate= (Ndiced * Norm->norm(n100cos)) * area * selEff;
00161 rateErr_stat = EventRate/sqrt( (double) n100cos);
00162 rateErr_syst = EventRate/2.63e-3 * 0.06e-3;
00163
00164
00165 if(MaxTheta<0.572){
00166 double spacean = 2.*Pi*(1.-cos(MaxTheta));
00167 EventRate= (Ndiced * Norm->norm(n100cos)) * area * selEff * spacean;
00168 rateErr_stat = EventRate/sqrt( (double) n100cos);
00169 rateErr_syst = EventRate/2.63e-3 * 0.06e-3;
00170 }
00171
00172 }else{
00173 EventRate=Nsel;
00174 rateErr_stat =Nsel;
00175 rateErr_syst =Nsel;
00176 std::cout << std::endl;
00177 if (MinP > 100.)
00178 std::cout << " !!! MinP > 100 GeV. Cannot apply normalisation!" << std::endl;
00179 else if (MaxTheta > 84.26*Deg2Rad)
00180 std::cout << " !!! Note: generated cosmics exceed parameterisation. No flux calculated!" << std::endl;
00181 else
00182 std::cout << " !!! Not enough statistics to apply normalisation (rate=1 +- 1) !!!" << std::endl;
00183 }
00184
00185 std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
00186 std::cout << " rate is " << EventRate << " +-" << rateErr_stat <<" (stat) " << "+-" <<
00187 rateErr_syst << " (syst) " <<" muons per second" << std::endl;
00188 if(EventRate!=0) std::cout << " number of events corresponds to " << Nsel/EventRate << " s" << std::endl;
00189 std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
00190 std::cout << std::endl;
00191 std::cout << "*********************************************************" << std::endl;
00192 std::cout << "*********************************************************" << std::endl;
00193 }
00194 }
00195
00196 void CosmicMuonGenerator::checkIn(){
00197 if (MinP < 0.){ NumberOfEvents = 0;
00198 std::cout << " CMG-ERR: min.energy is out of range (0 GeV ... inf]" << std::endl << std::endl; }
00199 if (MaxP < 0.){ NumberOfEvents = 0;
00200 std::cout << " CMG-ERR: max.energy is out of range (0 GeV ... inf]" << std::endl << std::endl; }
00201 if (MaxP <= MinP){ NumberOfEvents = 0;
00202 std::cout << " CMG-ERR: max.energy is not greater than min.energy" << std::endl << std::endl; }
00203 if (MinTheta < 0.){ NumberOfEvents = 0;
00204 std::cout << " CMG-ERR: min.theta is out of range [0 deg ... 90 deg)" << std::endl << std::endl; }
00205 if (MaxTheta < 0.){ NumberOfEvents = 0;
00206 std::cout << " CMG-ERR: max.theta is out of range [0 deg ... 90 deg)" << std::endl << std::endl; }
00207 if (MaxTheta <= MinTheta){ NumberOfEvents = 0;
00208 std::cout << " CMG-ERR: max.theta is not greater than min.theta" << std::endl << std::endl; }
00209 if (MinPhi < 0.){ NumberOfEvents = 0;
00210 std::cout << " CMG-ERR: min.phi is out of range [0 deg ... 360 deg]" << std::endl << std::endl; }
00211 if (MaxPhi < 0.){ NumberOfEvents = 0;
00212 std::cout << " CMG-ERR: max.phi is out of range [0 deg ... 360 deg]" << std::endl << std::endl; }
00213 if (MaxPhi <= MinPhi){ NumberOfEvents = 0;
00214 std::cout << " CMG-ERR: max.phi is not greater than min.phi" << std::endl << std::endl; }
00215 if (MaxT0 <= MinT0){ NumberOfEvents = 0;
00216 std::cout << " CMG-ERR: max.t0 is not greater than min.t0" << std::endl << std::endl; }
00217 if (ElossScaleFactor < 0.){ NumberOfEvents = 0;
00218 std::cout << " CMG-ERR: E-loss scale factor is out of range [0 ... inf)" << std::endl << std::endl; }
00219 }
00220
00221 bool CosmicMuonGenerator::goodOrientation(){
00222
00223 bool goodAngles = false;
00224 bool phiaccepted = false;
00225 bool thetaaccepted = false;
00226 double RxzV = sqrt(OneMuoEvt.vx()*OneMuoEvt.vx() + OneMuoEvt.vz()*OneMuoEvt.vz());
00227 double rVY = sqrt(RxzV*RxzV + (SurfaceOfEarth+PlugWidth)*(SurfaceOfEarth+PlugWidth));
00228 double Phi = OneMuoEvt.phi();
00229 double PhiV = atan2(OneMuoEvt.vx(),OneMuoEvt.vz()) + Pi; if (PhiV > TwoPi) PhiV -= TwoPi;
00230 double disPhi = fabs(PhiV - Phi); if (disPhi > Pi) disPhi = TwoPi - disPhi;
00231 double dPhi = Pi; if (RxzV > Target3dRadius) dPhi = asin(Target3dRadius/RxzV);
00232 if (disPhi < dPhi) phiaccepted = true;
00233 double Theta = OneMuoEvt.theta();
00234 double ThetaV = asin(RxzV/rVY);
00235 double dTheta = Pi; if (rVY > Target3dRadius) dTheta = asin(Target3dRadius/rVY);
00236
00237
00238
00239 if (!phiaccepted && RxzV < Target3dRadius)
00240
00241 std::cout << "Rejected phi=" << Phi << " PhiV=" << PhiV
00242 << " dPhi=" << dPhi << " disPhi=" << disPhi
00243 << " RxzV=" << RxzV << " Target3dRadius=" << Target3dRadius
00244 << " Theta=" << Theta << std::endl;
00245
00246 if (fabs(Theta-ThetaV) < dTheta) thetaaccepted = true;
00247 if (phiaccepted && thetaaccepted) goodAngles = true;
00248 return goodAngles;
00249 }
00250
00251 void CosmicMuonGenerator::initEvDis(){
00252 #if ROOT_INTERACTIVE
00253 float rCMS = RadiusCMS/1000.;
00254 float zCMS = Z_DistCMS/1000.;
00255 if(TrackerOnly==true){
00256 rCMS = RadiusTracker/1000.;
00257 zCMS = Z_DistTracker/1000.;
00258 }
00259 TH2F* disXY = new TH2F("disXY","X-Y view",160,-rCMS,rCMS,160,-rCMS,rCMS);
00260 TH2F* disZY = new TH2F("disZY","Z-Y view",150,-zCMS,zCMS,160,-rCMS,rCMS);
00261 gStyle->SetPalette(1,0);
00262 gStyle->SetMarkerColor(1);
00263 gStyle->SetMarkerSize(1.5);
00264 TCanvas *disC = new TCanvas("disC","Cosmic Muon Event Display",0,0,800,410);
00265 disC->Divide(2,1);
00266 disC->cd(1);
00267 gPad->SetTicks(1,1);
00268 disXY->SetMinimum(log10(MinP));
00269 disXY->SetMaximum(log10(MaxP));
00270 disXY->GetXaxis()->SetLabelSize(0.05);
00271 disXY->GetXaxis()->SetTitleSize(0.05);
00272 disXY->GetXaxis()->SetTitleOffset(1.0);
00273 disXY->GetXaxis()->SetTitle("X [m]");
00274 disXY->GetYaxis()->SetLabelSize(0.05);
00275 disXY->GetYaxis()->SetTitleSize(0.05);
00276 disXY->GetYaxis()->SetTitleOffset(0.8);
00277 disXY->GetYaxis()->SetTitle("Y [m]");
00278 disC->cd(2);
00279 gPad->SetGrid(1,1);
00280 gPad->SetTicks(1,1);
00281 disZY->SetMinimum(log10(MinP));
00282 disZY->SetMaximum(log10(MaxP));
00283 disZY->GetXaxis()->SetLabelSize(0.05);
00284 disZY->GetXaxis()->SetTitleSize(0.05);
00285 disZY->GetXaxis()->SetTitleOffset(1.0);
00286 disZY->GetXaxis()->SetTitle("Z [m]");
00287 disZY->GetYaxis()->SetLabelSize(0.05);
00288 disZY->GetYaxis()->SetTitleSize(0.05);
00289 disZY->GetYaxis()->SetTitleOffset(0.8);
00290 disZY->GetYaxis()->SetTitle("Y [m]");
00291 #endif
00292 }
00293
00294 void CosmicMuonGenerator::displayEv(){
00295 #if ROOT_INTERACTIVE
00296 double RadiusDet=RadiusCMS;
00297 double Z_DistDet=Z_DistCMS;
00298 if(TrackerOnly==true){
00299 RadiusDet = RadiusTracker;
00300 Z_DistDet = Z_DistTracker;
00301 }
00302 disXY->Reset();
00303 disZY->Reset();
00304 TMarker* InteractionPoint = new TMarker(0.,0.,2);
00305 TArc* r8m = new TArc(0.,0.,(RadiusDet/1000.));
00306 TLatex* logEaxis = new TLatex(); logEaxis->SetTextSize(0.05);
00307 float energy = float(OneMuoEvt.e());
00308 float verX = float(OneMuoEvt.vx()/1000.);
00309 float verY = float(OneMuoEvt.vy()/1000.);
00310 float verZ = float(OneMuoEvt.vz()/1000.);
00311 float dirX = float(OneMuoEvt.px())/fabs(OneMuoEvt.py());
00312 float dirY = float(OneMuoEvt.py())/fabs(OneMuoEvt.py());
00313 float dirZ = float(OneMuoEvt.pz())/fabs(OneMuoEvt.py());
00314 float yStep = disXY->GetYaxis()->GetBinWidth(1);
00315 int NbinY = disXY->GetYaxis()->GetNbins();
00316 for (int iy=0; iy<NbinY; ++iy){
00317 verX += dirX*yStep;
00318 verY += dirY*yStep;
00319 verZ += dirZ*yStep;
00320 float rXY = sqrt(verX*verX + verY*verY)*1000.;
00321 float absZ = fabs(verZ)*1000.;
00322 if (rXY < RadiusDet && absZ < Z_DistDet){
00323 disXY->Fill(verX,verY,log10(energy));
00324 disZY->Fill(verZ,verY,log10(energy));
00325 disC->cd(1); disXY->Draw("COLZ"); InteractionPoint->Draw("SAME"); r8m->Draw("SAME");
00326 logEaxis->DrawLatex((0.65*RadiusDet/1000.),(1.08*RadiusDet/1000.),"log_{10}E(#mu^{#pm})");
00327 disC->cd(2); disZY->Draw("COL"); InteractionPoint->Draw("SAME");
00328 gPad->Update();
00329 }
00330 }
00331 #endif
00332 }
00333
00334 void CosmicMuonGenerator::setNumberOfEvents(unsigned int N){ if (NotInitialized) NumberOfEvents = N; }
00335
00336 void CosmicMuonGenerator::setRanSeed(int N){ if (NotInitialized) RanSeed = N; }
00337
00338 void CosmicMuonGenerator::setMinP(double P){ if (NotInitialized) MinP = P; }
00339
00340 void CosmicMuonGenerator::setMinP_CMS(double P){ if (NotInitialized) MinP_CMS = P; }
00341
00342 void CosmicMuonGenerator::setMaxP(double P){ if (NotInitialized) MaxP = P; }
00343
00344 void CosmicMuonGenerator::setMinTheta(double Theta){ if (NotInitialized) MinTheta = Theta*Deg2Rad; }
00345
00346 void CosmicMuonGenerator::setMaxTheta(double Theta){ if (NotInitialized) MaxTheta = Theta*Deg2Rad; }
00347
00348 void CosmicMuonGenerator::setMinPhi(double Phi){ if (NotInitialized) MinPhi = Phi*Deg2Rad; }
00349
00350 void CosmicMuonGenerator::setMaxPhi(double Phi){ if (NotInitialized) MaxPhi = Phi*Deg2Rad; }
00351
00352 void CosmicMuonGenerator::setMinT0(double T0){ if (NotInitialized) MinT0 = T0; }
00353
00354 void CosmicMuonGenerator::setMaxT0(double T0){ if (NotInitialized) MaxT0 = T0; }
00355
00356 void CosmicMuonGenerator::setElossScaleFactor(double ElossScaleFact){ if (NotInitialized) ElossScaleFactor = ElossScaleFact; }
00357
00358 void CosmicMuonGenerator::setRadiusOfTarget(double R){ if (NotInitialized) RadiusOfTarget = R; }
00359
00360 void CosmicMuonGenerator::setZDistOfTarget(double Z){ if (NotInitialized) ZDistOfTarget = Z; }
00361
00362 void CosmicMuonGenerator::setZCentrOfTarget(double Z){ if (NotInitialized) ZCentrOfTarget = Z; }
00363
00364 void CosmicMuonGenerator::setTrackerOnly(bool Tracker){ if (NotInitialized) TrackerOnly = Tracker; }
00365
00366 void CosmicMuonGenerator::setTIFOnly_constant(bool TIF){ if (NotInitialized) TIFOnly_constant = TIF; }
00367
00368 void CosmicMuonGenerator::setTIFOnly_linear(bool TIF){ if (NotInitialized) TIFOnly_linear = TIF; }
00369
00370 void CosmicMuonGenerator::setMTCCHalf(bool MTCC){ if (NotInitialized) MTCCHalf = MTCC; }
00371
00372 void CosmicMuonGenerator::setPlugVx(double PlugVtx){ if (NotInitialized) PlugVx = PlugVtx; }
00373 void CosmicMuonGenerator::setPlugVz(double PlugVtz){ if (NotInitialized) PlugVz = PlugVtz; }
00374
00375
00376 double CosmicMuonGenerator::getRate(){ return EventRate; }