Documentation ¶
Overview ¶
Package riofs contains the types and low-level functions to deal with opening and creating ROOT files, and decoding the internal structure of ROOT files.
Users should prefer to use the groot package to open or create ROOT files instead of this one.
Example (Mkdir) ¶
package main import ( "fmt" "log" "os" "go-hep.org/x/hep/groot" "go-hep.org/x/hep/groot/rbase" "go-hep.org/x/hep/groot/riofs" "go-hep.org/x/hep/groot/root" ) func main() { const fname = "../testdata/subdirs.root" defer os.Remove(fname) { w, err := groot.Create(fname) if err != nil { log.Fatal(err) } defer w.Close() dir1, err := w.Mkdir("dir1") if err != nil { log.Fatal(err) } dir11, err := dir1.Mkdir("dir11") if err != nil { log.Fatal(err) } err = dir11.Put("obj1", rbase.NewObjString("data-obj1")) if err != nil { log.Fatal(err) } dir2, err := w.Mkdir("dir2") if err != nil { log.Fatal(err) } err = dir2.Put("obj2", rbase.NewObjString("data-obj2")) if err != nil { log.Fatal(err) } err = w.Close() if err != nil { log.Fatal(err) } } r, err := groot.Open(fname) if err != nil { log.Fatal(err) } defer r.Close() err = riofs.Walk(r, func(path string, obj root.Object, err error) error { fmt.Printf(">> %v\n", path) return err }) if err != nil { log.Fatalf("could not walk ROOT file: %+v", err) } }
Output: >> ../testdata/subdirs.root >> ../testdata/subdirs.root/dir1 >> ../testdata/subdirs.root/dir1/dir11 >> ../testdata/subdirs.root/dir1/dir11/obj1 >> ../testdata/subdirs.root/dir2 >> ../testdata/subdirs.root/dir2/obj2
Example (RecursiveMkdir) ¶
package main import ( "fmt" "io/ioutil" "log" "os" stdpath "path" "go-hep.org/x/hep/groot" "go-hep.org/x/hep/groot/rbase" "go-hep.org/x/hep/groot/riofs" "go-hep.org/x/hep/groot/root" ) func main() { dir, err := ioutil.TempDir("", "groot-riofs-") if err != nil { log.Fatal(err) } defer os.RemoveAll(dir) fname := stdpath.Join(dir, "dirs.root") f, err := groot.Create(fname) if err != nil { log.Fatal(err) } defer f.Close() rd := riofs.Dir(f) for _, path := range []string{ "dir1/dir11/dir111", "/dir2/dir22/dir000", "dir2/dir22/dir222", } { _, err = rd.Mkdir(path) if err != nil { log.Fatal(err) } } err = rd.Put("/dir1/dir11/obj-1", rbase.NewObjString("obj-1")) if err != nil { log.Fatal(err) } err = riofs.Walk(f, func(path string, obj root.Object, err error) error { name := path[len(fname):] if name == "" { return err } switch o := obj.(type) { case *rbase.ObjString: fmt.Printf(">> %v -- value=%q\n", name, o) default: fmt.Printf(">> %v\n", name) } return err }) if err != nil { log.Fatalf("could not walk ROOT file: %+v", err) } err = f.Close() if err != nil { log.Fatalf("could not close ROOT file: %v", err) } }
Output: >> /dir1 >> /dir1/dir11 >> /dir1/dir11/dir111 >> /dir1/dir11/obj-1 -- value="obj-1" >> /dir2 >> /dir2/dir22 >> /dir2/dir22/dir000 >> /dir2/dir22/dir222
Example (RecursivePut) ¶
package main import ( "fmt" "io/ioutil" "log" "os" stdpath "path" "go-hep.org/x/hep/groot" "go-hep.org/x/hep/groot/rbase" "go-hep.org/x/hep/groot/riofs" "go-hep.org/x/hep/groot/root" ) func main() { dir, err := ioutil.TempDir("", "groot-riofs-") if err != nil { log.Fatal(err) } defer os.RemoveAll(dir) fname := stdpath.Join(dir, "dirs.root") f, err := groot.Create(fname) if err != nil { log.Fatal(err) } defer f.Close() rd := riofs.Dir(f) // create obj-1, put it under dir1/dir11, create all intermediate directories. err = rd.Put("dir1/dir11/obj-1", rbase.NewObjString("obj-1")) if err != nil { log.Fatal(err) } // create obj-2 err = rd.Put("/dir2/dir22/dir222/obj-2", rbase.NewObjString("obj-2")) if err != nil { log.Fatal(err) } // update obj-1 err = rd.Put("dir1/dir11/obj-1", rbase.NewObjString("obj-1-1")) if err != nil { log.Fatal(err) } o, err := rd.Get("dir1/dir11/obj-1;1") if err != nil { log.Fatal(err) } if got, want := o.(*rbase.ObjString).String(), "obj-1"; got != want { log.Fatalf("invalid obj-1;1 value. got=%q, want=%q", got, want) } o, err = rd.Get("dir1/dir11/obj-1;2") if err != nil { log.Fatal(err) } if got, want := o.(*rbase.ObjString).String(), "obj-1-1"; got != want { log.Fatalf("invalid obj-1;1 value. got=%q, want=%q", got, want) } o, err = rd.Get("dir1/dir11/obj-1") if err != nil { log.Fatal(err) } if got, want := o.(*rbase.ObjString).String(), "obj-1-1"; got != want { log.Fatalf("invalid obj-1 value. got=%q, want=%q", got, want) } err = riofs.Walk(f, func(path string, obj root.Object, err error) error { name := path[len(fname):] if name == "" { return err } switch o := obj.(type) { case *rbase.ObjString: fmt.Printf(">> %v -- value=%q\n", name, o) default: fmt.Printf(">> %v\n", name) } return err }) if err != nil { log.Fatalf("could not walk ROOT file: %+v", err) } err = f.Close() if err != nil { log.Fatalf("could not close ROOT file: %v", err) } }
Output: >> /dir1 >> /dir1/dir11 >> /dir1/dir11/obj-1 -- value="obj-1-1" >> /dir2 >> /dir2/dir22 >> /dir2/dir22/dir222 >> /dir2/dir22/dir222/obj-2 -- value="obj-2"
Index ¶
- Variables
- func Drivers() []string
- func Register(name string, f func(path string) (Reader, error))
- func Walk(dir Directory, walkFn WalkFunc) error
- type Directory
- type File
- func (f *File) Class() string
- func (f *File) Close() error
- func (f *File) Compression() int32
- func (f *File) Get(namecycle string) (root.Object, error)
- func (f *File) Keys() []Key
- func (f *File) Mkdir(name string) (Directory, error)
- func (f *File) Name() string
- func (*File) Parent() Directory
- func (f *File) Put(name string, v root.Object) error
- func (f *File) Read(p []byte) (int, error)
- func (f *File) ReadAt(p []byte, off int64) (int, error)
- func (f *File) Records(w io.Writer) error
- func (f *File) RegisterStreamer(streamer rbytes.StreamerInfo)
- func (f *File) SegmentMap(w io.Writer) (err error)
- func (f *File) Stat() (os.FileInfo, error)
- func (f *File) StreamerInfo(name string, version int) (rbytes.StreamerInfo, error)
- func (f *File) StreamerInfos() []rbytes.StreamerInfo
- func (f *File) Title() string
- func (f *File) Version() int
- func (f *File) WriteAt(p []byte, off int64) (int, error)
- type FileOption
- type Key
- func (k *Key) Buffer() []byte
- func (k *Key) Bytes() ([]byte, error)
- func (*Key) Class() string
- func (k *Key) ClassName() string
- func (k *Key) Cycle() int
- func (k *Key) KeyLen() int32
- func (k *Key) Load(buf []byte) ([]byte, error)
- func (k *Key) MarshalROOT(w *rbytes.WBuffer) (int, error)
- func (k *Key) Name() string
- func (k *Key) Nbytes() int32
- func (k *Key) ObjLen() int32
- func (k *Key) Object() (root.Object, error)
- func (k *Key) ObjectType() reflect.Type
- func (k *Key) RVersion() int16
- func (k *Key) SeekKey() int64
- func (k *Key) SetBuffer(buf []byte)
- func (k *Key) SetFile(f *File)
- func (k *Key) Title() string
- func (k *Key) UnmarshalROOT(r *rbytes.RBuffer) error
- func (k *Key) Value() interface{}
- type Reader
- type SetFiler
- type WalkFunc
- type Writer
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var (
ErrReadOnly = errors.New("riofs: file read-only")
)
var SkipDir = errors.New("riofs: skip this directory") //lint:ignore ST1012 EOF-like sentry
SkipDir is used as a return value from WalkFuncs to indicate that the directory named in the call is to be skipped. It is not returned as an error by any function.
Functions ¶
func Drivers ¶ added in v0.18.0
func Drivers() []string
Drivers returns a sorted list of the names of the registered plugins to open ROOT files.
func Register ¶ added in v0.18.0
Register registers a plugin to open ROOT files. Register panics if it is called twice with the same name of if the plugin function is nil.
func Walk ¶
Walk walks the ROOT file tree rooted at dir, calling walkFn for each ROOT object or Directory in the ROOT file tree, including dir.
If an object exists with multiple cycle values, only the latest one is considered.
Example ¶
package main import ( "fmt" "log" stdpath "path" "strings" "go-hep.org/x/hep/groot/riofs" "go-hep.org/x/hep/groot/root" ) func main() { f, err := riofs.Open("../testdata/dirs-6.14.00.root") if err != nil { log.Fatal(err) } defer f.Close() fmt.Printf("visit all ROOT file tree:\n") err = riofs.Walk(f, func(path string, obj root.Object, err error) error { fmt.Printf("%s (%s)\n", path, obj.Class()) return nil }) if err != nil { log.Fatalf("could not walk through file: %v", err) } fmt.Printf("visit only dir1:\n") err = riofs.Walk(f, func(path string, obj root.Object, err error) error { if !(strings.HasPrefix(path, stdpath.Join(f.Name(), "dir1")) || path == f.Name()) { return riofs.SkipDir } fmt.Printf("%s (%s)\n", path, obj.Class()) return nil }) if err != nil { log.Fatalf("could not walk through file: %v", err) } }
Output: visit all ROOT file tree: dirs-6.14.00.root (TFile) dirs-6.14.00.root/dir1 (TDirectoryFile) dirs-6.14.00.root/dir1/dir11 (TDirectoryFile) dirs-6.14.00.root/dir1/dir11/h1 (TH1F) dirs-6.14.00.root/dir2 (TDirectoryFile) dirs-6.14.00.root/dir3 (TDirectoryFile) visit only dir1: dirs-6.14.00.root (TFile) dirs-6.14.00.root/dir1 (TDirectoryFile) dirs-6.14.00.root/dir1/dir11 (TDirectoryFile) dirs-6.14.00.root/dir1/dir11/h1 (TH1F)
Types ¶
type Directory ¶
type Directory interface { // Get returns the object identified by namecycle // namecycle has the format name;cycle // name = * is illegal, cycle = * is illegal // cycle = "" or cycle = 9999 ==> apply to a memory object // // examples: // foo : get object named foo in memory // if object is not in memory, try with highest cycle from file // foo;1 : get cycle 1 of foo on file Get(namecycle string) (root.Object, error) // Put puts the object v under the key with the given name. Put(name string, v root.Object) error // Keys returns the list of keys being held by this directory. Keys() []Key // Mkdir creates a new subdirectory Mkdir(name string) (Directory, error) // Parent returns the directory holding this directory. // Parent returns nil if this is the top-level directory. Parent() Directory }
Directory describes a ROOT directory structure in memory.
type File ¶
type File struct {
// contains filtered or unexported fields
}
A ROOT file is a suite of consecutive data records (TKey's) with the following format (see also the TKey class). If the key is located past the 32 bit file limit (> 2 GB) then some fields will be 8 instead of 4 bytes:
1->4 Nbytes = Length of compressed object (in bytes) 5->6 Version = TKey version identifier 7->10 ObjLen = Length of uncompressed object 11->14 Datime = Date and time when object was written to file 15->16 KeyLen = Length of the key structure (in bytes) 17->18 Cycle = Cycle of key 19->22 [19->26] SeekKey = Pointer to record itself (consistency check) 23->26 [27->34] SeekPdir = Pointer to directory header 27->27 [35->35] lname = Number of bytes in the class name 28->.. [36->..] ClassName = Object Class Name ..->.. lname = Number of bytes in the object name ..->.. Name = lName bytes with the name of the object ..->.. lTitle = Number of bytes in the object title ..->.. Title = Title of the object -----> DATA = Data bytes associated to the object
The first data record starts at byte fBEGIN (currently set to kBEGIN). Bytes 1->kBEGIN contain the file description, when fVersion >= 1000000 it is a large file (> 2 GB) and the offsets will be 8 bytes long and fUnits will be set to 8:
1->4 "root" = Root file identifier 5->8 fVersion = File format version 9->12 fBEGIN = Pointer to first data record 13->16 [13->20] fEND = Pointer to first free word at the EOF 17->20 [21->28] fSeekFree = Pointer to FREE data record 21->24 [29->32] fNbytesFree = Number of bytes in FREE data record 25->28 [33->36] nfree = Number of free data records 29->32 [37->40] fNbytesName = Number of bytes in TNamed at creation time 33->33 [41->41] fUnits = Number of bytes for file pointers 34->37 [42->45] fCompress = Compression level and algorithm 38->41 [46->53] fSeekInfo = Pointer to TStreamerInfo record 42->45 [54->57] fNbytesInfo = Number of bytes in TStreamerInfo record 46->63 [58->75] fUUID = Universal Unique ID
func Create ¶
func Create(name string, opts ...FileOption) (*File, error)
Create creates the named ROOT file for writing.
Example ¶
package main import ( "fmt" "log" "os" "go-hep.org/x/hep/groot" "go-hep.org/x/hep/groot/rbase" "go-hep.org/x/hep/groot/root" ) func main() { const fname = "objstring.root" defer os.Remove(fname) w, err := groot.Create(fname) if err != nil { log.Fatal(err) } defer w.Close() var ( k = "my-objstring" v = rbase.NewObjString("Hello World from Go-HEP!") ) err = w.Put(k, v) if err != nil { log.Fatal(err) } fmt.Printf("wkeys: %d\n", len(w.Keys())) err = w.Close() if err != nil { log.Fatalf("could not close file: %v", err) } r, err := groot.Open(fname) if err != nil { log.Fatalf("could not open file: %v", err) } defer r.Close() fmt.Printf("rkeys: %d\n", len(r.Keys())) for _, k := range r.Keys() { fmt.Printf("key: name=%q, type=%q\n", k.Name(), k.ClassName()) } obj, err := r.Get(k) if err != nil { log.Fatal(err) } rv := obj.(root.ObjString) fmt.Printf("objstring=%q\n", rv) }
Output: wkeys: 1 rkeys: 1 key: name="my-objstring", type="TObjString" objstring="Hello World from Go-HEP!"
Example (Empty) ¶
package main import ( "fmt" "log" "os" "go-hep.org/x/hep/groot" ) func main() { const fname = "empty.root" defer os.Remove(fname) w, err := groot.Create(fname) if err != nil { log.Fatal(err) } defer w.Close() // empty file. close it. err = w.Close() if err != nil { log.Fatalf("could not close empty file: %v", err) } // read back. r, err := groot.Open(fname) if err != nil { log.Fatalf("could not open empty file: %v", err) } defer r.Close() fmt.Printf("file: %q\n", r.Name()) }
Output: file: "empty.root"
Example (WithZlib) ¶
package main import ( "compress/flate" "fmt" "log" "os" "go-hep.org/x/hep/groot" "go-hep.org/x/hep/groot/rbase" "go-hep.org/x/hep/groot/riofs" "go-hep.org/x/hep/groot/root" ) func main() { const fname = "objstring-zlib.root" defer os.Remove(fname) w, err := groot.Create(fname, riofs.WithZlib(flate.BestCompression)) if err != nil { log.Fatal(err) } defer w.Close() var ( k = "my-objstring" v = rbase.NewObjString("Hello World from Go-HEP!") ) err = w.Put(k, v) if err != nil { log.Fatal(err) } err = w.Close() if err != nil { log.Fatalf("could not close writable file: %v", err) } r, err := groot.Open(fname) if err != nil { log.Fatalf("could not open file: %v", err) } defer r.Close() for _, k := range r.Keys() { fmt.Printf("key: name=%q, type=%q\n", k.Name(), k.ClassName()) } obj, err := r.Get(k) if err != nil { log.Fatalf("could not get key %q: %v", k, err) } rv := obj.(root.ObjString) fmt.Printf("objstring=%q\n", rv) }
Output: key: name="my-objstring", type="TObjString" objstring="Hello World from Go-HEP!"
func Open ¶
Open opens the named ROOT file for reading. If successful, methods on the returned file can be used for reading; the associated file descriptor has mode os.O_RDONLY.
func (*File) Close ¶
Close closes the File, rendering it unusable for I/O. It returns an error, if any.
func (*File) Compression ¶ added in v0.21.0
Compression returns the compression-mechanism and compression-level used for this file.
func (*File) Get ¶
Get returns the object identified by namecycle
namecycle has the format name;cycle name = * is illegal, cycle = * is illegal cycle = "" or cycle = 9999 ==> apply to a memory object examples: foo : get object named foo in memory if object is not in memory, try with highest cycle from file foo;1 : get cycle 1 of foo on file
func (*File) Parent ¶ added in v0.20.0
Parent returns the directory holding this directory. Parent returns nil if this is the top-level directory.
func (*File) RegisterStreamer ¶ added in v0.26.0
func (f *File) RegisterStreamer(streamer rbytes.StreamerInfo)
RegisterStreamer adds the given streamer info to the list of streamers that will be stored in the ROOT file.
func (*File) SegmentMap ¶ added in v0.20.0
SegmentMap displays to w the file's segments map.
func (*File) StreamerInfo ¶
StreamerInfo returns the named StreamerInfo. If version is negative, the latest version should be returned.
func (*File) StreamerInfos ¶
func (f *File) StreamerInfos() []rbytes.StreamerInfo
StreamerInfos returns the list of StreamerInfos of this file.
type FileOption ¶
FileOption configures internal states of a ROOT file.
func WithLZ4 ¶
func WithLZ4(level int) FileOption
WithLZ4 configures a ROOT file to use LZ4 as a compression mechanism.
func WithLZMA ¶
func WithLZMA(level int) FileOption
WithLZMA configures a ROOT file to use LZMA as a compression mechanism.
func WithZlib ¶
func WithZlib(level int) FileOption
WithZlib configures a ROOT file to use zlib as a compression mechanism.
func WithZstd ¶ added in v0.22.0
func WithZstd(level int) FileOption
WithZstd configures a ROOT file to use zstd as a compression mechanism.
func WithoutCompression ¶
func WithoutCompression() FileOption
WithoutCompression configures a ROOT file to not use any compression mechanism.
type Key ¶
type Key struct {
// contains filtered or unexported fields
}
Key is a key (a label) in a ROOT file
The Key class includes functions to book space on a file, to create I/O buffers, to fill these buffers to compress/uncompress data buffers. Before saving (making persistent) an object on a file, a key must be created. The key structure contains all the information to uniquely identify a persistent object on a file. The Key class is used by ROOT: - to write an object in the Current Directory - to write a new ntuple buffer
func KeyFromDir ¶ added in v0.20.0
KeyFromDir creates a new empty key (with no associated payload object) with provided name and title, and the expected object type name. The key will be held by the provided directory.
func NewKey ¶ added in v0.20.0
func NewKey(dir Directory, name, title, class string, cycle int16, obj []byte, f *File) (Key, error)
NewKey creates a new key from the provided serialized object buffer. NewKey puts the key and its payload at the end of the provided file f. Depending on the file configuration, NewKey may compress the provided object buffer.
func NewKeyForBasketInternal ¶ added in v0.20.0
NewKeyForBasketInternal creates a new empty key. This is needed for Tree/Branch/Basket persistency.
DO NOT USE.
func (*Key) MarshalROOT ¶
MarshalROOT encodes the key to the provided buffer.
func (*Key) ObjectType ¶
ObjectType returns the Key's payload type.
ObjectType returns nil if the Key's payload type is not known to the registry of groot.
func (*Key) UnmarshalROOT ¶
UnmarshalROOT decodes the content of data into the Key
type SetFiler ¶
type SetFiler interface {
SetFile(f *File)
}
SetFiler is a simple interface to establish File ownership.
type WalkFunc ¶
WalkFunc is the type of the function called for each object or directory visited by Walk. The path argument contains the argument to Walk as a prefix; that is, if Walk is called with "dir", which is a directory containing the file "a", the walk function will be called with argument "dir/a". The obj argument is the root.Object for the named path.
If there was a problem walking to the file or directory named by path, the incoming error will describe the problem and the function can decide how to handle that error (and Walk will not descend into that directory). In the case of an error, the obj argument will be nil. If an error is returned, processing stops. The sole exception is when the function returns the special value SkipDir. If the function returns SkipDir when invoked on a directory, Walk skips the directory's contents entirely. If the function returns SkipDir when invoked on a non-directory root.Object, Walk skips the remaining keys in the containing directory.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
plugin
|
|
http
Package http is a plugin for riofs.Open to support opening ROOT files over http(s).
|
Package http is a plugin for riofs.Open to support opening ROOT files over http(s). |
xrootd
Package xrootd is a plugin for riofs.Open to support opening ROOT files over xrootd.
|
Package xrootd is a plugin for riofs.Open to support opening ROOT files over xrootd. |