go-hep.org/x/hep@v0.38.1/hepmc/hepmc_test.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_test
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"log"
    12  	"os"
    13  	"testing"
    14  
    15  	"go-hep.org/x/hep/fmom"
    16  	"go-hep.org/x/hep/hepmc"
    17  	"go-hep.org/x/hep/internal/diff"
    18  )
    19  
    20  func TestEventRW(t *testing.T) {
    21  	for _, table := range []struct {
    22  		fname    string
    23  		outfname string
    24  		nevts    int
    25  	}{
    26  		{"testdata/small.hepmc", "out.small.hepmc", 1},
    27  		{"testdata/test.hepmc", "out.hepmc", 6},
    28  		{"out.hepmc", "rb.out.hepmc", 6},
    29  	} {
    30  		t.Run(table.fname, func(t *testing.T) {
    31  			testEventRW(t, table.fname, table.outfname, table.nevts)
    32  		})
    33  	}
    34  
    35  	// clean-up
    36  	for _, fname := range []string{"out.small.hepmc", "out.hepmc", "rb.out.hepmc"} {
    37  		err := os.Remove(fname)
    38  		if err != nil {
    39  			t.Fatal(err)
    40  		}
    41  	}
    42  }
    43  
    44  func testEventRW(t *testing.T, fname, outfname string, nevts int) {
    45  	f, err := os.Open(fname)
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	defer f.Close()
    50  
    51  	dec := hepmc.NewDecoder(f)
    52  	if dec == nil {
    53  		t.Fatalf("hepmc.decoder: nil decoder")
    54  	}
    55  
    56  	const NEVTS = 10
    57  	evts := make([]*hepmc.Event, 0, NEVTS)
    58  	for ievt := range NEVTS {
    59  		var evt hepmc.Event
    60  		err = dec.Decode(&evt)
    61  		if err != nil {
    62  			if err == io.EOF && ievt == nevts {
    63  				break
    64  			}
    65  			t.Fatalf("file: %s. ievt=%d err=%v\n", fname, ievt, err)
    66  		}
    67  		evts = append(evts, &evt)
    68  		defer func() {
    69  			err = hepmc.Delete(&evt)
    70  			if err != nil {
    71  				t.Fatalf("error: %+v", err)
    72  			}
    73  		}()
    74  	}
    75  
    76  	o, err := os.Create(outfname)
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  	defer o.Close()
    81  
    82  	enc := hepmc.NewEncoder(o)
    83  	if enc == nil {
    84  		t.Fatal(fmt.Errorf("hepmc.encoder: nil encoder"))
    85  	}
    86  	for _, evt := range evts {
    87  		err = enc.Encode(evt)
    88  		if err != nil {
    89  			t.Fatalf("file: %s. err=%v\n", fname, err)
    90  		}
    91  	}
    92  	err = enc.Close()
    93  	if err != nil {
    94  		t.Fatalf("file: %s. err=%v\n", fname, err)
    95  	}
    96  
    97  	err = o.Close()
    98  	if err != nil {
    99  		t.Fatalf("error closing output file %q: %v", outfname, err)
   100  	}
   101  
   102  	// test output files
   103  	err = diff.Files(outfname, fname)
   104  	if err != nil {
   105  		t.Fatalf("file: %s\n%+v", fname, err)
   106  	}
   107  }
   108  
   109  type reader struct {
   110  	header []byte
   111  	footer []byte
   112  	data   []byte
   113  	pos    int
   114  }
   115  
   116  func newReader() *reader {
   117  	r := &reader{
   118  		header: []byte(`
   119  HepMC::Version 2.06.09
   120  HepMC::IO_GenEvent-START_EVENT_LISTING
   121  `),
   122  		data: []byte(`E 1 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 20 -3 4 0 0 0 0
   123  U GEV MM
   124  F 0 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   125  V -1 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 1 1 0
   126  P 1 2212 0.0000000000000000e+00 0.0000000000000000e+00 7.0000000000000000e+03 7.0000000000000000e+03 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -1 0
   127  P 3 1 7.5000000000000000e-01 -1.5690000000000000e+00 3.2191000000000003e+01 3.2238000000000000e+01 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -3 0
   128  V -2 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 1 1 0
   129  P 2 2212 0.0000000000000000e+00 0.0000000000000000e+00 -7.0000000000000000e+03 7.0000000000000000e+03 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -2 0
   130  P 4 -2 -3.0470000000000002e+00 -1.9000000000000000e+01 -5.4628999999999998e+01 5.7920000000000002e+01 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -3 0
   131  V -3 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0 2 0
   132  P 5 22 -3.8130000000000002e+00 1.1300000000000000e-01 -1.8330000000000000e+00 4.2329999999999997e+00 0.0000000000000000e+00 1 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   133  P 6 -24 1.5169999999999999e+00 -2.0680000000000000e+01 -2.0605000000000000e+01 8.5924999999999997e+01 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -4 0
   134  V -4 0 1.2000000000000000e-01 -2.9999999999999999e-01 5.0000000000000003e-02 4.0000000000000001e-03 0 2 0
   135  P 7 1 -2.4449999999999998e+00 2.8815999999999999e+01 6.0819999999999999e+00 2.9552000000000000e+01 0.0000000000000000e+00 1 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   136  P 8 -2 3.9620000000000002e+00 -4.9497999999999998e+01 -2.6687000000000001e+01 5.6372999999999998e+01 0.0000000000000000e+00 1 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   137  `),
   138  		footer: []byte(`HepMC::IO_GenEvent-END_EVENT_LISTING
   139  `),
   140  	}
   141  
   142  	return r
   143  }
   144  
   145  func (r *reader) Read(data []byte) (int, error) {
   146  	return r.read(data)
   147  }
   148  
   149  func (r *reader) read(dst []byte) (int, error) {
   150  	n := 0
   151  	for n < len(dst) {
   152  		// printf("::read - n=%d dst=%d...\n", n, len(dst))
   153  		if len(r.header) > 0 {
   154  			// printf(":: header...\n")
   155  			sz := copy(dst, r.header)
   156  			n += sz
   157  			r.header = nil
   158  		}
   159  		end := len(dst[n:])
   160  		if end > len(r.data[r.pos:]) {
   161  			end = len(r.data[r.pos:]) + r.pos
   162  		}
   163  		// printf(":: copy(dst[%d:], data[%d:%d])...\n", n, r.pos, end)
   164  		sz := copy(dst[n:], r.data[r.pos:end])
   165  		// printf(":: copy(dst[%d:], data[%d:%d]) -> %d\n", n, r.pos, end, sz)
   166  		n += sz
   167  		if r.pos+sz >= len(r.data) {
   168  			r.pos = 0
   169  		} else {
   170  			r.pos += sz
   171  		}
   172  	}
   173  	return n, nil
   174  }
   175  
   176  func TestRead(t *testing.T) {
   177  	r := newReader()
   178  	dec := hepmc.NewDecoder(r)
   179  	if dec == nil {
   180  		t.Fatal(fmt.Errorf("hepmc.decoder: nil decoder"))
   181  	}
   182  
   183  	const NEVTS = 10
   184  	const fname = "small.hepmc"
   185  	for ievt := range NEVTS {
   186  		var evt hepmc.Event
   187  		err := dec.Decode(&evt)
   188  		if err != nil {
   189  			if err == io.EOF && ievt == NEVTS {
   190  				break
   191  			}
   192  			t.Fatalf("file: %s. ievt=%d err=%v\n", fname, ievt, err)
   193  		}
   194  		err = hepmc.Delete(&evt)
   195  		if err != nil {
   196  			t.Fatalf("error: %+v", err)
   197  		}
   198  	}
   199  }
   200  
   201  func BenchmarkDecode(b *testing.B) {
   202  	r := newReader()
   203  	dec := hepmc.NewDecoder(r)
   204  	if dec == nil {
   205  		b.Fatalf("hepmc.decoder: nil decoder")
   206  	}
   207  
   208  	const fname = "small.hepmc"
   209  
   210  	{
   211  		var evt hepmc.Event
   212  		err := dec.Decode(&evt)
   213  		if err != nil {
   214  			b.Fatalf("error: %v\n", err)
   215  		}
   216  		_ = hepmc.Delete(&evt)
   217  	}
   218  
   219  	b.ResetTimer()
   220  
   221  	for i := 0; i < b.N; i++ {
   222  		var evt hepmc.Event
   223  		err := dec.Decode(&evt)
   224  		if err != nil {
   225  			if err == io.EOF {
   226  				break
   227  			}
   228  			b.Fatalf("file: %s. ievt=%d err=%v\n", fname, i, err)
   229  		}
   230  		_ = hepmc.Delete(&evt)
   231  	}
   232  
   233  }
   234  
   235  // This example will place the following event into HepMC "by hand"
   236  //
   237  //	   name status pdg_id  parent Px       Py    Pz       Energy      Mass
   238  //	1  !p+!    3   2212    0,0    0.000    0.000 7000.000 7000.000    0.938
   239  //	2  !p+!    3   2212    0,0    0.000    0.000-7000.000 7000.000    0.938
   240  //
   241  // =========================================================================
   242  //
   243  //	3  !d!     3      1    1,1    0.750   -1.569   32.191   32.238    0.000
   244  //	4  !u~!    3     -2    2,2   -3.047  -19.000  -54.629   57.920    0.000
   245  //	5  !W-!    3    -24    1,2    1.517   -20.68  -20.605   85.925   80.799
   246  //	6  !gamma! 1     22    1,2   -3.813    0.113   -1.833    4.233    0.000
   247  //	7  !d!     1      1    5,5   -2.445   28.816    6.082   29.552    0.010
   248  //	8  !u~!    1     -2    5,5    3.962  -49.498  -26.687   56.373    0.006
   249  //
   250  // now we build the graph, which will look like
   251  //
   252  //	#                       p7                         #
   253  //	# p1                   /                           #
   254  //	#   \v1__p3      p5---v4                           #
   255  //	#         \_v3_/       \                           #
   256  //	#         /    \        p8                         #
   257  //	#    v2__p4     \                                  #
   258  //	#   /            p6                                #
   259  //	# p2                                               #
   260  //	#                                                  #
   261  func ExampleEvent_buildFromScratch() {
   262  	var err error
   263  
   264  	// first create the event container, with signal process 20, event number 1
   265  	evt := hepmc.Event{
   266  		SignalProcessID: 20,
   267  		EventNumber:     1,
   268  		Particles:       make(map[int]*hepmc.Particle),
   269  		Vertices:        make(map[int]*hepmc.Vertex),
   270  	}
   271  	defer func() {
   272  		err = evt.Delete()
   273  		if err != nil {
   274  			log.Fatalf("could not clean-up event: %+v", err)
   275  		}
   276  	}()
   277  
   278  	// define the units
   279  	evt.MomentumUnit = hepmc.GEV
   280  	evt.LengthUnit = hepmc.MM
   281  
   282  	// create vertex 1 and 2, together with their in-particles
   283  	v1 := &hepmc.Vertex{}
   284  	err = evt.AddVertex(v1)
   285  	if err != nil {
   286  		log.Fatal(err)
   287  	}
   288  
   289  	err = v1.AddParticleIn(&hepmc.Particle{
   290  		Momentum: fmom.NewPxPyPzE(0, 0, 7000, 7000),
   291  		PdgID:    2212,
   292  		Status:   3,
   293  	})
   294  	if err != nil {
   295  		log.Fatal(err)
   296  	}
   297  
   298  	v2 := &hepmc.Vertex{}
   299  	err = evt.AddVertex(v2)
   300  	if err != nil {
   301  		log.Fatal(err)
   302  	}
   303  
   304  	err = v2.AddParticleIn(&hepmc.Particle{
   305  		Momentum: fmom.NewPxPyPzE(0, 0, -7000, 7000),
   306  		PdgID:    2212,
   307  		Status:   3,
   308  		//Barcode:  2,
   309  	})
   310  	if err != nil {
   311  		log.Fatal(err)
   312  	}
   313  
   314  	// create the outgoing particles of v1 and v2
   315  	p3 := &hepmc.Particle{
   316  		Momentum: fmom.NewPxPyPzE(.750, -1.569, 32.191, 32.238),
   317  		PdgID:    1,
   318  		Status:   3,
   319  		// Barcode: 3,
   320  	}
   321  	err = v1.AddParticleOut(p3)
   322  	if err != nil {
   323  		log.Fatal(err)
   324  	}
   325  
   326  	p4 := &hepmc.Particle{
   327  		Momentum: fmom.NewPxPyPzE(-3.047, -19., -54.629, 57.920),
   328  		PdgID:    -2,
   329  		Status:   3,
   330  		// Barcode: 4,
   331  	}
   332  	err = v2.AddParticleOut(p4)
   333  	if err != nil {
   334  		log.Fatal(err)
   335  	}
   336  
   337  	// create v3
   338  	v3 := &hepmc.Vertex{}
   339  	err = evt.AddVertex(v3)
   340  	if err != nil {
   341  		log.Fatal(err)
   342  	}
   343  
   344  	err = v3.AddParticleIn(p3)
   345  	if err != nil {
   346  		log.Fatal(err)
   347  	}
   348  
   349  	err = v3.AddParticleIn(p4)
   350  	if err != nil {
   351  		log.Fatal(err)
   352  	}
   353  
   354  	err = v3.AddParticleOut(&hepmc.Particle{
   355  		Momentum: fmom.NewPxPyPzE(-3.813, 0.113, -1.833, 4.233),
   356  		PdgID:    22,
   357  		Status:   1,
   358  	})
   359  	if err != nil {
   360  		log.Fatal(err)
   361  	}
   362  
   363  	p5 := &hepmc.Particle{
   364  		Momentum: fmom.NewPxPyPzE(1.517, -20.68, -20.605, 85.925),
   365  		PdgID:    -24,
   366  		Status:   3,
   367  	}
   368  	err = v3.AddParticleOut(p5)
   369  	if err != nil {
   370  		log.Fatal(err)
   371  	}
   372  
   373  	// create v4
   374  	v4 := &hepmc.Vertex{
   375  		Position: fmom.NewPxPyPzE(0.12, -0.3, 0.05, 0.004),
   376  	}
   377  	err = evt.AddVertex(v4)
   378  	if err != nil {
   379  		log.Fatal(err)
   380  	}
   381  
   382  	err = v4.AddParticleIn(p5)
   383  	if err != nil {
   384  		log.Fatal(err)
   385  	}
   386  
   387  	err = v4.AddParticleOut(&hepmc.Particle{
   388  		Momentum: fmom.NewPxPyPzE(-2.445, 28.816, 6.082, 29.552),
   389  		PdgID:    1,
   390  		Status:   1,
   391  	})
   392  	if err != nil {
   393  		log.Fatal(err)
   394  	}
   395  
   396  	err = v4.AddParticleOut(&hepmc.Particle{
   397  		Momentum: fmom.NewPxPyPzE(3.962, -49.498, -26.687, 56.373),
   398  		PdgID:    -2,
   399  		Status:   1,
   400  	})
   401  	if err != nil {
   402  		log.Fatal(err)
   403  	}
   404  
   405  	evt.SignalVertex = v3
   406  
   407  	err = evt.Print(os.Stdout)
   408  	if err != nil {
   409  		log.Fatal(err)
   410  	}
   411  
   412  	out := new(bytes.Buffer)
   413  	enc := hepmc.NewEncoder(out)
   414  	err = enc.Encode(&evt)
   415  	if err != nil {
   416  		log.Fatal(err)
   417  	}
   418  
   419  	fmt.Printf("%s\n", out.Bytes())
   420  
   421  	// Output:
   422  	// ________________________________________________________________________________
   423  	// GenEvent: #0001 ID=   20 SignalProcessGenVertex Barcode: -3
   424  	//  Momentum units:     GEV     Position units:      MM
   425  	//  Entries this event: 4 vertices, 8 particles.
   426  	//  Beam Particles are not defined.
   427  	//  RndmState(0)=
   428  	//  Wgts(0)=
   429  	//  EventScale 0.00000 [energy] 	 alphaQCD=0.00000000	 alphaQED=0.00000000
   430  	//                                     GenParticle Legend
   431  	//         Barcode   PDG ID      ( Px,       Py,       Pz,     E ) Stat  DecayVtx
   432  	// ________________________________________________________________________________
   433  	// GenVertex:       -1 ID:    0 (X,cT):0
   434  	//  I: 1         1     2212 +0.00e+00,+0.00e+00,+7.00e+03,+7.00e+03   3        -1
   435  	//  O: 1         3        1 +7.50e-01,-1.57e+00,+3.22e+01,+3.22e+01   3        -3
   436  	// GenVertex:       -2 ID:    0 (X,cT):0
   437  	//  I: 1         2     2212 +0.00e+00,+0.00e+00,-7.00e+03,+7.00e+03   3        -2
   438  	//  O: 1         4       -2 -3.05e+00,-1.90e+01,-5.46e+01,+5.79e+01   3        -3
   439  	// GenVertex:       -3 ID:    0 (X,cT):0
   440  	//  I: 2         3        1 +7.50e-01,-1.57e+00,+3.22e+01,+3.22e+01   3        -3
   441  	//               4       -2 -3.05e+00,-1.90e+01,-5.46e+01,+5.79e+01   3        -3
   442  	//  O: 2         5       22 -3.81e+00,+1.13e-01,-1.83e+00,+4.23e+00   1
   443  	//               6      -24 +1.52e+00,-2.07e+01,-2.06e+01,+8.59e+01   3        -4
   444  	// Vertex:       -4 ID:    0 (X,cT)=+1.20e-01,-3.00e-01,+5.00e-02,+4.00e-03
   445  	//  I: 1         6      -24 +1.52e+00,-2.07e+01,-2.06e+01,+8.59e+01   3        -4
   446  	//  O: 2         7        1 -2.44e+00,+2.88e+01,+6.08e+00,+2.96e+01   1
   447  	//               8       -2 +3.96e+00,-4.95e+01,-2.67e+01,+5.64e+01   1
   448  	// ________________________________________________________________________________
   449  	//
   450  	// HepMC::Version 2.06.09
   451  	// HepMC::IO_GenEvent-START_EVENT_LISTING
   452  	// E 1 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 20 -3 4 0 0 0 0
   453  	// U GEV MM
   454  	// F 0 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   455  	// V -1 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 1 1 0
   456  	// P 1 2212 0.0000000000000000e+00 0.0000000000000000e+00 7.0000000000000000e+03 7.0000000000000000e+03 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -1 0
   457  	// P 3 1 7.5000000000000000e-01 -1.5690000000000000e+00 3.2191000000000003e+01 3.2238000000000000e+01 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -3 0
   458  	// V -2 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 1 1 0
   459  	// P 2 2212 0.0000000000000000e+00 0.0000000000000000e+00 -7.0000000000000000e+03 7.0000000000000000e+03 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -2 0
   460  	// P 4 -2 -3.0470000000000002e+00 -1.9000000000000000e+01 -5.4628999999999998e+01 5.7920000000000002e+01 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -3 0
   461  	// V -3 0 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0.0000000000000000e+00 0 2 0
   462  	// P 5 22 -3.8130000000000002e+00 1.1300000000000000e-01 -1.8330000000000000e+00 4.2329999999999997e+00 0.0000000000000000e+00 1 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   463  	// P 6 -24 1.5169999999999999e+00 -2.0680000000000000e+01 -2.0605000000000000e+01 8.5924999999999997e+01 0.0000000000000000e+00 3 0.0000000000000000e+00 0.0000000000000000e+00 -4 0
   464  	// V -4 0 1.2000000000000000e-01 -2.9999999999999999e-01 5.0000000000000003e-02 4.0000000000000001e-03 0 2 0
   465  	// P 7 1 -2.4449999999999998e+00 2.8815999999999999e+01 6.0819999999999999e+00 2.9552000000000000e+01 0.0000000000000000e+00 1 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   466  	// P 8 -2 3.9620000000000002e+00 -4.9497999999999998e+01 -2.6687000000000001e+01 5.6372999999999998e+01 0.0000000000000000e+00 1 0.0000000000000000e+00 0.0000000000000000e+00 0 0
   467  	//
   468  }