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 )