Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaCodaFile.cxx
Go to the documentation of this file.
1
2//
3// THaCodaFile
4// File of CODA data
5//
6// CODA data file, and facilities to open, close, read,
7// write, filter CODA data to disk files, etc.
8//
9// This is largely a wrapper around the JLAB EVIO library.
10//
11// author Robert Michaels (rom@jlab.org)
12//
14
15#include "THaCodaFile.h"
16#include "Helper.h"
17#include "TSystem.h"
18#include "evio.h"
19#include <iostream>
20#include <memory>
21#include <algorithm>
22
23using namespace std;
24
25namespace Decoder {
26
27//Constructors
28
29//_____________________________________________________________________________
31 : max_to_filt(0), maxflist(0), maxftype(0)
32 {
33 // Default constructor. Do nothing (must open file separately).
34 }
35
36//_____________________________________________________________________________
37 THaCodaFile::THaCodaFile(const char* fname, const char* readwrite)
38 : max_to_filt(0), maxflist(0), maxftype(0)
39 {
40 // Standard constructor. Pass read or write flag
41 THaCodaFile::codaOpen(fname, readwrite);
42 }
43
44//_____________________________________________________________________________
46 {
47 //Destructor
49 }
50
51//_____________________________________________________________________________
52 Int_t THaCodaFile::codaOpen(const char* fname, Int_t mode )
53 {
54 // Open CODA file 'fname' in read-only mode
55 return codaOpen( fname, "r", mode );
56 }
57
58//_____________________________________________________________________________
59 Int_t THaCodaFile::codaOpen(const char* fname, const char* readwrite,
60 Int_t /* mode */ )
61 {
62 // Open CODA file 'fname' with 'readwrite' access
63 init(fname);
64 Int_t status = evOpen((char*)fname, (char*)readwrite, &handle);
65 fIsGood = (status == S_SUCCESS);
66 staterr("open",status);
67 return ReturnCode(status);
68 }
69
70//_____________________________________________________________________________
72// Close the file. Do nothing if file not opened.
73 if( !handle ) {
74 return ReturnCode(S_SUCCESS);
75 }
76 Int_t status = evClose(handle);
77 handle = 0;
78 fIsGood = (status == S_SUCCESS);
79 staterr("close",status);
80 return ReturnCode(status);
81 }
82
83//_____________________________________________________________________________
85// codaRead: Reads data from file, stored in evbuffer.
86// Must be called once per event.
87 if( !handle ) {
88 if (verbose > 0) {
89 cout << "codaRead ERROR: tried to access a file with handle = 0" << endl;
90 cout << "You need to call codaOpen(filename)" << endl;
91 cout << "or use the constructor with (filename) arg" << endl;
92 }
93 return ReturnCode(S_EVFILE_BADHANDLE);
94 }
95 Int_t status = S_SUCCESS;
96 do {
98 status = evRead(handle, getEvBuffer(), getBuffSize());
99 if( status == S_EVFILE_TRUNC ) {
100 // At least with EVIO version 5.2, probably earlier and hopefully later
101 // versions too, evRead has not consumed any buffer data if this
102 // error occurs. Thus growing the buffer and retrying is safe.
103 // Unfortunately, the EVIO C-API does not provide any means to access
104 // the actual event length here, so we have to guess how much more
105 // space is needed. TODO: Make an EVIO feature request?
106 if( !evbuffer.grow() )
107 break;
108 }
109 } while( status == S_EVFILE_TRUNC );
110
111 if( status == S_SUCCESS )
113
114 fIsGood = (status == S_SUCCESS || status == EOF );
115 staterr("read",status);
116 return ReturnCode(status);
117 }
118
119
120//_____________________________________________________________________________
122// codaWrite: Writes data from 'evbuf' to file
123 if( !handle ) {
124 cout << "codaWrite ERROR: tried to access file with handle = 0" << endl;
125 return ReturnCode(S_EVFILE_BADHANDLE);
126 }
127 Int_t status = evWrite(handle, evbuf);
128 fIsGood = (status == S_SUCCESS);
129 staterr("write",status);
130 return ReturnCode(status);
131 }
132
133 bool THaCodaFile::isOpen() const {
134 return (handle!=0);
135 }
136
137//_____________________________________________________________________________
138template<typename T>
139struct Equals {
140 const T m_val;
141 explicit Equals(T val) : m_val(val) {}
142 bool operator()(T val) const { return val == m_val; }
143};
144
145//_____________________________________________________________________________
146Int_t THaCodaFile::filterToFile( const char* output_file )
147{
148// A call to filterToFile filters from present file to output_file
149// using filter criteria defined by evtypes, evlist, and max_to_filt
150// which are loaded by public methods of this class. If no conditions
151// were loaded, it makes a copy of the input file (i.e. no filtering).
152
153 if( filename == output_file ) {
154 if (verbose > 0) {
155 cout << "filterToFile: ERROR: ";
156 cout << "Input and output files cannot be same " << endl;
157 cout << "This is to protect you against overwriting data" << endl;
158 }
159 return CODA_ERROR;
160 }
161 if( !gSystem->AccessPathName(output_file, kReadPermission) ) {
162 if (verbose > 0) {
163 cout << "filterToFile: ERROR: ";
164 cout << "Output file `" << output_file << "' exists " << endl;
165 cout << "You must remove it by hand first. " << endl;
166 cout << "This forces you to think and not overwrite data." << endl;
167 }
168 fIsGood = false;
169 return CODA_FATAL;
170 }
171 unique_ptr<THaCodaFile> fout{new THaCodaFile(output_file, "w")};
172 if( !fout->isGood()) {
173 fIsGood = false;
174 return CODA_FATAL;
175 }
176
177 UInt_t nfilt = 0;
178 Int_t status = CODA_OK, fout_status = CODA_OK;
179 while( (status = codaRead()) == CODA_OK ) {
180 UInt_t* rawbuff = getEvBuffer();
181 UInt_t evtype = rawbuff[1] >> 16;
182 UInt_t evnum = rawbuff[4];
183 if (verbose > 1) {
184 cout << "Input evtype " << dec << evtype;
185 cout << " evnum " << evnum << endl;
186 cout << "max_to_filt = " << max_to_filt << endl;
187 cout << "evtype size = " << evtypes.size() << endl;
188 cout << "evlist size = " << evlist.size() << endl;
189 }
190
191 Bool_t oktofilt = true;
192 if( !evtypes.empty() )
193 oktofilt = any_of(ALL(evtypes), Equals<UInt_t>(evtype));
194 // JOH: Added this test to let the filter act as a logical AND of
195 // the configured event types and event numbers, which is more general.
196 // Empty event type or event number lists always pass. I.e. if both lists
197 // are empty, the filter passes all events. If only event types are set,
198 // it passes only those types, regardless of event number. Etc.
199 // The previous behavior was to ignore any configured event types if
200 // event numbers were also configured. Obviously, that's a special case of
201 // the above which one can achieve by leaving the event type list empty.
202 if( !oktofilt )
203 continue;
204 if( !evlist.empty() )
205 oktofilt = any_of(ALL(evlist), Equals<UInt_t>(evnum));
206 if( !oktofilt )
207 continue;
208
209 nfilt++;
210 if (verbose > 1) {
211 cout << "Filtering event, nfilt " << dec << nfilt << endl;
212 }
213 fout_status = fout->codaWrite(getEvBuffer());
214 if( fout_status != CODA_OK ) {
215 if (verbose > 0) {
216 cout << "Error in filterToFile ! " << endl;
217 cout << "codaWrite returned status " << fout_status << endl;
218 }
219 break;
220 }
221 if( max_to_filt > 0 ) {
222 if( nfilt == max_to_filt ) {
223 break;
224 }
225 }
226 }
227 if( status == CODA_EOF) // EOF is normal
228 status = CODA_OK;
229 fIsGood = (status == CODA_OK);
230
231 fout_status = fout->codaClose();
232
233 return fIsGood ? fout_status : status;
234}
235
236//_____________________________________________________________________________
238// Function to set up filtering by event type
239 {
240 if( evtypes.capacity() < 16 )
241 // Typical filtering scenarios involve a small number of event types
242 evtypes.reserve(16);
243 evtypes.push_back(evtype_to_filt);
244 }
245
246//_____________________________________________________________________________
248// Function to set up filtering by list of event numbers
249 {
250 if( evlist.capacity() < 1024 )
251 // Event lists tend to be lengthy, so start out with a generous size
252 evlist.reserve(1024);
253 evlist.push_back(event_to_filt);
254 }
255
256//_____________________________________________________________________________
258// Function to set up the max number of events to filter
259 {
260 max_to_filt = max_event;
261 }
262
263//_____________________________________________________________________________
264 void THaCodaFile::init(const char* fname) {
265 if( filename != fname ) {
266 codaClose();
267 filename = fname;
268 }
269 handle = 0;
270 }
271}
272
273//_____________________________________________________________________________
int Int_t
unsigned int UInt_t
bool Bool_t
Option_t Option_t TPoint TPoint const char mode
#define CODA_ERROR
Definition THaCodaData.h:30
#define CODA_FATAL
Definition THaCodaData.h:31
#define CODA_EOF
Definition THaCodaData.h:29
#define CODA_OK
Definition THaCodaData.h:28
kReadPermission
R__EXTERN TSystem * gSystem
Bool_t grow(UInt_t newsize=0)
UInt_t * getEvBuffer()
Definition THaCodaData.h:76
void staterr(const char *tried_to, Int_t status) const
UInt_t getBuffSize() const
Definition THaCodaData.h:77
static Int_t ReturnCode(Int_t evio_retcode)
void addEvTypeFilt(UInt_t evtype_to_filt)
virtual bool isOpen() const
virtual Int_t codaOpen(const char *filename, Int_t mode=1)
std::vector< UInt_t > evtypes
Definition THaCodaFile.h:51
void init(const char *fname="")
void setMaxEvFilt(UInt_t max_event)
Int_t filterToFile(const char *output_file)
virtual Int_t codaClose()
virtual Int_t codaRead()
std::vector< UInt_t > evlist
Definition THaCodaFile.h:51
Int_t codaWrite(const UInt_t *evbuffer)
void addEvListFilt(UInt_t event_to_filt)
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
double T(double x)
STL namespace.
bool operator()(T val) const
ClassImp(TPyArg)