go-hep.org/x/hep@v0.38.1/groot/rhist/multigraph.go (about)

     1  // Copyright ©2022 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  	"bytes"
     9  	"fmt"
    10  	"reflect"
    11  
    12  	"go-hep.org/x/hep/groot/rbase"
    13  	"go-hep.org/x/hep/groot/rbytes"
    14  	"go-hep.org/x/hep/groot/rcont"
    15  	"go-hep.org/x/hep/groot/root"
    16  	"go-hep.org/x/hep/groot/rtypes"
    17  	"go-hep.org/x/hep/groot/rvers"
    18  	"go-hep.org/x/hep/hbook"
    19  	"go-hep.org/x/hep/hbook/yodacnv"
    20  )
    21  
    22  type tmultigraph struct {
    23  	rbase.Named
    24  
    25  	graphs *rcont.List // Pointer to list of TGraphs
    26  	funcs  *rcont.List // Pointer to list of functions (fits and user)
    27  	histo  *H1F        // Pointer to histogram used for drawing axis
    28  	ymax   float64     // Maximum value for plotting along y
    29  	ymin   float64     // Minimum value for plotting along y
    30  }
    31  
    32  func newMultiGraph() *tmultigraph {
    33  	return &tmultigraph{
    34  		Named:  *rbase.NewNamed("", ""),
    35  		graphs: rcont.NewList("", nil),
    36  		funcs:  rcont.NewList("", nil),
    37  	}
    38  }
    39  
    40  func (*tmultigraph) Class() string {
    41  	return "TMultiGraph"
    42  }
    43  
    44  func (*tmultigraph) RVersion() int16 {
    45  	return rvers.MultiGraph
    46  }
    47  
    48  func (mg *tmultigraph) Len() int {
    49  	return mg.graphs.Len()
    50  }
    51  
    52  func (mg *tmultigraph) Graphs() []Graph {
    53  	o := make([]Graph, mg.Len())
    54  	for i := range o {
    55  		o[i] = mg.graphs.At(i).(Graph)
    56  	}
    57  	return o
    58  }
    59  
    60  func (mg *tmultigraph) ROOTMerge(src root.Object) error {
    61  	panic("not implemented")
    62  }
    63  
    64  // MarshalROOT implements rbytes.Marshaler
    65  func (o *tmultigraph) MarshalROOT(w *rbytes.WBuffer) (int, error) {
    66  	if w.Err() != nil {
    67  		return 0, w.Err()
    68  	}
    69  
    70  	hdr := w.WriteHeader(o.Class(), o.RVersion())
    71  
    72  	w.WriteObject(&o.Named)
    73  	w.WriteObjectAny(o.graphs) // obj-ptr
    74  	w.WriteObjectAny(o.funcs)  // obj-ptr
    75  	w.WriteObjectAny(o.histo)  // obj-ptr
    76  	w.WriteF64(o.ymax)
    77  	w.WriteF64(o.ymin)
    78  
    79  	return w.SetHeader(hdr)
    80  }
    81  
    82  // UnmarshalROOT implements rbytes.Unmarshaler
    83  func (o *tmultigraph) UnmarshalROOT(r *rbytes.RBuffer) error {
    84  	if r.Err() != nil {
    85  		return r.Err()
    86  	}
    87  
    88  	hdr := r.ReadHeader(o.Class(), o.RVersion())
    89  
    90  	r.ReadObject(&o.Named)
    91  	{
    92  		o.graphs = nil
    93  		if oo := r.ReadObjectAny(); oo != nil { // obj-ptr
    94  			o.graphs = oo.(*rcont.List)
    95  		}
    96  	}
    97  	{
    98  		o.funcs = nil
    99  		if oo := r.ReadObjectAny(); oo != nil { // obj-ptr
   100  			o.funcs = oo.(*rcont.List)
   101  		}
   102  	}
   103  	{
   104  		o.histo = nil
   105  		if oo := r.ReadObjectAny(); oo != nil { // obj-ptr
   106  			o.histo = oo.(*H1F)
   107  		}
   108  	}
   109  	o.ymax = r.ReadF64()
   110  	o.ymin = r.ReadF64()
   111  
   112  	r.CheckHeader(hdr)
   113  	return r.Err()
   114  }
   115  
   116  // MarshalYODA implements the YODAMarshaler interface.
   117  func (mg *tmultigraph) MarshalYODA() ([]byte, error) {
   118  	out := new(bytes.Buffer)
   119  	for i := range mg.graphs.Len() {
   120  		g := mg.graphs.At(i).(yodacnv.Marshaler)
   121  		raw, err := g.MarshalYODA()
   122  		if err != nil {
   123  			return nil, fmt.Errorf("rhist: could not marshal multigraph %q: %w", mg.Name(), err)
   124  		}
   125  		_, _ = out.Write(raw)
   126  	}
   127  	return out.Bytes(), nil
   128  }
   129  
   130  // UnmarshalYODA implements the YODAUnmarshaler interface.
   131  func (mg *tmultigraph) UnmarshalYODA(raw []byte) error {
   132  	objs, err := yodacnv.Read(bytes.NewReader(raw))
   133  	if err != nil {
   134  		return fmt.Errorf("rhist: could not unmarshal multigraph: %w", err)
   135  	}
   136  	for i, obj := range objs {
   137  		s2, ok := obj.(*hbook.S2D)
   138  		if !ok {
   139  			return fmt.Errorf("rhist: could not unmarshal multigraph element #%d: got=%T, want=*hbook.S2D", i, obj)
   140  		}
   141  		mg.graphs.Append(NewGraphAsymmErrorsFrom(s2))
   142  	}
   143  	return nil
   144  }
   145  
   146  func (mg *tmultigraph) String() string {
   147  	o, err := mg.MarshalYODA()
   148  	if err != nil {
   149  		panic(err)
   150  	}
   151  	return string(o)
   152  }
   153  
   154  func init() {
   155  	f := func() reflect.Value {
   156  		o := newMultiGraph()
   157  		return reflect.ValueOf(o)
   158  	}
   159  	rtypes.Factory.Add("TMultiGraph", f)
   160  }
   161  
   162  var (
   163  	_ root.Object         = (*tmultigraph)(nil)
   164  	_ root.Named          = (*tmultigraph)(nil)
   165  	_ root.Merger         = (*tmultigraph)(nil)
   166  	_ MultiGraph          = (*tmultigraph)(nil)
   167  	_ rbytes.Marshaler    = (*tmultigraph)(nil)
   168  	_ rbytes.Unmarshaler  = (*tmultigraph)(nil)
   169  	_ yodacnv.Marshaler   = (*tmultigraph)(nil)
   170  	_ yodacnv.Unmarshaler = (*tmultigraph)(nil)
   171  )