Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
evio_cull_events.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // Created June 10, 2014 David Lawrence
4 
5 #include <iostream>
6 #include <fstream>
7 #include <iomanip>
8 #include <vector>
9 using namespace std;
10 
11 #include <signal.h>
12 #include <time.h>
13 #include <stdlib.h>
14 
15 #include <evioFileChannel.hxx>
16 #include <evioUtil.hxx>
17 using namespace evio;
18 
19 
20 #ifndef _DBG_
21 #define _DBG_ cout<<__FILE__<<":"<<__LINE__<<" "
22 #define _DBG__ cout<<__FILE__<<":"<<__LINE__<<endl
23 #endif
24 
25 void ParseCommandLineArguments(int narg, char* argv[]);
26 void Usage(void);
27 void ctrlCHandle(int x);
28 void Process(unsigned int &NEvents, unsigned int &NEvents_read);
29 uint64_t FindEventNumber(evioDOMTree *evt, uint64_t &block_size);
30 
31 
32 vector<char*> INFILENAMES;
33 char *OUTFILENAME = NULL;
34 int QUIT = 0;
35 unsigned int EVENTS_TO_SKIP = 0;
36 unsigned int EVENTS_TO_KEEP = 1;
37 unsigned int SPECIFIC_OFFSET_TO_KEEP = 0;
38 unsigned int SPECIFIC_EVENT_TO_KEEP = 0;
39 unsigned int BUFFER_SIZE = 20000000;
40 bool EVENT_TO_KEEP_MODE = false;
41 
42 
43 
44 //-----------
45 // main
46 //-----------
47 int main(int narg,char* argv[])
48 {
49  // Set up to catch SIGINTs for graceful exits
50  signal(SIGINT,ctrlCHandle);
51 
52  ParseCommandLineArguments(narg, argv);
53 
55  cout<<"Searching for event " << SPECIFIC_EVENT_TO_KEEP << " ..." << endl;
56  }else{
57  cout<<"Skipping "<<EVENTS_TO_SKIP<<endl;
58  cout<<"Keeping "<<EVENTS_TO_KEEP<<endl;
59  }
60  unsigned int NEvents = 0;
61  unsigned int NEvents_read = 0;
62 
63  // Process all events
64  Process(NEvents, NEvents_read);
65 
66  cout<<endl;
67  cout<<" "<<NEvents_read<<" events read, "<<NEvents<<" events written"<<endl;
68 
69  return 0;
70 }
71 
72 //-----------
73 // ParseCommandLineArguments
74 //-----------
75 void ParseCommandLineArguments(int narg, char* argv[])
76 {
77  INFILENAMES.clear();
78 
79  for(int i=1; i<narg; i++){
80  char *ptr = argv[i];
81 
82  if(ptr[0] == '-'){
83  switch(ptr[1]){
84  case 'h': Usage(); break;
85  case 'o': OUTFILENAME=&ptr[2]; break;
86  case 'b': BUFFER_SIZE=atoi(&ptr[2]); break;
87  case 's': EVENTS_TO_SKIP=atoi(&ptr[2]); break;
88  case 'k': EVENTS_TO_KEEP=atoi(&ptr[2]); break;
89  case 'e': SPECIFIC_OFFSET_TO_KEEP=atoi(&ptr[2]); break;
90  case 'E': SPECIFIC_EVENT_TO_KEEP=atoi(&ptr[2]); EVENT_TO_KEEP_MODE=true;
91 // // WE DON'T SUPPORT THIS YET!!!!
92 // cout << "The -E option is not yet supported. Sorry! Contact davidl@jlab.org if you need this functionality." <<endl;
93 // exit(-2);
94  break;
95  }
96  }else{
97  INFILENAMES.push_back(argv[i]);
98  }
99  }
100 
101  if(INFILENAMES.size()==0){
102  cout<<endl<<"You must enter a filename!"<<endl<<endl;
103  Usage();
104  }
105 
107  EVENTS_TO_KEEP=1;
109  }
110 
112  EVENTS_TO_KEEP=1;
113  EVENTS_TO_SKIP=1000000000; // Large number of events to read in while looking for the specified event
114  }
115 
116  if(OUTFILENAME==NULL){
118  OUTFILENAME = new char[256];
120  }else if(SPECIFIC_EVENT_TO_KEEP>0){
121  OUTFILENAME = new char[256];
123 
124  }else{
125  OUTFILENAME = (char*)"culled.evio";
126  }
127  }
128 }
129 
130 
131 //-----------
132 // Usage
133 //-----------
134 void Usage(void)
135 {
136  cout<<endl<<"Usage:"<<endl;
137  cout<<" evio_cull_events [-oOutputfile] [-sNeventsToSkip] [-kNeventsToKeep] file1.evio file2.evio ..."<<endl;
138  cout<<endl;
139  cout<<"options:"<<endl;
140  cout<<" -oOutputfile Set output filename (def. merged_files.evio)"<<endl;
141  cout<<" -sNeventsToSkip Set number of events to skip (def. 0)"<<endl;
142  cout<<" -kNeventsToKeep Set number of events to keep (def. 1)"<<endl;
143  cout<<" -eSingleEvent Keep only the single, specified event (file pos.)"<<endl;
144  cout<<" -ESingleEvent Keep only the single, specified event (event number)"<<endl;
145  cout<<" -bBufferSize Size of EVIO input buffer in bytes (def. " << (BUFFER_SIZE>>20) << "MB)" << endl;
146  cout<<endl;
147  cout<<" This will copy a continguous set of events from the combined event streams"<<endl;
148  cout<<" into a seperate output file. The primary use for this would be to copy"<<endl;
149  cout<<" a single, problematic event into a seperate file for easier debugging."<<endl;
150  cout<<endl;
151  cout<<" If the -eNNN option is used then only a single event is extracted"<<endl;
152  cout<<" (the NNN-th event) and written to a file with the name evtNNN.hddm."<<endl;
153  cout<<" Note that the event is counted from the begining of the file, starting"<<endl;
154  cout<<" with \"1\". This does NOT look at the event number stored in the event itself."<<endl;
155  cout<<" "<<endl;
156  cout<<" If the -ENNN option is used then only a single event is extracted"<<endl;
157  cout<<" (the specified event number) and written to a file with the name EvtNNN.hddm."<<endl;
158  cout<<" "<<endl;
159  cout<<endl;
160 
161  exit(0);
162 }
163 
164 //-----------------------------------------------------------------
165 // ctrlCHandle
166 //-----------------------------------------------------------------
167 void ctrlCHandle(int x)
168 {
169  QUIT++;
170  cerr<<endl<<"SIGINT received ("<<QUIT<<")....."<<endl;
171  if(QUIT>=3){
172  cerr << "3 or more SIGINTs received. exiting..." << endl;
173  exit(-1);
174  }
175 }
176 
177 //-----------
178 // Process
179 //-----------
180 void Process(unsigned int &NEvents, unsigned int &NEvents_read)
181 {
182  NEvents = 0;
183  NEvents_read = 0;
184  time_t last_time = time(NULL);;
185 
186  // Output file
187  cout<<" output file: "<<OUTFILENAME<<endl;
188  evioFileChannel ochan(OUTFILENAME, "w", BUFFER_SIZE);
189  ochan.open();
190 
191  // Loop over input files
192  for(unsigned int i=0; i<INFILENAMES.size(); i++){
193  try{
194  cout << "Opening input file : \"" << INFILENAMES[i] << "\"" << endl;
195  evioFileChannel *ichan = new evioFileChannel(INFILENAMES[i], "r", BUFFER_SIZE);
196  ichan->open();
197  while( ichan->read() ){
198  NEvents_read++;
199 
200  evioDOMTree *dom = NULL;
201  bool write_event = false;
203 
204  // User specified a specific event by event number within file
205  dom = new evioDOMTree(ichan);
206  uint64_t block_size=0;
207  uint64_t eventnumber = FindEventNumber(dom, block_size);
208  uint64_t min_event = eventnumber;
209  uint64_t max_event = min_event + block_size - 1;
210  if( (SPECIFIC_EVENT_TO_KEEP >= min_event) && (SPECIFIC_EVENT_TO_KEEP <= max_event) ){
211  write_event = true;
212  if(min_event != max_event){
213  cout << endl;
214  cout << "WARNING: The CODA block size for this data is not \"1\"!" << endl;
215  cout << "The entire block of " << block_size << " events is being written" << endl;
216  cout << "that contains the requested event." << endl;
217  cout << "Events " << min_event << " - " << max_event << " will be written." << endl;
218  }
219  }
220 
221  } else if(NEvents_read > EVENTS_TO_SKIP){
222 
223  // User specified event range or specific event by offset
224  write_event = true;
225 
226  }
227 
228  if(write_event){
229 
230  if(!dom) dom = new evioDOMTree(ichan);
231  ochan.write(dom);
232  if(dom) delete dom;
233  NEvents++;
234  }
235 
236  if(NEvents >= EVENTS_TO_KEEP){
237  QUIT = true;
238  break;
239  }
240 
241  // print ticker
242  time_t t = time(NULL);
243  if((t-last_time) >= 2){
244  cout << " " << NEvents_read << " event read " << NEvents << " events written \r";
245  cout.flush();
246  last_time = t;
247  }
248  }
249  cout << endl;
250  ichan->close();
251  delete ichan;
252  }catch(evioException e){
253  cerr << e.what() << endl;
254  // QUIT=true;
255  break;
256  }
257 
258  if(QUIT) break;
259  }
260 
261  // Close output file
262  ochan.close();
263 
264 }
265 
266 //----------------
267 // FindEventNumber
268 //----------------
269 uint64_t FindEventNumber(evioDOMTree *evt, uint64_t &block_size)
270 {
271  evioDOMNodeListP bankList = evt->getNodeList(typeIs<uint64_t>());
272  evioDOMNodeList::iterator iter = bankList->begin();
273  for(; iter!=bankList->end(); iter++){
274 
275  // Get pointer to bank data
276  evioDOMNodeP bankPtr = *iter;
277  const vector<uint64_t> *vec = bankPtr->getVector<uint64_t>();
278  if(!vec) continue; // this should never actually happen
279  const uint32_t *iptr = (const uint32_t *)&(*vec)[0];
280 
281  // Check that parent bank is built trigger bank header
282  evioDOMNodeP trigger_bank = bankPtr->getParent();
283  if( trigger_bank == NULL ) continue;
284  if((trigger_bank->tag & 0xFF20) != 0xFF20) continue;
285 
286  // Check that grand-parent (Physics Event Bank) exists
287  evioDOMNodeP physics_event_bank = trigger_bank->getParent();
288  if( physics_event_bank == NULL ) continue;
289 
290  // Bomb-proof
291  if(vec->size() < 2) continue;
292 
293  // Copy number of events in block
294  block_size = (uint64_t)physics_event_bank->num;
295 
296  // Extract event number
297  uint64_t loevent_num = iptr[0];
298  uint64_t hievent_num = iptr[1];
299  uint64_t event_num = loevent_num + (hievent_num<<32);
300 
301  return event_num;
302  }
303 
304  return 0; // couldn't find the Trigger bank bank
305 }
306 
void Process(unsigned int &NEvents, unsigned int &NEvents_read)
unsigned int EVENTS_TO_KEEP
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
unsigned int SPECIFIC_EVENT_TO_KEEP
sprintf(text,"Post KinFit Cut")
int event_num
char * OUTFILENAME
unsigned int BUFFER_SIZE
bool EVENT_TO_KEEP_MODE
TEllipse * e
void ParseCommandLineArguments(int &narg, char *argv[])
Definition: hd_dump.cc:124
uint64_t FindEventNumber(evioDOMTree *evt, uint64_t &block_size)
int QUIT
static const size_t block_size
Definition: src/md5.cpp:54
unsigned int SPECIFIC_OFFSET_TO_KEEP
vector< char * > INFILENAMES
void ctrlCHandle(int x)
unsigned int EVENTS_TO_SKIP
void Usage(JApplication &app)
Definition: hd_ana.cc:33
int main(int argc, char *argv[])
Definition: gendoc.cc:6