HepMC3 event record library
WriterDOT.cc
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
5//
6#include "WriterDOT.h"
7namespace HepMC3
8{
9WriterDOT::WriterDOT(const std::string &filename,std::shared_ptr<GenRunInfo> /*run*/): m_file(filename),
10 m_stream(&m_file),
11 m_style(0),
12 m_buffer(nullptr),
13 m_cursor(nullptr),
14 m_buffer_size( 256*1024 )
15{
16 if ( !m_file.is_open() ) {
17 HEPMC3_ERROR( "WriterDOT: could not open output file: "<<filename )
18 }
19}
20
21WriterDOT::WriterDOT(std::ostream &stream, std::shared_ptr<GenRunInfo> /*run*/)
22 : m_stream(&stream),
23 m_style(0),
24 m_buffer(nullptr),
25 m_cursor(nullptr),
26 m_buffer_size( 256*1024 )
27{}
28
29
31 auto* ofs = dynamic_cast<std::ofstream*>(m_stream);
32 if (ofs && !ofs->is_open()) return;
34 if (ofs) ofs->close();
35}
36/// @brief Detects if particle is parton. Might be used to draw partons different from hadrons
37bool is_parton(const int& pd )
38{
39 bool parton=false;
40
41 if (pd==81||pd==82||pd<25) parton=true;
42 if (
43 (pd/1000==1||pd/1000==2||pd/1000==3||pd/1000==4||pd/1000==5)
44 &&(pd%1000/100==1||pd%1000/100==2||pd%1000/100==3||pd%1000/100==4)
45 &&(pd%100==1||pd%100==3)
46 )
47 { parton = true;}
48 return parton;
49}
51{
53 if ( !m_buffer ) return;
54 flush();
55 m_cursor += sprintf(m_cursor, "digraph graphname%d {\n",evt.event_number());
56 m_cursor += sprintf(m_cursor, "v0[label=\"Machine\"];\n");
57 for(auto v: evt.vertices() ) {
58 if (m_style != 0)
59 {
60 if (m_style == 1) //paint decay and fragmentation vertices in green
61 {
62 if (v->status() == 2) {m_cursor += sprintf(m_cursor, "node [color=\"green\"];\n");}
63 else {m_cursor += sprintf(m_cursor, "node [color=\"black\"];\n");}
64 }
65 }
66 m_cursor += sprintf(m_cursor, "node [shape=ellipse];\n");
67 m_cursor += sprintf(m_cursor, "v%d[label=\"%d\"];\n", -v->id(),v->id());
68 flush();
69 }
70 for(auto p: evt.beams() ) {
71 if (!p->end_vertex()) continue;
72 m_cursor += sprintf(m_cursor, "node [shape=point];\n");
73 m_cursor += sprintf(m_cursor, "v0 -> v%d [label=\"%d(%d)\"];\n", -p->end_vertex()->id(),p->id(),p->pid());
74 }
75
76 for(auto v: evt.vertices() ) {
77 for(auto p: v->particles_out() ) {
78 {
79 if (m_style != 0)
80 {
81 if (m_style == 1) //paint suspected partons and 81/82 in red
82 {
83 if (is_parton(std::abs(p->pid()))&&p->status()!=1) {m_cursor += sprintf(m_cursor, "edge [color=\"red\"];\n");}
84 else { m_cursor +=sprintf(m_cursor, "edge [color=\"black\"];\n");}
85 }
86 }
87 if (!p->end_vertex())
88 {
89 m_cursor += sprintf(m_cursor, "node [shape=point];\n");
90 m_cursor += sprintf(m_cursor, "v%d -> o%d [label=\"%d(%d)\"];\n", -v->id(), p->id(), p->id(), p->pid());
91 flush();
92 continue;
93 }
94 m_cursor += sprintf(m_cursor, "node [shape=ellipse];\n");
95 m_cursor += sprintf(m_cursor, "v%d -> v%d [label=\"%d(%d)\"];\n", -v->id(), -p->end_vertex()->id(), p->id(), p->pid());
96 flush();
97 }
98 }
99 }
100 m_cursor += sprintf(m_cursor, "labelloc=\"t\";\nlabel=\"Event %d; Vertices %lu; Particles %lu;\";\n", evt.event_number(), evt.vertices().size(), evt.particles().size());
101 m_cursor += sprintf(m_cursor,"}\n\n");
102 forced_flush();
103}
105 if ( m_buffer ) return;
106 while( m_buffer == nullptr && m_buffer_size >= 256 ) {
107 try {
108 m_buffer = new char[ m_buffer_size ]();
109 } catch (const std::bad_alloc& e) {
110 delete[] m_buffer;
111 m_buffer_size /= 2;
112 HEPMC3_WARNING( "WriterDOT::allocate_buffer: buffer size too large. Dividing by 2. New size: " << m_buffer_size << e.what())
113 }
114 }
115
116 if ( !m_buffer ) {
117 HEPMC3_ERROR( "WriterDOT::allocate_buffer: could not allocate buffer!" )
118 return;
119 }
121}
122inline void WriterDOT::flush() {
123 // The maximum size of single add to the buffer (other than by
124 // using WriterDOT::write) is 32 bytes. This is a safe value as
125 // we will not allow precision larger than 24 anyway
126 if ( m_buffer + m_buffer_size < m_cursor + 256 ) {
127 m_stream->write( m_buffer, m_cursor - m_buffer );
129 }
130}
132 m_stream->write( m_buffer, m_cursor - m_buffer );
134}
135
136} // namespace HepMC3
#define HEPMC3_WARNING(MESSAGE)
Macro for printing HEPMC3_HEPMC3_WARNING messages.
Definition: Errors.h:27
#define HEPMC3_ERROR(MESSAGE)
Macro for printing error messages.
Definition: Errors.h:24
Definition of class WriterDOT.
Stores event-related information.
Definition: GenEvent.h:41
int event_number() const
Get event number.
Definition: GenEvent.h:148
std::vector< ConstGenParticlePtr > beams() const
Vector of beam particles.
Definition: GenEvent.cc:423
const std::vector< ConstGenVertexPtr > & vertices() const
Get list of vertices (const)
Definition: GenEvent.cc:43
const std::vector< ConstGenParticlePtr > & particles() const
Get list of particles (const)
Definition: GenEvent.cc:39
void allocate_buffer()
allocates buffer for output
Definition: WriterDOT.cc:104
char * m_cursor
Cursor inside stream buffer.
Definition: WriterDOT.h:57
char * m_buffer
Stream buffer.
Definition: WriterDOT.h:56
void close() override
Close file stream.
Definition: WriterDOT.cc:30
std::ofstream m_file
Output file.
Definition: WriterDOT.h:53
unsigned long m_buffer_size
Buffer size.
Definition: WriterDOT.h:58
void write_event(const GenEvent &evt) override
Write event to file.
Definition: WriterDOT.cc:50
void flush()
flushes output buffer
Definition: WriterDOT.cc:122
void forced_flush()
flushes output buffer
Definition: WriterDOT.cc:131
std::ostream * m_stream
Output stream.
Definition: WriterDOT.h:54
int m_style
style of dot file
Definition: WriterDOT.h:55
WriterDOT(const std::string &filename, std::shared_ptr< GenRunInfo > run=std::shared_ptr< GenRunInfo >())
Constructor.
Definition: WriterDOT.cc:9
HepMC3 main namespace.
bool is_parton(const int &pd)
Detects if particle is parton. Might be used to draw partons different from hadrons.
Definition: WriterDOT.cc:37