go-hep.org/x/hep@v0.38.1/lcio/writer.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  	"compress/flate"
     9  
    10  	"go-hep.org/x/hep/sio"
    11  )
    12  
    13  // Create creates a new LCIO writer, saving data in file fname.
    14  func Create(fname string) (*Writer, error) {
    15  	f, err := sio.Create(fname)
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  	w := &Writer{
    20  		f:    f,
    21  		clvl: flate.DefaultCompression,
    22  	}
    23  	w.err = w.init()
    24  	return w, w.err
    25  }
    26  
    27  // Writer provides a way to write LCIO RunHeaders and Events to an
    28  // output SIO stream.
    29  type Writer struct {
    30  	f    *sio.Stream
    31  	clvl int
    32  	recs struct {
    33  		idx  *sio.Record
    34  		rnd  *sio.Record
    35  		rhdr *sio.Record
    36  		ehdr *sio.Record
    37  		evt  *sio.Record
    38  	}
    39  	data struct {
    40  		idx  Index
    41  		rnd  RandomAccess
    42  		rhdr RunHeader
    43  		ehdr EventHeader
    44  	}
    45  	closed bool
    46  	err    error
    47  }
    48  
    49  // Close closes the underlying output stream and makes it unavailable for
    50  // further I/O operations.
    51  // Close will synchronize and commit to disk any lingering data before closing
    52  // the output stream.
    53  func (w *Writer) Close() error {
    54  	if w.closed {
    55  		return w.err
    56  	}
    57  	w.err = w.f.Sync()
    58  	if w.err != nil {
    59  		return w.err
    60  	}
    61  	w.err = w.f.Close()
    62  	w.closed = true
    63  	return w.err
    64  }
    65  
    66  func (w *Writer) init() error {
    67  	var (
    68  		err error
    69  		rec *sio.Record
    70  	)
    71  
    72  	rec = w.f.Record(Records.Index)
    73  	if rec != nil {
    74  		err = rec.Connect(Blocks.Index, &w.data.idx)
    75  		if err != nil {
    76  			return err
    77  		}
    78  	}
    79  	w.recs.idx = rec
    80  
    81  	rec = w.f.Record(Records.RandomAccess)
    82  	if rec != nil {
    83  		err = rec.Connect(Blocks.RandomAccess, &w.data.rnd)
    84  		if err != nil {
    85  			return err
    86  		}
    87  	}
    88  	w.recs.rnd = rec
    89  
    90  	rec = w.f.Record(Records.RunHeader)
    91  	if rec != nil {
    92  		err = rec.Connect(Blocks.RunHeader, &w.data.rhdr)
    93  		if err != nil {
    94  			return err
    95  		}
    96  	}
    97  	w.recs.rhdr = rec
    98  
    99  	rec = w.f.Record(Records.EventHeader)
   100  	if rec != nil {
   101  		err = rec.Connect(Blocks.EventHeader, &w.data.ehdr)
   102  		if err != nil {
   103  			return err
   104  		}
   105  	}
   106  	w.recs.ehdr = rec
   107  
   108  	rec = w.f.Record(Records.Event)
   109  	w.recs.evt = rec
   110  
   111  	w.SetCompressionLevel(w.clvl)
   112  	return nil
   113  }
   114  
   115  // SetCompressionLevel sets the compression level to lvl.
   116  // lvl must be a compress/flate compression value.
   117  // SetCompressionLevel must be called before WriteRunHeader or WriteEvent.
   118  func (w *Writer) SetCompressionLevel(lvl int) {
   119  	w.clvl = lvl
   120  	compress := w.clvl != flate.NoCompression
   121  	w.f.SetCompressionLevel(lvl)
   122  	for _, rec := range []*sio.Record{
   123  		w.recs.idx,
   124  		w.recs.rnd,
   125  		w.recs.rhdr,
   126  		w.recs.ehdr,
   127  		w.recs.evt,
   128  	} {
   129  		if rec == nil {
   130  			continue
   131  		}
   132  		rec.SetCompress(compress)
   133  	}
   134  }
   135  
   136  func (w *Writer) WriteRunHeader(run *RunHeader) error {
   137  	if w.err != nil {
   138  		return w.err
   139  	}
   140  	w.data.rhdr = *run
   141  	w.data.rhdr.SubDetectors = make([]string, len(run.SubDetectors))
   142  	copy(w.data.rhdr.SubDetectors, run.SubDetectors)
   143  
   144  	w.err = w.f.WriteRecord(w.recs.rhdr)
   145  	return w.err
   146  }
   147  
   148  func (w *Writer) WriteEvent(evt *Event) error {
   149  	if w.err != nil {
   150  		return w.err
   151  	}
   152  	w.data.ehdr.RunNumber = evt.RunNumber
   153  	w.data.ehdr.EventNumber = evt.EventNumber
   154  	w.data.ehdr.TimeStamp = evt.TimeStamp
   155  	w.data.ehdr.Detector = evt.Detector
   156  	w.data.ehdr.Blocks = make([]BlockDescr, len(evt.names))
   157  	for i, n := range evt.names {
   158  		w.data.ehdr.Blocks[i] = BlockDescr{Name: n, Type: typeName(evt.colls[n])}
   159  	}
   160  	w.data.ehdr.Params = evt.Params
   161  
   162  	w.err = w.f.WriteRecord(w.recs.ehdr)
   163  	if w.err != nil {
   164  		return w.err
   165  	}
   166  
   167  	w.recs.evt.Disconnect()
   168  
   169  	for _, name := range evt.names {
   170  		coll := evt.colls[name]
   171  		w.err = w.recs.evt.Connect(name, coll)
   172  		if w.err != nil {
   173  			return w.err
   174  		}
   175  	}
   176  
   177  	w.err = w.f.WriteRecord(w.recs.evt)
   178  	if w.err != nil {
   179  		return w.err
   180  	}
   181  
   182  	return w.err
   183  }