ATLAS Offline Software
HepMcFloatWriterTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // HepMcFloatWriterTool.cxx
7 // Implementation file for class HepMcFloatWriterTool
8 // Author: S.Binet<binet@cern.ch>
10 
11 
12 // STL includes
13 #include <algorithm>
14 #include <cctype>
15 #include <fstream>
16 #include <sstream>
17 #include <limits>
18 
19 // FrameWork includes
20 
22 #include "HepPDT/ParticleDataTable.hh"
23 
24 // McParticleTools includes
25 #include "HepMcFloatWriterTool.h"
26 #include "AtlasHepMC/Flow.h"
28 static const char * const s_protocolSep = ":";
29 
34  const std::string& name,
35  const IInterface* parent ) :
37  m_ioBackend( nullptr )
38 {
39  //
40  // Property declaration
41  //
42 
43  declareProperty( "Output",
44  m_ioBackendURL = "ascii:hepmc.genevent.txt",
45  "Name of the back-end we'll use to write out the HepMC::GenEvent."
46  "\nEx: ascii:hepmc.genevent.txt" );
47  m_ioBackendURL.declareUpdateHandler( &HepMcFloatWriterTool::setupBackend,this );
48 
49  declareProperty( "McEvents",
50  m_mcEventsName = "GEN_EVENT",
51  "Input location of the McEventCollection to write out" );
52 
53  declareInterface<IIOHepMcTool>(this);
54 }
55 
59 {
60  ATH_MSG_DEBUG("Calling destructor");
61 
62  if ( m_ioBackend ) {
63  delete m_ioBackend;
64  m_ioBackend = nullptr;
65  }
66 }
67 
71 {
72  ATH_MSG_INFO("Initializing " << name() << "...");
73 
74  // setup backend
75  if ( nullptr == m_ioBackend ) {
77  }
78 
79  (*m_ioBackend) << "# epsilon<float> = "
80  << std::numeric_limits<float>::epsilon()
81  << "\n"
82  << "# dbl precision = "
83  << std::numeric_limits<double>::digits10 + 1
84  << "\n"
85  << "# flt precision = "
86  << std::numeric_limits<float>::digits10 + 1
87  << "\n";
88 
89  return StatusCode::SUCCESS;
90 }
91 
93 {
94  ATH_MSG_INFO("Finalizing " << name() << "...");
95  return StatusCode::SUCCESS;
96 }
97 
99 {
100  // retrieve the McEventCollection
101  const McEventCollection * mcEvts = nullptr;
102  if ( evtStore()->retrieve( mcEvts, m_mcEventsName ).isFailure() || nullptr == mcEvts ) {
103  ATH_MSG_ERROR("Could not retrieve a McEventCollection at [" << m_mcEventsName << "] !!");
104  return StatusCode::FAILURE;
105  }
106 
107  if ( mcEvts->empty() ) {
108  ATH_MSG_WARNING("McEventCollection at [" << m_mcEventsName << "] is EMPTY !!");
109  return StatusCode::FAILURE;
110  }
111 
112  const HepMC::GenEvent * evt = mcEvts->front();
113  if ( !evt ) {
114  ATH_MSG_ERROR("Retrieved NULL pointer to HepMC::GenEvent !!");
115  return StatusCode::FAILURE;
116  }
117 
118  return write(evt);
119 }
120 
124 
125 StatusCode HepMcFloatWriterTool::write( const HepMC::GenEvent* evt )
126 {
127  std::ostringstream out;
128 
129  // precision 8 (# digits following decimal point) is the minimum that
130  // will capture the full information stored in a float
131  out.precision( std::numeric_limits<double>::digits10 + 1 );
132  // we use decimal to store integers, because it is smaller than hex!
133  out.setf(std::ios::dec,std::ios::basefield);
134  out.setf(std::ios::scientific,std::ios::floatfield);
135 
136 
137 #ifdef HEPMC3
138  long evt_vertices_size=evt->vertices().size();
139  std::shared_ptr<HepMC3::DoubleAttribute> A_alphaQCD=evt->attribute<HepMC3::DoubleAttribute>("alphaQCD");
140  double evt_alphaQCD=(A_alphaQCD?(A_alphaQCD->value()):0.0);
141  std::shared_ptr<HepMC3::DoubleAttribute> A_alphaQED=evt->attribute<HepMC3::DoubleAttribute>("alphaQED");
142  double evt_alphaQED=(A_alphaQED?(A_alphaQED->value()):0.0);
143  std::shared_ptr<HepMC3::DoubleAttribute> A_event_scale=evt->attribute<HepMC3::DoubleAttribute>("event_scale");
144  double evt_event_scale=(A_event_scale?(A_event_scale->value()):0.0);
145  std::shared_ptr<HepMC3::VectorLongIntAttribute> A_random_states=evt->attribute<HepMC3::VectorLongIntAttribute>("random_states");
146  std::vector<long int> random_states=(A_random_states?(A_random_states->value()):std::vector<long int>());
147  long random_states_size=random_states.size();
148 #else
149  long evt_vertices_size=evt->vertices_size();
150  double evt_alphaQCD=evt->alphaQCD();
151  double evt_alphaQED=evt->alphaQED();
152  double evt_event_scale=evt->event_scale();
153  std::vector<long int> random_states=evt->random_states();
154  long random_states_size=random_states.size();
155 #endif
156  out << "# -- GenEvent -->\n";
157  out << "#" << evt->event_number()
158  << " " << evt_event_scale
159  << " " << evt_alphaQCD
160  << " " << evt_alphaQED
161  << " " << HepMC::signal_process_id(evt)
163  << " " << evt_vertices_size
164  << " " << random_states_size
165  << "\n";
166  out << "#";
167  std::copy( random_states.begin(), random_states.end(), std::ostream_iterator<long int>(out, " ") );
168  out << evt->weights().size() << "\n";
169 
170  out << "#";
171  std::copy( evt->weights().begin(), evt->weights().end(), std::ostream_iterator<double>(out, " ") );
172  out << '\n';
173 
174  out << "#-- particles --\n";
175  for (const auto& p: *evt) {
176  if ( p ) {
177  out << "# " << HepMC::barcode(p) << " " << p->pdg_id() << "\n";
178 
179  const HepMC::FourVector mom = p->momentum();
180  std::ostringstream buf;
181  buf.precision( std::numeric_limits<float>::digits10 + 1 );
182  buf.setf(std::ios::dec,std::ios::basefield);
183  buf.setf(std::ios::scientific,std::ios::floatfield);
184 
185  const float px = static_cast<float>(mom.px());
186  const float py = static_cast<float>(mom.py());
187  const float pz = static_cast<float>(mom.pz());
188  const float m = static_cast<float>(mom.m());
189  const float e = static_cast<float>(std::sqrt( std::pow( px, 2 ) + std::pow( py, 2 ) + std::pow( pz, 2 ) + std::pow( m, 2 ) ) );
190  buf << px << " " << py << " " << pz << " " << e << " " << m << "\n";
191 
192  out << buf.str();
193  auto pol=HepMC::polarization(p);
194  out << "# "<< p->status()
195  << " " << pol.theta()
196  << " " << pol.phi()
197  << " " << ( p->end_vertex() ? HepMC::barcode(p->end_vertex()) : 0 )
198  << " " << HepMC::flow(p)
199  << "\n";
200  }
201  }
202 
203  out << "#-- vertices -- \n";
204 #ifdef HEPMC3
205  for (const auto& v: evt->vertices()) {
206  if ( v ) {
207  out << "# " << HepMC::barcode(v) << " " << v->status() << "\n";
208  const HepMC::FourVector pos = v->position();
209  std::ostringstream buf;
210  buf.precision( std::numeric_limits<float>::digits10 + 1 );
211  buf.setf(std::ios::dec,std::ios::basefield);
212  buf.setf(std::ios::scientific,std::ios::floatfield);
213 
214  buf << pos.x() << " " << pos.y() << " " << pos.z() << " " << pos.t() << "\n";
215 
216  out << buf.str();
217  out << "#";
218  std::string svertexeights("1.0");
219  auto vertexeights=v->attribute<HepMC3::VectorDoubleAttribute>("weights");
220  if (vertexeights) vertexeights->to_string(svertexeights);
221  out << svertexeights;
222  out << '\n';
223  }
224 #else
225  for ( HepMC::GenEvent::vertex_const_iterator
226  i = evt->vertices_begin(),
227  iEnd = evt->vertices_end();
228  i != iEnd;
229  ++i ) {
230  const HepMC::GenVertex * v = *i;
231  if ( v ) {
232  out << "# " << v->barcode() << " " << v->id() << "\n";
233 
234  const HepMC::FourVector pos = v->position();
235  std::ostringstream buf;
236  buf.precision( std::numeric_limits<float>::digits10 + 1 );
237  buf.setf(std::ios::dec,std::ios::basefield);
238  buf.setf(std::ios::scientific,std::ios::floatfield);
239 
240  buf << pos.x() << " " << pos.y() << " " << pos.z() << " " << pos.t() << "\n";
241 
242  out << buf.str();
243  out << "#";
244  std::copy( v->weights().begin(), v->weights().end(), std::ostream_iterator<double>(out, " ") );
245  out << '\n';
246  }
247 #endif
248  }
249  out << "#<-- GenEvent --\n";
250 
251  (*m_ioBackend) << out.str() << std::flush;
252  return StatusCode::SUCCESS;
253 }
254 
258 
259 void HepMcFloatWriterTool::setupBackend( Gaudi::Details::PropertyBase& /*prop*/ )
260 {
261  // defaults
262  std::string protocol = "ascii";
263  std::string fileName = "hepmc.genevent.txt";
264 
265  // reset internal state
266  if ( m_ioBackend ) {
267  delete m_ioBackend;
268  m_ioBackend = nullptr;
269  }
270 
271  // caching URL
272  const std::string& url = m_ioBackendURL.value();
273 
274  std::string::size_type protocolPos = url.find(s_protocolSep);
275 
276  if ( std::string::npos != protocolPos ) {
277  protocol = url.substr( 0, protocolPos );
278  fileName = url.substr( protocolPos+1, std::string::npos );
279  } else {
280  //protocol = "ascii";
281  fileName = url;
282  }
283 
284  // get the protocol name in lower cases
285  std::transform( protocol.begin(), protocol.end(), protocol.begin(), [](unsigned char c){ return std::tolower(c); } );
286  if ( "ascii" == protocol ) {
287  m_ioBackend = new std::ofstream( fileName.c_str(), std::ios::out | std::ios::trunc );
288 
289  } else {
290  ATH_MSG_WARNING("UNKNOWN protocol [" << protocol << "] !!" << endmsg << "Will use [ascii] instead...");
291  protocol = "ascii";
292  m_ioBackend = new std::ofstream( fileName.c_str(), std::ios::out | std::ios::trunc );
293  }
294  ATH_MSG_DEBUG("Using protocol [" << protocol << "] and write to ["<< fileName << "]");
295 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
Flow.h
HepMcFloatWriterTool::initialize
StatusCode initialize()
Athena Algorithm's Hooks.
Definition: HepMcFloatWriterTool.cxx:70
test_pyathena.px
px
Definition: test_pyathena.py:18
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
HepMcFloatWriterTool::HepMcFloatWriterTool
HepMcFloatWriterTool()
Default constructor:
HepMC::polarization
Polarization polarization(const T &a)
Definition: Polarization.h:47
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
FullCPAlgorithmsTest_eljob.flush
flush
Definition: FullCPAlgorithmsTest_eljob.py:168
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
HepMC::signal_process_id
int signal_process_id(const GenEvent &e)
Definition: GenEvent.h:513
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
physics_parameters.url
string url
Definition: physics_parameters.py:27
HepMcFloatWriterTool::m_mcEventsName
StringProperty m_mcEventsName
Location of the McEventCollection to be written out If there is more than 1 HepMC::GenEvent in the Mc...
Definition: HepMcFloatWriterTool.h:85
AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
FortranAlgorithmOptions.fileName
fileName
Definition: FortranAlgorithmOptions.py:13
HepMcFloatWriterTool::m_ioBackend
std::ostream * m_ioBackend
Abstract base class for the back-end.
Definition: HepMcFloatWriterTool.h:89
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
McEventCollection.h
HepMC::flow
int flow(const T &a, int i)
Definition: Flow.h:51
lumiFormat.i
int i
Definition: lumiFormat.py:92
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
HepMC::barcode
int barcode(const T *p)
Definition: Barcode.h:16
HepMcFloatWriterTool::finalize
StatusCode finalize()
Definition: HepMcFloatWriterTool.cxx:92
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
DataVector::front
const T * front() const
Access the first element in the collection as an rvalue.
Amg::pz
@ pz
Definition: GeoPrimitives.h:40
test_pyathena.parent
parent
Definition: test_pyathena.py:15
McEventCollection
This defines the McEventCollection, which is really just an ObjectVector of McEvent objects.
Definition: McEventCollection.h:33
HepMcFloatWriterTool::setupBackend
void setupBackend(Gaudi::Details::PropertyBase &ioBackendURL)
Method to configure the back-end to write out the HepMC::GenEvent.
Definition: HepMcFloatWriterTool.cxx:259
Amg::py
@ py
Definition: GeoPrimitives.h:39
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
HepMcFloatWriterTool::~HepMcFloatWriterTool
virtual ~HepMcFloatWriterTool()
Destructor:
Definition: HepMcFloatWriterTool.cxx:58
HepMcFloatWriterTool::write
StatusCode write(const HepMC::GenEvent *evt)
Process the HepMC::GenEvent through the I/O backend.
Definition: HepMcFloatWriterTool.cxx:125
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
python.PyAthena.v
v
Definition: PyAthena.py:157
HepMcFloatWriterTool::m_ioBackendURL
StringProperty m_ioBackendURL
URL of the I/O back-end (only "ASCII" for now...) glued with the name of the output file name.
Definition: HepMcFloatWriterTool.h:79
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
HepMcFloatWriterTool.h
calibdata.copy
bool copy
Definition: calibdata.py:27
AthAlgTool
Definition: AthAlgTool.h:26
Polarization.h
python.compressB64.c
def c
Definition: compressB64.py:93
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
HepMcFloatWriterTool::execute
StatusCode execute()
Definition: HepMcFloatWriterTool.cxx:98
HepMC::signal_process_vertex
GenVertex * signal_process_vertex(const GenEvent *e)
Definition: GenEvent.h:503