22namespace fs = std::filesystem;
29 std::cout <<
"handling signal no. " << sig <<
" ";
30 std::cout <<
"(press ctrl-\\ to abort now)\n";
35 std::cout <<
"handling signal no. " << sig <<
"\n";
36 std::cout <<
"Restarts the event loop in online mode." << std::endl;
40#include "THaCodaFile.h"
42#include "THaEtClient.h"
95 (
"online", po::value<bool>()->default_bool_value(
false),
96 "use online data stream");
98 (
"online.RunNumber", po::value<int>()->default_bool_value(0),
99 "Effective run number to be used by online system to find the parameter files");
101 (
"run,r", po::value<string>()->default_value(
"0:0"),
102 "run range in format #[:#]");
105 "data directory, also $QW_DATA");
107 (
"runlist", po::value<string>()->default_value(
""),
108 "run list file name");
110 (
"event,e", po::value<string>()->default_value(
"0:"),
111 "event range in format #[:#]");
113 (
"segment,s", po::value<string>()->default_value(
"0:"),
114 "run segment range in format #[:#]");
116 (
"chainfiles", po::value<bool>()->default_bool_value(
false),
117 "chain file segments together, do not analyze them separately");
120 "stem of the input CODA filename");
123 "extension of the input CODA filename");
125 (
"directfile", po::value<string>(),
126 "Run over single event file");
129 (
"allow-low-subbank-ids", po::value<bool>()->default_bool_value(
false),
130 "allow the sub-bank ids to be 31 or less, when using this flag, all ROCs must be sub-banked");
133 (
"ET.hostname", po::value<string>(),
134 "Name of the ET session's host machine --- Only used in online mode\nDefaults to the environment variable $HOSTNAME");
136 (
"ET.session", po::value<string>(),
137 "ET session name --- Only used in online mode\nDefaults to the environment variable $SESSION");
139 (
"ET.station", po::value<string>(),
140 "ET station name --- Only used in online mode");
142 (
"ET.waitmode", po::value<int>()->default_value(0),
143 "ET system wait mode: 0 is wait-forever, 1 is timeout \"quickly\" --- Only used in online mode");
145 (
"ET.exit-on-end", po::value<bool>()->default_value(
false),
146 "Exit the event loop if the end event is found. JAPAN remains open and waits for the next run. --- Only used in online mode");
148 (
"coda-version", po::value<int>()->default_value(3),
149 "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.");
151 (
"max-event-rate", po::value<double>()->default_value(0.0),
152 "Maximum event write rate in Hz (0 = disabled, no rate limiting)");
162 QwError <<
"Online mode will not work without the CODA libraries!"
166 if (options.
HasValue(
"online.RunNumber")) {
169 if (options.
HasValue(
"ET.station")) {
174 if (options.
HasValue(
"ET.hostname")) {
179 if (options.
HasValue(
"ET.session")) {
187 tmp +=
" \"HOSTNAME\"";
189 if (tmp.Length() > 0)
191 tmp +=
" ET \"SESSION\"";
194 <<
" variable(s) is(are) not defined in your environment.\n"
195 <<
" This is needed to run the online analysis."
209 QwError <<
"ERROR: Can't get the data directory in the QwEventBuffer creator."
215 if( ! fs::exists(tmppath) || ! fs::is_directory(tmppath)) {
217 <<
", does not exist. Exiting."
236 QwError <<
"Invalid Coda Version. Only versions 2 and 3 are supported. "
237 <<
"Please set using --coda-version 2(3)" <<
QwLog::endl;
241 decoder->SetAllowLowSubbankIDs( options.
GetValue<
bool>(
"allow-low-subbank-ids") );
249 <<
"(minimum interval: " << (1000.0 /
fMaxEventRate) <<
" ms)"
289 if (nevents==0) nevents=1;
293 <<
"CPU time used: " <<
fRunTimer.CpuTime() <<
" s "
295 <<
"Real time used: " <<
fRunTimer.RealTime() <<
" s "
306 std::string eventrange;
326 std::string runrange;
334 QwWarning <<
"No valid event range in run list file: "
336 <<
"Assuming the full event range." <<
QwLog::endl;
373 Int_t status = CODA_ERROR;
394 Int_t status = CODA_ERROR;
404 QwMessage <<
"Try to open the ET station with HOSTNAME=="
419 if (status == CODA_ERROR){
422 QwError <<
"ERROR: Unable to find data files for run "
467 Int_t status = CODA_OK;
490 if (
decoder->GetEvtNumber() > 1000) status = EOF;
507 }
while (status == CODA_OK &&
521 QwMessage << efficiency <<
"% efficiency)";
525 }
else if (
decoder->GetEvtNumber() > 0 &&
decoder->GetEvtNumber() % 100 == 0) {
542 if (status == CODA_OK){
544 UInt_t* evBuffer = (UInt_t*)
fEvStream->getEvBuffer();
548 decoder->DecodeEventIDBank(evBuffer);
560 if(buffer[0] == 0)
return;
561 UInt_t header = buffer[1];
562 int top = (header & 0xff000000) >> 24;
563 int bot = (header & 0xff );
565 if( (top == 0xff) && (bot != 0xcc) ){
567 }
else if( (top != 0xff) && (bot == 0xcc) ){
574 <<
", but it looks like the data is from Coda Version "
584 Int_t status = CODA_OK;
602 Int_t status = CODA_OK;
606 if (status != CODA_OK) {
620 auto now = std::chrono::steady_clock::now();
630 if (actual_sleep > std::chrono::duration<double>(0)) {
632 auto sleep_until_time = now + actual_sleep;
633 std::this_thread::sleep_until(sleep_until_time);
667 Int_t status = CODA_OK;
670 status = ((THaCodaFile*)
fEvStream)->codaWrite((UInt_t*) buffer);
676 Int_t status = CODA_OK;
681 UInt_t* ubuffer = (UInt_t*)buffer;
682 UInt_t event_length = ubuffer[0];
684 if( event_length == 0 || event_length > MAXEVLEN ) {
689 status = ((THaEtClient*)
fEvStream)->codaWrite(ubuffer, event_length);
690 if( status != CODA_OK ) {
704 std::vector<UInt_t> buffer;
705 std::vector<ROCID_t> ROCList;
709 std::vector<UInt_t> header =
decoder->EncodePHYSEventHeader(ROCList);
714 int* codabuffer =
new int[header.size() + buffer.size() + 1];
717 codabuffer[k++] = header.size() + buffer.size();
718 for (
size_t i = 0; i < header.size(); i++)
719 codabuffer[k++] = header.at(i);
720 for (
size_t i = 0; i < buffer.size(); i++)
721 codabuffer[k++] = buffer.at(i);
734 decoder->ResetControlParameters();
743 return decoder->GetStartSQLTime();
748 return decoder->GetEndSQLTime();
753 return decoder->GetStartUnixTime();
758 return decoder->GetEndUnixTime();
764 int localtime = (int)time(0);
765 decoder->EncodePrestartEventHeader(buffer, runnumber, runtype, localtime);
771 int localtime = (int)time(0);
773 decoder->EncodeGoEventHeader(buffer, eventcount, localtime);
779 int localtime = (int)time(0);
781 decoder->EncodePauseEventHeader(buffer, eventcount, localtime);
787 int localtime = (int)time(0);
789 decoder->EncodeEndEventHeader(buffer, eventcount, localtime);
806 UInt_t rocnum =
decoder->GetEvtType() - 0x90;
807 QwMessage <<
"QwEventBuffer::FillSubsystemConfigurationData: "
808 <<
"Found configuration event for ROC"
813 UInt_t *localbuff = (UInt_t*)(
fEvStream->getEvBuffer());
814 decoder->DecodeEventIDBank(localbuff);
815 while ((okay =
decoder->DecodeSubbankHeader(&localbuff[
decoder->GetWordsSoFar()]))){
817 if (
decoder->GetSubbankType() == 0x10) {
824 decoder->AddWordsSoFarAndFragLength();
838 &localbuff[
decoder->GetWordsSoFar()],
840 decoder->AddWordsSoFarAndFragLength();
841 QwDebug <<
"QwEventBuffer::FillSubsystemConfigurationData: "
842 <<
"Ending loop: fWordsSoFar=="<<
decoder->GetWordsSoFar()
856 UInt_t *localbuff = (UInt_t*)(
fEvStream->getEvBuffer());
858 decoder->DecodeEventIDBank(localbuff);
877 while ((okay =
decoder->DecodeSubbankHeader(&localbuff[
decoder->GetWordsSoFar()]))){
880 if (
decoder->GetSubbankType() == 0x10)
continue;
885 decoder->AddWordsSoFarAndFragLength();
911 for (
size_t i=0; i<nmarkers; i++){
914 tmpbank = ((tmpbank)<<32) +
decoder->GetSubbankTag();
917 &localbuff[
decoder->GetWordsSoFar()+offset],
918 decoder->GetFragLength()-offset);
921 QwDebug <<
"QwEventBuffer::FillSubsystemData: "
922 <<
"fROC=="<<
decoder->GetROC() <<
", GetSubbankTag()==" <<
decoder->GetSubbankTag()
925 &localbuff[
decoder->GetWordsSoFar()],
928 decoder->AddWordsSoFarAndFragLength();
956 QwVerbose <<
"QwEventBuffer::FillEPICSData: "
959 UInt_t *localbuff = (UInt_t*)(
fEvStream->getEvBuffer());
960 if (
decoder->GetBankDataType()==0x10){
961 while ((okay =
decoder->DecodeSubbankHeader(&localbuff[
decoder->GetWordsSoFar()]))){
963 if (
decoder->GetSubbankType() == 0x10)
continue;
967 decoder->AddWordsSoFarAndFragLength();
971 if (
decoder->GetSubbankType() == 0x3){
974 char* tmpchar = (Char_t*)&localbuff[
decoder->GetWordsSoFar()];
982 decoder->AddWordsSoFarAndFragLength();
993 if (
decoder->GetBankDataType() == 0x3){
996 Char_t* tmpchar = (Char_t*)&localbuff[
decoder->GetWordsSoFar()];
1007 QwVerbose <<
"QwEventBuffer::FillEPICSData: End of routine"
1032 Int_t local_segment;
1034 std::vector<Int_t> tmp_segments;
1035 std::vector<Int_t> local_index;
1038 tmp_segments.clear();
1044 glob(searchpath.Data(), GLOB_ERR, NULL, &globbuf);
1050 }
else if (globbuf.gl_pathc == 1){
1059 <<
" Trying to find run segments for run "
1062 searchpath.Append(
".[0-9]*");
1063 glob(searchpath.Data(), GLOB_ERR, NULL, &globbuf);
1065 if (globbuf.gl_pathc == 0){
1083 for (
size_t iloop=0;iloop<globbuf.gl_pathc;++iloop){
1085 sscanf(globbuf.gl_pathv[iloop], scanvalue.Data(), &local_segment);
1086 tmp_segments.push_back(local_segment);
1088 local_index.resize(tmp_segments.size(),0);
1091 TMath::Sort(
static_cast<int>(tmp_segments.size()),&(tmp_segments[0]),&(local_index[0]),
1097 for (
size_t iloop=0; iloop<tmp_segments.size(); ++iloop){
1098 local_segment = tmp_segments[local_index[iloop]];
1101 if (local_segment == 0 ||
1117 QwError <<
"First requested run segment "
1134 Int_t last_runsegment;
1139 QwMessage <<
"Closing run segment " << last_runsegment <<
"."
1179 status = CODA_ERROR;
1220 QwDebug <<
"QwEventBuffer::OpenDataFile: File handle doesn't exist.\n"
1221 <<
" Try to open a new file handle!"
1226 QwError <<
"QwEventBuffer::OpenDataFile: The stream is not configured as an input\n"
1227 <<
" file stream! Can't deal with this!\n"
1233 if (rw.Contains(
"w",TString::kIgnoreCase)) {
1240 glob(
fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1241 if (globbuf.gl_pathc == 0){
1244 glob(
fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1246 if (globbuf.gl_pathc == 0){
1249 glob(
fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1251 if (globbuf.gl_pathc == 0){
1254 glob(
fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1256 if (globbuf.gl_pathc == 1){
1261 << filename.Data() <<
" or "
1282 const TString stationname)
1284 Int_t status = CODA_OK;
1287 if (stationname !=
""){
1288 fEvStream =
new THaEtClient(computer, session, mode, stationname.Data());
1290 fEvStream =
new THaEtClient(computer, session, mode);
1316 std::vector<UInt_t> tmpvec;
1321 QwDebug <<
"QwEventBuffer::GetMarkerWordList: fMarkerList.count(fThisRocBankLabel)=="
1323 <<
" fMarkerList.at(fThisRocBankLabel).size()=="
1337 if (markerpos < num_words && buffer[markerpos] == markerval){
1341 for (
size_t i=0; i<num_words; i++){
1342 if (buffer[i] == markerval){
void sigint_handler(int sig)
void sigusr_handler(int sig)
#define QwVerbose
Predefined log drain for verbose messages.
#define QwError
Predefined log drain for errors.
#define QwWarning
Predefined log drain for warnings.
#define QwMessage
Predefined log drain for regular messages.
#define QwDebug
Predefined log drain for debugging output.
Event buffer management for reading and processing CODA data.
EPICS data event handling and storage.
Definition of the pure virtual base class of all subsystems.
Array container for managing multiple subsystems.
An options class which parses command line, config file and environment.
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)
static const Int_t kRunNotSegmented
time_t GetStartUnixTime()
UInt_t fStartingPhysicsEvent
static std::string fDefaultDataDirectory
std::unordered_map< RocBankLabel_t, std::vector< UInt_t > > fMarkerList
enum QwEventBuffer::CodaStreamMode fEvStreamMode
Int_t CloseStream()
Closes a currently open event stream.
Int_t WriteEtEvent(int *buffer)
Int_t OpenETStream(TString computer, TString session, int mode, const TString stationname="")
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
std::chrono::duration< double > fAccumulatedDelay
void ProcessOptions(QwOptions &options)
Sets internal flags based on the QwOptions.
Bool_t FillSubsystemData(QwSubsystemArray &subsystems)
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()
Bool_t fEventRateLimitEnabled
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
TStopwatch fRunTimer
Timer used for runlet processing loop.
static std::string fDefaultDataFileStem
Bool_t GetNextRunNumber()
Get the next run in the active run range, proceed to next range if needed.
std::chrono::duration< double > fMinEventInterval
Bool_t FillEPICSData(QwEPICSEvent &epics)
std::pair< Int_t, Int_t > fSegmentRange
std::unique_ptr< QwParameterFile > fRunListFile
std::size_t CheckForMarkerWords(QwSubsystemArray &subsystems)
std::chrono::steady_clock::time_point fLastEventTime
std::vector< Int_t > fRunSegments
Bool_t FillSubsystemConfigurationData(QwSubsystemArray &subsystems)
UInt_t GetMarkerWord(UInt_t markerID)
static std::ostream & endl(std::ostream &)
End of the line.
Command-line and configuration file options processor.
std::pair< int, int > GetIntValuePair(const std::string &key)
Get a pair of integer values.
po::options_description_easy_init AddDefaultOptions()
Add a default option.
T GetValue(const std::string &key)
Get a templated value.
bool HasValue(const std::string &key)
Has this key been defined.
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
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.
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.