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){
An options class which parses command line, config file and environment.
Array container for managing multiple subsystems.
EPICS data event handling and storage.
#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.
Definition of the pure virtual base class of all subsystems.
Event buffer management for reading and processing CODA data.
void sigint_handler(int sig)
void sigusr_handler(int sig)
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.