go-hep.org/x/hep@v0.38.1/groot/rhist/formula.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  	"fmt"
     9  	"reflect"
    10  
    11  	"go-hep.org/x/hep/groot/rbase"
    12  	"go-hep.org/x/hep/groot/rbytes"
    13  	"go-hep.org/x/hep/groot/root"
    14  	"go-hep.org/x/hep/groot/rtypes"
    15  	"go-hep.org/x/hep/groot/rvers"
    16  )
    17  
    18  // Formula describes a ROOT TFormula.
    19  type Formula struct {
    20  	named rbase.Named
    21  
    22  	clingParams  []float64 // parameter values
    23  	allParamsSet bool      // flag to control if all parameters are set
    24  
    25  	params      map[string]int32 // list of parameter names
    26  	formula     string           // string representing the formula expression
    27  	ndim        int32            // Dimension - needed for lambda expressions
    28  	numID       int32            // Number used to identify pre-defined functions (gaus, expo,..)
    29  	linearParts []root.Object    // vector of linear functions
    30  	vectorized  bool             // whether we should use vectorized or regular variables
    31  }
    32  
    33  func newFormula() *Formula {
    34  	return &Formula{
    35  		named: *rbase.NewNamed("", ""),
    36  	}
    37  }
    38  
    39  func (*Formula) RVersion() int16 {
    40  	return rvers.Formula
    41  }
    42  
    43  func (*Formula) Class() string {
    44  	return "TFormula"
    45  }
    46  
    47  // Name returns the name of the instance
    48  func (f *Formula) Name() string {
    49  	return f.named.Name()
    50  }
    51  
    52  // Title returns the title of the instance
    53  func (f *Formula) Title() string {
    54  	return f.named.Title()
    55  }
    56  
    57  // MarshalROOT implements rbytes.Marshaler
    58  func (f *Formula) MarshalROOT(w *rbytes.WBuffer) (int, error) {
    59  	if w.Err() != nil {
    60  		return 0, w.Err()
    61  	}
    62  
    63  	hdr := w.WriteHeader(f.Class(), f.RVersion())
    64  	w.WriteObject(&f.named)
    65  	w.WriteStdVectorF64(f.clingParams)
    66  	w.WriteBool(f.allParamsSet)
    67  	writeMapStringInt(w, f.params)
    68  	w.WriteString(f.formula)
    69  	w.WriteI32(f.ndim)
    70  	w.WriteI32(f.numID)
    71  	writeStdVectorObjP(w, f.linearParts)
    72  	w.WriteBool(f.vectorized)
    73  
    74  	return w.SetHeader(hdr)
    75  }
    76  
    77  func (f *Formula) UnmarshalROOT(r *rbytes.RBuffer) error {
    78  	if r.Err() != nil {
    79  		return r.Err()
    80  	}
    81  
    82  	hdr := r.ReadHeader(f.Class(), f.RVersion())
    83  
    84  	if hdr.Vers < 12 || hdr.Vers > 14 {
    85  		// tested with v12 and v14
    86  		if hdr.Vers < 12 {
    87  			panic(fmt.Errorf("rhist: too old TFormula version=%d < 12", hdr.Vers))
    88  		}
    89  		if hdr.Vers > 14 {
    90  			panic(fmt.Errorf("rhist: too new TFormula version=%d > 14", hdr.Vers))
    91  		}
    92  	}
    93  
    94  	r.ReadObject(&f.named)
    95  	r.ReadStdVectorF64(&f.clingParams)
    96  	f.allParamsSet = r.ReadBool()
    97  	f.params = readMapStringInt(r)
    98  	f.formula = r.ReadString()
    99  	f.ndim = r.ReadI32()
   100  	if hdr.Vers > 13 {
   101  		f.numID = r.ReadI32()
   102  	}
   103  
   104  	f.linearParts = readStdVectorObjP(r)
   105  	f.vectorized = r.ReadBool()
   106  
   107  	r.CheckHeader(hdr)
   108  	return r.Err()
   109  }
   110  
   111  func (f *Formula) String() string {
   112  	return fmt.Sprintf("TFormula{%s}", f.formula)
   113  }
   114  
   115  func readMapStringInt(r *rbytes.RBuffer) map[string]int32 {
   116  	if r.Err() != nil {
   117  		return nil
   118  	}
   119  
   120  	hdr := r.ReadHeader("map<TString,int,TFormulaParamOrder>", rvers.StreamerBaseSTL)
   121  
   122  	n := int(r.ReadI32())
   123  	o := make(map[string]int32, n)
   124  	for range n {
   125  		k := r.ReadString()
   126  		v := r.ReadI32()
   127  		o[k] = v
   128  	}
   129  
   130  	r.CheckHeader(hdr)
   131  	return o
   132  }
   133  
   134  func readStdVectorObjP(r *rbytes.RBuffer) []root.Object {
   135  	if r.Err() != nil {
   136  		return nil
   137  	}
   138  
   139  	hdr := r.ReadHeader("vector<TObject*>", rvers.StreamerBaseSTL)
   140  
   141  	n := int(r.ReadI32())
   142  	o := make([]root.Object, n)
   143  	for i := range o {
   144  		o[i] = r.ReadObjectAny()
   145  	}
   146  
   147  	r.CheckHeader(hdr)
   148  	return o
   149  }
   150  
   151  func writeMapStringInt(w *rbytes.WBuffer, m map[string]int32) {
   152  	if w.Err() != nil {
   153  		return
   154  	}
   155  	const typename = "map<TString,int,TFormulaParamOrder>"
   156  	hdr := w.WriteHeader(typename, rvers.StreamerBaseSTL)
   157  	w.WriteI32(int32(len(m)))
   158  	// FIXME(sbinet): write in correct order?
   159  	for k, v := range m {
   160  		w.WriteString(k)
   161  		w.WriteI32(v)
   162  	}
   163  	_, _ = w.SetHeader(hdr)
   164  }
   165  
   166  func writeStdVectorObjP(w *rbytes.WBuffer, vs []root.Object) {
   167  	if w.Err() != nil {
   168  		return
   169  	}
   170  	const typename = "vector<TObject*>"
   171  	hdr := w.WriteHeader(typename, rvers.StreamerBaseSTL)
   172  	w.WriteI32(int32(len(vs)))
   173  	for i := range vs {
   174  		w.WriteObjectAny(vs[i])
   175  	}
   176  	_, _ = w.SetHeader(hdr)
   177  }
   178  
   179  func init() {
   180  	{
   181  		f := func() reflect.Value {
   182  			o := newFormula()
   183  			return reflect.ValueOf(o)
   184  		}
   185  		rtypes.Factory.Add("TFormula", f)
   186  	}
   187  }
   188  
   189  var (
   190  	_ root.Object        = (*Formula)(nil)
   191  	_ root.Named         = (*Formula)(nil)
   192  	_ rbytes.Marshaler   = (*Formula)(nil)
   193  	_ rbytes.Unmarshaler = (*Formula)(nil)
   194  )