Skip to content

Commit

Permalink
groot/{rcmd,rhist,rvers}: add support for TMultiGraph
Browse files Browse the repository at this point in the history
Fixes #422.
  • Loading branch information
sbinet committed Feb 23, 2022
1 parent 1747412 commit e453fa7
Show file tree
Hide file tree
Showing 11 changed files with 354 additions and 0 deletions.
1 change: 1 addition & 0 deletions groot/gen.rboot.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ var (
"TH1", "TH1C", "TH1D", "TH1F", "TH1I", "TH1K", "TH1S",
"TH2", "TH2C", "TH2D", "TH2F", "TH2I", "TH2Poly", "TH2PolyBin", "TH2S",
"TLimit", "TLimitDataSource",
"TMultiGraph",
"TProfile", "TProfile2D",

// riofs
Expand Down
8 changes: 8 additions & 0 deletions groot/rcmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ func (cmd *dumpCmd) dumpObj(obj root.Object) error {
case rhist.Graph:
fmt.Fprintf(cmd.w, "\n")
err = cmd.dumpGraph(obj)
case rhist.MultiGraph:
for _, g := range obj.Graphs() {
fmt.Fprintf(cmd.w, "\n")
err = cmd.dumpGraph(g)
if err != nil {
return err
}
}
case root.List:
fmt.Fprintf(cmd.w, "\n")
err = cmd.dumpList(obj)
Expand Down
4 changes: 4 additions & 0 deletions groot/rcmd/dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ key[004]: tree;1 "my tree title" (TTree)
[001][b3]: {2006-01-03 15:04:05 +0000 UTC [49 50 51 52 53 0]}
`,
},
{
name: "../testdata/tgme.root",
want: loadRef("testdata/tgme.root.txt"),
},
} {
t.Run(tc.name, func(t *testing.T) {
got := new(strings.Builder)
Expand Down
56 changes: 56 additions & 0 deletions groot/rcmd/testdata/tgme.root.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
key[000]: gme;1 "TGraphMultiErrors Example" (TGraphMultiErrors)
BEGIN YODA_SCATTER2D_V2 /gme
Path: /gme
Title: TGraphMultiErrors Example
Type: Scatter2D
---
# xval xerr- xerr+ yval yerr- yerr+
0.000000e+00 3.000000e-01 3.000000e-01 0.000000e+00 1.000000e+00 5.000000e-01
1.000000e+00 3.000000e-01 3.000000e-01 2.000000e+00 5.000000e-01 1.000000e+00
2.000000e+00 3.000000e-01 3.000000e-01 4.000000e+00 1.000000e+00 5.000000e-01
3.000000e+00 3.000000e-01 3.000000e-01 1.000000e+00 5.000000e-01 1.000000e+00
4.000000e+00 3.000000e-01 3.000000e-01 3.000000e+00 1.000000e+00 2.000000e+00
END YODA_SCATTER2D_V2

key[001]: mg;1 "multi-graph example" (TMultiGraph)
BEGIN YODA_SCATTER2D_V2 /Graph
Path: /Graph
Title: Graph
Type: Scatter2D
---
# xval xerr- xerr+ yval yerr- yerr+
0.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00 0.000000e+00 0.000000e+00
1.000000e+00 0.000000e+00 0.000000e+00 5.000000e-01 0.000000e+00 0.000000e+00
2.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00 0.000000e+00 0.000000e+00
3.000000e+00 0.000000e+00 0.000000e+00 5.000000e-01 0.000000e+00 0.000000e+00
4.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00 0.000000e+00 0.000000e+00
END YODA_SCATTER2D_V2


BEGIN YODA_SCATTER2D_V2 /Graph
Path: /Graph
Title: Graph
Type: Scatter2D
---
# xval xerr- xerr+ yval yerr- yerr+
0.000000e+00 3.000000e-01 3.000000e-01 0.000000e+00 5.000000e-01 5.000000e-01
1.000000e+00 3.000000e-01 3.000000e-01 2.000000e+00 4.000000e-01 4.000000e-01
2.000000e+00 3.000000e-01 3.000000e-01 4.000000e+00 8.000000e-01 8.000000e-01
3.000000e+00 3.000000e-01 3.000000e-01 1.000000e+00 3.000000e-01 3.000000e-01
4.000000e+00 3.000000e-01 3.000000e-01 3.000000e+00 1.200000e+00 1.200000e+00
END YODA_SCATTER2D_V2


BEGIN YODA_SCATTER2D_V2 /Graph
Path: /Graph
Title: Graph
Type: Scatter2D
---
# xval xerr- xerr+ yval yerr- yerr+
0.000000e+00 3.000000e-01 3.000000e-01 0.000000e+00 1.000000e+00 5.000000e-01
1.000000e+00 3.000000e-01 3.000000e-01 2.000000e+00 5.000000e-01 1.000000e+00
2.000000e+00 3.000000e-01 3.000000e-01 4.000000e+00 1.000000e+00 5.000000e-01
3.000000e+00 3.000000e-01 3.000000e-01 1.000000e+00 5.000000e-01 1.000000e+00
4.000000e+00 3.000000e-01 3.000000e-01 3.000000e+00 1.000000e+00 2.000000e+00
END YODA_SCATTER2D_V2

80 changes: 80 additions & 0 deletions groot/rdict/cxx_root_streamers_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4362,6 +4362,86 @@ func init() {
Factor: 0.000000,
}.New()},
}))
StreamerInfos.Add(NewCxxStreamerInfo("TMultiGraph", 2, 0xe0893cd5, []rbytes.StreamerElement{
NewStreamerBase(Element{
Name: *rbase.NewNamed("TNamed", "The basis for a named object (name, title)"),
Type: rmeta.Base,
Size: 0,
ArrLen: 0,
ArrDim: 0,
MaxIdx: [5]int32{0, -541636036, 0, 0, 0},
Offset: 0,
EName: "BASE",
XMin: 0.000000,
XMax: 0.000000,
Factor: 0.000000,
}.New(), 1),
&StreamerObjectPointer{StreamerElement: Element{
Name: *rbase.NewNamed("fGraphs", "Pointer to list of TGraphs"),
Type: rmeta.ObjectP,
Size: 8,
ArrLen: 0,
ArrDim: 0,
MaxIdx: [5]int32{0, 0, 0, 0, 0},
Offset: 0,
EName: "TList*",
XMin: 0.000000,
XMax: 0.000000,
Factor: 0.000000,
}.New()},
&StreamerObjectPointer{StreamerElement: Element{
Name: *rbase.NewNamed("fFunctions", "Pointer to list of functions (fits and user)"),
Type: rmeta.ObjectP,
Size: 8,
ArrLen: 0,
ArrDim: 0,
MaxIdx: [5]int32{0, 0, 0, 0, 0},
Offset: 0,
EName: "TList*",
XMin: 0.000000,
XMax: 0.000000,
Factor: 0.000000,
}.New()},
&StreamerObjectPointer{StreamerElement: Element{
Name: *rbase.NewNamed("fHistogram", "Pointer to histogram used for drawing axis"),
Type: rmeta.ObjectP,
Size: 8,
ArrLen: 0,
ArrDim: 0,
MaxIdx: [5]int32{0, 0, 0, 0, 0},
Offset: 0,
EName: "TH1F*",
XMin: 0.000000,
XMax: 0.000000,
Factor: 0.000000,
}.New()},
&StreamerBasicType{StreamerElement: Element{
Name: *rbase.NewNamed("fMaximum", "Maximum value for plotting along y"),
Type: rmeta.Double,
Size: 8,
ArrLen: 0,
ArrDim: 0,
MaxIdx: [5]int32{0, 0, 0, 0, 0},
Offset: 0,
EName: "double",
XMin: 0.000000,
XMax: 0.000000,
Factor: 0.000000,
}.New()},
&StreamerBasicType{StreamerElement: Element{
Name: *rbase.NewNamed("fMinimum", "Minimum value for plotting along y"),
Type: rmeta.Double,
Size: 8,
ArrLen: 0,
ArrDim: 0,
MaxIdx: [5]int32{0, 0, 0, 0, 0},
Offset: 0,
EName: "double",
XMin: 0.000000,
XMax: 0.000000,
Factor: 0.000000,
}.New()},
}))
StreamerInfos.Add(NewCxxStreamerInfo("TProfile", 7, 0x4bedee54, []rbytes.StreamerElement{
NewStreamerBase(Element{
Name: *rbase.NewNamed("TH1D", "1-Dim histograms (one double per channel)"),
Expand Down
177 changes: 177 additions & 0 deletions groot/rhist/multigraph.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright ©2022 The go-hep Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rhist

import (
"bytes"
"fmt"
"reflect"

"go-hep.org/x/hep/groot/rbase"
"go-hep.org/x/hep/groot/rbytes"
"go-hep.org/x/hep/groot/rcont"
"go-hep.org/x/hep/groot/root"
"go-hep.org/x/hep/groot/rtypes"
"go-hep.org/x/hep/groot/rvers"
"go-hep.org/x/hep/hbook"
"go-hep.org/x/hep/hbook/yodacnv"
)

type tmultigraph struct {
rbase.Named

graphs *rcont.List // Pointer to list of TGraphs
funcs *rcont.List // Pointer to list of functions (fits and user)
histo *H1F // Pointer to histogram used for drawing axis
ymax float64 // Maximum value for plotting along y
ymin float64 // Minimum value for plotting along y
}

func newMultiGraph() *tmultigraph {
return &tmultigraph{
Named: *rbase.NewNamed("", ""),
graphs: rcont.NewList("", nil),
funcs: rcont.NewList("", nil),
}
}

func (*tmultigraph) Class() string {
return "TMultiGraph"
}

func (*tmultigraph) RVersion() int16 {
return rvers.MultiGraph
}

func (mg *tmultigraph) Len() int {
return mg.graphs.Len()
}

func (mg *tmultigraph) Graphs() []Graph {
o := make([]Graph, mg.Len())
for i := range o {
o[i] = mg.graphs.At(i).(Graph)
}
return o
}

func (mg *tmultigraph) ROOTMerge(src root.Object) error {
panic("not implemented")
}

// MarshalROOT implements rbytes.Marshaler
func (o *tmultigraph) MarshalROOT(w *rbytes.WBuffer) (int, error) {
if w.Err() != nil {
return 0, w.Err()
}

hdr := w.WriteHeader(o.Class(), o.RVersion())

w.WriteObject(&o.Named)
w.WriteObjectAny(o.graphs) // obj-ptr
w.WriteObjectAny(o.funcs) // obj-ptr
w.WriteObjectAny(o.histo) // obj-ptr
w.WriteF64(o.ymax)
w.WriteF64(o.ymin)

return w.SetHeader(hdr)
}

// UnmarshalROOT implements rbytes.Unmarshaler
func (o *tmultigraph) UnmarshalROOT(r *rbytes.RBuffer) error {
if r.Err() != nil {
return r.Err()
}

hdr := r.ReadHeader(o.Class())
if hdr.Vers > o.RVersion() {
panic(fmt.Errorf(
"rbytes: invalid %s version=%d > %d",
o.Class(), hdr.Vers, o.RVersion(),
))
}

r.ReadObject(&o.Named)
{
o.graphs = nil
if oo := r.ReadObjectAny(); oo != nil { // obj-ptr
o.graphs = oo.(*rcont.List)
}
}
{
o.funcs = nil
if oo := r.ReadObjectAny(); oo != nil { // obj-ptr
o.funcs = oo.(*rcont.List)
}
}
{
o.histo = nil
if oo := r.ReadObjectAny(); oo != nil { // obj-ptr
o.histo = oo.(*H1F)
}
}
o.ymax = r.ReadF64()
o.ymin = r.ReadF64()

r.CheckHeader(hdr)
return r.Err()
}

// MarshalYODA implements the YODAMarshaler interface.
func (mg *tmultigraph) MarshalYODA() ([]byte, error) {
out := new(bytes.Buffer)
for i := 0; i < mg.graphs.Len(); i++ {
g := mg.graphs.At(i).(yodacnv.Marshaler)
raw, err := g.MarshalYODA()
if err != nil {
return nil, fmt.Errorf("rhist: could not marshal multigraph %q: %w", mg.Name(), err)
}
_, _ = out.Write(raw)
}
return out.Bytes(), nil
}

// UnmarshalYODA implements the YODAUnmarshaler interface.
func (mg *tmultigraph) UnmarshalYODA(raw []byte) error {
objs, err := yodacnv.Read(bytes.NewReader(raw))
if err != nil {
return fmt.Errorf("rhist: could not unmarshal multigraph: %w", err)
}
for i, obj := range objs {
s2, ok := obj.(*hbook.S2D)
if !ok {
return fmt.Errorf("rhist: could not unmarshal multigraph element #%d: got=%T, want=*hbook.S2D", i, obj)
}
mg.graphs.Append(NewGraphAsymmErrorsFrom(s2))
}
return nil
}

func (mg *tmultigraph) String() string {
o, err := mg.MarshalYODA()
if err != nil {
panic(err)
}
return string(o)
}

func init() {
f := func() reflect.Value {
o := newMultiGraph()
return reflect.ValueOf(o)
}
rtypes.Factory.Add("TMultiGraph", f)
}

var (
_ root.Object = (*tmultigraph)(nil)
_ root.Named = (*tmultigraph)(nil)
_ root.Merger = (*tmultigraph)(nil)
_ MultiGraph = (*tmultigraph)(nil)
_ rbytes.Marshaler = (*tmultigraph)(nil)
_ rbytes.Unmarshaler = (*tmultigraph)(nil)
_ yodacnv.Marshaler = (*tmultigraph)(nil)
_ yodacnv.Unmarshaler = (*tmultigraph)(nil)
)
7 changes: 7 additions & 0 deletions groot/rhist/rhist.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,10 @@ type F1Composition interface {
isF1Composition() // FIXME(sbinet): have a more useful interface?
// Eval(xs, ps []float64) float64
}

// MultiGraph describes a ROOT TMultiGraph
type MultiGraph interface {
root.Named

Graphs() []Graph
}
4 changes: 4 additions & 0 deletions groot/rhist/rw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ func TestWRBuffer(t *testing.T) {
name: "TGraphMultiErrors",
want: loadFrom("../testdata/tgme.root", "gme"),
},
{
name: "TMultiGraph",
want: loadFrom("../testdata/tgme.root", "mg"),
},
} {
t.Run(tc.name, func(t *testing.T) {
{
Expand Down
Loading

0 comments on commit e453fa7

Please sign in to comment.