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  }