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 }