go-hep.org/x/hep@v0.38.1/groot/rhist/rw_test.go (about) 1 // Copyright ©2018 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 rhist 6 7 import ( 8 "io" 9 "reflect" 10 "testing" 11 12 "go-hep.org/x/hep/groot/internal/rtests" 13 "go-hep.org/x/hep/groot/rbase" 14 "go-hep.org/x/hep/groot/rbytes" 15 "go-hep.org/x/hep/groot/rcont" 16 "go-hep.org/x/hep/groot/riofs" 17 "go-hep.org/x/hep/groot/root" 18 "go-hep.org/x/hep/groot/rtypes" 19 ) 20 21 func TestWRBuffer(t *testing.T) { 22 loadFrom := func(fname, key string) rtests.ROOTer { 23 t.Helper() 24 25 f, err := riofs.Open(fname) 26 if err != nil { 27 t.Fatal(err) 28 } 29 defer f.Close() 30 obj, err := riofs.Dir(f).Get(key) 31 if err != nil { 32 t.Fatal(err) 33 } 34 return obj.(rtests.ROOTer) 35 } 36 37 for _, tc := range []struct { 38 name string 39 want rtests.ROOTer 40 }{ 41 { 42 name: "TH1F", 43 want: &H1F{ 44 th1: th1{ 45 Named: *rbase.NewNamed("h1f", "my-title"), 46 attline: rbase.AttLine{Color: 602, Style: 1, Width: 1}, 47 attfill: rbase.AttFill{Color: 0, Style: 1001}, 48 attmarker: rbase.AttMarker{Color: 1, Style: 1, Width: 1}, 49 ncells: 102, 50 xaxis: taxis{ 51 Named: *rbase.NewNamed("xaxis", ""), 52 attaxis: rbase.AttAxis{ 53 Ndivs: 510, AxisColor: 1, LabelColor: 1, LabelFont: 42, LabelOffset: 0.005, LabelSize: 0.035, Ticks: 0.03, TitleOffset: 1, TitleSize: 0.035, TitleColor: 1, TitleFont: 42, 54 }, 55 nbins: 100, xmin: 0, xmax: 100, 56 xbins: rcont.ArrayD{Data: nil}, 57 first: 0, last: 0, bits2: 0x0, time: false, tfmt: "", 58 labels: nil, 59 modlabs: nil, 60 }, 61 yaxis: taxis{ 62 Named: *rbase.NewNamed("yaxis", ""), 63 attaxis: rbase.AttAxis{ 64 Ndivs: 510, AxisColor: 1, LabelColor: 1, LabelFont: 42, LabelOffset: 0.005, LabelSize: 0.035, Ticks: 0.03, TitleOffset: 1, TitleSize: 0.035, TitleColor: 1, TitleFont: 42, 65 }, 66 nbins: 1, xmin: 0, xmax: 1, 67 xbins: rcont.ArrayD{Data: nil}, 68 first: 0, last: 0, bits2: 0x0, time: false, tfmt: "", 69 labels: nil, 70 modlabs: nil, 71 }, 72 zaxis: taxis{ 73 Named: *rbase.NewNamed("zaxis", ""), 74 attaxis: rbase.AttAxis{ 75 Ndivs: 510, AxisColor: 1, LabelColor: 1, LabelFont: 42, LabelOffset: 0.005, LabelSize: 0.035, Ticks: 0.03, TitleOffset: 1, TitleSize: 0.035, TitleColor: 1, TitleFont: 42, 76 }, 77 nbins: 1, xmin: 0, xmax: 1, 78 xbins: rcont.ArrayD{Data: nil}, 79 first: 0, last: 0, bits2: 0x0, time: false, tfmt: "", 80 labels: nil, 81 modlabs: nil, 82 }, 83 boffset: 0, bwidth: 1000, 84 entries: 10, 85 tsumw: 10, tsumw2: 16, tsumwx: 278, tsumwx2: 9286, 86 max: -1111, min: -1111, 87 norm: 0, 88 contour: rcont.ArrayD{Data: nil}, 89 sumw2: rcont.ArrayD{ 90 Data: []float64{ 91 1, 92 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97 1, 98 }, 99 }, 100 opt: "", 101 funcs: *rcont.NewList("", []root.Object{}), 102 buffer: nil, 103 erropt: 0, 104 }, 105 arr: rcont.ArrayF{ 106 Data: []float32{ 107 1, 108 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113 1, 114 }, 115 }, 116 }, 117 }, 118 { 119 name: "TH2F", 120 want: &H2F{ 121 th2: th2{ 122 th1: th1{ 123 Named: *rbase.NewNamed("h2f", "my title"), 124 attline: rbase.AttLine{Color: 602, Style: 1, Width: 1}, 125 attfill: rbase.AttFill{Color: 0, Style: 1001}, 126 attmarker: rbase.AttMarker{Color: 1, Style: 1, Width: 1}, 127 ncells: 144, 128 xaxis: taxis{ 129 Named: *rbase.NewNamed("xaxis", ""), 130 attaxis: rbase.AttAxis{ 131 Ndivs: 510, AxisColor: 1, LabelColor: 1, LabelFont: 42, LabelOffset: 0.004999999888241291, LabelSize: 0.03500000014901161, 132 Ticks: 0.029999999329447746, TitleOffset: 1, TitleSize: 0.03500000014901161, TitleColor: 1, TitleFont: 42, 133 }, 134 nbins: 10, 135 xmin: 0, 136 xmax: 10, 137 xbins: rcont.ArrayD{}, 138 first: 0, 139 last: 0, 140 bits2: 0x0, 141 time: false, 142 tfmt: "", 143 labels: nil, 144 modlabs: nil, 145 }, 146 yaxis: taxis{ 147 Named: *rbase.NewNamed("yaxis", ""), 148 attaxis: rbase.AttAxis{ 149 Ndivs: 510, AxisColor: 1, LabelColor: 1, LabelFont: 42, LabelOffset: 0.004999999888241291, LabelSize: 0.03500000014901161, 150 Ticks: 0.029999999329447746, TitleOffset: 1, TitleSize: 0.03500000014901161, TitleColor: 1, TitleFont: 42, 151 }, 152 nbins: 10, 153 xmin: 0, 154 xmax: 10, 155 xbins: rcont.ArrayD{}, 156 first: 0, 157 last: 0, 158 bits2: 0x0, 159 time: false, 160 tfmt: "", 161 labels: nil, 162 modlabs: nil, 163 }, 164 zaxis: taxis{ 165 Named: *rbase.NewNamed("zaxis", ""), 166 attaxis: rbase.AttAxis{ 167 Ndivs: 510, AxisColor: 1, LabelColor: 1, LabelFont: 42, LabelOffset: 0.004999999888241291, LabelSize: 0.03500000014901161, 168 Ticks: 0.029999999329447746, TitleOffset: 1, TitleSize: 0.03500000014901161, TitleColor: 1, TitleFont: 42, 169 }, 170 nbins: 1, 171 xmin: 0, 172 xmax: 1, 173 xbins: rcont.ArrayD{}, 174 first: 0, 175 last: 0, 176 bits2: 0x0, 177 time: false, 178 tfmt: "", 179 labels: nil, 180 modlabs: nil, 181 }, 182 boffset: 0, 183 bwidth: 1000, 184 entries: 13, 185 tsumw: 9, 186 tsumw2: 29, 187 tsumwx: 21, 188 tsumwx2: 55, 189 max: -1111, 190 min: -1111, 191 norm: 0, 192 contour: rcont.ArrayD{}, 193 sumw2: rcont.ArrayD{ 194 Data: []float64{ 195 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 196 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 197 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 202 }, 203 }, 204 opt: "", 205 funcs: *rcont.NewList("", []root.Object{}), 206 buffer: nil, 207 erropt: 0, 208 }, 209 scale: 1, 210 tsumwy: 21, 211 tsumwy2: 55, 212 tsumwxy: 55, 213 }, 214 arr: rcont.ArrayF{ 215 Data: []float32{ 216 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 218 0, 1, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 222 0, 0, 0, 0, 0, 1, 223 }, 224 }, 225 }, 226 }, 227 { 228 name: "TConfidenceLevel", 229 want: &ConfidenceLevel{ 230 base: *rbase.NewObject(), 231 fNNMC: 3, 232 fDtot: 5, 233 fStot: 2, 234 fBtot: 3, 235 fTSD: 10, 236 fNMC: 11, 237 fMCL3S: 12, 238 fMCL5S: 13, 239 fTSB: []float64{11, 12, 13}, 240 fTSS: []float64{21, 22, 23}, 241 fLRS: []float64{31, 32, 33}, 242 fLRB: []float64{41, 42, 43}, 243 fISB: []int32{1, 2, 3}, 244 fISS: []int32{4, 5, 6}, 245 }, 246 }, 247 { 248 name: "TLimit", 249 want: &Limit{}, 250 }, 251 { 252 name: "TLimitDataSource", 253 want: &LimitDataSource{ 254 base: *rbase.NewObject(), 255 sig: newObjArray("sig", "sig1"), 256 bkg: newObjArray("bkg", "bkg1"), 257 data: newObjArray("data", "data1"), 258 sigErr: newObjArray("0", "1", "2"), 259 bkgErr: newObjArray("3", "4", "5"), 260 ids: newObjArray("6", "7", "8"), 261 dummyTA: newObjArray("00", "11", "22"), 262 dummyIDs: newObjArray("11", "22", "33"), 263 }, 264 }, 265 { 266 name: "TEfficiency", 267 want: loadFrom("../testdata/tconfidence-level.root", "eff"), 268 }, 269 { 270 name: "TProfile", 271 want: loadFrom("../testdata/tprofile.root", "p1d"), 272 }, 273 { 274 name: "TProfile2D", 275 want: loadFrom("../testdata/tprofile.root", "p2d"), 276 }, 277 { 278 name: "TGraphMultiErrors", 279 want: loadFrom("../testdata/tgme.root", "gme"), 280 }, 281 { 282 name: "TMultiGraph", 283 want: loadFrom("../testdata/tgme.root", "mg"), 284 }, 285 { 286 name: "TScatter", 287 want: loadFrom("../testdata/tscatter.root", "scatter"), 288 }, 289 } { 290 t.Run(tc.name, func(t *testing.T) { 291 { 292 wbuf := rbytes.NewWBuffer(nil, nil, 0, nil) 293 wbuf.SetErr(io.EOF) 294 _, err := tc.want.MarshalROOT(wbuf) 295 if err == nil { 296 t.Fatalf("expected an error") 297 } 298 if err != io.EOF { 299 t.Fatalf("got=%v, want=%v", err, io.EOF) 300 } 301 } 302 wbuf := rbytes.NewWBuffer(nil, nil, 0, nil) 303 _, err := tc.want.MarshalROOT(wbuf) 304 if err != nil { 305 t.Fatalf("could not marshal ROOT: %v", err) 306 } 307 308 rbuf := rbytes.NewRBuffer(wbuf.Bytes(), nil, 0, nil) 309 class := tc.want.Class() 310 obj := rtypes.Factory.Get(class)().Interface().(rbytes.Unmarshaler) 311 { 312 rbuf.SetErr(io.EOF) 313 err = obj.UnmarshalROOT(rbuf) 314 if err == nil { 315 t.Fatalf("expected an error") 316 } 317 if err != io.EOF { 318 t.Fatalf("got=%v, want=%v", err, io.EOF) 319 } 320 rbuf.SetErr(nil) 321 } 322 err = obj.UnmarshalROOT(rbuf) 323 if err != nil { 324 t.Fatalf("could not unmarshal ROOT: %v", err) 325 } 326 327 if !reflect.DeepEqual(obj, tc.want) { 328 t.Fatalf("error\ngot= %+v\nwant=%+v\n", obj, tc.want) 329 } 330 }) 331 } 332 } 333 334 func TestReadF1(t *testing.T) { 335 for _, fname := range []string{ 336 "../testdata/tformula.root", 337 "../testdata/tformula-v14.root", 338 } { 339 t.Run(fname, func(t *testing.T) { 340 f, err := riofs.Open(fname) 341 if err != nil { 342 t.Fatal(err) 343 } 344 defer f.Close() 345 346 for _, key := range []string{ 347 "func1", "func2", "func3", "func4", 348 "fconv", 349 "fnorm", 350 } { 351 t.Run(key, func(t *testing.T) { 352 obj, err := f.Get(key) 353 if err != nil { 354 t.Fatalf("could not read object %q: %+v", key, err) 355 } 356 switch v := obj.(type) { 357 case *F1: 358 if got, want := v.Name(), key; got != want { 359 t.Fatalf("invalid name: got=%q, want=%q", got, want) 360 } 361 if got, want := v.Class(), "TF1"; got != want { 362 t.Fatalf("invalid class: got=%q, want=%q", got, want) 363 } 364 if got, want := v.chi2, 0.2; got != want { 365 t.Fatalf("invalid chi2: got=%v, want=%v", got, want) 366 } 367 case F1Composition: 368 // ok. 369 default: 370 t.Fatalf("invalid object type for %q", key) 371 } 372 }) 373 } 374 }) 375 } 376 } 377 378 func newObjArray(vs ...string) rcont.ObjArray { 379 elems := make([]root.Object, len(vs)) 380 for i, v := range vs { 381 elems[i] = rbase.NewObjString(v) 382 } 383 o := rcont.NewObjArray() 384 o.SetElems(elems) 385 return *o 386 } 387 388 func TestHistObjectFinder(t *testing.T) { 389 h := newH1() 390 h.funcs.Append(rbase.NewNamed("e1", "elem-1")) 391 h.funcs.Append(rbase.NewNamed("e2", "elem-2")) 392 h.funcs.Append(rbase.NewObject()) 393 h.funcs.Append(rbase.NewNamed("e4", "elem-4")) 394 395 if got, want := h.Keys(), []string{"e1", "e2", "e4"}; !reflect.DeepEqual(got, want) { 396 t.Fatalf("invalid keys: got=%q, want=%q", got, want) 397 } 398 399 _, err := h.Get("Not-There") 400 if err == nil { 401 t.Fatalf("expected an error") 402 } 403 404 got, err := h.Get("e2") 405 if err != nil { 406 t.Fatalf("could not retrieve e2: %+v", err) 407 } 408 409 n2, ok := got.(*rbase.Named) 410 if !ok { 411 t.Fatalf("retrieved invalid element (not a Named: %T)", got) 412 } 413 if got, want := n2.Name(), "e2"; got != want { 414 t.Fatalf("invalid element name: got=%q, want=%q", got, want) 415 } 416 } 417 418 func TestGraphObjectFinder(t *testing.T) { 419 g := newGraph(2) 420 funcs := g.funcs.(*rcont.List) 421 funcs.Append(rbase.NewNamed("e1", "elem-1")) 422 funcs.Append(rbase.NewNamed("e2", "elem-2")) 423 funcs.Append(rbase.NewObject()) 424 funcs.Append(rbase.NewNamed("e4", "elem-4")) 425 426 if got, want := g.Keys(), []string{"e1", "e2", "e4"}; !reflect.DeepEqual(got, want) { 427 t.Fatalf("invalid keys: got=%q, want=%q", got, want) 428 } 429 430 _, err := g.Get("Not-There") 431 if err == nil { 432 t.Fatalf("expected an error") 433 } 434 435 got, err := g.Get("e2") 436 if err != nil { 437 t.Fatalf("could not retrieve e2: %+v", err) 438 } 439 440 n2, ok := got.(*rbase.Named) 441 if !ok { 442 t.Fatalf("retrieved invalid element (not a Named: %T)", got) 443 } 444 if got, want := n2.Name(), "e2"; got != want { 445 t.Fatalf("invalid element name: got=%q, want=%q", got, want) 446 } 447 }