go-hep.org/x/hep@v0.38.1/lcio/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 lcio 6 7 import ( 8 "fmt" 9 10 "go-hep.org/x/hep/sio" 11 ) 12 13 func Open(fname string) (*Reader, error) { 14 f, err := sio.Open(fname) 15 if err != nil { 16 return nil, err 17 } 18 r := &Reader{ 19 f: f, 20 } 21 err = r.init() 22 if err != nil { 23 return nil, err 24 } 25 return r, nil 26 } 27 28 type Reader struct { 29 f *sio.Stream 30 idx Index 31 rnd RandomAccess 32 rhdr RunHeader 33 ehdr EventHeader 34 evt Event 35 err error 36 } 37 38 func (r *Reader) Close() error { 39 return r.f.Close() 40 } 41 42 func (r *Reader) init() error { 43 var ( 44 err error 45 rec *sio.Record 46 ) 47 48 rec = r.f.Record(Records.Index) 49 if rec != nil { 50 rec.SetUnpack(true) 51 err = rec.Connect(Blocks.Index, &r.idx) 52 if err != nil { 53 return err 54 } 55 } 56 57 rec = r.f.Record(Records.RandomAccess) 58 if rec != nil { 59 rec.SetUnpack(true) 60 err = rec.Connect(Blocks.RandomAccess, &r.rnd) 61 if err != nil { 62 return err 63 } 64 } 65 66 rec = r.f.Record(Records.RunHeader) 67 if rec != nil { 68 rec.SetUnpack(true) 69 err = rec.Connect(Blocks.RunHeader, &r.rhdr) 70 if err != nil { 71 return err 72 } 73 } 74 75 rec = r.f.Record(Records.EventHeader) 76 if rec != nil { 77 rec.SetUnpack(true) 78 err = rec.Connect(Blocks.EventHeader, &r.ehdr) 79 if err != nil { 80 return err 81 } 82 } 83 84 rec = r.f.Record(Records.Event) 85 if rec != nil { 86 rec.SetUnpack(true) 87 } 88 89 return nil 90 } 91 92 func (r *Reader) Next() bool { 93 if r.err != nil { 94 return false 95 } 96 rec, err := r.f.ReadRecord() 97 if err != nil { 98 r.err = err 99 return false 100 } 101 // log.Printf(">>> %q", rec.Name()) 102 switch rec.Name() { 103 case Records.Index: 104 if !rec.Unpack() { 105 r.err = fmt.Errorf("lcio: expected record %q to unpack", rec.Name()) 106 return false 107 } 108 return r.Next() 109 110 case Records.RandomAccess: 111 if !rec.Unpack() { 112 r.err = fmt.Errorf("lcio: expected record %q to unpack", rec.Name()) 113 return false 114 } 115 return r.Next() 116 117 case Records.RunHeader: 118 if !rec.Unpack() { 119 r.err = fmt.Errorf("lcio: expected record %q to unpack", rec.Name()) 120 return false 121 } 122 return r.Next() 123 124 case Records.EventHeader: 125 if !rec.Unpack() { 126 r.err = fmt.Errorf("lcio: expected record %q to unpack", rec.Name()) 127 return false 128 } 129 err = r.remap() 130 if err != nil { 131 r.err = err 132 return false 133 } 134 return r.Next() 135 136 case Records.Event: 137 if !rec.Unpack() { 138 r.err = fmt.Errorf("lcio: expected record %q to unpack", rec.Name()) 139 } 140 } 141 return true 142 } 143 144 func (r *Reader) remap() error { 145 var err error 146 rec := r.f.Record(Records.Event) 147 r.evt.colls = nil 148 r.evt.names = nil 149 if len(r.ehdr.Blocks) > 0 { 150 r.evt.colls = make(map[string]any, len(r.ehdr.Blocks)) 151 r.evt.names = make([]string, 0, len(r.ehdr.Blocks)) 152 for _, blk := range r.ehdr.Blocks { 153 ptr := typeFrom(blk.Type) 154 if ptr == nil { 155 continue 156 } 157 err = rec.Connect(blk.Name, ptr) 158 if err != nil { 159 r.err = err 160 return err 161 } 162 r.evt.colls[blk.Name] = ptr 163 r.evt.names = append(r.evt.names, blk.Name) 164 } 165 } 166 r.evt.RunNumber = r.ehdr.RunNumber 167 r.evt.EventNumber = r.ehdr.EventNumber 168 r.evt.TimeStamp = r.ehdr.TimeStamp 169 r.evt.Detector = r.ehdr.Detector 170 r.evt.Params = r.ehdr.Params 171 return err 172 } 173 174 func (r *Reader) RunHeader() RunHeader { 175 return r.rhdr 176 } 177 178 func (r *Reader) EventHeader() EventHeader { 179 return r.ehdr 180 } 181 182 func (r *Reader) Event() Event { 183 return r.evt 184 } 185 186 func (r *Reader) Err() error { 187 return r.err 188 }