go-hep.org/x/hep@v0.38.1/hepmc/encoder.go (about)

     1  // Copyright ©2017 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package hepmc
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"sort"
    11  )
    12  
    13  // Encoder encodes a hepmc Event into a stream.
    14  type Encoder struct {
    15  	w          io.Writer
    16  	seenEvtHdr bool
    17  }
    18  
    19  // NewEncoder returns a new hepmc Encoder that writes into the io.Writer.
    20  func NewEncoder(w io.Writer) *Encoder {
    21  	return &Encoder{w: w}
    22  }
    23  
    24  // Close closes the encoder and adds a footer to the stream.
    25  func (enc *Encoder) Close() error {
    26  	var err error
    27  	if enc.seenEvtHdr {
    28  		_, err = fmt.Fprintf(
    29  			enc.w,
    30  			"%s\n",
    31  			endGenEvent,
    32  		)
    33  		if err != nil {
    34  			return err
    35  		}
    36  	}
    37  	return err
    38  }
    39  
    40  // Encode writes evt into the stream.
    41  func (enc *Encoder) Encode(evt *Event) error {
    42  	var err error
    43  
    44  	if !enc.seenEvtHdr {
    45  		_, err = fmt.Fprintf(
    46  			enc.w,
    47  			"\nHepMC::Version %s\n",
    48  			VersionName(),
    49  		)
    50  		if err != nil {
    51  			return err
    52  		}
    53  
    54  		_, err = fmt.Fprintf(enc.w, "%s\n", startGenEvent)
    55  		if err != nil {
    56  			return err
    57  		}
    58  
    59  		enc.seenEvtHdr = true
    60  	}
    61  
    62  	sigBc := 0
    63  	if evt.SignalVertex != nil {
    64  		sigBc = evt.SignalVertex.Barcode
    65  	}
    66  	bp1 := 0
    67  	if evt.Beams[0] != nil {
    68  		bp1 = evt.Beams[0].Barcode
    69  	}
    70  	bp2 := 0
    71  	if evt.Beams[1] != nil {
    72  		bp2 = evt.Beams[1].Barcode
    73  	}
    74  	// output the event data including the number of primary vertices
    75  	// and the total number of vertices
    76  	_, err = fmt.Fprintf(
    77  		enc.w,
    78  		"E %d %d %1.16e %1.16e %1.16e %d %d %d %d %d %d",
    79  		evt.EventNumber,
    80  		evt.Mpi,
    81  		evt.Scale,
    82  		evt.AlphaQCD,
    83  		evt.AlphaQED,
    84  		evt.SignalProcessID,
    85  		sigBc,
    86  		len(evt.Vertices),
    87  		bp1,
    88  		bp2,
    89  		len(evt.RandomStates),
    90  	)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	for _, rndm := range evt.RandomStates {
    95  		_, err = fmt.Fprintf(enc.w, " %d", rndm)
    96  		if err != nil {
    97  			return err
    98  		}
    99  	}
   100  	_, err = fmt.Fprintf(enc.w, " %d", len(evt.Weights.Slice))
   101  	if err != nil {
   102  		return err
   103  	}
   104  	// we need to iterate over the weights in the same order than their names
   105  	// (we'll make sure of that in the 'N' line)
   106  	for _, weight := range evt.Weights.Slice {
   107  		_, err = fmt.Fprintf(enc.w, " %1.16e", weight)
   108  		if err != nil {
   109  			return err
   110  		}
   111  	}
   112  	_, err = fmt.Fprintf(enc.w, "\n")
   113  	if err != nil {
   114  		return err
   115  	}
   116  	if len(evt.Weights.Slice) > 0 {
   117  		nn := len(evt.Weights.Slice)
   118  		names := make(map[int]string, nn)
   119  		for k, v := range evt.Weights.Map {
   120  			names[v] = k
   121  		}
   122  		_, err = fmt.Fprintf(enc.w, "N %d ", nn)
   123  		if err != nil {
   124  			return err
   125  		}
   126  		for iw := range nn {
   127  			_, err = fmt.Fprintf(enc.w, "%q ", names[iw])
   128  			if err != nil {
   129  				return err
   130  			}
   131  		}
   132  		_, err = fmt.Fprintf(enc.w, "\n")
   133  		if err != nil {
   134  			return err
   135  		}
   136  	}
   137  
   138  	// units
   139  	_, err = fmt.Fprintf(
   140  		enc.w,
   141  		"U %s %s\n",
   142  		evt.MomentumUnit,
   143  		evt.LengthUnit,
   144  	)
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	// cross-section
   150  	if evt.CrossSection != nil {
   151  		err = enc.encodeCrossSection(evt.CrossSection)
   152  		if err != nil {
   153  			return err
   154  		}
   155  	}
   156  
   157  	if evt.HeavyIon != nil {
   158  		err = enc.encodeHeavyIon(evt.HeavyIon)
   159  		if err != nil {
   160  			return err
   161  		}
   162  	}
   163  
   164  	err = enc.encodePdfInfo(evt.PdfInfo)
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	// output all of the vertices
   170  	vertices := make([]*Vertex, 0, len(evt.Vertices))
   171  	for _, vtx := range evt.Vertices {
   172  		vertices = append(vertices, vtx)
   173  	}
   174  	sort.Sort(sort.Reverse(Vertices(vertices)))
   175  	for _, vtx := range vertices {
   176  		err = enc.encodeVertex(vtx)
   177  		if err != nil {
   178  			return err
   179  		}
   180  	}
   181  	return err
   182  }
   183  
   184  func (enc *Encoder) encodeVertex(vtx *Vertex) error {
   185  	var err error
   186  	orphans := 0
   187  	for _, p := range vtx.ParticlesIn {
   188  		if p.ProdVertex == nil {
   189  			orphans++
   190  		}
   191  	}
   192  
   193  	_, err = fmt.Fprintf(
   194  		enc.w,
   195  		"V %d %d %1.16e %1.16e %1.16e %1.16e %d %d %d",
   196  		vtx.Barcode,
   197  		vtx.ID,
   198  		vtx.Position.X(), vtx.Position.Y(), vtx.Position.Z(), vtx.Position.T(),
   199  		orphans,
   200  		len(vtx.ParticlesOut),
   201  		len(vtx.Weights.Slice),
   202  	)
   203  	if err != nil {
   204  		return err
   205  	}
   206  	for _, w := range vtx.Weights.Slice {
   207  		_, err = fmt.Fprintf(enc.w, " %1.16e", w)
   208  		if err != nil {
   209  			return err
   210  		}
   211  	}
   212  	_, err = fmt.Fprintf(enc.w, "\n")
   213  	if err != nil {
   214  		return err
   215  	}
   216  
   217  	for _, p := range vtx.ParticlesIn {
   218  		if p.ProdVertex == nil {
   219  			err = enc.encodeParticle(p)
   220  			if err != nil {
   221  				return err
   222  			}
   223  		}
   224  	}
   225  
   226  	for _, p := range vtx.ParticlesOut {
   227  		err = enc.encodeParticle(p)
   228  		if err != nil {
   229  			return err
   230  		}
   231  	}
   232  	return err
   233  }
   234  
   235  func (enc *Encoder) encodeParticle(p *Particle) error {
   236  	var err error
   237  
   238  	endBc := 0
   239  	if p.EndVertex != nil {
   240  		endBc = p.EndVertex.Barcode
   241  	}
   242  
   243  	_, err = fmt.Fprintf(
   244  		enc.w,
   245  		"P %d %d %1.16e %1.16e %1.16e %1.16e %1.16e %d %1.16e %1.16e %d",
   246  		p.Barcode,
   247  		p.PdgID,
   248  		p.Momentum.Px(), p.Momentum.Py(), p.Momentum.Pz(), p.Momentum.E(),
   249  		p.GeneratedMass,
   250  		p.Status,
   251  		p.Polarization.Theta,
   252  		p.Polarization.Phi,
   253  		endBc,
   254  	)
   255  	if err != nil {
   256  		return err
   257  	}
   258  	err = enc.encodeFlow(&p.Flow)
   259  	if err != nil {
   260  		return err
   261  	}
   262  	_, err = fmt.Fprintf(enc.w, "\n")
   263  	return err
   264  }
   265  
   266  func (enc *Encoder) encodeFlow(flow *Flow) error {
   267  	var err error
   268  	_, err = fmt.Fprintf(enc.w, " %d", len(flow.Icode))
   269  	if err != nil {
   270  		return err
   271  	}
   272  	icodes := make([]int, 0, len(flow.Icode))
   273  	for k := range flow.Icode {
   274  		icodes = append(icodes, k)
   275  	}
   276  	sort.Ints(icodes)
   277  	for _, k := range icodes {
   278  		v := flow.Icode[k]
   279  		_, err = fmt.Fprintf(enc.w, " %d %d", k, v)
   280  		if err != nil {
   281  			return err
   282  		}
   283  	}
   284  	return err
   285  }
   286  
   287  func (enc *Encoder) encodeCrossSection(x *CrossSection) error {
   288  	var err error
   289  	_, err = fmt.Fprintf(
   290  		enc.w,
   291  		"C %1.16e %1.16e\n",
   292  		x.Value,
   293  		x.Error,
   294  	)
   295  	return err
   296  }
   297  
   298  func (enc *Encoder) encodeHeavyIon(hi *HeavyIon) error {
   299  	var err error
   300  	_, err = fmt.Fprintf(
   301  		enc.w,
   302  		"H %d %d %d %d %d %d %d %d %d %1.16e %1.16e %1.16e %1.16e\n",
   303  		hi.NCollHard,
   304  		hi.NPartProj,
   305  		hi.NPartTarg,
   306  		hi.NColl,
   307  		hi.NNwColl,
   308  		hi.NwNColl,
   309  		hi.NwNwColl,
   310  		hi.SpectatorNeutrons,
   311  		hi.SpectatorProtons,
   312  		hi.ImpactParameter,
   313  		hi.EventPlaneAngle,
   314  		hi.Eccentricity,
   315  		hi.SigmaInelNN,
   316  	)
   317  	return err
   318  }
   319  
   320  func (enc *Encoder) encodePdfInfo(pdf *PdfInfo) error {
   321  	var err error
   322  	if pdf == nil {
   323  		_, err = fmt.Fprintf(
   324  			enc.w,
   325  			"F %d %d %1.16e %1.16e %1.16e %1.16e %1.16e %d %d\n",
   326  			0, 0, 0., 0., 0., 0., 0., 0, 0,
   327  		)
   328  		return err
   329  	}
   330  	_, err = fmt.Fprintf(
   331  		enc.w,
   332  		"F %d %d %1.16e %1.16e %1.16e %1.16e %1.16e %d %d\n",
   333  		pdf.ID1,
   334  		pdf.ID2,
   335  		pdf.X1,
   336  		pdf.X2,
   337  		pdf.ScalePDF,
   338  		pdf.Pdf1,
   339  		pdf.Pdf2,
   340  		pdf.LHAPdf1,
   341  		pdf.LHAPdf2,
   342  	)
   343  	return err
   344  }