go-hep.org/x/hep@v0.38.1/cmd/lhef2hepmc/main.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 // lhef2hepmc converts a LHEF input file into a HepMC file. 6 // 7 // Example: 8 // 9 // $> lhef2hepmc -i in.lhef -o out.hepmc 10 // $> lhef2hepmc < in.lhef > out.hepmc 11 package main // import "go-hep.org/x/hep/cmd/lhef2hepmc" 12 13 import ( 14 "flag" 15 "io" 16 "log" 17 "math" 18 "os" 19 20 "go-hep.org/x/hep/fmom" 21 "go-hep.org/x/hep/hepmc" 22 "go-hep.org/x/hep/lhef" 23 ) 24 25 var ( 26 ifname = flag.String("i", "", "path to LHEF input file (default: STDIN)") 27 ofname = flag.String("o", "", "path to HEPMC output file (default: STDOUT)") 28 29 // see https://arxiv.org/pdf/hep-ph/0109068.pdf, page 7: 30 // integer ISTUP(I) : status code 31 // –1 Incoming particle 32 // +1 Outgoing final state particle 33 // –2 Intermediate space-like propagator defining an x and Q2 which should be preserved 34 // +2 Intermediate resonance, Mass should be preserved 35 // +3 Intermediate resonance, for documentation only 36 // –9 Incoming beam particles at time t = −∞ 37 keep = flag.Bool("keep-all", false, "keep internediaries (with |ISTUP| != 1)") 38 39 // in case IDWTUP == +/-4, one has to keep track of the accumulated 40 // weights and event numbers to evaluate the cross section on-the-fly. 41 // The last evaluation is the one used. 42 // Better to be sure that crossSection() is never used to fill the 43 // histograms, but only in the finalization stage, by reweighting the 44 // histograms with crossSection()/sumOfWeights() 45 sumw = 0.0 46 sumw2 = 0.0 47 nevt = 0 48 ) 49 50 func main() { 51 log.SetFlags(0) 52 log.SetPrefix("lhef2hepmc: ") 53 log.SetOutput(os.Stderr) 54 55 flag.Parse() 56 57 var r io.Reader 58 if *ifname == "" { 59 r = os.Stdin 60 } else { 61 f, err := os.Open(*ifname) 62 if err != nil { 63 log.Fatal(err) 64 } 65 r = f 66 defer f.Close() 67 } 68 69 var w io.Writer 70 if *ofname == "" { 71 w = os.Stdout 72 } else { 73 f, err := os.Create(*ofname) 74 if err != nil { 75 log.Fatal(err) 76 } 77 w = f 78 defer f.Close() 79 } 80 81 dec, err := lhef.NewDecoder(r) 82 if err != nil { 83 log.Fatalf("error creating LHEF decoder: %v", err) 84 } 85 86 enc := hepmc.NewEncoder(w) 87 if enc == nil { 88 log.Fatalf("error creating HepMC encoder: %v", err) 89 } 90 defer enc.Close() 91 92 for ievt := 0; ; ievt++ { 93 lhevt, err := dec.Decode() 94 if err == io.EOF { 95 break 96 } 97 if err != nil { 98 log.Fatalf("error at event #%d: %v", ievt, err) 99 } 100 101 evt := hepmc.Event{ 102 EventNumber: ievt + 1, 103 Particles: make(map[int]*hepmc.Particle), 104 Vertices: make(map[int]*hepmc.Vertex), 105 Weights: hepmc.NewWeights(), 106 } 107 108 // define the units 109 evt.MomentumUnit = hepmc.GEV 110 evt.LengthUnit = hepmc.MM 111 112 weight := lhevt.XWGTUP 113 err = evt.Weights.Add("0", weight) 114 if err != nil { 115 log.Fatalf("could not add weights: %+v", err) 116 } 117 118 xsecval := -1.0 119 xsecerr := -1.0 120 switch math.Abs(float64(dec.Run.IDWTUP)) { 121 case 3: 122 xsecval = dec.Run.XSECUP[0] 123 xsecerr = dec.Run.XSECUP[1] 124 125 case 4: 126 sumw += weight 127 sumw2 += weight * weight 128 nevt++ 129 xsecval = sumw / float64(nevt) 130 xsecerr2 := (sumw2/float64(nevt) - xsecval*xsecval) / float64(nevt) 131 132 if xsecerr2 < 0 { 133 log.Printf("WARNING: event #%d: xsecerr^2 < 0. forcing to zero. (xsecerr^2=%g)\n", ievt, xsecerr2) 134 xsecerr2 = 0. 135 } 136 xsecerr = math.Sqrt(xsecerr2) 137 138 default: 139 log.Fatalf("IDWTUP=%v value not handled yet", dec.Run.IDWTUP) 140 } 141 142 evt.CrossSection = &hepmc.CrossSection{Value: xsecval, Error: xsecerr} 143 vtx := hepmc.Vertex{ 144 Event: &evt, 145 Barcode: -1, 146 } 147 p1 := hepmc.Particle{ 148 Momentum: fmom.NewPxPyPzE( 149 0, 0, 150 dec.Run.EBMUP[0], 151 dec.Run.EBMUP[0], 152 ), 153 PdgID: dec.Run.IDBMUP[0], 154 Status: 4, 155 Barcode: 1, 156 } 157 p2 := hepmc.Particle{ 158 Momentum: fmom.NewPxPyPzE( 159 0, 0, 160 dec.Run.EBMUP[1], 161 dec.Run.EBMUP[1], 162 ), 163 PdgID: dec.Run.IDBMUP[1], 164 Status: 4, 165 Barcode: 2, 166 } 167 err = vtx.AddParticleIn(&p1) 168 if err != nil { 169 log.Fatalf("error at event #%d: %v", ievt, err) 170 } 171 err = vtx.AddParticleIn(&p2) 172 if err != nil { 173 log.Fatalf("error at event #%d: %v\n", ievt, err) 174 } 175 evt.Beams[0] = &p1 176 evt.Beams[1] = &p2 177 178 nmax := 2 179 imax := int(lhevt.NUP) 180 for i := range imax { 181 if !*keep && lhevt.ISTUP[i] != 1 { 182 continue 183 } 184 nmax += 1 185 err = vtx.AddParticleOut(&hepmc.Particle{ 186 Momentum: fmom.NewPxPyPzE( 187 lhevt.PUP[i][0], 188 lhevt.PUP[i][1], 189 lhevt.PUP[i][2], 190 lhevt.PUP[i][3], 191 ), 192 GeneratedMass: lhevt.PUP[i][4], 193 PdgID: lhevt.IDUP[i], 194 Status: int(lhevt.ISTUP[i]), 195 Barcode: 3 + i, 196 }) 197 if err != nil { 198 log.Fatalf("could not add out-particle: %+v", err) 199 } 200 } 201 err = evt.AddVertex(&vtx) 202 if err != nil { 203 log.Fatalf("error at event #%d: %v\n", ievt, err) 204 } 205 206 nparts := len(evt.Particles) 207 if nmax != nparts { 208 log.Printf("error at event #%d: LHEF/HEPMC inconsistency (LHEF particles: %d, HEPMC particles: %d)\n", ievt, nmax, nparts) 209 for _, p := range evt.Particles { 210 log.Printf("part: %v\n", p) 211 } 212 log.Printf("p1: %v\n", p1) 213 log.Printf("p2: %v\n", p2) 214 os.Exit(1) 215 } 216 if len(evt.Vertices) != 1 { 217 log.Fatalf("error at event #%d: inconsistent number of vertices in HEPMC (got %d, expected 1)\n", ievt, len(evt.Vertices)) 218 } 219 220 err = enc.Encode(&evt) 221 if err != nil { 222 log.Fatalf("error at event #%d: %v\n", ievt, err) 223 } 224 } 225 }