go-hep.org/x/hep@v0.38.1/groot/cmd/root-ls/main.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  // root-ls lists the content of a ROOT file.
     6  //
     7  // Usage: root-ls [options] file1.root [file2.root [...]]
     8  //
     9  // ex:
    10  //
    11  //	$> root-ls -t ./testdata/graphs.root ./testdata/small-flat-tree.root
    12  //	=== [./testdata/graphs.root] ===
    13  //	version: 60806
    14  //	TGraph            tg      graph without errors         (cycle=1)
    15  //	TGraphErrors      tge     graph with errors            (cycle=1)
    16  //	TGraphAsymmErrors tgae    graph with asymmetric errors (cycle=1)
    17  //
    18  //	=== [./testdata/small-flat-tree.root] ===
    19  //	version: 60804
    20  //	TTree          tree                 my tree title (entries=100)
    21  //	  Int32        "Int32/I"            TBranch
    22  //	  Int64        "Int64/L"            TBranch
    23  //	  UInt32       "UInt32/i"           TBranch
    24  //	  UInt64       "UInt64/l"           TBranch
    25  //	  Float32      "Float32/F"          TBranch
    26  //	  Float64      "Float64/D"          TBranch
    27  //	  ArrayInt32   "ArrayInt32[10]/I"   TBranch
    28  //	  ArrayInt64   "ArrayInt64[10]/L"   TBranch
    29  //	  ArrayUInt32  "ArrayInt32[10]/i"   TBranch
    30  //	  ArrayUInt64  "ArrayInt64[10]/l"   TBranch
    31  //	  ArrayFloat32 "ArrayFloat32[10]/F" TBranch
    32  //	  ArrayFloat64 "ArrayFloat64[10]/D" TBranch
    33  //	  N            "N/I"                TBranch
    34  //	  SliceInt32   "SliceInt32[N]/I"    TBranch
    35  //	  SliceInt64   "SliceInt64[N]/L"    TBranch
    36  //	  SliceUInt32  "SliceInt32[N]/i"    TBranch
    37  //	  SliceUInt64  "SliceInt64[N]/l"    TBranch
    38  //	  SliceFloat32 "SliceFloat32[N]/F"  TBranch
    39  //	  SliceFloat64 "SliceFloat64[N]/D"  TBranch
    40  package main // import "go-hep.org/x/hep/groot/cmd/root-ls"
    41  
    42  import (
    43  	"bufio"
    44  	"errors"
    45  	"flag"
    46  	"fmt"
    47  	"io"
    48  	"log"
    49  	"os"
    50  	"runtime/pprof"
    51  
    52  	"go-hep.org/x/hep/groot/rcmd"
    53  	_ "go-hep.org/x/hep/groot/riofs/plugin/http"
    54  	_ "go-hep.org/x/hep/groot/riofs/plugin/xrootd"
    55  	_ "go-hep.org/x/hep/groot/ztypes"
    56  )
    57  
    58  var (
    59  	fset = flag.NewFlagSet("ls", flag.ContinueOnError)
    60  
    61  	siFlag   = fset.Bool("sinfos", false, "print StreamerInfos")
    62  	treeFlag = fset.Bool("t", false, "print Tree(s) (recursively)")
    63  	cpuFlag  = fset.String("cpu-profile", "", "path to CPU profile output file")
    64  
    65  	usage = `Usage: root-ls [options] file1.root [file2.root [...]]
    66  
    67  ex:
    68   $> root-ls ./testdata/graphs.root
    69   $> root-ls -t -sinfos ./testdata/graphs.root
    70  
    71  options:
    72  `
    73  )
    74  
    75  func main() {
    76  	os.Exit(run(os.Stdout, os.Stderr, os.Args[1:]))
    77  }
    78  
    79  func run(stdout, stderr io.Writer, args []string) int {
    80  	fset.Usage = func() {
    81  		fmt.Fprint(stderr, usage)
    82  		fset.PrintDefaults()
    83  	}
    84  
    85  	err := fset.Parse(args)
    86  	if err != nil {
    87  		if errors.Is(err, flag.ErrHelp) {
    88  			return 0
    89  		}
    90  		log.Printf("could not parse args %q: %+v", args, err)
    91  		return 1
    92  	}
    93  
    94  	if *cpuFlag != "" {
    95  		f, err := os.Create(*cpuFlag)
    96  		if err != nil {
    97  			log.Fatalf("%+v", err)
    98  		}
    99  		err = pprof.StartCPUProfile(f)
   100  		if err != nil {
   101  			log.Fatalf("could not start CPU profiling: %+v", err)
   102  		}
   103  		defer pprof.StopCPUProfile()
   104  	}
   105  
   106  	if fset.NArg() <= 0 {
   107  		fmt.Fprintf(stderr, "error: you need to give a ROOT file\n\n")
   108  		fset.Usage()
   109  		return 1
   110  	}
   111  
   112  	out := bufio.NewWriter(stdout)
   113  	defer out.Flush()
   114  
   115  	opts := []rcmd.ListOption{
   116  		rcmd.ListStreamers(*siFlag),
   117  		rcmd.ListTrees(*treeFlag),
   118  	}
   119  
   120  	for ii, fname := range fset.Args() {
   121  		if ii > 0 {
   122  			fmt.Fprintf(out, "\n")
   123  		}
   124  		err := rcmd.List(out, fname, opts...)
   125  		if err != nil {
   126  			out.Flush()
   127  			log.Printf("%+v", err)
   128  			return 1
   129  		}
   130  	}
   131  
   132  	return 0
   133  }