ATLAS Offline Software
Loading...
Searching...
No Matches
ALFA_BeamTransport.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// ALFA_BeamTransport.cxx, (c) ATLAS Detector software
8
11
12#include "GaudiKernel/ServiceHandle.h"
13
14// FrameWork includes
15#include "GaudiKernel/ITHistSvc.h"
16#include "Gaudi/Property.h"
17
18
19#include "AtlasHepMC/GenEvent.h"
23
24//ROOT headers
25#include "TFile.h"
26#include "TH1.h"
27#include "TString.h"
28
29
30#include <iostream>
31#include <vector>
32
33//================ Constructor =================================================
34
35ALFA_BeamTransport::ALFA_BeamTransport(const std::string& name, ISvcLocator* pSvcLocator)
36 :
37 AthAlgorithm(name,pSvcLocator)
38{
39 declareProperty("ConfDir", m_FPConfig.ConfDir="./config");
40 declareProperty("UseALFA", m_FPConfig.UseALFA=true);
41 declareProperty("Debug", m_WriteDebugOutput=false);
42 declareProperty("IP",m_FPConfig.IP = 1);
43 declareProperty("UseAper",m_FPConfig.useaper = true);
44 declareProperty("apermb",m_FPConfig.apermb = 0.);
45 declareProperty("xcol1",m_FPConfig.xcol1 = 999.);//999e-4 but we need open collimators
46 declareProperty("xcol2",m_FPConfig.xcol2 = 999.);//999e-4
47 declareProperty("BeamEnergy",m_FPConfig.pbeam0 = 7000.);//beam energy
48 declareProperty("RPDistance",m_FPConfig.RPDistance = 237.398);
49 declareProperty("absZMagMax",m_FPConfig.absZMagMax = 500.);//dont read magnets after this value
50
51 //Cuts for production
52 declareProperty("EtaCut",m_EtaCut = 8.);
53 declareProperty("XiCut",m_XiCut = 0.2);
54
55 declareProperty("FPOutputBeam1", m_FPOutputBeam1="Beam1");
56 declareProperty("FPOutputBeam2", m_FPOutputBeam2="Beam2");
57
58}
59
61
62
64{
65 ATH_MSG_INFO("Initializing " << name() << "...");
66 ATH_CHECK(m_eventInfoKey.initialize());
67 ATH_CHECK(m_MCKey.initialize());
68 // open files for beamtracking output
69 // string in char
70 char* cBeam1Name = new char[m_FPOutputBeam1.length()];
71 strcpy(cBeam1Name, m_FPOutputBeam1.c_str());
72 char* cBeam2Name = new char[m_FPOutputBeam2.length()];
73 strcpy(cBeam2Name, m_FPOutputBeam2.c_str());
74
76 m_FileBeam1.open(cBeam1Name);
77 m_FileBeam2.open(cBeam2Name);
78 }
79
80 //delete char arrays
81 delete[] cBeam1Name;
82 delete[] cBeam2Name;
83
84 //Initialisation of FPTracker
85 m_BeamTracker.ALFA_BeamTrack::initialize(m_FPConfig);
86
87 //-----------------------------------------------------------------------------------------
88 ATH_MSG_INFO( name() << " initialize()" );
89 ATH_MSG_INFO( "initialize() successful in " << name() );
90 return StatusCode::SUCCESS;
91}
92
93//================ Finalisation =================================================
94
96{
97 // close outputfiles for FPTracker
99 m_FileBeam1.close();
100 m_FileBeam2.close();
101 }
102 // Code entered here will be executed once at the end of the program run.
103 return StatusCode::SUCCESS;
104}
105
106//================ Execution ====================================================
107
109{
110 // Code entered here will be executed once per event
111 ATH_MSG_DEBUG ("Executing " << name() << "...");
112 //-----------------------------------------------------------------------------------------
113 int run_number;
114 uint64_t evt_number;
115
116 //Set particles counter to zero!
117 //counter for particles marked as outgoing in event record
118 m_pcount=0;
119 //counter for particles marked as incomming in event record
120 m_pint=0;
121
122 //Load event info
123 SG::ReadHandle<xAOD::EventInfo> eventInfo (m_eventInfoKey,getContext());
124 if(!eventInfo.isValid()) {
125 ATH_MSG_ERROR("Could not retrieve EventInfo");
126 return StatusCode::FAILURE;
127 }
128 else {
129 run_number=eventInfo->runNumber();
130 evt_number=eventInfo->eventNumber();
131
132 ATH_MSG_DEBUG("run: " << run_number << " event: " << evt_number);
133 }
134
135 SG::ReadHandle<McEventCollection> mcColl(m_MCKey, getContext());
136 if (!mcColl.isValid()) {
137 ATH_MSG_WARNING("Could not retrieve McEventCollection: " << m_MCKey);
138 return StatusCode::SUCCESS;
139 }
140 // Loop over all events in McEventCollectio
141 ATH_MSG_INFO("successful load of HepMC info");
142 for (const HepMC::GenEvent* itr : *mcColl){
143 HepMC::GenEvent evt = (*itr);
144 // convert unit MeV to GeV for energy and momenta
145 MeVToGeV(evt);
146
147 HepMC::Print::line(std::cout, evt);
148
149 // Select final state particle from event generator
150 // set event status !=1 (final state)
151 // fill member variables with particle data
152 // ALFA_BeamTransport::SelectParticles(evt);
153
154 // There should be a check if the first particle is really the
155 // particle for beam 1!!!!
156
157 // run Funktion which does the beamtracking
158 // ALFA_BeamTransport::DoBeamTracking(evt_number);
159
160
161 TransportSelectedParticle(evt, evt_number);
162
163 // Print new data collection on screen
164 HepMC::Print::line(std::cout, evt);
165 }
166
167 ATH_MSG_INFO("after running the process function");
168
169 //-----------------------------------------------------------------------------------------
170
171 return StatusCode::SUCCESS;
172}
173
174
175//convert unit MeV to GeV for energy and momenta
177void ALFA_BeamTransport::MeVToGeV (HepMC::GenEvent& evt)
178{
179 for (const HepMC::GenParticlePtr& p: evt) {
180 const HepMC::FourVector fv(p->momentum().px() / 1000.,
181 p->momentum().py() / 1000.,
182 p->momentum().pz() / 1000.,
183 p->momentum().e() / 1000.);
184
185 p->set_momentum(fv);
186 }
187}
188
189//convert unit MeV to GeV for energy and momenta
191void ALFA_BeamTransport::GeVToMeV (HepMC::GenEvent& evt)
192{
193 for (const HepMC::GenParticlePtr& p : evt) {
194 const HepMC::FourVector fv(p->momentum().px() * 1000.,
195 p->momentum().py() * 1000.,
196 p->momentum().pz() * 1000.,
197 p->momentum().e() * 1000.);
198
199 p->set_momentum(fv);
200 }
201}
202
203
204
206{
207 //do particle tracking for beam 1
208
209 //tracking funktion
210 m_BeamTracker.ALFA_BeamTrack::CalculatePosRP(m_Particle1);//calculates position and momentum at RP1
211 //Position at RP
212 m_PosRP1=m_BeamTracker.ALFA_BeamTrack::PosRP();
213 //Momentum at RP
214 m_MomRP1=m_BeamTracker.ALFA_BeamTrack::MomRP();
215
216 //do particle tracking for beam 2
217
218 //tracking funktion
219 m_BeamTracker.ALFA_BeamTrack::CalculatePosRP(m_Particle2);//gives position and momentum at RP3
220 //Position at RP
221 m_PosRP3=m_BeamTracker.ALFA_BeamTrack::PosRP();
222 //Momentum at RP
223 m_MomRP3=m_BeamTracker.ALFA_BeamTrack::MomRP();
224
225 //Write Output
227 {
228 m_FileBeam1 << evt_number << "\t" << std::setprecision(17)
229 << m_PosRP1.x() << std::setprecision(17) << "\t"
230 << m_PosRP1.y() << "\t" << std::setprecision(17)
231 << m_PosRP1.z() << "\t" << std::setprecision(17)
232 << m_MomRP1.x() << std::setprecision(17) << "\t"
233 << m_MomRP1.y() << "\t" << std::setprecision(17)
234 << m_MomRP1.z() << "\t" << std::setprecision(17)
235 << m_EnergyRP1 << std::endl;
236 m_FileBeam2 << evt_number << "\t" << std::setprecision(17)
237 << m_PosRP3.x() << std::setprecision(17) << "\t"
238 << m_PosRP3.y() << "\t" << std::setprecision(17)
239 << m_PosRP3.z() << "\t" << std::setprecision(17)
240 << m_MomRP3.x() << std::setprecision(17) << "\t"
241 << m_MomRP3.y() << "\t" << std::setprecision(17)
242 << m_MomRP3.z() << "\t" << std::setprecision(17)
243 << m_EnergyRP3 << std::endl;
244 }
245
246 return true;
247}
248
249int ALFA_BeamTransport::TransportSelectedParticle(HepMC::GenEvent& evt, int evt_number){
250 HepMC::GenParticlePtr p1{nullptr};
251 HepMC::GenParticlePtr p2{nullptr};
252
253 std::vector<FPTracker::Point> PosAtRP1;
254 std::vector<FPTracker::Point> PosAtRP3;
255 std::vector<FPTracker::Point> MomAtPR1;
256 std::vector<FPTracker::Point> MomAtPR3;
257 std::vector<double> EnergyRP1;
258 std::vector<double> EnergyRP3;
259
260
261 double mom=0.;
262 double eta=0.;
263 double theta=0.;
264
265 // First we have to select the final state particles from the MC
266 for (const HepMC::GenParticlePtr& p : evt) {
267
268 // Simple Eta Pt cut to remove particles from BeamTransportation which
269 // have no chance to reach RP plane
270 mom = std::sqrt(std::pow(p->momentum().px(), 2) +
271 std::pow(p->momentum().py(), 2) +
272 std::pow(p->momentum().pz(), 2));
273 theta = std::acos(std::abs(p->momentum().pz()) / mom);
274 eta = -std::log(std::tan(theta / 2));
275
276 if (MC::isStable(p) && (!p->end_vertex())) {
277
278 int pid = p->pdg_id();
279 if (eta > m_EtaCut && 1 - std::abs(mom / m_FPConfig.pbeam0) < m_XiCut) {
280
281 // save a copy of the particles which passed the cut
282 HepMC::FourVector Position = p->production_vertex()->position();
283 HepMC::FourVector Momentum = p->momentum();
284 HepMC::GenVertexPtr Vertex = HepMC::newGenVertexPtr(Position); // copy of the vertex
285 HepMC::GenParticlePtr Particle = HepMC::newGenParticlePtr(Momentum, pid, 1);
286
287 Vertex->add_particle_out(std::move(Particle));
288 evt.add_vertex(std::move(Vertex));
289
290 // select direction of particle
291 if (p->momentum().pz() > 0. && pid == 2212) { // Beam1 TODO Tracking only works for protons!!!!
292 p1 = p;
293 // now we want to track the final particle if it's a protons
294 // Positions are given in mm FPTracker needs them in meter
296 p1->production_vertex()->position().x() / 1000.,
297 p1->production_vertex()->position().y() / 1000.,
298 p1->production_vertex()->position().z() / 1000.,
299 p1->momentum().px(),
300 p1->momentum().py(),
301 p1->momentum().pz());
302
303 // do particle tracking for beam 1
304
305 // tracking funktion
306 m_BeamTracker.ALFA_BeamTrack::CalculatePosRP(m_Particle1); // calculates position and momentum at RP1
307 // Position at RP
308 m_PosRP1 = m_BeamTracker.ALFA_BeamTrack::PosRP();
309 PosAtRP1.push_back(m_PosRP1);
310 // Momentum at RP
311 m_MomRP1 = m_BeamTracker.ALFA_BeamTrack::MomRP();
312 MomAtPR1.push_back(m_MomRP1);
313 // no Energy change between IP and RP
314 m_EnergyRP1 = p1->momentum().e();
315 EnergyRP1.push_back(m_EnergyRP1);
316 if (m_WriteDebugOutput) {
317 m_FileBeam1 << evt_number << "\t" << std::setprecision(17)
318 << m_PosRP1.x() << std::setprecision(17) << "\t"
319 << m_PosRP1.y() << "\t" << std::setprecision(17)
320 << m_PosRP1.z() << "\t" << std::setprecision(17)
321 << m_MomRP1.x() << std::setprecision(17) << "\t"
322 << m_MomRP1.y() << "\t" << std::setprecision(17)
323 << m_MomRP1.z() << "\t" << std::setprecision(17)
324 << m_EnergyRP1 << std::endl;
325 }
326
327 } else if (p->momentum().pz() < 0. && pid == 2212) { // beam 2
328 p2 = p;
329
331 p2->production_vertex()->position().x() / 1000.,
332 p2->production_vertex()->position().y() / 1000.,
333 p2->production_vertex()->position().z() / 1000.,
334 p2->momentum().px(),
335 p2->momentum().py(),
336 p2->momentum().pz());
337 // tracking funktion
338 m_BeamTracker.ALFA_BeamTrack::CalculatePosRP(m_Particle2); // gives position and momentum at RP3
339 // Position at RP
340 m_PosRP3 = m_BeamTracker.ALFA_BeamTrack::PosRP();
341 PosAtRP3.push_back(m_PosRP3);
342 // Momentum at RP
343 m_MomRP3 = m_BeamTracker.ALFA_BeamTrack::MomRP();
344 MomAtPR3.push_back(m_MomRP3);
345
346 m_EnergyRP3 = p2->momentum().e();
347 EnergyRP3.push_back(m_EnergyRP3);
348 // Write Output
349 if (m_WriteDebugOutput) {
350 m_FileBeam2 << evt_number << "\t" << std::setprecision(17)
351 << m_PosRP3.x() << std::setprecision(17) << "\t"
352 << m_PosRP3.y() << "\t" << std::setprecision(17)
353 << m_PosRP3.z() << "\t" << std::setprecision(17)
354 << m_MomRP3.x() << std::setprecision(17) << "\t"
355 << m_MomRP3.y() << "\t" << std::setprecision(17)
356 << m_MomRP3.z() << "\t" << std::setprecision(17)
357 << m_EnergyRP3 << std::endl;
358 }
359
360 } else {
361 ATH_MSG_ERROR("Strange: Particle rests at IP");
362 }
363
364 if (pid == 2212) { // Find the protons
365 m_pcount++;
366 if (m_pcount > 2) {
367 ATH_MSG_ERROR("Strange: More than two protons in this event!");
368 }
369 }
370 }
371 }
372 }
373
374 //from here the transported particles are added to HepMC
375
376 ATH_MSG_INFO("Add transproted particle into HepMC event record Beam 1");
377 //Add Data for HepMC Collection
378
379 for(int i=0;i<(int)PosAtRP1.size();i++){//Beam1
380 //The factor 1000 comes from the fact that HepMC saves length in mm
381 HepMC::FourVector PositionVectorRP1 = HepMC::FourVector(PosAtRP1.at(i).x()*1000.,PosAtRP1.at(i).y()*1000.,PosAtRP1.at(i).z()*1000.,0.*1000.);
382 HepMC::FourVector MomentumVectorRP1 = HepMC::FourVector(MomAtPR1.at(i).x(),MomAtPR1.at(i).y(),MomAtPR1.at(i).z(),EnergyRP1.at(i));
383
384 HepMC::GenVertexPtr VertexRP1 = HepMC::newGenVertexPtr(PositionVectorRP1);
385 HepMC::GenParticlePtr ParticleRP1 = HepMC::newGenParticlePtr(MomentumVectorRP1,2212,1); //save the transported particle with status code 1 (added 120124) preview was 201
386 //Add particle to vertex
387 VertexRP1->add_particle_out(std::move(ParticleRP1));
388 //add new vertex to HepMC event record
389 if(m_PosRP1.x()!=-99){ // add vertex to event record if the particle in the first beam was not lost
390 evt.add_vertex(std::move(VertexRP1));
391 }
392 }
393 ATH_MSG_INFO ("Add transproted particle into HepMC event record Beam 2" );
394 for(int i=0;i<(int)PosAtRP3.size();i++){
395 HepMC::FourVector PositionVectorRP3 = HepMC::FourVector(PosAtRP3.at(i).x()*1000.,PosAtRP3.at(i).y()*1000.,PosAtRP3.at(i).z()*1000.,0.*1000.);
396 HepMC::FourVector MomentumVectorRP3 = HepMC::FourVector(MomAtPR3.at(i).x(),MomAtPR3.at(i).y(),MomAtPR3.at(i).z(),EnergyRP3.at(i));
397 HepMC::GenVertexPtr VertexRP3 = HepMC::newGenVertexPtr(PositionVectorRP3);
398 HepMC::GenParticlePtr ParticleRP3 = HepMC::newGenParticlePtr(MomentumVectorRP3,2212,1);//save the transported particle with status code 1 (added 120124) preview was 201
399 VertexRP3->add_particle_out(std::move(ParticleRP3));
400 if (m_PosRP3.x() != -99) { // add vertex to event record if the // particle in the second beam was not lost
401 evt.add_vertex(std::move(VertexRP3));
402 }
403 }
404
405 //convert HepMC data back to HepMC standart ( momentum and energy in MeV)
407 return true;
408}
Scalar eta() const
pseudorapidity method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
boost::graph_traits< boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS > >::vertex_descriptor Vertex
ATLAS-specific HepMC functions.
int TransportSelectedParticle(HepMC::GenEvent &evt, int evt_number)
This function is event selection, tracking and HepMC save ine one function.
FPTracker::Point m_PosRP3
ALFA_BeamTrack m_BeamTracker
FPTracker::Particle m_Particle1
StatusCode finalize()
standard Athena-Algorithm method
StatusCode initialize()
standard Athena-Algorithm method
StatusCode execute()
standard Athena-Algorithm method
FPTracker::Point m_PosRP1
ALFA_BeamTransport(const std::string &name, ISvcLocator *pSvcLocator)
Standard Athena-Algorithm Constructor.
SG::ReadHandleKey< McEventCollection > m_MCKey
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
void MeVToGeV(HepMC::GenEvent &evt)
convert unit MeV to GeV for energy and momenta
int DoBeamTracking(int evt_number)
Function which calls BeamTrack class to calcualte Position at RPs.
FPTracker::Particle m_Particle2
void GeVToMeV(HepMC::GenEvent &evt)
convert GeV to MeV for HepMC event record
FPTracker::Point m_MomRP3
~ALFA_BeamTransport()
Default Destructor.
FPTracker::Point m_MomRP1
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
virtual bool isValid() override final
Can the handle be successfully dereferenced?
void line(std::ostream &os, const GenEvent &e)
Definition GenEvent.h:678
HepMC::GenVertex * GenVertexPtr
Definition GenVertex.h:59
GenVertexPtr newGenVertexPtr(const HepMC::FourVector &pos=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), const int i=0)
Definition GenVertex.h:64
GenParticlePtr newGenParticlePtr(const HepMC::FourVector &mom=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), int pid=0, int status=0)
Definition GenParticle.h:39
GenParticle * GenParticlePtr
Definition GenParticle.h:37
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.