JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwEventBuffer.cc
Go to the documentation of this file.
1/*!
2 * \file QwEventBuffer.cc
3 * \brief Event buffer management for reading and processing CODA data files
4 */
5
6#include "QwEventBuffer.h"
7
8#include "QwOptions.h"
9#include "QwEPICSEvent.h"
10#include "VQwSubsystem.h"
11#include "QwSubsystemArray.h"
12
13#include <TMath.h>
14
15#include <vector>
16#include <glob.h>
17
18#include <csignal>
21void sigint_handler(int sig)
22{
23 std::cout << "handling signal no. " << sig << " ";
24 std::cout << "(press ctrl-\\ to abort now)\n";
25 globalEXIT=1;
26}
27void sigusr_handler(int sig)
28{
29 std::cout << "handling signal no. " << sig << "\n";
30 std::cout << "Restarts the event loop in online mode." << std::endl;
31 onlineRestart = 1;
32}
33
34#include "THaCodaFile.h"
35#ifdef __CODA_ET
36#include "THaEtClient.h"
37#endif
38
39std::string QwEventBuffer::fDefaultDataDirectory = "/adaq1/data1/apar";
40std::string QwEventBuffer::fDefaultDataFileStem = "QwRun_";
42
43const Int_t QwEventBuffer::kRunNotSegmented = -20;
44const Int_t QwEventBuffer::kNoNextDataFile = -30;
46
47/// This is the ASCII character array 'NULL', and is used by the
48/// DAQ to indicate a known empty buffer.
49const UInt_t QwEventBuffer::kNullDataWord = 0x4e554c4c;
50
51
52/// Default constructor
54 : fRunListFile(nullptr),
55 fEventListFile(nullptr),
60 fEvStream(NULL),
61 fCurrentRun(-1),
63 fSingleFile(kFALSE),
64 decoder(NULL)
65{
66 // Set up the signal handler.
67 globalEXIT=0;
68 signal(SIGINT, sigint_handler);// ctrl+c
69 signal(SIGTERM, sigint_handler);// kill in shell // 15
70 // signal(SIGTSTP, sigint_handler);// ctrl+z // 20
72 signal(SIGUSR1, sigusr_handler);
73
74 fCleanParameter[0] = 0.0;
75 fCleanParameter[1] = 0.0;
76 fCleanParameter[2] = 0.0;
77}
78
79/**
80 * Defines configuration options for QwEventBuffer class using QwOptions
81 * functionality.
82 *
83 * @param options Options object
84 */
86{
87 // Define the execution options
88 options.AddDefaultOptions()
89 ("online", po::value<bool>()->default_bool_value(false),
90 "use online data stream");
91 options.AddDefaultOptions()
92 ("online.RunNumber", po::value<int>()->default_bool_value(0),
93 "Effective run number to be used by online system to find the parameter files");
94 options.AddDefaultOptions()
95 ("run,r", po::value<string>()->default_value("0:0"),
96 "run range in format #[:#]");
97 options.AddDefaultOptions()
98 ("data,d", po::value<string>()->default_value(fDefaultDataDirectory),
99 "data directory, also $QW_DATA");
100 options.AddDefaultOptions()
101 ("runlist", po::value<string>()->default_value(""),
102 "run list file name");
103 options.AddDefaultOptions()
104 ("event,e", po::value<string>()->default_value("0:"),
105 "event range in format #[:#]");
106 options.AddDefaultOptions()
107 ("segment,s", po::value<string>()->default_value("0:"),
108 "run segment range in format #[:#]");
109 options.AddDefaultOptions()
110 ("chainfiles", po::value<bool>()->default_bool_value(false),
111 "chain file segments together, do not analyze them separately");
112 options.AddDefaultOptions()
113 ("codafile-stem", po::value<string>()->default_value(fDefaultDataFileStem),
114 "stem of the input CODA filename");
115 options.AddDefaultOptions()
116 ("codafile-ext", po::value<string>()->default_value(fDefaultDataFileExtension),
117 "extension of the input CODA filename");
118 options.AddOptions()
119 ("directfile", po::value<string>(),
120 "Run over single event file");
121 // Special flag to allow sub-bank IDs less than 31
122 options.AddDefaultOptions()
123 ("allow-low-subbank-ids", po::value<bool>()->default_bool_value(false),
124 "allow the sub-bank ids to be 31 or less, when using this flag, all ROCs must be sub-banked");
125 // Options specific to the ET clients
126 options.AddOptions("ET system options")
127 ("ET.hostname", po::value<string>(),
128 "Name of the ET session's host machine --- Only used in online mode\nDefaults to the environment variable $HOSTNAME");
129 options.AddOptions("ET system options")
130 ("ET.session", po::value<string>(),
131 "ET session name --- Only used in online mode\nDefaults to the environment variable $SESSION");
132 options.AddOptions("ET system options")
133 ("ET.station", po::value<string>(),
134 "ET station name --- Only used in online mode");
135 options.AddOptions("ET system options")
136 ("ET.waitmode", po::value<int>()->default_value(0),
137 "ET system wait mode: 0 is wait-forever, 1 is timeout \"quickly\" --- Only used in online mode");
138 options.AddOptions("ET system options")
139 ("ET.exit-on-end", po::value<bool>()->default_value(false),
140 "Exit the event loop if the end event is found. JAPAN remains open and waits for the next run. --- Only used in online mode");
141 options.AddOptions("CodaVersion")
142 ("coda-version", po::value<int>()->default_value(3),
143 "Sets the Coda Version. Allowed values = {2,3}. \nThis is needed for writing and reading mock data. Mock data needs to be written and read with the same Coda Version.");
144}
145
147{
148 fOnline = options.GetValue<bool>("online");
149 if (fOnline){
150 fETWaitMode = options.GetValue<int>("ET.waitmode");
151 fExitOnEnd = options.GetValue<bool>("ET.exit-on-end");
152#ifndef __CODA_ET
153 QwError << "Online mode will not work without the CODA libraries!"
154 << QwLog::endl;
155 exit(EXIT_FAILURE);
156#else
157 if (options.HasValue("online.RunNumber")) {
158 fCurrentRun = options.GetValue<int>("online.RunNumber");
159 }
160 if (options.HasValue("ET.station")) {
161 fETStationName = options.GetValue<string>("ET.station");
162 } else {
163 fETStationName = "";
164 }
165 if (options.HasValue("ET.hostname")) {
166 fETHostname = options.GetValue<string>("ET.hostname");
167 } else {
168 fETHostname = getenv("HOSTNAME");
169 }
170 if (options.HasValue("ET.session")) {
171 fETSession = options.GetValue<string>("ET.session");
172 } else {
173 fETSession = getenv("SESSION");
174 }
175 if (fETHostname.Length() == 0 || fETSession.Length() == 0) {
176 TString tmp = "";
177 if (fETHostname == NULL || fETHostname.Length() == 0)
178 tmp += " \"HOSTNAME\"";
179 if (fETSession == NULL || fETSession.Length() == 0){
180 if (tmp.Length() > 0)
181 tmp += " and";
182 tmp += " ET \"SESSION\"";
183 }
184 QwError << "The" << tmp
185 << " variable(s) is(are) not defined in your environment.\n"
186 << " This is needed to run the online analysis."
187 << QwLog::endl;
188 exit(EXIT_FAILURE);
189 }
190#endif
191 }
192 if(options.HasValue("directfile")){
193 fSingleFile = kTRUE;
194 fDataFile = options.GetValue<string>("directfile");
195 } else {
196 fSingleFile = kFALSE;
197 }
198 fDataDirectory = options.GetValue<string>("data");
199 if (fDataDirectory.Length() == 0){
200 QwError << "ERROR: Can't get the data directory in the QwEventBuffer creator."
201 << QwLog::endl;
202 } else if (! fDataDirectory.EndsWith("/")) {
203 fDataDirectory.Append("/");
204 }
205
206 fRunRange = options.GetIntValuePair("run");
207 fEventRange = options.GetIntValuePair("event");
208 fSegmentRange = options.GetIntValuePair("segment");
209 fRunListFileName = options.GetValue<string>("runlist");
210 fChainDataFiles = options.GetValue<bool>("chainfiles");
211 fDataFileStem = options.GetValue<string>("codafile-stem");
212 fDataFileExtension = options.GetValue<string>("codafile-ext");
213 fDataVersion = options.GetValue<int>("coda-version");
214
215 if(fDataVersion == 2){
217 } else if(fDataVersion == 3) {
219 } else{
220 QwError << "Invalid Coda Version. Only versions 2 and 3 are supported. "
221 << "Please set using --coda-version 2(3)" << QwLog::endl;
222 exit(EXIT_FAILURE);
223 }
224
225 decoder->SetAllowLowSubbankIDs( options.GetValue<bool>("allow-low-subbank-ids") );
226
227 // Open run list file
228 /* runlist file format example:
229 [5253]
230 234
231 246
232 256
233 345:456
234 567:789
235 [5259]
236 [5260]
237 0:10000
238 [5261:5270]
239 9000:10000
240 - for run 5253 it will analyze three individual events, and two event ranges
241 - for run 5259 it will analyze the entire run (all segments)
242 - for run 5260 it will analyze the first 10000 events
243 - for runs 5261 through 5270 it will analyze the events 9000 through 10000)
244 */
245 if (fRunListFileName.size() > 0) {
246 fRunListFile = std::make_unique<QwParameterFile>(fRunListFileName);
247 fEventListFile = nullptr;
248 if (! GetNextRunRange()) {
249 QwWarning << "No run range found in run list file: " << fRunListFile->GetLine() << QwLog::endl;
250 }
251 } else {
252 fRunListFile = nullptr;
253 fEventListFile = nullptr;
254 }
255}
256
258{
259 UInt_t nevents = fNumPhysicsEvents - fStartingPhysicsEvent;
260 if (nevents==0) nevents=1;
262 << "Analysis of run " << GetRunNumber() << QwLog::endl
263 << fNumPhysicsEvents << " physics events were processed"<< QwLog::endl
264 << "CPU time used: " << fRunTimer.CpuTime() << " s "
265 << "(" << 1000.0 * fRunTimer.CpuTime() / nevents << " ms per event)" << QwLog::endl
266 << "Real time used: " << fRunTimer.RealTime() << " s "
267 << "(" << 1000.0 * fRunTimer.RealTime() / nevents << " ms per event)" << QwLog::endl
268 << QwLog::endl;
269}
270
271
272
273/// Read the next requested event range, return true if success
275 // If there is an event list, open the next section
276 if (fEventListFile && !fEventListFile->IsEOF()) {
277 std::string eventrange;
278 // Find next non-whitespace, non-comment, non-empty line, before EOF
279 do {
280 fEventListFile->ReadNextLine(eventrange);
281 fEventListFile->TrimWhitespace();
282 fEventListFile->TrimComment('#');
283 } while (fEventListFile->LineIsEmpty() && !fEventListFile->IsEOF());
284 // If EOF return false; no next event range
285 if (fEventListFile->IsEOF()) return kFALSE;
286 // Parse the event range
288 QwMessage << "Next event range is " << eventrange << QwLog::endl;
289 return kTRUE;
290 }
291 return kFALSE;
292}
293
294/// Read the next requested run range, return true if success
296 // If there is a run list, open the next section
297 std::string runrange;
298 if (fRunListFile && !fRunListFile->IsEOF() &&
299 (fEventListFile = fRunListFile->ReadNextSection(runrange))) {
300 // Parse the run range
302 QwMessage << "Next run range is " << runrange << QwLog::endl;
303 // If there is no event range for this run range, set to default of 0:MAXINT
304 if (! GetNextEventRange()) {
305 QwWarning << "No valid event range in run list file: "
306 << fEventListFile->GetLine() << ". "
307 << "Assuming the full event range." << QwLog::endl;
309 }
310 return kTRUE;
311 }
312 return kFALSE;
313}
314
315/// Get the next run in the active run range, proceed to next range if needed
317 // First run
318 if (fCurrentRun == -1) {
319 fCurrentRun = fRunRange.first;
320 return kTRUE;
321 // Run is in range
322 } else if (fCurrentRun < fRunRange.second) {
323 fCurrentRun++;
324 return kTRUE;
325 // Run is not in range, get new range
326 } else if (GetNextRunRange()) {
327 fCurrentRun = fRunRange.first;
328 return kTRUE;
329 }
330 return kFALSE;
331}
332
334{
335 TString runlabel = Form("%d",fCurrentRun);
337 runlabel += Form(".%03d",*fRunSegmentIterator);
338 }
339 return runlabel;
340}
341
343{
344 Int_t status = CODA_ERROR;
345 // Reset the physics event counter
347
348 if (fOnline) {
349 // Online stream
351 } else {
352 // Offline data file
353 if (fRunIsSegmented)
354 // Segmented
355 status = OpenNextSegment();
356 else
357 // Not segmented
358 status = OpenDataFile(fCurrentRun);
359 }
360 return status;
361}
362
364{
365 Int_t status = CODA_ERROR;
366 if (globalEXIT==1) {
367 // We want to exit, so don't open the next stream.
368 status = CODA_ERROR;
369 } else if (fOnline) {
370 /* Modify the call below for your ET system, if needed.
371 OpenETStream( ET host name , $SESSION , mode)
372 mode=0: wait forever
373 mode=1: timeout quickly
374 */
375 QwMessage << "Try to open the ET station with HOSTNAME=="
376 << fETHostname
377 << ", SESSION==" << fETSession << "."
378 << QwLog::endl;
380
381 } else {
382 // Try to open the next data file for the current run,
383 // but only if we haven't hit the event limit.
384 if (fCurrentRun != -1 && !fChainDataFiles
385 && decoder->GetEvtNumber() <= fEventRange.second) {
386 status = OpenNextSegment();
387 }
388 while (status != CODA_OK && GetNextRunNumber()) {
389 status = OpenDataFile(fCurrentRun);
390 if (status == CODA_ERROR){
391 // The data file can't be opened.
392 // Get ready to process the next run.
393 QwError << "ERROR: Unable to find data files for run "
394 << fCurrentRun << ". Moving to the next run.\n"
395 << QwLog::endl;
396 }
397 }
398
399 }
400 // Grab the starting event counter
402 // Start the timers.
403 fRunTimer.Reset();
404 fRunTimer.Start();
405 fStopwatch.Start();
406 return status;
407}
408
410{
411 // Stop the timers.
412 fRunTimer.Stop();
413 fStopwatch.Stop();
414 QwWarning << "Starting CloseStream."
415 << QwLog::endl;
416 Int_t status = kFileHandleNotConfigured;
419 // The run is segmented and we are not chaining the
420 // segments together in the event loop, so close
421 // the current segment.
422 status = CloseThisSegment();
423 } else if (fEvStreamMode==fEvStreamFile) {
424 status = CloseDataFile();
425 } else if (fEvStreamMode==fEvStreamFile){
426 status = CloseETStream();
427 }
428 return status;
429}
430
431
432
434{
435 // This will return for read errors,
436 // non-physics events, and for physics
437 // events that are within the event range.
438 Int_t status = CODA_OK;
439 do {
440 status = GetEvent();
441 if (globalEXIT == 1) {
442 // QUESTION: Should we continue to loop once we've
443 // reached the maximum event, to allow access to
444 // non-physics events?
445 // For now, mock up EOF if we've reached the maximum event.
446 status = EOF;
447 }
448 if (decoder->GetEvtNumber() > fEventRange.second) {
449 do {
450 if (GetNextEventRange()) status = CODA_OK;
451 else status = EOF;
452 } while (decoder->GetEvtNumber() < fEventRange.first);
453 }
454 // While we're in a run segment which was not requested (which
455 // should happen only when reading the zeroth segment for startup
456 // information), pretend that there's an event cut causing us to
457 // ignore events. Read configuration events only from the first
458 // part of the file.
460 fEventRange.first = decoder->GetEvtNumber() + 1;
461 if (decoder->GetEvtNumber() > 1000) status = EOF;
462 }
463 if (fOnline && fExitOnEnd && decoder->GetEndTime()>0){
464 // fExitOnEnd exits the event loop only and does not exit JAPAN.
465 // The root file gets processed and JAPAN immediately waits for the next run.
466 // We considered adding a exit-JAPAN-on-end flag that quits JAPAN but decided
467 // we didn't have a use case for it. If quitting JAPAN is desired, just set:
468 // globalEXIT = 1
469 // -- mrc (01/21/25)
470 QwMessage << "Caught End Event (end time=="<< decoder->GetEndTime()
471 << "). Exit event loop." << QwLog::endl;
472 status = EOF;
473 }
474 if (fOnline && onlineRestart){
476 status = EOF;
477 }
478 } while (status == CODA_OK &&
479 IsPhysicsEvent() &&
480 (decoder->GetEvtNumber() < fEventRange.first
481 || decoder->GetEvtNumber() > fEventRange.second)
482 );
483 if (status == CODA_OK && IsPhysicsEvent()) fNumPhysicsEvents++;
484
485 // Progress meter (this should probably produce less output in production)
486 int nevents = 10000;
487 if (IsPhysicsEvent() && decoder->GetEvtNumber() > 0 && decoder->GetEvtNumber() % nevents == 0) {
488 QwMessage << "Processing event " << decoder->GetEvtNumber() << " ";
489 fStopwatch.Stop();
490 double efficiency = 100.0 * fStopwatch.CpuTime() / fStopwatch.RealTime();
491 QwMessage << "(" << fStopwatch.CpuTime()*1e3/nevents << " ms per event with ";
492 QwMessage << efficiency << "% efficiency)";
493 fStopwatch.Reset();
494 fStopwatch.Start();
496 } else if (decoder->GetEvtNumber() > 0 && decoder->GetEvtNumber() % 100 == 0) {
497 QwVerbose << "Processing event " << decoder->GetEvtNumber() << QwLog::endl;
498 }
499
500 return status;
501}
502
503
505{
506 Int_t status = kFileHandleNotConfigured;
507 ResetFlags();
509 status = GetFileEvent();
510 } else if (fEvStreamMode==fEvStreamET){
511 status = GetEtEvent();
512 }
513 if (status == CODA_OK){
514 // Coda Data was loaded correctly
515 UInt_t* evBuffer = (UInt_t*)fEvStream->getEvBuffer();
516 if(fDataVersionVerify == 0){ // Default = 0 => Undetermined
517 VerifyCodaVersion(evBuffer);
518 }
519 decoder->DecodeEventIDBank(evBuffer);
520 }
521 return status;
522}
523
524// Tries to figure out what Coda Version the Data is
525// fDataVersionVerify =
526// 2 -- Coda Version 2
527// 3 -- Coda Version 3
528// 0 -- Default (Unknown, Could be a EPICs Event or a ROCConfiguration)
529void QwEventBuffer::VerifyCodaVersion( const UInt_t *buffer )
530{
531 if(buffer[0] == 0) return;
532 UInt_t header = buffer[1];
533 int top = (header & 0xff000000) >> 24;
534 int bot = (header & 0xff );
535 fDataVersionVerify = 0; // Default
536 if( (top == 0xff) && (bot != 0xcc) ){
537 fDataVersionVerify = 3; // Coda 3
538 } else if( (top != 0xff) && (bot == 0xcc) ){
539 fDataVersionVerify = 2; // Coda 2
540 }
541 // Validate
543 QwError << "QwEventBuffer::GetEvent: Coda Version is not recognized" << QwLog::endl;
544 QwError << "fDataVersion == " << fDataVersion
545 << ", but it looks like the data is from Coda Version "
547 << "\nTry running with --coda-version " << fDataVersionVerify
548 << "\nExiting ... " << QwLog::endl;
549 globalEXIT = 1;
550 }
551 return;
552}
553
555 Int_t status = CODA_OK;
556 // Try to get a new event. If the EOF occurs,
557 // and the run is segmented, try to open the
558 // next segment and read a new event; repeat
559 // if needed.
560 do {
561 status = fEvStream->codaRead();
562 if (fChainDataFiles && status == EOF){
564 // Crash out of the loop if we can't open the
565 // next segment!
566 if (OpenNextSegment()!=CODA_OK) break;
567 }
568 } while (fChainDataFiles && status == EOF);
569 return status;
570}
571
573 Int_t status = CODA_OK;
574 // Do we want to have any loop here to wait for a bad
575 // read to be cleared?
576 status = fEvStream->codaRead();
577 if (status != CODA_OK) {
578 globalEXIT = 1;
579 }
580 return status;
581}
582
583
585{
586 Int_t status = kFileHandleNotConfigured;
587 ResetFlags();
589 status = WriteFileEvent(buffer);
590 } else if (fEvStreamMode==fEvStreamET) {
591 QwMessage << "No support for writing to ET streams" << QwLog::endl;
592 status = CODA_ERROR;
593 }
594 return status;
595}
596
598{
599 Int_t status = CODA_OK;
600 // fEvStream is of inherited type THaCodaData,
601 // but codaWrite is only defined for THaCodaFile.
602 status = ((THaCodaFile*)fEvStream)->codaWrite((UInt_t*) buffer);
603 return status;
604}
605
606
608{
609 // Encode the data in the elements of the subsystem array
610 std::vector<UInt_t> buffer;
611 std::vector<ROCID_t> ROCList;
612 subsystems.EncodeEventData(buffer);
613 subsystems.GetROCIDList(ROCList);
614 // Add CODA event header
615 std::vector<UInt_t> header = decoder->EncodePHYSEventHeader(ROCList);
616
617 // Copy the encoded event buffer into an array of integers,
618 // as expected by the CODA routines.
619 // Size of the event buffer in long words
620 int* codabuffer = new int[header.size() + buffer.size() + 1];
621 // First entry contains the buffer size
622 int k = 0;
623 codabuffer[k++] = header.size() + buffer.size();
624 for (size_t i = 0; i < header.size(); i++)
625 codabuffer[k++] = header.at(i);
626 for (size_t i = 0; i < buffer.size(); i++)
627 codabuffer[k++] = buffer.at(i);
628
629 // Now write the buffer to the stream
630 Int_t status = WriteEvent(codabuffer);
631 // delete the buffer
632 delete[] codabuffer;
633 // and report success or fail
634 return status;
635}
636
637
639{
640 decoder->ResetControlParameters();
641}
643{
644 decoder->ReportRunSummary();
645}
646
648{
649 return decoder->GetStartSQLTime();
650}
651
653{
654 return decoder->GetEndSQLTime();
655}
656
658{
659 return decoder->GetStartUnixTime();
660}
661
663{
664 return decoder->GetEndUnixTime();
665}
666
667Int_t QwEventBuffer::EncodePrestartEvent(int runnumber, int runtype)
668{
669 int buffer[5];
670 int localtime = (int)time(0);
671 decoder->EncodePrestartEventHeader(buffer, runnumber, runtype, localtime);
672 return WriteEvent(buffer);
673}
675{
676 int buffer[5];
677 int localtime = (int)time(0);
678 int eventcount = 0;
679 decoder->EncodeGoEventHeader(buffer, eventcount, localtime);
680 return WriteEvent(buffer);
681}
683{
684 int buffer[5];
685 int localtime = (int)time(0);
686 int eventcount = 0;
687 decoder->EncodePauseEventHeader(buffer, eventcount, localtime);
688 return WriteEvent(buffer);
689}
691{
692 int buffer[5];
693 int localtime = (int)time(0);
694 int eventcount = 0;
695 decoder->EncodeEndEventHeader(buffer, eventcount, localtime);
696 return WriteEvent(buffer);
697}
698
699
702
704{
705 /// Passes the data for the configuration events into each subsystem
706 /// object. Each object is responsible for recognizing the configuration
707 /// data which it ought to decode.
708 /// NOTE TO DAQ PROGRAMMERS:
709 /// The configuration event for a ROC must have the same
710 /// subbank structure as the physics events for that ROC.
711 Bool_t okay = kTRUE;
712 UInt_t rocnum = decoder->GetEvtType() - 0x90;
713 QwMessage << "QwEventBuffer::FillSubsystemConfigurationData: "
714 << "Found configuration event for ROC"
715 << rocnum
716 << QwLog::endl;
717 decoder->PrintDecoderInfo(QwMessage);
718 // Loop through the data buffer in this event.
719 UInt_t *localbuff = (UInt_t*)(fEvStream->getEvBuffer());
720 decoder->DecodeEventIDBank(localbuff);
721 while ((okay = decoder->DecodeSubbankHeader(&localbuff[decoder->GetWordsSoFar()]))){
722 // If this bank has further subbanks, restart the loop.
723 if (decoder->GetSubbankType() == 0x10) {
724 QwMessage << "This bank has further subbanks, restart the loop" << QwLog::endl;
725 continue;
726 }
727 // If this bank only contains the word 'NULL' then skip
728 // this bank.
729 if (decoder->GetFragLength()==1 && localbuff[decoder->GetWordsSoFar()]==kNullDataWord){
730 decoder->AddWordsSoFarAndFragLength();
731 QwMessage << "Skip this bank" << QwLog::endl;
732 continue;
733 }
734
735 // Subsystems may be configured to accept data in formats
736 // other than 32 bit integer (banktype==1), but the
737 // bank type is not provided. Subsystems must be able
738 // to process their data knowing only the ROC and bank tags.
739 //
740 // After trying the data in each subsystem, bump the
741 // fWordsSoFar to move to the next bank.
742
743 subsystems.ProcessConfigurationBuffer(rocnum, decoder->GetSubbankTag(),
744 &localbuff[decoder->GetWordsSoFar()],
745 decoder->GetFragLength());
746 decoder->AddWordsSoFarAndFragLength();
747 QwDebug << "QwEventBuffer::FillSubsystemConfigurationData: "
748 << "Ending loop: fWordsSoFar=="<<decoder->GetWordsSoFar()
749 <<QwLog::endl;
750 }
751
752 return okay;
753}
754
756{
757 // Initialize local flag
758 Bool_t okay = kTRUE;
759
760 // Reload the data buffer and decode the header again, this allows
761 // multiple calls to this function for different subsystem arrays.
762 UInt_t *localbuff = (UInt_t*)(fEvStream->getEvBuffer());
763
764 decoder->DecodeEventIDBank(localbuff);
765
766 // Clear the old event information from the subsystems.
767 subsystems.ClearEventData();
768
769 // Pass CODA run, segment, event number and type to the subsystem array.
770 subsystems.SetCodaRunNumber(fCurrentRun);
772 subsystems.SetCodaEventNumber(decoder->GetEvtNumber());
773 subsystems.SetCodaEventType(decoder->GetEvtType());
774
775 // If this event type is masked for the subsystem array, return right away
776 if (((0x1 << (decoder->GetEvtType() - 1)) & subsystems.GetEventTypeMask()) == 0) {
777 return kTRUE;
778 }
779
780 UInt_t offset;
781
782 // Loop through the data buffer in this event.
783 while ((okay = decoder->DecodeSubbankHeader(&localbuff[decoder->GetWordsSoFar()]))){
784
785 // If this bank has further subbanks, restart the loop.
786 if (decoder->GetSubbankType() == 0x10) continue;
787
788 // If this bank only contains the word 'NULL' then skip
789 // this bank.
790 if (decoder->GetFragLength() == 1 && localbuff[decoder->GetWordsSoFar()]==kNullDataWord) {
791 decoder->AddWordsSoFarAndFragLength();
792 continue;
793 }
794
795 // if (GetSubbankType() == 0x85) {
796 // std::cout << "ProcessEventBuffer: , SubbankTag= "<< GetSubbankTag()<<" FragLength="<<GetFragLength() <<std::endl;
797 // }
798
799// QwDebug << "QwEventBuffer::FillSubsystemData: "
800// << "Beginning loop: fWordsSoFar=="<<GetWordsSoFar()
801// <<QwLog::endl;
802
803 // Loop through the subsystems and try to store the data
804 // from this bank in each subsystem.
805 //
806 // Subsystems may be configured to accept data in formats
807 // other than 32 bit integer (banktype==1), but the
808 // bank type is not provided. Subsystems must be able
809 // to process their data knowing only the ROC and bank tags.
810 //
811 // After trying the data in each subsystem, bump the
812 // fWordsSoFar to move to the next bank.
813
814 // TODO:
815 // What is special about this subbank?
816 if( decoder->GetROC() == 0 && decoder->GetSubbankTag()==0x6101) {
817 //std::cout << "ProcessEventBuffer: ROC="<<GetROC()<<", SubbankTag="<< GetSubbankTag()<<", FragLength="<<GetFragLength() <<std::endl;
818 fCleanParameter[0]=localbuff[decoder->GetWordsSoFar()+decoder->GetFragLength()-4];//clean data
819 fCleanParameter[1]=localbuff[decoder->GetWordsSoFar()+decoder->GetFragLength()-3];//scan data 1
820 fCleanParameter[2]=localbuff[decoder->GetWordsSoFar()+decoder->GetFragLength()-2];//scan data 2
821 //std::cout << "ProcessEventBuffer: ROC="<<GetROC()<<", SubbankTag="<< GetSubbankTag()
822 // <<", FragLength="<<GetFragLength() << " " <<fCleanParameter[0]<< " " <<fCleanParameter[1]<< " " <<fCleanParameter[2]<<std::endl;
823
824 }
825
827
828 std::size_t nmarkers = CheckForMarkerWords(subsystems);
829 if (nmarkers>0) {
830 // There are markerwords for this ROC/Bank
831 for (size_t i=0; i<nmarkers; i++){
832 offset = FindMarkerWord(i,&localbuff[decoder->GetWordsSoFar()],decoder->GetFragLength());
833 BankID_t tmpbank = GetMarkerWord(i);
834 tmpbank = ((tmpbank)<<32) + decoder->GetSubbankTag();
835 offset++; // Skip the marker word
836 subsystems.ProcessEvBuffer(decoder->GetEvtType(), decoder->GetROC(), tmpbank,
837 &localbuff[decoder->GetWordsSoFar()+offset],
838 decoder->GetFragLength()-offset);
839 }
840 } else {
841 QwDebug << "QwEventBuffer::FillSubsystemData: "
842 << "fROC=="<<decoder->GetROC() << ", GetSubbankTag()==" << decoder->GetSubbankTag()
843 << QwLog::endl;
844 subsystems.ProcessEvBuffer(decoder->GetEvtType(), decoder->GetROC(), decoder->GetSubbankTag(),
845 &localbuff[decoder->GetWordsSoFar()],
846 decoder->GetFragLength());
847 }
848 decoder->AddWordsSoFarAndFragLength();
849// QwDebug << "QwEventBuffer::FillSubsystemData: "
850// << "Ending loop: fWordsSoFar=="<<GetWordsSoFar()
851// <<QwLog::endl;
852 }
853 return okay;
854}
855
856
857// added all this method for QwEPICSEvent class
859{
860 // QwVerbose << "QwEventBuffer::FillEPICSData: "
861// << Form("Length: %d; Tag: 0x%x; Bank ID num: 0x%x; ",
862// fEvtLength, fEvtTag, fIDBankNum)
863// << Form("Evt type: 0x%x; Evt number %d; Evt Class 0x%.8x; ",
864// fEvtType(), fEvtNumber, fEvtClass)
865// << Form("Status Summary: 0x%.8x; Words so far %d",
866// fStatSum, fWordsSoFar)
867// << QwLog::endl;
868
869
870 ///
871 Bool_t okay = kTRUE;
872 if (! IsEPICSEvent()){
873 okay = kFALSE;
874 return okay;
875 }
876 QwVerbose << "QwEventBuffer::FillEPICSData: "
877 << QwLog::endl;
878 // Loop through the data buffer in this event.
879 UInt_t *localbuff = (UInt_t*)(fEvStream->getEvBuffer());
880 if (decoder->GetBankDataType()==0x10){
881 while ((okay = decoder->DecodeSubbankHeader(&localbuff[decoder->GetWordsSoFar()]))){
882 // If this bank has further subbanks, restart the loop.
883 if (decoder->GetSubbankType() == 0x10) continue;
884 // If this bank only contains the word 'NULL' then skip
885 // this bank.
886 if (decoder->GetFragLength()==1 && localbuff[decoder->GetWordsSoFar()]==kNullDataWord){
887 decoder->AddWordsSoFarAndFragLength();
888 continue;
889 }
890
891 if (decoder->GetSubbankType() == 0x3){
892 // This is an ASCII string bank. Try to decode it and
893 // pass it to the EPICS class.
894 char* tmpchar = (Char_t*)&localbuff[decoder->GetWordsSoFar()];
895
896 epics.ExtractEPICSValues(string(tmpchar), GetEventNumber());
897 QwVerbose << "test for GetEventNumber =" << GetEventNumber() << QwLog::endl;// always zero, wrong.
898
899 }
900
901
902 decoder->AddWordsSoFarAndFragLength();
903
904// QwDebug << "QwEventBuffer::FillEPICSData: "
905// << "Ending loop: fWordsSoFar=="<<GetWordsSoFar()
906// <<QwLog::endl;
907// QwMessage<<"\nQwEventBuffer::FillEPICSData: fWordsSoFar = "<<GetWordsSoFar()<<QwLog::endl;
908
909
910 }
911 } else {
912 // Single bank in the event, use event headers.
913 if (decoder->GetBankDataType() == 0x3){
914 // This is an ASCII string bank. Try to decode it and
915 // pass it to the EPICS class.
916 Char_t* tmpchar = (Char_t*)&localbuff[decoder->GetWordsSoFar()];
917
918 QwError << tmpchar << QwLog::endl;
919
920 epics.ExtractEPICSValues(string(tmpchar), GetEventNumber());
921
922 }
923
924 }
925
926 //std::cout<<"\nEpics data coming!! "<<GetWordsSoFar()<<std::endl;
927 QwVerbose << "QwEventBuffer::FillEPICSData: End of routine"
928 << QwLog::endl;
929 return okay;
930}
931
932const TString& QwEventBuffer::DataFile(const UInt_t run, const Short_t seg = -1)
933{
934 if(!fSingleFile){
935 TString basename = fDataFileStem + Form("%u.",run) + fDataFileExtension;
936 if(seg == -1){
937 fDataFile = fDataDirectory + basename;
938 } else {
939 fDataFile = fDataDirectory + basename + Form(".%d",seg);
940 }
941 }
942 return fDataFile;
943}
944
945
947{
948 glob_t globbuf;
949
950 TString searchpath;
951 TString scanvalue;
952 Int_t local_segment;
953
954 std::vector<Int_t> tmp_segments;
955 std::vector<Int_t> local_index;
956
957 /* Clear and set up the fRunSegments vector. */
958 tmp_segments.clear();
959 fRunSegments.clear();
960 fRunSegments.resize(0);
961 fRunIsSegmented = kFALSE;
962
963 searchpath = fDataFile;
964 glob(searchpath.Data(), GLOB_ERR, NULL, &globbuf);
965
966 if(fSingleFile){
967
968 fRunIsSegmented = kFALSE;
969
970 } else if (globbuf.gl_pathc == 1){
971 /* The base file name exists. *
972 * Do not look for file segments. */
973 fRunIsSegmented = kFALSE;
974
975 } else {
976 /* The base file name does not exist. *
977 * Look for file segments. */
978 QwWarning << "File " << fDataFile << " does not exist!\n"
979 << " Trying to find run segments for run "
980 << fCurrentRun << "... ";
981
982 searchpath.Append(".[0-9]*");
983 glob(searchpath.Data(), GLOB_ERR, NULL, &globbuf);
984
985 if (globbuf.gl_pathc == 0){
986 /* There are no file segments and no base file *
987 * Produce and error message and exit. */
988 QwError << "\n There are no file segments either!!" << QwLog::endl;
989
990 // This could mean a single gzipped file!
991 fRunIsSegmented = kFALSE;
992
993 } else {
994 /* There are file segments. *
995 * Determine the segment numbers and fill fRunSegments *
996 * to indicate the existing file segments. */
997
998 QwMessage << "OK" << QwLog::endl;
999 scanvalue = fDataFile + ".%d";
1000
1001 /* Get the list of segment numbers in file listing *
1002 * order. */
1003 for (size_t iloop=0;iloop<globbuf.gl_pathc;++iloop){
1004 /* Extract the segment numbers from the file name. */
1005 sscanf(globbuf.gl_pathv[iloop], scanvalue.Data(), &local_segment);
1006 tmp_segments.push_back(local_segment);
1007 }
1008 local_index.resize(tmp_segments.size(),0);
1009 /* Get the list of segments sorted numerically in *
1010 * increasing order. */
1011 TMath::Sort(static_cast<int>(tmp_segments.size()),&(tmp_segments[0]),&(local_index[0]),
1012 kFALSE);
1013 /* Put the segments into numerical order in fRunSegments. Add *
1014 * only those segments requested (though always add segment 0). */
1015 QwMessage << " Found the segment(s): ";
1016 size_t printed = 0;
1017 for (size_t iloop=0; iloop<tmp_segments.size(); ++iloop){
1018 local_segment = tmp_segments[local_index[iloop]];
1019 if (printed++) QwMessage << ", ";
1020 QwMessage << local_segment ;
1021 if (local_segment == 0 ||
1022 ( fSegmentRange.first <= local_segment &&
1023 local_segment <= fSegmentRange.second ) ) {
1024 fRunSegments.push_back(local_segment);
1025 } else {
1026 QwMessage << " (skipped)" ;
1027 }
1028 }
1029 QwMessage << "." << QwLog::endl;
1031
1032 fRunIsSegmented = kTRUE;
1033
1034 /* If the first requested segment hasn't been found,
1035 forget everything. */
1036 if ( local_segment < fSegmentRange.first ) {
1037 QwError << "First requested run segment "
1038 << fSegmentRange.first << " not found.\n";
1039 fRunSegments.pop_back();
1041 fRunIsSegmented = kTRUE; // well, it is true.
1042 }
1043 }
1044 }
1045 globfree(&globbuf);
1046 return fRunIsSegmented;
1047}
1048
1049//------------------------------------------------------------
1050
1052{
1053 Int_t status = kFileHandleNotConfigured;
1054 Int_t last_runsegment;
1055 if (fRunIsSegmented){
1056 last_runsegment = *fRunSegmentIterator;
1058 if (fRunSegmentIterator <= fRunSegments.end()){
1059 QwMessage << "Closing run segment " << last_runsegment <<"."
1060 << QwLog::endl;
1061 status = CloseDataFile();
1062 }
1063 } else {
1064 // Don't try to close a nonsegmented file; we will explicitly
1065 // use CloseDataFile() later.
1066 }
1067 return status;
1068}
1069
1070//------------------------------------------------------------
1071
1073{
1074 Int_t status;
1075 if (! fRunIsSegmented){
1076 /* We are processing a non-segmented run. *
1077 * We should not have entered this routine, but *
1078 * since we are here, don't do anything. */
1079 status = kRunNotSegmented;
1080
1081 } else if (fRunSegments.size()==0){
1082 /* There are actually no file segments located. *
1083 * Return "kNoNextDataFile", but don't print an *
1084 * error message. */
1085 status = kNoNextDataFile;
1086
1087 } else if (fRunSegmentIterator >= fRunSegments.begin() &&
1089 QwMessage << "Trying to open run segment " << *fRunSegmentIterator << QwLog::endl;
1091
1092 } else if (fRunSegmentIterator == fRunSegments.end() ) {
1093 /* We have reached the last run segment. */
1094 QwMessage << "There are no run segments remaining." << QwLog::endl;
1095 status = kNoNextDataFile;
1096
1097 } else {
1098 QwError << "QwEventBuffer::OpenNextSegment(): Unrecognized error" << QwLog::endl;
1099 status = CODA_ERROR;
1100 }
1101 return status;
1102}
1103
1104
1105//------------------------------------------------------------
1106//call this routine if we've selected the run segment by hand
1107Int_t QwEventBuffer::OpenDataFile(UInt_t current_run, Short_t seg)
1108{
1109 fCurrentRun = current_run;
1110
1111 fRunSegments.clear();
1112 fRunIsSegmented = kTRUE;
1113
1114 fRunSegments.push_back(seg);
1116 return OpenNextSegment();
1117}
1118
1119//------------------------------------------------------------
1120//call this routine if the run is not segmented
1121Int_t QwEventBuffer::OpenDataFile(UInt_t current_run, const TString rw)
1122{
1123 Int_t status;
1124 fCurrentRun = current_run;
1126 if (DataFileIsSegmented()){
1127 status = OpenNextSegment();
1128 } else {
1129 status = OpenDataFile(DataFile(fCurrentRun),rw);
1130 }
1131 return status;
1132}
1133
1134
1135
1136//------------------------------------------------------------
1137Int_t QwEventBuffer::OpenDataFile(const TString filename, const TString rw)
1138{
1140 QwDebug << "QwEventBuffer::OpenDataFile: File handle doesn't exist.\n"
1141 << " Try to open a new file handle!"
1142 << QwLog::endl;
1143 fEvStream = new THaCodaFile();
1145 } else if (fEvStreamMode!=fEvStreamFile){
1146 QwError << "QwEventBuffer::OpenDataFile: The stream is not configured as an input\n"
1147 << " file stream! Can't deal with this!\n"
1148 << QwLog::endl;
1149 exit(1);
1150 }
1151 fDataFile = filename;
1152
1153 if (rw.Contains("w",TString::kIgnoreCase)) {
1154 // If we open a file for write access, let's suppose
1155 // we've given the path we want to use.
1156 QwMessage << "Opening data file: " << fDataFile << QwLog::endl;
1157 } else {
1158 // Let's try to find the data file for read access.
1159 glob_t globbuf;
1160 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1161 if (globbuf.gl_pathc == 0){
1162 // Can't find the file; try in the "fDataDirectory".
1163 fDataFile = fDataDirectory + filename;
1164 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1165 }
1166 if (globbuf.gl_pathc == 0){
1167 // Can't find the file; try gzipped.
1168 fDataFile = filename + ".gz";
1169 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1170 }
1171 if (globbuf.gl_pathc == 0){
1172 // Can't find the file; try gzipped in the "fDataDirectory".
1173 fDataFile = fDataDirectory + filename + ".gz";
1174 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1175 }
1176 if (globbuf.gl_pathc == 1){
1177 QwMessage << "Opening data file: " << fDataFile << QwLog::endl;
1178 } else {
1179 fDataFile = filename;
1180 QwError << "Unable to find "
1181 << filename.Data() << " or "
1182 << (fDataDirectory + filename).Data() << QwLog::endl;
1183 }
1184 globfree(&globbuf);
1185 }
1186 return fEvStream->codaOpen(fDataFile, rw);
1187}
1188
1189
1190//------------------------------------------------------------
1192{
1193 Int_t status = kFileHandleNotConfigured;
1195 status = fEvStream->codaClose();
1196 }
1197 return status;
1198}
1199
1200//------------------------------------------------------------
1201Int_t QwEventBuffer::OpenETStream(TString computer, TString session, int mode,
1202 const TString stationname)
1203{
1204 Int_t status = CODA_OK;
1206#ifdef __CODA_ET
1207 if (stationname != ""){
1208 fEvStream = new THaEtClient(computer, session, mode, stationname.Data());
1209 } else {
1210 fEvStream = new THaEtClient(computer, session, mode);
1211 }
1213#endif
1214 }
1215 return status;
1216}
1217
1218//------------------------------------------------------------
1220{
1221 Int_t status = kFileHandleNotConfigured;
1223 status = fEvStream->codaClose();
1224 }
1225 return status;
1226}
1227
1228//------------------------------------------------------------
1230{
1231 QwDebug << "QwEventBuffer::GetMarkerWordList: start function" <<QwLog::endl;
1232 fThisRocBankLabel = decoder->GetROC();
1234 fThisRocBankLabel += decoder->GetSubbankTag();
1235 if (fMarkerList.count(fThisRocBankLabel)==0){
1236 std::vector<UInt_t> tmpvec;
1237 subsystems.GetMarkerWordList(decoder->GetROC(), decoder->GetSubbankTag(), tmpvec);
1238 fMarkerList.emplace(fThisRocBankLabel, tmpvec);
1239 fOffsetList.emplace(fThisRocBankLabel, std::vector<UInt_t>(tmpvec.size(),0));
1240 }
1241 QwDebug << "QwEventBuffer::GetMarkerWordList: fMarkerList.count(fThisRocBankLabel)=="
1243 << " fMarkerList.at(fThisRocBankLabel).size()=="
1244 << fMarkerList.at(fThisRocBankLabel).size()
1245 << QwLog::endl;
1246 return fMarkerList.at(fThisRocBankLabel).size();
1247}
1248
1249UInt_t QwEventBuffer::GetMarkerWord(UInt_t markerID){
1250 return fMarkerList.at(fThisRocBankLabel).at(markerID);
1251};
1252
1253
1254UInt_t QwEventBuffer::FindMarkerWord(UInt_t markerindex, UInt_t* buffer, UInt_t num_words){
1255 UInt_t markerpos = fOffsetList.at(fThisRocBankLabel).at(markerindex);
1256 UInt_t markerval = fMarkerList.at(fThisRocBankLabel).at(markerindex);
1257 if (markerpos < num_words && buffer[markerpos] == markerval){
1258 // The marker word is where it was last time
1259 return markerpos;
1260 } else {
1261 for (size_t i=0; i<num_words; i++){
1262 if (buffer[i] == markerval){
1263 fOffsetList.at(fThisRocBankLabel).at(markerindex) = i;
1264 markerpos = i;
1265 break;
1266 }
1267 }
1268 }
1269 return markerpos;
1270}
Definition of the pure virtual base class of all subsystems.
An options class which parses command line, config file and environment.
#define QwVerbose
Predefined log drain for verbose messages.
Definition QwLog.h:54
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
Array container for managing multiple subsystems.
EPICS data event handling and storage.
Event buffer management for reading and processing CODA data.
ULong64_t BankID_t
Definition QwTypes.h:21
void sigint_handler(int sig)
Bool_t onlineRestart
void sigusr_handler(int sig)
Bool_t globalEXIT
CODA version 2 event decoder implementation.
CODA version 3 event decoder implementation.
EPICS slow controls data management.
void ExtractEPICSValues(const string &data, int event)
TString GetRunLabel() const
Returns a string like <run#> or <run#>.<file#>
Int_t EncodeSubsystemData(QwSubsystemArray &subsystems)
TString fETHostname
static const Int_t kRunNotSegmented
Int_t EncodeGoEvent()
TString GetEndSQLTime()
time_t GetStartUnixTime()
TString fDataDirectory
Int_t EncodePauseEvent()
UInt_t fStartingPhysicsEvent
Int_t GetEventNumber()
Int_t CloseThisSegment()
void ReportRunSummary()
static std::string fDefaultDataDirectory
Int_t EncodeEndEvent()
Bool_t fChainDataFiles
std::unordered_map< RocBankLabel_t, std::vector< UInt_t > > fMarkerList
enum QwEventBuffer::CodaStreamMode fEvStreamMode
Int_t CloseStream()
Closes a currently open event stream.
Bool_t IsEPICSEvent()
Int_t OpenETStream(TString computer, TString session, int mode, const TString stationname="")
Bool_t fRunIsSegmented
Bool_t GetNextRunRange()
Read the next requested run range, return true if success.
Int_t EncodePrestartEvent(int runnumber, int runtype=0)
QwEventBuffer()
Default constructor.
void VerifyCodaVersion(const UInt_t *buffer)
Int_t WriteFileEvent(int *buffer)
Int_t OpenNextStream()
Opens the event stream (file or ET) based on the internal flags.
static const Int_t kFileHandleNotConfigured
std::vector< Int_t >::iterator fRunSegmentIterator
void ProcessOptions(QwOptions &options)
Sets internal flags based on the QwOptions.
Bool_t FillSubsystemData(QwSubsystemArray &subsystems)
VEventDecoder * decoder
TStopwatch fStopwatch
Timer used for internal timing.
Int_t WriteEvent(int *buffer)
Int_t GetSegmentNumber() const
Return CODA file segment number.
std::unique_ptr< QwParameterFile > fEventListFile
void ResetControlParameters()
const TString & DataFile(const UInt_t run, const Short_t seg)
TString GetStartSQLTime()
TString fETStationName
static void DefineOptions(QwOptions &options)
std::unordered_map< RocBankLabel_t, std::vector< UInt_t > > fOffsetList
Double_t fCleanParameter[3]
Scan data/clean data from the green monster.
UInt_t FindMarkerWord(UInt_t markerID, UInt_t *buffer, UInt_t num_words)
TString fDataFileExtension
Int_t GetRunNumber() const
Return CODA file run number.
static const UInt_t kNullDataWord
static const Int_t kNoNextDataFile
RocBankLabel_t fThisRocBankLabel
Bool_t GetNextEventRange()
Read the next requested event range, return true if success.
Bool_t DataFileIsSegmented()
std::pair< Int_t, Int_t > fRunRange
std::pair< UInt_t, UInt_t > fEventRange
Int_t OpenDataFile(UInt_t current_run, Short_t seg)
static std::string fDefaultDataFileExtension
std::string fRunListFileName
Int_t OpenNextSegment()
UInt_t fNumPhysicsEvents
TStopwatch fRunTimer
Timer used for runlet processing loop.
time_t GetEndUnixTime()
static std::string fDefaultDataFileStem
Bool_t GetNextRunNumber()
Get the next run in the active run range, proceed to next range if needed.
Bool_t IsPhysicsEvent()
Bool_t FillEPICSData(QwEPICSEvent &epics)
THaCodaData * fEvStream
std::pair< Int_t, Int_t > fSegmentRange
std::unique_ptr< QwParameterFile > fRunListFile
std::size_t CheckForMarkerWords(QwSubsystemArray &subsystems)
std::vector< Int_t > fRunSegments
Bool_t FillSubsystemConfigurationData(QwSubsystemArray &subsystems)
TString fDataFileStem
Int_t fDataVersionVerify
UInt_t GetMarkerWord(UInt_t markerID)
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Command-line and configuration file options processor.
Definition QwOptions.h:141
std::pair< int, int > GetIntValuePair(const std::string &key)
Get a pair of integer values.
Definition QwOptions.cc:357
po::options_description_easy_init AddDefaultOptions()
Add a default option.
Definition QwOptions.h:165
T GetValue(const std::string &key)
Get a templated value.
Definition QwOptions.h:236
bool HasValue(const std::string &key)
Has this key been defined.
Definition QwOptions.h:229
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition QwOptions.h:170
static std::pair< int, int > ParseIntRange(const std::string &separatorchars, const std::string &range)
Parse a range of integers as #:# where either can be missing.
Container for managing multiple subsystems with common operations.
void SetCodaRunNumber(UInt_t runnum)
Set the internal record of the CODA run number.
void SetCleanParameters(Double_t cleanparameter[3])
Set the internal record of the CODA event number.
UInt_t GetEventTypeMask() const
Get event type mask.
void GetMarkerWordList(const ROCID_t roc_id, const BankID_t bank_id, std::vector< UInt_t > &marker) const
void EncodeEventData(std::vector< UInt_t > &buffer)
Encode the data in this event.
void SetCodaSegmentNumber(UInt_t segnum)
Set the internal record of the CODA segment number.
Int_t ProcessEvBuffer(const UInt_t event_type, const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for events.
void SetCodaEventNumber(UInt_t evtnum)
Set the internal record of the CODA event number.
void SetCodaEventType(UInt_t evttype)
Set the internal record of the CODA event type.
Int_t ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for configuration events.
void GetROCIDList(std::vector< ROCID_t > &list)
Get the ROCID list.