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  }