go-hep.org/x/hep@v0.38.1/groot/rcmd/dump_test.go (about)

     1  // Copyright ©2020 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 rcmd_test
     6  
     7  import (
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"go-hep.org/x/hep/groot/rcmd"
    14  )
    15  
    16  func TestDump(t *testing.T) {
    17  	const deep = true
    18  	loadRef := func(fname string) string {
    19  		t.Helper()
    20  		raw, err := os.ReadFile(fname)
    21  		if err != nil {
    22  			t.Fatalf("could not load reference file %q: %+v", fname, err)
    23  		}
    24  		return string(raw)
    25  	}
    26  
    27  	for _, tc := range []struct {
    28  		name string
    29  		want string
    30  	}{
    31  		{
    32  			name: "../testdata/simple.root",
    33  			want: `key[000]: tree;1 "fake data" (TTree)
    34  [000][one]: 1
    35  [000][two]: 1.1
    36  [000][three]: uno
    37  [001][one]: 2
    38  [001][two]: 2.2
    39  [001][three]: dos
    40  [002][one]: 3
    41  [002][two]: 3.3
    42  [002][three]: tres
    43  [003][one]: 4
    44  [003][two]: 4.4
    45  [003][three]: quatro
    46  `,
    47  		},
    48  		{
    49  			name: "../testdata/root_numpy_struct.root",
    50  			want: `key[000]: test;1 "identical leaf names in different branches" (TTree)
    51  [000][branch1.intleaf]: 10
    52  [000][branch1.floatleaf]: 15.5
    53  [000][branch2.intleaf]: 20
    54  [000][branch2.floatleaf]: 781.2
    55  `,
    56  		},
    57  		{
    58  			name: "../testdata/tntuple.root",
    59  			want: `key[000]: ntup;1 "my ntuple title" (TNtuple)
    60  [000][x]: 0
    61  [000][y]: 0.5
    62  [001][x]: 1
    63  [001][y]: 1.5
    64  [002][x]: 2
    65  [002][y]: 2.5
    66  [003][x]: 3
    67  [003][y]: 3.5
    68  [004][x]: 4
    69  [004][y]: 4.5
    70  [005][x]: 5
    71  [005][y]: 5.5
    72  [006][x]: 6
    73  [006][y]: 6.5
    74  [007][x]: 7
    75  [007][y]: 7.5
    76  [008][x]: 8
    77  [008][y]: 8.5
    78  [009][x]: 9
    79  [009][y]: 9.5
    80  `,
    81  		},
    82  		{
    83  			name: "../testdata/tntupled.root",
    84  			want: `key[000]: ntup;1 "my ntuple title" (TNtupleD)
    85  [000][x]: 0
    86  [000][y]: 0.5
    87  [001][x]: 1
    88  [001][y]: 1.5
    89  [002][x]: 2
    90  [002][y]: 2.5
    91  [003][x]: 3
    92  [003][y]: 3.5
    93  [004][x]: 4
    94  [004][y]: 4.5
    95  [005][x]: 5
    96  [005][y]: 5.5
    97  [006][x]: 6
    98  [006][y]: 6.5
    99  [007][x]: 7
   100  [007][y]: 7.5
   101  [008][x]: 8
   102  [008][y]: 8.5
   103  [009][x]: 9
   104  [009][y]: 9.5
   105  `,
   106  		},
   107  		{
   108  			name: "../testdata/padding.root",
   109  			want: `key[000]: tree;1 "tree w/ & w/o padding" (TTree)
   110  [000][pad.x1]: 0
   111  [000][pad.x2]: 548655054794
   112  [000][pad.x3]: 0
   113  [000][nop.x1]: 0
   114  [000][nop.x2]: 0
   115  [000][nop.x3]: 0
   116  [001][pad.x1]: 1
   117  [001][pad.x2]: 72058142692982730
   118  [001][pad.x3]: 0
   119  [001][nop.x1]: 1
   120  [001][nop.x2]: 1
   121  [001][nop.x3]: 1
   122  [002][pad.x1]: 2
   123  [002][pad.x2]: 144115736730910666
   124  [002][pad.x3]: 0
   125  [002][nop.x1]: 2
   126  [002][nop.x2]: 2
   127  [002][nop.x3]: 2
   128  [003][pad.x1]: 3
   129  [003][pad.x2]: 216173330768838602
   130  [003][pad.x3]: 0
   131  [003][nop.x1]: 3
   132  [003][nop.x2]: 3
   133  [003][nop.x3]: 3
   134  [004][pad.x1]: 4
   135  [004][pad.x2]: 288230924806766538
   136  [004][pad.x3]: 0
   137  [004][nop.x1]: 4
   138  [004][nop.x2]: 4
   139  [004][nop.x3]: 4
   140  `,
   141  		},
   142  		{
   143  			name: "../testdata/small-flat-tree.root",
   144  			want: loadRef("testdata/small-flat-tree.root.txt"),
   145  		},
   146  		{
   147  			name: "../testdata/small-evnt-tree-fullsplit.root",
   148  			want: loadRef("testdata/small-evnt-tree-fullsplit.root.txt"),
   149  		},
   150  		{
   151  			name: "../testdata/small-evnt-tree-nosplit.root",
   152  			want: loadRef("testdata/small-evnt-tree-nosplit.root.txt"),
   153  		},
   154  		{
   155  			name: "../testdata/leaves.root",
   156  			want: loadRef("testdata/leaves.root.txt"),
   157  		},
   158  		{
   159  			name: "../testdata/embedded-std-vector.root",
   160  			want: `key[000]: modules;1 "Module Tree Analysis" (TTree)
   161  [000][hits_n]: 10
   162  [000][hits_time_mc]: [12.206399 11.711122 11.73492 12.45704 11.558057 11.56502 11.687759 11.528914 12.893241 11.429288]
   163  [001][hits_n]: 11
   164  [001][hits_time_mc]: [11.718019 12.985347 12.23121 11.825082 12.405976 15.339471 11.939051 12.935032 13.661691 11.969542 11.893113]
   165  [002][hits_n]: 15
   166  [002][hits_time_mc]: [12.231329 12.214683 12.194867 12.246092 11.859249 19.35934 12.155213 12.226966 -4.712372 11.851829 11.8806925 11.8204975 11.866335 13.285733 -4.6470475]
   167  [003][hits_n]: 9
   168  [003][hits_time_mc]: [11.33844 11.725604 12.774131 12.108594 12.192085 12.120591 12.129445 12.18349 11.591005]
   169  [004][hits_n]: 13
   170  [004][hits_time_mc]: [12.156414 12.641215 11.678816 12.329707 11.578169 12.512748 11.840462 14.120602 11.875188 14.133265 14.105912 14.905052 11.813884]
   171  `,
   172  		},
   173  		{
   174  			// recovered baskets
   175  			name: "../testdata/uproot/issue21.root",
   176  			want: loadRef("../testdata/uproot/issue21.root.txt"),
   177  		},
   178  		{
   179  			name: "../testdata/treeCharExample.root",
   180  			want: `key[000]: nominal;1 "tree" (TTree)
   181  [000][d_fakeEvent]: false
   182  [000][d_lep_ECIDS]: [1 110]
   183  [001][d_fakeEvent]: false
   184  [001][d_lep_ECIDS]: [1 1]
   185  [002][d_fakeEvent]: false
   186  [002][d_lep_ECIDS]: [110 110]
   187  [003][d_fakeEvent]: false
   188  [003][d_lep_ECIDS]: [1 110]
   189  [004][d_fakeEvent]: false
   190  [004][d_lep_ECIDS]: [1 110]
   191  [005][d_fakeEvent]: false
   192  [005][d_lep_ECIDS]: [110 110]
   193  [006][d_fakeEvent]: false
   194  [006][d_lep_ECIDS]: [1 0]
   195  [007][d_fakeEvent]: false
   196  [007][d_lep_ECIDS]: [1 110]
   197  [008][d_fakeEvent]: false
   198  [008][d_lep_ECIDS]: [1 1]
   199  [009][d_fakeEvent]: false
   200  [009][d_lep_ECIDS]: [1 1]
   201  `,
   202  		},
   203  		{
   204  			// no embedded streamer for std::string
   205  			name: "../testdata/no-streamer-string.root",
   206  			want: loadRef("testdata/no-streamer-string.root.txt"),
   207  		},
   208  		{
   209  			// 'This' streamer of vector<vector<double>>
   210  			name: "../testdata/vec-vec-double.root",
   211  			want: `key[000]: t;1 "" (TTree)
   212  [000][x]: []
   213  [001][x]: [[] []]
   214  [002][x]: [[10] [] [10 20]]
   215  [003][x]: [[20 -21 -22]]
   216  [004][x]: [[200] [-201] [202]]
   217  `,
   218  		},
   219  		{
   220  			// Geant4 w/ recover baskets
   221  			name: "../testdata/g4-like.root",
   222  			want: `key[000]: mytree;1 "my title" (TTree)
   223  [000][i32]: 1
   224  [000][f64]: 1
   225  [000][slif64]: []
   226  [001][i32]: 2
   227  [001][f64]: 2
   228  [001][slif64]: [1]
   229  [002][i32]: 3
   230  [002][f64]: 3
   231  [002][slif64]: [2 3]
   232  [003][i32]: 4
   233  [003][f64]: 4
   234  [003][slif64]: [3 4 5]
   235  [004][i32]: 5
   236  [004][f64]: 5
   237  [004][slif64]: [4 5 6 7]
   238  `,
   239  		},
   240  		{
   241  			// std::bitset<N>, std::vector<std::bitset<N>>
   242  			name: "../testdata/std-bitset.root",
   243  			want: `key[000]: tree;1 "my tree title" (TTree)
   244  [000][evt]: {[0 0 0 1 0 0 0 1] [[1 1 1 0 1 1 1 0]]}
   245  [001][evt]: {[1 0 0 1 1 0 0 1] [[0 0 0 1 0 0 0 1] [1 1 1 0 1 1 1 0]]}
   246  [002][evt]: {[0 1 1 0 0 1 1 0] [[1 0 0 1 1 0 0 1] [0 1 1 0 0 1 1 0] [1 1 0 0 1 1 0 0]]}
   247  `,
   248  		},
   249  		{
   250  			// std-map w/ split-level=0, mbr-wise
   251  			name: "../testdata/std-map-split0.root",
   252  			want: loadRef("testdata/std-map-split0.root.txt"),
   253  		},
   254  		{
   255  			// std-map w/ split-level=1, mbr-wise
   256  			name: "../testdata/std-map-split1.root",
   257  			want: loadRef("testdata/std-map-split1.root.txt"),
   258  		},
   259  		{
   260  			// std::map, std::set, std::list, std::deque, std::unordered_map, std::unordered_set, TString
   261  			name: "../testdata/std-containers-split00.root",
   262  			want: loadRef("testdata/std-containers-split00.root.txt"),
   263  		},
   264  		{
   265  			// n-dim arrays
   266  			// FIXME(sbinet): arrays of Float16_t and Double32_t are flatten.
   267  			// This is because of:
   268  			// https://sft.its.cern.ch/jira/browse/ROOT-10149
   269  			name: "../testdata/ndim.root",
   270  			want: loadRef("testdata/ndim.root.txt"),
   271  		},
   272  		{
   273  			// slices of n-dim arrays
   274  			// FIXME(sbinet): arrays of Float16_t and Double32_t are flatten.
   275  			// This is because of:
   276  			// https://sft.its.cern.ch/jira/browse/ROOT-10149
   277  			name: "../testdata/ndim-slice.root",
   278  			want: loadRef("testdata/ndim-slice.root.txt"),
   279  		},
   280  		{
   281  			name: "../testdata/tformula.root",
   282  			want: `key[000]: func1;1 "[0] + [1]*x" (TF1) => "TF1{Formula: TFormula{[p0]+[p1]*x}}"
   283  key[001]: func2;1 "func2" (TF1) => "TF1{Params: TF1Parameters{Values: [10 20], Names: [p0 p1]}}"
   284  key[002]: func3;1 "func3" (TF1) => "TF1{Params: TF1Parameters{Values: [1 -0.3 0 1], Names: [p0 p1 p2 p3]}}"
   285  key[003]: func4;1 "func4" (TF1) => "TF1{Params: TF1Parameters{Values: [0 0 0 0 0 0], Names: [p0 p1 p2 p3 p4 p5]}}"
   286  key[004]: fconv;1 "" (TF1Convolution) => "TF1Convolution{Func1: TF1{Formula: TFormula{exp([Constant]+[Slope]*x)}}, Func2: TF1{Formula: TFormula{[Constant]*exp(-0.5*((x-[Mean])/[Sigma])*((x-[Mean])/[Sigma]))}}}"
   287  key[005]: fnorm;1 "" (TF1NormSum) => "TF1Convolution{Funcs: []{TF1{Formula: TFormula{[p0]+[p1]*x}}, TF1{Params: TF1Parameters{Values: [10 20], Names: [p0 p1]}}}, Coeffs: [10 20]}"
   288  `,
   289  		},
   290  		{
   291  			name: "../testdata/tconfidence-level.root",
   292  			want: `key[000]: clvl;1 "output for TLimit functions" (TConfidenceLevel) => ignoring key of type *rhist.ConfidenceLevel
   293  key[001]: limit;1 "object title" (TLimit) => ignoring key of type *rhist.Limit
   294  key[002]: dsrc;1 "input for TLimit routines" (TLimitDataSource) => ignoring key of type *rhist.LimitDataSource
   295  key[003]: eff;1 "efficiency" (TEfficiency) => ignoring key of type *rhist.Efficiency
   296  `,
   297  		},
   298  		{
   299  			name: "../testdata/pod.root",
   300  			want: loadRef("testdata/pod.root.txt"),
   301  		},
   302  		{
   303  			name: "../testdata/pod-advanced.root",
   304  			want: loadRef("testdata/pod-advanced.root.txt"),
   305  		},
   306  		{
   307  			name: "../testdata/uproot/uproot-issue-172.root",
   308  			want: loadRef("testdata/uproot-issue-172.root.txt"),
   309  		},
   310  		{
   311  			name: "../testdata/tdatime.root",
   312  			want: `key[000]: tda;1 "object title" (TDatime) => "2006-01-02 15:04:05 +0000 UTC"
   313  key[001]: foo;1 "" (TFoo) => &{{0 50331648} 2006-01-02 15:04:05 +0000 UTC}
   314  key[002]: bar;1 "" (TBar) => &{{0 50331648} 2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]}
   315  key[003]: dat;1 "object title" (Date) => &{2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]}
   316  key[004]: tree;1 "my tree title" (TTree)
   317  [000][b0]: 2006-01-02 15:04:05 +0000 UTC
   318  [000][b1]: {{0 50331648} 2006-01-02 15:04:05 +0000 UTC}
   319  [000][b2]: {{0 50331648} 2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]}
   320  [000][b3]: {2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]}
   321  [001][b0]: 2006-01-03 15:04:05 +0000 UTC
   322  [001][b1]: {{0 50331648} 2006-01-03 15:04:05 +0000 UTC}
   323  [001][b2]: {{0 50331648} 2006-01-03 15:04:05 +0000 UTC [49 50 51 52 53 0]}
   324  [001][b3]: {2006-01-03 15:04:05 +0000 UTC [49 50 51 52 53 0]}
   325  `,
   326  		},
   327  		{
   328  			name: "../testdata/tgme.root",
   329  			want: loadRef("testdata/tgme.root.txt"),
   330  		},
   331  		{
   332  			// ROOT::VecOps::RVec<T>
   333  			name: "../testdata/rvec.root",
   334  			want: loadRef("testdata/rvec.root.txt"),
   335  		},
   336  		{
   337  			name: "../testdata/tcanvas.root",
   338  			want: loadRef("testdata/tcanvas.root.txt"),
   339  		},
   340  	} {
   341  		t.Run(tc.name, func(t *testing.T) {
   342  			got := new(strings.Builder)
   343  			err := rcmd.Dump(got, tc.name, deep, nil)
   344  			if err != nil {
   345  				t.Fatalf("could not run root-dump: %+v", err)
   346  			}
   347  
   348  			if got, want := got.String(), tc.want; got != want {
   349  				diff := cmp.Diff(want, got)
   350  				t.Fatalf("invalid root-dump output: -- (-ref +got)\n%s", diff)
   351  			}
   352  		})
   353  	}
   354  }
   355  
   356  func BenchmarkDump(b *testing.B) {
   357  	const deep = true
   358  	out := new(strings.Builder)
   359  	for i := 0; i < b.N; i++ {
   360  		b.StopTimer()
   361  		out.Reset()
   362  		b.StartTimer()
   363  		// big-file.root is: rtests.XrdRemote("testdata/SMHiggsToZZTo4L.root")
   364  		err := rcmd.Dump(out, "../testdata/big-file.root", deep, nil)
   365  		if err != nil {
   366  			b.Fatal(err)
   367  		}
   368  	}
   369  }