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 }