Index: /trunk/Utilities/HepMC/interface/CommonIO.h
===================================================================
--- /trunk/Utilities/HepMC/interface/CommonIO.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/CommonIO.h	(revision 349)
@@ -0,0 +1,147 @@
+#ifndef HEPMC_COMMON_IO_H
+#define HEPMC_COMMON_IO_H
+// ----------------------------------------------------------------------
+//
+// CommonIO.h
+// Author:  Lynn Garren
+//
+//  Allowed keys used at the beginning and end of HepMC data dumps
+//
+// ----------------------------------------------------------------------
+
+#include <fstream>
+#include <string>
+
+#include "GenEvent.h"
+#include "TempParticleMap.h"
+#include "ParticleDataTable.h"
+
+namespace HepMC {
+
+/// The known_io enum is used to track which type of input is being read
+enum known_io { gen=1, ascii, extascii, ascii_pdt, extascii_pdt };
+
+class CommonIO {
+
+public:
+
+  CommonIO();
+  ~CommonIO() {;}
+
+  // input keys - IO_GenEvent is strongly recommended
+  std::string IO_GenEvent_Key()          const { return m_io_genevent_start; }
+  std::string IO_GenEvent_End()          const { return m_io_genevent_end; }
+  // IO_Ascii is deprecated, but we want to be able to read these files
+  std::string IO_Ascii_Key()             const { return m_io_ascii_start; }
+  std::string IO_Ascii_End()             const { return m_io_ascii_end; }
+  // IO_ExtendedAscii has been removed, but we want to be able to read these files
+  std::string IO_ExtendedAscii_Key()     const { return m_io_extendedascii_start; }
+  std::string IO_ExtendedAscii_End()     const { return m_io_extendedascii_end; }
+  /// get IO type
+  int io_type() const { return m_io_type; }
+
+  // write keys
+  void write_IO_GenEvent_Key( std::ostream& );
+  void write_IO_GenEvent_End( std::ostream& );
+  // write keys for deprecated IO methods
+  void write_IO_Ascii_Key( std::ostream& );
+  void write_IO_Ascii_End( std::ostream& );
+  // write keys for deprecated particle data IO methods
+  void write_IO_Ascii_PDT_Key( std::ostream& );
+  void write_IO_Ascii_PDT_End( std::ostream& );
+
+  // methods to read input
+
+  /// look for line type (key)
+  int find_file_type( std::istream& );
+
+  /// look for line type (key)
+  int find_end_key( std::istream& );
+
+  bool read_io_ascii( std::istream* is, GenEvent* evt );
+
+  bool read_io_extendedascii( std::istream* is, GenEvent* evt );
+
+  bool read_io_genevent( std::istream* is, GenEvent* evt );
+
+  bool read_units( std::istream* is, GenEvent* evt );
+
+  /// needed when reading a file without units if those units are 
+  /// different than the declared default units 
+  /// (e.g., the default units are MeV, but the file was written with GeV)
+  /// This method is not necessary if the units are written in the file
+  void use_input_units( Units::MomentumUnit, Units::LengthUnit );
+
+  /// ParticleDataTable is deprecated.
+  /// We include this method for reading old files which may have ParticleData information.
+  bool read_io_particle_data_table( std::istream*, ParticleDataTable* );
+ 
+protected:
+  // methods used by the read_io* methods
+  HeavyIon*    read_heavy_ion( std::istream* );
+  PdfInfo*     read_pdf_info( std::istream* );
+  GenParticle* read_particle( std::istream*, TempParticleMap&  );
+  GenVertex*   read_vertex( std::istream*, TempParticleMap&  );
+  /// ParticleDataTable is deprecated.
+  /// We include this method for reading old files which may have ParticleData information.
+  ParticleData* read_particle_data( std::istream*, ParticleDataTable* );
+
+private:
+  std::string m_io_genevent_start;
+  std::string m_io_ascii_start;
+  std::string m_io_extendedascii_start;
+  std::string m_io_genevent_end;
+  std::string m_io_ascii_end;
+  std::string m_io_extendedascii_end;
+  // particle data method keys
+  std::string m_io_ascii_pdt_start;
+  std::string m_io_extendedascii_pdt_start;
+  std::string m_io_ascii_pdt_end;
+  std::string m_io_extendedascii_pdt_end;
+  // io type
+  int         m_io_type;
+  // default io units - used only when reading a file with no units
+  Units::MomentumUnit m_io_momentum_unit;
+  Units::LengthUnit   m_io_position_unit;
+
+};
+
+// inline methods
+
+inline CommonIO::CommonIO()
+: m_io_genevent_start("HepMC::IO_GenEvent-START_EVENT_LISTING"),
+  m_io_ascii_start("HepMC::IO_Ascii-START_EVENT_LISTING"),
+  m_io_extendedascii_start("HepMC::IO_ExtendedAscii-START_EVENT_LISTING"),
+  m_io_genevent_end("HepMC::IO_GenEvent-END_EVENT_LISTING"),
+  m_io_ascii_end("HepMC::IO_Ascii-END_EVENT_LISTING"),
+  m_io_extendedascii_end("HepMC::IO_ExtendedAscii-END_EVENT_LISTING"),
+  m_io_ascii_pdt_start("HepMC::IO_Ascii-START_PARTICLE_DATA"),
+  m_io_extendedascii_pdt_start("HepMC::IO_ExtendedAscii-START_PARTICLE_DATA"),
+  m_io_ascii_pdt_end("HepMC::IO_Ascii-END_PARTICLE_DATA"),
+  m_io_extendedascii_pdt_end("HepMC::IO_ExtendedAscii-END_PARTICLE_DATA"),
+  m_io_type(0),
+  m_io_momentum_unit(Units::default_momentum_unit()),
+  m_io_position_unit(Units::default_length_unit())
+  {}
+
+inline void CommonIO::write_IO_GenEvent_Key( std::ostream& os )
+{ os << m_io_genevent_start << "\n"; }
+
+inline void CommonIO::write_IO_GenEvent_End( std::ostream& os )
+{ os << m_io_genevent_end << "\n"; }
+
+inline void CommonIO::write_IO_Ascii_Key( std::ostream& os )
+{ os << m_io_ascii_start << "\n"; }
+
+inline void CommonIO::write_IO_Ascii_End( std::ostream& os )
+{ os << m_io_ascii_end << "\n"; }
+
+inline void CommonIO::write_IO_Ascii_PDT_Key( std::ostream& os )
+{ os << m_io_ascii_pdt_start << "\n"; }
+
+inline void CommonIO::write_IO_Ascii_PDT_End( std::ostream& os )
+{ os << m_io_ascii_pdt_end << "\n"; }
+
+} // HepMC
+
+#endif // HEPMC_COMMON_IO_H
Index: /trunk/Utilities/HepMC/interface/CompareGenEvent.h
===================================================================
--- /trunk/Utilities/HepMC/interface/CompareGenEvent.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/CompareGenEvent.h	(revision 349)
@@ -0,0 +1,30 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_COMPARE_GENEVENT_H
+#define HEPMC_COMPARE_GENEVENT_H
+
+/////////////////////////////////////////////////////////////////////////
+// CompareGenEvent.h
+//
+// garren@fnal.gov, January 2008
+// Free functions used to compare two copies of GenEvent
+//////////////////////////////////////////////////////////////////////////
+//
+
+#include <iostream>
+
+#include "GenEvent.h"
+
+namespace HepMC {
+
+bool compareGenEvent( GenEvent*, GenEvent* );
+bool compareSignalProcessVertex( GenEvent*, GenEvent* );
+bool compareBeamParticles( GenEvent*, GenEvent* );
+bool compareWeights( GenEvent*, GenEvent* );
+bool compareVertices( GenEvent*, GenEvent* );
+bool compareParticles( GenEvent*, GenEvent* );
+bool compareVertex( GenVertex* v1, GenVertex* v2 );
+
+} // HepMC
+
+#endif  // HEPMC_COMPARE_GENEVENT_H
+//--------------------------------------------------------------------------
Index: /trunk/Utilities/HepMC/interface/Flow.h
===================================================================
--- /trunk/Utilities/HepMC/interface/Flow.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/Flow.h	(revision 349)
@@ -0,0 +1,214 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_FLOW_H
+#define HEPMC_FLOW_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, January 2000, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// particle's flow object
+// keeps track of an arbitrary number of flow patterns within a graph 
+// (i.e. color flow, charge flow, lepton number flow, ...) 
+// Flow patterns are coded with an integer, in the same manner as in Herwig.
+// Note: 0 is NOT allowed as code index nor as flow code since it
+//       is used to indicate null.
+//////////////////////////////////////////////////////////////////////////
+
+// This class can be used to keep track of flow patterns within 
+//  a graph. An example is color flow. If we have two quarks going through
+//  an s-channel gluon to form two more quarks:
+//
+//  \q1       /q3   then we can keep track of the color flow with the
+//   \_______/      HepMC::Flow class as follows: 
+//   /   g   \. 
+//  /q2       \q4
+//
+//  lets say the color flows from q2-->g-->q3  and q1-->g-->q4
+//  the individual colors are unimportant, but the flow pattern is.
+//  We can capture this flow by assigning the first pattern (q2-->g-->q3)
+//  a unique (arbitrary) flow code 678 and the second pattern (q1-->g-->q4)
+//  flow code 269  ( you can ask HepMC::Flow to choose
+//  a unique code for you using Flow::set_unique_icode() ).
+//  The first two code indices are reserved for color codes, so we store 
+//  these codes with the particles as follows:
+//    q2->flow().set_icode(1,678);
+//    g->flow().set_icode(1,678);
+//    q3->flow().set_icode(1,678);
+//    q1->flow().set_icode(1,269);
+//    g->flow().set_icode(2,269);
+//    q4->flow().set_icode(1,269);
+//  later on if we wish to know the color partner of q1 we can ask for a list
+//  of all particles connected via this code to q1 which do have less than 
+//  2 color partners using:
+//    vector<GenParticle*> result=q1->dangling_connected_partners(q1->icode(1),1,2);
+//  this will return a list containing q1 and q4.
+//    vector<GenParticle*> result=q1->connected_partners(q1->icode(1),1,2);
+//  would return a list containing q1, g, and q4.
+//
+
+#include <iostream>
+#include <map>
+#include <vector>
+
+namespace HepMC {
+
+    class GenParticle;
+
+    //! The flow object
+
+    ///
+    /// \class  Flow
+    /// The particle's flow object
+    /// keeps track of an arbitrary number of flow patterns within a graph 
+    /// (i.e. color flow, charge flow, lepton number flow, ...) 
+    /// Flow patterns are coded with an integer, in the same manner as in Herwig.
+    class Flow {
+
+        /// for printing
+	friend std::ostream& operator<<( std::ostream& ostr, const Flow& f );
+	
+    public:
+        /// default constructor
+	Flow( GenParticle* particle_owner = 0 );
+	/// copy
+	Flow( const Flow& );
+	virtual         ~Flow();
+        /// swap
+        void swap( Flow & other);
+	/// make a copy
+	Flow&           operator=( const Flow& );
+	/// equality
+	bool            operator==( const Flow& a ) const; //compares only flow
+	/// inequality
+	bool            operator!=( const Flow& a ) const; //patterns not owner
+
+        /// print Flow information to ostr
+	void            print( std::ostream& ostr = std::cout ) const;
+
+	/// returns all connected particles which have "code" in any  of the 
+	///  num_indices beginning with index code_index.
+	std::vector<HepMC::GenParticle*> connected_partners( int code, int code_index =1,
+						   int num_indices = 2 ) const;
+	/// same as connected_partners, but returns only those particles which
+	///  are connected to <=1 other particles (i.e. the flow line "dangles"
+	///  at these particles)
+	std::vector<HepMC::GenParticle*> dangling_connected_partners( int code, 
+			       int code_index = 1, int num_indices = 2 ) const;
+
+	////////////////////
+	// access methods //
+	////////////////////
+
+	/// find particle owning this Flow
+	const GenParticle* particle_owner() const;
+	/// flow code
+	int             icode( int code_index = 1 ) const;
+	/// set flow code
+	Flow            set_icode( int code_index, int code );
+	/// set unique flow code
+	Flow            set_unique_icode( int code_index = 1 );
+
+	//////////////////////
+	// container access //
+	//////////////////////
+
+        /// return true if there is no flow container
+	bool            empty() const;
+	/// size of flow pattern container
+	int             size() const;
+	/// clear flow patterns
+        void            clear();
+	/// empty flow pattern container
+	bool            erase( int code_index );
+
+        /// iterator for flow pattern container
+        typedef std::map<int,int>::iterator       iterator;
+        /// const iterator for flow pattern container
+        typedef std::map<int,int>::const_iterator const_iterator;
+	/// beginning of flow pattern container
+        iterator            begin();
+	/// end of flow pattern container
+        iterator            end();
+	/// beginning of flow pattern container
+        const_iterator      begin() const;
+	/// end of flow pattern container
+        const_iterator      end() const;
+
+    protected: // intended for internal use only
+        /// for internal use only
+	void            connected_partners( std::vector<HepMC::GenParticle*>* output, 
+					    int code,
+					    int code_index,
+					    int num_indices ) const;
+        /// for internal use only
+	void            dangling_connected_partners( std::vector<HepMC::GenParticle*>* 
+						     output, 
+						     std::vector<HepMC::GenParticle*>*
+						     visited_particles, 
+						     int code, int code_index, 
+						     int num_indices ) const; 
+    private:
+	GenParticle*         m_particle_owner;
+	std::map<int,int> m_icode; // stores flow patterns as(code_index,icode)
+    };  
+
+    ///////////////////////////
+    // INLINE Access Methods //
+    ///////////////////////////
+
+    inline const GenParticle* Flow::particle_owner() const {
+	return m_particle_owner;
+    }
+    inline int Flow::icode( int code_index ) const {
+	std::map<int,int>::const_iterator a = m_icode.find(code_index);
+	return a==m_icode.end() ? 0 : (*a).second;
+    }
+    inline Flow Flow::set_icode( int code_index, int code ) {
+	m_icode[code_index] = code;
+	return *this;
+    }
+    inline Flow Flow::set_unique_icode( int flow_num ) {
+	/// use this method if you want to assign a unique flow code, but
+	/// do not want the burden of choosing it yourself
+	m_icode[flow_num] = size_t(this);
+	return *this;
+    }
+    inline bool Flow::empty() const { return (bool)m_icode.empty(); }
+    inline int Flow::size() const { return (int)m_icode.size(); }
+    inline void Flow::clear() { m_icode.clear(); }
+    inline bool Flow::erase( int code_index ) {
+	return (bool)m_icode.erase( code_index );
+    }
+    inline Flow::iterator Flow::begin() { return m_icode.begin(); }
+    inline Flow::iterator Flow::end() { return m_icode.end(); }
+    inline Flow::const_iterator Flow::begin() const { return m_icode.begin(); }
+    inline Flow::const_iterator Flow::end() const { return m_icode.end(); }
+
+    ///////////////////////////
+    // INLINE Operators      //
+    ///////////////////////////
+
+    inline bool Flow::operator==( const Flow& a ) const {
+	/// equivalent flows have the same flow codes for all flow_numbers 
+	/// (i.e. their m_icode maps are identical), but they need not have the
+	/// same m_particle owner
+	return (m_icode == a.m_icode);
+    }
+    inline bool Flow::operator!=( const Flow& a ) const {
+	return !( *this == a );
+    }
+    inline Flow& Flow::operator=( const Flow& inflow ) {
+	/// copies only the m_icode ... not the particle_owner
+	/// this is intuitive behaviour so you can do
+	/// oneparticle->flow() = otherparticle->flow()
+	//
+	m_icode = inflow.m_icode;
+	return *this;
+    }
+
+} // HepMC
+
+#endif  // HEPMC_FLOW_H
+//--------------------------------------------------------------------------
+
Index: /trunk/Utilities/HepMC/interface/GenEvent.h
===================================================================
--- /trunk/Utilities/HepMC/interface/GenEvent.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/GenEvent.h	(revision 349)
@@ -0,0 +1,739 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_GEN_EVENT_H
+#define HEPMC_GEN_EVENT_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// Event record for MC generators (for use at any stage of generation)
+//////////////////////////////////////////////////////////////////////////
+//
+// This class is intended as both a "container class" ( to store a MC
+//  event for interface between MC generators and detector simulation )
+//  and also as a "work in progress class" ( that could be used inside
+//  a generator and modified as the event is built ).
+//
+// Iterators are provided which allow the user to easily obtain a
+//  list of particles or vertices in an event --- this list can be filled
+//  subject to some sort of selection criteria. Examples are given below
+//  ( see HepMC::copy_if and std::copy )
+
+///
+/// \namespace HepMC
+/// All classes in the HepMC packages are in the HepMC namespace 
+///
+namespace HepMC {
+
+    // To create a list from an iterator, use: (i.e. for a list of particles);
+    // #include <algorithm>
+    //     list<GenParticle*> thelist;
+    //     copy( evt->particles_begin(), evt->particles_end(), 
+    //           back_inserter(thelist) );
+    // to create a list subject to a condition (predicate) use:
+    //     list<GenParticle*> thelist;
+    //     HepMC::copy_if( evt->particles_begin(), evt->particles_end(), 
+    //                     back_inserter(thelist), is_photon() );
+    // where is_photon() is a predicate like:
+    //     class is_photon {
+    //       public:
+    //         bool operator() ( GenParticle const * p ) {
+    //             if ( p && p->pdg_id() == 22 ) return true;
+    //             return false;
+    //         }
+    //     };
+    // which the user defines herself.
+
+    /// define the type of iterator to use
+    template <class InputIterator, class OutputIterator, class Predicate>
+    void copy_if( InputIterator first, InputIterator last, OutputIterator out,
+		  Predicate pred ) {
+	for ( ; first != last; ++first ) { if ( pred(*first) ) out = *first; }
+    }
+} // HepMC
+
+// Since a container of all vertices in the event is maintained, the time
+//  required to loop over all vertices (or particles) is very fast -- and 
+//  the user does not gain much by first making his own list.
+//  (this is not true for the GenVertex:: versions of these iterators, which
+//   allow you to specify the vertex starting point and range)
+
+// Data Members:
+// signal_process_id()   The integer ID that uniquely specifies this signal
+//                       process, i.e. MSUB in Pythia. It is necessary to
+//                       package this with each event rather than with the run
+//                       because many processes may be generated within one
+//                       run.
+// event_number()        Strictly speaking we cannot think of any reason that
+//                       an event would need to know its own event number, it
+//                       is more likely something that would be assigned by
+//                       a database. It is included anyway (tradition?) since
+//                       we expect it may be useful for debugging. It can
+//                       be reset later by a database.
+// mpi()                 The number of multi parton interactions in the event.
+//                       This is NOT beam pileup.  Set to -1 by default.
+// beam_particles()      A pair of pointers to the incoming beam particles.
+// signal_process_vertex() pointer to the vertex containing the signal process
+// weights()             Vector of doubles which specify th weight of the evnt,
+//                       the first entry will be the "event weight" used for
+//                       hit and miss etc., but a general vector is used to
+//                       allow for reweighting etc. We envision a list of
+//                       WeightTags to be included with a run class which
+//                       would specify the meaning of the Weights .
+// random_states()       Vector of integers which specify the random number 
+//                       generator's state for this event. It is left to the
+//                       generator to make use of this. We envision a vector of
+//                       RndmStatesTags to be included with a run class which
+//                       would specify the meaning of the random_states.
+//
+///////////////////////
+// Memory allocation //
+///////////////////////
+// -When a vertex (particle) is added to a event (vertex), it is "adopted" 
+//  and becomes the responsibility of the event (vertex) to delete that 
+//  particle. 
+// -objects responsible for deleting memory:
+//    -events delete included vertices
+//    -each vertex deletes its outgoing particles which do not have decay
+//     vertices
+//    -each vertex deletes its incoming particles which do not
+//     have creation vertices 
+//
+////////////////////////
+// About the Barcodes //
+////////////////////////
+// - each vertex or particle has a barcode, which is just an integer which
+//   uniquely identifies it inside the event (i.e. there is a one to one
+//   mapping between particle memory addresses and particle barcodes... and 
+//   the same applied for vertices)
+// - The value of a barcode has NO MEANING and NO ORDER!
+//   For the user's convenience, when an event is read in via an IO_method
+//   from an indexed list (like the HEPEVT common block), then the index will
+//   become the barcode for that particle.
+// - particle barcodes are always positive integers
+//   vertex barcodes are always negative integers
+//   The barcodes are chosen and set automatically when a vertex or particle
+//   comes under the ownership of an event (i.e. it is contained in an event).
+// - You can tell when a particle or vertex is owned, because its 
+//   parent_event() return value will return a pointer to the event which owns
+//   it (or null if its an orphan).
+// 
+
+#include "GenVertex.h"
+#include "GenParticle.h"
+#include "WeightContainer.h"
+#include "HeavyIon.h"
+#include "PdfInfo.h"
+#include "Units.h"
+#include <map>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+namespace HepMC {
+
+    //! The GenEvent class is the core of HepMC
+
+    ///
+    /// \class GenEvent 
+    /// HepMC::GenEvent contains information about generated particles.
+    /// GenEvent is structured as a set of vertices which contain the particles.
+    ///
+    class GenEvent {
+	friend class GenParticle;
+	friend class GenVertex;  
+    public:
+        /// default constructor creates null pointers to HeavyIon and PdfInfo
+	GenEvent( int signal_process_id = 0, int event_number = 0,
+		  GenVertex* signal_vertex = 0,
+		  const WeightContainer& weights = std::vector<double>(),
+		  const std::vector<long>& randomstates = std::vector<long>(),
+		  Units::MomentumUnit = Units::default_momentum_unit(), 
+		  Units::LengthUnit = Units::default_length_unit() );
+        /// explicit constructor that takes HeavyIon and PdfInfo
+	GenEvent( int signal_process_id, int event_number,
+		  GenVertex* signal_vertex, const WeightContainer& weights,
+		  const std::vector<long>& randomstates,
+		  const HeavyIon& ion, const PdfInfo& pdf,
+		  Units::MomentumUnit = Units::default_momentum_unit(), 
+		  Units::LengthUnit = Units::default_length_unit() );
+        /// constructor requiring units - all else is default
+	GenEvent( Units::MomentumUnit, Units::LengthUnit,
+	          int signal_process_id = 0, int event_number = 0,
+		  GenVertex* signal_vertex = 0,
+		  const WeightContainer& weights = std::vector<double>(),
+		  const std::vector<long>& randomstates = std::vector<long>() );
+        /// explicit constructor with units first that takes HeavyIon and PdfInfo
+	GenEvent( Units::MomentumUnit, Units::LengthUnit,
+	          int signal_process_id, int event_number,
+		  GenVertex* signal_vertex, const WeightContainer& weights,
+		  const std::vector<long>& randomstates,
+		  const HeavyIon& ion, const PdfInfo& pdf );
+	GenEvent( const GenEvent& inevent );          //!< deep copy
+	GenEvent& operator=( const GenEvent& inevent ); //!< make a deep copy
+	virtual ~GenEvent(); //!<deletes all vertices/particles in this evt
+
+        void swap( GenEvent & other );  //!< swap
+    
+	void print( std::ostream& ostr = std::cout ) const; //!< dumps to ostr
+	void print_version( std::ostream& ostr = std::cout ) const; //!< dumps release version to ostr
+
+        /// assign a barcode to a particle
+	GenParticle* barcode_to_particle( int barCode ) const;
+        /// assign a barcode to a vertex
+	GenVertex*   barcode_to_vertex(   int barCode ) const;
+
+	////////////////////
+	// access methods //
+	////////////////////
+
+	int signal_process_id() const; //!<  unique signal process id
+	int event_number() const; //!<  event number
+	int mpi() const;          //!<  number of multi parton interactions
+	double event_scale() const; //!< energy scale, see hep-ph/0109068
+	double alphaQCD() const; //!<  QCD coupling, see hep-ph/0109068
+	double alphaQED() const; //!<  QED coupling, see hep-ph/0109068
+        /// pointer to the vertex containing the signal process
+	GenVertex* signal_process_vertex() const;
+	/// test to see if we have two valid beam particles
+	bool valid_beam_particles() const;
+	/// pair of pointers to the two incoming beam particles
+	std::pair<HepMC::GenParticle*,HepMC::GenParticle*> beam_particles() const;
+
+	/// direct access to the weights container is allowed. 
+	/// Thus you can use myevt.weights()[2];
+	/// to access element 2 of the weights.
+	/// or use myevt.weights().push_back( mywgt ); to add an element.
+	/// and you can set the weights with myevt.weights() = myvector;
+	WeightContainer&        weights(); //!< direct access to WeightContainer
+	const WeightContainer&  weights() const; //!< direct access to WeightContainer
+
+	/// access the HeavyIon container if it exists
+	HeavyIon const *          heavy_ion() const;
+	HeavyIon*                heavy_ion();
+	/// access the PdfInfo container if it exists
+	PdfInfo const *           pdf_info() const;
+	PdfInfo*                 pdf_info();
+
+	/// vector of integers containing information about the random state
+	const std::vector<long>& random_states() const;
+
+        /// how many particle barcodes exist?
+	int     particles_size() const;
+        /// return true if there are no particle barcodes
+	bool    particles_empty() const;
+        /// how many vertex barcodes exist?
+	int     vertices_size() const;
+        /// return true if there are no vertex barcodes
+	bool    vertices_empty() const;
+
+        void write_units( std::ostream & os = std::cout ) const; 
+
+	/// Units used by the GenParticle momentum FourVector.
+	Units::MomentumUnit momentum_unit() const;
+	/// Units used by the GenVertex position FourVector.
+	Units::LengthUnit   length_unit()   const;
+
+	/////////////////////
+	// mutator methods //
+	/////////////////////
+
+	bool    add_vertex( GenVertex* vtx );    //!< adds to evt and adopts
+	bool    remove_vertex( GenVertex* vtx ); //!< erases vtx from evt
+	void    clear();                         //!< empties the entire event
+	
+	void set_signal_process_id( int id ); //!< set unique signal process id
+	void set_event_number( int eventno ); //!< set event number
+	void set_mpi( int  ); //!< set number of multi parton interactions
+	void set_event_scale( double scale ); //!< set energy scale
+	void set_alphaQCD( double a ); //!< set QCD coupling
+	void set_alphaQED( double a ); //!< set QED coupling
+
+        /// set pointer to the vertex containing the signal process
+	void set_signal_process_vertex( GenVertex* );
+	/// set incoming beam particles
+	bool set_beam_particles(GenParticle*, GenParticle*);
+        /// use a pair of GenParticle*'s to set incoming beam particles
+	bool set_beam_particles(std::pair<HepMC::GenParticle*,HepMC::GenParticle*> const &);
+	/// provide random state information
+	void set_random_states( const std::vector<long>& randomstates );
+
+	/// provide a pointer to the HeavyIon container
+	void set_heavy_ion( const HeavyIon& ion );
+	/// provide a pointer to the PdfInfo container
+	void set_pdf_info( const PdfInfo& p );
+	
+	/// set the units using enums
+	void use_units( Units::MomentumUnit, Units::LengthUnit );
+	/// set the units using strings
+	/// the string must match the enum exactly
+        void use_units( std::string&, std::string& );
+
+    public:
+	///////////////////////////////
+	// vertex_iterators          //
+	///////////////////////////////
+	// Note:  the XXX_iterator is "resolvable" as XXX_const_iterator, but 
+	//  not the reverse, which is consistent with STL, 
+	//  see Musser, Derge, Saini 2ndEd. p. 69,70.
+
+	//!  const vertex iterator
+
+	/// \class  vertex_const_iterator
+	/// HepMC::GenEvent::vertex_const_iterator
+	/// is used to iterate over all vertices in the event.
+	class vertex_const_iterator :
+	  public std::iterator<std::forward_iterator_tag,HepMC::GenVertex*,ptrdiff_t>{
+	    // Iterates over all vertices in this event
+	public:
+	    /// constructor requiring vertex information
+	    vertex_const_iterator(
+		const 
+		std::map<int,HepMC::GenVertex*,std::greater<int> >::const_iterator& i)
+		: m_map_iterator(i) {}
+	    vertex_const_iterator() {}
+	    /// copy constructor
+	    vertex_const_iterator( const vertex_const_iterator& i )
+		{ *this = i; }
+	    virtual ~vertex_const_iterator() {}
+	    /// make a copy
+	    vertex_const_iterator&  operator=( const vertex_const_iterator& i )
+		{ m_map_iterator = i.m_map_iterator; return *this; }
+	    /// return a pointer to a GenVertex
+	    GenVertex* operator*(void) const { return m_map_iterator->second; }
+	    /// Pre-fix increment
+	    vertex_const_iterator&  operator++(void)  //Pre-fix increment 
+		{ ++m_map_iterator; return *this; }
+	    /// Post-fix increment
+	    vertex_const_iterator   operator++(int)   //Post-fix increment
+		{ vertex_const_iterator out(*this); ++(*this); return out; }
+	    /// equality
+	    bool  operator==( const vertex_const_iterator& a ) const
+		{ return m_map_iterator == a.m_map_iterator; }
+	    /// inequality
+	    bool  operator!=( const vertex_const_iterator& a ) const
+		{ return !(m_map_iterator == a.m_map_iterator); }
+	protected:
+	    /// const iterator to a vertex map
+	    std::map<int,HepMC::GenVertex*,std::greater<int> >::const_iterator 
+	                                                        m_map_iterator;
+	};
+	friend class vertex_const_iterator;
+	/// begin vertex iteration
+	vertex_const_iterator      vertices_begin() const
+	    { return GenEvent::vertex_const_iterator( 
+		m_vertex_barcodes.begin() ); }
+	/// end vertex iteration
+	vertex_const_iterator      vertices_end() const
+	    { return GenEvent::vertex_const_iterator(
+		m_vertex_barcodes.end() ); }
+
+
+	//!  non-const vertex iterator
+
+	/// \class  vertex_iterator
+	/// HepMC::GenEvent::vertex_iterator
+	/// is used to iterate over all vertices in the event.
+	class vertex_iterator :
+	  public std::iterator<std::forward_iterator_tag,HepMC::GenVertex*,ptrdiff_t>{
+	    // Iterates over all vertices in this event
+	public:
+	    /// constructor requiring vertex information
+	    vertex_iterator( 
+		const 
+		std::map<int,HepMC::GenVertex*,std::greater<int> >::iterator& i )
+		: m_map_iterator( i ) {}
+	    vertex_iterator() {}
+	    /// copy constructor
+	    vertex_iterator( const vertex_iterator& i ) { *this = i; }
+	    virtual ~vertex_iterator() {}
+	    /// make a copy
+	    vertex_iterator&  operator=( const vertex_iterator& i ) {
+		m_map_iterator = i.m_map_iterator;
+		return *this;
+	    }
+	    /// const vertex iterator
+	    operator vertex_const_iterator() const
+		{ return vertex_const_iterator(m_map_iterator); }
+	    /// return a pointer to a GenVertex
+	    GenVertex*        operator*(void) const
+		{ return m_map_iterator->second; }
+	    /// Pre-fix increment
+	    vertex_iterator&  operator++(void)  //Pre-fix increment 
+		{ ++m_map_iterator;     return *this; }
+	    /// Post-fix increment
+	    vertex_iterator   operator++(int)   //Post-fix increment
+		{ vertex_iterator out(*this); ++(*this); return out; }
+	    /// equality
+	    bool              operator==( const vertex_iterator& a ) const
+		{ return m_map_iterator == a.m_map_iterator; }
+	    /// inequality
+	    bool              operator!=( const vertex_iterator& a ) const
+		{ return !(m_map_iterator == a.m_map_iterator); }
+	protected:
+	    /// iterator to the vertex map
+	    std::map<int,HepMC::GenVertex*,std::greater<int> >::iterator 
+	                                                       m_map_iterator;
+	};
+	friend class vertex_iterator;
+	/// begin vertex iteration
+	vertex_iterator            vertices_begin() 
+	    { return GenEvent::vertex_iterator( 
+		m_vertex_barcodes.begin() ); }
+	/// end vertex iteration
+        vertex_iterator            vertices_end()
+	    { return GenEvent::vertex_iterator(
+		m_vertex_barcodes.end() ); }
+
+    public:
+	///////////////////////////////
+	// particle_iterator         //
+	///////////////////////////////
+	// Example of iterating over all particles in the event:
+	//      for ( GenEvent::particle_const_iterator p = particles_begin();
+	//            p != particles_end(); ++p ) {
+	//         (*p)->print();
+	//      }
+	//
+
+	//!  const particle iterator
+
+	/// \class  particle_const_iterator
+	/// HepMC::GenEvent::particle_const_iterator 
+	/// is used to iterate over all particles in the event.
+	class particle_const_iterator :
+	  public std::iterator<std::forward_iterator_tag,HepMC::GenParticle*,ptrdiff_t>{
+	    // Iterates over all vertices in this event
+	public:
+	    /// iterate over particles
+	    particle_const_iterator(
+		const std::map<int,HepMC::GenParticle*>::const_iterator& i )
+		: m_map_iterator(i) {}
+	    particle_const_iterator() {}
+	    /// copy constructor
+	    particle_const_iterator( const particle_const_iterator& i )
+		{ *this = i; }
+	    virtual ~particle_const_iterator() {}
+	    /// make a copy
+	    particle_const_iterator& operator=(
+		const particle_const_iterator& i )
+		{ m_map_iterator = i.m_map_iterator; return *this; }
+	    /// return a pointer to GenParticle
+	    GenParticle*        operator*(void) const
+		{ return m_map_iterator->second; }
+	    /// Pre-fix increment
+	    particle_const_iterator&  operator++(void)  //Pre-fix increment 
+		{ ++m_map_iterator; return *this; }
+	    /// Post-fix increment
+	    particle_const_iterator   operator++(int)   //Post-fix increment
+		{ particle_const_iterator out(*this); ++(*this); return out; }
+	    /// equality
+	    bool  operator==( const particle_const_iterator& a ) const
+		{ return m_map_iterator == a.m_map_iterator; }
+	    /// inequality
+	    bool  operator!=( const particle_const_iterator& a ) const
+		{ return !(m_map_iterator == a.m_map_iterator); }
+	protected:
+	    /// const iterator to the GenParticle map
+	    std::map<int,HepMC::GenParticle*>::const_iterator m_map_iterator;
+	};	
+	friend class particle_const_iterator;
+	/// begin particle iteration
+	particle_const_iterator      particles_begin() const
+	    { return GenEvent::particle_const_iterator( 
+		m_particle_barcodes.begin() ); }
+	/// end particle iteration
+	particle_const_iterator      particles_end() const
+	    { return GenEvent::particle_const_iterator(
+		m_particle_barcodes.end() ); }
+
+	//!  non-const particle iterator
+
+	/// \class  particle_iterator
+	/// HepMC::GenEvent::particle_iterator 
+	/// is used to iterate over all particles in the event.
+ 	class particle_iterator :
+	  public std::iterator<std::forward_iterator_tag,HepMC::GenParticle*,ptrdiff_t>{
+	    // Iterates over all vertices in this event
+	public:
+	    /// iterate over particles
+	    particle_iterator( const std::map<int,HepMC::GenParticle*>::iterator& i )
+		: m_map_iterator( i ) {}
+	    particle_iterator() {}
+	    /// copy constructor
+	    particle_iterator( const particle_iterator& i ) { *this = i; }
+	    virtual ~particle_iterator() {}
+	    /// make a copy
+	    particle_iterator&  operator=( const particle_iterator& i ) {
+		m_map_iterator = i.m_map_iterator;
+		return *this;
+	    }
+	    /// const particle iterator
+	    operator particle_const_iterator() const
+		{ return particle_const_iterator(m_map_iterator); }
+	    /// return pointer to GenParticle
+	    GenParticle*        operator*(void) const
+		{ return m_map_iterator->second; }
+            /// Pre-fix increment
+	    particle_iterator&  operator++(void) 
+		{ ++m_map_iterator;     return *this; }
+            /// Post-fix increment
+	    particle_iterator   operator++(int)   
+		{ particle_iterator out(*this); ++(*this); return out; }
+            /// equality
+	    bool              operator==( const particle_iterator& a ) const
+		{ return m_map_iterator == a.m_map_iterator; }
+            /// inequality
+	    bool              operator!=( const particle_iterator& a ) const
+		{ return !(m_map_iterator == a.m_map_iterator); }
+	protected:
+	    /// iterator for GenParticle map
+	    std::map<int,HepMC::GenParticle*>::iterator m_map_iterator;
+	};
+	friend class particle_iterator;
+	/// begin particle iteration
+	particle_iterator particles_begin() 
+	    { return GenEvent::particle_iterator(
+		m_particle_barcodes.begin() ); }
+	/// end particle iteration
+        particle_iterator particles_end()
+	    { return GenEvent::particle_iterator(
+		m_particle_barcodes.end() ); }
+
+	////////////////////////////////////////////////
+    protected:
+	//
+	// Following methods intended for use by GenParticle/Vertex classes:
+	// In general there is no reason they should be used elsewhere.
+	/// set the barcode - intended for use by GenParticle
+	bool         set_barcode( GenParticle* p, int suggested_barcode =false );
+	/// set the barcode - intended for use by GenVertex
+	bool         set_barcode( GenVertex*   v, int suggested_barcode =false );
+	///  intended for use by GenParticle
+	void         remove_barcode( GenParticle* p );
+	///  intended for use by GenVertex
+	void         remove_barcode( GenVertex*   v );
+
+   	void delete_all_vertices(); //!<delete all vertices owned by this event
+
+     private: // methods
+        /// internal method used when converting momentum units
+        bool use_momentum_unit( Units::MomentumUnit );
+        bool use_momentum_unit( std::string& );
+        /// internal method used when converting length units
+	bool use_length_unit( Units::LengthUnit );
+	bool use_length_unit( std::string& );
+
+    private: // data members
+	int                   m_signal_process_id;
+	int                   m_event_number;  
+	int                   m_mpi;        // number of multi paricle interactions
+	double                m_event_scale;// energy scale, see hep-ph/0109068
+	double                m_alphaQCD;   // QCD coupling, see hep-ph/0109068
+	double                m_alphaQED;   // QED coupling, see hep-ph/0109068
+	GenVertex*            m_signal_process_vertex;
+	GenParticle*          m_beam_particle_1;
+	GenParticle*          m_beam_particle_2;
+	WeightContainer       m_weights; // weights for this event first weight
+	                                 // is used by default for hit and miss
+	std::vector<long> m_random_states; // container of rndm num 
+	                                       // generator states
+
+	std::map< int,HepMC::GenVertex*,std::greater<int> >   m_vertex_barcodes;
+	std::map< int,HepMC::GenParticle*,std::less<int> >    m_particle_barcodes;
+	HeavyIon*             m_heavy_ion; 	      // undefined by default
+	PdfInfo*              m_pdf_info; 	      // undefined by default
+	Units::MomentumUnit   m_momentum_unit;    // default value set by configure switch
+	Units::LengthUnit     m_position_unit;    // default value set by configure switch
+
+	//static unsigned int   s_counter;
+    };
+
+
+    ///////////////////////////
+    // INLINE Free Functions //
+    ///////////////////////////
+
+    // Implemented in terms of GenEvent::use_...
+    inline GenEvent& convert_units(GenEvent & evt, Units::MomentumUnit m, Units::LengthUnit l)
+    {
+      evt.use_units(m, l);
+      return evt;
+    }
+
+    ///////////////////////////
+    // INLINE Access Methods //
+    ///////////////////////////
+
+    ///  The integer ID that uniquely specifies this signal
+    ///  process, i.e. MSUB in Pythia. It is necessary to
+    ///  package this with each event rather than with the run
+    ///  because many processes may be generated within one run.
+    inline int GenEvent::signal_process_id() const 
+    { return m_signal_process_id; }
+
+    inline int GenEvent::event_number() const { return m_event_number; }
+
+    /// Returns the number of multi parton interactions in the event.
+    /// This number is -1 if it is not set.
+    inline int GenEvent::mpi() const { return m_mpi; }
+
+    inline double GenEvent::event_scale() const { return m_event_scale; }
+
+    inline double GenEvent::alphaQCD() const { return m_alphaQCD; }
+
+    inline double GenEvent::alphaQED() const { return m_alphaQED; }
+ 
+    inline GenVertex* GenEvent::signal_process_vertex() const {
+	/// returns a (mutable) pointer to the signal process vertex
+	return m_signal_process_vertex;
+    }  
+
+    inline WeightContainer& GenEvent::weights() { return m_weights; }
+
+    inline const WeightContainer& GenEvent::weights() const 
+    { return m_weights; }
+
+    inline HeavyIon const * GenEvent::heavy_ion() const 
+    { return m_heavy_ion; }
+
+    inline HeavyIon*  GenEvent::heavy_ion()  
+    { return m_heavy_ion; }
+
+    inline PdfInfo const * GenEvent::pdf_info() const 
+    { return m_pdf_info; }
+
+    inline PdfInfo*  GenEvent::pdf_info()  
+    { return m_pdf_info; }
+
+    ///  Vector of integers which specify the random number 
+    ///  generator's state for this event. It is left to the
+    ///  generator to make use of this. We envision a vector of
+    ///  RndmStatesTags to be included with a run class which
+    ///  would specify the meaning of the random_states.
+    inline const std::vector<long>& GenEvent::random_states() const 
+    { return m_random_states; }
+
+    inline void GenEvent::set_signal_process_id( int id )
+    { m_signal_process_id = id; }
+
+    inline void GenEvent::set_event_number( int eventno )
+    { m_event_number = eventno; }
+
+    /// Use this to set the number of multi parton interactions in each event.
+    inline void GenEvent::set_mpi( int nmpi )
+    { m_mpi = nmpi; }
+
+
+    inline void GenEvent::set_event_scale( double sc ) { m_event_scale = sc; }
+
+    inline void GenEvent::set_alphaQCD( double a ) { m_alphaQCD = a; }
+
+    inline void GenEvent::set_alphaQED( double a ) { m_alphaQED = a; }
+
+    inline void GenEvent::set_signal_process_vertex( GenVertex* vtx ) {
+	m_signal_process_vertex = vtx;
+	if ( m_signal_process_vertex ) add_vertex( m_signal_process_vertex );
+    }
+
+    inline void GenEvent::set_heavy_ion( const HeavyIon& ion )
+    { m_heavy_ion = new HeavyIon(ion); }
+
+    inline void GenEvent::set_pdf_info( const PdfInfo& p )
+    { m_pdf_info = new PdfInfo(p); }
+
+    inline void GenEvent::set_random_states( const std::vector<long>&
+					     randomstates )
+    { m_random_states = randomstates; }
+
+    inline void GenEvent::remove_barcode( HepMC::GenParticle* p )
+    { m_particle_barcodes.erase( p->barcode() ); }
+
+    inline void GenEvent::remove_barcode( GenVertex* v )
+    { m_vertex_barcodes.erase( v->barcode() ); }
+
+    /// Each vertex or particle has a barcode, which is just an integer which
+    /// uniquely identifies it inside the event (i.e. there is a one to one
+    /// mapping between particle memory addresses and particle barcodes... and 
+    /// the same applied for vertices).
+    ///
+    /// The value of a barcode has NO MEANING and NO ORDER!
+    /// For the user's convenience, when an event is read in via an IO_method
+    /// from an indexed list (like the HEPEVT common block), then the index will
+    /// become the barcode for that particle.
+    ///
+    /// Particle barcodes are always positive integers.
+    /// The barcodes are chosen and set automatically when a vertex or particle
+    /// comes under the ownership of an event (i.e. it is contained in an event).
+    inline GenParticle* GenEvent::barcode_to_particle( int barCode ) const
+    { 
+	std::map<int,HepMC::GenParticle*>::const_iterator i 
+	    = m_particle_barcodes.find(barCode);
+	return ( i != m_particle_barcodes.end() ) ? (*i).second : 0;
+    }
+
+    /// Each vertex or particle has a barcode, which is just an integer which
+    /// uniquely identifies it inside the event (i.e. there is a one to one
+    /// mapping between particle memory addresses and particle barcodes... and 
+    /// the same applied for vertices).
+    ///
+    /// The value of a barcode has NO MEANING and NO ORDER!
+    /// For the user's convenience, when an event is read in via an IO_method
+    /// from an indexed list (like the HEPEVT common block), then the index will
+    /// become the barcode for that particle.
+    ///
+    /// Vertex barcodes are always negative integers.
+    /// The barcodes are chosen and set automatically when a vertex or particle
+    /// comes under the ownership of an event (i.e. it is contained in an event).
+    inline GenVertex* GenEvent::barcode_to_vertex( int barCode ) const
+    {
+	std::map<int,GenVertex*,std::greater<int> >::const_iterator i 
+	    = m_vertex_barcodes.find(barCode);
+	return ( i != m_vertex_barcodes.end() ) ? (*i).second : 0;
+    }
+
+    inline int GenEvent::particles_size() const {
+	return (int)m_particle_barcodes.size();
+    }
+    inline bool GenEvent::particles_empty() const {
+	return (bool)m_particle_barcodes.empty();
+    }
+    inline int GenEvent::vertices_size() const {
+	return (int)m_vertex_barcodes.size();
+    }
+    inline bool GenEvent::vertices_empty() const {
+	return (bool)m_vertex_barcodes.empty();
+    }
+    
+    // beam particles
+    inline std::pair<HepMC::GenParticle*,HepMC::GenParticle*> GenEvent::beam_particles() const {
+        return std::pair<GenParticle*,GenParticle*> (m_beam_particle_1, m_beam_particle_2);
+    }
+
+    // units
+    inline Units::MomentumUnit GenEvent::momentum_unit() const {
+        return m_momentum_unit; 
+    }
+    inline Units::LengthUnit   GenEvent::length_unit()   const {
+        return m_position_unit; 
+    }
+    
+    inline void GenEvent::use_units( Units::MomentumUnit new_m, Units::LengthUnit new_l ) { 
+       use_momentum_unit( new_m );
+       use_length_unit( new_l );
+    }
+    
+    inline void GenEvent::use_units( std::string& new_m, std::string& new_l ) { 
+       use_momentum_unit( new_m );
+       use_length_unit( new_l );
+    }
+
+} // HepMC
+
+#endif  // HEPMC_GEN_EVENT_H
+
+//--------------------------------------------------------------------------
+
+
Index: /trunk/Utilities/HepMC/interface/GenParticle.h
===================================================================
--- /trunk/Utilities/HepMC/interface/GenParticle.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/GenParticle.h	(revision 349)
@@ -0,0 +1,231 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_GEN_PARTICLE_H
+#define HEPMC_GEN_PARTICLE_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// particle within an event coming in/out of a vertex
+// particle is the basic building block or unit of the event record
+//////////////////////////////////////////////////////////////////////////
+//
+// example:
+//      GenParticle* p = new GenParticle( FourVector(1,1,1,3), 11, 1 );
+// creates a particle with 4-vector (p,E)=1,1,1,3 - with pdg id 11 (electron)
+// and give this particle status =1.
+//
+// the pointers to end/production vertices can only be set by the
+//  vertices themselves - thus to set the production vertex for a particle,
+//  you add the particle to that vertex with GenVertex::add_particle_out()
+//
+// We decide not to have a separate 4 vector for the momentum 
+//  at decay time (which MC++ includes to allow dE/dX losses etc). 
+//  If you want that, just add a decay vertex with the
+//  same particle (modified momentum) going out
+//
+
+#include "Flow.h"
+#include "Polarization.h"
+#include "SimpleVector.h"
+#include <iostream>
+#ifdef _WIN32
+#define hepmc_uint64_t  __int64
+#else
+#include <stdint.h>	// for uint64_t
+#define hepmc_uint64_t   uint64_t
+#endif
+
+namespace HepMC {
+
+    class GenVertex;
+    class GenEvent; 
+
+
+    //! The GenParticle class contains information about generated particles
+
+    ///
+    /// \class GenParticle 
+    /// HepMC::GenParticle 
+    /// contains momentum, generated mass, particle ID, decay status, 
+    /// flow, polarization, pointers to production and decay vertices
+    /// and a unique barcode identfier.
+    ///
+    class GenParticle {
+
+	friend class GenVertex; // so vertex can set decay/production vertexes
+	friend class GenEvent;  // so event can set the barCodes
+	/// print particle
+	friend std::ostream& operator<<( std::ostream&, const GenParticle& );
+
+    public:
+        /// default constructor
+        GenParticle(void);
+        /// constructor requires momentum and particle ID
+ 	GenParticle( const FourVector& momentum, int pdg_id,
+		     int status = 0, const Flow& itsflow = Flow(),
+		     const Polarization& polar = Polarization(0,0) );
+	GenParticle( const GenParticle& inparticle ); //!< shallow copy.
+	virtual ~GenParticle();
+
+        void swap( GenParticle & other); //!< swap
+	GenParticle& operator=( const GenParticle& inparticle ); //!< shallow.
+        /// check for equality
+	bool         operator==( const GenParticle& ) const;
+        /// check for inequality
+	bool         operator!=( const GenParticle& ) const;
+
+	/// dump this particle's full info to ostr
+	void       print( std::ostream& ostr = std::cout ) const; 
+
+	operator HepMC::FourVector() const; //!< conversion operator
+
+	////////////////////
+	// access methods //
+	////////////////////
+
+	/// standard 4 momentum
+	const FourVector &          momentum() const;
+	/// particle ID
+	int                  pdg_id() const;
+	/// HEPEVT decay status
+	int                  status() const;
+	/// particle flow
+	const Flow &         flow() const;
+	/// particle flow index
+	int                  flow( int code_index ) const;
+        /// polarization information
+	const Polarization & polarization() const;
+	/// pointer to the production vertex
+	GenVertex*           production_vertex() const;
+	/// pointer to the decay vertex
+	GenVertex*           end_vertex() const;
+	/// pointer to the event that owns this particle
+	GenEvent*            parent_event() const;
+
+        /// Because of precision issues, the generated mass is not always the 
+	/// same as the mass calculated from the momentum 4 vector.
+        /// If the generated mass has been set, then generated_mass() 
+	/// returns that value.
+        /// If the generated mass has not been set, then generated_mass() 
+	/// returns the mass calculated from the momentum 4 vector.
+        double               generated_mass() const; //!< mass as generated
+
+	/// generatedMass() is included for backwards compatibility with CLHEP HepMC
+        double               generatedMass() const { return generated_mass(); }
+
+
+	///
+	/// The barcode is the particle's reference number, every vertex in the
+	///  event has a unique barcode. Particle barcodes are positive numbers,
+	///  vertex barcodes are negative numbers.
+	int                  barcode() const; //!< particle barcode
+
+	/////////////////////
+	// mutator methods //
+	/////////////////////
+
+	/// In general there is no reason to "suggest_barcode"
+	bool                 suggest_barcode( int the_bar_code );
+
+	void   set_momentum( const FourVector& vec4 ); //!< set standard 4 momentum
+	void   set_pdg_id( int id ); //!< set particle ID
+	void   set_status( int status = 0 ); //!< set decay status
+	void   set_flow( const Flow& f ); //!< set particle flow
+	void   set_flow( int code_index, int code = 0 ); //!< set particle flow index
+	/// set polarization
+	void   set_polarization( const Polarization& pol = Polarization(0,0) );
+        ///  If you do not call set_generated_mass(), then 
+        ///  generated_mass() will simply return the mass calculated from momentum()
+        void   set_generated_mass( const double & m ); //!< define the actual generated mass
+
+	///  setGeneratedMass() is included for backwards compatibility with CLHEP HepMC
+        void   setGeneratedMass( const double & m )  
+	                 { return set_generated_mass(m); }
+
+    protected: // for internal use only by friend GenVertex class
+
+	//static unsigned int counter(); //!< temporary for debugging
+
+        /// set production vertex - for internal use only
+	void   set_production_vertex_( GenVertex* productionvertex = 0);
+        /// set decay vertex - for internal use only
+	void   set_end_vertex_( GenVertex* decayvertex = 0 );
+	void   set_barcode_( int the_bar_code ); //!< for use by GenEvent only
+
+        /// scale the momentum vector and generated mass 
+        /// this method is only for use by GenEvent
+	void convert_momentum( const double& );
+
+    private:
+	FourVector       m_momentum;          // momentum vector
+	int              m_pdg_id;            // id according to PDG convention
+	int              m_status;            // As defined for HEPEVT
+	Flow             m_flow;
+	Polarization     m_polarization;
+	GenVertex*       m_production_vertex; // null if vacuum or beam
+	GenVertex*       m_end_vertex;        // null if not-decayed
+	int              m_barcode;           // unique identifier in the event
+        double           m_generated_mass;    // mass of this particle when it was generated
+
+	//static unsigned int       s_counter;
+    };  
+
+    //////////////
+    // INLINES  //
+    //////////////
+
+    inline GenParticle::operator HepMC::FourVector() const 
+    { return m_momentum; }
+
+    inline const FourVector & GenParticle::momentum() const 
+    { return m_momentum; }
+
+    inline int GenParticle::pdg_id() const { return m_pdg_id; }
+
+    inline int GenParticle::status() const { return m_status; }
+
+    inline GenVertex* GenParticle::production_vertex() const 
+    { return m_production_vertex; }
+
+    inline GenVertex* GenParticle::end_vertex() const { return m_end_vertex; }
+
+    inline const Flow & GenParticle::flow() const { return m_flow; }
+
+    inline int GenParticle::flow( int code_index ) const
+    { return m_flow.icode( code_index ); }
+
+    inline const Polarization & GenParticle::polarization() const 
+    { return m_polarization; }
+
+    inline void GenParticle::set_momentum( const FourVector& vec4 )
+    { m_momentum = vec4; }
+
+    inline void GenParticle::set_pdg_id( int id ) { m_pdg_id = id; }
+
+    inline void GenParticle::set_status( int status ) { m_status = status; }
+
+    inline void GenParticle::set_flow( const Flow& f ) { m_flow = f; }
+
+    inline void GenParticle::set_flow( int code_index, int code ) 
+    {
+	if ( code == 0 ) { 
+	    m_flow.set_unique_icode( code_index );
+	} else { 
+	    m_flow.set_icode( code_index, code );
+	}
+    }
+
+    inline void GenParticle::set_polarization( const Polarization& polar )
+    { m_polarization = polar; }
+
+    inline int  GenParticle::barcode() const { return m_barcode; }
+
+    inline void GenParticle::set_barcode_( int bc ) { m_barcode = bc; }
+
+} // HepMC
+
+#endif  // HEPMC_GEN_PARTICLE_H
+//--------------------------------------------------------------------------
+
Index: /trunk/Utilities/HepMC/interface/GenVertex.h
===================================================================
--- /trunk/Utilities/HepMC/interface/GenVertex.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/GenVertex.h	(revision 349)
@@ -0,0 +1,509 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_GEN_VERTEX_H
+#define HEPMC_GEN_VERTEX_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// GenVertex within an event
+// A vertex is indirectly (via particle "edges") linked to other 
+//   vertices ("nodes") to form a composite "graph"
+//////////////////////////////////////////////////////////////////////////
+
+// --> HANDLE COMPILER INCONSISTENCIES
+// This pre-compiler directive is included (2002-01-16) to allow compatibility
+// with several compilers.
+// Mar 27, 2004: HepMC is now standard compliant only. 
+//   I've removed forward_iterator, and it will no longer compile on gcc < 3. 
+#ifdef __SUNPRO_CC    // Solaris CC 5.2
+#define NEED_SOLARIS_FRIEND_FEATURE
+#endif // Platform
+
+#include "WeightContainer.h"
+#include "SimpleVector.h"
+#include <iostream>
+#include <iterator>
+#include <vector>
+#include <set>
+#include <algorithm>
+
+namespace HepMC {
+
+    /// type of iteration
+    enum IteratorRange { parents, children, family, 
+			 ancestors, descendants, relatives };
+    class GenParticle;
+    class GenEvent;
+
+    //! GenVertex contains information about decay vertices.
+
+    ///
+    /// \class GenVertex 
+    /// HepMC::GenVertex contains the position in space and time of a decay.
+    /// It also contains lists of incoming and outgoing particles.  
+    ///
+    class GenVertex {
+
+        /// print vertex information
+	friend std::ostream& operator<<( std::ostream&, const GenVertex& );
+	friend class GenEvent;
+
+#ifdef NEED_SOLARIS_FRIEND_FEATURE
+	// This bit of ugly code is only for CC-5.2 compiler. 
+	// M.Dobbs 2002/02/19 
+	// It is not needed by linux gcc, nor Windows Visual C++.
+    public: 
+	class vertex_iterator;
+	friend class vertex_iterator;
+	class particle_iterator;
+	friend class particle_iterator;
+#endif // NEED_SOLARIS_FRIEND_FEATURE
+
+    public:
+        /// default constructor
+	GenVertex( const FourVector& position =FourVector(0,0,0,0),
+		   int id = 0, 
+		   const WeightContainer& weights = std::vector<double>() );
+	GenVertex( const GenVertex& invertex );            //!< shallow copy
+	virtual    ~GenVertex();
+
+        void swap( GenVertex & other); //!< swap
+	GenVertex& operator= ( const GenVertex& invertex ); //!< shallow
+	bool       operator==( const GenVertex& a ) const; //!< equality
+	bool       operator!=( const GenVertex& a ) const; //!< inequality
+	void       print( std::ostream& ostr = std::cout ) const; //!< print vertex information
+
+	double     check_momentum_conservation() const;//!< |Sum (mom_in-mom_out)|
+
+	/// add incoming particle
+	void       add_particle_in( GenParticle* inparticle );
+	/// add outgoing particle
+	void       add_particle_out( GenParticle* outparticle );
+	/// remove_particle finds *particle in the in and/or out list and
+	///  removes it from these lists ... it DOES NOT DELETE THE PARTICLE 
+	///  or its relations. You could delete the particle too as follows:
+	///      delete vtx->remove_particle( particle );
+	GenParticle* remove_particle( GenParticle* particle ); //!< remove a particle
+
+	operator    HepMC::FourVector() const; //!< conversion operator
+	operator   HepMC::ThreeVector() const; //!< conversion operator
+
+	////////////////////
+	// access methods //
+	////////////////////
+
+	/// pointer to the event that owns this vertex
+	GenEvent*               parent_event() const;
+	/// vertex position
+	ThreeVector             point3d() const;
+	/// vertex position and time
+	const FourVector &      position() const;
+	/// set vertex position and time
+	void                    set_position( const FourVector& position = FourVector(0,0,0,0) );
+	/// we don't define what you use the id for -- but we imagine,
+	/// for example it might code the meaning of the weights()
+	int                     id() const;  //!< vertex ID
+	void                    set_id( int id );  //!< set vertex ID
+
+	///
+	/// The barcode is the vertex's reference number, every vertex in the
+	///  event has a unique barcode. Vertex barcodes are negative numbers,
+	///  particle barcodes are positive numbers.
+	int                     barcode() const; //!< unique identifier
+
+	/// In general there is no reason to "suggest_barcode"
+	bool                    suggest_barcode( int the_bar_code );
+	
+	/// direct access to the weights container is allowed. 
+	WeightContainer&        weights();
+	/// const direct access to the weights container
+	const WeightContainer&  weights() const;
+
+	////////////////////
+	// Iterators      // users should use prefer to use particle_iterator
+	////////////////////    
+
+	/// const iterator for incoming particles
+	typedef std::vector<HepMC::GenParticle*>::const_iterator 
+	particles_in_const_iterator;
+	/// const iterator for outgoing particles
+	typedef std::vector<HepMC::GenParticle*>::const_iterator 
+	particles_out_const_iterator;
+	/// begin iteration of incoming particles
+	particles_in_const_iterator         particles_in_const_begin() const;
+	/// end iteration of incoming particles
+	particles_in_const_iterator         particles_in_const_end() const;
+	/// begin iteration of outgoing particles
+	particles_out_const_iterator        particles_out_const_begin() const;
+	/// end iteration of outgoing particles
+	particles_out_const_iterator        particles_out_const_end() const;
+	/// number of incoming particles
+	int                                 particles_in_size() const;
+	/// number of outgoing particles
+	int                                 particles_out_size() const;
+
+    protected:
+	//static unsigned int     counter(); //!< temporary for debugging
+
+	/// only the GenEvent (friend) is allowed to set the parent_event,
+	///  and barcode. It is done automatically anytime you add a 
+	///  vertex to an event
+	void                    set_parent_event_( GenEvent* evt ); //!< set parent event
+	void                    set_barcode_( int the_bar_code ); //!< set identifier
+	void                    change_parent_event_( GenEvent* evt ); //!< for use with swap
+
+	/////////////////////////////
+	// edge_iterator           // (protected - for internal use only)
+	/////////////////////////////
+	// If the user wants the functionality of the edge_iterator, he should
+	// use particle_iterator with IteratorRange = family, parents, children
+	//
+
+	//!  edge iterator
+
+	/// \class  edge_iterator
+	/// iterate over the family of edges connected to m_vertex begins 
+	/// with parents (incoming particles) then children (outgoing)
+	/// This is not a recursive iterator ... it is a building block
+	/// for the public iterators and is intended for internal use only.
+	/// The acceptable Iterator Ranges are: family, parents, children
+	class edge_iterator :
+	  public std::iterator<std::forward_iterator_tag,HepMC::GenParticle*,ptrdiff_t>{
+	public:
+	    edge_iterator();
+	    /// used to set limits on the iteration
+	    edge_iterator( const GenVertex& vtx, IteratorRange range =family );
+	    /// copy
+	    edge_iterator( const edge_iterator& p );
+	    virtual        ~edge_iterator();
+	    /// make a copy
+	    edge_iterator& operator=( const edge_iterator& p );
+	    /// return a pointer to a particle
+	    GenParticle*      operator*(void) const;
+	    /// Pre-fix increment 
+	    edge_iterator& operator++(void); // Pre-fix increment 
+	    /// Post-fix increment
+	    edge_iterator  operator++(int);   // Post-fix increment
+	    /// equality
+	    bool           operator==( const edge_iterator& a ) const;
+	    /// inequality
+	    bool           operator!=( const edge_iterator& a ) const;
+	    /// true if parent of root vtx
+	    bool           is_parent() const;
+	    /// true if child of root vtx
+	    bool           is_child() const;
+	    /// root vertex of this iteration
+	    const GenVertex*  vertex_root() const;
+	private:
+	    const GenVertex*  m_vertex;
+	    IteratorRange  m_range;
+	    std::vector<HepMC::GenParticle*>::const_iterator m_set_iter;
+	    bool           m_is_inparticle_iter;
+	    bool           m_is_past_end;
+	};
+	friend class edge_iterator;
+	/// size
+	int              edges_size( IteratorRange range = family ) const;
+	/// begin range
+	edge_iterator    edges_begin( IteratorRange range = family) const;
+	/// end range
+	edge_iterator    edges_end( IteratorRange /* dummy_range */ ) const;
+
+    public:
+	///////////////////////////////
+	// vertex_iterator           //
+	///////////////////////////////
+
+	//!  vertex iterator
+
+	/// \class  vertex_iterator
+	/// Iterates over all vertices connected via a graph to this vertex.
+	/// this is made friend to that it can access protected edge
+	/// iterator the range can be IteratorRange= ( parents, children, 
+	/// family, ancestors, descendants, relatives )
+	/// example for range=descendants the iterator 
+	/// will return all vertices
+	/// which are children (connected by an outgoing particle edge),
+	/// grandchildren, great-grandchildren, etc. of this vertex
+	/// In all cases the iterator always returns this vertex
+	/// (returned last).
+	/// The algorithm is accomplished by converting the graph to a tree
+	/// (by "chopping" the edges connecting to an already visited
+	/// vertex) and returning the vertices in POST ORDER traversal.
+	///
+	class vertex_iterator :
+	  public std::iterator<std::forward_iterator_tag,HepMC::GenVertex*,ptrdiff_t>{
+	public:
+	    vertex_iterator();
+	    /// used to set limits on the iteration
+	    vertex_iterator( GenVertex& vtx_root, IteratorRange range );
+	    /// next constructor is intended for internal use only
+	    vertex_iterator( GenVertex& vtx_root, IteratorRange range,
+			     std::set<const HepMC::GenVertex*>& visited_vertices );
+            /// copy
+	    vertex_iterator( const vertex_iterator& v_iter );
+	    virtual             ~vertex_iterator();
+	    /// make a copy
+	    vertex_iterator&    operator=( const vertex_iterator& );
+	    /// return a pointer to a vertex
+	    GenVertex*          operator*(void) const;
+	    /// Pre-fix increment 
+	    vertex_iterator&    operator++(void);  //Pre-fix increment 
+	    /// Post-fix increment
+	    vertex_iterator     operator++(int);   //Post-fix increment
+	    /// equality
+	    bool                operator==( const vertex_iterator& ) const;
+	    /// inequality
+	    bool                operator!=( const vertex_iterator& ) const;
+	    /// vertex that this iterator begins from
+	    GenVertex*          vertex_root() const;
+	    /// iterator range
+	    IteratorRange       range() const;
+	    /// intended for internal use only.
+	    void                copy_with_own_set( const vertex_iterator& 
+						   v_iter,
+						   std::set<const HepMC::GenVertex*>& 
+						   visited_vertices );
+
+	protected:                  // intended for internal use only
+	    /// non-null if recursive iter. created
+	    GenVertex* follow_edge_(); 
+	    /// copy recursive iterator
+	    void    copy_recursive_iterator_( const vertex_iterator* 
+					      recursive_v_iter );
+	private:
+	    GenVertex*       m_vertex;   // the vertex associated to this iter
+	    IteratorRange    m_range;
+	    std::set<const HepMC::GenVertex*>* m_visited_vertices;
+	    bool             m_it_owns_set;  // true if it is responsible for 
+	                                     // deleting the visited vertex set
+	    edge_iterator    m_edge; // particle edge pointing to return vtx
+	    vertex_iterator* m_recursive_iterator;
+	};	
+	friend class vertex_iterator;
+	/// begin vertex range
+	vertex_iterator     vertices_begin( IteratorRange range = relatives );
+	/// end vertex range
+	vertex_iterator     vertices_end( IteratorRange /* dummy_range */ );
+ 
+    public:
+	///////////////////////////////
+	// particle_iterator         //
+	///////////////////////////////
+
+	//!  particle iterator
+
+	/// \class  particle_iterator
+	/// Iterates over all particles connected via a graph.
+	/// by iterating through all vertices in the m_range. For each
+	/// vertex it returns orphaned parent particles 
+	/// (i.e. parents without production vertices) 
+	/// then children ... in this way each particle is associated
+	/// to exactly one vertex and so it is returned exactly once.
+	/// Is made friend so that it can access protected edge iterator
+ 	class particle_iterator :
+	  public std::iterator<std::forward_iterator_tag,GenParticle*,ptrdiff_t>{
+	public:
+	    particle_iterator();
+	    /// used to set limits on the iteration
+	    particle_iterator( GenVertex& vertex_root, IteratorRange range );
+	    /// copy
+	    particle_iterator( const particle_iterator& );
+	    virtual             ~particle_iterator();
+	    /// make a copy
+	    particle_iterator&  operator=( const particle_iterator& );
+	    /// return a pointer to a particle
+	    GenParticle*        operator*(void) const;
+	    /// Pre-fix increment 
+	    particle_iterator&  operator++(void); 
+	    /// Post-fix increment
+	    particle_iterator   operator++(int); 
+	    /// equality
+	    bool                operator==( const particle_iterator& ) const;
+	    /// inequality
+	    bool                operator!=( const particle_iterator& ) const;
+	protected:
+	    GenParticle*        advance_to_first_(); //!< "first" particle
+	private:
+	    vertex_iterator     m_vertex_iterator;
+	    edge_iterator       m_edge;     // points to the return
+	};
+	friend class particle_iterator;
+	/// begin particle range
+	particle_iterator       particles_begin( IteratorRange range 
+						 = relatives );
+	/// end particle range
+	particle_iterator       particles_end( IteratorRange 
+					       /* dummy_range */ );
+
+	////////////////////////////////////////////////
+    protected: 
+        /// for internal use only
+	void delete_adopted_particles();
+	/// for internal use only - remove particle from incoming list
+	void remove_particle_in( GenParticle* );
+	/// for internal use only - remove particle from outgoing list
+	void remove_particle_out( GenParticle* );
+	/// scale the position vector
+        /// this method is only for use by GenEvent
+	void convert_position( const double& );
+
+    private: // GenVertex data members
+	FourVector              m_position;      //4-vec of vertex [mm]
+	std::vector<HepMC::GenParticle*>  m_particles_in;  //all incoming particles
+	std::vector<HepMC::GenParticle*>  m_particles_out; //all outgoing particles
+	int                  m_id;
+	WeightContainer      m_weights;       // weights for this vtx
+	GenEvent*            m_event;
+	int                  m_barcode;   // unique identifier in the event
+
+	//static unsigned int  s_counter;
+    };  
+
+    ////////////////////////////
+    // INLINES access methods //
+    ////////////////////////////
+
+    inline GenVertex::operator HepMC::FourVector() const { return position(); }
+
+    inline GenVertex::operator HepMC::ThreeVector() const { return point3d(); }
+
+    inline const FourVector & GenVertex::position() const { return m_position; }
+
+    inline GenEvent* GenVertex::parent_event() const { return m_event; }
+
+    inline ThreeVector GenVertex::point3d() const { 
+	return ThreeVector(m_position.x(),m_position.y(),m_position.z()); 
+    }
+
+    inline int GenVertex::id() const { return m_id; }
+
+    inline int  GenVertex::barcode() const { return m_barcode; }
+    inline void GenVertex::set_barcode_( int bc ) { m_barcode = bc; }
+
+    inline WeightContainer& GenVertex::weights() { return m_weights; }
+
+    inline const WeightContainer& GenVertex::weights() const 
+    { return m_weights; }
+
+    inline void GenVertex::set_position( const FourVector& position ) {
+	m_position = position;
+    }
+
+    inline void GenVertex::set_id( int id ) { m_id = id; }
+
+    //////////////
+    // INLINES  //
+    //////////////
+
+    inline GenVertex::particles_in_const_iterator 
+    GenVertex::particles_in_const_begin() const { 
+	return m_particles_in.begin(); 
+    }
+
+    inline GenVertex::particles_in_const_iterator 
+    GenVertex::particles_in_const_end() const { 
+	return m_particles_in.end(); 
+    }
+
+    inline GenVertex::particles_out_const_iterator 
+    GenVertex::particles_out_const_begin() const { 
+	return m_particles_out.begin();
+    }
+
+    inline GenVertex::particles_out_const_iterator 
+    GenVertex::particles_out_const_end() const {	
+	return m_particles_out.end(); 
+    }
+
+    inline int GenVertex::particles_in_size() const {
+	return m_particles_in.size(); 
+    }
+
+    inline int GenVertex::particles_out_size() const {
+	return m_particles_out.size(); 
+    }	
+
+    inline bool GenVertex::edge_iterator::operator==( 
+	const edge_iterator& a ) const { 
+	return **this == *a; 
+    }
+
+    inline bool GenVertex::edge_iterator::operator!=(
+	const edge_iterator& a ) const { 
+	return !(**this == *a); 
+    }
+
+    inline const GenVertex* GenVertex::edge_iterator::vertex_root() const {
+	return m_vertex;
+    }
+
+    inline GenVertex::edge_iterator GenVertex::edges_begin( IteratorRange 
+						      range ) const {
+	return GenVertex::edge_iterator(*this, range);
+    }
+
+    inline GenVertex::edge_iterator GenVertex::edges_end( IteratorRange 
+						    /* dummy_range */ ) const {
+	return GenVertex::edge_iterator();
+    }
+
+    inline bool GenVertex::vertex_iterator::operator==( 
+	const vertex_iterator& a ) const {
+	return **this == *a; 
+    }
+
+    inline bool GenVertex::vertex_iterator::operator!=( 
+	const vertex_iterator& a ) const {
+	return !(**this == *a); 
+    }
+
+    inline GenVertex* GenVertex::vertex_iterator::vertex_root() const {
+	return m_vertex; 
+    }
+
+    inline IteratorRange GenVertex::vertex_iterator::range() const {
+	return m_range; 
+    }
+
+    inline GenVertex::vertex_iterator GenVertex::vertices_begin( 
+	IteratorRange range ){
+	// this is not const because the it could return itself
+	return vertex_iterator( *this, range );
+    }
+
+    inline GenVertex::vertex_iterator GenVertex::vertices_end( 
+	IteratorRange /* dummy_range */ ) {
+	return vertex_iterator();
+    }
+
+    inline bool GenVertex::particle_iterator::operator==( 
+	const particle_iterator& a ) const {
+	return **this == *a; 
+    }
+
+    inline bool GenVertex::particle_iterator::operator!=( 
+	const particle_iterator& a ) const {
+	return !(**this == *a); 
+    }
+
+    inline GenVertex::particle_iterator GenVertex::particles_begin( 
+	IteratorRange range ) {
+	return particle_iterator( *this, range );
+    }
+
+    inline GenVertex::particle_iterator GenVertex::particles_end(
+	IteratorRange /* dummy_range */ ){
+	return particle_iterator();
+    }
+
+} // HepMC
+
+#endif  // HEPMC_GEN_VERTEX_H
+//--------------------------------------------------------------------------
+
+
+
+
Index: /trunk/Utilities/HepMC/interface/HeavyIon.h
===================================================================
--- /trunk/Utilities/HepMC/interface/HeavyIon.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/HeavyIon.h	(revision 349)
@@ -0,0 +1,252 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_HEAVY_ION_H
+#define HEPMC_HEAVY_ION_H
+
+//////////////////////////////////////////////////////////////////////////
+// garren@fnal.gov, February 2006
+//
+// Additional information storage for Heavy Ion generators
+//////////////////////////////////////////////////////////////////////////
+//
+//      int   Ncoll_hard          // Number of hard scatterings
+//      int   Npart_proj          // Number of projectile participants
+//      int   Npart_targ          // Number of target participants
+//      int   Ncoll               // Number of NN (nucleon-nucleon) collisions
+//      int   N_Nwounded_collisions        // Number of N-Nwounded collisions
+//      int   Nwounded_N_collisions        // Number of Nwounded-N collisons
+//      int   Nwounded_Nwounded_collisions // Number of Nwounded-Nwounded collisions
+//      int   spectator_neutrons           // Number of spectator neutrons
+//      int   spectator_protons            // Number of spectator protons
+//      float impact_parameter        // Impact Parameter(fm) of collision
+//      float event_plane_angle       // Azimuthal angle of event plane
+//      float eccentricity            // eccentricity of participating nucleons
+//                                        in the transverse plane 
+//                                        (as in phobos nucl-ex/0510031) 
+//      float sigma_inel_NN           // nucleon-nucleon inelastic 
+//                                        (including diffractive) cross-section
+//
+//////////////////////////////////////////////////////////////////////////
+// Feb. 17, 2006: adjust names according to suggestions from Heavy Ion users
+// Feb.  7, 2006: first pass at making method names consistent with existing
+//                HepMC code
+//////////////////////////////////////////////////////////////////////////
+
+namespace HepMC {
+
+
+//! The HeavyIon class stores information about heavy ions
+
+///
+/// \class  HeavyIon
+/// HepMC::HeavyIon provides
+/// additional information storage for Heavy Ion generators in GenEvent.
+/// Creation and use of this information is optional. 
+///
+class HeavyIon {
+
+public:
+  // ---  birth/death:
+  //
+  /// default constructor
+  HeavyIon()
+    : m_Ncoll_hard(0), 
+      m_Npart_proj(0),
+      m_Npart_targ(0),
+      m_Ncoll(0),
+      m_spectator_neutrons(0),
+      m_spectator_protons(0),
+      m_N_Nwounded_collisions(0),
+      m_Nwounded_N_collisions(0),
+      m_Nwounded_Nwounded_collisions(0),
+      m_impact_parameter(0),
+      m_event_plane_angle(0),
+      m_eccentricity(0),
+      m_sigma_inel_NN(0)
+    {}
+
+  /// The first 6 values must be provided.
+  HeavyIon( int nh, int np, int nt, int nc, int ns, int nsp,
+                   int nnw=0, int nwn=0, int nwnw=0, 
+		   float im=0., float pl=0., float ec=0., float s=0. );
+
+  ~HeavyIon() {}
+    
+  // ---  copying:
+  //
+  HeavyIon( HeavyIon const & orig );	//!< copy constructor
+  HeavyIon &  operator = ( HeavyIon const & rhs ); //!< make a copy
+  void swap( HeavyIon & other );	//!< swap two HeavyIon objects
+
+  // ---  equivalence:
+  //
+  bool    operator==( const HeavyIon& ) const; //!< check for equality
+  bool    operator!=( const HeavyIon& ) const; //!< check for inequality
+
+  // ---  accessors:
+    /// Number of hard scatterings
+    int   Ncoll_hard()                   const { return m_Ncoll_hard; }
+    /// Number of projectile participants
+    int   Npart_proj()                   const { return m_Npart_proj; }
+    /// Number of target participants
+    int   Npart_targ()                   const { return m_Npart_targ; }
+    /// Number of NN (nucleon-nucleon) collisions
+    int   Ncoll()                        const { return m_Ncoll; }
+    /// Number of spectator neutrons
+    int   spectator_neutrons()           const { return m_spectator_neutrons; }
+    /// Number of spectator protons
+    int   spectator_protons()            const { return m_spectator_protons; }
+    /// Number of N-Nwounded collisions
+    int   N_Nwounded_collisions()        const { return m_N_Nwounded_collisions; }
+    /// Number of Nwounded-N collisons
+    int   Nwounded_N_collisions()        const { return m_Nwounded_N_collisions; }
+    /// Number of Nwounded-Nwounded collisions
+    int   Nwounded_Nwounded_collisions() const { return m_Nwounded_Nwounded_collisions; }
+    /// Impact Parameter(in fm) of collision
+    float impact_parameter()             const { return m_impact_parameter; }
+    /// Azimuthal angle of event plane
+    float event_plane_angle()            const { return m_event_plane_angle; }
+    /// eccentricity of participating nucleons in the transverse plane 
+    /// (as in phobos nucl-ex/0510031)
+    float eccentricity()                 const { return m_eccentricity;  }
+    /// nucleon-nucleon inelastic (including diffractive) cross-section
+    float sigma_inel_NN()                const { return m_sigma_inel_NN; }
+
+  // ---  mutators:
+    /// set number of hard scatterings
+    void   set_Ncoll_hard(const int &i)              { m_Ncoll_hard=i; }
+    /// set number of projectile participants
+    void   set_Npart_proj(const int &i)              { m_Npart_proj=i; }
+    /// set number of target participants
+    void   set_Npart_targ(const int &i)              { m_Npart_targ=i; }
+    /// set number of NN (nucleon-nucleon) collisions
+    void   set_Ncoll(const int &i)                   { m_Ncoll=i; }
+    /// set number of spectator neutrons
+    void   set_spectator_neutrons(const int &i)      { m_spectator_neutrons=i; }
+    /// set number of spectator protons
+    void   set_spectator_protons(const int &i)       { m_spectator_protons=i; }
+    /// set number of N-Nwounded collisions
+    void   set_N_Nwounded_collisions(const int &i)   { m_N_Nwounded_collisions=i; }
+    /// set number of Nwounded-N collisons
+    void   set_Nwounded_N_collisions(const int &i)   { m_Nwounded_N_collisions=i; }
+    /// set number of Nwounded-Nwounded collisions
+    void   set_Nwounded_Nwounded_collisions(const int &i) 
+                                          { m_Nwounded_Nwounded_collisions=i; }
+    /// set Impact Parameter in fm
+    void   set_impact_parameter(const float &f)      { m_impact_parameter=f; }
+    /// set azimuthal angle of event plane
+    void   set_event_plane_angle(const float &f)     { m_event_plane_angle=f; }
+    /// set eccentricity of participating nucleons in the transverse plane 
+    void   set_eccentricity(const float &f)          { m_eccentricity=f;  }
+    /// set nucleon-nucleon inelastic cross-section
+    void   set_sigma_inel_NN(const float &f)         { m_sigma_inel_NN=f; }
+
+private: // data members
+    int   m_Ncoll_hard; 
+    int   m_Npart_proj; 
+    int   m_Npart_targ;
+    int   m_Ncoll;
+    int   m_spectator_neutrons;
+    int   m_spectator_protons;
+    int   m_N_Nwounded_collisions;
+    int   m_Nwounded_N_collisions;
+    int   m_Nwounded_Nwounded_collisions;
+    float m_impact_parameter;
+    float m_event_plane_angle;
+    float m_eccentricity; 
+    float m_sigma_inel_NN;
+
+};
+
+// inline operators
+  /// Required members are
+  /// the number of hard scatterings,
+  /// the number of projectile participants.
+  /// the number of target participants.
+  /// the number of nucleon-nucleon collisions,
+  /// the number of spectator neutrons, and
+  /// the number of spectator protons.
+inline HeavyIon::HeavyIon( int nh, int np, int nt, int nc, int ns, int nsp,
+                   int nnw, int nwn, int nwnw, 
+		   float im, float pl, float ec, float s )
+    : m_Ncoll_hard(nh), 
+      m_Npart_proj(np),
+      m_Npart_targ(nt),
+      m_Ncoll(nc),
+      m_spectator_neutrons(ns),
+      m_spectator_protons(nsp),
+      m_N_Nwounded_collisions(nnw),
+      m_Nwounded_N_collisions(nwn),
+      m_Nwounded_Nwounded_collisions(nwnw),
+      m_impact_parameter(im),
+      m_event_plane_angle(pl),
+      m_eccentricity(ec),
+      m_sigma_inel_NN(s)
+   {}
+
+inline HeavyIon::HeavyIon( HeavyIon const & orig )
+    : m_Ncoll_hard(orig.m_Ncoll_hard), 
+      m_Npart_proj(orig.m_Npart_proj),
+      m_Npart_targ(orig.m_Npart_targ),
+      m_Ncoll(orig.m_Ncoll),
+      m_spectator_neutrons(orig.m_spectator_neutrons),
+      m_spectator_protons(orig.m_spectator_protons),
+      m_N_Nwounded_collisions(orig.m_N_Nwounded_collisions),
+      m_Nwounded_N_collisions(orig.m_Nwounded_N_collisions),
+      m_Nwounded_Nwounded_collisions(orig.m_Nwounded_Nwounded_collisions),
+      m_impact_parameter(orig.m_impact_parameter),
+      m_event_plane_angle(orig.m_event_plane_angle),
+      m_eccentricity(orig.m_eccentricity),
+      m_sigma_inel_NN(orig.m_sigma_inel_NN)
+   {}
+
+inline HeavyIon &  HeavyIon::operator = ( HeavyIon const & rhs ) 
+{
+  HeavyIon temp( rhs );
+  swap( temp );
+  return *this;
+}
+
+inline void HeavyIon::swap( HeavyIon & other ) 
+{
+  std::swap(m_Ncoll_hard, other.m_Ncoll_hard); 
+  std::swap(m_Npart_proj, other.m_Npart_proj);
+  std::swap(m_Npart_targ, other.m_Npart_targ);
+  std::swap(m_Ncoll, other.m_Ncoll);
+  std::swap(m_N_Nwounded_collisions, other.m_N_Nwounded_collisions);
+  std::swap(m_Nwounded_N_collisions, other.m_Nwounded_N_collisions);
+  std::swap(m_Nwounded_Nwounded_collisions, other.m_Nwounded_Nwounded_collisions);
+  std::swap(m_spectator_neutrons, other.m_spectator_neutrons);
+  std::swap(m_spectator_protons, other.m_spectator_protons);
+  std::swap(m_impact_parameter, other.m_impact_parameter);
+  std::swap(m_event_plane_angle, other.m_event_plane_angle);
+  std::swap(m_eccentricity, other.m_eccentricity);
+  std::swap(m_sigma_inel_NN, other.m_sigma_inel_NN);
+}
+
+inline bool    HeavyIon::operator==( const HeavyIon& a ) const
+{
+    /// equality requires that each member match
+    return ( a.Ncoll_hard() == this->Ncoll_hard() 
+             && a.Npart_proj() == this->Npart_proj() 
+             && a.Npart_targ() == this->Npart_targ() 
+	     && a.Ncoll() == this->Ncoll() 
+             && a.N_Nwounded_collisions() == this->N_Nwounded_collisions() 
+	     && a.Nwounded_N_collisions() == this->Nwounded_N_collisions() 
+             && a.Nwounded_Nwounded_collisions() == this->Nwounded_Nwounded_collisions() 
+	     && a.spectator_neutrons() == this->spectator_neutrons() 
+             && a.spectator_protons() == this->spectator_protons() 
+	     && a.impact_parameter() == this->impact_parameter() 
+	     && a.event_plane_angle() == this->event_plane_angle()
+	     && a.eccentricity() == this->eccentricity() 
+	     && a.sigma_inel_NN() == this->sigma_inel_NN() );
+}
+
+inline bool    HeavyIon::operator!=( const HeavyIon& a ) const
+{
+    /// any nonmatching member generates inequality
+    return !( a == *this );
+}
+
+} // HepMC
+
+#endif  // HEPMC_HEAVY_ION_H
Index: /trunk/Utilities/HepMC/interface/IO_Ascii.h
===================================================================
--- /trunk/Utilities/HepMC/interface/IO_Ascii.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/IO_Ascii.h	(revision 349)
@@ -0,0 +1,134 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_IO_ASCII_H
+#define HEPMC_IO_ASCII_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, January 2000, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// event input/output in ascii format for machine reading
+//////////////////////////////////////////////////////////////////////////
+//
+// Strategy for reading or writing events/particleData as machine readable
+//  ascii to a file. When instantiating, the mode of file to be created 
+//  must be specified. Options are:
+//      std::ios::in     open file for input 
+//      std::ios::out    open file for output
+//      std::ios::trunc  erase old file when opening (i.e. ios::out|ios::trunc
+//                    removes oldfile, and creates a new one for output )
+//      std::ios::app    append output to end of file
+//  for the purposes of this class, simultaneous input and output mode 
+//  ( std::ios::in | std::ios::out ) is not allowed.
+// 
+// Event listings are preceded by the key:
+//  "HepMC::IO_Ascii-START_EVENT_LISTING\n"
+//  and terminated by the key:
+//  "HepMC::IO_Ascii-END_EVENT_LISTING\n"
+// GenParticle Data tables are preceded by the key:
+//  "HepMC::IO_Ascii-START_PARTICLE_DATA\n"
+//  and terminated by the key:
+//  "HepMC::IO_Ascii-END_PARTICLE_DATA\n"
+// Comments are allowed. They need not be preceded by anything, though if
+//  a comment is written using write_comment( const string ) then it will be
+//  preceded by "HepMC::IO_Ascii-COMMENT\n"
+// Each event, vertex, particle, particle data is preceded by 
+//  "E ","V ","P ","D "    respectively.
+// Comments may appear anywhere in the file -- so long as they do not contain
+//  any of the 4 start/stop keys.
+//
+
+#include <fstream>
+#include <string>
+#include <map>
+#include <vector>
+#include "IO_BaseClass.h"
+#include "TempParticleMap.h"
+#include "CommonIO.h"
+
+namespace HepMC {
+
+    class GenEvent;
+    class GenVertex;
+    class GenParticle;
+    class ParticleData;
+
+    //! IO_Ascii is used to read or write from an ascii file
+
+    ///
+    /// \class  IO_Ascii
+    /// Strategy for reading or writing events/particleData as machine readable
+    ///  ascii to a file. When instantiating, the mode of file to be created 
+    ///  must be specified. 
+    ///
+    class IO_Ascii : public IO_BaseClass {
+    public:
+        /// constructor requiring a file name and std::ios mode
+	IO_Ascii( const char* filename="IO_Ascii.dat", 
+		  std::ios::openmode mode=std::ios::out );
+	virtual       ~IO_Ascii();
+
+        /// write this event
+	void          write_event( const GenEvent* evt );
+        /// get the next event
+	bool          fill_next_event( GenEvent* evt );
+	void          write_particle_data_table(const ParticleDataTable*);
+	bool          fill_particle_data_table( ParticleDataTable* );
+	/// insert a comment directly into the output file --- normally you
+	///  only want to do this at the beginning or end of the file. All
+	///  comments are preceded with "HepMC::IO_Ascii-COMMENT\n"
+  	void          write_comment( const std::string comment );
+
+	int           rdstate() const;  //!< check the state of the IO stream
+	void          clear();  //!< clear the IO stream
+
+        /// write to ostr
+	void          print( std::ostream& ostr = std::cout ) const;
+
+    protected: // for internal use only
+	/// write vertex information
+	void          write_vertex( GenVertex* );
+	/// write particle information
+	void          write_particle( GenParticle* p );
+	/// write ParticleDataTable information
+	void          write_particle_data( const ParticleData* d );
+	/// write end tag
+	bool          write_end_listing();
+
+	void          output( const double& );  //!< write double
+	void          output( const int& );  //!< write int
+	void          output( const long int& );  //!< write long int
+	void          output( const char& );  //!< write a single character
+    private: // use of copy constructor is not allowed
+	IO_Ascii( const IO_Ascii& ) : IO_BaseClass() {}
+    private: // data members
+	std::ios::openmode  m_mode;
+	std::fstream        m_file;
+	bool                m_finished_first_event_io;
+	CommonIO            m_common_io;
+    };
+
+    //////////////
+    // Inlines  //
+    //////////////
+
+    inline void IO_Ascii::output( const double& d ) {
+	if ( d == 0. ) {
+	    m_file << ' ' << (int)0;
+	} else {
+	    m_file << ' ' << d;
+	}
+    }
+    inline void IO_Ascii::output( const int& i ) { m_file << ' ' << i; }
+    inline void IO_Ascii::output( const long int& i ) { m_file << ' ' << i; }
+    inline void IO_Ascii::output( const char& c ) { m_file << c; }
+    inline int  IO_Ascii::rdstate() const { return (int)m_file.rdstate(); }
+    inline void IO_Ascii::clear() { m_file.clear(); }
+
+} // HepMC
+
+#endif  // HEPMC_IO_ASCII_H
+//--------------------------------------------------------------------------
+
+
+
Index: /trunk/Utilities/HepMC/interface/IO_AsciiParticles.h
===================================================================
--- /trunk/Utilities/HepMC/interface/IO_AsciiParticles.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/IO_AsciiParticles.h	(revision 349)
@@ -0,0 +1,112 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_IO_ASCIIPARTICLES_H
+#define HEPMC_IO_ASCIIPARTICLES_H
+
+//////////////////////////////////////////////////////////////////////////
+// Mikhail.Kirsanov@Cern.CH, 2006
+// event input/output in ascii format for eye and machine reading
+//////////////////////////////////////////////////////////////////////////
+//
+// Strategy for reading or writing events/particleData as machine readable
+//  ascii to a file. When instantiating, the mode of file to be created 
+//  must be specified. Options are:
+//      std::ios::in     open file for input 
+//      std::ios::out    open file for output
+//      std::ios::trunc  erase old file when opening (i.e. ios::out|ios::trunc
+//                    removes oldfile, and creates a new one for output )
+//      std::ios::app    append output to end of file
+//  for the purposes of this class, simultaneous input and output mode 
+//  ( std::ios::in | std::ios::out ) is not allowed.
+// 
+// Event listings are preceded by the key:
+//  "HepMC::IO_AsciiParticles-START_EVENT_LISTING\n"
+//  and terminated by the key:
+//  "HepMC::IO_AsciiParticles-END_EVENT_LISTING\n"
+// Comments are allowed. They need not be preceded by anything, though if
+//  a comment is written using write_comment( const string ) then it will be
+//  preceded by "HepMC::IO_AsciiParticles-COMMENT\n"
+// Each event, vertex, particle, particle data is preceded by 
+//  "E ","V ","P ","D "    respectively.
+// Comments may appear anywhere in the file -- so long as they do not contain
+//  any of the 4 start/stop keys.
+//
+
+#include <fstream>
+#include <string>
+#include <map>
+#include <vector>
+#include "IO_BaseClass.h"
+
+namespace HepMC {
+
+    class GenEvent;
+    class GenVertex;
+    class GenParticle;
+
+    //! event input/output in ascii format for eye and machine reading
+
+    ///
+    /// \class IO_AsciiParticles
+    /// Strategy for reading or writing events/particleData as machine readable
+    ///  ascii to a file. When instantiating, the mode of file to be created 
+    ///  must be specified. 
+    ///
+    class IO_AsciiParticles : public IO_BaseClass {
+    public:
+        /// constructor requiring a file name and std::ios mode
+	IO_AsciiParticles( const char* filename="IO_AsciiParticles.dat", 
+		  std::ios::openmode mode=std::ios::out );
+	virtual       ~IO_AsciiParticles();
+
+        /// write this event
+  	void          write_event( const GenEvent* evt );
+        /// get the next event
+	bool          fill_next_event( GenEvent* evt );
+    inline void          write_particle_data_table(const ParticleDataTable*);
+    inline bool          fill_particle_data_table( ParticleDataTable* );
+	/// insert a comment directly into the output file --- normally you
+	///  only want to do this at the beginning or end of the file. All
+	///  comments are preceded with "HepMC::IO_AsciiParticles-COMMENT\n"
+  	void          write_comment( const std::string comment );
+
+        /// set output precision
+        void          setPrecision(int iprec);
+
+	int           rdstate() const;  //!< check the state of the IO stream
+	void          clear();  //!< clear the IO stream
+
+        /// write to ostr
+	void          print( std::ostream& ostr = std::cout ) const;
+
+    protected: // for internal use only
+	/// write end tag
+	bool          write_end_listing();
+    private: // use of copy constructor is not allowed
+	IO_AsciiParticles( const IO_AsciiParticles& ) : IO_BaseClass() {}
+    private: // data members
+    int                 m_precision;
+	std::ios::openmode  m_mode;
+	std::fstream*       m_file;
+    std::ostream*       m_outstream;
+	bool                m_finished_first_event_io;
+    };
+
+    //////////////
+    // Inlines  //
+    //////////////
+
+    inline int  IO_AsciiParticles::rdstate() const { return (int)m_file->rdstate(); }
+    inline void IO_AsciiParticles::clear() { m_file->clear(); }
+    inline void IO_AsciiParticles::setPrecision(int iprec) { m_precision=iprec; }
+
+    /////////////////////
+    // Inline dummies  //
+    /////////////////////
+
+  void IO_AsciiParticles::write_particle_data_table(const ParticleDataTable*) {;}
+  bool IO_AsciiParticles::fill_particle_data_table( ParticleDataTable* ) {return false;}
+
+} // HepMC
+
+#endif  // HEPMC_IO_ASCIIPARTICLES_H
+//--------------------------------------------------------------------------
Index: /trunk/Utilities/HepMC/interface/IO_BaseClass.h
===================================================================
--- /trunk/Utilities/HepMC/interface/IO_BaseClass.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/IO_BaseClass.h	(revision 349)
@@ -0,0 +1,161 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_IO_BASECLASS_H
+#define HEPMC_IO_BASECLASS_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, November 1999, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// event input/output base class
+//////////////////////////////////////////////////////////////////////////
+//
+// class from which all input/output classes shall inherit from.
+// i.e.: if you want to write events to hbook ntuples,
+//              then inherit from this class and re-define read_event()
+//              and write_event()
+//
+// (Possible extension: Could make this an input iterator)
+//
+
+#include <iostream>
+#include "ParticleDataTable.h"
+#include "GenEvent.h"
+
+namespace HepMC {
+
+    //! all input/output classes inherit from IO_BaseClass
+
+    ///
+    /// \class  IO_BaseClass
+    /// If you want to write a new IO class, 
+    /// then inherit from this class and re-define read_event()
+    /// and write_event()
+    ///
+    class IO_BaseClass {
+    public:
+        virtual ~IO_BaseClass() {}
+
+	/// write this GenEvent
+	virtual void write_event( const GenEvent* ) =0;
+	/// fill this GenEvent
+	virtual bool fill_next_event( GenEvent* ) =0;
+	/// write this ParticleDataTable
+	virtual void write_particle_data_table( const ParticleDataTable* ) =0;
+	/// fill this ParticleDataTable
+	virtual bool fill_particle_data_table( ParticleDataTable* ) =0;
+	/// write output to ostr
+	virtual void print( std::ostream& ostr = std::cout ) const;
+	//
+	// the read_next_event() and read_particle_data_table() differ from
+	// the fill_***() methods in that they create a new event or pdt
+	// before calling the  corresponding fill_*** method
+	// (they are not intended to be over-ridden)
+	GenEvent*    read_next_event();  //!< do not over-ride
+	ParticleDataTable* read_particle_data_table();  //!< do not over-ride
+	//
+	// The overloaded stream operators >>,<< are identical to
+	//   read_next_event and write_event methods respectively.
+	//   (or read_particle_data_table and write_particle_data_table)
+	// the event argument for the overloaded stream operators is a pointer,
+	// which is passed by reference.
+	//  i.e.  GenEvent* evt; 
+	//        io >> evt; 
+	// will give the expected result.
+	// (note: I don't see any reason to have separate const and non-const
+	//  versions of operator<<, but the pedantic ansi standard insists 
+	//  on it) 
+	/// the same as read_next_event
+	virtual       GenEvent*& operator>>( GenEvent*& );
+	/// the same as write_event
+	virtual const GenEvent*& operator<<( const GenEvent*& );
+	/// the same as write_event
+	virtual       GenEvent*& operator<<( GenEvent*& );
+	/// the same as read_particle_data_table
+	virtual       ParticleDataTable*& operator>>( ParticleDataTable*& );
+	/// the same as write_particle_data_table
+	virtual const ParticleDataTable*& operator<<( const 
+						      ParticleDataTable*& );
+	/// the same as write_particle_data_table
+	virtual       ParticleDataTable*& operator<<( ParticleDataTable*& );
+    };
+
+    //////////////
+    // Inlines  //
+    //////////////
+
+    inline GenEvent* IO_BaseClass::read_next_event() {
+	/// creates a new event and fills it by calling 
+	/// the sister method read_next_event( GenEvent* )
+	// 
+        // 1. create an empty event container
+        GenEvent* evt = new GenEvent();
+	// 2. fill the evt container - if the read is successful, return the
+	//    pointer, otherwise return null and delete the evt
+	if ( fill_next_event( evt ) ) return evt;
+	// note: the below delete is only reached if read fails
+	//       ... thus there is not much overhead in new then delete 
+	//       since this statement is rarely reached
+	delete evt;
+	return 0;
+    }
+
+    inline ParticleDataTable* IO_BaseClass::read_particle_data_table() {
+	/// creates a new particle data table and fills it by calling 
+	/// the sister method read_particle_data_table( ParticleDataTable* )
+	//
+	// 1. create an empty pdt
+	ParticleDataTable* pdt = new ParticleDataTable();
+	// 2. fill the pdt container - if the read is successful, return the
+	//    pointer, otherwise return null and delete the evt
+	if ( fill_particle_data_table( pdt ) ) return pdt;
+	// next statement is only reached if read fails
+	delete pdt;
+	return 0;
+    }
+
+    inline void IO_BaseClass::print( std::ostream& ostr ) const { 
+	ostr << "IO_BaseClass: abstract parent I/O class. " <<  std::endl;
+    }
+
+    inline GenEvent*& IO_BaseClass::operator>>( GenEvent*& evt ){
+	evt = read_next_event();
+	return evt;
+    }
+
+    inline const GenEvent*& IO_BaseClass::operator<<(
+					      const GenEvent*& evt ) {
+	write_event( evt );
+	return evt;
+    }
+
+    inline GenEvent*& IO_BaseClass::operator<<( GenEvent*& evt ) {
+	write_event( evt );
+	return evt;
+    }
+
+    inline ParticleDataTable*& IO_BaseClass::operator>>( 
+					   ParticleDataTable*& pdt ){
+	pdt = read_particle_data_table();
+	return pdt;
+    }
+
+    inline const ParticleDataTable*& IO_BaseClass::operator<<(
+					     const ParticleDataTable*& pdt ) {
+	write_particle_data_table( pdt );
+	return pdt;
+    }
+
+    inline ParticleDataTable*& IO_BaseClass::operator<<(
+	                                            ParticleDataTable*& pdt ) {
+	write_particle_data_table( pdt );
+	return pdt;
+    }
+
+} // HepMC
+
+#endif  // HEPMC_IO_BASECLASS_H
+//--------------------------------------------------------------------------
+
+
+
Index: /trunk/Utilities/HepMC/interface/IO_GenEvent.h
===================================================================
--- /trunk/Utilities/HepMC/interface/IO_GenEvent.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/IO_GenEvent.h	(revision 349)
@@ -0,0 +1,219 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_IO_GENEVENT_H
+#define HEPMC_IO_GENEVENT_H
+
+//////////////////////////////////////////////////////////////////////////
+// garren@fnal.gov, July 2007
+// with input from Gavin Salam, salam@lpthe.jussieu.fr
+//
+// event input/output in ascii format for machine reading
+// This class persists all information found in a GenEvent
+//////////////////////////////////////////////////////////////////////////
+
+#include <fstream>
+#include <string>
+#include <map>
+#include <vector>
+#include "IO_BaseClass.h"
+#include "TempParticleMap.h"
+#include "CommonIO.h"
+#include "Units.h"
+
+namespace HepMC {
+
+    class GenEvent;
+    class GenVertex;
+    class GenParticle;
+    class ParticleData;
+    class HeavyIon;
+    class PdfInfo;
+
+    //! IO_GenEvent also deals with HeavyIon and PdfInfo 
+
+    ///
+    /// \class  IO_GenEvent
+    /// event input/output in ascii format for machine reading
+    /// extended format contains HeavyIon and PdfInfo classes
+    ///
+    /// Strategy for reading or writing events using iostreams
+    /// When instantiating with a file name, the mode of file to be created 
+    ///  must be specified. Options are:
+    ///      std::ios::in     open file for input 
+    ///      std::ios::out    open file for output
+    ///      std::ios::trunc  erase old file when opening (i.e. ios::out|ios::trunc
+    ///                    removes oldfile, and creates a new one for output )
+    ///      std::ios::app    append output to end of file
+    ///  for the purposes of this class, simultaneous input and output mode 
+    ///  ( std::ios::in | std::ios::out ) is not allowed.
+    /// 
+    /// Event listings are preceded by the key:
+    ///  "HepMC::IO_GenEvent-START_EVENT_LISTING\n"
+    ///  and terminated by the key:
+    ///  "HepMC::IO_GenEvent-END_EVENT_LISTING\n"
+    /// GenParticle Data tables are preceded by the key:
+    ///  "HepMC::IO_GenEvent-START_PARTICLE_DATA\n"
+    ///  and terminated by the key:
+    ///  "HepMC::IO_GenEvent-END_PARTICLE_DATA\n"
+    /// Comments are allowed. They need not be preceded by anything, though if
+    ///  a comment is written using write_comment( const string ) then it will be
+    ///  preceded by "HepMC::IO_GenEvent-COMMENT\n"
+    /// Each event, vertex, particle, particle data, heavy ion, or pdf info line
+    ///  is preceded by   "E ","V ","P ","D ","H ","F "    respectively.
+    /// Comments may appear anywhere in the file -- so long as they do not contain
+    ///  any of the start/stop keys.
+    ///
+    class IO_GenEvent : public IO_BaseClass {
+    public:
+        /// constructor requiring a file name and std::ios mode
+	IO_GenEvent( const std::string& filename="IO_GenEvent.dat", 
+		  std::ios::openmode mode=std::ios::out );
+        /// constructor requiring an input stream
+	IO_GenEvent( std::istream & );
+        /// constructor requiring an output stream
+	IO_GenEvent( std::ostream & );
+	virtual       ~IO_GenEvent();
+
+        /// write this event
+	void          write_event( const GenEvent* evt );
+        /// get the next event
+	bool          fill_next_event( GenEvent* evt );
+	void          write_particle_data_table(const ParticleDataTable*);
+	bool          fill_particle_data_table( ParticleDataTable* );
+	/// insert a comment directly into the output file --- normally you
+	///  only want to do this at the beginning or end of the file. All
+	///  comments are preceded with "HepMC::IO_GenEvent-COMMENT\n"
+  	void          write_comment( const std::string comment );
+
+	int           rdstate() const;  //!< check the state of the IO stream
+	void          clear();  //!< clear the IO stream
+
+        /// write to ostr
+	void          print( std::ostream& ostr = std::cout ) const;
+
+	/// needed when reading a file without units if those units are 
+	/// different than the declared default units 
+	/// (e.g., the default units are MeV, but the file was written with GeV)
+	/// This method is not necessary if the units are written in the file
+	void use_input_units( Units::MomentumUnit, Units::LengthUnit );
+
+    protected: // for internal use only
+	/// write vertex information
+	void          write_vertex( GenVertex* );
+	/// write beam particle information
+	void          write_beam_particles( std::pair<HepMC::GenParticle *,HepMC::GenParticle *> );
+	/// write heavy ion information
+	void          write_heavy_ion( HeavyIon const * );
+	/// write PDF information
+	void          write_pdf_info( PdfInfo const * );
+	/// write units
+	void          write_unit_info( const GenEvent* evt );
+	/// write particle information
+	void          write_particle( GenParticle* p );
+	/// write particle data information
+	void          write_particle_data( const ParticleData* d );
+	/// read vertex information
+	GenVertex*    read_vertex( TempParticleMap& particle_to_end_vertex );
+	/// read GenParticle information
+	GenParticle*  read_particle( TempParticleMap& particle_to_end_vertex );
+	/// read particle data table information
+	ParticleData* read_particle_data( ParticleDataTable* );
+	/// read heavy ion information
+	HeavyIon*     read_heavy_ion(  );
+	/// read units
+	void          read_unit_info( GenEvent* evt );
+	/// write end tag
+	bool          write_end_listing();
+
+	void          output( const double& );  //!< write double
+	void          output( const float& );  //!< write float
+	void          output( const int& ); //!< write int
+	void          output( const long& ); //!< write long
+	void          output( const char& );  //!< write a single character
+    private: // use of copy constructor is not allowed
+	IO_GenEvent( const IO_GenEvent& ) : IO_BaseClass() {}
+    private: // data members
+	std::ios::openmode  m_mode;
+	std::fstream        m_file;
+	std::ostream *      m_ostr;
+	std::istream *      m_istr;
+	std::ios *          m_iostr;
+	bool                m_finished_first_event_io;
+	bool                m_have_file;
+	CommonIO            m_common_io;
+	
+    };
+
+    //////////////
+    // Inlines  //
+    //////////////
+
+    inline void IO_GenEvent::output( const double& d ) {
+	if( m_ostr  ) {
+	    if ( d == 0. ) {
+		*m_ostr << ' ' << (int)0;
+	    } else {
+		*m_ostr << ' ' << d;
+	    }
+	}
+    }
+    inline void IO_GenEvent::output( const float& d ) {
+	if( m_ostr  ) {
+	    if ( d == 0. ) {
+		*m_ostr << ' ' << (int)0;
+	    } else {
+		*m_ostr << ' ' << d;
+	    }
+	}
+    }
+    inline void IO_GenEvent::output( const int& i ) { 
+	if( m_ostr  ) {
+	    if ( i == 0. ) {
+		*m_ostr << ' ' << (int)0;
+	    } else {
+        	*m_ostr << ' ' << i; 
+	    }
+	}
+    }
+    inline void IO_GenEvent::output( const long& i ) {
+	if( m_ostr  ) {
+	    if ( i == 0. ) {
+		*m_ostr << ' ' << (int)0;
+	    } else {
+        	*m_ostr << ' ' << i; 
+	    }
+	}
+    }
+    inline void IO_GenEvent::output( const char& c ) {
+	if( m_ostr  ) {
+	    if ( c ) {
+        	*m_ostr << c; 
+	    } else {
+		*m_ostr << ' ' ;
+	    }
+	}
+    }
+    inline int  IO_GenEvent::rdstate() const { 
+        int state;
+	if( m_istr ) {
+	    state =  (int)m_istr->rdstate();
+	} else {
+	    state =  (int)m_ostr->rdstate();
+	}
+        return state; 
+    }
+    inline void IO_GenEvent::clear() { 
+	if( m_istr ) {
+	    m_istr->clear();
+	} else {
+	    m_ostr->clear();
+	}
+    }
+    // these are required by IO_BaseClass, but not used here
+    inline void IO_GenEvent::write_particle_data_table(const ParticleDataTable*) {;}
+    inline bool IO_GenEvent::fill_particle_data_table( ParticleDataTable* ) 
+    { return false;}
+
+} // HepMC
+
+#endif  // HEPMC_IO_GENEVENT_H
+//--------------------------------------------------------------------------
Index: /trunk/Utilities/HepMC/interface/IO_PDG_ParticleDataTable.h
===================================================================
--- /trunk/Utilities/HepMC/interface/IO_PDG_ParticleDataTable.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/IO_PDG_ParticleDataTable.h	(revision 349)
@@ -0,0 +1,104 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_IO_PDG_PARTICLEDATATABLE_H
+#define HEPMC_IO_PDG_PARTICLEDATATABLE_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, November 1999, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// Reads a particle data table from file supplied in PDG format
+// For the most recent table see: http://pdg.lbl.gov/computer_read.html
+//////////////////////////////////////////////////////////////////////////
+//
+// Example of reading from file PDG98_ParticleDataTable.txt
+//
+//	IO_PDG_ParticleDataTable pdg_io("PDG98_ParticleDataTable.txt");
+// 	ParticleDataTable pdt = *pdg_io.read_particle_data_table();
+//      (note the read_particle_data_table method comes from the IO_Baseclass)
+//  or
+//	IO_PDG_ParticleDataTable pdg_io("PDG98_ParticleDataTable.txt");
+// 	ParticleDataTable* pdt;
+//      pdg_io >> pdt;       
+//  in both cases IO_PDG_ParticleDataTable creates an instance of the 
+//  ParticleDataTable which the user becomes owner of (i.e. user is 
+//  responsible for deleting)
+//
+// Note the PDG table does not include antiparticles nor quarks (except top)
+// You can make anti-particle entries corresponding to each charged entry with
+// the method make_antiparticles_from_particles() and you can make default
+// entries for the 6 quarks + anti-quarks with the method add_quarks_to_table()
+// Continuing with the above example:
+//      pdt->make_antiparticles_from_particles();
+//      pdg_io.add_quarks_to_table( *pdt );
+//
+
+#include "IO_BaseClass.h"
+#include <fstream>
+
+namespace HepMC {
+
+    class GenEvent;
+
+    //! an example ParticleDataTable IO method
+    
+    ///
+    /// \class IO_PDG_ParticleDataTable
+    /// Example of reading from file PDG98_ParticleDataTable.txt
+    ///
+    class IO_PDG_ParticleDataTable : public IO_BaseClass {
+    public:
+        /// constructor using filename
+	IO_PDG_ParticleDataTable( const char* filename
+				  ="PDG98_ParticleDataTable.txt" );
+	virtual ~IO_PDG_ParticleDataTable();
+	/// read the input and fill the table
+	bool    fill_particle_data_table( ParticleDataTable* );
+	/// add u, d, s, c, b, and t
+	void    add_quarks_to_table( ParticleDataTable& );
+	/// write to ostr
+	void    print( std::ostream& ostr = std::cout ) const;
+
+        /// check the IO state
+	int     rdstate() const { return (int)m_file.rdstate(); }
+    protected: // for internal use only
+        /// for internal use
+	bool search_for_key_end( std::istream& in, const char* key );
+	/// read a line
+	void read_entry( ParticleDataTable* );
+    private: // following are not implemented
+	void write_event( const GenEvent* ){}
+	bool fill_next_event( GenEvent* ){ return false; }
+	void write_particle_data_table( const ParticleDataTable* ){}
+    private: // use of copy constructor is not allowed
+	IO_PDG_ParticleDataTable( const IO_PDG_ParticleDataTable& ) : 
+	    IO_BaseClass() {}
+    private: // member data
+	std::string   m_filename;
+	std::ifstream m_file;
+    };
+
+    //////////////
+    // Inlines  //
+    //////////////
+
+    inline void IO_PDG_ParticleDataTable::print( std::ostream& ostr ) const { 
+	ostr << "IO_PDG_ParticleDataTable: for computer readable PDG tables.\n"
+             << " file state: " << m_file.rdstate()
+             << " bad:" << (m_file.rdstate()&std::ios::badbit)
+             << " eof:" << (m_file.rdstate()&std::ios::eofbit)
+             << " fail:" << (m_file.rdstate()&std::ios::failbit)
+             << " good:" << (m_file.rdstate()&std::ios::goodbit) << std::endl;
+    }
+
+} // HepMC
+
+#endif  // HEPMC_IO_BASECLASS_H
+//--------------------------------------------------------------------------
+
+
+
+
+
+
+
Index: /trunk/Utilities/HepMC/interface/ParticleData.h
===================================================================
--- /trunk/Utilities/HepMC/interface/ParticleData.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/ParticleData.h	(revision 349)
@@ -0,0 +1,233 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_PARTICLE_DATA_H
+#define HEPMC_PARTICLE_DATA_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// GenParticle Data common to all particles of a given PDG id
+//////////////////////////////////////////////////////////////////////////
+//
+// Units  ID: defined by PDG group (particles are +ve, antiparticles are -ve) 
+//              also consistent with the Pythia definitions
+//              See: http://d0lblt.lbl.gov/wwwpdg/mc_numbers.htm
+//        charge: fraction of proton charge
+//        mass in user defined energy units
+//        width:  ( stored as cLifetime = hbar / Width )
+//        cLifetime: c*time
+//        spin: fraction of photon spin (always a positive number)
+//
+// Default mass is 0.
+// Default cLifetime is -1 which means stable (setting width = 0 gives this)
+//     (we define cLifetime = -1 --> width = 0 (i.e stable), 
+//                    width = -1 --> cLifetime = 0 (i.e. prompt)  )
+// These defaults exist because many very basic MC generators
+//     may produce only massless stable particles in the event record.
+//
+// It is intended that a different ParticleData object is created for each 
+//     particle and its anti-particle - useful for CP violation studies.
+//
+// There are few set methods for this class, there should be no reason
+//     to change anything after instantiating. If you need to, then
+//     create a new object and kill the old one.
+//
+// Example: 
+//  HepMC::ParticleData* pd_electron = 
+//                    new HepMC::ParticleData("electron",11,-1,0.000511,-1,.5);
+// A method is provided to allow you to set the lifetime from the
+//     width in the constructor
+// Example: new HepMC::ParticleData("W+",24,+1,80.396,
+//                                  HepMC::clifetime_from_width(2.06),1);
+// Example of finding a ParticleData object from its PDG ID 
+// in ParticleDataTable pdt:
+//        HepMC::ParticleData* electron = pdt.find(11);
+// or if you just wanted two know the electron mass, you could do:
+//        pdt.find(11)->mass();
+
+#include <iostream>
+#include <string>
+#include <stdlib.h>	// for integer abs()
+
+namespace HepMC {
+
+    /// hbar * c --> calculated with units of [mm*GeV]
+    static const double HepMC_hbarc   = (6.6260755e-34 * (1.e-6/1.60217733e-19) / (2*3.14159265358979323846))
+                                        * (2.99792458e+8 * 1000.) * 1.e+3;
+
+    // if you want to instantiate the particle lifetime from its width,
+    // use this static method inside the constructor:
+    double clifetime_from_width( double width );  //!< set lifetime from width
+
+    //! an example ParticleData class
+    
+    ///
+    /// \class ParticleData
+    /// Particle Data common to all particles of a given PDG id
+    ///
+    class ParticleData {
+  
+	friend std::ostream&  operator<<( std::ostream&, const ParticleData& );
+
+    public:
+        /// constructor requiring name, ID, and charge
+	ParticleData( std::string name, int id, double charge, double mass = 0,
+		      double cLifetime = -1, double spin = 0 );
+        /// constructor requiring name, ID, and charge
+	ParticleData( const char* name, int id, double charge, double mass = 0,
+		      double cLifetime = -1, double spin = 0 );
+	virtual ~ParticleData();
+
+	bool    operator==( const ParticleData& ) const; //!< equality
+	bool    operator!=( const ParticleData& ) const; //!< inequality
+
+        /// write particle data information to ostr
+	void    print( std::ostream& ostr = std::cout ) const;
+
+	bool    is_lepton() const;        //!< true if charged lepton /neutrino
+	bool    is_charged_lepton() const;//!< true if a charged lepton
+	bool    is_em() const;            //!< true if an electron or photon
+	bool    is_neutrino() const;      //!< true if a neutrino
+	bool    is_hadron() const;        //!< true if a hadron
+	bool    is_boson() const;         //!< true if a gauge or higgs boson
+
+	////////////////////
+	// access methods //
+	////////////////////
+	
+	/// description of the particle according to PDG, i.e. "Delta(1900) S_31"
+	std::string  name() const;
+	/// PDG ID number
+	int          pdg_id() const;
+	/// charge
+	double       charge() const;
+	/// nominal mass
+	double       mass() const;
+	/// width as calculated from clifetime
+	double       width() const; 
+	/// lifetime in mm
+	double       clifetime() const;
+	/// J spin
+	double       spin() const;
+
+	void         set_charge( double ); //!< set charge
+	void         set_mass( double ); //!< set nominal mass
+	void         set_width( double ); //!< set width
+	void         set_clifetime( double ); //!< set lifetime in mm
+	void         set_spin( double ); //!< set J spin
+
+    protected:
+	static unsigned int counter(); //!< num ParticleData objects in memory
+    
+	/// omits susy/excited/technicolor digit from returned ID
+	int    model_independent_pdg_id_() const;
+
+    private:
+	std::string   m_name;   // description of the particle according to PDG
+                                // i.e. "Delta(1900) S_31"
+	int           m_pdg_id; // PDG ID number (note we allow -ve)
+	int           m_3charge;// 3*electric charge in units of proton charge
+	double        m_mass;   // nominal mass in user defined energy units
+	double        m_clifetime; // [mm]
+	unsigned char m_2spin;  // 2*spin (J) of particle
+
+	static unsigned int s_counter;
+    };
+
+    ///////////////////////////
+    // INLINES               //
+    ///////////////////////////
+
+    inline bool ParticleData::is_lepton() const {
+	/// true if a charged lepton or neutrino --> | 11,13,15,12,14,16,17,18 |
+	return ( abs(pdg_id()) >=11 &&  abs(pdg_id()) <= 18 );
+    }
+    inline bool ParticleData::is_charged_lepton() const {
+	/// true if a charged lepton --> | 11,13,15 |
+	return ( is_lepton() && abs(pdg_id())%2==1 );
+    }
+    inline bool ParticleData::is_neutrino() const {
+	/// true if a neutrino --> | 12,14,16 |
+	return ( is_lepton() && abs(pdg_id())%2==0 );
+    }
+    inline bool ParticleData::is_em() const {
+	/// true if an electron or photon --> | 11, 22 |
+	return ( abs(pdg_id()) == 11 || abs(pdg_id()) == 22 );
+    }
+    inline bool ParticleData::is_hadron() const {
+	/// true if a hadron --> q,g,meson,baryon
+	return ( abs(pdg_id()) <= 9 || abs(pdg_id()) == 21 
+		 || abs(pdg_id()) >100 );
+    }
+    inline bool ParticleData::is_boson() const {
+	/// true if a gauge or higgs boson --> | 9, 21-39 | 
+	return ( ( abs(pdg_id()) >20 && abs(pdg_id()) <=40 )
+		 || abs(pdg_id()) == 9 );
+    }
+
+    ///////////////////////////
+    // INLINE Access Methods //
+    ///////////////////////////
+
+    inline std::string ParticleData::name() const { return m_name; }
+    inline int         ParticleData::pdg_id() const { return m_pdg_id; }
+    inline double      ParticleData::charge() const { 
+	return ( (double)m_3charge )/3.; 
+    }
+    inline double      ParticleData::mass() const { return m_mass; }
+    inline double      ParticleData::clifetime() const { return m_clifetime; }
+    inline double      ParticleData::spin() const { return m_2spin/2.; }
+    inline void        ParticleData::set_charge( double charge ) {
+	if ( charge > 0 ) { 
+	    m_3charge = (int)(3.*charge+.1); 
+	} else if ( charge < 0. ) { 
+	    m_3charge = (int)(3.*charge-.1); 
+	} else { 
+	    m_3charge = 0; 
+	}
+    }
+    inline void        ParticleData::set_mass( double its_mass ) {
+	m_mass = its_mass;
+    }
+    inline void        ParticleData::set_width( double width ) {
+	if ( width > 0 ) { 
+	    m_clifetime = HepMC_hbarc/width;
+	} else if ( width == 0. ) { 
+	    m_clifetime = -1.;
+	} else { 
+	    m_clifetime = 0.; 
+	}
+    }
+    inline void        ParticleData::set_clifetime( double its_clifetime ) {
+	m_clifetime = its_clifetime; 
+    }
+    inline void        ParticleData::set_spin( double spin ) {
+	m_2spin = (unsigned char)(2.*spin+.1);
+    }
+
+    ///////////////////////////
+    // INLINE Operators      //
+    ///////////////////////////
+
+    inline bool ParticleData::operator==( const ParticleData& a ) const {
+	// compares everything except the particle's name
+	return ( a.m_pdg_id != m_pdg_id ||
+		 a.m_mass != m_mass ||
+		 a.m_clifetime != m_clifetime ||
+		 a.m_3charge != m_3charge ||
+		 a.m_2spin != m_2spin            ) ? 0 : 1;
+    }
+
+    inline bool ParticleData::operator!=( const ParticleData& a ) const {
+	// compares everything except the particle's name
+	return ( a.pdg_id() != this->pdg_id() );
+    }
+
+} // HepMC
+
+#endif  // HEPMC_PARTICLE_DATA_H
+//--------------------------------------------------------------------------
+
+
+
Index: /trunk/Utilities/HepMC/interface/ParticleDataTable.h
===================================================================
--- /trunk/Utilities/HepMC/interface/ParticleDataTable.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/ParticleDataTable.h	(revision 349)
@@ -0,0 +1,270 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_PARTICLE_DATA_TABLE_H
+#define HEPMC_PARTICLE_DATA_TABLE_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, Jan 2000, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// Container for GenParticle Data Instances --- basically just an interface
+//   to STL map -- the same naming conventions are used
+// A GenParticle may belong to any number of ParticleDataTables. 
+// The ParticleDataTable does not own the ParticleData objects and will NOT
+//   delete them unless explicity told to do so with the delete_all method.
+// Each ParticleData entry in the table MUST have a unique pdg_id (otherwise
+//   an attempt to insert it as a new entry will fail).
+// Updated 2000.02.08 M.Dobbs added merge_table and 
+//                            make_antiparticles_from_particles
+//////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+#include <map>
+#include <cstdio>       // needed for formatted output using sprintf 
+#include "ParticleData.h"
+
+namespace HepMC {
+
+    //! an example ParticleDataTable class
+    
+    ///
+    /// \class ParticleDataTable
+    /// Example container for ParticleData instances. 
+    /// Basically just an interface to STL map.
+    ///
+    class ParticleDataTable {
+  
+    public:
+        /// constructor with optional description
+	ParticleDataTable( std::string description = std::string() );
+        /// constructor with description
+	ParticleDataTable( const char description );
+	/// copy constructor
+	ParticleDataTable( const ParticleDataTable& );
+        /// Shallow: does not delete ParticleData entries
+	virtual ~ParticleDataTable(); 
+	/// shallow: does not copy the entries, only makes new pointers 
+	ParticleDataTable& operator=( const ParticleDataTable& );
+
+        /// make corresponding anti-particles for all particles in table
+	void    make_antiparticles_from_particles();
+	/// merge two tables
+	int     merge_table( const ParticleDataTable& );
+
+        /// write the table to ostr
+	void    print( std::ostream& ostr = std::cout ) const;
+
+	void    delete_all(); //!<delete all ParticleData instances in this table
+	void    clear();      //!<clears table without deleting
+
+        /// return pointer to requested ParticleData
+	ParticleData*       operator[]( int id ) const;
+        /// return pointer to requested ParticleData
+	ParticleData*       find( int id ) const;
+	/// size of table
+	int                 size() const;
+	/// true if the table is empty
+	bool                empty() const;
+	/// true if successful
+	bool                insert( ParticleData* ); 
+	/// removes from table - does not delete
+	bool                erase( ParticleData* );  
+	/// removes from table - does not delete
+	bool                erase( int id );       
+	/// iterator for ParticleData map
+	typedef std::map<int,HepMC::ParticleData*>::iterator iterator;
+	/// const iterator for ParticleData map
+	typedef std::map<int,HepMC::ParticleData*>::const_iterator const_iterator;
+	/// begin iteration
+	iterator            begin();
+	/// end iteration
+	iterator            end();
+	/// begin const iteration
+	const_iterator      begin() const;
+	/// end const iteration
+	const_iterator      end() const;
+	
+	////////////////////
+	// access methods //
+	////////////////////
+	
+	/// table description
+	std::string description() const;
+	/// set table description
+	void        set_description( std::string );
+	/// set table description
+	void        set_description( const char );
+
+    private:
+	std::string                        m_description;
+	std::map<int,HepMC::ParticleData*> m_data_table;
+    };
+
+    ///////////////////////////
+    // INLINES               //
+    ///////////////////////////
+
+    inline ParticleDataTable::ParticleDataTable( std::string description ) 
+	: m_description(description) {
+	std::cout << "-------------------------------------------------------" << std::endl;
+	std::cout << "Use of HepMC/ParticleDataTable is deprecated" << std::endl;
+	std::cout << "-------------------------------------------------------" << std::endl;
+    }
+
+    inline ParticleDataTable::ParticleDataTable( const char description ) {
+	m_description = description; 
+
+        std::cout << "-------------------------------------------------------" << std::endl;
+        std::cout << "Use of HepMC/ParticleDataTable is deprecated" << std::endl;
+        std::cout << "-------------------------------------------------------" << std::endl;
+    }
+
+    inline ParticleDataTable::ParticleDataTable( const ParticleDataTable& pdt){
+	*this = pdt;
+    }
+
+    inline ParticleDataTable::~ParticleDataTable(){}
+
+    inline ParticleDataTable& ParticleDataTable::operator=( const 
+							    ParticleDataTable& 
+							    pdt) {
+	m_description = pdt.m_description;
+	m_data_table = pdt.m_data_table;
+	return *this;
+    }
+
+    inline void ParticleDataTable::make_antiparticles_from_particles() {
+        /// make corresponding anti-particles for all particles in table
+	ParticleDataTable new_data;
+	for ( ParticleDataTable::iterator p = begin(); p != end(); ++p ) {
+	    ParticleData* pdata = p->second;
+	    if ( pdata->charge() ) {
+		new_data.insert( new ParticleData( pdata->name()+"~",
+						   -1*pdata->pdg_id(),
+						   -1.*pdata->charge(), 
+						   pdata->mass(),
+						   pdata->clifetime(), 
+						   pdata->spin() ));
+	    }
+	}
+	merge_table( new_data );
+    }
+
+    inline void ParticleDataTable::print( std::ostream& ostr ) const {
+        /// prints a summary of all particle Data currently in memory
+        //
+        ostr << "________________________________________"
+             << "________________________________________\n";
+	ostr << "ParticleData:   *****  ParticleDataTable"
+             << "  *****   ( " << size() 
+             << " entries )\n";
+	ostr << " Description: " << m_description << "\n";
+        ostr << "   PDG ID " << "       PARTICLE NAME "
+             << "CHARGE" <<    "     MASS     "
+             << "  C*LIFETIME (CM) " << " SPIN\n";
+        for ( std::map< int,ParticleData* >::const_iterator pd 
+                  = m_data_table.begin(); pd != m_data_table.end(); pd++ ) {
+            ostr << *(pd->second) << "\n";
+        }
+        ostr << "________________________________________"
+             << "________________________________________" << std::endl;
+    }      
+
+    inline ParticleData* ParticleDataTable::find( int id ) const {
+	/// finds a ParticleData pointer corresponding to id IF it exists in
+	///  the table. If not returns NULL
+	std::map<int,ParticleData*>::const_iterator iter 
+	    = m_data_table.find(id);
+	return ( iter == m_data_table.end() ) ? 0 : iter->second;
+    }
+
+    inline ParticleData* ParticleDataTable::operator[]( int id ) const {
+	return find(id);
+    }
+
+    inline int ParticleDataTable::size() const { 
+	return (int)m_data_table.size();
+    }
+
+    inline bool ParticleDataTable::empty() const {
+	return (bool)m_data_table.empty();
+    }
+
+    inline bool ParticleDataTable::insert( ParticleData* pdata ) {
+	/// inserts pdata in the table IFF pdata's id has not already been used.
+	/// It does NOT replace entries with the same id. True if successful.
+	/// If you wish to overwrite another entry, first use erase()
+	if ( m_data_table.count(pdata->pdg_id()) ) return 0;
+	return ( m_data_table[pdata->pdg_id()] = pdata ); // true is success
+    }
+
+    inline bool ParticleDataTable::erase( ParticleData* pdata ) {
+	/// removes from table does not delete
+	/// returns True is an entry pdata existed in the table and was erased
+	return (bool)m_data_table.erase( pdata->pdg_id() );
+    }
+
+
+    inline bool ParticleDataTable::erase( int id ) {
+	/// removes from table does not delete
+	/// returns True is an entry pdata existed in the table and was erased
+	return (bool)m_data_table.erase( id );
+    }
+
+    inline ParticleDataTable::iterator ParticleDataTable::begin() { 
+	return m_data_table.begin(); 
+    }
+
+    inline ParticleDataTable::iterator ParticleDataTable::end() { 
+	return m_data_table.end(); 
+    }
+
+    inline ParticleDataTable::const_iterator ParticleDataTable::begin() const {
+	return m_data_table.begin(); 
+    }
+
+    inline ParticleDataTable::const_iterator ParticleDataTable::end() const { 
+	return m_data_table.end(); 
+    }
+
+    inline std::string ParticleDataTable::description() const { 
+	return m_description; 
+    }
+
+    inline void ParticleDataTable::set_description( std::string description ) {
+	m_description = description;
+    }
+
+    inline void ParticleDataTable::set_description( const char description ) {
+	m_description = description;
+    }
+
+    inline void ParticleDataTable::delete_all() {
+        /// deletes all ParticleData instances in this table
+        for ( std::map<int,ParticleData*>::iterator pd = m_data_table.begin();
+              pd != m_data_table.end(); pd++) delete pd->second;
+	clear();
+    }
+
+    inline void ParticleDataTable::clear() { m_data_table.clear(); }
+
+    inline int ParticleDataTable::merge_table( const ParticleDataTable& pdt ) {
+	/// merges pdt into this table
+	/// each entry from pdt is inserted only if this table does not
+	///  already have an entry matching the ParticleData's id
+	/// returns the number of new entries inserted into this table.
+	int count_number_insertions =0;
+	for ( ParticleDataTable::const_iterator p = pdt.begin(); 
+	      p != pdt.end(); ++p ) {
+	    if ( insert(p->second) ) ++count_number_insertions;
+	}
+	return count_number_insertions;
+    }
+
+} // HepMC
+
+#endif  // HEPMC_PARTICLE_DATA_TABLE_H
+//--------------------------------------------------------------------------
+
+
+
Index: /trunk/Utilities/HepMC/interface/PdfInfo.h
===================================================================
--- /trunk/Utilities/HepMC/interface/PdfInfo.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/PdfInfo.h	(revision 349)
@@ -0,0 +1,195 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_PDF_INFO_H
+#define HEPMC_PDF_INFO_H
+
+//////////////////////////////////////////////////////////////////////////
+// garren@fnal.gov, July 2006
+//
+// Additional PDF information
+//////////////////////////////////////////////////////////////////////////
+
+namespace HepMC {
+
+//! The PdfInfo class stores PDF information
+
+///
+/// \class  PdfInfo
+/// HepMC::PdfInfo stores additional PDF information for a GenEvent.
+/// Creation and use of this information is optional. 
+///
+///   - int id1; 	// flavour code of first parton
+///   - int id2; 	// flavour code of second parton 
+///   - int pdf_id1; 	// LHAPDF set id of first parton (zero by default)
+///   - int pdf_id2; 	// LHAPDF set id of second parton  (zero by default)
+///   - double x1;  	// fraction of beam momentum carried by first parton ("beam side") 
+///   - double x2;  	// fraction of beam momentum carried by second parton ("target side") 
+///   - double scalePDF;  //  Q-scale used in evaluation of PDF's   (in GeV) 
+///   - double pdf1;  	// PDF (id1, x1, Q) 
+///   - double pdf2;  	// PDF (id2, x2, Q)   
+/// 
+/// Input parton flavour codes id1 & id2 are expected to obey the 
+/// PDG code conventions, especially g = 21.
+/// 
+/// The contents of pdf1 and pdf2 are expected to be x*f(x).
+/// The LHAPDF set ids are the entries in the first column of
+/// http:///projects.hepforge.org/lhapdf/PDFsets.index
+///
+class PdfInfo {
+
+public:
+  // ---  birth/death:
+  //
+  /// default constructor
+  PdfInfo()
+    : m_id1(0), 
+      m_id2(0),
+      m_pdf_id1(0),
+      m_pdf_id2(0),
+      m_x1(0),
+      m_x2(0),
+      m_scalePDF(0),
+      m_pdf1(0),
+      m_pdf2(0)
+    {}
+
+  /// all values EXCEPT pdf_id1 and pdf_id2 must be provided
+  PdfInfo( int i1, int i2, double x1, double x2,
+           double q, double p1, double p2,
+	   int pdf_id1 = 0, int pdf_id2 = 0 );
+
+  ~PdfInfo() {}
+    
+  // ---  copying:
+  //
+  PdfInfo( PdfInfo const & orig );	//!< copy constructor
+  PdfInfo &  operator = ( PdfInfo const & rhs ); //!< make a copy
+  void swap( PdfInfo & other );	//!< swap two PdfInfo objects
+
+  // ---  equivalence:
+  //
+  bool    operator==( const PdfInfo& ) const; //!< check for equality
+  bool    operator!=( const PdfInfo& ) const; //!< check for inequality
+
+  // ---  accessors:
+    /// flavour code of first parton
+    int   id1()                   const { return m_id1; }
+    /// flavour code of second parton 
+    int   id2()                   const { return m_id2; }
+    /// LHAPDF set id of first parton
+    int   pdf_id1()                   const { return m_pdf_id1; }
+    /// LHAPDF set id of second parton
+    int   pdf_id2()                   const { return m_pdf_id2; }
+    /// fraction of beam momentum carried by first parton ("beam side") 
+    double x1()                   const { return m_x1; } 
+    /// fraction of beam momentum carried by second parton ("target side") 
+    double x2()                   const { return m_x2; }
+    ///  Q-scale used in evaluation of PDF's   (in GeV) 
+    double scalePDF()             const { return m_scalePDF;  }
+    /// PDF (id1, x1, Q) - x*f(x)
+    double pdf1()                 const { return m_pdf1; }
+    /// PDF (id2, x2, Q) - x*f(x)
+    double pdf2()                 const { return m_pdf2; }
+
+  // ---  mutators:
+    /// set flavour code of first parton
+    void   set_id1(const int &i)              { m_id1=i; }
+    /// set flavour code of second parton 
+    void   set_id2(const int &i)              { m_id2=i; }
+    /// set LHAPDF set id of first parton
+    void   set_pdf_id1(const int &i)              { m_pdf_id1=i; }
+    /// set LHAPDF set id of second parton 
+    void   set_pdf_id2(const int &i)              { m_pdf_id2=i; }
+    /// set fraction of beam momentum carried by first parton ("beam side") 
+    void   set_x1(const double &f)            { m_x1=f; }
+    /// set fraction of beam momentum carried by second parton ("target side") 
+    void   set_x2(const double &f)            { m_x2=f; }
+    /// set Q-scale used in evaluation of PDF's   (in GeV) 
+    void   set_scalePDF(const double &f)      { m_scalePDF=f;  }
+    /// set x*f(x) of first parton
+    void   set_pdf1(const double &f)          { m_pdf1=f; }
+    /// set x*f(x) of second parton
+    void   set_pdf2(const double &f)          { m_pdf2=f; }
+
+private: // data members
+    int   m_id1; 
+    int   m_id2; 
+    int   m_pdf_id1; 
+    int   m_pdf_id2; 
+    double m_x1;
+    double m_x2;
+    double m_scalePDF; 
+    double m_pdf1;
+    double m_pdf2;
+
+};
+
+// inline operators
+inline PdfInfo::PdfInfo( int i1, int i2, double x1, double x2,
+        		 double q, double p1, double p2,
+			 int pdf_id1, int pdf_id2 )
+    : m_id1(i1), 
+      m_id2(i2),
+      m_pdf_id1(pdf_id1),
+      m_pdf_id2(pdf_id2),
+      m_x1(x1),
+      m_x2(x2),
+      m_scalePDF(q),
+      m_pdf1(p1),
+      m_pdf2(p2)
+   {}
+
+inline PdfInfo::PdfInfo( PdfInfo const & orig )
+    : m_id1(orig.m_id1), 
+      m_id2(orig.m_id2),
+      m_pdf_id1(orig.m_pdf_id1), 
+      m_pdf_id2(orig.m_pdf_id2),
+      m_x1(orig.m_x1),
+      m_x2(orig.m_x2),
+      m_scalePDF(orig.m_scalePDF),
+      m_pdf1(orig.m_pdf1),
+      m_pdf2(orig.m_pdf2)
+   {}
+
+inline PdfInfo &  PdfInfo::operator = ( PdfInfo const & rhs ) 
+{
+  PdfInfo temp( rhs );
+  swap( temp );
+  return *this;
+}
+
+inline void PdfInfo::swap( PdfInfo & other ) 
+{
+  std::swap(m_id1, other.m_id1); 
+  std::swap(m_id2, other.m_id2);
+  std::swap(m_pdf_id1, other.m_pdf_id1); 
+  std::swap(m_pdf_id2, other.m_pdf_id2);
+  std::swap(m_x1, other.m_x1);
+  std::swap(m_x2, other.m_x2);
+  std::swap(m_scalePDF, other.m_scalePDF);
+  std::swap(m_pdf1, other.m_pdf1);
+  std::swap(m_pdf2, other.m_pdf2);
+}
+
+inline bool    PdfInfo::operator==( const PdfInfo& a ) const
+{
+    /// equality requires that each member match
+    return (    a.id1() == this->id1() 
+             && a.id2() == this->id2() 
+             && a.pdf_id1() == this->pdf_id1() 
+             && a.pdf_id2() == this->pdf_id2() 
+	     && a.x1() == this->x1() 
+	     && a.x2() == this->x2()
+	     && a.scalePDF() == this->scalePDF() 
+	     && a.pdf1() == this->pdf1()
+	     && a.pdf2() == this->pdf2() );
+}
+
+inline bool    PdfInfo::operator!=( const PdfInfo& a ) const
+{
+    /// any nonmatching member generates inequality
+    return !( a == *this );
+}
+
+} // HepMC
+
+#endif  // HEPMC_PDF_INFO_H
Index: /trunk/Utilities/HepMC/interface/Polarization.h
===================================================================
--- /trunk/Utilities/HepMC/interface/Polarization.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/Polarization.h	(revision 349)
@@ -0,0 +1,106 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_POLARIZATION_H
+#define HEPMC_POLARIZATION_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// Polarization object for a particle. All angles are in radians.
+//////////////////////////////////////////////////////////////////////////
+
+#include "SimpleVector.h"
+#include <iostream>
+#include <cmath>
+
+namespace HepMC {
+
+    static const double HepMC_pi = 3.14159265358979323846;  // copy of pi from CLHEP
+    
+    //! The Polarization class stores theta and phi for a GenParticle
+
+    ///
+    /// \class  Polarization
+    /// HepMC::Polarization stores a particle's theta and phi in radians.
+    /// Use of this information is optional. 
+    /// By default, the polarization is set to zero.
+    ///
+    class Polarization {
+
+        /// print polarization information
+	friend std::ostream& operator<<( std::ostream&, const Polarization& );
+
+    public:
+        /// default constructor
+	Polarization( double theta = 0, double phi = 0 );
+	/// construct from another polarization object
+	Polarization( const Polarization& inpolar );
+	/// construct using the polar and azimuthal angles from a ThreeVector
+	Polarization( const ThreeVector& vec3in );
+	virtual       ~Polarization() {}
+
+        /// swap
+        void swap( Polarization & other);
+	/// make a copy
+	Polarization& operator=( const Polarization& inpolar );
+	/// equality requires that theta and phi are equal
+	bool          operator==( const Polarization& ) const;
+	/// inequality results if either theta or phi differ
+	bool          operator!=( const Polarization& ) const;
+
+        /// print theta and phi
+	void          print( std::ostream& ostr = std::cout ) const;
+    
+	////////////////////
+	// access methods //
+	////////////////////
+	double        theta() const;    //!< returns polar angle in radians
+	double        phi() const;      //!< returns azimuthal angle in radians
+	ThreeVector   normal3d() const; //!< unit 3 vector for easy manipulation
+
+        /// set polar angle in radians 
+	double        set_theta( double theta );
+        /// set azimuthal angle in radians 
+	double        set_phi( double phi );
+	/// set both polar and azimuthal angles in radians
+	void          set_theta_phi( double theta, double phi );
+	/// sets polarization according to direction of 3 vec
+	ThreeVector   set_normal3d( const ThreeVector& vec3in ); 
+
+    private:
+    	/// private method to return a polar angle in the correct range
+	double valid_theta( double theta );
+    	/// private method to return an azimuthal angle in the correct range
+	double valid_phi( double phi );
+
+    private:
+	double m_theta; //polar angle of polarization in radians 0< theta <pi
+	double m_phi;   //azimuthal angle of polarization in rad. 0< phi <2pi
+    };
+
+    ///////////////////////////
+    // INLINE Access Methods //
+    ///////////////////////////
+
+    inline double Polarization::theta() const { return m_theta; }
+    inline double Polarization::phi() const { return m_phi; }
+
+    ///////////////////////////
+    // INLINE Operators      //
+    ///////////////////////////
+
+    inline bool Polarization::operator==( const Polarization& a ) const 
+    {
+	return ( a.theta() == this->theta() && a.phi() == this->phi() );
+    }
+
+    inline bool Polarization::operator!=(const Polarization& a ) const 
+    {
+	return !( a == *this );
+    }
+
+} // HepMC
+
+#endif  // HEPMC_POLARIZATION_H
+//--------------------------------------------------------------------------
Index: /trunk/Utilities/HepMC/interface/SearchVector.h
===================================================================
--- /trunk/Utilities/HepMC/interface/SearchVector.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/SearchVector.h	(revision 349)
@@ -0,0 +1,25 @@
+#ifndef SearchVector_h
+#define SearchVector_h
+// ----------------------------------------------------------------------
+//
+// SearchVector.h
+// Author: Lynn Garren
+//
+// Utilities to search std::vector<GenParticle*> a GenParticle instance
+// ----------------------------------------------------------------------
+
+#include "GenVertex.h"
+#include "GenParticle.h"
+
+namespace HepMC {
+  
+/// returns true if it cannot find GenParticle* in the vector
+bool not_in_vector( std::vector<HepMC::GenParticle*>*, GenParticle* );
+
+/// Returns the index of a GenParticle* within a vector.
+/// Returns -1 if GenParticle* is not in the vector.
+std::vector<HepMC::GenParticle*>::iterator already_in_vector( std::vector<HepMC::GenParticle*>*, GenParticle* );
+
+}	// HepMC
+
+#endif // SearchVector_h
Index: /trunk/Utilities/HepMC/interface/SimpleVector.h
===================================================================
--- /trunk/Utilities/HepMC/interface/SimpleVector.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/SimpleVector.h	(revision 349)
@@ -0,0 +1,196 @@
+//////////////////////////////////////////////////////////////////////////
+// SimpleVector.h
+//////////////////////////////////////////////////////////////////////////
+#ifndef  HEPMC_SIMPLEVECTOR_H
+#define  HEPMC_SIMPLEVECTOR_H
+
+//////////////////////////////////////////////////////////////////////////
+// garren@fnal.gov, July 2006
+//
+// This header provides a place to hold the doubles which are part of one of 
+// three types of physics vectors:
+//    momentum 4 vector 
+//    position or displacement 4 vector
+//    position or displacement 3 vector
+//
+// For compatibility with existing code, 
+// the basic expected geometrical access methods are povided 
+// Also, both FourVector and ThreeVector have a templated constructor that will 
+// take another vector (HepLorentzVector, GenVector, ...)
+//    --> this vector must have the following methods: x(), y(), z()
+//    -->  FourVector also requires the t() method
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+#include "enable_if.h"
+#include "is_arithmetic.h"
+
+
+namespace HepMC {
+
+//! FourVector is a simple representation of a physics 4 vector
+
+///
+/// \class  FourVector
+/// For compatibility with existing code, 
+/// the basic expected geometrical access methods are povided.
+/// Also, there is a templated constructor that will 
+/// take another vector (HepLorentzVector, GenVector, ...)
+/// which must have the following methods: x(), y(), z(), t().
+///
+class FourVector {
+
+public:
+
+  /// constructor requiring at least x, y, and z
+  FourVector( double xin, double yin, double zin, double tin=0) 
+  : m_x(xin), m_y(yin), m_z(zin), m_t(tin) {}
+
+  /// constructor requiring only t 
+  FourVector(double t)
+  : m_x(0), m_y(0), m_z(0), m_t(t) {}
+
+  FourVector() 
+  : m_x(0), m_y(0), m_z(0), m_t(0) {}
+
+  /// templated constructor
+  /// this is used ONLY if T is not arithmetic
+  template <class T >
+  FourVector( const T& v,
+         typename detail::disable_if< detail::is_arithmetic<T>::value, void >::type * = 0 )
+  : m_x(v.x()), m_y(v.y()), m_z(v.z()), m_t(v.t()) {}
+
+  /// copy constructor
+  FourVector(const FourVector & v)
+  : m_x(v.x()), m_y(v.y()), m_z(v.z()), m_t(v.t()) {}
+
+  void swap( FourVector & other );  //!< swap
+
+  double px() const { return m_x; }  //!< return px
+  double py() const { return m_y; }  //!< return py
+  double pz() const { return m_z; }  //!< return pz
+  double e()  const { return m_t; }  //!< return E
+
+  double x() const { return m_x; }  //!< return x
+  double y() const { return m_y; }  //!< return y
+  double z() const { return m_z; }  //!< return z
+  double t() const { return m_t; }  //!< return t
+
+  double m2() const;  //!< Invariant mass squared.
+  double m() const;   //!< Invariant mass. If m2() is negative then -sqrt(-m2()) is returned.
+
+  double perp2() const;  //!< Transverse component of the spatial vector squared.
+  double perp() const;   //!< Transverse component of the spatial vector (R in cylindrical system).
+  double mag() const;    //!< Magnitude of the spatial vector
+
+  // Get spatial vector components in spherical coordinate system.
+  double theta() const;  //!< The polar angle.
+  double phi() const;  //!< The azimuth angle.
+  double rho() const;  //!< spatial vector component magnitude
+
+  FourVector & operator = (const FourVector &); //!< make a copy
+
+  bool operator == (const FourVector &) const; //!< equality
+  bool operator != (const FourVector &) const; //!< inequality
+
+  double pseudoRapidity() const;  //!< Returns the pseudo-rapidity, i.e. -ln(tan(theta/2))
+  double eta() const;             //!< Pseudorapidity (of the space part)
+
+  /// set x, y, z, and t
+  void set        (double x, double y, double z, double  t);
+
+  void setX(double x) { m_x=x; }  //!< set x
+  void setY(double y) { m_y=y; }  //!< set y
+  void setZ(double z) { m_z=z; }  //!< set z
+  void setT(double t) { m_t=t; }  //!< set t
+
+  void setPx(double x) { m_x=x; }  //!< set px
+  void setPy(double y) { m_y=y; }  //!< set py
+  void setPz(double z) { m_z=z; }  //!< set pz
+  void setE(double t)  { m_t=t; }  //!< set E
+
+private:
+
+  double m_x;
+  double m_y;
+  double m_z;
+  double m_t;
+  
+};
+
+//! ThreeVector is a simple representation of a position or displacement 3 vector
+
+///
+/// \class  ThreeVector
+/// For compatibility with existing code, 
+/// the basic expected geometrical access methods are povided.
+/// Also, there is a templated constructor that will 
+/// take another vector (HepLorentzVector, GenVector, ...)
+/// which must have the following methods: x(), y(), z().
+///
+class ThreeVector {
+
+public:
+
+  /// construct using x, y, and z (only x is required)
+  ThreeVector( double xin, double yin =0, double zin =0 ) 
+  : m_x(xin), m_y(yin), m_z(zin) {}
+
+  ThreeVector( ) 
+  : m_x(0), m_y(0), m_z(0) {}
+  
+  /// templated constructor
+  /// this is used ONLY if T is not arithmetic
+  template <class T >
+  ThreeVector( const T& v,
+         typename detail::disable_if< detail::is_arithmetic<T>::value, void >::type * = 0 )
+  : m_x(v.x()), m_y(v.y()), m_z(v.z()) {}
+
+  /// copy constructor
+  ThreeVector(const ThreeVector & v)
+  : m_x(v.x()), m_y(v.y()), m_z(v.z()) {}
+
+  void swap( ThreeVector & other );  //!< swap
+
+  double x() const { return m_x; }  //!< return x
+  double y() const { return m_y; }  //!< return y
+  double z() const { return m_z; }  //!< return z
+
+  void setX(double x) { m_x=x; }  //!< set x
+  void setY(double y) { m_y=y; }  //!< set y
+  void setZ(double z) { m_z=z; }  //!< set z
+  void set( double x, double y, double z);   //!< set x, y, and z
+
+  double phi()   const;  //!< The azimuth angle.
+  double theta() const;  //!< The polar angle.
+  double r()     const;  //!< The magnitude
+
+  double mag() const;  //!< The magnitude (r in spherical coordinate system).
+
+  void setPhi(double);  //!< Set phi keeping mag and theta constant (BaBar).
+  void setTheta(double);  //!< Set theta keeping mag and phi constant (BaBar).
+
+  double perp2() const;  //!< The transverse component squared (rho^2 in cylindrical coordinate system).
+  double perp() const;  //!< The transverse component (rho in cylindrical coordinate system).
+
+  ThreeVector & operator = (const ThreeVector &); //!< make a copy
+
+  bool operator == (const ThreeVector &) const; //!< equality
+  bool operator != (const ThreeVector &) const; //!< inequality
+
+private:
+
+  double m_x;
+  double m_y;
+  double m_z;
+
+};  
+
+
+} // HepMC
+
+#include "SimpleVector.icc"
+
+#endif  // HEPMC_SIMPLEVECTOR_H
+
Index: /trunk/Utilities/HepMC/interface/SimpleVector.icc
===================================================================
--- /trunk/Utilities/HepMC/interface/SimpleVector.icc	(revision 349)
+++ /trunk/Utilities/HepMC/interface/SimpleVector.icc	(revision 349)
@@ -0,0 +1,154 @@
+//////////////////////////////////////////////////////////////////////////
+// SimpleVector.icc
+//////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////
+// garren@fnal.gov, July 2006
+//
+//
+//////////////////////////////////////////////////////////////////////////
+
+#include <cmath>
+#include <algorithm>	// for swap
+
+namespace HepMC {
+
+//////////////////////////////////////////////////////////////////////////
+//  FourVector inline methods
+//////////////////////////////////////////////////////////////////////////
+
+inline void FourVector::swap( FourVector & other ) {
+    std::swap( m_x, other.m_x );
+    std::swap( m_y, other.m_y );
+    std::swap( m_z, other.m_z );
+    std::swap( m_t, other.m_t );
+}
+
+inline FourVector & FourVector::operator=(const FourVector & v) {
+  m_x = v.x();
+  m_y = v.y();
+  m_z = v.z();
+  m_t = v.t();
+  return *this;
+}
+
+inline void FourVector::set(double x, double y, double z, double  t) {
+  m_x = x;
+  m_y = y;
+  m_z = z;
+  m_t = t;
+}
+
+inline double FourVector::m2() const {
+  return m_t*m_t - (m_x*m_x + m_y*m_y + m_z*m_z);
+}
+
+inline double FourVector::m() const {
+  double mm = m2();
+  return mm < 0.0 ? -std::sqrt(-mm) : std::sqrt(mm);
+}
+
+inline double  FourVector::mag() const { 
+return std::sqrt( m_x*m_x + m_y*m_y + m_z*m_z );
+}
+
+inline double FourVector::perp2() const { return m_x*m_x + m_y*m_y; }
+
+inline double FourVector::perp() const { return std::sqrt(perp2()); }
+
+inline double FourVector::theta() const	 {
+  return m_x == 0.0 && m_y == 0.0 && m_z == 0.0 ? 0.0 : std::atan2(perp(),m_z);
+}
+
+inline double FourVector::phi() const {
+  return m_x == 0.0 && m_y == 0.0 ? 0.0 : std::atan2(m_y,m_x);
+}
+
+inline double  FourVector::rho() const { 
+return std::sqrt( m_x*m_x + m_y*m_y + m_z*m_z );
+}
+
+inline bool FourVector::operator == (const FourVector & v) const {
+  return (v.x()==x() && v.y()==y() && v.z()==z() && v.t()==t()) ? true : false;
+}
+
+inline bool FourVector::operator != (const FourVector & v) const {
+  return (v.x()!=x() || v.y()!=y() || v.z()!=z() || v.t()!=t()) ? true : false;
+}
+
+inline double FourVector::pseudoRapidity() const {
+  double m = mag();
+  if ( m==  0   ) return  0.0;   
+  if ( m==  z() ) return  1.0E72;
+  if ( m== -z() ) return -1.0E72;
+  return 0.5*log( (m+z())/(m-z()) );
+}
+
+inline double FourVector::eta()    const { return pseudoRapidity();}
+
+
+//////////////////////////////////////////////////////////////////////////
+//  ThreeVector inline methods
+//////////////////////////////////////////////////////////////////////////
+
+inline void ThreeVector::swap( ThreeVector & other ) {
+    std::swap( m_x, other.m_x );
+    std::swap( m_y, other.m_y );
+    std::swap( m_z, other.m_z );
+}
+
+inline double ThreeVector::theta() const	 {
+  return m_x == 0.0 && m_y == 0.0 && m_z == 0.0 ? 0.0 : std::atan2(perp(),m_z);
+}
+
+inline double ThreeVector::phi() const {
+  return m_x == 0.0 && m_y == 0.0 ? 0.0 : std::atan2(m_y,m_x);
+}
+
+inline double  ThreeVector::mag() const { 
+return std::sqrt( m_x*m_x + m_y*m_y + m_z*m_z );
+}
+
+inline double ThreeVector::r()    const { return mag(); }
+
+inline void ThreeVector::set(double x, double y, double z) {
+  m_x = x;
+  m_y = y;
+  m_z = z;
+}
+
+inline void ThreeVector::setPhi(double ph) { 
+  double xy   = perp();
+  setX(xy*std::cos(ph));
+  setY(xy*std::sin(ph));
+}
+
+inline void ThreeVector::setTheta(double th) { 
+  double ma   = mag();
+  double ph   = phi();
+  setX(ma*std::sin(th)*std::cos(ph));
+  setY(ma*std::sin(th)*std::sin(ph));
+  setZ(ma*std::cos(th));
+}
+
+inline double ThreeVector::perp2() const { return m_x*m_x + m_y*m_y; }
+
+inline double ThreeVector::perp() const { return std::sqrt(perp2()); }
+
+inline ThreeVector & ThreeVector::operator = (const ThreeVector & p) {
+  m_x = p.x();
+  m_y = p.y();
+  m_z = p.z();
+  return *this;
+}
+
+
+inline bool ThreeVector::operator == (const ThreeVector& v) const {
+  return (v.x()==x() && v.y()==y() && v.z()==z()) ? true : false;
+}
+
+inline bool ThreeVector::operator != (const ThreeVector& v) const {
+  return (v.x()!=x() || v.y()!=y() || v.z()!=z()) ? true : false;
+}
+
+} // HepMC
Index: /trunk/Utilities/HepMC/interface/TempParticleMap.h
===================================================================
--- /trunk/Utilities/HepMC/interface/TempParticleMap.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/TempParticleMap.h	(revision 349)
@@ -0,0 +1,67 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_TempParticleMap_H
+#define HEPMC_TempParticleMap_H
+
+//////////////////////////////////////////////////////////////////////////
+// garren@fnal.gov, October 2007
+//
+// Used by IO classes
+//////////////////////////////////////////////////////////////////////////
+
+#include <map>
+
+namespace HepMC {
+
+    class GenParticle;
+
+    //! TempParticleMap is a temporary GenParticle* container used during input.
+
+    ///
+    /// \class  TempParticleMap
+    /// Used by IO classes for recoverable particle ordering.
+    /// Map GenParticle* against both outgoing vertex and particle order.
+    ///
+    class TempParticleMap {
+    public:
+        typedef std::map<HepMC::GenParticle*,int> TempMap;
+        typedef std::map<int,HepMC::GenParticle*> TempOrderMap;
+	typedef TempMap::iterator     TempMapIterator;
+	typedef TempOrderMap::iterator  orderIterator;
+	
+	TempParticleMap() 
+	: m_particle_to_end_vertex(), m_particle_order() {}
+	
+	~TempParticleMap() {}
+	
+	TempMapIterator begin() { return m_particle_to_end_vertex.begin(); }
+	TempMapIterator end() { return m_particle_to_end_vertex.end(); }
+	orderIterator order_begin() { return m_particle_order.begin(); }
+	orderIterator order_end() { return m_particle_order.end(); }
+	
+	int end_vertex( GenParticle* );
+	
+	void addEndParticle( GenParticle*, int& );
+	
+    private:
+        TempMap       m_particle_to_end_vertex;
+	TempOrderMap  m_particle_order;
+    };
+    
+    inline int TempParticleMap::end_vertex( GenParticle* p )
+    { 
+        //return m_particle_to_end_vertex[p]->second; 
+	TempMapIterator it = m_particle_to_end_vertex.find(p);
+	if( it == end() ) return 0;
+	return m_particle_to_end_vertex[p];
+    }
+
+    inline void TempParticleMap::addEndParticle( GenParticle* p, int& end_vtx_code )
+    {
+	m_particle_order[p->barcode()] = p;
+        m_particle_to_end_vertex[p] = end_vtx_code;
+    }
+
+} // HepMC
+
+#endif  // HEPMC_TempParticleMap_H
+//--------------------------------------------------------------------------
Index: /trunk/Utilities/HepMC/interface/Units.h
===================================================================
--- /trunk/Utilities/HepMC/interface/Units.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/Units.h	(revision 349)
@@ -0,0 +1,42 @@
+#ifndef HEPMC_UNITS_H
+#define HEPMC_UNITS_H
+
+//--------------------------------------------------------------------------
+// Units.h
+// Author:  A. Buckley, D. Grellscheid
+//
+// units used by a GenEvent
+// The default units are set by a configure switch at compile time in Units.cc.
+//--------------------------------------------------------------------------
+
+#include <iostream>
+#include <string>
+
+namespace HepMC {
+
+  ///
+  /// \namespace Units
+  /// Allow units to be specified within HepMC.
+  /// The default units are set at compile time. 
+  ///
+  namespace Units {
+
+    // Convention: if both types are passed, MomentumUnit always goes first.
+    enum MomentumUnit { MEV, GEV };	//!< momentum units
+    enum LengthUnit   { MM, CM };	//!< position units
+    
+    LengthUnit   default_length_unit();		//!< default unit is defined by configure
+    MomentumUnit default_momentum_unit();	//!< default unit is defined by configure
+
+    // helper functions
+    std::string name( MomentumUnit );	//!< convert enum to string
+    std::string name( LengthUnit );	//!< convert enum to string
+
+    /// scaling factor relative to MeV
+    double conversion_factor( MomentumUnit from, MomentumUnit to ); 
+    double conversion_factor( LengthUnit from, LengthUnit to );
+
+  }	// Units
+}	// HepMC
+
+#endif // HEPMC_UNITS_H
Index: /trunk/Utilities/HepMC/interface/Version.h
===================================================================
--- /trunk/Utilities/HepMC/interface/Version.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/Version.h	(revision 349)
@@ -0,0 +1,39 @@
+#ifndef HEPMC_VERSION_H
+#define HEPMC_VERSION_H
+// ----------------------------------------------------------------------
+//
+// Version.h
+// Author:  Lynn Garren
+//
+//  for now, these are free functions
+//
+// ----------------------------------------------------------------------
+
+#include <string>
+#include <iostream>
+
+namespace HepMC {
+
+void version( );			//!< print HepMC version
+void writeVersion( std::ostream & os );	//!< write HepMC version to os
+std::string versionName( );	//!< return HepMC version
+
+inline std::string versionName( )
+{
+    return "2.04.01";
+}
+
+inline void version( )
+{
+    std::cout << " --------------- HepMC Version " << versionName()
+              << " --------------- " << std::endl;
+}
+
+inline void writeVersion( std::ostream & os )
+{
+    os << "             HepMC Version: " << versionName() << std::endl;
+}
+
+}	// HepMC
+
+#endif // HEPMC_VERSION_H
Index: /trunk/Utilities/HepMC/interface/WeightContainer.h
===================================================================
--- /trunk/Utilities/HepMC/interface/WeightContainer.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/WeightContainer.h	(revision 349)
@@ -0,0 +1,179 @@
+//--------------------------------------------------------------------------
+#ifndef HEPMC_WEIGHT_CONTAINER_H
+#define HEPMC_WEIGHT_CONTAINER_H
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, November 2000, refer to:
+// M. Dobbs and J.B. Hansen, "The HepMC C++ Monte Carlo Event Record for
+// High Energy Physics", Computer Physics Communications (to be published).
+//
+// Container for the Weights associated with an event or vertex.
+// Basically just an interface to STL vector.
+//////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+#include <vector>
+
+namespace HepMC {
+
+    //! Container for the Weights associated with an event or vertex.
+
+    ///
+    /// \class  WeightContainer
+    /// Basically just an interface to STL vector.
+    class WeightContainer {
+
+    public:
+        /// default constructor
+	WeightContainer( unsigned int n = 0, const double& value = 0. );
+        /// construct from a vector of weights
+	WeightContainer( const std::vector<double>& weights );
+        /// copy
+	WeightContainer( const WeightContainer& in );
+	virtual ~WeightContainer();
+
+        /// swap
+        void swap( WeightContainer & other);
+        /// copy
+	WeightContainer& operator=( const WeightContainer& );
+        /// copy
+	WeightContainer& operator=( const std::vector<double>& in );
+
+        /// print weights
+	void          print( std::ostream& ostr = std::cout ) const;
+
+        /// size of weight container
+	int           size() const;
+	/// return true if weight container is empty
+	bool          empty() const;
+	/// push onto weight container
+	void          push_back( const double& );
+	/// pop from weight container
+	void          pop_back();
+	/// clear the weight container
+	void          clear();
+
+        /// access the weight container
+	double&       operator[]( unsigned int n );  // unchecked access
+        /// access the weight container
+	const double& operator[]( unsigned int n ) const;
+	
+	/// returns the first element
+	double&       front();
+	/// returns the first element
+	const double& front() const;   
+	/// returns the last element
+	double&       back();
+	/// returns the last element
+	const double& back() const;
+
+        /// iterator for the weight container
+	typedef std::vector<double>::iterator iterator;
+        /// const iterator for the weight container
+	typedef std::vector<double>::const_iterator const_iterator;
+	/// begining of the weight container
+	iterator            begin();
+	/// end of the weight container
+	iterator            end();
+	/// begining of the weight container
+	const_iterator      begin() const;
+	/// end of the weight container
+	const_iterator      end() const;
+	
+    private:
+	std::vector<double>  m_weights;
+    };
+
+    ///////////////////////////
+    // INLINES               //
+    ///////////////////////////
+
+    inline WeightContainer::WeightContainer( unsigned int n,
+					     const double& value ) 
+	: m_weights(n,value)
+    {}
+
+    inline WeightContainer::WeightContainer( const std::vector<double>& wgts )
+	: m_weights(wgts)
+    {}
+
+    inline WeightContainer::WeightContainer( const WeightContainer& in )
+	: m_weights(in.m_weights)
+    {}
+
+    inline WeightContainer::~WeightContainer() {}
+
+    inline void WeightContainer::swap( WeightContainer & other)
+    { m_weights.swap( other.m_weights ); }
+
+    inline WeightContainer& WeightContainer::operator=
+    ( const WeightContainer& in ) {
+        /// best practices implementation
+	WeightContainer tmp( in );
+	swap( tmp );
+	return *this;
+    }
+
+    inline WeightContainer& WeightContainer::operator=
+    ( const std::vector<double>& in ) {
+        /// best practices implementation
+	WeightContainer tmp( in );
+	swap( tmp );
+	return *this;
+    }
+
+    inline void WeightContainer::print( std::ostream& ostr ) const 
+    { 
+	for ( const_iterator w = begin(); w != end(); ++w ) 
+	{ 
+	    ostr << *w << " ";
+	}
+	ostr << std::endl; 
+    }
+
+    inline int WeightContainer::size() const { return m_weights.size(); }
+
+    inline bool WeightContainer::empty() const { return m_weights.empty(); }
+
+    inline void WeightContainer::push_back( const double& value) 
+    { m_weights.push_back(value); }
+
+    inline void WeightContainer::pop_back() { m_weights.pop_back(); }
+
+    inline void WeightContainer::clear() { m_weights.clear(); }
+
+    inline double& WeightContainer::operator[]( unsigned int n ) 
+    { return m_weights[(int)n]; }
+
+    inline const double& WeightContainer::operator[]( unsigned int n ) const
+    { return m_weights[(int)n]; }
+
+    inline double& WeightContainer::front() { return m_weights.front(); }
+
+    inline const double& WeightContainer::front() const 
+    { return m_weights.front(); }
+
+    inline double& WeightContainer::back() { return m_weights.back(); }
+
+    inline const double& WeightContainer::back() const 
+    { return m_weights.back(); }
+
+    inline WeightContainer::iterator WeightContainer::begin() 
+    { return m_weights.begin(); }
+
+    inline WeightContainer::iterator WeightContainer::end() 
+    { return m_weights.end(); }
+
+    inline WeightContainer::const_iterator WeightContainer::begin() const 
+    { return m_weights.begin(); }
+
+    inline WeightContainer::const_iterator WeightContainer::end() const 
+    { return m_weights.end(); }
+
+} // HepMC
+
+#endif  // HEPMC_WEIGHT_CONTAINER_H
+//--------------------------------------------------------------------------
+
+
+
Index: /trunk/Utilities/HepMC/interface/enable_if.h
===================================================================
--- /trunk/Utilities/HepMC/interface/enable_if.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/enable_if.h	(revision 349)
@@ -0,0 +1,50 @@
+#ifndef ENABLE_IF_H
+#define ENABLE_IF_H
+// author: Walter Brown
+
+// ----------------------------------------------------------------------
+// prolog
+
+namespace HepMC  {
+namespace detail {
+
+
+// ----------------------------------------------------------------------
+// enable_if<>
+
+/// internal - used to decide if a class is arithmetic
+template< bool, class >
+struct enable_if
+{ };
+
+/// internal - use if class T is arithmetic
+template< class T >
+struct enable_if<true, T>
+{
+  typedef  T  type;	//!< check type of class T
+};
+
+
+// ----------------------------------------------------------------------
+// disable_if<>
+
+/// internal - used by SimpleVector to decide if a class is arithmetic
+template< bool, class >
+struct disable_if
+{ };
+
+/// internal - used by SimpleVector to decide if a class is arithmetic
+template< class T >
+struct disable_if<false, T>
+{
+  typedef  T  type;	//!< check type of class T
+};
+
+
+// ----------------------------------------------------------------------
+// epilog
+
+}  // namespace detail
+}  // namespace HepMC
+
+#endif  // ENABLE_IF_H
Index: /trunk/Utilities/HepMC/interface/is_arithmetic.h
===================================================================
--- /trunk/Utilities/HepMC/interface/is_arithmetic.h	(revision 349)
+++ /trunk/Utilities/HepMC/interface/is_arithmetic.h	(revision 349)
@@ -0,0 +1,94 @@
+#ifndef IS_ARITHMETIC
+#define IS_ARITHMETIC
+// author: Walter Brown
+
+// ----------------------------------------------------------------------
+// prolog
+
+namespace HepMC  {
+
+///
+/// \namespace detail
+/// internal namespace
+///
+namespace detail  {
+
+
+// ----------------------------------------------------------------------
+// is_arithmetic<>
+
+/// undefined and therefore non-arithmetic
+template< class T >
+  struct is_arithmetic
+{
+  static  bool const  value = false;
+};
+
+/// character is arithmetic
+template<>
+  struct is_arithmetic<char>
+{ static  bool const  value = true; };
+
+/// unsigned character is arithmetic
+template<>
+  struct is_arithmetic<unsigned char>
+{ static  bool const  value = true; };
+
+/// signed character is arithmetic
+template<>
+  struct is_arithmetic<signed char>
+{ static  bool const  value = true; };
+
+/// short is arithmetic
+template<>
+  struct is_arithmetic<short>
+{ static  bool const  value = true; };
+
+/// unsigned short is arithmetic
+template<>
+  struct is_arithmetic<unsigned short>
+{ static  bool const  value = true; };
+
+/// int is arithmetic
+template<>
+  struct is_arithmetic<int>
+{ static  bool const  value = true; };
+
+/// unsigned int is arithmetic
+template<>
+  struct is_arithmetic<unsigned int>
+{ static  bool const  value = true; };
+
+/// long is arithmetic
+template<>
+  struct is_arithmetic<long>
+{ static  bool const  value = true; };
+
+/// unsigned long is arithmetic
+template<>
+  struct is_arithmetic<unsigned long>
+{ static  bool const  value = true; };
+
+/// float is arithmetic
+template<>
+  struct is_arithmetic<float>
+{ static  bool const  value = true; };
+
+/// double is arithmetic
+template<>
+  struct is_arithmetic<double>
+{ static  bool const  value = true; };
+
+/// long double is arithmetic
+template<>
+  struct is_arithmetic<long double>
+{ static  bool const  value = true; };
+
+
+// ----------------------------------------------------------------------
+// epilog
+
+}  // namespace detail
+}  // namespace HepMC
+
+#endif  // IS_ARITHMETIC
Index: /trunk/Utilities/HepMC/src/CommonIO.cc
===================================================================
--- /trunk/Utilities/HepMC/src/CommonIO.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/CommonIO.cc	(revision 349)
@@ -0,0 +1,491 @@
+//--------------------------------------------------------------------------
+//
+// CommonIO.cc
+// Author:  Lynn Garren
+//
+// ----------------------------------------------------------------------
+
+#include <string>
+#include <sstream>
+
+#include "CommonIO.h"
+#include "GenEvent.h"
+#include "HeavyIon.h"
+#include "PdfInfo.h"
+#include "TempParticleMap.h"
+#include "ParticleDataTable.h"
+
+namespace HepMC {
+
+int CommonIO::find_file_type( std::istream& istr )
+{
+    std::string line;
+    while ( std::getline(istr,line) ) {
+	//
+	// search for event listing key before first event only.
+	//
+	if( line == m_io_genevent_start ) {
+	    m_io_type = gen;
+	    return gen;
+	} else if( line == m_io_ascii_start ) {
+	    m_io_type = ascii;
+	    return ascii;
+	} else if( line == m_io_extendedascii_start ) {
+	    m_io_type = extascii;
+	    return extascii;
+	} else if( line == m_io_ascii_pdt_start ) {
+	    m_io_type = ascii_pdt;
+	    return ascii_pdt;
+	} else if( line == m_io_extendedascii_pdt_start ) {
+	    m_io_type = extascii_pdt;
+	    return extascii_pdt;
+	}
+    }
+    return -1;
+}
+
+int CommonIO::find_end_key( std::istream& istr )
+{
+    // peek at the first character before proceeding
+    if( istr.peek()!='H' ) return false;
+    //
+    // we only check the next line
+    std::string line;
+    std::getline(istr,line);
+    //
+    // check to see if this is an end key
+    int iotype = 0;
+    if( line == m_io_genevent_end ) {
+	m_io_type = gen;
+    } else if( line == m_io_ascii_end ) {
+	m_io_type = ascii;
+    } else if( line == m_io_extendedascii_end ) {
+	m_io_type = extascii;
+    } else if( line == m_io_ascii_pdt_end ) {
+	m_io_type = ascii_pdt;
+    } else if( line == m_io_extendedascii_pdt_end ) {
+	m_io_type = extascii_pdt;
+    }
+    if( iotype != 0 && m_io_type != iotype ) {
+        std::cerr << "CommonIO::find_end_key: iotype keys have changed" << std::endl;
+    } else {
+        return iotype;
+    }
+    //
+    // if we get here, then something has gotten badly confused
+    std::cerr << "CommonIO::find_end_key: MALFORMED INPUT" << std::endl;
+    return -1;
+}
+
+void CommonIO::use_input_units( Units::MomentumUnit mom, Units::LengthUnit len ) 
+{
+     m_io_momentum_unit = mom;
+     m_io_position_unit = len;
+}
+
+bool CommonIO::read_io_ascii( std::istream* istr, GenEvent* evt )
+{
+	// read values into temp variables, then create a new GenEvent
+	int event_number = 0, signal_process_id = 0, signal_process_vertex = 0,
+	    num_vertices = 0, random_states_size = 0, weights_size = 0;
+	double eventScale = 0, alpha_qcd = 0, alpha_qed = 0;
+	*istr >> event_number >> eventScale >> alpha_qcd >> alpha_qed
+	       >> signal_process_id >> signal_process_vertex
+	       >> num_vertices >> random_states_size;
+	std::vector<long> random_states(random_states_size);
+	for ( int i = 0; i < random_states_size; ++i ) {
+	    *istr >> random_states[i];
+	}
+	*istr >> weights_size;
+	WeightContainer weights(weights_size);
+	for ( int ii = 0; ii < weights_size; ++ii ) *istr >> weights[ii];
+	istr->ignore(2,'\n');
+	// 
+	// fill signal_process_id, event_number, weights, random_states
+	evt->set_signal_process_id( signal_process_id );
+	evt->set_event_number( event_number );
+	evt->weights() = weights;
+	evt->set_random_states( random_states );
+	// no unit information, so just set it
+	// this is done before the event has any vertices, so it is safe
+ 	evt->use_units( m_io_momentum_unit, m_io_position_unit );
+	//
+	// the end vertices of the particles are not connected until
+	//  after the event is read --- we store the values in a map until then
+       	TempParticleMap particle_to_end_vertex;
+	//
+	// read in the vertices
+	for ( int iii = 1; iii <= num_vertices; ++iii ) {
+	    GenVertex* v = read_vertex(istr,particle_to_end_vertex);
+	    evt->add_vertex( v );
+	}
+	// set the signal process vertex
+	if ( signal_process_vertex ) {
+	    evt->set_signal_process_vertex( 
+		evt->barcode_to_vertex(signal_process_vertex) );
+	}
+	//
+	// last connect particles to their end vertices
+	for ( std::map<int,GenParticle*>::iterator pmap 
+		  = particle_to_end_vertex.order_begin(); 
+	      pmap != particle_to_end_vertex.order_end(); ++pmap ) {
+	    GenParticle* p =  pmap->second;
+	    int vtx = particle_to_end_vertex.end_vertex( p );
+	    GenVertex* itsDecayVtx = evt->barcode_to_vertex(vtx);
+	    if ( itsDecayVtx ) itsDecayVtx->add_particle_in( p );
+	    else {
+		std::cerr << "IO_Ascii::fill_next_event ERROR particle points"
+			  << "\n to null end vertex. " <<std::endl;
+	    }
+	}
+	return true;
+}
+
+bool CommonIO::read_io_extendedascii( std::istream* istr, GenEvent* evt )
+{
+	// read values into temp variables, then create a new GenEvent
+	int event_number = 0, signal_process_id = 0, signal_process_vertex = 0,
+	    num_vertices = 0, random_states_size = 0, weights_size = 0,
+	    nmpi = 0, bp1 = 0, bp2 = 0;
+	double eventScale = 0, alpha_qcd = 0, alpha_qed = 0;
+	*istr >> event_number >> nmpi >> eventScale >> alpha_qcd >> alpha_qed
+	       >> signal_process_id >> signal_process_vertex
+	       >> num_vertices >> bp1 >> bp2 >> random_states_size;
+	std::vector<long> random_states(random_states_size);
+	for ( int i = 0; i < random_states_size; ++i ) {
+	    *istr >> random_states[i];
+	}
+	*istr >> weights_size;
+	WeightContainer weights(weights_size);
+	for ( int ii = 0; ii < weights_size; ++ii ) *istr >> weights[ii];
+	istr->ignore(2,'\n');
+	// 
+	// fill signal_process_id, event_number, weights, random_states
+	evt->set_signal_process_id( signal_process_id );
+	evt->set_event_number( event_number );
+	evt->set_mpi( nmpi );
+	evt->weights() = weights;
+	evt->set_random_states( random_states );
+	evt->set_event_scale( eventScale );
+	evt->set_alphaQCD( alpha_qcd );
+	evt->set_alphaQED( alpha_qed );
+	// get HeavyIon and PdfInfo
+	HeavyIon* ion = read_heavy_ion(istr);
+	if(ion) evt->set_heavy_ion( *ion );
+	PdfInfo* pdf = read_pdf_info(istr);
+	if(pdf) evt->set_pdf_info( *pdf );
+	// no unit information, so just set it
+	// this is done before the event has any vertices, so it is safe
+ 	evt->use_units( m_io_momentum_unit, m_io_position_unit );
+	//
+	// the end vertices of the particles are not connected until
+	//  after the event is read --- we store the values in a map until then
+       	TempParticleMap particle_to_end_vertex;
+	//
+	// read in the vertices
+	for ( int iii = 1; iii <= num_vertices; ++iii ) {
+	    GenVertex* v = read_vertex(istr,particle_to_end_vertex);
+	    evt->add_vertex( v );
+	}
+	// set the signal process vertex
+	if ( signal_process_vertex ) {
+	    evt->set_signal_process_vertex( 
+		evt->barcode_to_vertex(signal_process_vertex) );
+	}
+	//
+	// last connect particles to their end vertices
+	GenParticle* beam1(0);
+	GenParticle* beam2(0);
+	for ( std::map<int,GenParticle*>::iterator pmap 
+		  = particle_to_end_vertex.order_begin(); 
+	      pmap != particle_to_end_vertex.order_end(); ++pmap ) {
+	    GenParticle* p =  pmap->second;
+	    int vtx = particle_to_end_vertex.end_vertex( p );
+	    GenVertex* itsDecayVtx = evt->barcode_to_vertex(vtx);
+	    if ( itsDecayVtx ) itsDecayVtx->add_particle_in( p );
+	    else {
+		std::cerr << "read_io_extendedascii: ERROR particle points"
+			  << "\n to null end vertex. " <<std::endl;
+	    }
+	    // also look for the beam particles
+	    if( p->barcode() == bp1 ) beam1 = p;
+	    if( p->barcode() == bp2 ) beam2 = p;
+	}
+	evt->set_beam_particles(beam1,beam2);
+	return true;
+}
+
+bool CommonIO::read_io_genevent( std::istream* is, GenEvent* evt )
+{
+    /// this method ONLY works if called from fill_next_event
+    //
+    // assume that we've been handed a valid stream and event pointer
+    //
+    // read values into temp variables, then fill GenEvent
+    int event_number = 0, signal_process_id = 0, signal_process_vertex = 0,
+	num_vertices = 0, random_states_size = 0, weights_size = 0,
+	nmpi = 0, bp1 = 0, bp2 = 0;
+    double eventScale = 0, alpha_qcd = 0, alpha_qed = 0;
+    *is >> event_number >> nmpi >> eventScale >> alpha_qcd >> alpha_qed
+	   >> signal_process_id >> signal_process_vertex
+	   >> num_vertices >> bp1 >> bp2 >> random_states_size;
+    std::vector<long> random_states(random_states_size);
+    for ( int i = 0; i < random_states_size; ++i ) {
+	*is >> random_states[i];
+    }
+    *is >> weights_size;
+    WeightContainer weights(weights_size);
+    for ( int ii = 0; ii < weights_size; ++ii ) *is >> weights[ii];
+    is->ignore(2,'\n');
+    // 
+    // fill signal_process_id, event_number, weights, random_states, etc.
+    evt->set_signal_process_id( signal_process_id );
+    evt->set_event_number( event_number );
+    evt->set_mpi( nmpi );
+    evt->weights() = weights;
+    evt->set_random_states( random_states );
+    evt->set_event_scale( eventScale );
+    evt->set_alphaQCD( alpha_qcd );
+    evt->set_alphaQED( alpha_qed );
+    // get unit information if it exists
+    read_units( is, evt );
+    // get HeavyIon and PdfInfo
+    HeavyIon* ion = read_heavy_ion(is);
+    if(ion) evt->set_heavy_ion( *ion );
+    PdfInfo* pdf = read_pdf_info(is);
+    if(pdf) evt->set_pdf_info( *pdf );
+    //
+    // the end vertices of the particles are not connected until
+    //  after the event is read --- we store the values in a map until then
+    TempParticleMap particle_to_end_vertex;
+    //
+    // read in the vertices
+    for ( int iii = 1; iii <= num_vertices; ++iii ) {
+	GenVertex* v = read_vertex(is,particle_to_end_vertex);
+	evt->add_vertex( v );
+    }
+    // set the signal process vertex
+    if ( signal_process_vertex ) {
+	evt->set_signal_process_vertex( 
+	    evt->barcode_to_vertex(signal_process_vertex) );
+    }
+    //
+    // last connect particles to their end vertices
+    GenParticle* beam1(0);
+    GenParticle* beam2(0);
+    for ( std::map<int,GenParticle*>::iterator pmap 
+	      = particle_to_end_vertex.order_begin(); 
+	  pmap != particle_to_end_vertex.order_end(); ++pmap ) {
+	GenParticle* p =  pmap->second;
+	int vtx = particle_to_end_vertex.end_vertex( p );
+	GenVertex* itsDecayVtx = evt->barcode_to_vertex(vtx);
+	if ( itsDecayVtx ) itsDecayVtx->add_particle_in( p );
+	else {
+	    std::cerr << "read_io_genevent: ERROR particle points"
+		      << " to null end vertex. " <<std::endl;
+	}
+	// also look for the beam particles
+	if( p->barcode() == bp1 ) beam1 = p;
+	if( p->barcode() == bp2 ) beam2 = p;
+    }
+    evt->set_beam_particles(beam1,beam2);
+    return true;
+}
+
+bool CommonIO::read_io_particle_data_table( std::istream* is, ParticleDataTable* pdt )
+{
+    // 
+    // read Individual GenParticle data entries
+    while ( read_particle_data( is, pdt ) ) ;
+    return true;
+}
+
+HeavyIon* CommonIO::read_heavy_ion(std::istream* is)
+{
+    // assumes mode has already been checked
+    //
+    // test to be sure the next entry is of type "H" then ignore it
+    if ( !(*is) || is->peek()!='H' ) {
+	std::cerr << "CommonIO::read_heavy_ion setting badbit." << std::endl;
+	is->clear(std::ios::badbit); 
+	return false;
+    } 
+    is->ignore();
+    // read values into temp variables, then create a new HeavyIon object
+    int nh =0, np =0, nt =0, nc =0, 
+        neut = 0, prot = 0, nw =0, nwn =0, nwnw =0;
+    float impact = 0., plane = 0., xcen = 0., inel = 0.; 
+    *is >> nh >> np >> nt >> nc >> neut >> prot
+	   >> nw >> nwn >> nwnw >> impact >> plane >> xcen >> inel;
+    is->ignore(2,'\n');
+    if( nh == 0 ) return false;
+    HeavyIon* ion = new HeavyIon(nh, np, nt, nc, neut, prot,
+	                         nw, nwn, nwnw, 
+				 impact, plane, xcen, inel );
+    //
+    return ion;
+}
+
+PdfInfo* CommonIO::read_pdf_info(std::istream* is)
+{
+    // assumes mode has already been checked
+    //
+    // test to be sure the next entry is of type "F" then ignore it
+    if ( !(*is) || is->peek() !='F') {
+	std::cerr << "CommonIO::read_pdf_info setting badbit." << std::endl;
+	is->clear(std::ios::badbit); 
+	return false;
+    } 
+    is->ignore();
+    // read values into temp variables, then create a new PdfInfo object
+    int id1 =0, id2 =0, pdf_id1=0, pdf_id2=0;
+    double  x1 = 0., x2 = 0., scale = 0., pdf1 = 0., pdf2 = 0.; 
+    *is >> id1 >> id2 >> x1 >> x2 >> scale >> pdf1 >> pdf2;
+    // check to see if we are at the end of the line
+    if( is->peek() != 10 ) {
+        *is >> pdf_id1 >> pdf_id2;
+    }
+    is->ignore(2,'\n');
+    if( id1 == 0 ) return false;
+    PdfInfo* pdf = new PdfInfo( id1, id2, x1, x2, scale, pdf1, pdf2,
+                                pdf_id1, pdf_id2 );
+    //
+    return pdf;
+}
+
+GenVertex* CommonIO::read_vertex( std::istream* is, TempParticleMap& particle_to_end_vertex )
+{
+    // assumes mode has already been checked
+    //
+    // test to be sure the next entry is of type "V" then ignore it
+    if ( !(*is) || is->peek()!='V' ) {
+	std::cerr << "CommonIO::read_vertex setting badbit." << std::endl;
+	std::string line;
+	*is >> line;
+	std::cerr << "attempting to read " << line << std::endl;
+	is->clear(std::ios::badbit); 
+	return false;
+    } 
+    is->ignore();
+    // read values into temp variables, then create a new GenVertex object
+    int identifier =0, id =0, num_orphans_in =0, 
+        num_particles_out = 0, weights_size = 0;
+    double x = 0., y = 0., z = 0., t = 0.; 
+    *is >> identifier >> id >> x >> y >> z >> t
+	   >> num_orphans_in >> num_particles_out >> weights_size;
+    WeightContainer weights(weights_size);
+    for ( int i1 = 0; i1 < weights_size; ++i1 ) *is >> weights[i1];
+    is->ignore(2,'\n');
+    GenVertex* v = new GenVertex( FourVector(x,y,z,t),
+			    id, weights);
+    v->suggest_barcode( identifier );
+    //
+    // read and create the associated particles. outgoing particles are
+    //  added to their production vertices immediately, while incoming
+    //  particles are added to a map and handles later.
+    for ( int i2 = 1; i2 <= num_orphans_in; ++i2 ) {
+	read_particle(is,particle_to_end_vertex);
+    }
+    for ( int i3 = 1; i3 <= num_particles_out; ++i3 ) {
+	v->add_particle_out( read_particle(is,particle_to_end_vertex) );
+    }
+    return v;
+}
+
+GenParticle* CommonIO::read_particle(std::istream* is,
+    TempParticleMap& particle_to_end_vertex ){
+    // assumes mode has already been checked
+    //
+    // test to be sure the next entry is of type "P" then ignore it
+    if ( !(*is) || is->peek()!='P' ) { 
+	std::cerr << "CommonIO::read_particle setting badbit." 
+		  << std::endl;
+	is->clear(std::ios::badbit); 
+	return false;
+    } 
+    is->ignore();
+    //
+    // declare variables to be read in to, and read everything except flow
+    double px = 0., py = 0., pz = 0., e = 0., m = 0., theta = 0., phi = 0.;
+    int bar_code = 0, id = 0, status = 0, end_vtx_code = 0, flow_size = 0;
+    if( m_io_type == ascii ) {
+	*is >> bar_code >> id >> px >> py >> pz >> e >> status 
+	    >> theta >> phi >> end_vtx_code >> flow_size;
+    } else {
+        *is >> bar_code >> id >> px >> py >> pz >> e >> m >> status 
+	    >> theta >> phi >> end_vtx_code >> flow_size;
+    }
+    //
+    // read flow patterns if any exist
+    Flow flow;
+    int code_index, code;
+    for ( int i = 1; i <= flow_size; ++i ) {
+	*is >> code_index >> code;
+	flow.set_icode( code_index,code);
+    }
+    is->ignore(2,'\n'); // '\n' at end of entry
+    GenParticle* p = new GenParticle( FourVector(px,py,pz,e), 
+				id, status, flow, 
+				Polarization(theta,phi) );
+    if( m_io_type != ascii ) {
+        p->set_generated_mass( m );
+    }
+    p->suggest_barcode( bar_code );
+    //
+    // all particles are connected to their end vertex separately 
+    // after all particles and vertices have been created - so we keep
+    // a map of all particles that have end vertices
+    if ( end_vtx_code != 0 ) {
+	particle_to_end_vertex.addEndParticle(p,end_vtx_code);
+    }
+    return p;
+}
+
+ParticleData* CommonIO::read_particle_data( std::istream* is, ParticleDataTable* pdt ) {
+    // assumes mode has already been checked
+    //
+    // test to be sure the next entry is of type "D" then ignore it
+    if ( !(*is) || is->peek()!='D' ) return 0;
+    is->ignore();
+    //
+    // read values into temp variables then create new ParticleData object
+    char its_name[22];
+    int its_id = 0, its_spin = 0;  
+    double its_charge = 0, its_mass = 0, its_clifetime = 0;
+    *is >> its_id >> its_charge >> its_mass 
+	   >> its_clifetime >> its_spin;
+    is->ignore(1); // eat the " "
+    is->getline( its_name, 22, '\n' );
+    ParticleData* pdata = new ParticleData( its_name, its_id, its_charge, 
+					    its_mass, its_clifetime, 
+					    double(its_spin)/2.);
+    pdt->insert(pdata);
+    return pdata;
+}
+
+bool CommonIO::read_units( std::istream* is, GenEvent* evt ) {
+    // assumes mode has already been checked
+    //
+    // test to be sure the next entry is of type "F" then ignore it
+    if ( !(*is) ) {
+	std::cerr << "CommonIO::read_units setting badbit." << std::endl;
+	is->clear(std::ios::badbit); 
+	return false;
+    } 
+    // have no units, but this is not an error
+    // releases prior to 2.04.00 did not write unit information
+    if ( is->peek() !='U') {
+ 	evt->use_units( m_io_momentum_unit, m_io_position_unit );
+	return true;
+    } 
+    is->ignore();	// ignore the first character in the line
+    std::string mom, pos;
+    *is >> mom >> pos;
+    is->ignore(1);      // eat the extra whitespace
+    evt->use_units(mom,pos);
+    //
+    return true;
+}
+
+}	// end namespace HepMC
+
Index: /trunk/Utilities/HepMC/src/CompareGenEvent.cc
===================================================================
--- /trunk/Utilities/HepMC/src/CompareGenEvent.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/CompareGenEvent.cc	(revision 349)
@@ -0,0 +1,203 @@
+/////////////////////////////////////////////////////////////////////////
+// CompareGenEvent.cc
+//
+// garren@fnal.gov, January 2008
+// Free functions used to compare two copies of GenEvent
+//////////////////////////////////////////////////////////////////////////
+//
+
+#include <iostream>
+
+#include "CompareGenEvent.h"
+#include "GenEvent.h"
+
+namespace HepMC {
+
+bool compareGenEvent( GenEvent* e1, GenEvent* e2)
+{
+   //std::cout << "compareGenEvent: comparing event " << e1->event_number() << " to event " 
+   //          << e2->event_number() << std::endl;
+   if( e1->event_number() != e2->event_number() ) { 
+       std::cerr << "compareGenEvent: event numbers differ " << std::endl;
+       return false; 
+   }
+   if( e1->signal_process_id() != e2->signal_process_id() ) { 
+       std::cerr << "compareGenEvent: signal process ids differ " << std::endl;
+       return false; 
+   }
+   if( e1->event_scale() != e2->event_scale() ) { 
+       std::cerr << "compareGenEvent: event scales differ " << std::endl;
+       return false; 
+   }
+   if( e1->alphaQCD() != e2->alphaQCD() ) { 
+       std::cerr << "compareGenEvent: alphaQCD differs " << std::endl;
+       return false; 
+   }
+   if( e1->alphaQED() != e2->alphaQED() ) { 
+       std::cerr << "alphaQED differs " << std::endl;
+       return false; 
+   }
+   if( e1->mpi() != e2->mpi() ) { 
+       std::cerr << "compareGenEvent: mpi differs " << std::endl;
+       return false; 
+   }
+   if ( !compareSignalProcessVertex( e1, e2 ) ) { return false; }
+   if ( !compareBeamParticles( e1, e2 ) ) { return false; }
+   if ( !compareWeights( e1, e2 ) ) { return false; }
+   if( e1->random_states() != e2->random_states() ) { 
+       std::cerr << "compareGenEvent: random states differ " << std::endl;
+       return false; 
+   }
+   if( e1->heavy_ion() != e2->heavy_ion() ) { 
+       std::cerr << "compareGenEvent: heavy ions differ " << std::endl;
+       return false; 
+   }
+   if( e1->pdf_info() != e2->pdf_info() ) { 
+       std::cerr << "compareGenEvent: pdf info differs " << std::endl;
+       return false; 
+   }
+   if ( !compareParticles( e1, e2 ) ) { return false; }
+   if ( !compareVertices( e1, e2 ) ) { return false; }
+   return true;
+}
+
+bool compareSignalProcessVertex( GenEvent* e1, GenEvent* e2 ) {
+   // compare signal process vertex
+   GenVertex* s1 = e1->signal_process_vertex();
+   GenVertex* s2 = e2->signal_process_vertex();
+   if( s1 && s2 ) {
+       if( (*s1) != (*s2) ) { 
+	   std::cerr << "compareSignalProcessVertex: signal process vertices differ " << std::endl;
+	   return false; 
+       }
+   }
+   return true;
+}
+
+bool compareBeamParticles( GenEvent* e1, GenEvent* e2 ) {
+   GenParticle* e1b1 = e1->beam_particles().first;
+   GenParticle* e1b2 = e1->beam_particles().second;
+   GenParticle* e2b1 = e2->beam_particles().first;
+   GenParticle* e2b2 = e2->beam_particles().second;
+   if( e1b1 && e1b2 && e2b1 && e2b2 ) {
+       if( (*e1b1) == (*e2b1)  && (*e1b2) == (*e2b2) ) {
+       } else { 
+	   std::cerr << "compareBeamParticles: beam particles differ " << std::endl;
+	   return false; 
+       }
+   }
+   return true;
+}
+
+bool compareWeights( GenEvent* e1, GenEvent* e2 ) {
+   WeightContainer w1 = e1->weights();
+   WeightContainer w2 = e2->weights();
+   if( w1.size() != w2.size() ) { 
+       std::cerr << "compareWeights: size of weight container differs " << std::endl;
+       return false; 
+   }
+   for( int i=0; i<w1.size(); ++i ) {
+       if( w1[i] != w2[i] ) {
+	   std::cerr << "compareWeights: weight container entry " 
+	             << i << " differs" << std::endl;
+	   return false; 
+       }
+   }
+   return true;
+}
+
+bool compareParticles( GenEvent* e1, GenEvent* e2 ) {
+   if( e1->particles_size() != e2->particles_size() ) { 
+       std::cerr << "compareParticles: number of particles differs " << std::endl;
+       return false; 
+   }
+   if( e1->particles_size() == 0 ) { return true; }
+   for ( GenEvent::particle_const_iterator p1 =  e1->particles_begin(),
+         p2 = e2->particles_begin();
+         p1 !=  e1->particles_end(); ++p1, ++p2 ) {
+       /* std::cout << "compareParticles: particle " 
+		 << (*p1)->barcode() << " " << (*p2)->barcode()
+		 << std::endl; */
+       if ( **p1 != **p2 ) {
+	   std::cerr << "compareParticles: particle " 
+	             << (*p1)->barcode() << " differs from " 
+		     << (*p2)->barcode() << std::endl;
+	   return false; 
+       }
+   }
+   return true;
+}
+
+bool compareVertices( GenEvent* e1, GenEvent* e2 ) {
+   if( e1->vertices_size() != e2->vertices_size() ) { 
+       std::cerr << "compareVertices: number of vertices differs " << std::endl;
+       return false; 
+   }
+   for ( GenEvent::vertex_const_iterator v =  e1->vertices_begin();
+         v !=  e1->vertices_end(); ++v ) {
+       //std::cout << "compareVertices:  comparing vertex " 
+	//         << (*v)->barcode() << std::endl;
+       GenVertex* v1 = (*v);
+       GenVertex* v2 = e2->barcode_to_vertex((*v)->barcode());
+       compareVertex( (*v), e2->barcode_to_vertex((*v)->barcode()));
+       if ( (*v1) != (*v2) ) {
+	   std::cerr << "compareVertices: vertex " 
+	             << (*v)->barcode() << " differs" << std::endl;
+	   return false; 
+       }
+   }
+   return true;
+}
+
+bool compareVertex( GenVertex* v1, GenVertex* v2 ) {
+       if ( v1->position() !=  v2->position() ) {
+	  std::cerr << "compareVertex: position " 
+	            << v1->barcode() << " differs" << std::endl;
+	  return false; 
+       }
+       // if the size of the inlist differs, return false.
+       if ( v1->particles_in_size() !=  v2->particles_in_size() ) {
+	  std::cerr << "compareVertex: particles_in_size " 
+	            << v1->barcode() << " differs" << std::endl;
+	  return false; 
+       }
+       // loop over the inlist and ensure particles are identical
+       if ( v1->particles_in_const_begin() != v1->particles_in_const_end() ) {
+	   for ( GenVertex::particles_in_const_iterator 
+		    ia = v1->particles_in_const_begin(),
+		    ib = v2->particles_in_const_begin();
+		ia != v1->particles_in_const_end(); ia++, ib++ ){
+	      if ( **ia != **ib ) {
+		 std::cerr << "compareVertex: incoming particle " 
+	        	   << v1->barcode() << " differs: " 
+			   << (*ia)->barcode() << " " << (*ib)->barcode()
+			   << std::endl;
+		  //return false; 
+	      }
+	   }
+       }
+       // if the size of the outlist differs, return false.
+       if ( v1->particles_out_size() !=  v2->particles_out_size() ) {
+	  std::cerr << "compareVertex: particles_out_size " 
+	            << v1->barcode() << " differs" << std::endl;
+	  return false; 
+       }
+       // loop over the outlist and ensure particles are identical
+       if ( v1->particles_out_const_begin() != v1->particles_out_const_end() ) {
+	   for ( GenVertex::particles_out_const_iterator 
+		     ia = v1->particles_out_const_begin(),
+		     ib = v2->particles_out_const_begin();
+		 ia != v1->particles_out_const_end(); ia++, ib++ ){
+	       if ( **ia != **ib ) {
+		   std::cerr << "compareVertex: outgoing particle " 
+	        	     << v1->barcode() << " differs: " 
+			     << (*ia)->barcode() << " " << (*ib)->barcode()
+			     << std::endl;
+		   //return false; 
+	       }
+	   }
+       }
+   return true;
+}
+
+} // HepMC
Index: /trunk/Utilities/HepMC/src/Flow.cc
===================================================================
--- /trunk/Utilities/HepMC/src/Flow.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/Flow.cc	(revision 349)
@@ -0,0 +1,217 @@
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, January 2000
+// particle's flow object
+//////////////////////////////////////////////////////////////////////////
+
+#include "Flow.h"
+#include "GenParticle.h"
+#include "GenVertex.h"
+#include "SearchVector.h"
+
+namespace HepMC {
+
+    Flow::Flow( GenParticle* particle_owner ) 
+	: m_particle_owner(particle_owner) 
+    {}
+
+    Flow::Flow( const Flow& inflow ) : 
+	m_particle_owner(inflow.m_particle_owner),
+	m_icode(inflow.m_icode)
+    {
+	/// copies both the m_icode AND the m_particle_owner
+    }
+
+    Flow::~Flow() {
+	m_icode.clear();
+    }
+
+    void Flow::swap( Flow & other)
+    {
+	std::swap( m_particle_owner, other.m_particle_owner );
+	m_icode.swap( other.m_icode );
+    }
+
+    void Flow::print( std::ostream& ostr ) const {
+	ostr << "Flow(" << m_particle_owner << "): " << *this << std::endl;
+    }
+    
+    std::vector<GenParticle*> Flow::connected_partners( int code, int code_index, 
+						  int num_indices ) const {
+	/// Returns all flow partners which have "code" in any  of the 
+	///  num_indices beginning with index code_index.
+	///  m_particle_owner is included in the result.
+	///  Return is by value since the set should never be very big.
+	/// EXAMPLE: if you want to find all flow partners that have the same
+	///   code in indices 2,3,4 as particle p has in index 2, you would use:
+	///   set<GenParticle*> result = 
+	///             p->flow().connected_partners(p->flow().icode(2),2,3);
+	//
+	std::vector<GenParticle*> output;
+	for ( int i = code_index; i!=code_index+num_indices; ++i ) {
+	    if ( icode(i)==code ) {
+		output.push_back(m_particle_owner);
+		connected_partners( &output, code, code_index, num_indices );
+		break;
+	    } 
+	}
+	return output;
+    }
+
+    void Flow::connected_partners( std::vector<HepMC::GenParticle*>* output, int code, 
+				   int code_index, int num_indices ) const
+    {
+	/// protected: for recursive use by Flow::connected_partners()
+	//
+    	if ( !m_particle_owner ) return; // nothing to do
+	// look for connected partners joined to this m_particle_owner
+	// through its end_vertex
+	if ( m_particle_owner->end_vertex() ) {
+	    for ( GenVertex::particle_iterator p 
+		     = m_particle_owner->end_vertex()->particles_begin(family);
+		  p != m_particle_owner->end_vertex()->particles_end(family);
+		  ++p ) {
+		// if the particle has the correct flow code and is not yet in 
+		// the set, then we recursively call connected_partners
+		for ( int index = code_index; index!=code_index+num_indices; 
+		      ++index ){
+		    if ( (*p)->flow(index)==code && not_in_vector(output,(*p)) ) {
+			output->push_back(*p);
+			(*p)->flow().connected_partners( output, code,
+							 code_index, 
+							 num_indices );
+		    }
+		}
+	    }
+	}
+	// same for production_vertex
+	if ( m_particle_owner->production_vertex() ) {
+	    for ( GenVertex::particle_iterator p 
+		      = m_particle_owner->production_vertex()->
+		      particles_begin( family );
+		  p != m_particle_owner->production_vertex()->
+		      particles_end( family ); ++p ) {
+		// if the particle has the correct flow code and is not yet in 
+		// the set, then we recursively call connected_partners
+		for ( int index = code_index; index!=code_index+num_indices; 
+		      ++index ){
+		    if ( (*p)->flow(index)==code && not_in_vector(output,(*p)) ) {
+			output->push_back(*p);
+			(*p)->flow().connected_partners( output, code,
+							 code_index, 
+							 num_indices );
+		    }
+		}
+	    }
+	}
+    }
+
+    std::vector<GenParticle*> Flow::dangling_connected_partners( int code, 
+				     int code_index, int num_indices ) const {
+	std::vector<GenParticle*> output;
+	std::vector<GenParticle*> visited_particles;
+	for ( int i = code_index; i!=code_index+num_indices; ++i ) {
+	    if ( icode(i)==code ) {
+		visited_particles.push_back(m_particle_owner);
+		dangling_connected_partners( &output, &visited_particles, code,
+					     code_index, num_indices );
+		break;
+	    }
+	}
+	return output;
+    }
+
+    void Flow::dangling_connected_partners( std::vector<HepMC::GenParticle*>* output, 
+					    std::vector<HepMC::GenParticle*>* 
+					    visited_particles,
+					    int code, int code_index, 
+					    int num_indices ) const 
+    {
+	/// protected: for recursive use by Flow::dangling_connected_partners
+	//
+    	if ( !m_particle_owner ) return; // nothing to do
+	int count_partners = 0;
+	// look for connected partners joined to this m_particle_owner
+	// through its end_vertex
+	if ( m_particle_owner->end_vertex() ) {
+	    for ( GenVertex::particle_iterator p 
+		     = m_particle_owner->end_vertex()->particles_begin(family);
+		  p != m_particle_owner->end_vertex()->particles_end(family);
+		  ++p ) {
+		// if the particle has the correct flow code and is not yet in 
+		// the set, then we recursively call connected_partners
+		for ( int index = code_index; index!=code_index+num_indices; 
+		      ++index ){
+		    if ( (*p)->flow(index)==code ) {
+			if ( *p!=m_particle_owner ) ++count_partners;
+			if ( not_in_vector(visited_particles,(*p)) ) {
+			    visited_particles->push_back(*p);
+			    (*p)->flow().dangling_connected_partners( output, 
+					             visited_particles, code,
+						     code_index, num_indices );
+
+			}
+		    }		
+		}
+	    }
+	}
+	// same for production_vertex
+	if ( m_particle_owner->production_vertex() ) {
+	    for ( GenVertex::particle_iterator p = m_particle_owner->
+						production_vertex()->
+						particles_begin( family );
+		  p != m_particle_owner->production_vertex()->
+						particles_end( family ); 
+		  ++p ) {
+		// if the particle has the correct flow code and is not yet in 
+		// the set, then we recursively call connected_partners
+		for ( int index = code_index; index!=code_index+num_indices; 
+		      ++index ){
+		    if ( (*p)->flow(index)==code ) {
+			if ( *p!=m_particle_owner ) ++count_partners;
+			if ( not_in_vector(visited_particles,(*p)) ) {
+			    visited_particles->push_back(*p);
+			    (*p)->flow().dangling_connected_partners( output, 
+					             visited_particles, code,
+						     code_index, num_indices );
+
+			}
+		    }
+		}
+	    }
+	}
+	if ( count_partners <= 1 ) output->push_back( m_particle_owner );
+    }
+	
+    /////////////
+    // Friends //
+    /////////////
+
+        /// send Flow informatin to ostr for printing
+    std::ostream& operator<<( std::ostream& ostr, const Flow& f ) {
+	ostr << f.m_icode.size();
+	for ( std::map<int,int>::const_iterator i = f.m_icode.begin();
+	      i != f.m_icode.end(); ++i ) {
+	    ostr << " " << (*i).first << " " << (*i).second;
+	}
+	return ostr;
+    }
+
+} // HepMC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /trunk/Utilities/HepMC/src/GenEvent.cc
===================================================================
--- /trunk/Utilities/HepMC/src/GenEvent.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/GenEvent.cc	(revision 349)
@@ -0,0 +1,653 @@
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999
+// Updated: 7.1.2000 iterators complete and working!
+// Updated: 10.1.2000 GenEvent::vertex, particle iterators are made 
+//                    constant WRT this event ... note that 
+//                    GenVertex::***_iterator is not const, since it must
+//                    be able to return a mutable pointer to itself.
+// Updated: 08.2.2000 the event now holds a set of all attached vertices
+//                    rather than just the roots of the graph
+// Event record for MC generators (for use at any stage of generation)
+//////////////////////////////////////////////////////////////////////////
+
+#include <iomanip>
+
+#include "GenEvent.h"
+#include "Version.h"
+
+namespace HepMC {
+
+    GenEvent::GenEvent( int signal_process_id, 
+                        int event_number,
+			GenVertex* signal_vertex,
+			const WeightContainer& weights,
+			const std::vector<long>& random_states,
+			Units::MomentumUnit mom, 
+			Units::LengthUnit len ) :
+	m_signal_process_id(signal_process_id), 
+	m_event_number(event_number),
+	m_mpi(-1),
+	m_event_scale(-1), 
+	m_alphaQCD(-1), 
+	m_alphaQED(-1),
+	m_signal_process_vertex(signal_vertex), 
+	m_beam_particle_1(0),
+	m_beam_particle_2(0),
+	m_weights(weights),
+	m_random_states(random_states),
+	m_vertex_barcodes(),
+	m_particle_barcodes(),
+	m_heavy_ion(0), 
+	m_pdf_info(0),
+	m_momentum_unit(mom),
+	m_position_unit(len)
+    {
+        /// This constructor only allows null pointers to HeavyIon and PdfInfo
+	///
+	/// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
+	///       are as suggested in hep-ph/0109068, "Generic Interface..."
+	///
+    }
+
+    GenEvent::GenEvent( int signal_process_id, int event_number,
+			GenVertex* signal_vertex,
+			const WeightContainer& weights,
+			const std::vector<long>& random_states,
+			const HeavyIon& ion, 
+			const PdfInfo& pdf,
+			Units::MomentumUnit mom, 
+			Units::LengthUnit len ) :
+	m_signal_process_id(signal_process_id), 
+	m_event_number(event_number),
+	m_mpi(-1),
+	m_event_scale(-1), 
+	m_alphaQCD(-1), 
+	m_alphaQED(-1),
+	m_signal_process_vertex(signal_vertex), 
+	m_beam_particle_1(0),
+	m_beam_particle_2(0),
+	m_weights(weights),
+	m_random_states(random_states), 
+	m_vertex_barcodes(),
+	m_particle_barcodes(),
+	m_heavy_ion( new HeavyIon(ion) ), 
+	m_pdf_info( new PdfInfo(pdf) ),
+	m_momentum_unit(mom),
+	m_position_unit(len)
+    {
+        /// GenEvent makes its own copy of HeavyIon and PdfInfo
+	///
+	/// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
+	///       are as suggested in hep-ph/0109068, "Generic Interface..."
+    }
+
+    GenEvent::GenEvent( Units::MomentumUnit mom, 
+			Units::LengthUnit len, 
+			int signal_process_id, 
+                        int event_number,
+			GenVertex* signal_vertex,
+			const WeightContainer& weights,
+			const std::vector<long>& random_states ) :
+	m_signal_process_id(signal_process_id), 
+	m_event_number(event_number),
+	m_mpi(-1),
+	m_event_scale(-1), 
+	m_alphaQCD(-1), 
+	m_alphaQED(-1),
+	m_signal_process_vertex(signal_vertex), 
+	m_beam_particle_1(0),
+	m_beam_particle_2(0),
+	m_weights(weights),
+	m_random_states(random_states),
+	m_vertex_barcodes(),
+	m_particle_barcodes(),
+	m_heavy_ion(0), 
+	m_pdf_info(0),
+	m_momentum_unit(mom),
+	m_position_unit(len)
+    {
+        /// constructor requiring units - all else is default
+        /// This constructor only allows null pointers to HeavyIon and PdfInfo
+	///
+	/// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
+	///       are as suggested in hep-ph/0109068, "Generic Interface..."
+	///
+    }
+
+    GenEvent::GenEvent( Units::MomentumUnit mom, 
+			Units::LengthUnit len,
+			int signal_process_id, int event_number,
+			GenVertex* signal_vertex,
+			const WeightContainer& weights,
+			const std::vector<long>& random_states,
+			const HeavyIon& ion, 
+			const PdfInfo& pdf ) :
+	m_signal_process_id(signal_process_id), 
+	m_event_number(event_number),
+	m_mpi(-1),
+	m_event_scale(-1), 
+	m_alphaQCD(-1), 
+	m_alphaQED(-1),
+	m_signal_process_vertex(signal_vertex), 
+	m_beam_particle_1(0),
+	m_beam_particle_2(0),
+	m_weights(weights),
+	m_random_states(random_states), 
+	m_vertex_barcodes(),
+	m_particle_barcodes(),
+	m_heavy_ion( new HeavyIon(ion) ), 
+	m_pdf_info( new PdfInfo(pdf) ),
+	m_momentum_unit(mom),
+	m_position_unit(len)
+    {
+        /// explicit constructor with units first that takes HeavyIon and PdfInfo
+        /// GenEvent makes its own copy of HeavyIon and PdfInfo
+	///
+	/// note: default values for m_event_scale, m_alphaQCD, m_alphaQED
+	///       are as suggested in hep-ph/0109068, "Generic Interface..."
+    }
+
+    GenEvent::GenEvent( const GenEvent& inevent ) 
+      : m_signal_process_id    ( inevent.signal_process_id() ),
+	m_event_number         ( inevent.event_number() ),
+	m_mpi                  ( inevent.mpi() ),
+	m_event_scale          ( inevent.event_scale() ),
+	m_alphaQCD             ( inevent.alphaQCD() ),
+	m_alphaQED             ( inevent.alphaQED() ),
+	m_signal_process_vertex( /* inevent.m_signal_process_vertex */ ),
+	m_beam_particle_1      ( /* inevent.m_beam_particle_1 */ ),
+	m_beam_particle_2      ( /* inevent.m_beam_particle_2 */ ),
+	m_weights              ( /* inevent.m_weights */ ),
+	m_random_states        ( /* inevent.m_random_states */ ),
+	m_vertex_barcodes      ( /* inevent.m_vertex_barcodes */ ),
+	m_particle_barcodes    ( /* inevent.m_particle_barcodes */ ),
+	m_heavy_ion            ( inevent.heavy_ion() ? new HeavyIon(*inevent.heavy_ion()) : 0 ),
+	m_pdf_info             ( inevent.pdf_info() ? new PdfInfo(*inevent.pdf_info()) : 0 ),
+	m_momentum_unit        ( inevent.momentum_unit() ),
+	m_position_unit        ( inevent.length_unit() )
+    {
+	/// deep copy - makes a copy of all vertices!
+	//++s_counter;
+	//
+
+	// 1. create a NEW copy of all vertices from inevent
+	//    taking care to map new vertices onto the vertices being copied
+	//    and add these new vertices to this event.
+	//    We do not use GenVertex::operator= because that would copy
+	//    the attached particles as well.
+	std::map<const GenVertex*,GenVertex*> map_in_to_new;
+	for ( GenEvent::vertex_const_iterator v = inevent.vertices_begin();
+	      v != inevent.vertices_end(); ++v ) {
+	    GenVertex* newvertex = new GenVertex(
+	        (*v)->position(), (*v)->id(), (*v)->weights() );
+            newvertex->suggest_barcode( (*v)->barcode() );
+	    map_in_to_new[*v] = newvertex;
+	    add_vertex( newvertex );
+	}
+	// 2. copy the signal process vertex info.
+	if ( inevent.signal_process_vertex() ) {
+	    set_signal_process_vertex( 
+		map_in_to_new[inevent.signal_process_vertex()] );
+	} else set_signal_process_vertex( 0 );
+        //
+        // 3. create a NEW copy of all particles from inevent
+        //    taking care to attach them to the appropriate vertex
+	GenParticle* beam1(0);
+	GenParticle* beam2(0);
+        for ( GenEvent::particle_const_iterator p = inevent.particles_begin();
+              p != inevent.particles_end(); ++p ) 
+        {
+	    GenParticle* oldparticle = *p;
+	    GenParticle* newparticle = new GenParticle(*oldparticle);
+	    if ( oldparticle->end_vertex() ) {
+                map_in_to_new[ oldparticle->end_vertex() ]->
+                                         add_particle_in(newparticle);
+            }
+            if ( oldparticle->production_vertex() ) {
+                map_in_to_new[ oldparticle->production_vertex() ]->
+                                         add_particle_out(newparticle);
+            }
+	    if ( oldparticle == inevent.beam_particles().first ) beam1 = newparticle;
+	    if ( oldparticle == inevent.beam_particles().second ) beam2 = newparticle;
+        }
+	set_beam_particles( beam1, beam2 );
+	//
+	// 4. now that vtx/particles are copied, copy weights and random states
+	set_random_states( inevent.random_states() );
+	weights() = inevent.weights();
+    }
+
+    void GenEvent::swap( GenEvent & other )
+    {
+        // if a container has a swap method, use that for improved performance
+	std::swap(m_signal_process_id    , other.m_signal_process_id    );
+	std::swap(m_event_number         , other.m_event_number         );
+	std::swap(m_mpi                  , other.m_mpi                  );
+	std::swap(m_event_scale          , other.m_event_scale          );
+	std::swap(m_alphaQCD             , other.m_alphaQCD             );
+	std::swap(m_alphaQED             , other.m_alphaQED             );
+	std::swap(m_signal_process_vertex, other.m_signal_process_vertex);
+	std::swap(m_beam_particle_1      , other.m_beam_particle_1      );
+	std::swap(m_beam_particle_2      , other.m_beam_particle_2      );
+	m_weights.swap(           other.m_weights  );
+	m_random_states.swap(     other.m_random_states  );
+	m_vertex_barcodes.swap(   other.m_vertex_barcodes );
+	m_particle_barcodes.swap( other.m_particle_barcodes );
+	std::swap(m_heavy_ion            , other.m_heavy_ion            );
+	std::swap(m_pdf_info             , other.m_pdf_info             );
+	std::swap(m_momentum_unit       , other.m_momentum_unit       );
+	std::swap(m_position_unit       , other.m_position_unit       );
+	// must now adjust GenVertex back pointers
+	for ( GenEvent::vertex_const_iterator vthis = vertices_begin();
+	      vthis != vertices_end(); ++vthis ) {
+	    (*vthis)->change_parent_event_( this );
+	}
+	for ( GenEvent::vertex_const_iterator voth = other.vertices_begin();
+	      voth != other.vertices_end(); ++voth ) {
+	    (*voth)->change_parent_event_( &other );
+	}
+    }
+
+    GenEvent::~GenEvent() 
+    {
+	/// Deep destructor.
+	/// deletes all vertices/particles in this evt
+	///
+	delete_all_vertices();
+	delete m_heavy_ion;
+	delete m_pdf_info;
+	//--s_counter;
+    }
+
+    GenEvent& GenEvent::operator=( const GenEvent& inevent ) 
+    {
+        /// best practices implementation
+	GenEvent tmp( inevent );
+	swap( tmp );
+	return *this;
+    }
+
+    void GenEvent::print( std::ostream& ostr ) const {
+	/// dumps the content of this event to ostr
+	///   to dump to cout use: event.print();
+	///   if you want to write this event to file outfile.txt you could use:
+	///      std::ofstream outfile("outfile.txt"); event.print( outfile );
+	ostr << "________________________________________"
+	     << "________________________________________\n";
+	ostr << "GenEvent: #" << event_number() 
+	     << " ID=" << signal_process_id() 
+	     << " SignalProcessGenVertex Barcode: " 
+	     << ( signal_process_vertex() ? signal_process_vertex()->barcode()
+		  : 0 )
+	     << "\n";
+	//ostr << " Current Memory Usage: " 
+	//     << GenEvent::counter() << " events, "
+	//     << GenVertex::counter() << " vertices, "
+	//     << GenParticle::counter() << " particles.\n"; 
+	write_units( ostr );
+	ostr << " Entries this event: " << vertices_size() << " vertices, "
+	     << particles_size() << " particles.\n"; 
+	if( m_beam_particle_1 && m_beam_particle_2 ) {
+	  ostr << " Beam Particle barcodes: " << beam_particles().first->barcode() << " "
+	       << beam_particles().second->barcode() << " \n";
+	} else {
+	  ostr << " Beam Particles are not defined.\n";
+	}
+	// Random State
+	ostr << " RndmState(" << m_random_states.size() << ")=";
+	for ( std::vector<long>::const_iterator rs 
+		  = m_random_states.begin();
+	      rs != m_random_states.end(); ++rs ) { ostr << *rs << " "; }
+	ostr << "\n";
+	// Weights
+	ostr << " Wgts(" << weights().size() << ")=";
+	for ( WeightContainer::const_iterator wgt = weights().begin();
+	      wgt != weights().end(); ++wgt ) { ostr << *wgt << " "; }
+	ostr << "\n";
+	ostr << " EventScale " << event_scale() 
+	     << " [energy] \t alphaQCD=" << alphaQCD() 
+	     << "\t alphaQED=" << alphaQED() << std::endl;
+	// print a legend to describe the particle info
+	ostr << "                                    GenParticle Legend\n";
+ 	ostr  << "        Barcode   PDG ID      "
+	      << "( Px,       Py,       Pz,     E )"
+	      << " Stat  DecayVtx\n";
+	ostr << "________________________________________"
+	     << "________________________________________\n";
+	// Print all Vertices
+	for ( GenEvent::vertex_const_iterator vtx = this->vertices_begin();
+	      vtx != this->vertices_end(); ++vtx ) {
+	    (*vtx)->print(ostr); 
+	}
+	ostr << "________________________________________"
+	     << "________________________________________" << std::endl;
+    }
+
+    void GenEvent::print_version( std::ostream& ostr ) const {
+        ostr << "---------------------------------------------" << std::endl;
+        writeVersion( ostr );
+        ostr << "---------------------------------------------" << std::endl;
+    }
+
+    bool GenEvent::add_vertex( GenVertex* vtx ) {
+	/// returns true if successful - generally will only return false
+	/// if the inserted vertex is already included in the event.
+	if ( !vtx ) return false;
+	// if vtx previously pointed to another GenEvent, remove it from that
+	// GenEvent's list
+	if ( vtx->parent_event() && vtx->parent_event() != this ) {
+	    bool remove_status = vtx->parent_event()->remove_vertex( vtx );
+	    if ( !remove_status ) {	       
+		std::cerr << "GenEvent::add_vertex ERROR "
+			  << "GenVertex::parent_event points to \n"
+			  << "an event that does not point back to the "
+			  << "GenVertex. \n This probably indicates a deeper "
+			  << "problem. " << std::endl;
+	    }
+	}
+	//
+	// setting the vertex parent also inserts the vertex into this
+	// event
+	vtx->set_parent_event_( this );
+	return ( m_vertex_barcodes.count(vtx->barcode()) ? true : false );
+    }
+
+    bool GenEvent::remove_vertex( GenVertex* vtx ) {
+	/// this removes vtx from the event but does NOT delete it.
+	/// returns True if an entry vtx existed in the table and was erased
+	if ( m_signal_process_vertex == vtx ) m_signal_process_vertex = 0;
+	if ( vtx->parent_event() == this ) vtx->set_parent_event_( 0 );
+	return ( m_vertex_barcodes.count(vtx->barcode()) ? false : true );
+    }
+
+    void GenEvent::clear() 
+    {
+	/// remove all information from the event
+	/// deletes all vertices/particles in this evt
+	///
+	delete_all_vertices();
+	delete m_heavy_ion;
+	delete m_pdf_info;
+	m_signal_process_id = 0;
+        m_beam_particle_1 = 0;
+	m_beam_particle_2 = 0;
+	m_event_number = 0;
+	m_event_scale = -1;
+	m_alphaQCD = -1;
+	m_alphaQED = -1;
+	m_weights = std::vector<double>();
+	m_random_states = std::vector<long>();
+	//m_momentum_unit = ;
+	//m_position_unit = ;
+        // error check just to be safe
+	if ( m_vertex_barcodes.size() != 0 
+	     || m_particle_barcodes.size() != 0 ) {
+	    std::cerr << "GenEvent::clear() strange result ... \n"
+		      << "either the particle and/or the vertex map isn't empty" << std::endl;
+            std::cerr << "Number vtx,particle the event after deleting = "
+                      << m_vertex_barcodes.size() << "  " 
+		      << m_particle_barcodes.size() << std::endl;
+            //std::cerr << "Total Number vtx,particle in memory "
+             //         << "after method called = "
+             //         << GenVertex::counter() << "\t"
+		//      << GenParticle::counter() << std::endl;
+        }
+	return;
+    }
+    
+    void GenEvent::delete_all_vertices() {
+	/// deletes all vertices in the vertex container
+	/// (i.e. all vertices owned by this event)
+	/// The vertices are the "owners" of the particles, so as we delete
+	///   the vertices, the vertex desctructors are automatically
+	///   deleting their particles.
+
+  	// delete each vertex individually (this deletes particles as well)
+	while ( !vertices_empty() ) {
+	    GenVertex* vtx = ( m_vertex_barcodes.begin() )->second;
+            m_vertex_barcodes.erase( m_vertex_barcodes.begin() );
+            delete vtx;
+ 	}
+	//
+	// Error checking:
+	if ( !vertices_empty() || ! particles_empty() ) {
+	    std::cerr << "GenEvent::delete_all_vertices strange result ... "
+		      << "after deleting all vertices, \nthe particle and "
+		      << "vertex maps aren't empty.\n  This probably " 
+		      << "indicates deeper problems or memory leak in the "
+		      << "code." << std::endl;
+            std::cerr << "Number vtx,particle the event after deleting = "
+                      << m_vertex_barcodes.size() << "  " 
+		      << m_particle_barcodes.size() << std::endl;
+            //std::cerr << "Total Number vtx,particle in memory "
+            //          << "after method called = "
+            //          << GenVertex::counter() << "\t"
+		//      << GenParticle::counter() << std::endl;
+	}
+    }
+    
+    bool GenEvent::set_barcode( GenParticle* p, int suggested_barcode )
+    {
+	if ( p->parent_event() != this ) {
+	    std::cerr << "GenEvent::set_barcode attempted, but the argument's"
+		      << "\n parent_event is not this ... request rejected."
+		      << std::endl;
+	    return false;
+	}
+	// M.Dobbs  Nov 4, 2002
+	// First we must check to see if the particle already has a
+	// barcode which is different from the suggestion. If yes, we
+	// remove it from the particle map.
+	if ( p->barcode() != 0 && p->barcode() != suggested_barcode ) {
+	    if ( m_particle_barcodes.count(p->barcode()) &&
+		 m_particle_barcodes[p->barcode()] == p ) {
+		m_particle_barcodes.erase( p->barcode() );
+	    }
+	    // At this point either the particle is NOT in
+	    // m_particle_barcodes, or else it is in the map, but
+	    // already with the suggested barcode.
+	}
+	//
+	// First case --- a valid barcode has been suggested
+	//     (valid barcodes are numbers greater than zero)
+	bool insert_success = true;
+	if ( suggested_barcode > 0 ) {
+	    if ( m_particle_barcodes.count(suggested_barcode) ) {
+		// the suggested_barcode is already used.
+		if ( m_particle_barcodes[suggested_barcode] == p ) {
+		    // but it was used for this particle ... so everythings ok
+		    p->set_barcode_( suggested_barcode );
+		    return true;
+		}
+		insert_success = false;
+		suggested_barcode = 0;
+	    } else { // suggested barcode is OK, proceed to insert
+		m_particle_barcodes[suggested_barcode] = p;
+		p->set_barcode_( suggested_barcode );
+		return true;
+	    }
+	}
+	//
+	// Other possibility -- a valid barcode has not been suggested,
+	//    so one is automatically generated
+	if ( suggested_barcode < 0 ) insert_success = false;
+	if ( suggested_barcode <= 0 ) {
+	    if ( !m_particle_barcodes.empty() ) {
+		// in this case we find the highest barcode that was used,
+		// and increment it by 1
+		suggested_barcode = m_particle_barcodes.rbegin()->first;
+		++suggested_barcode;
+	    }
+	    // For the automatically assigned barcodes, the first one
+	    //   we use is 10001 ... this is just because when we read 
+	    //   events from HEPEVT, we will suggest their index as the
+	    //   barcode, and that index has maximum value 10000.
+	    //  This way we will immediately be able to recognize the hepevt
+	    //   particles from the auto-assigned ones.
+	    if ( suggested_barcode <= 10000 ) suggested_barcode = 10001;
+	}
+	// At this point we should have a valid barcode
+	if ( m_particle_barcodes.count(suggested_barcode) ) {
+	    std::cerr << "GenEvent::set_barcode ERROR, this should never "
+		      << "happen \n report bug to matt.dobbs@cern.ch" 
+		      << std::endl;
+	}
+	m_particle_barcodes[suggested_barcode] = p;
+	p->set_barcode_( suggested_barcode );
+	return insert_success;
+    }
+
+    bool GenEvent::set_barcode( GenVertex* v, int suggested_barcode )
+    {
+	if ( v->parent_event() != this ) {
+	    std::cerr << "GenEvent::set_barcode attempted, but the argument's"
+		      << "\n parent_event is not this ... request rejected."
+		      << std::endl;
+	    return false;
+	}
+	// M.Dobbs Nov 4, 2002
+	// First we must check to see if the vertex already has a
+	// barcode which is different from the suggestion. If yes, we
+	// remove it from the vertex map.
+	if ( v->barcode() != 0 && v->barcode() != suggested_barcode ) {
+	    if ( m_vertex_barcodes.count(v->barcode()) &&
+		 m_vertex_barcodes[v->barcode()] == v ) {
+		m_vertex_barcodes.erase( v->barcode() );
+	    }
+	    // At this point either the vertex is NOT in
+	    // m_vertex_barcodes, or else it is in the map, but
+	    // already with the suggested barcode.
+	}
+	
+	//
+	// First case --- a valid barcode has been suggested
+	//     (valid barcodes are numbers greater than zero)
+	bool insert_success = true;
+	if ( suggested_barcode < 0 ) {
+	    if ( m_vertex_barcodes.count(suggested_barcode) ) {
+		// the suggested_barcode is already used.
+		if ( m_vertex_barcodes[suggested_barcode] == v ) {
+		    // but it was used for this vertex ... so everythings ok
+		    v->set_barcode_( suggested_barcode );
+		    return true;
+		}
+		insert_success = false;
+		suggested_barcode = 0;
+	    } else { // suggested barcode is OK, proceed to insert
+		m_vertex_barcodes[suggested_barcode] = v;
+		v->set_barcode_( suggested_barcode );
+		return true;
+	    }
+	}
+	//
+	// Other possibility -- a valid barcode has not been suggested,
+	//    so one is automatically generated
+	if ( suggested_barcode > 0 ) insert_success = false;
+	if ( suggested_barcode >= 0 ) {
+	    if ( !m_vertex_barcodes.empty() ) {
+		// in this case we find the highest barcode that was used,
+		// and increment it by 1, (vertex barcodes are negative)
+		suggested_barcode = m_vertex_barcodes.rbegin()->first;
+		--suggested_barcode;
+	    }
+	    if ( suggested_barcode >= 0 ) suggested_barcode = -1;
+	}
+	// At this point we should have a valid barcode
+	if ( m_vertex_barcodes.count(suggested_barcode) ) {
+	    std::cerr << "GenEvent::set_barcode ERROR, this should never "
+		      << "happen \n report bug to matt.dobbs@cern.ch" 
+		      << std::endl;
+	}
+	m_vertex_barcodes[suggested_barcode] = v;
+	v->set_barcode_( suggested_barcode );
+	return insert_success;
+    }
+
+    /// test to see if we have two valid beam particles
+    bool  GenEvent::valid_beam_particles() const {
+        bool have1 = false;
+        bool have2 = false;
+	// first check that both are defined
+        if(m_beam_particle_1 && m_beam_particle_2) {
+	    // now look for a match with the particle "list"
+            for ( particle_const_iterator p = particles_begin();
+        	  p != particles_end(); ++p ) {
+		if( m_beam_particle_1 == *p ) have1 = true;
+		if( m_beam_particle_2 == *p ) have2 = true;
+	    }
+	}
+	if( have1 && have2 ) return true;
+	return false;
+    }
+    
+    /// construct the beam particle information using pointers to GenParticle
+    /// returns false if either GenParticle* is null
+    bool  GenEvent::set_beam_particles(GenParticle* bp1, GenParticle* bp2) {
+	m_beam_particle_1 = bp1;
+	m_beam_particle_2 = bp2;
+	if( m_beam_particle_1 && m_beam_particle_2 ) return true;
+	return false;
+    }
+
+    /// construct the beam particle information using a std::pair of pointers to GenParticle
+    /// returns false if either GenParticle* is null
+    bool  GenEvent::set_beam_particles(std::pair<HepMC::GenParticle*, HepMC::GenParticle*> const & bp) {
+	return set_beam_particles(bp.first,bp.second);
+    }
+
+    void GenEvent::write_units( std::ostream & os ) const {
+	os << " Momenutm units:" << std::setw(8) << name(momentum_unit());
+	os << "     Position units:" << std::setw(8) << name(length_unit());
+	os << std::endl;
+    }
+
+   bool GenEvent::use_momentum_unit( Units::MomentumUnit newunit ) { 
+	// currently not exception-safe. 
+	// Easy to fix, though, if needed.
+	if ( m_momentum_unit != newunit ) { 
+	    const double factor = Units::conversion_factor( m_momentum_unit, newunit );
+	    // multiply all momenta by 'factor',  
+	    // loop is entered only if particle list is not empty
+            for ( GenEvent::particle_iterator p = particles_begin();
+                                              p != particles_end(); ++p ) 
+            {
+		(*p)->convert_momentum(factor);
+            }
+	    // ... 
+	    m_momentum_unit = newunit; 
+	}
+	return true; 
+    }
+    
+    bool GenEvent::use_length_unit( Units::LengthUnit newunit ) { 
+	// currently not exception-safe. 
+	// Easy to fix, though, if needed.
+	if ( m_position_unit != newunit ) { 
+	    const double factor = Units::conversion_factor( m_position_unit, newunit );
+	    // multiply all lengths by 'factor', 
+	    // loop is entered only if vertex list is not empty
+	    for ( GenEvent::vertex_iterator vtx = vertices_begin();
+	                                    vtx != vertices_end(); ++vtx ) {
+		(*vtx)->convert_position(factor);
+	    }
+	    // ... 
+	    m_position_unit = newunit; 
+	} 
+	return true; 
+    }  
+
+    bool GenEvent::use_momentum_unit( std::string& newunit ) { 
+        if     ( newunit == "MEV" ) return use_momentum_unit( Units::MEV );
+	else if( newunit == "GEV" ) return use_momentum_unit( Units::GEV );
+	else std::cerr << "GenEvent::use_momentum_unit ERROR: use either MEV or GEV\n";
+	return false;
+    }
+    
+    bool GenEvent::use_length_unit( std::string& newunit ) { 
+        if     ( newunit == "MM" ) return use_length_unit( Units::MM );
+	else if( newunit == "CM" ) return use_length_unit( Units::CM );
+	else std::cerr << "GenEvent::use_length_unit ERROR: use either MEV or GEV\n";
+	return false;
+    }  
+
+} // HepMC
Index: /trunk/Utilities/HepMC/src/GenParticle.cc
===================================================================
--- /trunk/Utilities/HepMC/src/GenParticle.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/GenParticle.cc	(revision 349)
@@ -0,0 +1,252 @@
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999
+// Updated: 07.02.2000 no longer does particle point to ParticleData, 
+//                     but rather it uses an int id which can be looked up
+// particle within an event coming in/out of a vertex
+//////////////////////////////////////////////////////////////////////////
+#include "GenEvent.h"
+#include "GenVertex.h"
+#include "GenParticle.h"
+#include <iomanip>       // needed for formatted output
+
+namespace HepMC {
+
+    GenParticle::GenParticle( void ) :
+	m_momentum(0), m_pdg_id(0), m_status(0), m_flow(this),
+        m_polarization(0), m_production_vertex(0), m_end_vertex(0),
+        m_barcode(0), m_generated_mass(0.)
+    {}
+    //{
+	//s_counter++;
+    //}
+
+    GenParticle::GenParticle( const FourVector& momentum, 
+			int pdg_id, int status, 
+			const Flow& itsflow,
+			const Polarization& polar ) : 
+	m_momentum(momentum), m_pdg_id(pdg_id), m_status(status), m_flow(this),
+	m_polarization(polar), m_production_vertex(0), m_end_vertex(0),
+        m_barcode(0), m_generated_mass(momentum.m())
+    {
+	// Establishing *this as the owner of m_flow is done above,
+	// then we set it equal to the other flow pattern (subtle)
+	set_flow(itsflow);
+	//s_counter++;
+    }
+
+    GenParticle::GenParticle( const GenParticle& inparticle ) : 
+        m_momentum( inparticle.momentum() ),
+	m_pdg_id( inparticle.pdg_id() ), 
+	m_status( inparticle.status() ), 
+	m_flow(this),
+	m_polarization( inparticle.polarization() ),
+	m_production_vertex(0), 
+	m_end_vertex(0), 
+	m_barcode(0), 
+        m_generated_mass( inparticle.generated_mass() )
+    {
+	/// Shallow copy: does not copy the vertex pointers
+	/// (note - impossible to copy vertex pointers which having the vertex
+	///         and particles in/out point-back to one another -- unless you
+	///         copy the entire tree -- which we don't want to do)
+	set_production_vertex_( 0 );
+	set_end_vertex_( 0 );
+	suggest_barcode( inparticle.barcode() );
+	//s_counter++;
+    }
+
+    GenParticle::~GenParticle() {    
+	if ( parent_event() ) parent_event()->remove_barcode(this);
+	//s_counter--;
+    }
+
+    void GenParticle::swap( GenParticle & other)
+    {
+        // if a container has a swap method, use that for improved performance
+        m_momentum.swap( other.m_momentum );
+	std::swap( m_pdg_id, other.m_pdg_id );
+	std::swap( m_status, other.m_status );
+	m_flow.swap( other.m_flow );
+	m_polarization.swap( other.m_polarization );
+	std::swap( m_production_vertex, other.m_production_vertex );
+	std::swap( m_end_vertex, other.m_end_vertex );
+	std::swap( m_barcode, other.m_barcode );
+	std::swap( m_generated_mass, other.m_generated_mass );
+    }
+
+    GenParticle& GenParticle::operator=( const GenParticle& inparticle ) {
+	/// Shallow: does not copy the vertex pointers
+	/// (note - impossible to copy vertex pointers which having the vertex
+	///         and particles in/out point-back to one another -- unless you
+	///         copy the entire tree -- which we don't want to do)
+
+        // best practices implementation
+	GenParticle tmp( inparticle );
+	swap( tmp );
+	return *this;
+    }
+
+    bool GenParticle::operator==( const GenParticle& a ) const {
+	/// consistent with the definition of the copy constructor as a shallow
+	///  constructor,.. this operator does not test the vertex pointers.
+	///  Does not compare barcodes.
+	if ( a.momentum() != this->momentum() ) return false;
+        if ( a.generated_mass() != this->generated_mass() ) return false;
+	if ( a.pdg_id() != this->pdg_id() ) return false;
+	if ( a.status() != this->status() ) return false;
+	if ( a.m_flow != this->m_flow ) return false;
+	if ( a.polarization() != this->polarization() ) return false;
+	return true;
+    }
+
+    bool GenParticle::operator!=( const GenParticle& a ) const {
+	return !( a == *this );
+    }
+
+    void GenParticle::print( std::ostream& ostr ) const {
+	/// Dump this particle's full info to ostr, where by default
+	///  particle.print(); will dump to cout.
+	ostr << "GenParticle: " 
+	     << barcode() << " ID:" << pdg_id()
+	     << " (P,E)=" << momentum().px() << "," << momentum().py() 
+	     << "," << momentum().pz() << "," << momentum().e()
+	     << " Stat:" << status();
+	if ( production_vertex() && production_vertex()->barcode()!=0 ) {
+	    ostr << " PV:" << production_vertex()->barcode();
+	} else ostr << " PV:" << production_vertex();
+	if ( end_vertex() && end_vertex()->barcode()!=0 ) {
+	    ostr << " EV:" << end_vertex()->barcode();
+	} else ostr << " EV:" << end_vertex();
+	ostr << " Pol:" << polarization() << " F:" << m_flow << std::endl;
+    }
+
+    GenEvent* GenParticle::parent_event() const {
+	if ( production_vertex() ) return production_vertex()->parent_event();
+	if ( end_vertex() ) return end_vertex()->parent_event();
+	return 0;
+    }
+
+    void GenParticle::set_production_vertex_( GenVertex* prodvertex )
+    { 
+	GenEvent* its_orig_event = parent_event();
+	m_production_vertex = prodvertex; 
+	GenEvent* its_new_event = parent_event();
+	// Next bit of logic ensures the barcode maps are kept up to date
+	//  in the GenEvent containers.
+	if ( its_orig_event != its_new_event ) {
+	    if ( its_new_event ) its_new_event->set_barcode( this, barcode() );
+	    if ( its_orig_event ) its_orig_event->remove_barcode( this );
+	}
+    }
+
+    void GenParticle::set_end_vertex_( GenVertex* decayvertex ) 
+    { 
+	GenEvent* its_orig_event = parent_event();
+	m_end_vertex = decayvertex;
+	GenEvent* its_new_event = parent_event();
+	if ( its_orig_event != its_new_event ) {
+	    if ( its_new_event ) its_new_event->set_barcode( this, barcode() );
+	    if ( its_orig_event ) its_orig_event->remove_barcode( this );
+	}
+    }	
+
+    bool GenParticle::suggest_barcode( int the_bar_code )
+    {
+	/// allows a barcode to be suggested for this particle.
+	/// In general it is better to let the event pick the barcode for
+	/// you, which is automatic.
+	/// Returns TRUE if the suggested barcode has been accepted (i.e. the
+	///  suggested barcode has not already been used in the event, 
+	///  and so it was used).
+	/// Returns FALSE if the suggested barcode was rejected, or if the
+	///  particle is not yet part of an event, such that it is not yet
+	///  possible to know if the suggested barcode will be accepted).
+	if ( the_bar_code <0 ) {
+	    std::cerr << "GenParticle::suggest_barcode WARNING, particle bar "
+		      << "\n codes MUST be positive integers. Negative  "
+		      << "\n integers are reserved for vertices only. Your "
+		      << "\n suggestion has been rejected." << std::endl;
+	    return false;
+	}
+	bool success = false;
+	if ( parent_event() ) {
+	    success = parent_event()->set_barcode( this, the_bar_code );
+	} else { set_barcode_( the_bar_code ); }
+	return success;
+    }
+
+    /////////////
+    // Static  //
+    /////////////
+    //unsigned int GenParticle::counter() { return s_counter; }
+    //unsigned int GenParticle::s_counter = 0U; 
+
+    /////////////
+    // Friends //
+    /////////////
+
+    /// Dump this particle's full info to ostr
+    std::ostream& operator<<( std::ostream& ostr, const GenParticle& part ) {
+	ostr << " ";
+	ostr.width(9);
+	ostr << part.barcode();
+	ostr.width(9);
+	ostr << part.pdg_id() << " ";
+	ostr.width(9);
+        ostr.precision(2);
+        ostr.setf(std::ios::scientific, std::ios::floatfield);
+	ostr.setf(std::ios_base::showpos);
+	ostr << part.momentum().px() << ",";
+	ostr.width(9);
+        ostr.precision(2);
+	ostr << part.momentum().py() << ",";
+	ostr.width(9);
+        ostr.precision(2);
+	ostr << part.momentum().pz() << ",";
+	ostr.width(9);
+        ostr.precision(2);
+	ostr << part.momentum().e() << " ";
+        ostr.setf(std::ios::fmtflags(0), std::ios::floatfield);
+	ostr.unsetf(std::ios_base::showpos);
+	if ( part.end_vertex() && part.end_vertex()->barcode()!=0 ) {
+	    ostr.width(3);
+	    ostr << part.status() << " ";
+	    ostr.width(9);
+	    ostr << part.end_vertex()->barcode();
+	} else if ( !part.end_vertex() ) {
+	    // There is no valid end_vertex 
+	    // For consistency across different compilers, do not print anything
+	    ostr.width(3);
+	    ostr << part.status();
+	} else {
+	    // In this case the end_vertex does not have a unique 
+	    //   barcode assigned, so we choose instead to print its address
+	    ostr.width(3);
+	    ostr << part.status() << " ";
+	    ostr.width(9);
+	    ostr << (void*)part.end_vertex();
+	}
+	return ostr;
+    }
+
+
+    double  GenParticle::generated_mass() const {
+        return m_generated_mass;
+    }
+
+    void   GenParticle::set_generated_mass( const double & m ) {
+        m_generated_mass = m;
+    }
+
+    /// scale the momentum vector and generated mass 
+    /// this method is only for use by GenEvent
+    void GenParticle::convert_momentum( const double & f ) {
+       m_momentum = FourVector( f*m_momentum.px(),
+                                f*m_momentum.py(),
+                                f*m_momentum.pz(),
+                                f*m_momentum.e() );
+       if( m_generated_mass > 0. ) m_generated_mass = f*m_generated_mass;
+    }
+
+} // HepMC
+
Index: /trunk/Utilities/HepMC/src/GenVertex.cc
===================================================================
--- /trunk/Utilities/HepMC/src/GenVertex.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/GenVertex.cc	(revision 349)
@@ -0,0 +1,925 @@
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999
+// GenVertex within an event
+//////////////////////////////////////////////////////////////////////////
+
+#include "GenParticle.h"
+#include "GenVertex.h"
+#include "GenEvent.h"
+#include "SearchVector.h"
+#include <iomanip>       // needed for formatted output
+
+namespace HepMC {
+
+    GenVertex::GenVertex( const FourVector& position,
+			  int id, const WeightContainer& weights ) 
+	: m_position(position), m_id(id), m_weights(weights), m_event(0),
+	  m_barcode(0)
+    {}
+    //{
+	//s_counter++;
+    //}
+
+    GenVertex::GenVertex( const GenVertex& invertex ) 
+    : m_position( invertex.position() ),
+      m_particles_in(),
+      m_particles_out(),
+      m_id( invertex.id() ),
+      m_weights( invertex.weights() ),
+      m_event(0),
+      m_barcode(0) 
+    {
+	/// Shallow copy: does not copy the FULL list of particle pointers.
+	/// Creates a copy of  - invertex
+	///                    - outgoing particles of invertex, but sets the
+	///                      decay vertex of these particles to NULL
+	///                    - all incoming particles which do not have a
+	///                      creation vertex.
+	/// (i.e. it creates copies of all particles which it owns)
+	/// (note - impossible to copy the FULL list of particle pointers 
+	///         while having the vertex
+	///         and particles in/out point-back to one another -- unless you
+	///         copy the entire tree -- which we don't want to do)
+	//
+	for ( particles_in_const_iterator 
+		  part1 = invertex.particles_in_const_begin();
+	      part1 != invertex.particles_in_const_end(); ++part1 ) {
+	    if ( !(*part1)->production_vertex() ) { 
+		GenParticle* pin = new GenParticle(**part1);
+		add_particle_in(pin);
+	    }
+	}
+	for ( particles_out_const_iterator
+		  part2 = invertex.particles_out_const_begin();
+	      part2 != invertex.particles_out_const_end(); part2++ ) {
+	    GenParticle* pin = new GenParticle(**part2);
+	    add_particle_out(pin);
+	}
+	suggest_barcode( invertex.barcode() );
+	//
+	//s_counter++;
+    }
+    
+    GenVertex::~GenVertex() {
+	//
+	// need to delete any particles previously owned by this vertex
+	if ( parent_event() ) parent_event()->remove_barcode(this);
+	delete_adopted_particles();
+	//s_counter--;
+    }
+
+    void GenVertex::swap( GenVertex & other)
+    {
+        m_position.swap( other.m_position );
+	m_particles_in.swap( other.m_particles_in );
+	m_particles_out.swap( other.m_particles_out );
+	std::swap( m_id, other.m_id );
+	m_weights.swap( other.m_weights );
+	std::swap( m_event, other.m_event );
+	std::swap( m_barcode, other.m_barcode );
+    }
+
+    GenVertex& GenVertex::operator=( const GenVertex& invertex ) {
+	/// Shallow: does not copy the FULL list of particle pointers.
+	/// Creates a copy of  - invertex
+	///                    - outgoing particles of invertex, but sets the
+	///                      decay vertex of these particles to NULL
+	///                    - all incoming particles which do not have a
+	///                      creation vertex.
+	///                    - it does not alter *this's m_event (!)
+	/// (i.e. it creates copies of all particles which it owns)
+	/// (note - impossible to copy the FULL list of particle pointers 
+	///         while having the vertex
+	///         and particles in/out point-back to one another -- unless you
+	///         copy the entire tree -- which we don't want to do)
+	///
+
+        // best practices implementation
+	GenVertex tmp( invertex );
+	swap( tmp );
+	return *this;
+    }
+    
+    bool GenVertex::operator==( const GenVertex& a ) const {
+	/// Returns true if the positions and the particles in the lists of a 
+	///  and this are identical. Does not compare barcodes.
+	/// Note that it is impossible for two vertices to point to the same 
+	///  particle's address, so we need to do more than just compare the
+	///  particle pointers
+	//
+	if ( a.position() !=  this->position() ) return false;
+	// if the size of the inlist differs, return false.
+	if ( a.particles_in_size() !=  this->particles_in_size() ) return false;
+	// if the size of the outlist differs, return false.
+	if ( a.particles_out_size() !=  this->particles_out_size() ) return false;
+	// loop over the inlist and ensure particles are identical
+	//   (only do this if the lists aren't empty - we already know
+	//   if one isn't, then other isn't either!)
+	if ( a.particles_in_const_begin() != a.particles_in_const_end() ) {
+	    for ( GenVertex::particles_in_const_iterator 
+		      ia = a.particles_in_const_begin(),
+		      ib = this->particles_in_const_begin();
+		  ia != a.particles_in_const_end(); ia++, ib++ ){
+		if ( **ia != **ib ) return false;
+	    }
+	}
+	// loop over the outlist and ensure particles are identical
+	//   (only do this if the lists aren't empty - we already know
+	//   if one isn't, then other isn't either!)
+	if ( a.particles_out_const_begin() != a.particles_out_const_end() ) {
+	    for ( GenVertex::particles_out_const_iterator 
+		      ia = a.particles_out_const_begin(),
+		      ib = this->particles_out_const_begin();
+		  ia != a.particles_out_const_end(); ia++, ib++ ){
+		if ( **ia != **ib ) return false;
+	    }
+	}
+	return true;
+    }
+
+    bool GenVertex::operator!=( const GenVertex& a ) const {
+	// Returns true if the positions and lists of a and this are not equal.
+	return !( a == *this );
+    }  
+
+    void GenVertex::print( std::ostream& ostr ) const {
+	if ( barcode()!=0 ) {
+	    if ( position() != FourVector(0,0,0,0) ) {
+	        ostr << "Vertex:";
+		ostr.width(9);
+		ostr << barcode();
+		ostr << " ID:";
+		ostr.width(5);
+		ostr << id();
+		ostr << " (X,cT)=";
+		ostr.width(9);
+                ostr.precision(2);
+                ostr.setf(std::ios::scientific, std::ios::floatfield);
+		ostr.setf(std::ios_base::showpos);
+		ostr << position().x() << ",";
+		ostr.width(9);
+                ostr.precision(2);
+		ostr << position().y() << ",";
+		ostr.width(9);
+                ostr.precision(2);
+		ostr << position().z() << ",";
+		ostr.width(9);
+                ostr.precision(2);
+		ostr << position().t();
+                ostr.setf(std::ios::fmtflags(0), std::ios::floatfield);
+		ostr.unsetf(std::ios_base::showpos);
+	        ostr << std::endl;
+	    } else {
+		ostr << "GenVertex:";
+		ostr.width(9);
+		ostr << barcode();
+		ostr << " ID:";
+		ostr.width(5);
+		ostr << id();
+		ostr << " (X,cT):0";
+	        ostr << std::endl;
+	    }
+	} else {
+	    // If the vertex doesn't have a unique barcode assigned, then
+	    //  we print its memory address instead... so that the
+	    //  print out gives us a unique tag for the particle.
+	    if ( position() != FourVector(0,0,0,0) ) {
+	        ostr << "Vertex:";
+		ostr.width(9);
+		ostr << (void*)this;
+		ostr << " ID:";
+		ostr.width(5);
+		ostr << id();
+		ostr << " (X,cT)=";
+		ostr.width(9);
+                ostr.precision(2);
+                ostr.setf(std::ios::scientific, std::ios::floatfield);
+		ostr.setf(std::ios_base::showpos);
+		ostr << position().x();
+		ostr.width(9);
+                ostr.precision(2);
+		ostr << position().y();
+		ostr.width(9);
+                ostr.precision(2);
+		ostr << position().z();
+		ostr.width(9);
+                ostr.precision(2);
+		ostr << position().t();
+                ostr.setf(std::ios::fmtflags(0), std::ios::floatfield);
+		ostr.unsetf(std::ios_base::showpos);
+	        ostr << std::endl;
+	    } else {
+	        ostr << "GenVertex:";
+		ostr.width(9);
+		ostr << (void*)this;
+		ostr << " ID:";
+		ostr.width(5);
+		ostr << id();
+		ostr << " (X,cT):0";
+	        ostr << std::endl;
+	    }
+	}
+
+	// print the weights if there are any
+	if ( ! weights().empty() ) {
+	    ostr << " Wgts(" << weights().size() << ")=";
+	    for ( WeightContainer::const_iterator wgt = weights().begin();
+		  wgt != weights().end(); wgt++ ) { ostr << *wgt << " "; }
+	    ostr << std::endl;
+	}
+	// print out all the incoming, then outgoing particles
+	for ( particles_in_const_iterator part1 = particles_in_const_begin();
+	      part1 != particles_in_const_end(); part1++ ) {
+	    if ( part1 == particles_in_const_begin() ) {
+		ostr << " I:";
+		ostr.width(2);
+		ostr << m_particles_in.size();
+	    } else { ostr << "     "; }
+	    //(*part1)->print( ostr );  //uncomment for long debugging printout
+	    ostr << **part1 << std::endl;
+	}
+	for ( particles_out_const_iterator part2 = particles_out_const_begin();
+	      part2 != particles_out_const_end(); part2++ ) {
+	    if ( part2 == particles_out_const_begin() ) { 
+		ostr << " O:";
+		ostr.width(2);
+		ostr << m_particles_out.size();
+	    } else { ostr << "     "; }
+	    //(*part2)->print( ostr ); // uncomment for long debugging printout
+	    ostr << **part2 << std::endl;
+	}
+    }
+
+    double GenVertex::check_momentum_conservation() const {
+	/// finds the difference between the total momentum out and the total
+	/// momentum in vectors, and returns the magnitude of this vector
+	/// i.e.         returns | vec{p_in} - vec{p_out} |
+	double sumpx = 0, sumpy = 0, sumpz = 0;
+	for ( particles_in_const_iterator part1 = particles_in_const_begin();
+	      part1 != particles_in_const_end(); part1++ ) {
+	    sumpx   += (*part1)->momentum().px();
+	    sumpy   += (*part1)->momentum().py();
+	    sumpz   += (*part1)->momentum().pz();
+	}
+	for ( particles_out_const_iterator part2 = particles_out_const_begin();
+	      part2 != particles_out_const_end(); part2++ ) {
+	    sumpx   -= (*part2)->momentum().px();
+	    sumpy   -= (*part2)->momentum().py();
+	    sumpz   -= (*part2)->momentum().pz();
+	}
+	return sqrt( sumpx*sumpx + sumpy*sumpy + sumpz*sumpz );
+    }
+
+    void GenVertex::add_particle_in( GenParticle* inparticle ) {
+	if ( !inparticle ) return;
+	// if inparticle previously had a decay vertex, remove it from that
+	// vertex's list
+	if ( inparticle->end_vertex() ) {
+	    inparticle->end_vertex()->remove_particle_in( inparticle );
+	}
+	m_particles_in.push_back( inparticle );
+	inparticle->set_end_vertex_( this );
+    }
+
+    void GenVertex::add_particle_out( GenParticle* outparticle ) {
+	if ( !outparticle ) return;
+	// if outparticle previously had a production vertex,
+	// remove it from that vertex's list
+	if ( outparticle->production_vertex() ) {
+	    outparticle->production_vertex()->remove_particle_out( outparticle );
+	}
+	m_particles_out.push_back( outparticle );
+	outparticle->set_production_vertex_( this );
+    }
+
+    GenParticle* GenVertex::remove_particle( GenParticle* particle ) {
+	/// this finds *particle in the in and/or out list and removes it from
+	///  these lists ... it DOES NOT DELETE THE PARTICLE or its relations.
+	/// you could delete the particle too as follows:
+	///      delete vtx->remove_particle( particle );
+	/// or if the particle has an end vertex, you could:
+	///      delete vtx->remove_particle( particle )->end_vertex();
+	/// which would delete the particle's end vertex, and thus would
+	/// also delete the particle, since the particle would be 
+	/// owned by the end vertex.
+	if ( !particle ) return 0;
+	if ( particle->end_vertex() == this ) {
+	    particle->set_end_vertex_( 0 );
+	    remove_particle_in(particle);
+	}
+	if ( particle->production_vertex() == this ) {
+	    particle->set_production_vertex_(0);
+	    remove_particle_out(particle);
+	}
+	return particle;
+    }
+
+    void GenVertex::remove_particle_in( GenParticle* particle ) {
+	/// this finds *particle in m_particles_in and removes it from that list
+	if ( !particle ) return;
+	m_particles_in.erase( already_in_vector( &m_particles_in, particle ) );
+    }
+
+    void GenVertex::remove_particle_out( GenParticle* particle ) {
+	/// this finds *particle in m_particles_out and removes it from that list
+	if ( !particle ) return;
+	m_particles_out.erase( already_in_vector( &m_particles_out, particle ) );
+    }
+
+    void GenVertex::delete_adopted_particles() {
+	/// deletes all particles which this vertex owns
+	/// to be used by the vertex destructor and operator=
+	//
+	if ( m_particles_out.empty() && m_particles_in.empty() ) return;
+	// 1. delete all outgoing particles which don't have decay vertices.
+	//    those that do become the responsibility of the decay vertex
+	//    and have their productionvertex pointer set to NULL
+	for ( std::vector<GenParticle*>::iterator part1 = m_particles_out.begin();
+	      part1 != m_particles_out.end(); ) {
+	    if ( !(*part1)->end_vertex() ) {
+		delete *(part1++);
+	    } else { 
+		(*part1)->set_production_vertex_(0);
+		++part1;
+	    }
+	}
+	m_particles_out.clear();
+	//
+	// 2. delete all incoming particles which don't have production
+	//    vertices. those that do become the responsibility of the 
+	//    production vertex and have their decayvertex pointer set to NULL
+	for ( std::vector<GenParticle*>::iterator part2 = m_particles_in.begin();
+	      part2 != m_particles_in.end(); ) {
+	    if ( !(*part2)->production_vertex() ) { 
+		delete *(part2++);
+	    } else { 
+		(*part2)->set_end_vertex_(0); 
+		++part2;
+	    }
+	}
+	m_particles_in.clear();
+    }
+
+    bool GenVertex::suggest_barcode( int the_bar_code )
+    {
+	/// allows a barcode to be suggested for this vertex.
+	/// In general it is better to let the event pick the barcode for
+	/// you, which is automatic.
+	/// Returns TRUE if the suggested barcode has been accepted (i.e. the
+	///  suggested barcode has not already been used in the event, 
+	///  and so it was used).
+	/// Returns FALSE if the suggested barcode was rejected, or if the
+	///  vertex is not yet part of an event, such that it is not yet
+	///  possible to know if the suggested barcode will be accepted).
+	if ( the_bar_code >0 ) {
+	    std::cerr << "GenVertex::suggest_barcode WARNING, vertex bar codes"
+		      << "\n MUST be negative integers. Positive integers "
+		      << "\n are reserved for particles only. Your suggestion "
+		      << "\n has been rejected." << std::endl;
+	    return false;
+	}
+	bool success = false;
+	if ( parent_event() ) {
+	    success = parent_event()->set_barcode( this, the_bar_code );
+	} else { set_barcode_( the_bar_code ); }
+	return success;
+    }
+
+    void GenVertex::set_parent_event_( GenEvent* new_evt ) 
+    { 
+	GenEvent* orig_evt = m_event;
+	m_event = new_evt; 
+	//
+	// every time a vertex's parent event changes, the map of barcodes
+	//   in the new and old parent event needs to be modified to 
+	//   reflect this
+	if ( orig_evt != new_evt ) {
+	    if (new_evt) new_evt->set_barcode( this, barcode() );
+	    if (orig_evt) orig_evt->remove_barcode( this );
+	    // we also need to loop over all the particles which are owned by 
+	    //  this vertex, and remove their barcodes from the old event.
+	    for ( particles_in_const_iterator part1=particles_in_const_begin();
+		  part1 != particles_in_const_end(); part1++ ) {
+		if ( !(*part1)->production_vertex() ) { 
+		    if ( orig_evt ) orig_evt->remove_barcode( *part1 );
+		    if ( new_evt ) new_evt->set_barcode( *part1, 
+							 (*part1)->barcode() );
+		}
+	    }
+	    for ( particles_out_const_iterator
+		      part2 = particles_out_const_begin();
+		  part2 != particles_out_const_end(); part2++ ) {
+		    if ( orig_evt ) orig_evt->remove_barcode( *part2 );
+		    if ( new_evt ) new_evt->set_barcode( *part2, 
+							 (*part2)->barcode() );
+	    }
+	}
+    }
+
+    void GenVertex::change_parent_event_( GenEvent* new_evt ) 
+    { 
+	//
+	// this method is for use with swap
+	// particles and vertices have already been exchanged, 
+	// but the backpointer needs to be fixed
+	//GenEvent* orig_evt = m_event;
+	m_event = new_evt; 
+    }
+
+    /////////////
+    // Static  //
+    /////////////
+    //unsigned int GenVertex::counter() { return s_counter; }
+    //unsigned int GenVertex::s_counter = 0; 
+
+    /////////////
+    // Friends //
+    /////////////
+
+    /// send vertex information to ostr for printing
+    std::ostream& operator<<( std::ostream& ostr, const GenVertex& vtx ) {
+	if ( vtx.barcode()!=0 ) ostr << "BarCode " << vtx.barcode();
+	else ostr << "Address " << &vtx;
+	ostr << " (X,cT)=";
+	if ( vtx.position() != FourVector(0,0,0,0)) {
+	    ostr << vtx.position().x() << ","
+		 << vtx.position().y() << ","
+		 << vtx.position().z() << ","
+		 << vtx.position().t();
+	} else { ostr << 0; }
+	ostr << " #in:" << vtx.particles_in_size()
+	     << " #out:" << vtx.particles_out_size();
+	return ostr;
+    }
+
+    /////////////////////////////
+    // edge_iterator           // (protected - for internal use only)
+    /////////////////////////////
+    // If the user wants the functionality of the edge_iterator, he should
+    // use particle_iterator with IteratorRange = family, parents, or children
+    //
+
+    GenVertex::edge_iterator::edge_iterator() : m_vertex(0), m_range(family), 
+	m_is_inparticle_iter(false), m_is_past_end(true)
+    {}
+
+    GenVertex::edge_iterator::edge_iterator( const GenVertex& vtx, 
+					  IteratorRange range ) :
+	m_vertex(&vtx), m_range(family) 
+    {
+	// Note: (26.1.2000) the original version of edge_iterator inheritted
+	//       from set<GenParticle*>::const_iterator() rather than using
+	//       composition as it does now.
+	//       The inheritted version suffered from a strange bug, which
+	//       I have not fully understood --- it only occurred after many
+	//       events were processed and only when I called the delete 
+	//       function on past events. I believe it had something to do with
+	//       the past the end values, which are now robustly coded in this
+	//       version as boolean members.
+	//
+	// default range is family, only other choices are children/parents
+	//    descendants/ancestors not allowed & recasted ot children/parents
+	if ( range == descendants || range == children ) m_range = children;
+	if ( range == ancestors   || range == parents  ) m_range = parents;
+	//
+	if ( m_vertex->m_particles_in.empty() &&
+	     m_vertex->m_particles_out.empty() ) {
+	    // Case: particles_in and particles_out is empty.
+	    m_is_inparticle_iter = false;
+	    m_is_past_end = true;
+	} else if ( m_range == parents && m_vertex->m_particles_in.empty() ){
+	    // Case: particles in is empty and parents is requested.
+	    m_is_inparticle_iter = true;
+	    m_is_past_end = true;
+	} else if ( m_range == children && m_vertex->m_particles_out.empty() ){
+	    // Case: particles out is empty and children is requested.
+	    m_is_inparticle_iter = false;
+	    m_is_past_end = true;
+	} else if ( m_range == children ) {
+	    // Case: particles out is NOT empty, and children is requested
+	    m_set_iter = m_vertex->m_particles_out.begin();
+	    m_is_inparticle_iter = false;
+	    m_is_past_end = false;
+	} else if ( m_range == family && m_vertex->m_particles_in.empty() ) {
+	    // Case: particles in is empty, particles out is NOT empty,
+	    //       and family is requested. Then skip ahead to partilces out.
+	    m_set_iter = m_vertex->m_particles_out.begin();
+	    m_is_inparticle_iter = false;
+	    m_is_past_end = false;
+	} else {
+	    // Normal scenario: start with the first incoming particle
+	    m_set_iter = m_vertex->m_particles_in.begin();
+	    m_is_inparticle_iter = true;
+	    m_is_past_end = false;
+	}
+    }
+
+    GenVertex::edge_iterator::edge_iterator( const edge_iterator& p ) {
+	*this = p;
+    }
+
+    GenVertex::edge_iterator::~edge_iterator() {}
+
+    GenVertex::edge_iterator& GenVertex::edge_iterator::operator=(
+	const edge_iterator& p ) {
+	m_vertex = p.m_vertex;
+	m_range = p.m_range;
+	m_set_iter = p.m_set_iter;
+	m_is_inparticle_iter = p.m_is_inparticle_iter;
+	m_is_past_end = p.m_is_past_end;
+	return *this;
+    }
+
+    GenParticle* GenVertex::edge_iterator::operator*(void) const {
+	if ( !m_vertex || m_is_past_end ) return 0;
+	return *m_set_iter;
+    }
+
+    GenVertex::edge_iterator& GenVertex::edge_iterator::operator++(void){
+	// Pre-fix increment
+	//
+	// increment the set iterator (unless we're past the end value)
+	if ( m_is_past_end ) return *this;
+	++m_set_iter;
+	// handle cases where m_set_iter points past the end
+	if ( m_range == family && m_is_inparticle_iter &&
+	     m_set_iter == m_vertex->m_particles_in.end() ) {
+	    // at the end on in particle set, and range is family, so move to
+	    // out particle set
+	    m_set_iter = m_vertex->m_particles_out.begin();
+	    m_is_inparticle_iter = false;
+	} else if ( m_range == parents && 
+		    m_set_iter == m_vertex->m_particles_in.end() ) {
+	    // at the end on in particle set, and range is parents only, so
+	    // move into past the end state
+	    m_is_past_end = true;
+	    // might as well bail out now
+	    return *this;
+	} 
+	// are we iterating over input or output particles?
+	if( m_is_inparticle_iter ) {
+	    // the following is not else if because we might have range=family
+	    // with an empty particles_in set.	
+	    if ( m_set_iter == m_vertex->m_particles_in.end() ) {
+		//whenever out particles end is reached, go into past the end state
+		m_is_past_end = true;
+	    }
+	} else {
+	    // the following is not else if because we might have range=family
+	    // with an empty particles_out set.	
+	    if ( m_set_iter == m_vertex->m_particles_out.end() ) {
+		//whenever out particles end is reached, go into past the end state
+		m_is_past_end = true;
+	    }
+	}
+	return *this;
+    }
+
+    GenVertex::edge_iterator GenVertex::edge_iterator::operator++(int){
+	// Post-fix increment
+	edge_iterator returnvalue = *this;
+	++*this;
+	return returnvalue;
+    }
+
+    bool GenVertex::edge_iterator::is_parent() const {
+	if ( **this && (**this)->end_vertex() == m_vertex ) return true;
+	return false;
+    }
+
+    bool GenVertex::edge_iterator::is_child() const {
+	if ( **this && (**this)->production_vertex() == m_vertex ) return true;
+	return false;
+    }
+
+    int GenVertex::edges_size( IteratorRange range ) const {
+	if ( range == children ) return m_particles_out.size();
+	if ( range == parents ) return m_particles_in.size();
+	if ( range == family ) return m_particles_out.size()
+				      + m_particles_in.size();
+	return 0;
+    }
+
+    /////////////////////
+    // vertex_iterator //
+    /////////////////////
+    
+    GenVertex::vertex_iterator::vertex_iterator() 
+	: m_vertex(0), m_range(), m_visited_vertices(0), m_it_owns_set(0), 
+	  m_recursive_iterator(0)
+    {}
+
+    GenVertex::vertex_iterator::vertex_iterator( GenVertex& vtx_root,
+					      IteratorRange range )
+	: m_vertex(&vtx_root), m_range(range) 
+    {
+	// standard public constructor
+	//
+	m_visited_vertices = new std::set<const GenVertex*>;
+	m_it_owns_set = 1;
+	m_visited_vertices->insert( m_vertex );
+	m_recursive_iterator = 0;
+	m_edge = m_vertex->edges_begin( m_range );
+	// advance to the first good return value
+	if ( !follow_edge_() &&
+	     m_edge != m_vertex->edges_end( m_range )) ++*this;
+    }
+
+    GenVertex::vertex_iterator::vertex_iterator( GenVertex& vtx_root,
+	IteratorRange range, std::set<const HepMC::GenVertex*>& visited_vertices ) :
+	m_vertex(&vtx_root), m_range(range), 
+	m_visited_vertices(&visited_vertices), m_it_owns_set(0),
+	m_recursive_iterator(0) 
+    {
+	// This constuctor is only to be called internally by this class
+        //   for use with its recursive member pointer (m_recursive_iterator).
+        // Note: we do not need to insert m_vertex_root in the vertex - that is
+        //  the responsibility of this iterator's mother, which is normally
+        //  done just before calling this protected constructor.
+	m_edge = m_vertex->edges_begin( m_range );
+	// advance to the first good return value
+	if ( !follow_edge_() &&
+	     m_edge != m_vertex->edges_end( m_range )) ++*this;
+     }
+
+    GenVertex::vertex_iterator::vertex_iterator( const vertex_iterator& v_iter)
+	: m_vertex(0), m_visited_vertices(0), m_it_owns_set(0), 
+	  m_recursive_iterator(0) 
+    {
+        *this = v_iter;
+    }
+
+    GenVertex::vertex_iterator::~vertex_iterator() {
+	if ( m_recursive_iterator ) delete m_recursive_iterator;
+        if ( m_it_owns_set ) delete m_visited_vertices;
+    }
+
+    GenVertex::vertex_iterator& GenVertex::vertex_iterator::operator=( 
+	const vertex_iterator& v_iter ) 
+    {
+	// Note: when copying a vertex_iterator that is NOT the owner
+	// of its set container, the pointer to the set is copied. Beware!
+	// (see copy_with_own_set() if you want a different set pointed to)
+	// In practise the user never needs to worry
+	// since such iterators are only intended to be used internally.
+	//
+	// destruct data member pointers
+	if ( m_recursive_iterator ) delete m_recursive_iterator;
+	m_recursive_iterator = 0;
+	if ( m_it_owns_set ) delete m_visited_vertices;
+	m_visited_vertices = 0;
+	m_it_owns_set = 0;
+	// copy the target vertex_iterator to this iterator 
+	m_vertex = v_iter.m_vertex;
+	m_range = v_iter.m_range;
+	if ( v_iter.m_it_owns_set ) {
+	    // i.e. this vertex will own its set if v_iter points to any
+	    // vertex set regardless of whether v_iter owns the set or not!
+	    m_visited_vertices = 
+		new std::set<const GenVertex*>(*v_iter.m_visited_vertices);
+	    m_it_owns_set = 1;
+	} else {
+	    m_visited_vertices = v_iter.m_visited_vertices;
+	    m_it_owns_set = 0;
+	}
+	//
+        // Note: m_vertex_root is already included in the set of 
+        //  tv_iter.m_visited_vertices, we do not need to insert it.
+        //
+        m_edge = v_iter.m_edge;
+	copy_recursive_iterator_( v_iter.m_recursive_iterator );
+        return *this;
+    }
+
+    GenVertex* GenVertex::vertex_iterator::operator*(void) const {
+	// de-reference operator
+	//
+	// if this iterator has an iterator_node, then we return the iterator
+        // node.
+        if ( m_recursive_iterator ) return  **m_recursive_iterator;
+	//
+	// an iterator can only return its m_vertex -- any other vertex
+        //  is returned by means of a recursive iterator_node 
+        //  (so this is the only place in the iterator code that a vertex 
+        //   is returned!) 
+        if ( m_vertex ) return m_vertex;
+        return 0;
+    }
+
+    GenVertex::vertex_iterator& GenVertex::vertex_iterator::operator++(void) {
+        // Pre-fix incremental operator
+        //
+        // check for "past the end condition" denoted by m_vertex=0
+        if ( !m_vertex ) return *this;
+	// if at the last edge, move into the "past the end condition"
+	if ( m_edge == m_vertex->edges_end( m_range ) ) {
+	    m_vertex = 0;
+	    return *this;
+	}
+	// check to see if we need to create a new recursive iterator by
+	// following the current edge only if a recursive iterator doesn't
+	// already exist. If a new recursive_iterator is created, return it.
+	if ( follow_edge_() ) {
+              return *this;
+	}
+	//
+        // if a recursive iterator already exists, increment it, and return its
+        // value (unless the recursive iterator has null root_vertex [its
+        // root vertex is set to null if it has already returned its root] 
+        // - in which case we delete it) 
+        // and return the vertex pointed to by the edge.
+        if ( m_recursive_iterator ) {
+            ++(*m_recursive_iterator);
+            if ( **m_recursive_iterator ) {
+		return *this;
+	    } else {
+                delete m_recursive_iterator;
+                m_recursive_iterator = 0;
+	    }
+	}
+	//
+        // increment to the next particle edge
+        ++m_edge;
+	// if m_edge is at the end, then we have incremented through all
+	// edges, and it is time to return m_vertex, which we accomplish
+	// by returning *this
+	if ( m_edge == m_vertex->edges_end( m_range ) ) return *this;
+	// otherwise we follow the current edge by recursively ++ing.
+	return ++(*this);
+    }
+
+    GenVertex::vertex_iterator GenVertex::vertex_iterator::operator++(int) {
+	// Post-fix increment
+        vertex_iterator returnvalue(*this);
+        ++(*this);
+        return returnvalue;
+    }
+
+    void GenVertex::vertex_iterator::copy_with_own_set( 
+	const vertex_iterator& v_iter, 
+	std::set<const HepMC::GenVertex*>& visited_vertices ) {
+	/// intended for internal use only. (use with care!)
+	/// this is the same as the operator= method, but it allows the
+	/// user to specify which set container m_visited_vertices points to.
+	/// in all cases, this vertex will NOT own its set.
+	//
+	// destruct data member pointers
+	if ( m_recursive_iterator ) delete m_recursive_iterator;
+	m_recursive_iterator = 0;
+	if ( m_it_owns_set ) delete m_visited_vertices;
+	m_visited_vertices = 0;
+	m_it_owns_set = false;
+	// copy the target vertex_iterator to this iterator 
+	m_vertex = v_iter.m_vertex;
+	m_range = v_iter.m_range;
+	m_visited_vertices = &visited_vertices;
+	m_it_owns_set = false;
+        m_edge = v_iter.m_edge;
+	copy_recursive_iterator_( v_iter.m_recursive_iterator );
+    }
+
+    GenVertex* GenVertex::vertex_iterator::follow_edge_() {
+	// follows the edge pointed to by m_edge by creating a 
+	// recursive iterator for it.
+	//
+	// if a m_recursive_iterator already exists, 
+        // this routine has nothing to do,
+        // if there's no m_vertex, there's no point following anything, 
+	// also there's no point trying to follow a null edge.
+	if ( m_recursive_iterator || !m_vertex || !*m_edge ) return 0;
+	//
+	// if the range is parents, children, or family (i.e. <= family)
+	// then only the iterator which owns the set is allowed to create
+	// recursive iterators (i.e. recursivity is only allowed to go one
+	// layer deep)
+	if ( m_range <= family && m_it_owns_set == 0 ) return 0;
+	//
+	// M.Dobbs 2001-07-16
+	// Take care of the very special-rare case where a particle might
+	// point to the same vertex for both production and end
+	if ( (*m_edge)->production_vertex() == 
+	     (*m_edge)->end_vertex() ) return 0;
+	//
+	// figure out which vertex m_edge is pointing to
+	GenVertex* vtx = ( m_edge.is_parent() ? 
+			(*m_edge)->production_vertex() :
+			(*m_edge)->end_vertex() );
+        // if the pointed to vertex doesn't exist or has already been visited, 
+        // then return null
+	if ( !vtx || !(m_visited_vertices->insert(vtx).second) ) return 0;
+	// follow that edge by creating a recursive iterator
+	m_recursive_iterator = new vertex_iterator( *vtx, m_range,
+						    *m_visited_vertices);
+	// and return the vertex pointed to by m_recursive_iterator 
+	return **m_recursive_iterator;
+    }
+	
+    void GenVertex::vertex_iterator::copy_recursive_iterator_( 
+	const vertex_iterator* recursive_v_iter ) {
+	// to properly copy the recursive iterator, we need to ensure
+	// the proper set container is transfered ... then do this 
+	// operation .... you guessed it .... recursively!
+	//
+	if ( !recursive_v_iter ) return;
+	m_recursive_iterator = new vertex_iterator();
+	m_recursive_iterator->m_vertex = recursive_v_iter->m_vertex;
+	m_recursive_iterator->m_range = recursive_v_iter->m_range;
+	m_recursive_iterator->m_visited_vertices = m_visited_vertices;
+	m_recursive_iterator->m_it_owns_set = 0;
+	m_recursive_iterator->m_edge = recursive_v_iter->m_edge;
+	m_recursive_iterator->copy_recursive_iterator_( 
+	    recursive_v_iter->m_recursive_iterator );
+    }
+
+    ///////////////////////////////
+    // particle_iterator         //
+    ///////////////////////////////
+
+    GenVertex::particle_iterator::particle_iterator() {}
+
+    GenVertex::particle_iterator::particle_iterator( GenVertex& vertex_root,
+						     IteratorRange range ) {
+	// General Purpose Constructor
+	//
+	if ( range <= family ) {
+	    m_edge = GenVertex::edge_iterator( vertex_root, range ); 
+	} else {
+	    m_vertex_iterator = GenVertex::vertex_iterator(vertex_root, range);
+	    m_edge = GenVertex::edge_iterator( **m_vertex_iterator, 
+						  m_vertex_iterator.range() ); 
+	}
+	advance_to_first_();
+    }
+
+    GenVertex::particle_iterator::particle_iterator( 
+	const particle_iterator& p_iter ){
+	*this = p_iter;
+    }
+
+    GenVertex::particle_iterator::~particle_iterator() {}
+
+    GenVertex::particle_iterator& 
+    GenVertex::particle_iterator::operator=( const particle_iterator& p_iter )
+    {
+	m_vertex_iterator = p_iter.m_vertex_iterator;
+	m_edge = p_iter.m_edge;
+	return *this;
+    }
+
+    GenParticle* GenVertex::particle_iterator::operator*(void) const {
+	return *m_edge;
+    }
+
+    GenVertex::particle_iterator& 
+    GenVertex::particle_iterator::operator++(void) {
+	//Pre-fix increment 
+	//
+	if ( *m_edge ) {
+	    ++m_edge;
+	} else if ( *m_vertex_iterator ) {	// !*m_edge is implicit
+	    // past end of edge, but still have more vertices to visit
+	    // increment the vertex, checking that the result is valid
+	    if ( !*(++m_vertex_iterator) ) return *this;
+	    m_edge = GenVertex::edge_iterator( **m_vertex_iterator, 
+						  m_vertex_iterator.range() ); 
+	} else {	// !*m_edge and !*m_vertex_iterator are implicit
+	    // past the end condition: do nothing
+	    return *this;
+	}
+	advance_to_first_();
+	return *this;
+    }
+
+    GenVertex::particle_iterator GenVertex::particle_iterator::operator++(int){
+	//Post-fix increment
+	particle_iterator returnvalue(*this);
+	++(*this);
+	return returnvalue;
+    }
+
+    GenParticle* GenVertex::particle_iterator::advance_to_first_() {
+	/// if the current edge is not a suitable return value ( because
+	/// it is a parent of the vertex root that itself belongs to a 
+	/// different vertex ) it advances to the first suitable return value 
+	if ( !*m_edge ) return *(++*this);
+	// if the range is relatives, we need to uniquely assign each particle
+	// to a single vertex so as to guarantee particles are returned
+	// exactly once.
+	if ( m_vertex_iterator.range() == relatives &&
+	     m_edge.is_parent() && 
+	     (*m_edge)->production_vertex() ) return *(++*this);
+	return *m_edge;
+    }
+
+    /// scale the position vector
+    /// this method is only for use by GenEvent
+    /// convert_position assumes that 4th component of the position vector 
+    /// is ctau rather than time and has units of length-time
+    void GenVertex::convert_position( const double& f ) {
+        m_position = FourVector( f*m_position.x(),
+                                 f*m_position.y(),
+                                 f*m_position.z(),
+                                 f*m_position.t() );
+   }
+
+} // HepMC
Index: /trunk/Utilities/HepMC/src/IO_Ascii.cc
===================================================================
--- /trunk/Utilities/HepMC/src/IO_Ascii.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/IO_Ascii.cc	(revision 349)
@@ -0,0 +1,348 @@
+//--------------------------------------------------------------------------
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, January 2000
+// event input/output in ascii format for machine reading
+//////////////////////////////////////////////////////////////////////////
+
+#include "IO_Ascii.h"
+#include "GenEvent.h"
+#include "ParticleDataTable.h"
+#include "CommonIO.h"
+#include "Version.h"
+
+namespace HepMC {
+
+    IO_Ascii::IO_Ascii( const char* filename, std::ios::openmode mode ) 
+	: m_mode(mode), m_file(filename, mode), m_finished_first_event_io(0),
+          m_common_io()  
+    {
+        std::cout << "-------------------------------------------------------" << std::endl;
+        std::cout << "Use of HepMC/IO_Ascii is deprecated" << std::endl;
+        std::cout << "-------------------------------------------------------" << std::endl;
+	if ( (m_mode&std::ios::out && m_mode&std::ios::in) ||
+	     (m_mode&std::ios::app && m_mode&std::ios::in) ) {
+	    std::cerr << "IO_Ascii::IO_Ascii Error, open of file requested "
+		      << "of input AND output type. Not allowed. Closing file."
+		      << std::endl;
+	    m_file.close();
+	    return;
+	}
+	// precision 16 (# digits following decimal point) is the minimum that
+	//  will capture the full information stored in a double
+	m_file.precision(16);
+	// we use decimal to store integers, because it is smaller than hex!
+	m_file.setf(std::ios::dec,std::ios::basefield);
+	m_file.setf(std::ios::scientific,std::ios::floatfield);
+    }
+
+    IO_Ascii::~IO_Ascii() {
+	write_end_listing();
+	m_file.close();
+    }
+
+    void IO_Ascii::print( std::ostream& ostr ) const { 
+	ostr << "IO_Ascii: unformated ascii file IO for machine reading.\n" 
+	     << "\tFile openmode: " << m_mode 
+	     << " file state: " << m_file.rdstate()
+	     << " bad:" << (m_file.rdstate()&std::ios::badbit)
+	     << " eof:" << (m_file.rdstate()&std::ios::eofbit)
+	     << " fail:" << (m_file.rdstate()&std::ios::failbit)
+	     << " good:" << (m_file.rdstate()&std::ios::goodbit) << std::endl;
+    }
+
+    void IO_Ascii::write_event( const GenEvent* evt ) {
+	/// Writes evt to m_file. It does NOT delete the event after writing.
+	//
+	// check the state of m_file is good, and that it is in output mode
+	if ( !evt || !m_file ) return;
+	if ( !(m_mode&std::ios::out) ) {
+	    std::cerr << "HepMC::IO_Ascii::write_event "
+		      << " attempt to write to input file." << std::endl;
+	    return;
+	}
+	//
+	// write event listing key before first event only.
+	if ( !m_finished_first_event_io ) {
+	    m_finished_first_event_io = 1;
+	    m_file << "\n" << "HepMC::Version " << versionName();
+	    m_file << "\n" << "HepMC::IO_Ascii-START_EVENT_LISTING\n";
+	}
+	//
+	// output the event data including the number of primary vertices
+	//  and the total number of vertices
+	std::vector<long int> random_states = evt->random_states();
+	m_file << 'E';
+	output( evt->event_number() );
+	output( evt->event_scale() );
+	output( evt->alphaQCD() );
+	output( evt->alphaQED() );
+	output( evt->signal_process_id() );
+	output(   ( evt->signal_process_vertex() ?
+		    evt->signal_process_vertex()->barcode() : 0 )   );
+	output( evt->vertices_size() ); // total number of vertices.
+	output( (int)random_states.size() );
+	for ( std::vector<long int>::iterator rs = random_states.begin(); 
+	      rs != random_states.end(); ++rs ) {
+	    output( *rs );
+	}
+	output( (int)evt->weights().size() );
+	for ( WeightContainer::const_iterator w = evt->weights().begin(); 
+	      w != evt->weights().end(); ++w ) {
+	    output( *w );
+	}
+	output('\n');
+	//
+	// Output all of the vertices - note there is no real order.
+	for ( GenEvent::vertex_const_iterator v = evt->vertices_begin();
+	      v != evt->vertices_end(); ++v ) {
+	    write_vertex( *v );
+	}
+    }
+
+    bool IO_Ascii::fill_next_event( GenEvent* evt ){
+	//
+	//
+	// test that evt pointer is not null
+	if ( !evt ) {
+	    std::cerr 
+		<< "IO_Ascii::fill_next_event error - passed null event." 
+		<< std::endl;
+	    return false;
+	}
+	// check the state of m_file is good, and that it is in input mode
+	if ( !m_file ) return false;
+	if ( !(m_mode&std::ios::in) ) {
+	    std::cerr << "HepMC::IO_Ascii::fill_next_event "
+		      << " attempt to read from output file." << std::endl;
+	    return false;
+	}
+	//
+	// search for event listing key before first event only.
+	//
+	// skip through the file just after first occurence of the start_key
+	int iotype;
+	if ( !m_finished_first_event_io ) {
+	    m_file.seekg( 0 ); // go to position zero in the file.
+	    iotype = m_common_io.find_file_type(m_file);
+	    if( iotype != ascii ) {
+		std::cerr << "IO_Ascii::fill_next_event start key not found "
+			  << "setting badbit." << std::endl;
+		m_file.clear(std::ios::badbit); 
+		return false;
+	    }
+	    m_finished_first_event_io = 1;
+	}
+	//
+	// test to be sure the next entry is of type "E" then ignore it
+	if ( !m_file ) { 
+		std::cerr << "IO_Ascii::fill_next_event end of stream found "
+			  << "setting badbit." << std::endl;
+		m_file.clear(std::ios::badbit); 
+		return false;
+	}
+	if ( !m_file || m_file.peek()!='E' ) { 
+	    // if the E is not the next entry, then check to see if it is
+	    // the end event listing key - if yes, search for another start key
+	    if ( m_common_io.find_end_key(m_file) ) {
+		iotype = m_common_io.find_file_type(m_file);
+		if( iotype != ascii ) {
+		    // this is the only case where we set an EOF state
+		    m_file.clear(std::ios::eofbit);
+		    return false;
+		}
+	    } else {
+		std::cerr << "IO_Ascii::fill_next_event end key not found "
+			  << "setting badbit." << std::endl;
+		m_file.clear(std::ios::badbit); 
+		return false;
+	    }
+	} 
+	m_file.ignore();
+	// call the read method
+	return m_common_io.read_io_ascii(&m_file, evt);
+    }
+
+    void IO_Ascii::write_comment( const std::string comment ) {
+	// check the state of m_file is good, and that it is in output mode
+	if ( !m_file ) return;
+	if ( !(m_mode&std::ios::out) ) {
+	    std::cerr << "HepMC::IO_Ascii::write_particle_data_table "
+		      << " attempt to write to input file." << std::endl;
+	    return;
+	}
+	// write end of event listing key if events have already been written
+	write_end_listing();
+	// insert the comment key before the comment
+	m_file << "\n" << "HepMC::IO_Ascii-COMMENT\n";
+	m_file << comment << std::endl;
+    }
+
+    void IO_Ascii::write_particle_data_table( const ParticleDataTable* pdt) {
+	//
+	// check the state of m_file is good, and that it is in output mode
+	if ( !m_file ) return;
+	if ( !(m_mode&std::ios::out) ) {
+	    std::cerr << "HepMC::IO_Ascii::write_particle_data_table "
+		      << " attempt to write to input file." << std::endl;
+	    return;
+	}
+	// write end of event listing key if events have already been written
+	write_end_listing();
+	//
+	m_file << "\n" << "HepMC::IO_Ascii-START_PARTICLE_DATA\n";
+        for ( ParticleDataTable::const_iterator pd = pdt->begin(); 
+	      pd != pdt->end(); pd++ ) {
+	    write_particle_data( pd->second );
+        }
+	m_file << "HepMC::IO_Ascii-END_PARTICLE_DATA\n" << std::flush;
+    }
+
+    bool IO_Ascii::fill_particle_data_table( ParticleDataTable* pdt ) {
+	//
+	// test that pdt pointer is not null
+	if ( !pdt ) {
+	    std::cerr 
+		<< "IO_Ascii::fill_particle_data_table - passed null table." 
+		<< std::endl;
+	    return false;
+	}
+	//
+	// check the state of m_file is good, and that it is in input mode
+	if ( !m_file ) return false;
+	if ( !m_mode&std::ios::in ) {
+	    std::cerr << "HepMC::IO_Ascii::fill_particle_data_table "
+		      << " attempt to read from output file." << std::endl;
+	    return false;
+	}
+	// position to beginning of file
+	int initial_file_position = m_file.tellg();
+	std::ios::iostate initial_state = m_file.rdstate();
+	m_file.seekg( 0 );
+	// skip through the file just after first occurence of the start_key
+	int iotype;
+	iotype = m_common_io.find_file_type(m_file);
+	if( iotype != ascii_pdt ) {
+	    m_file.seekg( initial_file_position );
+	    std::cerr << "IO_Ascii::fill_particle_data_table start key not  "
+		      << "found setting badbit." << std::endl;
+	    m_file.clear(std::ios::badbit); 
+	    return false;
+	}
+	//
+	pdt->set_description("Read with IO_Ascii");
+	m_common_io.read_io_particle_data_table( &m_file, pdt );
+	//
+	// check for the end event listing key
+	iotype =  m_common_io.find_end_key(m_file);
+	if( iotype != ascii_pdt ) {
+	    std::cerr << "IO_Ascii::fill_particle_data_table end key not  "
+		      << "found setting badbit." << std::endl;
+	    m_file.clear(std::ios::badbit);
+	}
+	// put the file back into its original state and position
+	m_file.clear( initial_state );
+	m_file.seekg( initial_file_position );
+	return true;
+    }
+
+    void IO_Ascii::write_vertex( GenVertex* v ) {
+	// assumes mode has already been checked
+	if ( !v || !m_file ) {
+	    std::cerr << "IO_Ascii::write_vertex !v||!m_file, "
+		      << "v="<< v << " setting badbit" << std::endl;
+	    m_file.clear(std::ios::badbit); 
+	    return;
+	}
+	// First collect info we need
+	// count the number of orphan particles going into v
+	int num_orphans_in = 0;
+	for ( GenVertex::particles_in_const_iterator p1
+		  = v->particles_in_const_begin();
+	      p1 != v->particles_in_const_end(); ++p1 ) {
+	    if ( !(*p1)->production_vertex() ) ++num_orphans_in;
+	}
+	//
+	m_file << 'V';
+	output( v->barcode() ); // v's unique identifier
+	output( v->id() );
+	output( v->position().x() );
+	output( v->position().y() );
+	output( v->position().z() );
+	output( v->position().t() );
+	output( num_orphans_in );
+	output( (int)v->particles_out_size() );
+	output( (int)v->weights().size() );
+	for ( WeightContainer::iterator w = v->weights().begin(); 
+	      w != v->weights().end(); ++w ) {
+	    output( *w );
+	}
+	output('\n');
+	for ( GenVertex::particles_in_const_iterator p2 
+		  = v->particles_in_const_begin();
+	      p2 != v->particles_in_const_end(); ++p2 ) {
+	    if ( !(*p2)->production_vertex() ) {
+		write_particle( *p2 );
+	    }
+	}
+	for ( GenVertex::particles_out_const_iterator p3 
+		  = v->particles_out_const_begin();
+	      p3 != v->particles_out_const_end(); ++p3 ) {
+	    write_particle( *p3 );
+	}
+    }
+
+    void IO_Ascii::write_particle( GenParticle* p ) {
+	// assumes mode has already been checked
+	if ( !p || !m_file ) {
+	    std::cerr << "IO_Ascii::write_particle !p||!m_file, "
+		      << "p="<< p << " setting badbit" << std::endl;
+	    m_file.clear(std::ios::badbit); 
+	    return;
+	}
+	m_file << 'P';
+	output( p->barcode() );
+	output( p->pdg_id() );
+	output( p->momentum().px() );
+	output( p->momentum().py() );
+	output( p->momentum().pz() );
+	output( p->momentum().e() );
+	output( p->status() );
+	output( p->polarization().theta() );
+	output( p->polarization().phi() );
+	// since end_vertex is oftentimes null, this CREATES a null vertex
+	// in the map
+	output(   ( p->end_vertex() ? p->end_vertex()->barcode() : 0 )  );
+	m_file << ' ' << p->flow() << "\n";
+    }
+
+    void IO_Ascii::write_particle_data( const ParticleData* pdata ) {
+	// assumes mode has already been checked
+	if ( !pdata || !m_file ) {
+	    std::cerr << "IO_Ascii::write_vertex !pdata||!m_file, "
+		      << "pdata="<< pdata << " setting badbit" << std::endl;
+	    m_file.clear(std::ios::badbit); 
+	    return;
+	}
+	m_file << 'D';
+	output( pdata->pdg_id() );
+	output( pdata->charge() );
+	output( pdata->mass() );
+	output( pdata->clifetime() );
+	output( (int)(pdata->spin()*2.+.1) );
+	// writes the first 21 characters starting with 0
+	m_file << " " << pdata->name().substr(0,21) << "\n";
+    }
+
+    bool IO_Ascii::write_end_listing() {
+    	if ( m_finished_first_event_io && m_mode&std::ios::out ) {
+	    m_common_io.write_IO_Ascii_End(m_file);
+	    m_file << std::flush;
+	    m_finished_first_event_io = 0;
+	    return true;
+	}
+	return false;
+    }
+	
+} // HepMC
+
Index: /trunk/Utilities/HepMC/src/IO_AsciiParticles.cc
===================================================================
--- /trunk/Utilities/HepMC/src/IO_AsciiParticles.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/IO_AsciiParticles.cc	(revision 349)
@@ -0,0 +1,223 @@
+//--------------------------------------------------------------------------
+
+//////////////////////////////////////////////////////////////////////////////
+// Mikhail.Kirsanov@Cern.CH, 2006
+// event input/output in ascii format for eye and machine reading
+//
+// for arguments mostly similar to IO_Ascii. Special value of
+// argument filename in constructor: if it is "cout" the output is to std::cout
+//////////////////////////////////////////////////////////////////////////////
+
+#include "IO_AsciiParticles.h"
+#include "GenEvent.h"
+#include "ParticleDataTable.h"
+#include "Version.h"
+
+namespace HepMC {
+
+  IO_AsciiParticles::IO_AsciiParticles( const char* filename, std::ios::openmode mode ) 
+  : m_precision(2),
+    m_mode(mode), m_finished_first_event_io(0)
+  {
+    if(std::string(filename) == std::string("cout")) {
+      m_outstream = &(std::cout);
+      m_file = 0;
+    } else {
+      m_file = new std::fstream(filename, mode);
+      m_outstream = m_file;
+      if ( (m_mode&std::ios::out && m_mode&std::ios::in) ||
+           (m_mode&std::ios::app && m_mode&std::ios::in) ) {
+	    std::cerr << "IO_AsciiParticles::IO_AsciiParticles Error, open of file requested "
+                  << "of input AND output type. Not allowed. Closing file."
+                  << std::endl;
+        m_file->close();
+        delete m_file;
+	return;
+      }
+    }
+    // precision 16 (# digits following decimal point) is the minimum that
+    // will capture the full information stored in a double
+    // with precision <= 2 the width of output will be < 80 characters
+    m_outstream->precision(m_precision);
+    // we use decimal to store integers, because it is smaller than hex!
+    m_outstream->setf(std::ios::dec,std::ios::basefield);
+    m_outstream->setf(std::ios::scientific,std::ios::floatfield);
+  }
+
+  IO_AsciiParticles::~IO_AsciiParticles() {
+    if(m_file) {
+       m_file->close();
+       delete m_file;
+    }
+  }
+
+  void IO_AsciiParticles::print( std::ostream& ostr ) const { 
+    ostr << "IO_AsciiParticles: formated ascii file IO for eye and machine reading.\n" 
+         << "\tFile openmode: " << m_mode 
+         << " file state: " << m_outstream->rdstate()
+         << " bad:" << (m_outstream->rdstate()&std::ios::badbit)
+         << " eof:" << (m_outstream->rdstate()&std::ios::eofbit)
+         << " fail:" << (m_outstream->rdstate()&std::ios::failbit)
+         << " good:" << (m_outstream->rdstate()&std::ios::goodbit) << std::endl;
+  }
+
+  void IO_AsciiParticles::write_event( const GenEvent* evt ) {
+  // Writes evt to m_outstream. It does NOT delete the event after writing.
+    //
+	// check the state of m_outstream is good, and that it is in output mode
+	if ( !evt || !m_outstream ) return;
+	if ( !(m_mode&std::ios::out) ) {
+	    std::cerr << "HepMC::IO_AsciiParticles::write_event "
+		      << " attempt to write to input file." << std::endl;
+	    return;
+	}
+	//
+	// write event listing key before first event only.
+	if ( !m_finished_first_event_io ) {
+	    m_finished_first_event_io = 1;
+        *m_outstream << "0 Run  HepMC::IO_AsciiParticles eye-readable events output"
+                     << std::endl;
+        *m_outstream << "#      HepMC::Version " << versionName() << std::endl;
+        *m_outstream <<
+    "  #  stat pdg  moth1   px        py         pz     energy    mass      eta"
+                     << std::endl;
+	}
+	//
+	// output the event data
+	std::vector<long int> random_states = evt->random_states();
+	*m_outstream << evt->event_number() << " Event" << std::endl;
+#if 0
+	*m_outstream << " " << evt->event_scale();
+	output( evt->alphaQCD() );
+	output( evt->alphaQED() );
+	output( evt->signal_process_id() );
+	output(   ( evt->signal_process_vertex() ?
+		    evt->signal_process_vertex()->barcode() : 0 )   );
+	output( evt->vertices_size() ); // total number of vertices.
+	output( (int)random_states.size() );
+	for ( std::vector<long int>::iterator rs = random_states.begin(); 
+	      rs != random_states.end(); ++rs ) {
+	    output( *rs );
+	}
+	output( (int)evt->weights().size() );
+	for ( WeightContainer::const_iterator w = evt->weights().begin(); 
+	      w != evt->weights().end(); ++w ) {
+	    output( *w );
+	}
+	output('\n');
+#endif
+	//
+    int nparticles=0, imoth=0, ip=0, istati;
+    double xmassi, etai;
+    *m_outstream << evt->particles_size() << " particles" << std::endl;
+    GenVertex* orig;
+    for(HepMC::GenEvent::particle_const_iterator part = evt->particles_begin();
+        part != evt->particles_end(); ++part ) {
+      //if( (*part)->status() != 1 ) continue;
+      nparticles++;
+      ip++;
+      istati = (*part)->status();
+      if( (*part)->end_vertex() && istati == 1) {
+        std::cout << "final particle with end vertex!" << std::endl;
+        istati = -100;
+      }
+      imoth=0;
+      orig = (*part)->production_vertex();
+      if(orig) {
+        imoth = 0;
+        bool ifound=false;
+        for(HepMC::GenEvent::particle_const_iterator part1 =
+                                                     evt->particles_begin();
+                                                     part1 != part; part1++ ) {
+          imoth++;
+          if( (*part1)->end_vertex() == orig ) { ifound = true; break; }
+        }
+        if(!ifound) imoth = 0;
+      }
+
+      m_outstream->width(4);
+      *m_outstream << ip << " ";
+
+      m_outstream->width(3);
+      *m_outstream << istati << " ";
+
+      m_outstream->width(5);
+      *m_outstream << (*part)->pdg_id() << " ";
+
+      m_outstream->width(3);
+      *m_outstream << imoth << "  ";
+
+      if((*part)->momentum().px() >= 0.) *m_outstream << " ";
+      *m_outstream << (*part)->momentum().px() << " ";
+      if((*part)->momentum().py() >= 0.) *m_outstream << " ";
+      *m_outstream << (*part)->momentum().py() << " ";
+      if((*part)->momentum().pz() >= 0.) *m_outstream << " ";
+      *m_outstream << (*part)->momentum().pz() << " "
+             << (*part)->momentum().e() << " ";
+
+      xmassi = (*part)->generatedMass();
+      if(fabs(xmassi) < 0.0001) xmassi =0.;
+      m_outstream->setf(std::ios::fixed);
+      m_outstream->precision(3);
+      m_outstream->width(8);
+      *m_outstream << xmassi << " ";
+      m_outstream->setf(std::ios::scientific,std::ios::floatfield);
+      m_outstream->precision(m_precision);
+
+      m_outstream->setf(std::ios::fixed);
+      m_outstream->precision(3);
+      m_outstream->width(6);
+      etai = (*part)->momentum().eta();
+      if(etai > 999.)etai = 999.;
+      if(etai < -999.)etai = -999.;
+      *m_outstream << etai << std::endl;
+      m_outstream->setf(std::ios::scientific,std::ios::floatfield);
+      m_outstream->precision(m_precision);
+
+    }
+  }
+
+  bool IO_AsciiParticles::fill_next_event( GenEvent* evt ){
+	//
+	//
+	// test that evt pointer is not null
+	if ( !evt ) {
+	    std::cerr 
+		<< "IO_AsciiParticles::fill_next_event error - passed null event." 
+		<< std::endl;
+	    return false;
+	}
+	// check the state of m_outstream is good, and that it is in input mode
+	if ( !m_file )
+      std::cerr << "HepMC::IO_AsciiParticles::fill_next_event "
+                << " no file for input" << std::endl;
+	if ( !(m_mode&std::ios::in) ) {
+	    std::cerr << "HepMC::IO_AsciiParticles::fill_next_event "
+		      << " attempt to read from output file" << std::endl;
+	    return false;
+	}
+    std::cerr << "IO_AsciiParticles input is not yet implemented" << std::endl;
+    return false;
+  }
+
+  void IO_AsciiParticles::write_comment( const std::string comment ) {
+	// check the state of *m_outstream is good, and that it is in output mode
+	if ( !m_outstream ) return;
+	if ( !(m_mode&std::ios::out) ) {
+	    std::cerr << "HepMC::IO_AsciiParticles::write_particle_data_table "
+		      << " attempt to write to input file." << std::endl;
+	    return;
+	}
+	// write end of event listing key if events have already been written
+	write_end_listing();
+	// insert the comment key before the comment
+	*m_outstream << "\n" << "HepMC::IO_AsciiParticles-COMMENT\n";
+	*m_outstream << comment << std::endl;
+  }
+
+  bool IO_AsciiParticles::write_end_listing() {
+	return false;
+  }
+
+} // HepMC
+
Index: /trunk/Utilities/HepMC/src/IO_GenEvent.cc
===================================================================
--- /trunk/Utilities/HepMC/src/IO_GenEvent.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/IO_GenEvent.cc	(revision 349)
@@ -0,0 +1,548 @@
+//--------------------------------------------------------------------------
+
+//////////////////////////////////////////////////////////////////////////
+// garren@fnal.gov, July 2006
+// event input/output in ascii format for machine reading
+// IO_GenEvent format contains HeavyIon and PdfInfo classes
+//////////////////////////////////////////////////////////////////////////
+
+#include "IO_GenEvent.h"
+#include "GenEvent.h"
+#include "ParticleDataTable.h"
+#include "HeavyIon.h"
+#include "PdfInfo.h"
+#include "CommonIO.h"
+#include "Version.h"
+
+namespace HepMC {
+
+    IO_GenEvent::IO_GenEvent( const std::string& filename, std::ios::openmode mode ) 
+    : m_mode(mode), 
+      m_file(filename.c_str(), mode), 
+      m_ostr(0),
+      m_istr(0),
+      m_iostr(0),
+      m_finished_first_event_io(false),
+      m_have_file(false),
+      m_common_io()
+    {
+	if ( (m_mode&std::ios::out && m_mode&std::ios::in) ||
+	     (m_mode&std::ios::app && m_mode&std::ios::in) ) {
+	    std::cerr << "IO_GenEvent::IO_GenEvent Error, open of file requested "
+		      << "of input AND output type. Not allowed. Closing file."
+		      << std::endl;
+	    m_file.close();
+	    return;
+	}
+	// precision 16 (# digits following decimal point) is the minimum that
+	//  will capture the full information stored in a double
+	m_file.precision(16);
+	// we use decimal to store integers, because it is smaller than hex!
+	m_file.setf(std::ios::dec,std::ios::basefield);
+	m_file.setf(std::ios::scientific,std::ios::floatfield);
+	// now we set the streams
+	m_iostr = &m_file;
+	if ( m_mode&std::ios::in ) {
+	    m_istr = &m_file;
+	    m_ostr = NULL;
+	}
+	if ( m_mode&std::ios::out ) {
+	    m_ostr = &m_file;
+	    m_istr = NULL;
+	}
+	m_have_file = true;
+    }
+
+
+    IO_GenEvent::IO_GenEvent( std::istream & istr ) 
+    : m_ostr(0),
+      m_istr(&istr),
+      m_iostr(&istr),
+      m_finished_first_event_io(false),
+      m_have_file(false),
+      m_common_io()
+    { }
+
+    IO_GenEvent::IO_GenEvent( std::ostream & ostr )
+    : m_ostr(&ostr),
+      m_istr(0),
+      m_iostr(&ostr),
+      m_finished_first_event_io(false),
+      m_have_file(false),
+      m_common_io()
+    {
+	// precision 16 (# digits following decimal point) is the minimum that
+	//  will capture the full information stored in a double
+	m_ostr->precision(16);
+	// we use decimal to store integers, because it is smaller than hex!
+	m_ostr->setf(std::ios::dec,std::ios::basefield);
+	m_ostr->setf(std::ios::scientific,std::ios::floatfield);
+    }
+
+    IO_GenEvent::~IO_GenEvent() {
+	write_end_listing();
+	if(m_have_file) m_file.close();
+    }
+
+    void IO_GenEvent::use_input_units( Units::MomentumUnit mom, Units::LengthUnit len ) {
+	m_common_io.use_input_units(mom,len);
+    }
+
+    void IO_GenEvent::print( std::ostream& ostr ) const { 
+	ostr << "IO_GenEvent: unformated ascii file IO for machine reading.\n"; 
+	if(m_have_file)    ostr  << "\tFile openmode: " << m_mode ;
+	ostr << " stream state: " << m_ostr->rdstate()
+	     << " bad:" << (m_ostr->rdstate()&std::ios::badbit)
+	     << " eof:" << (m_ostr->rdstate()&std::ios::eofbit)
+	     << " fail:" << (m_ostr->rdstate()&std::ios::failbit)
+	     << " good:" << (m_ostr->rdstate()&std::ios::goodbit) << std::endl;
+    }
+
+    void IO_GenEvent::write_event( const GenEvent* evt ) {
+	/// Writes evt to output stream. It does NOT delete the event after writing.
+	//
+	// make sure the state is good, and that it is in output mode
+	if ( !evt  ) return;
+	if ( m_ostr == NULL ) {
+	    std::cerr << "HepMC::IO_GenEvent::write_event "
+		      << " attempt to write to input file." << std::endl;
+	    return;
+	}
+	//
+	// write event listing key before first event only.
+	if ( !m_finished_first_event_io ) {
+	    m_finished_first_event_io = 1;
+	    *m_ostr << "\n" << "HepMC::Version " << versionName();
+	    *m_ostr << "\n";
+	    m_common_io.write_IO_GenEvent_Key(*m_ostr);
+	}
+	//
+	// output the event data including the number of primary vertices
+	//  and the total number of vertices
+	std::vector<long> random_states = evt->random_states();
+	*m_ostr << 'E';
+	output( evt->event_number() );
+	output( evt->mpi() );
+	output( evt->event_scale() );
+	output( evt->alphaQCD() );
+	output( evt->alphaQED() );
+	output( evt->signal_process_id() );
+	output(   ( evt->signal_process_vertex() ?
+		    evt->signal_process_vertex()->barcode() : 0 )   );
+	output( evt->vertices_size() ); // total number of vertices.
+	write_beam_particles( evt->beam_particles() );
+	output( (int)random_states.size() );
+	for ( std::vector<long>::iterator rs = random_states.begin(); 
+	      rs != random_states.end(); ++rs ) {
+	    output( *rs );
+	}
+	output( (int)evt->weights().size() );
+	for ( WeightContainer::const_iterator w = evt->weights().begin(); 
+	      w != evt->weights().end(); ++w ) {
+	    output( *w );
+	}
+	output('\n');
+	write_unit_info( evt );
+	write_heavy_ion( evt->heavy_ion() );
+	write_pdf_info( evt->pdf_info() );
+	//
+	// Output all of the vertices - note there is no real order.
+	for ( GenEvent::vertex_const_iterator v = evt->vertices_begin();
+	      v != evt->vertices_end(); ++v ) {
+	    write_vertex( *v );
+	}
+    }
+
+    bool IO_GenEvent::fill_next_event( GenEvent* evt ){
+	//
+	//
+	// test that evt pointer is not null
+	if ( !evt ) {
+	    std::cerr 
+		<< "IO_GenEvent::fill_next_event error - passed null event." 
+		<< std::endl;
+	    return false;
+	}
+	// make sure the stream is good, and that it is in input mode
+	if ( !(*m_istr) ) return false;
+	if ( !m_istr ) {
+	    std::cerr << "HepMC::IO_GenEvent::fill_next_event "
+		      << " attempt to read from output file." << std::endl;
+	    return false;
+	}
+	//
+	// search for event listing key before first event only.
+	//
+	// skip through the file just after first occurence of the start_key
+	int iotype = 0;
+	if ( !m_finished_first_event_io ) {
+	    iotype = m_common_io.find_file_type(*m_istr);
+	    if( iotype <= 0 ) {
+		std::cerr << "IO_GenEvent::fill_next_event start key not found "
+			  << "setting badbit." << std::endl;
+		m_istr->clear(std::ios::badbit); 
+		return false;
+	    }
+	    m_finished_first_event_io = 1;
+	}
+	//
+	// test to be sure the next entry is of type "E" then ignore it
+	if ( !(*m_istr) ) { 
+		std::cerr << "IO_GenEvent::fill_next_event end of stream found "
+			  << "setting badbit." << std::endl;
+		m_istr->clear(std::ios::badbit); 
+		return false;
+	}
+	if ( !(*m_istr) || m_istr->peek()!='E' ) { 
+	    // if the E is not the next entry, then check to see if it is
+	    // the end event listing key - if yes, search for another start key
+	    int ioendtype = m_common_io.find_end_key(*m_istr);
+	    if ( ioendtype == iotype ) {
+		iotype = m_common_io.find_file_type(*m_istr);
+		if( iotype <= 0 ) {
+		    // this is the only case where we set an EOF state
+		    m_istr->clear(std::ios::eofbit);
+		    return false;
+		}
+	    } else if ( ioendtype > 0 ) {
+		std::cerr << "IO_GenEvent::fill_next_event end key does not match start key "
+			  << "setting badbit." << std::endl;
+		m_istr->clear(std::ios::badbit); 
+		return false;
+	    } else {
+		std::cerr << "IO_GenEvent::fill_next_event end key not found "
+			  << "setting badbit." << std::endl;
+		m_istr->clear(std::ios::badbit); 
+		return false;
+	    }
+	}
+	m_istr->ignore();
+	// call the appropriate read method
+	if( m_common_io.io_type() == gen ) {
+	    return m_common_io.read_io_genevent(m_istr, evt);
+	} else if( m_common_io.io_type() == ascii ) { 
+	    return m_common_io.read_io_ascii(m_istr, evt);
+	} else if( m_common_io.io_type() == extascii ) { 
+	    return m_common_io.read_io_extendedascii(m_istr, evt);
+	} else if( m_common_io.io_type() == ascii_pdt ) { 
+	} else if( m_common_io.io_type() == extascii_pdt ) { 
+	}
+	// should not get to this statement
+	return false;
+    }
+
+    void IO_GenEvent::write_comment( const std::string comment ) {
+	// make sure the stream is good, and that it is in output mode
+	if ( !(*m_ostr) ) return;
+	if ( m_ostr == NULL ) {
+	    std::cerr << "HepMC::IO_GenEvent::write_comment "
+		      << " attempt to write to input file." << std::endl;
+	    return;
+	}
+	// write end of event listing key if events have already been written
+	write_end_listing();
+	// insert the comment key before the comment
+	*m_ostr << "\n" << "HepMC::IO_GenEvent-COMMENT\n";
+	*m_ostr << comment << std::endl;
+    }
+
+    void IO_GenEvent::write_vertex( GenVertex* v ) {
+	// assumes mode has already been checked
+	if ( !v || !(*m_ostr) ) {
+	    std::cerr << "IO_GenEvent::write_vertex !v||!(*m_ostr), "
+		      << "v="<< v << " setting badbit" << std::endl;
+	    m_ostr->clear(std::ios::badbit); 
+	    return;
+	}
+	// First collect info we need
+	// count the number of orphan particles going into v
+	int num_orphans_in = 0;
+	for ( GenVertex::particles_in_const_iterator p1
+		  = v->particles_in_const_begin();
+	      p1 != v->particles_in_const_end(); ++p1 ) {
+	    if ( !(*p1)->production_vertex() ) ++num_orphans_in;
+	}
+	//
+	*m_ostr << 'V';
+	output( v->barcode() ); // v's unique identifier
+	output( v->id() );
+	output( v->position().x() );
+	output( v->position().y() );
+	output( v->position().z() );
+	output( v->position().t() );
+	output( num_orphans_in );
+	output( (int)v->particles_out_size() );
+	output( (int)v->weights().size() );
+	for ( WeightContainer::iterator w = v->weights().begin(); 
+	      w != v->weights().end(); ++w ) {
+	    output( *w );
+	}
+	output('\n');
+	for ( GenVertex::particles_in_const_iterator p2 
+		  = v->particles_in_const_begin();
+	      p2 != v->particles_in_const_end(); ++p2 ) {
+	    if ( !(*p2)->production_vertex() ) {
+		write_particle( *p2 );
+	    }
+	}
+	for ( GenVertex::particles_out_const_iterator p3 
+		  = v->particles_out_const_begin();
+	      p3 != v->particles_out_const_end(); ++p3 ) {
+	    write_particle( *p3 );
+	}
+    }
+
+    void IO_GenEvent::write_beam_particles( 
+        std::pair<HepMC::GenParticle *,HepMC::GenParticle *> pr ) {
+        GenParticle* p = pr.first;
+	//m_file << 'B';
+	if(!p) {
+	   output( 0 );
+	} else {
+	   output( p->barcode() );
+	}
+        p = pr.second;
+	if(!p) {
+	   output( 0 );
+	} else {
+	   output( p->barcode() );
+	}
+    }
+
+    void IO_GenEvent::write_heavy_ion( HeavyIon const * ion ) {
+	// assumes mode has already been checked
+	if ( !(*m_ostr) ) {
+	    std::cerr << "IO_GenEvent::write_heavy_ion !(*m_ostr), "
+		      << " setting badbit" << std::endl;
+	    m_ostr->clear(std::ios::badbit); 
+	    return;
+	}
+	*m_ostr << 'H';
+	// HeavyIon* is set to 0 by default
+	if ( !ion  ) {
+	    output( 0 );
+	    output( 0 );
+	    output( 0 );
+	    output( 0 );
+	    output( 0 );
+	    output( 0 );
+	    output( 0 );
+	    output( 0 );
+	    output( 0 );
+	    output( 0. );
+	    output( 0. );
+	    output( 0. );
+	    output( 0. );
+	    output('\n');
+	    return;
+	}
+	//
+	output( ion->Ncoll_hard() );
+	output( ion->Npart_proj() );
+	output( ion->Npart_targ() );
+	output( ion->Ncoll() );
+	output( ion->spectator_neutrons() );
+	output( ion->spectator_protons() );
+	output( ion->N_Nwounded_collisions() );
+	output( ion->Nwounded_N_collisions() );
+	output( ion->Nwounded_Nwounded_collisions() );
+	output( ion->impact_parameter() );
+	output( ion->event_plane_angle() );
+	output( ion->eccentricity() );
+	output( ion->sigma_inel_NN() );
+	output('\n');
+    }
+
+    void IO_GenEvent::write_pdf_info( PdfInfo const * pdf ) {
+	// assumes mode has already been checked
+	if ( !(*m_ostr) ) {
+	    std::cerr << "IO_GenEvent::write_pdf_info !(*m_ostr), "
+		      << " setting badbit" << std::endl;
+	    m_ostr->clear(std::ios::badbit); 
+	    return;
+	}
+	*m_ostr << 'F';
+	// PdfInfo* is set to 0 by default
+	if ( !pdf ) {
+	    output( 0 );
+	    output( 0 );
+	    output( 0. );
+	    output( 0. );
+	    output( 0. );
+	    output( 0. );
+	    output( 0. );
+	    output( 0 );
+	    output( 0 );
+	    output('\n');
+	    return;
+	}
+	//
+	output( pdf->id1() );
+	output( pdf->id2() );
+	output( pdf->x1() );
+	output( pdf->x2() );
+	output( pdf->scalePDF() );
+	output( pdf->pdf1() );
+	output( pdf->pdf2() );
+	output( pdf->pdf_id1() );
+	output( pdf->pdf_id2() );
+	output('\n');
+    }
+
+    void IO_GenEvent::write_unit_info( const GenEvent* evt ) {
+	if ( !(*m_ostr) ) {
+	    std::cerr << "IO_GenEvent::write_unit_info !(*m_ostr), "
+		      << " setting badbit" << std::endl;
+	    m_ostr->clear(std::ios::badbit); 
+	    return;
+	}
+	// could write enums here, but strings are more readable
+	*m_ostr << "U " << name(evt->momentum_unit());
+	*m_ostr << " " << name(evt->length_unit());
+	output('\n');
+    }
+
+    void IO_GenEvent::write_particle( GenParticle* p ) {
+	// assumes mode has already been checked
+	if ( !p || !(*m_ostr) ) {
+	    std::cerr << "IO_GenEvent::write_particle !p||!(*m_ostr), "
+		      << "p="<< p << " setting badbit" << std::endl;
+	    m_ostr->clear(std::ios::badbit); 
+	    return;
+	}
+	*m_ostr << 'P';
+	output( p->barcode() );
+	output( p->pdg_id() );
+	output( p->momentum().px() );
+	output( p->momentum().py() );
+	output( p->momentum().pz() );
+	output( p->momentum().e() );
+	output( p->generated_mass() );
+	output( p->status() );
+	output( p->polarization().theta() );
+	output( p->polarization().phi() );
+	// since end_vertex is oftentimes null, this CREATES a null vertex
+	// in the map
+	output(   ( p->end_vertex() ? p->end_vertex()->barcode() : 0 )  );
+	*m_ostr << ' ' << p->flow() << "\n";
+    }
+
+    void IO_GenEvent::write_particle_data( const ParticleData* pdata ) {
+	// assumes mode has already been checked
+	if ( !pdata || !(*m_ostr) ) {
+	    std::cerr << "IO_GenEvent::write_particle_data !pdata||!(*m_ostr), "
+		      << "pdata="<< pdata << " setting badbit" << std::endl;
+	    m_ostr->clear(std::ios::badbit); 
+	    return;
+	}
+	*m_ostr << 'D';
+	output( pdata->pdg_id() );
+	output( pdata->charge() );
+	output( pdata->mass() );
+	output( pdata->clifetime() );
+	output( (int)(pdata->spin()*2.+.1) );
+	// writes the first 21 characters starting with 0
+	*m_ostr << " " << pdata->name().substr(0,21) << "\n";
+    }
+
+    HeavyIon* IO_GenEvent::read_heavy_ion()
+    {
+	// assumes mode has already been checked
+	//
+	// test to be sure the next entry is of type "H" then ignore it
+	if ( !(*m_istr) || m_istr->peek()!='H' ) {
+	    std::cerr << "IO_GenEvent::read_heavy_ion setting badbit." << std::endl;
+	    m_istr->clear(std::ios::badbit); 
+	    return false;
+	} 
+	m_istr->ignore();
+	// read values into temp variables, then create a new HeavyIon object
+	int nh =0, np =0, nt =0, nc =0, 
+            neut = 0, prot = 0, nw =0, nwn =0, nwnw =0;
+	float impact = 0., plane = 0., xcen = 0., inel = 0.; 
+	*m_istr >> nh >> np >> nt >> nc >> neut >> prot
+	       >> nw >> nwn >> nwnw >> impact >> plane >> xcen >> inel;
+	m_istr->ignore(2,'\n');
+	if( nh == 0 ) return false;
+	HeavyIon* ion = new HeavyIon(nh, np, nt, nc, neut, prot,
+	                             nw, nwn, nwnw, 
+				     impact, plane, xcen, inel );
+	//
+	return ion;
+    }
+
+    GenParticle* IO_GenEvent::read_particle(
+	TempParticleMap& particle_to_end_vertex ){
+	// assumes mode has already been checked
+	//
+	// test to be sure the next entry is of type "P" then ignore it
+	if ( !(*m_istr) || m_istr->peek()!='P' ) { 
+	    std::cerr << "IO_GenEvent::read_particle setting badbit." 
+		      << std::endl;
+	    m_istr->clear(std::ios::badbit); 
+	    return false;
+	} 
+	m_istr->ignore();
+	//
+	// declare variables to be read in to, and read everything except flow
+	double px = 0., py = 0., pz = 0., e = 0., m = 0., theta = 0., phi = 0.;
+	int bar_code = 0, id = 0, status = 0, end_vtx_code = 0, flow_size = 0;
+	*m_istr >> bar_code >> id >> px >> py >> pz >> e >> m >> status 
+	       >> theta >> phi >> end_vtx_code >> flow_size;
+	//
+	// read flow patterns if any exist
+	Flow flow;
+	int code_index, code;
+	for ( int i = 1; i <= flow_size; ++i ) {
+	    *m_istr >> code_index >> code;
+	    flow.set_icode( code_index,code);
+	}
+	m_istr->ignore(2,'\n'); // '\n' at end of entry
+	GenParticle* p = new GenParticle( FourVector(px,py,pz,e), 
+				    id, status, flow, 
+				    Polarization(theta,phi) );
+        p->set_generated_mass( m );
+	p->suggest_barcode( bar_code );
+	//
+	// all particles are connected to their end vertex separately 
+	// after all particles and vertices have been created - so we keep
+	// a map of all particles that have end vertices
+	if ( end_vtx_code != 0 ) {
+	    particle_to_end_vertex.addEndParticle(p,end_vtx_code);
+	}
+	return p;
+    }
+
+    ParticleData* IO_GenEvent::read_particle_data( ParticleDataTable* pdt ) {
+	// assumes mode has already been checked
+	//
+	// test to be sure the next entry is of type "D" then ignore it
+	if ( !(*m_istr) || m_istr->peek()!='D' ) return false;
+	m_istr->ignore();
+	//
+	// read values into temp variables then create new ParticleData object
+	char its_name[22];
+	int its_id = 0, its_spin = 0;  
+	double its_charge = 0, its_mass = 0, its_clifetime = 0;
+	*m_istr >> its_id >> its_charge >> its_mass 
+	       >> its_clifetime >> its_spin;
+	m_istr->ignore(1); // eat the " "
+	m_istr->getline( its_name, 22, '\n' );
+	ParticleData* pdata = new ParticleData( its_name, its_id, its_charge, 
+						its_mass, its_clifetime, 
+						double(its_spin)/2.);
+	pdt->insert(pdata);
+	return pdata;
+    }
+
+    bool IO_GenEvent::write_end_listing() {
+    	if ( m_finished_first_event_io && (m_ostr != NULL) ) {
+	    m_common_io.write_IO_GenEvent_End(*m_ostr);
+	    *m_ostr << std::flush;
+	    m_finished_first_event_io = 0;
+	    return true;
+	}
+	return false;
+    }
+	
+} // HepMC
Index: /trunk/Utilities/HepMC/src/IO_PDG_ParticleDataTable.cc
===================================================================
--- /trunk/Utilities/HepMC/src/IO_PDG_ParticleDataTable.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/IO_PDG_ParticleDataTable.cc	(revision 349)
@@ -0,0 +1,236 @@
+//--------------------------------------------------------------------------
+
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, January 2000
+// Reads a particle data table from file supplied in PDG format
+// For the most recent table see: http://pdg.lbl.gov/computer_read.html
+//////////////////////////////////////////////////////////////////////////
+
+#include <ctype.h>      // for isspace() etc.
+#include <string>
+#include <vector>
+#include <cstdlib>      // needed for abort()
+#include <cstring>	// for strlen()
+#include "IO_PDG_ParticleDataTable.h"
+
+namespace HepMC {
+
+    IO_PDG_ParticleDataTable::IO_PDG_ParticleDataTable( const char* filename ) 
+        : m_filename(filename), m_file(filename) {
+        std::cout << "-------------------------------------------------------" << std::endl;
+        std::cout << "Use of HepMC/IO_PDG_ParticleDataTable is deprecated" << std::endl;
+        std::cout << "Use of HepMC/ParticleDataTable is deprecated" << std::endl;
+        std::cout << "-------------------------------------------------------" << std::endl;
+    }
+    
+    IO_PDG_ParticleDataTable::~IO_PDG_ParticleDataTable() {
+	m_file.close();
+    }
+
+    bool IO_PDG_ParticleDataTable::fill_particle_data_table( 
+	ParticleDataTable* pdt) 
+    {
+	//
+	// test that pdt pointer is not null
+	if ( !pdt ) {
+	    std::cerr 
+		<< "IO_Ascii::fill_particle_data_table - passed null table." 
+		<< std::endl;
+	    return false;
+	}
+	//
+	// test the file is good and advance to keyword
+        if (!m_file ) {
+	  // return false;
+	  std::cerr << "IO_PDG_ParticleDataTable::fill_particle_data_table "
+		    << " ERROR, file " << m_filename << " does not exist, "
+		    << " ABORT." << std::endl;
+	  abort();
+	}	
+	m_file.seekg( 0 );
+	if ( !search_for_key_end(m_file,"\nM") ) {
+	    std::cerr << "IO_PDG_ParticleDataTable: "
+		      << "Error advancing to first entry." 
+		      << std::endl;
+	    return false;
+	}
+	// set description
+	std::string description = "Read from " + m_filename 
+				  + " by IO_PDG_ParticleDataTable";
+	pdt->set_description( description );
+	m_file.putback('M');
+	// read in each entry one by one
+	while ( m_file.rdstate() == 0 ) {
+	    read_entry( pdt );
+	}
+	return true;
+    }
+
+    void IO_PDG_ParticleDataTable::read_entry( ParticleDataTable* pdt ) {
+	int position = m_file.tellg();
+	// variables for input
+	char code;
+	int id[4] = { 0,0,0,0 };
+	int charge[4] = { 999, 999, 999, 999 };
+	double value;
+	std::string name;
+
+	code = m_file.get();
+	if ( code == EOF ) {
+	    m_file.clear( std::ios::eofbit );
+	    return;
+	}
+
+	if ( code == '\n' ) return; // ignore empty lines.
+
+	if ( code!='M' && code!='W' ) {
+	    std::cerr << "IO_PDG_ParticleDataTable::read_entry cannot "
+		      << "understand syntax, setting badbit."
+		      << std::endl;
+	    m_file.putback( code );
+	    m_file.clear( std::ios::badbit ); 
+            return;
+        } 
+	// read the particle ID's -- here I assume there is atleast one
+	// white space b/t the 4 id columns.
+	for ( int id_i1 = 0; id_i1 < 4; ++id_i1 ) {
+	    m_file.seekg( position+1+(id_i1*8) );
+	    for ( int i = 0; i < 8; ++i ) {
+		if ( !isspace(m_file.peek()) ) {
+		    //m_file.width(8-i); // has no effect
+		    // how do I limit to reading only 8-i characters?
+		    // setw(8-i) has no effect either.
+		    m_file >> id[id_i1];
+		    break;
+		}
+		m_file.ignore(); 
+	    }
+	}
+	//m_file.width(0);
+	m_file.seekg(position+33);
+	m_file >> value;
+	m_file.seekg(position+66);
+	m_file >> name;
+	// loop over all remaining columns of the name section, where the 
+	// charge is stored --- until \n is reached
+	// Here I assume there is atleast one white space between the name
+	// and the charge. This is true for the 1998 PDG table, and I expect
+	// it will always be true.
+	int id_i2 = 0;
+	while ( m_file.rdstate() == 0 ) {
+	    char c = m_file.get();
+	    if ( c == '\n' || c == EOF ) break;
+	    if ( isspace(c) || c==',' ) {
+	    } else if ( c=='-' ) { 
+		charge[id_i2] = -1; 
+		++id_i2; 
+	    } else if ( c=='0' ) {
+		charge[id_i2] = 0;
+		++id_i2; 
+	    } else if ( c=='+' ) {
+		charge[id_i2] = 1;
+		if ( m_file.peek() == '+' ) {
+		    charge[id_i2] = 2;
+		    m_file.ignore();
+		}
+		++id_i2;
+	    }
+	}
+	// add the new information to the particle data table.
+	for ( int id_i3 = 0; id_i3 < 4; ++id_i3 ) {
+	    if ( id[id_i3] == 0 ) continue;
+	    std::string scharge;
+	    if ( charge[id_i3] == -1 ) { 
+		scharge = "-";
+	    } else if ( charge[id_i3] == 1 ) { 
+		scharge = "+";
+	    } else if ( charge[id_i3] == 2 ) { 
+		scharge = "++"; 
+	    }
+	    ParticleData* pdata = pdt->find( id[id_i3] );
+	    if ( pdata ) {
+		if ( code == 'M' ) {
+		    pdata->set_mass( value );
+		} else if ( code == 'W' ) {
+		    pdata->set_clifetime( clifetime_from_width(value) );
+		}
+	    } else if ( code == 'M' ) {
+		pdata = new ParticleData( name+scharge, 
+					  id[id_i3], (double)charge[id_i3], 
+					  value );
+		pdt->insert(pdata);
+	    } else if ( code == 'W' ) {
+		pdata = new ParticleData( name+scharge, 
+					  id[id_i3], (double)charge[id_i3],
+					  0, clifetime_from_width(value) );
+		pdt->insert(pdata);
+	    }
+	}
+    }
+
+    void IO_PDG_ParticleDataTable::add_quarks_to_table( 
+	ParticleDataTable& pdt ) {
+	/// since quarks aren't included in PDG table, this method adds them
+	// in
+	std::vector<std::string> name(6);
+	name[0] = "d";
+	name[1] = "u";
+	name[2] = "s";
+	name[3] = "c";
+	name[4] = "b";
+	name[5] = "t";
+	int id[6] = { 1, 2, 3, 4, 5, 6 };
+	double charge[6] = { -1./3., 2./3., -1./3., 2./3., -1./3., 2./3. };
+	// take central values from PDG July 1998 for masses
+	double mass[6] = { 0.006, 0.00325, 0.115, 1.25, 4.25, 173.8 };
+	for ( int i = 0; i<6; ++i ) {
+	    // build the particle
+	    ParticleData* pdata = pdt.find(id[i]);
+	    if ( pdata ) {
+		mass[i] = pdata->mass();
+		pdt.erase(pdata);
+		delete pdata;
+	    }
+	    pdata = new ParticleData( name[i], id[i], charge[i], mass[i], -1.,
+				      .5 );
+	    pdt.insert(pdata);
+	    // build the antiparticle
+	    pdata = pdt.find(-1*id[i]);
+	    if ( pdata ) {
+		pdt.erase(pdata);
+		delete pdata;
+	    }
+	    pdata = new ParticleData( name[i]+"~", -1*id[i], -1*charge[i], 
+				      mass[i], -1., .5 );
+	    pdt.insert(pdata);
+	}
+    }
+
+    bool IO_PDG_ParticleDataTable::search_for_key_end( std::istream& in, 
+						       const char* key ) {
+	/// (this method borrowed from IO_Ascii class)
+        /// reads characters from in until the string of characters matching
+        /// key is found (success) or EOF is reached (failure).
+        /// It stops immediately thereafter. Returns T/F for success/fail
+        // 
+        char c[1];
+        unsigned int index = 0;
+        while ( in.get(c[0]) ) {
+            if ( c[0] == key[index] ) { 
+                ++index;
+            } else { index = 0; }
+            if ( index == strlen(key) ) return true;
+        }
+        return false;
+    }
+
+} // HepMC
+
+
+
+
+
+
+
+
+
Index: /trunk/Utilities/HepMC/src/ParticleData.cc
===================================================================
--- /trunk/Utilities/HepMC/src/ParticleData.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/ParticleData.cc	(revision 349)
@@ -0,0 +1,126 @@
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999
+//
+// particle properties common to all particles of a given PDG id
+//////////////////////////////////////////////////////////////////////////
+
+#include "ParticleData.h"
+#include <cstdio>       // needed for formatted output using sprintf 
+
+namespace HepMC {
+
+    ParticleData::ParticleData( std::string name, int id, double charge, 
+				double mass, double clifetime, double spin ) :
+	m_name(name), m_pdg_id(id), m_mass(mass), m_clifetime(clifetime)
+    {
+	/// Units ID: defined by PDG group (particles are +ve, antipart are -ve)
+	///              also consistent with the Pythia definitions
+	///       charge: fraction of proton charge
+	///       mass
+	///       cLifetime: c*time
+	/// Default mass=0 and cLifetime is -1 which means stable (width= 0.)
+	/// These defaults exist because many very basic MC generators
+	///   may produce only massless stable particles in the event record.
+	//
+	set_charge(charge);
+	set_spin(spin);
+        s_counter++;
+    }
+
+    ParticleData::ParticleData( const char* name, int id, double charge, 
+				double mass, double clifetime, double spin ):
+	m_name(name), m_pdg_id(id), m_mass(mass), m_clifetime(clifetime)
+    {
+	/// note, this constructor is redundant to the one above, 
+	/// i.e. one could use: 
+	/// new HepMC::ParticleData(string("electron"),11,-1,0.000511,-1,.5);
+	/// but we keep it because it is convenient.
+	//
+	set_charge(charge);
+	set_spin(spin);	
+        s_counter++;
+    }
+
+    ParticleData::~ParticleData() {
+	s_counter--;
+    }
+
+    void ParticleData::print( std::ostream& ostr ) const {
+	ostr << "ParticleData: " << name() << "\t"
+	     << " ID[pdg]:" << pdg_id()
+	     << " Charge[e+]:" << charge()
+	     << " Mass:" << mass()
+	     << " Tau:" << clifetime()
+	     << " J:" << spin() << std::endl;
+    }
+
+    ////////////////////
+    // access methods //
+    ////////////////////
+
+    int ParticleData::model_independent_pdg_id_() const { 
+	/// returns the particle id with the seventh
+	/// digit removed for susy/excited/technicolor particles.
+	/// Thus en excited electron (40000011) would be returned as 11
+	/// Useful only internally for sorting particles!
+	int id = m_pdg_id;
+	if ( id/1000000 >=1 && id/1000000 <= 4 ) id %= 1000000;
+	return id;
+    }
+
+    double ParticleData::width() const { 
+	double width;
+	if ( m_clifetime > 0 ) { 
+	    width = HepMC_hbarc/m_clifetime;
+	} else if ( m_clifetime == 0 ) { 
+	    width = -1;
+	} else { 
+	    width = 0; 
+	}
+	return width;
+    }
+
+    /////////////
+    // Static  //
+    /////////////
+    unsigned int ParticleData::counter() { return s_counter; }
+    unsigned int ParticleData::s_counter = 0; 
+
+    /////////////
+    // Friends //
+    /////////////
+
+    /// write to ostr
+    std::ostream& operator<<( std::ostream& ostr, const ParticleData& pdata ) {
+	char outline[80];
+	sprintf( outline,"%+9d%21s%+6.2f%19.11e%19.11e%5.1f",
+		 pdata.pdg_id(),
+		 pdata.name().substr(0,21).c_str(),
+		 pdata.charge(),
+		 pdata.mass(),
+		 pdata.clifetime(),
+		 pdata.spin() );
+	return ostr << outline;
+    }
+
+    //////////////////////
+    // Related Methods  //
+    //////////////////////
+
+    double clifetime_from_width( double width ) {
+	/// if you want to instantiate the particle lifetime from its width,
+	/// use this static method inside the constructor:
+	// i.e. new ParticleData(
+	if ( width > 0 ) return HepMC_hbarc/width;
+	if ( width == 0. ) return -1.;
+	return 0.;
+    }
+    
+} // HepMC
+
+
+
+
+
+
+
Index: /trunk/Utilities/HepMC/src/Polarization.cc
===================================================================
--- /trunk/Utilities/HepMC/src/Polarization.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/Polarization.cc	(revision 349)
@@ -0,0 +1,114 @@
+//////////////////////////////////////////////////////////////////////////
+// Matt.Dobbs@Cern.CH, September 1999
+//
+// Polarization object for a particle. All angles are in radians.
+//////////////////////////////////////////////////////////////////////////
+
+#include "Polarization.h"
+
+namespace HepMC {
+
+    Polarization::Polarization( double theta, double phi )
+    : m_theta( valid_theta(theta) ),
+      m_phi  ( valid_phi(phi) )
+    { }
+
+    Polarization::Polarization( const Polarization& inpolar )
+    : m_theta( valid_theta( inpolar.theta() ) ),
+      m_phi  ( valid_phi(   inpolar.phi()   ) )
+    { }
+
+    Polarization::Polarization( const ThreeVector& vec3in ) 
+    : m_theta( valid_theta( vec3in.theta() ) ),
+      m_phi  ( valid_phi(   vec3in.phi()   ) )
+    { }
+
+    void Polarization::swap( Polarization & other)
+    {
+ 	std::swap( m_theta, other.m_theta );
+ 	std::swap( m_phi,   other.m_phi   );
+    }
+
+    Polarization& Polarization::operator=( const Polarization& inpolar ) {
+        /// best practices implementation
+	Polarization tmp( inpolar );
+	swap( tmp ); 
+	return *this;
+    }
+
+    void Polarization::print( std::ostream& ostr ) const {
+	ostr << "Polarization: " << *this << std::endl;
+    }
+
+    ////////////////////
+    // access methods //
+    ////////////////////
+
+    ThreeVector  Polarization::normal3d() const {
+	// unit Hep3Vector for easy manipulation
+	ThreeVector outvec(0,0,1);      // makes unit vector along Z
+	outvec.setTheta( theta() ); // sets phi keeping mag and theta constant
+	outvec.setPhi( phi() );     // sets theta keeping mag and phi constant
+	return outvec;
+    }
+
+    double Polarization::set_theta( double theta ) {
+	/// Theta is restricted to be between 0 --> pi
+	/// if an out of range value is given, it is translated to this range.
+	return m_theta = valid_theta( theta );
+    }
+
+    double Polarization::set_phi( double phi ) {
+	/// Phi is restricted to be between 0 --> 2pi
+	/// if an out of range value is given, it is translated to this range.
+	return m_phi = valid_phi( phi );
+    }
+
+    void Polarization::set_theta_phi( double theta, double phi ) {
+	set_theta( theta );
+	set_phi( phi ) ;
+    }
+
+    ThreeVector Polarization::set_normal3d( const ThreeVector& vec3in ) {
+	set_theta( vec3in.theta() );
+	set_phi( vec3in.phi() );
+	return vec3in;
+    }
+
+    /////////////////////
+    // private methods //
+    /////////////////////
+
+    double Polarization::valid_theta( double theta ) {
+        // this is just absolute value.
+	theta = ( theta>0 ? theta : -theta );
+	// translate to 0 < theta < 2pi
+	theta = ( theta/(2*HepMC_pi) - int(theta/(2*HepMC_pi)) ) 
+		* 2*HepMC_pi;
+        // now translate to 0 < theta < pi
+	if ( theta > HepMC_pi ) theta = 2*HepMC_pi - theta;
+	return theta;
+    }
+
+    double Polarization::valid_phi( double phi ) {
+	//
+	// translate to -2pi < phi < 2pi
+	phi = ( phi/(2*HepMC_pi) - int(phi/(2*HepMC_pi)) ) * 2*HepMC_pi;
+	// translates to 0 < phi < 2pi
+	if ( phi < 0 ) phi = 2*HepMC_pi + phi;
+	return phi;
+    }
+
+    /////////////
+    // Friends //
+    /////////////
+
+    /// write theta and phi to the output stream
+    std::ostream& operator<<( std::ostream& ostr, const Polarization& polar ) {
+	return ostr << "(" << polar.theta() 
+		    << ","  << polar.phi() << ")";
+    }
+    
+} // HepMC
+
+
Index: /trunk/Utilities/HepMC/src/SearchVector.cc
===================================================================
--- /trunk/Utilities/HepMC/src/SearchVector.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/SearchVector.cc	(revision 349)
@@ -0,0 +1,29 @@
+//////////////////////////////////////////////////////////////////////////
+// Author: Lynn Garren
+// search vectors for a GenParicle* instance
+//////////////////////////////////////////////////////////////////////////
+
+#include "SearchVector.h"
+
+namespace HepMC {
+
+  
+bool not_in_vector( std::vector<GenParticle*>* v, GenParticle* p )
+{
+    if( already_in_vector(v,p) == v->end()  ) return true;
+    return false;
+}
+
+/// returns true if GenParticle is in the vector
+std::vector<HepMC::GenParticle*>::iterator already_in_vector( std::vector<GenParticle*>* v, GenParticle* p )
+{
+    // if the vectors are mostly large, the search should be coded differently
+    std::vector<GenParticle*>::iterator it;
+    for( it = v->begin(); it != v->end(); ++it ) {
+        // bail as soon as we find a match
+        if( (*it) == p ) return it;
+    }
+    return v->end();
+}
+
+}	// HepMC
Index: /trunk/Utilities/HepMC/src/Units.cc
===================================================================
--- /trunk/Utilities/HepMC/src/Units.cc	(revision 349)
+++ /trunk/Utilities/HepMC/src/Units.cc	(revision 349)
@@ -0,0 +1,66 @@
+//--------------------------------------------------------------------------
+// Units.cc
+// Author:  A. Buckley, D. Grellscheid
+//
+// units used by a GenEvent
+// The default units are set here at compile time.
+//--------------------------------------------------------------------------
+
+#include "Units.h"
+
+namespace HepMC {
+
+  namespace Units {
+
+   // helper functions
+    std::string name(MomentumUnit m) {
+      switch (m) {
+        case MEV : return "MEV";
+        case GEV : return "GEV";
+ 	default  : return "badValue";
+      } 
+    }
+
+    std::string name(LengthUnit l) {
+      switch (l) {
+        case MM : return "MM";
+        case CM : return "CM";
+  	default : return "badValue";
+     } 
+    }
+
+    double conversion_factor(MomentumUnit from, MomentumUnit to) 
+    {
+      if ( from == to )
+	return 1.0;
+      else if ( from == MEV && to == GEV )
+	return 0.001;
+      else
+	return 1000.0;
+    }
+
+    double conversion_factor(LengthUnit from, LengthUnit to) 
+    {
+      if ( from == to )
+	return 1.0;
+      else if ( from == MM && to == CM )
+	return 0.1;
+      else
+	return 10.0;
+    }
+
+    // if this function fails to compile, rerun configure using --with-length_units
+    LengthUnit default_length_unit() {
+      //return @HEPMC_DEFAULT_LEN_UNIT@ ;
+      return MM ;
+    }
+
+    // if this function fails to compile, rerun configure using --with-momentum_units
+    MomentumUnit default_momentum_unit() {
+      //return @HEPMC_DEFAULT_MOM_UNIT@ ;
+      return GEV;
+    }
+
+  }	// Units
+
+}	// HepMC
