go-hep.org/x/hep@v0.38.1/lhef/reader.go (about) 1 // Copyright ©2017 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 lhef 6 7 import ( 8 "bytes" 9 "encoding/xml" 10 "errors" 11 "fmt" 12 "io" 13 ) 14 15 // Decoder represents an LHEF parser reading a particular input stream. 16 // 17 // A Decoder is initialized with an input io.Reader from which to read a version 1.0 18 // Les Houches Accord event file. 19 type Decoder struct { 20 r io.Reader 21 dec *xml.Decoder 22 evt xml.StartElement // the current xml.Token holding a HEPEUP 23 Version int // LHEF file version 24 Run HEPRUP // User process run common block 25 } 26 27 func NewDecoder(r io.Reader) (*Decoder, error) { 28 var err error 29 dec := xml.NewDecoder(r) 30 d := &Decoder{ 31 r: r, 32 dec: dec, 33 Version: -42, 34 Run: HEPRUP{}, 35 } 36 // err := dec.dec.Decode(&dec.lhevt) 37 // if err != nil { 38 // return nil 39 // } 40 // fmt.Printf(">>> version=%v\n", dec.lhevt.Version) 41 42 tok, err := dec.Token() 43 if err != nil || tok == nil { 44 return nil, err 45 } 46 47 // make sure we are reading a LHEF file 48 start, ok := tok.(xml.StartElement) 49 if !ok || start.Name.Local != "LesHouchesEvents" { 50 return nil, errors.New("lhef.Decoder: missing LesHouchesEvent start-tag") 51 } 52 53 //fmt.Printf(">>> %v\n", start) 54 version := start.Attr[0].Value 55 //fmt.Printf(" version=[%s]\n", version) 56 switch version { 57 default: 58 d.Version = -42 59 case "1.0": 60 d.Version = 1 61 case "2.0": 62 d.Version = 2 63 } 64 65 var ( 66 init xml.StartElement 67 // header xml.StartElement // FIXME(sbinet) 68 ) 69 70 Loop: 71 for { 72 tok, err = dec.Token() 73 if err != nil || tok == nil { 74 return nil, err 75 } 76 switch tok := tok.(type) { 77 case xml.Comment: 78 // skip 79 case xml.CharData: 80 // skip 81 case xml.StartElement: 82 switch tok.Name.Local { 83 case "init": 84 init = tok 85 break Loop 86 case "header": 87 // FIXME(sbinet): do something about header's content. 88 // header = tok //FIXME 89 //panic(fmt.Errorf("header not implemented: %v", header)) 90 } 91 } 92 } 93 94 if init.Name.Local != "init" { 95 return nil, errors.New("lhef.Decoder: missing init start-tag") 96 } 97 98 // extract compulsory initialization information 99 tok, err = dec.Token() 100 if err != nil { 101 return nil, err 102 } 103 data, ok := tok.(xml.CharData) 104 if !ok || len(data) == 0 { 105 return nil, errors.New("lhef.Decoder: missing init payload") 106 } 107 buf := bytes.NewBuffer(data) 108 _, err = fmt.Fscanf( 109 buf, 110 "\n%d %d %f %f %d %d %d %d %d %d\n", 111 &d.Run.IDBMUP[0], 112 &d.Run.IDBMUP[1], 113 &d.Run.EBMUP[0], 114 &d.Run.EBMUP[1], 115 &d.Run.PDFGUP[0], 116 &d.Run.PDFGUP[1], 117 &d.Run.PDFSUP[0], 118 &d.Run.PDFSUP[1], 119 &d.Run.IDWTUP, 120 &d.Run.NPRUP, 121 ) 122 if err != nil { 123 return nil, err 124 } 125 126 n := int(d.Run.NPRUP) 127 if n < 0 { 128 return nil, fmt.Errorf("lhef.Decoder: invalid NPRUP (%d)", d.Run.NPRUP) 129 } 130 f64 := make([]float64, 3*n) 131 d.Run.XSECUP = f64[:n:n] 132 d.Run.XERRUP = f64[n : 2*n : 2*n] 133 d.Run.XMAXUP = f64[2*n:] 134 d.Run.LPRUP = make([]int32, n) 135 136 for i := range n { 137 _, err = fmt.Fscanf( 138 buf, 139 "%f %f %f %d\n", 140 &d.Run.XSECUP[i], 141 &d.Run.XERRUP[i], 142 &d.Run.XMAXUP[i], 143 &d.Run.LPRUP[i], 144 ) 145 if err != nil { 146 return nil, fmt.Errorf("lhef: failed to decode NPRUP %d: %w", i, err) 147 } 148 } 149 150 // FIXME(sbinet): implement v2 specific stuff 151 // if d.Version >= 2 { 152 // // do version-2 specific stuff 153 // } 154 155 err = d.seek(init.End()) 156 if err != nil { 157 return nil, fmt.Errorf("lhef: could not find 'init' end tag: %w", err) 158 } 159 160 return d, nil 161 } 162 163 // advance to next event 164 func (d *Decoder) next() error { 165 LoopEvt: 166 for { 167 tok, err := d.dec.Token() 168 if err != nil { 169 return err 170 } 171 switch tt := tok.(type) { 172 case xml.Comment: 173 // skip 174 case xml.CharData: 175 // skip 176 case xml.StartElement: 177 switch tt.Name.Local { 178 case "event": 179 d.evt = tt 180 break LoopEvt 181 } 182 } 183 } 184 185 return nil 186 } 187 188 func (d *Decoder) seek(tok xml.Token) error { 189 seek: 190 for { 191 tk, err := d.dec.Token() 192 if err != nil { 193 return err 194 } 195 if tk == tok { 196 break seek 197 } 198 } 199 200 return nil 201 } 202 203 // Read an event from the file 204 func (d *Decoder) Decode() (*HEPEUP, error) { 205 206 // check whether the initialization was successful 207 if d.Run.NPRUP < 0 { 208 return nil, errors.New("lhef.Decode: initialization failed (no particle entries)") 209 } 210 211 err := d.next() 212 if err != nil { 213 return nil, err 214 } 215 216 // extract payload data 217 tok, err := d.dec.Token() 218 if err != nil { 219 return nil, err 220 } 221 data, ok := tok.(xml.CharData) 222 if !ok { 223 return nil, fmt.Errorf("lhef.Decode: invalid token (%T: %v)", tok, tok) 224 } 225 if len(data) <= 0 { 226 return nil, errors.New("lhef.Decode: empty event") 227 } 228 buf := bytes.NewBuffer(data) 229 230 evt := &HEPEUP{ 231 NUP: 0, 232 } 233 234 _, err = fmt.Fscanf( 235 buf, 236 "\n%d %d %f %f %f %f\n", 237 &evt.NUP, 238 &evt.IDPRUP, 239 &evt.XWGTUP, 240 &evt.SCALUP, 241 &evt.AQEDUP, 242 &evt.AQCDUP, 243 ) 244 if err != nil { 245 fmt.Printf("--> 2 err: %v\n", err) 246 fmt.Printf(" data: %v\n", string(data)) 247 fmt.Printf(" token: (%T: %v)\n", tok, tok) 248 return nil, err 249 } 250 251 n := int(evt.NUP) 252 evt.IDUP = make([]int64, n) 253 evt.ISTUP = make([]int32, n) 254 n2 := make([][2]int32, 2*n) 255 evt.MOTHUP = n2[:n:n] 256 evt.ICOLUP = n2[n:] 257 evt.PUP = make([][5]float64, n) 258 f64 := make([]float64, 2*n) 259 evt.VTIMUP = f64[:n:n] 260 evt.SPINUP = f64[n:] 261 for i := range n { 262 _, err = fmt.Fscanf( 263 buf, 264 "%d %d %d %d %d %d %f %f %f %f %f %f %f\n", 265 &evt.IDUP[i], 266 &evt.ISTUP[i], 267 &evt.MOTHUP[i][0], 268 &evt.MOTHUP[i][1], 269 &evt.ICOLUP[i][0], 270 &evt.ICOLUP[i][1], 271 &evt.PUP[i][0], &evt.PUP[i][1], &evt.PUP[i][2], 272 &evt.PUP[i][3], &evt.PUP[i][4], 273 &evt.VTIMUP[i], 274 &evt.SPINUP[i], 275 ) 276 if err != nil { 277 fmt.Printf("--> 3-%d err: %v\n", i, err) 278 return nil, err 279 } 280 } 281 282 // read any additional comments... 283 _ /*evtComments*/ = buf.Bytes() 284 285 // do 286 287 // put "cursor" to next event... 288 err = d.seek(d.evt.End()) 289 if err != nil { 290 return nil, fmt.Errorf("lhef: could not find 'event' end tag: %w", err) 291 } 292 293 return evt, nil 294 }