ATLAS Offline Software
Loading...
Searching...
No Matches
CosmicGenerator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// -------------------------------------------------------------
6// File: CosmicGenerator/CosmicGenerator.cxx
7// Description:
8
9// The output will be stored in the transient event store so it can be
10// passed to the simulation.
11//
12// AuthorList:
13// W. Seligman: Initial Code 08-Nov-2002,
14// based on work by M. Shapiro and I. Hinchliffe
15//
16
17// Modification for increasing efficiency of muon hitting the detector:
18// H. Ma. March 17, 2006
19// Property: ExzCut:
20// if true, the method exzCut(...) will be called to apply a
21// energy dependent position cut on the surface.
22// This rejects low energy muons at large distance.
23// Property: RMax
24// Used by exzCut to reject non-projective muons, which are
25// too far out on the surface
26
27
28// Modifications to accomodate Pixel EndCap C Cosmic Test needs
29// Marian Zdrazil June 7, 2006 mzdrazil@lbl.gov
30//
31// Modifications to accomodate replacement of Pixel EndCap C by a Pixel EndCap A
32// Marian Zdrazil November 24, 2006 mzdrazil@lbl.gov
33//
34// Description:
35// ------------
36// It is easier and actually more useful to leave the EndCap A
37// in the vertical position (the way it is positioned in the ATLAS detector)
38// instead of rotating it clockwise by 90deg which corresponds to the
39// placement during the Pixel EndCap A cosmic test in SR1 in November 2006.
40// This is why we will generate cosmic muons coming from the positive Z-axis
41// direction better than rotating the whole setup in PixelGeoModel.
42
43// Modifications July 3rd 2007, Rob McPherson
44// - Fix mu+/mu- bug (always present in Athena versions)
45// - Fix sign of Py (since tag CosmicGenerator-00-00-21, muons only upward-going)
46
47// Optimize selection of events passed to Geant4 for full simulation:
48// - cut on energy based on pathlength in rock
49// - reweighting of generated cosmic rays
50// - geometrical cut in plane of pixel detector
51//
52// Juerg Beringer November 2007 JBeringer@lgl.gov
53// Robert Cahn November 2007 RNCahn@lbl.gov
54
55
59
60#include "CLHEP/Vector/ThreeVector.h"
61#include "CLHEP/Geometry/Normal3D.h"
62#include "CLHEP/Units/PhysicalConstants.h"
63#include "CLHEP/Random/RandFlat.h"
65
66#include <limits>
67#include <cmath>
68#include <vector>
69#include <string>
70#include <fstream>
71
72
73CLHEP::HepRandomEngine* CosmicGenerator::COSMIC_RANDOM_ENGINE{};
74extern "C" float cosmicrndm_(int* /*dummy*/)
75{
76 return CLHEP::RandFlat::shoot(CosmicGenerator::COSMIC_RANDOM_ENGINE);
77}
78
79//--------------------------------------------------------------------------
80CosmicGenerator::CosmicGenerator(const std::string& name,
81 ISvcLocator* pSvcLocator)
82 : GenModule(name,pSvcLocator)
83//--------------------------------------------------------------------------
84{
85}
86
87//---------------------------------------------------------------------------
89//---------------------------------------------------------------------------
90
91 // Initialize event count.
92
93 m_events = 0;
94
95 m_accepted=0;
96 m_rejected=0;
97
98 if(m_infile.value()=="NONE") {
101
103 gun->SetCosCut(m_ctcut);
105 float flux_withCT = gun->InitializeGenerator();
106
107 ATH_MSG_INFO( "Initialisation cosmic gun done." );
108 ATH_MSG_INFO( "Accepted diff flux after E and cos(theta) cuts = " << flux_withCT << " /cm^2/s" );
109 if (! m_doReweighting) {
110 // The following is only correct w/o reweighting
111 ATH_MSG_INFO( "Accepted total flux after E and cos(theta) cuts = " <<
112 flux_withCT*(m_xhig-m_xlow)/m_mm*(m_zhig-m_zlow)/m_mm << " /s" );
113 }
114
115 }
116 else {
117 ATH_MSG_INFO( "Cosmics are read from file " << m_infile );
118 m_ffile.open(m_infile.value().c_str());
119 if(!m_ffile) {
120 ATH_MSG_FATAL( "Could not open input file - stop! " );
121 return StatusCode::FAILURE;
122 }
123 m_readfile = true;
124 }
125
126 m_center=CLHEP::Hep3Vector(m_IPx, m_IPy, m_IPz);
127
128 m_gendata = std::make_shared<GenData>();
129
130 return StatusCode::SUCCESS;
131
132}
133
134CLHEP::HepLorentzVector CosmicGenerator::generateVertex(void) {
135
136 // Get the pointer to the engine of the stream named SINGLE. If the
137 // stream does not exist is created automaticaly
138 CLHEP::HepRandomEngine* engine = COSMIC_RANDOM_ENGINE;
139
140 // Generate a random number according to the distribution.
141
142 float x_val = CLHEP::RandFlat::shoot(engine, m_xlow, m_xhig);
143 float z_val = CLHEP::RandFlat::shoot(engine, m_zlow, m_zhig);
144
145 // Generate a random number for time offset
146 float t_val = m_tmin; // Assign defined value
147 if(m_tmin < m_tmax){
148 t_val = CLHEP::RandFlat::shoot(engine, m_tmin, m_tmax);
149 }
150 else if(m_tmin.value() == m_tmax.value()){
151 t_val = m_tmin;
152 }
153 else ATH_MSG_FATAL("You specified m_tmin = " << m_tmin << " and m_tmax " << m_tmax);
154 CLHEP::HepLorentzVector p(x_val,m_yval,z_val, t_val*CLHEP::c_light);
155
156 return p;
157
158}
159
160CLHEP::HepLorentzVector CosmicGenerator::generateVertexReweighted(void) {
161
162 // Get the pointer to the engine of the stream named SINGLE. If the
163 // stream does not exist is created automaticaly
164 CLHEP::HepRandomEngine* engine = COSMIC_RANDOM_ENGINE;
165
166 // Generate non-uniform distribution of vertices to reflect azimuthal
167 // angle subtended by the sphere of radiusm m_radius
168 // Inside m_radius, the density of vertices is proportional to 2 pi r dr
169 // Outside m_radius, the density is proportional to 2r arcsin (m_radius/r)
170 // We approximate the latter by its maximum: m_radius * pi
171 // We generate vertices out to m_rvertmax.
172 // Integrating the approximated distribution gives
173 // pi r**2 for r < m_radius and pi m_radius r for r> m_radius
174 // So with ran in (0,1) we take r=max_r * ran for ran>m_radius/max_r
175 // and r= sqrt(m_radius*max_r*ran) for ran<m_radius/max_r
176 // for r>m_radius we use acceptance/rejection by comparing
177 // m_radius * pi * new_ran with 2r arcsin (m_radius/r)
178 int accept=0;
179 float max_r = m_rvertmax;
180 float r_val = 0.;
181 while(accept==0){
182 float ran_one = CLHEP::RandFlat::shoot(engine,0.,1.);
183 if(ran_one>(m_radius/max_r)){
184 r_val = ran_one*max_r;
185 float ran_two = CLHEP::RandFlat::shoot(engine,0.,1.);
186 if(m_radius*M_PI*ran_two<2*r_val*asin(m_radius/r_val)){
187 accept=1;
188 }
189 }
190 else
191 {
192 r_val = std::sqrt(m_radius*max_r*ran_one);
193 accept=1;
194 }
195 }
196 float ran_three= CLHEP::RandFlat::shoot(engine, 0.,2*M_PI);
197 float x_val = r_val*cos(ran_three);
198 float z_val = r_val*sin(ran_three);
199
200 // Generate a random number for time offset
201 float t_val = m_tmin; // Assign defined value
202 if(m_tmin < m_tmax){
203 t_val = CLHEP::RandFlat::shoot(engine, m_tmin, m_tmax);
204 }
205 else if(m_tmin.value() == m_tmax.value()){
206 t_val = m_tmin;
207 }
208 else ATH_MSG_FATAL( " You specified m_tmin = " << m_tmin << " and m_tmax " << m_tmax );
209 CLHEP::HepLorentzVector p(x_val,m_yval,z_val, t_val*CLHEP::c_light);
210
211 return p;
212}
213
214
215//---------------------------------------------------------------------------
217//---------------------------------------------------------------------------
218
219 ++m_events;
220 ATH_MSG_DEBUG( "Event #" << m_events);
221
222 assert(COSMIC_RANDOM_ENGINE != 0);
223 //Re-seed the random number stream
224 long seeds[7];
225 const EventContext& ctx = Gaudi::Hive::currentContext();
226 ATHRNG::calculateSeedsMC21(seeds, "COSMICS", ctx.eventID().event_number(), m_dsid, m_randomSeed);
227 COSMIC_RANDOM_ENGINE->setSeeds(seeds, 0); // NOT THREAD-SAFE
228 CLHEP::HepRandomEngine* engine = COSMIC_RANDOM_ENGINE;
229
230 // clear up the vectors
231 m_fourPos.clear();
232 m_fourMom.clear();
233 m_polarization.clear();
234 m_pdgCode.clear();
235
236
237 if(m_readfile)
238 {
239 if(!m_ffile.eof())
240 {
242 m_ffile >> evt;
243
244 ATH_MSG_VERBOSE( evt );
245
246 HepMC::Polarization thePolarization(0.0,0.0);
247 m_polarization.push_back(thePolarization);
248
249 //
250 // units are already converted to MeV's and mm.
251 //
252 m_fourPos.push_back(evt.Vertex());
253 m_fourMom.push_back(evt.Momentum());
254 m_pdgCode.push_back(evt.pdgID());
255
256 }
257 else
258 {
259 ATH_MSG_FATAL( "End of file reached - stop " );
260 exit(1);
261 return StatusCode::FAILURE;
262 }
263 }
264 else
265 {
266
267 bool accepted=false;
268 CLHEP::HepLorentzVector pp;
270 CLHEP::HepLorentzVector vert;
271 CLHEP::Hep3Vector vert3;
272 double theta1;
273 double phi1;
274 double mag1;
275
276 while(!accepted){
277
278 if (m_doReweighting && m_cavOpt) {
279 // The code here doesn't make sense without the sphere cut in the
280 // cavern optimization that is selected by OptimizeForCavern=True
282 vert3 = CLHEP::Hep3Vector(vert.x(),vert.y(),vert.z());
283
284 double vert_radius=sqrt(vert3.x()*vert3.x() + vert3.z()*vert3.z());
285
286 pp = gun->GenerateEvent();
287
288 theta1=pp.theta();
289 phi1=pp.phi();
290 mag1=pp.rho();
291
292 if (vert_radius>m_radius) {
293 phi1=atan2(vert.z(),vert.x())+M_PI;
294 float delta_phi=std::asin(m_radius/vert_radius);
295 phi1=phi1+CLHEP::RandFlat::shoot(engine, -delta_phi, delta_phi);
296 }
297 pp.setX(mag1*sin(theta1)*std::cos(phi1));
298 pp.setY(mag1*sin(theta1)*std::sin(phi1));
299
300 } else {
301 vert = generateVertex();
302 vert3 = CLHEP::Hep3Vector(vert.x(),vert.y(),vert.z());
303
304 pp = gun->GenerateEvent();
305
306 theta1=pp.theta();
307 phi1=pp.phi();
308 mag1=pp.rho();
309 }
310
311 CLHEP::Hep3Vector pp_corr(mag1*sin(theta1)*std::cos(phi1),
312 -mag1*std::cos(theta1),
313 mag1*std::sin(theta1)*std::sin(phi1));
314 CLHEP::Hep3Vector direction(pp_corr.x(),pp_corr.y(), pp_corr.z());
315
316 // if optimization activated, check for the direction of the generated muon
317 if(m_cavOpt) {
318
319 CLHEP::Hep3Vector center_dir=m_center-vert3;
320 double beta=direction.angle(center_dir);
321 double alpha=std::asin(m_radius/center_dir.r());
322
323 if(std::abs(beta)<alpha) {
324
325 if(m_exzCut) {
326 // Old optimization code - is it still useful?
327 CLHEP::HepLorentzVector pp2(pp_corr.x(),pp_corr.y(), pp_corr.z(), pp.e());
328 if( exzCut(vert3,pp2) ) {
329 accepted=true;
330 }
331 } else {
332
333 accepted = true;
334
335 ATH_MSG_DEBUG( "x0 = " << vert3.x()
336 << ", y0 = " << vert3.y()
337 << ", z0 = " << vert3.z()
338 << ", theta = " << pp.theta()
339 << ", phi = " << pp.phi()
340 << ", energy = " << pp.e()*m_GeV );
341
342 if (m_doPathlengthCut) {
343 double path = pathLengthInRock(vert3.x(),vert3.y(),vert3.z(),pp.theta(),pp.phi());
344 double energyLoss = 2.33e-3 * 244. * path; //FIXME Hardcoded values!
345 ATH_MSG_DEBUG( "Energy loss is " << energyLoss
346 << " --> " << (energyLoss>pp.e()*m_GeV ? "REJECTED" : "ACCEPTED") << " by pathlength cut");
347 if (energyLoss-m_energyCutThreshold > pp.e()*m_GeV) accepted = false;
348 }
349
351 bool aimedAtPixels = pointsAtPixels(vert3.x(),vert3.y(),vert3.z(),pp.theta(),pp.phi());
352 ATH_MSG_DEBUG( (aimedAtPixels ? "AIMED AT PIXELS" : "NOT AIMED AT PIXELS") );
353 if (!aimedAtPixels) accepted = false;
354 }
355
356 // FOR DEBUGGING ONLY
357 if (accepted) {
358 ATH_MSG_VERBOSE("The following event has been accepted for simulation:");
359 ATH_MSG_VERBOSE( "x0 = " << vert3.x() << ", y0 = " << vert3.y() << ", z0 = " << vert3.z()
360 << ", theta = " << pp.theta() << ", phi = " << pp.phi() << ", energy = " << pp.e()*m_GeV );
361
362 if (m_doPathlengthCut) {
363 double path = pathLengthInRock(vert3.x(),vert3.y(),vert3.z(),pp.theta(),pp.phi());
364 double energyLoss = 2.33e-3 * 244. * path;
365 ATH_MSG_VERBOSE( "Energy loss is " << energyLoss
366 << " --> " << (energyLoss>pp.e()*m_GeV ? "REJECTED" : "ACCEPTED") << " by pathlength cut" );
367 }
368
370 bool aimedAtPixels = pointsAtPixels(vert3.x(),vert3.y(),vert3.z(),pp.theta(),pp.phi());
371 ATH_MSG_VERBOSE( (aimedAtPixels ? "AIMED AT PIXELS" : "NOT AIMED AT PIXELS") );
372 }
373
374 }
375
376 }
377 }
378
379 if(accepted) {
380 m_accepted++;
381 } else {
382 ATH_MSG_VERBOSE("Rejected muon due to cavern optimization request!");
383 m_rejected++;
384 }
385 }
386 else if(m_srOneOpt == 1) {
387 CLHEP::Hep3Vector srOneVec(direction.x(), direction.y(), direction.z());
388 if(mag1 < 0) // Check if momentum vector is flipped.
389 srOneVec *= -1;
390
391 if( (srOneVec.phi() >= -2.25) && (srOneVec.phi() <= -1.7) &&
392 (srOneVec.theta() >= 0.85) && (srOneVec.theta() <= 2.25) ) { //FIXME Hardcoded values!
393 accepted = true;
394 m_accepted++;
395 ATH_MSG_DEBUG("Muon accepted by SR1 SCT/TRT optimization!");
396 } else {
397 ATH_MSG_DEBUG("Rejected muon due to SR1 SCT/TRT optimization request!");
398 m_rejected++;
399 }
400 }
401 else if(m_srOneOpt == 2) {
402 CLHEP::Hep3Vector srOneVec(direction.x(), direction.y(), direction.z());
403 if(mag1 < 0) // Check if momentum vector is flipped.
404 srOneVec *= -1;
405
406 if( (srOneVec.phi() >= -1.68) && (srOneVec.phi() <= -1.08) &&
407 (srOneVec.theta() >= 0.29) && (srOneVec.theta() <= 0.72) ) { //FIXME Hardcoded values!
408 accepted = true;
409 m_accepted++;
410 ATH_MSG_DEBUG("Muon accepted by SR1 SCT/TRT EndCapC optimization!");
411 } else {
412 ATH_MSG_DEBUG("Rejected muon due to SR1 SCT/TRT EndcapC optimization request!");
413 m_rejected++;
414 }
415 }
416
417 else if(m_srOnePixECOpt) {
418 CLHEP::Hep3Vector srOneVec(direction.x(), direction.y(), direction.z());
419 if(mag1 < 0) // Check if momentum vector is flipped.
420 srOneVec *= -1;
421
422 if( (srOneVec.phi() >= m_phimin) && (srOneVec.phi() <= m_phimax) &&
423 (srOneVec.theta() >= m_thetamin) && (srOneVec.theta() <= m_thetamax) ) {
424 accepted = true;
425 m_accepted++;
426 ATH_MSG_DEBUG("Muon accepted by SR1 Pixel EndCap optimization!");
427 } else {
428 ATH_MSG_DEBUG("Rejected muon due to SR1 Pixel EndCap optimization request!");
429 m_rejected++;
430 }
431 }
432
433 else if (m_muonECOpt) {
434 double coor_x, coor_y, coor_z;
435 coor_z = m_zpos; // defined in jobOpt.
436 coor_x = direction.x()*(coor_z - vert.z())/direction.z() +vert.x();
437 coor_y = direction.y()*(coor_z - vert.z())/direction.z() +vert.y();
438 if( ((coor_x)*(coor_x) + (coor_y)*(coor_y)) <= m_radius*m_radius ) {
439 accepted = true;
440 m_accepted++;
441 } else {
442 coor_z = -m_zpos;
443 coor_x = direction.x()*(coor_z - vert.z())/direction.z() +vert.x();
444 coor_y = direction.y()*(coor_z - vert.z())/direction.z() +vert.y();
445 if( ((coor_x)*(coor_x) + (coor_y)*(coor_y)) <= m_radius*m_radius ) {
446 accepted = true;
447 m_accepted++;
448 } else {
449 ATH_MSG_DEBUG("Rejected muon due to Muon EndCap optimization request!");
450 m_rejected++;
451 }
452 }
453 }
454
455 else accepted=true; // if no opt required accept the first muon
456 }
457
458 pp.setX(pp.x()*m_GeV);
459 pp.setY(pp.y()*m_GeV);
460 pp.setZ(pp.z()*m_GeV);
461 pp.setT(pp.t()*m_GeV);
462
463 // Get the mass of the particle to be generated
464 int charge = gun->GetMuonCharge();
465 // m_pdgCode.push_back(charge*13);
466 m_pdgCode.push_back(charge*-13);
467
468 const auto pmass = m_gendata->particleMass(std::abs(m_pdgCode.back()));
469 if (!pmass){
470 ATH_MSG_FATAL( "Particle with PDG ID=" << std::abs(m_pdgCode.back()) << " returned a nullptr" );
471 return StatusCode::FAILURE;
472 }
473
474 double mass = *pmass;
475
476 // Compute the kinematic values. First, the vertex 4-vector:
477 double x = vert.x();
478 double y = vert.y();
479 double z = vert.z();
480 double t = vert.t();
481
482 // Do we need to swap Y- and Z-axis for the PixelEndCap A Cosmic test ?
483 // if not...do nothing...if so, invert position of y- and z- coordinate
484 //
485 // but not only that...change also the direction of the incoming cosmic muon(s),
486 // they must go towards the pixel endcap A, i.e. y -> -y
487 //
488 if(!m_swapYZAxis)
489 m_fourPos.push_back(CLHEP::HepLorentzVector(x,y,z,t));
490 else
491 m_fourPos.push_back(CLHEP::HepLorentzVector(x,z,y,t));
492
493 // Set the polarization. Realistically, this is going to be zero
494 // for most studies.
495 HepMC::Polarization thePolarization(0.0);
496 m_polarization.push_back(thePolarization);
497
498
499 // The method of calculating e, theta, and phi depends on the user's
500 // commands. Let the KinematicManager handle it.
501 double e = pp.e();
502 double theta = pp.theta();
503 double phi = pp.phi();
504
505 // At this point, we have e, theta, and phi. Put them together to
506 // get the four-momentum.
507
508 double p2 = e*e - mass*mass;
509 if ( p2 < 0 )
510 {
511 ATH_MSG_ERROR( "Event #" << m_events
512 << " E=" << e << ", mass=" << mass
513 << " -- you have generated a tachyon! Increase energy or change particle ID." );
514 return StatusCode::FAILURE;
515 }
516
517 double p = std::sqrt(p2);
518 double px = p*std::sin(theta)*std::cos(phi);
519 double pz = p*std::sin(theta)*std::sin(phi);
520 double py = -p*std::cos(theta);
521
522 // Do we need to swap Y- and Z-axis for the PixelEndCap C Cosmic test ?
523 // if not...do nothing...if so, invert position of y- and z- coordinate
524 //
525 // well and don't forget about the direction of the incoming cosmic muon(s) either
526 // that means: y -> -y
527 //
528 if(!m_swapYZAxis) {
529 // Line below corrupted py sign and forces muons to be upwards, not downwards.
530 // m_fourMom.push_back(CLHEP::HepLorentzVector(px,-py,pz,pp.e()));
531 m_fourMom.push_back(CLHEP::HepLorentzVector(px,py,pz,pp.e()));
532 }
533 else
534 m_fourMom.push_back(CLHEP::HepLorentzVector(px,pz,-py,pp.e()));
535
537 " (x,y,z,t) = ("
538 << m_fourPos.back().x() << ","
539 << m_fourPos.back().y() << ","
540 << m_fourPos.back().z() << ","
541 << m_fourPos.back().t() << "), (Px,Py,Pz,E) = ("
542 << m_fourMom.back().px() << ","
543 << m_fourMom.back().py() << ","
544 << m_fourMom.back().pz() << ","
545 << m_fourMom.back().e() << ")" );
547 " (theta,phi) = (" << theta << "," << phi << "), "
548 << "polarization(theta,phi) = ("<< m_polarization.back().theta() << ","<< m_polarization.back().phi() << ")" );
549 }
550 return StatusCode::SUCCESS;
551
552}
553
554
555//---------------------------------------------------------------------------
557//---------------------------------------------------------------------------
558 // Get the KinematicManager.
559
560 if(m_cavOpt){
561
562 ATH_MSG_INFO("********************************************");
563 ATH_MSG_INFO("** you have run CosmicGenerator with some ");
564 ATH_MSG_INFO("** optimizations for cavern simulation");
565 ATH_MSG_INFO("** "<<m_accepted<<" muons were accepted");
566 ATH_MSG_INFO("** "<<m_rejected<<" muons were rejected");
567 ATH_MSG_INFO("********************************************");
568
569 }
570 if(m_srOneOpt == 1){
571
572 ATH_MSG_INFO("**********************************************");
573 ATH_MSG_INFO("** you have run CosmicGenerator with some ");
574 ATH_MSG_INFO("** optimizations for SR1 SCT/TRT simulation");
575 ATH_MSG_INFO("** "<<m_accepted<<" muons were accepted");
576 ATH_MSG_INFO("** "<<m_rejected<<" muons were rejected");
577 ATH_MSG_INFO("**********************************************");
578
579 }
580 if(m_srOneOpt == 2){
581
582 ATH_MSG_INFO("**********************************************");
583 ATH_MSG_INFO("** you have run CosmicGenerator with some ");
584 ATH_MSG_INFO("** optimizations for SR1 SCT/TRT EndcapC simulation");
585 ATH_MSG_INFO("** "<<m_accepted<<" muons were accepted");
586 ATH_MSG_INFO("** "<<m_rejected<<" muons were rejected");
587 ATH_MSG_INFO("**********************************************");
588
589 }
590
591 if(m_srOnePixECOpt){
592
593 ATH_MSG_INFO("***************************************************");
594 ATH_MSG_INFO("** you have run CosmicGenerator with some ");
595 ATH_MSG_INFO("** optimizations for SR1 Pixel EndCap simulation");
596 ATH_MSG_INFO("** "<<m_accepted<<" muons were accepted");
597 ATH_MSG_INFO("** "<<m_rejected<<" muons were rejected");
598 ATH_MSG_INFO("***************************************************");
599
600 if(m_swapYZAxis){
601 ATH_MSG_INFO("***************************************************");
602 ATH_MSG_INFO(" You have swapped Y- and Z-axis, i.e. muons are ");
603 ATH_MSG_INFO(" not coming from the top any more !!! ");
604 ATH_MSG_INFO("***************************************************");
605 }
606
607 }
608
609 if(m_muonECOpt) {
610
611 ATH_MSG_INFO("***************************************************");
612 ATH_MSG_INFO("** you have run CosmicGenerator with some " );
613 ATH_MSG_INFO("** filters for cosmic muon simulation" );
614 ATH_MSG_INFO("** "<<m_accepted<<" muons were accepted" );
615 ATH_MSG_INFO("** "<<m_rejected<<" muons were rejected" );
616 ATH_MSG_INFO("***************************************************");
617 }
618
619 return StatusCode::SUCCESS;
620}
621
622
623//---------------------------------------------------------------------------
625//---------------------------------------------------------------------------
626
627
628 // loop over generated vertices
629 if(m_fourMom.size()==m_fourPos.size()&&m_fourMom.size()==m_polarization.size()){
630
631 for(std::size_t v=0;v<m_fourMom.size();++v){
632
633 // Note: The vertex and particle are owned by the event, so the
634 // event is responsible for those pointers.
635
636 // Create the particle, and specify its polarization.
637
640
641 // Create the vertex, and add the particle to the vertex.
643 vertex->add_particle_out( std::move(particle) );
644
645 // Add the vertex to the event.
646 event->add_vertex( std::move(vertex) );
647
648 }
649
650 event->set_event_number(m_events); // Set the event number
651 if (event->weights().empty()){
652 event->weights().push_back(1.0);
653 }
654 return StatusCode::SUCCESS;
655 } else {
656 ATH_MSG_ERROR("Wrong different number of vertexes/momenta/polaritazions!");
657 return StatusCode::FAILURE;
658 }
659
660}
661
662
663// Energy dependent position cut on the surface.
664bool CosmicGenerator::exzCut(const CLHEP::Hep3Vector& pos,const CLHEP::HepLorentzVector& p)
665{
666// p is in GeV...
667
668 double r =0;
669 bool cut = false;
670 if(pos.z()<0){
671 r = std::sqrt((std::pow(pos.x(),2)+std::pow(pos.z()+28000,2))) ; //FIXME Hardcoded values!
672 double e = 0.45238*r+5000 ; //FIXME Hardcoded values!
673 cut = p.e()*m_GeV>e;
674 }
675 else
676 {
677 r = std::sqrt((std::pow(pos.x(),2)+std::pow(pos.z()-20000,2))) ; //FIXME Hardcoded values!
678 if(r<15000) { //FIXME Hardcoded values!
679 cut = true;
680 } else
681 {
682 double e = 0.461538*(r-15000)+10000 ; //FIXME Hardcoded values!
683 cut = p.e()*m_GeV>e;
684 ATH_MSG_VERBOSE("z>0 r , e, p.e = "<<r <<" " <<e <<" " <<p.e()*m_GeV);
685 }
686 }
687
688 cut = cut && r < m_rmax ;
689
690 return cut;
691}
692
693
694// Estimate pathlength in rock towards the pixel detector, taking into account both
695// the PX14 and PX16 shafts. The shaft positions are currently hard-coded.
696double CosmicGenerator::pathLengthInRock(double xgen, double ygen, double zgen, double theta, double phi) {
697 // y is vertical direction, z along beam, major shaft has z>0
698
699 // Definition of shafts and cavern
700 double p14_x = 1700; //FIXME Hardcoded values!
701 double p14_z = 13500; //FIXME Hardcoded values!
702 double p14_radius = 9000.; //FIXME Hardcoded values!
703 double p16_x = 1700; //FIXME Hardcoded values!
704 double p16_z = -20000; //FIXME Hardcoded values!
705 double p16_radius = 6300.; //FIXME Hardcoded values!
706 double y1 = 26400; // ! mm cavern height above IP //FIXME Hardcoded values!
707
708 // direction of trajectory
709 // x=x0 - t sinth cosphi; y=y0 + t costh; z=z0 - t sinth sinphi
710 double cosphi = std::cos(phi);
711 double sinphi = std::sin(phi);
712 double costh = std::cos(theta);
713 double sinth = std::sin(theta);
714
715 double y0 = m_ysurface;
716 double t = (ygen-y0)/costh;
717 double x0 = xgen + t*sinth*cosphi; // x position at y=0
718 double z0 = zgen + t*sinth*sinphi; // z position at y=0
719
720 // full path length ignoring shaft
721 double full_distance = (y0-y1)/costh;
722
723 // does trajectory intersect p14 cylinder?
724 double z_mid14 = (x0-p14_x)*sinphi-(z0-p14_z)*cosphi;
725 double min_dist14 = std::abs(z_mid14); //minimum distance of line from center
726 double shaft_distance14 = 0.;
727 if (min_dist14<p14_radius) {
728
729 // z values at intersections
730 double z_plus14 = -cosphi*z_mid14+sinphi*std::sqrt(std::pow(p14_radius,2.)-std::pow(z_mid14,2.)) + p14_z;
731 double z_minus14 = -cosphi*z_mid14-sinphi*std::sqrt(std::pow(p14_radius,2.)-std::pow(z_mid14,2.)) + p14_z;
732
733 // y values at intersections
734 double y_plus14 = y0-costh*(z_plus14-z0)/sinth/sinphi;
735 double y_minus14 = y0-costh*(z_minus14-z0)/sinth/sinphi;
736 double y_great14 = y_plus14>y_minus14 ? y_plus14 : y_minus14;
737 double y_less14 = y_plus14>y_minus14 ? y_minus14 : y_plus14;
738
739 // top intersection must occur above bottom of shaft
740 if ( (y_great14>y1) && (y_less14<y0) ) {
741 double y_top14 = y_great14<y0 ? y_great14 : y0;
742 double y_bottom14 = y_less14>y1 ? y_less14 : y1;
743 shaft_distance14 = (y_top14-y_bottom14)/costh;
744 }
745 }
746
747 // does trajectory intersect p16 cylinder?
748 double z_mid16 = (x0-p16_x)*sinphi-(z0-p16_z)*cosphi;
749 double min_dist16 = std::abs(z_mid16);
750 double shaft_distance16 = 0.;
751 if (min_dist16<p16_radius) {
752
753 // z values at intersections
754 double z_plus16 = -cosphi*z_mid16+sinphi*std::sqrt(std::pow(p16_radius,2.)-std::pow(z_mid16,2.)) + p16_z;
755 double z_minus16 = -cosphi*z_mid16-sinphi*std::sqrt(std::pow(p16_radius,2.)-std::pow(z_mid16,2.)) + p16_z;
756
757 // determine y values at intersections
758 double y_plus16 = y0-costh*(z_plus16-z0)/sinth/sinphi;
759 double y_minus16 = y0-costh*(z_minus16-z0)/sinth/sinphi;
760 double y_great16 = y_plus16>y_minus16 ? y_plus16 : y_minus16;
761 double y_less16 = y_plus16>y_minus16 ? y_minus16 : y_plus16;
762
763 // top intersection must occur above bottom of shaft
764 if ( (y_great16>y1) && (y_less16<y0) ) {
765 double y_top16 = y_great16<y0 ? y_great16 : y0;
766 double y_bottom16 = y_less16>y1 ? y_less16 : y1;
767 shaft_distance16 = (y_top16-y_bottom16)/costh;
768 }
769 }
770
771 double rock_distance = full_distance - shaft_distance14-shaft_distance16;
772 return rock_distance;
773}
774
775
776// Check if trajectory points towards a horizontal rectangle centered at the pixel detector
777bool CosmicGenerator::pointsAtPixels(double xgen, double ygen, double zgen, double theta, double phi) {
778 // y is vertical direction, z along beam, major shaft has z<0
779 bool does = false;
780
781 // direction of trajectory
782 // x=xgen+ t sinth cosphi; y=ygen+t costh; z=zgen+t sinth sinphi
783 double cosphi = std::cos(phi);
784 double sinphi = std::sin(phi);
785 double costh = std::cos(theta);
786 double sinth = std::sin(theta);
787 double t = ygen/costh; //for parameterized trajectory
788 double x_pos = xgen + t*sinth*cosphi; //x position at y=0
789 double z_pos = zgen + t*sinth*sinphi; //z position at y=0
790
791 ATH_MSG_VERBOSE("x_pos = " << x_pos << ", z_pos = " << z_pos);
792
793 if((std::abs(x_pos)<m_pixelplanemaxx)&&(std::abs(z_pos)<m_pixelplanemaxz)){
794 does=true;
795 }
796
797 return does;
798}
#define M_PI
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
float cosmicrndm_(int *)
#define y
#define x
#define z
BooleanProperty m_doAimedAtPixelsCut
FloatProperty m_thetamax
FloatProperty m_zhig
std::vector< CLHEP::HepLorentzVector > m_fourPos
FloatProperty m_IPz
FloatProperty m_xhig
FloatProperty m_ctcut
BooleanProperty m_doPathlengthCut
BooleanProperty m_cavOpt
IntegerProperty m_printMod
BooleanProperty m_doReweighting
FloatProperty m_phimin
CLHEP::HepLorentzVector generateVertexReweighted(void)
FloatProperty m_phimax
virtual StatusCode genInitialize()
For initializing the generator, if required.
FloatProperty m_tmin
FloatProperty m_IPy
DoubleProperty m_ysurface
bool exzCut(const CLHEP::Hep3Vector &pos, const CLHEP::HepLorentzVector &p)
DoubleProperty m_pixelplanemaxx
FloatProperty m_emin
std::ifstream m_ffile
static constexpr float m_mm
FloatProperty m_zpos
IntegerProperty m_srOneOpt
bool pointsAtPixels(double xgen, double ygen, double zgen, double theta, double phi)
IntegerProperty m_printEvent
FloatProperty m_tmax
virtual StatusCode fillEvt(HepMC::GenEvent *evt)
For filling the HepMC event object.
std::shared_ptr< GenData > m_gendata
StringProperty m_infile
BooleanProperty m_srOnePixECOpt
DoubleProperty m_energyCutThreshold
static CLHEP::HepRandomEngine * COSMIC_RANDOM_ENGINE
Static pointer to random number generator for use by.
CLHEP::HepLorentzVector generateVertex(void)
BooleanProperty m_exzCut
FloatProperty m_zlow
FloatProperty m_IPx
std::vector< HepMC::Polarization > m_polarization
DoubleProperty m_rvertmax
std::vector< CLHEP::HepLorentzVector > m_fourMom
CLHEP::Hep3Vector m_center
DoubleProperty m_pixelplanemaxz
FloatProperty m_emax
FloatProperty m_thetamin
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
FloatProperty m_yval
CosmicGenerator(const std::string &name, ISvcLocator *pSvcLocator)
FloatProperty m_radius
BooleanProperty m_muonECOpt
static constexpr float m_GeV
BooleanProperty m_swapYZAxis
std::vector< int > m_pdgCode
FloatProperty m_rmax
virtual StatusCode genFinalize()
For finalising the generator, if required.
FloatProperty m_xlow
double pathLengthInRock(double xgen, double ygen, double zgen, double theta, double phi)
IntegerProperty m_dsid
void PrintLevel(int printevt, int printmod)
Definition CosmicGun.cxx:94
void SetEnergyRange(float emin, float emax)
int GetMuonCharge(void)
float InitializeGenerator()
Definition CosmicGun.cxx:85
CLHEP::HepLorentzVector GenerateEvent(void)
void SetCosCut(float ctcut)
static CosmicGun * GetCosmicGun(void)
Definition CosmicGun.cxx:53
GenModule(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Definition GenModule.cxx:14
CLHEP::HepRandomEngine * getRandomEngineDuringInitialize(const std::string &streamName, unsigned long int randomSeedOffset, unsigned int conditionsRun=1, unsigned int lbn=1) const
Definition GenModule.cxx:53
IntegerProperty m_randomSeed
Seed for random number engine.
Definition GenModule.h:84
int r
Definition globals.cxx:22
void calculateSeedsMC21(long *seeds, const std::string &algName, uint64_t ev, uint64_t run, uint64_t offset=0)
Set the random seed using a string (e.g.
void set_polarization(T &a, const Polarization &b)
HepMC3::FourVector FourVector
GenParticlePtr newGenParticlePtr(const HepMC3::FourVector &mom=HepMC3::FourVector::ZERO_VECTOR(), int pid=0, int status=0)
Definition GenParticle.h:21
HepMC3::GenParticlePtr GenParticlePtr
Definition GenParticle.h:19
GenVertexPtr newGenVertexPtr(const HepMC3::FourVector &pos=HepMC3::FourVector::ZERO_VECTOR(), const int i=0)
Definition GenVertex.h:25
HepMC3::GenVertexPtr GenVertexPtr
Definition GenVertex.h:23
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39