go-hep.org/x/hep@v0.38.1/lcio/writer_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 lcio_test
     6  
     7  import (
     8  	"compress/flate"
     9  	"encoding/hex"
    10  	"fmt"
    11  	"log"
    12  	"os"
    13  	"reflect"
    14  	"strings"
    15  	"testing"
    16  
    17  	"go-hep.org/x/hep/lcio"
    18  )
    19  
    20  func ExampleWriter() {
    21  	w, err := lcio.Create("out.slcio")
    22  	if err != nil {
    23  		log.Fatal(err)
    24  	}
    25  	defer w.Close()
    26  
    27  	run := lcio.RunHeader{
    28  		RunNumber:    42,
    29  		Descr:        "a simple run header",
    30  		Detector:     "my detector",
    31  		SubDetectors: []string{"det-1", "det-2"},
    32  		Params: lcio.Params{
    33  			Floats: map[string][]float32{
    34  				"floats-1": {1, 2, 3},
    35  				"floats-2": {4, 5, 6},
    36  			},
    37  		},
    38  	}
    39  
    40  	err = w.WriteRunHeader(&run)
    41  	if err != nil {
    42  		log.Fatal(err)
    43  	}
    44  
    45  	const NEVENTS = 1
    46  	for ievt := range NEVENTS {
    47  		evt := lcio.Event{
    48  			RunNumber:   run.RunNumber,
    49  			Detector:    run.Detector,
    50  			EventNumber: 52 + int32(ievt),
    51  			TimeStamp:   1234567890 + int64(ievt),
    52  			Params: lcio.Params{
    53  				Floats: map[string][]float32{
    54  					"_weight": {42},
    55  				},
    56  				Strings: map[string][]string{
    57  					"Descr": {"a description"},
    58  				},
    59  			},
    60  		}
    61  
    62  		calhits := lcio.CalorimeterHitContainer{
    63  			Flags: lcio.BitsRChLong | lcio.BitsRChID1 | lcio.BitsRChTime | lcio.BitsRChNoPtr | lcio.BitsRChEnergyError,
    64  			Params: lcio.Params{
    65  				Floats:  map[string][]float32{"f32": {1, 2, 3}},
    66  				Ints:    map[string][]int32{"i32": {1, 2, 3}},
    67  				Strings: map[string][]string{"str": {"1", "2", "3"}},
    68  			},
    69  			Hits: []lcio.CalorimeterHit{
    70  				{
    71  					CellID0:   1024,
    72  					CellID1:   2048,
    73  					Energy:    1000,
    74  					EnergyErr: 0.1,
    75  					Time:      1234,
    76  					Pos:       [3]float32{11, 22, 33},
    77  					Type:      42,
    78  				},
    79  			},
    80  		}
    81  
    82  		evt.Add("CaloHits", &calhits)
    83  
    84  		fmt.Printf("evt has key %q: %v\n", "CaloHits", evt.Has("CaloHits"))
    85  
    86  		err = w.WriteEvent(&evt)
    87  		if err != nil {
    88  			log.Fatal(err)
    89  		}
    90  	}
    91  
    92  	err = w.Close()
    93  	if err != nil {
    94  		log.Fatal(err)
    95  	}
    96  
    97  	// Output:
    98  	// evt has key "CaloHits": true
    99  }
   100  
   101  func TestCreateRunHeader(t *testing.T) {
   102  	testCreateRunHeader(t, flate.NoCompression, "testdata/run-header.slcio")
   103  }
   104  
   105  func TestCreateCompressedRunHeader(t *testing.T) {
   106  	testCreateRunHeader(t, flate.BestCompression, "testdata/run-header-compressed.slcio")
   107  }
   108  
   109  func TestCreateEvent(t *testing.T) {
   110  	testCreateEvent(t, flate.NoCompression, "testdata/event.slcio")
   111  }
   112  
   113  func TestCreateCompressedEvent(t *testing.T) {
   114  	testCreateEvent(t, flate.BestCompression, "testdata/event-compressed.slcio")
   115  }
   116  
   117  func testCreateRunHeader(t *testing.T, compLevel int, fname string) {
   118  	w, err := lcio.Create(fname)
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  	defer w.Close()
   123  
   124  	w.SetCompressionLevel(compLevel)
   125  
   126  	rhdr := lcio.RunHeader{
   127  		RunNumber:    42,
   128  		Descr:        "a simple run header",
   129  		Detector:     "my detector",
   130  		SubDetectors: []string{"det-1", "det-2"},
   131  		Params: lcio.Params{
   132  			Floats: map[string][]float32{
   133  				"floats-1": {1, 2, 3},
   134  				"floats-2": {4, 5, 6},
   135  			},
   136  			Ints: map[string][]int32{
   137  				"ints-1": {1, 2, 3},
   138  				"ints-2": {4, 5, 6},
   139  			},
   140  			Strings: map[string][]string{
   141  				"strs-1": {"1", "2", "3"},
   142  			},
   143  		},
   144  	}
   145  
   146  	err = w.WriteRunHeader(&rhdr)
   147  	if err != nil {
   148  		t.Error(err)
   149  		return
   150  	}
   151  
   152  	err = w.Close()
   153  	if err != nil {
   154  		t.Error(err)
   155  		return
   156  	}
   157  
   158  	chk, err := os.ReadFile(fname)
   159  	if err != nil {
   160  		t.Error(err)
   161  		return
   162  	}
   163  
   164  	ref, err := os.ReadFile(strings.Replace(fname, ".slcio", "_golden.slcio", -1))
   165  	if err != nil {
   166  		t.Error(err)
   167  		return
   168  	}
   169  
   170  	if !reflect.DeepEqual(ref, chk) {
   171  		t.Errorf("%s: --- ref ---\n%s\n", fname, hex.Dump(ref))
   172  		t.Errorf("%s: --- chk ---\n%s\n", fname, hex.Dump(chk))
   173  		t.Errorf("%s: differ with golden", fname)
   174  		return
   175  	}
   176  
   177  	os.Remove(fname)
   178  }
   179  
   180  func testCreateEvent(t *testing.T, compLevel int, fname string) {
   181  	w, err := lcio.Create(fname)
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	defer w.Close()
   186  	w.SetCompressionLevel(compLevel)
   187  
   188  	rhdr := lcio.RunHeader{
   189  		RunNumber:    42,
   190  		Descr:        "a simple run header",
   191  		Detector:     "my detector",
   192  		SubDetectors: []string{"det-1", "det-2"},
   193  		Params: lcio.Params{
   194  			Floats: map[string][]float32{
   195  				"floats-1": {1, 2, 3},
   196  				"floats-2": {4, 5, 6},
   197  			},
   198  			Strings: map[string][]string{
   199  				"strings-1": {"1", "2", "3"},
   200  			},
   201  			Ints: map[string][]int32{
   202  				"ints-1": {1, 2, 3},
   203  			},
   204  		},
   205  	}
   206  
   207  	err = w.WriteRunHeader(&rhdr)
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  
   212  	evt := lcio.Event{
   213  		RunNumber:   rhdr.RunNumber,
   214  		Detector:    rhdr.Detector,
   215  		EventNumber: 52,
   216  		TimeStamp:   1234567890,
   217  		Params: lcio.Params{
   218  			Floats: map[string][]float32{
   219  				"_weight": {42},
   220  			},
   221  			Strings: map[string][]string{
   222  				"Descr": {"a description"},
   223  			},
   224  			Ints: map[string][]int32{
   225  				"ints": {10, 20, 30},
   226  			},
   227  		},
   228  	}
   229  
   230  	if evt.Has("not-there") {
   231  		t.Errorf("got an unexpected collection")
   232  	}
   233  
   234  	mcparts := lcio.McParticleContainer{
   235  		Flags: 0x1234,
   236  		Params: lcio.Params{
   237  			Floats:  map[string][]float32{},
   238  			Strings: map[string][]string{},
   239  			Ints:    map[string][]int32{},
   240  		},
   241  	}
   242  	for i := range 3 {
   243  		i32 := int32(i+1) * 10
   244  		f32 := float32(i+1) * 10
   245  		f64 := float64(i+1) * 10
   246  		mc := lcio.McParticle{
   247  			PDG:       i32,
   248  			Mass:      f64,
   249  			Charge:    f32,
   250  			P:         [3]float64{f64, f64, f64},
   251  			PEndPoint: [3]float64{f64, f64, f64},
   252  			GenStatus: int32(i + 1),
   253  			SimStatus: 1 << 31,
   254  			ColorFlow: [2]int32{i32, i32},
   255  			Spin:      [3]float32{f32, f32, f32},
   256  		}
   257  		mcparts.Particles = append(mcparts.Particles, mc)
   258  	}
   259  	mcparts.Particles[1].Parents = []*lcio.McParticle{&mcparts.Particles[0], &mcparts.Particles[2]}
   260  	mcparts.Particles[0].Children = []*lcio.McParticle{&mcparts.Particles[1]}
   261  	mcparts.Particles[2].Children = []*lcio.McParticle{&mcparts.Particles[1]}
   262  
   263  	simhits := lcio.SimCalorimeterHitContainer{
   264  		Flags: lcio.BitsChLong | lcio.BitsChID1 | lcio.BitsChStep | lcio.BitsChPDG,
   265  		Params: lcio.Params{
   266  			Strings: map[string][]string{
   267  				"CellIDEncoding": {"M:3,S-1:3,I:9,J:9,K-1:6"},
   268  			},
   269  			Floats: map[string][]float32{},
   270  			Ints:   map[string][]int32{},
   271  		},
   272  		Hits: []lcio.SimCalorimeterHit{
   273  			{
   274  				CellID0: 1024, CellID1: 256, Energy: 42.666, Pos: [3]float32{1, 2, 3},
   275  				Contributions: []lcio.Contrib{
   276  					{Energy: 10, Mc: &mcparts.Particles[0]},
   277  					{Energy: 11, Mc: &mcparts.Particles[1]},
   278  				},
   279  			},
   280  			{
   281  				CellID0: 1025, CellID1: 256, Energy: 42.666, Pos: [3]float32{1, 2, 3},
   282  				Contributions: []lcio.Contrib{
   283  					{Energy: 10, Mc: &mcparts.Particles[0]},
   284  					{Energy: 11, Mc: &mcparts.Particles[1]},
   285  					{Energy: 12, Mc: &mcparts.Particles[2]},
   286  				},
   287  			},
   288  		},
   289  	}
   290  
   291  	calhits := lcio.CalorimeterHitContainer{
   292  		Flags: lcio.BitsRChLong | lcio.BitsRChID1 | lcio.BitsRChTime | lcio.BitsRChNoPtr | lcio.BitsRChEnergyError,
   293  		Params: lcio.Params{
   294  			Floats:  map[string][]float32{"f32": {1, 2, 3}},
   295  			Ints:    map[string][]int32{"i32": {1, 2, 3}},
   296  			Strings: map[string][]string{"str": {"1", "2", "3"}},
   297  		},
   298  		Hits: []lcio.CalorimeterHit{
   299  			{
   300  				CellID0:   1024,
   301  				CellID1:   2048,
   302  				Energy:    1000,
   303  				EnergyErr: 0.1,
   304  				Time:      1234,
   305  				Pos:       [3]float32{11, 22, 33},
   306  				Type:      42,
   307  			},
   308  		},
   309  	}
   310  
   311  	evt.Add("McParticles", &mcparts)
   312  	evt.Add("SimCaloHits", &simhits)
   313  	evt.Add("CaloHits", &calhits)
   314  
   315  	if key := "McParticles"; !evt.Has(key) {
   316  		t.Errorf("expected to have key %q", key)
   317  	}
   318  
   319  	err = w.WriteEvent(&evt)
   320  	if err != nil {
   321  		t.Fatal(err)
   322  	}
   323  
   324  	err = w.Close()
   325  	if err != nil {
   326  		t.Fatal(err)
   327  	}
   328  
   329  	r, err := lcio.Open(fname)
   330  	if err != nil {
   331  		t.Fatal(err)
   332  	}
   333  	defer r.Close()
   334  
   335  	r.Next()
   336  	if r.Err() != nil {
   337  		t.Fatal(r.Err())
   338  	}
   339  
   340  	if got, want := r.RunHeader(), rhdr; !reflect.DeepEqual(got, want) {
   341  		t.Fatalf("%s: run-headers differ.\ngot= %#v\nwant=%#v\n", fname, got, want)
   342  	}
   343  
   344  	if got, want := r.Event(), evt; !reflect.DeepEqual(got, want) {
   345  		t.Fatalf("%s: evts differ.\ngot:\n%v\nwant:\n%v\n", fname, &got, &want)
   346  	}
   347  
   348  	chk, err := os.ReadFile(fname)
   349  	if err != nil {
   350  		t.Fatal(err)
   351  	}
   352  
   353  	ref, err := os.ReadFile(strings.Replace(fname, ".slcio", "_golden.slcio", -1))
   354  	if err != nil {
   355  		t.Fatal(err)
   356  	}
   357  
   358  	if !reflect.DeepEqual(ref, chk) {
   359  		t.Errorf("%s: --- ref ---\n%s\n", fname, hex.Dump(ref))
   360  		t.Errorf("%s: --- chk ---\n%s\n", fname, hex.Dump(chk))
   361  		t.Fatalf("%s: differ with golden", fname)
   362  	}
   363  
   364  	os.Remove(fname)
   365  }