23#include "GRSIDataVersion.h"
31 uint32_t endian = 0x12345678;
32 fDoByteSwap = *
reinterpret_cast<char*
>(&endian) != 0x78;
43 std::stringstream str;
45 throw std::runtime_error(str.str());
58 std::stringstream str;
63static int hasSuffix(
const char* name,
const char* suffix)
66 const char*
s = strstr(name, suffix);
71 return static_cast<int>((
s - name) + strlen(suffix) == strlen(name));
105 std::ifstream in(
GetFilename(), std::ifstream::in | std::ifstream::binary);
106 in.seekg(0, std::ifstream::end);
114 if(strncmp(filename,
"ssh://", 6) == 0) {
115 const char* name = filename + 6;
116 const char*
s = strstr(name,
"/");
120 fLastError.assign(
"TMidasFile::Open: Invalid ssh:// URI. Should be: ssh://user@host/file/path/...");
124 const char* remoteFile =
s + 1;
126 std::string remoteHost;
127 for(
s = name; *
s !=
'/';
s++) {
131 pipe =
"ssh -e none -T -x -n ";
138 pipe +=
" | gzip -dc";
139 }
else if(
hasSuffix(remoteFile,
".bz2") != 0) {
140 pipe +=
" | bzip2 -dc";
142 }
else if(strncmp(filename,
"dccp://", 7) == 0) {
143 const char* name = filename + 7;
147 pipe +=
" /dev/fd/1";
150 pipe +=
" | gzip -dc";
151 }
else if(
hasSuffix(filename,
".bz2") != 0) {
152 pipe +=
" | bzip2 -dc";
154 }
else if(strncmp(filename,
"pipein://", 9) == 0) {
161 }
else if(
hasSuffix(filename,
".bz2") != 0) {
169 if(pipe.length() > 0) {
170 fprintf(stderr,
"TMidasFile::Open: Reading from pipe: %s\n", pipe.c_str());
171 fPoFile = popen(pipe.c_str(),
"r");
198 if((*(gzFile*)
fGzFile) ==
nullptr) {
205 fLastError.assign(
"Do not know how to read compressed MIDAS files");
244 std::cout <<
"Attempting normal open of file " << filename << std::endl;
255 std::cout <<
"Opened output file " << filename <<
"; return fOutFile is " <<
fOutFile << std::endl;
267 std::cout <<
"Opened gz file successfully" << std::endl;
269 if(gzsetparams(*(gzFile*)
fOutGzFile, 1, Z_DEFAULT_STRATEGY) != Z_OK) {
270 std::cout <<
"Cannot set gzparams" << std::endl;
272 fLastError.assign(
"zlib gzsetparams() error");
275 std::cout <<
"setparams for gz file successfully" << std::endl;
279 fLastError.assign(
"Do not know how to write compressed MIDAS files");
290 int rd = read(fd, buf, length);
311 if(event ==
nullptr) {
314 std::shared_ptr<TMidasEvent> midasEvent = std::static_pointer_cast<TMidasEvent>(event);
326 std::cout <<
"Swapping bytes" << std::endl;
327 midasEvent->SwapBytesEventHeader();
329 if(!midasEvent->IsGoodSize()) {
335 size_t event_size = midasEvent->GetDataSize();
347 midasEvent->SwapBytes(
false);
360 for(
size_t i = 0; i < nofEvents; ++i) {
375 std::cout <<
"Swapping bytes" << std::endl;
420 assert(!
"Cannot get here");
431 }
else if(rd != bytes) {
445 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetEventId() & 0xFF));
446 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetEventId() >> 8));
448 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTriggerMask() & 0xFF));
449 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTriggerMask() >> 8));
451 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetSerialNumber() & 0xFF));
452 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetSerialNumber() >> 8) & 0xFF));
453 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetSerialNumber() >> 16) & 0xFF));
454 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetSerialNumber() >> 24));
456 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTimeStamp() & 0xFF));
457 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetTimeStamp() >> 8) & 0xFF));
458 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetTimeStamp() >> 16) & 0xFF));
459 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTimeStamp() >> 24));
461 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetDataSize() & 0xFF));
462 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetDataSize() >> 8) & 0xFF));
463 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetDataSize() >> 16) & 0xFF));
464 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetDataSize() >> 24));
466 for(
size_t i = 0; i < midasEvent->GetDataSize(); i++) {
486 assert(!
"Cannot get here");
507 assert(!
"Cannot get here");
514 std::cout <<
"TMidasFile: error on write event header, return " << wr <<
", size requested " <<
sizeof(
TMidas_EVENT_HEADER) << std::endl;
518 if(strncmp(opt,
"q", 1) != 0) {
519 std::cout <<
"Written event header to outfile , return is " << wr << std::endl;
524 wr = gzwrite(*(gzFile*)
fOutGzFile, (
char*)midasEvent->GetData(), midasEvent->GetDataSize());
526 assert(!
"Cannot get here");
529 wr = write(
fOutFile, midasEvent->GetData(), midasEvent->GetDataSize());
532 if(strncmp(opt,
"q", 1) != 0) {
533 std::cout <<
"Written event to outfile , return is " << wr << std::endl;
551 pclose(
reinterpret_cast<FILE*
>(
fPoFile));
570 if(
static_cast<unsigned int>(!
fWriteBuffer.empty()) != 0u) {
594 std::size_t foundslash =
Filename().rfind(
'/');
595 std::size_t found =
Filename().rfind(
".mid");
596 if(found == std::string::npos) {
599 std::size_t found2 =
Filename().rfind(
'-');
600 if((found2 < foundslash && foundslash != std::string::npos) || found2 == std::string::npos) {
603 if(found2 < foundslash && foundslash != std::string::npos) {
604 found2 = std::string::npos;
607 if(found2 == std::string::npos ||
Filename().compare(found2 + 4, 4,
".mid") != 0) {
608 temp =
Filename().substr(found - 5, 5);
610 temp =
Filename().substr(found - 9, 5);
612 return atoi(temp.c_str());
622 std::size_t foundslash =
Filename().rfind(
'/');
623 std::size_t found =
Filename().rfind(
'-');
624 if((found < foundslash && foundslash != std::string::npos) || found == std::string::npos) {
627 if(found < foundslash && foundslash != std::string::npos) {
628 found = std::string::npos;
630 if(found != std::string::npos) {
631 std::string temp =
Filename().substr(found + 1, 3);
632 return atoi(temp.c_str());
646 std::cout <<
DYELLOW <<
"\tskipping odb information stored in file." <<
RESET_COLOR << std::endl;
652 }
catch(std::exception& e) {
653 std::cout <<
"Got exception '" << e.what() <<
"' trying to read " <<
fOdbEvent->GetDataSize() <<
" bytes (or words?) from:" << std::endl;
654 std::cout <<
fOdbEvent->GetData() << std::endl;
665 std::cout <<
DYELLOW <<
"\tskipping odb channel information stored in file." <<
RESET_COLOR << std::endl;
671 if(!node->HasChildren()) {
674 node = node->GetChildren();
679 expt = node->GetText();
682 if(!node->HasNextNode()) {
685 node = node->GetNextNode();
687 if(expt ==
"tigress") {
689 }
else if(expt.find(
"grif") != std::string::npos) {
692 }
else if(expt ==
"tigdaq") {
695 std::cerr <<
RED <<
"Unknown experiment name \"" << expt <<
"\", ODB won't be read!" <<
RESET_COLOR << std::endl;
703 TXMLNode* node =
fOdb->
FindPath(
"/Runinfo/Start time binary");
704 if(node !=
nullptr) {
705 std::stringstream str(node->GetText());
706 unsigned int odbTime = 0;
709 std::cout <<
"Warning, ODB start time of first subrun (" << odbTime <<
") does not match midas time of first event in this subrun (" << time <<
")!" << std::endl;
714 node =
fOdb->
FindPath(
"/Experiment/Run parameters/Run Title");
715 if(node !=
nullptr) {
717 std::cout <<
"Title: " <<
DBLUE << node->GetText() <<
RESET_COLOR << std::endl;
720 if(node !=
nullptr) {
721 node =
fOdb->
FindPath(
"/Experiment/Run parameters/Comment");
723 std::cout <<
"Comment: " <<
DBLUE << node->GetText() <<
RESET_COLOR << std::endl;
731 TXMLNode* node =
fOdb->
FindPath(
"/Equipment/Epics/Settings/Names");
742 std::string path =
"/DAQ/PSC";
745 std::cout <<
"using GRIFFIN path to analyzer info: " << path <<
"..." << std::endl;
751 std::cout <<
"using GRIFFIN path to analyzer info: " << path <<
"..." << std::endl;
760 temp.append(
"/chan");
765 temp.append(
"/datatype");
771 temp.append(
"/DetType");
774 std::cout <<
"failed to find ODB path " << path <<
"/datatype, using " << type.size() <<
" entries from " << path <<
"/DetType instead" << std::endl;
778 temp.append(
"/gain");
783 temp.append(
"/offset");
789 temp.append(
"/quadratic");
794 temp.append(
"/digitizer");
798 if((address.size() == names.size()) && (names.size() == gains.size()) && (gains.size() == offsets.size()) &&
799 (offsets.size() == type.size())) {
802 for(
size_t x = 0; x < address.size(); x++) {
804 if(tempChan ==
nullptr) {
807 tempChan->
SetName(names.at(x).c_str());
813 if(x < quads.size()) {
816 if(x < digitizer.size()) {
824 std::cout <<
BG_WHITE DRED <<
"problem parsing odb data, arrays are different sizes, channels not set." <<
RESET_COLOR << std::endl;
832 if(node ==
nullptr) {
833 std::cerr << R
"(Failed to find "/PPG/Current" in ODB!)" << std::endl;
837 if(!node->HasChildren()) {
838 std::cout <<
"Node has no children, can't read ODB cycle" << std::endl;
841 std::string currentCycle =
"/PPG/Cycles/";
842 currentCycle.append(node->GetChildren()->GetContent());
844 temp.append(
"/PPGcodes");
846 if(node ==
nullptr) {
847 std::cerr << R
"(Failed to find ")" << temp << R"(" in ODB!)" << std::endl;
853 std::vector<int16_t> ppgCodes;
854 for(
auto& code : tmpCodes) {
855 if(((code >> 16) & 0xffff) != (code & 0xffff)) {
856 std::cout <<
DRED <<
"Found ppg code in the ODB with high bits (0x" << std::hex << (code >> 16)
857 <<
") != low bits (" << (code & 0xffff) << std::dec <<
")" <<
RESET_COLOR << std::endl;
859 ppgCodes.push_back(code & 0xffff);
862 temp.append(
"/durations");
864 if(node ==
nullptr) {
865 std::cerr << R
"(Failed to find ")" << temp << R"(" in ODB!)" << std::endl;
870 if(durations.size() != ppgCodes.size()) {
871 std::cerr <<
"Mismatching sizes of ppg codes (" << ppgCodes.size() <<
") and duration (" << durations.size() <<
")" << std::endl;
882 std::string typepath =
"/Equipment/Trigger/settings/Detector Settings";
883 std::map<int, std::pair<std::string, std::string>> typemap;
886 if(typenode->HasChildren()) {
887 TXMLNode* typechild = typenode->GetChildren();
890 if(tname.length() > 0 && typechild->HasChildren()) {
892 TXMLNode* grandchild = typechild->GetChildren();
895 if(grandchildname.compare(0, 7,
"Digitis") == 0) {
896 std::string dname = grandchild->GetText();
897 typemap[typecounter] = std::make_pair(tname, dname);
900 if(!grandchild->HasNextNode()) {
903 grandchild = grandchild->GetNextNode();
906 if(!typechild->HasNextNode()) {
909 typechild = typechild->GetNextNode();
913 std::string path =
"/Analyzer/Shared Parameters/Config";
915 if(test ==
nullptr) {
916 path.assign(
"/Analyzer/Parameters/Cathode/Config");
918 std::cout <<
"using TIGRESS path to analyzer info: " << path <<
"..." << std::endl;
920 std::string temp = path;
921 temp.append(
"/FSCP");
926 temp.append(
"/Name");
931 temp.append(
"/Type");
947 if((address.size() == gains.size()) && (gains.size() == offsets.size()) && offsets.size() == type.size()) {
950 std::cout <<
BG_WHITE DRED <<
"problem parsing odb data, arrays are different sizes, channels not set." <<
RESET_COLOR << std::endl;
951 std::cout <<
DRED <<
"\taddress.size() = " << address.size() <<
RESET_COLOR << std::endl;
952 std::cout <<
DRED <<
"\tnames.size() = " << names.size() <<
RESET_COLOR << std::endl;
953 std::cout <<
DRED <<
"\tgains.size() = " << gains.size() <<
RESET_COLOR << std::endl;
954 std::cout <<
DRED <<
"\toffsets.size() = " << offsets.size() <<
RESET_COLOR << std::endl;
955 std::cout <<
DRED <<
"\ttype.size() = " << type.size() <<
RESET_COLOR << std::endl;
959 for(
size_t x = 0; x < address.size(); x++) {
961 if(tempChan ==
nullptr) {
964 if(x < names.size()) {
965 tempChan->
SetName(names.at(x).c_str());
969 int temp_integration = 0;
970 if(type.at(x) != 0) {
974 temp_integration = 25;
976 temp_integration = 125;
994 std::string path =
"/DAQ/PSC";
997 std::cout <<
"using TIGRESS path to analyzer info: " << path <<
"..." << std::endl;
1000 temp.append(
"/PSC");
1003 std::cout <<
"using TIGRESS path to analyzer info: " << path <<
"..." << std::endl;
1006 temp.append(
"/MSC");
1012 temp.append(
"/chan");
1017 temp.append(
"/datatype");
1023 temp.append(
"/DetType");
1026 std::cout <<
"failed to find ODB path " << path <<
"/datatype, using " << type.size() <<
" entries from " << path <<
"/DetType instead" << std::endl;
1030 temp.append(
"/gain");
1035 temp.append(
"/offset");
1041 temp.append(
"/quadratic");
1046 temp.append(
"/digitizer");
1050 if((address.size() == names.size()) && (names.size() == gains.size()) && (gains.size() == offsets.size()) && (gains.size() == offsets.size()) &&
1051 (offsets.size() == type.size())) {
1053 for(
size_t x = 0; x < address.size(); x++) {
1055 if(tempChan ==
nullptr) {
1058 tempChan->
SetName(names.at(x).c_str());
1064 if(x < quads.size()) { tempChan->
AddENGCoefficient(
static_cast<Float_t
>(quads.at(x))); }
1068 std::cout <<
BG_WHITE DRED <<
"problem parsing odb data, arrays are different sizes, channels not set." <<
RESET_COLOR << std::endl;
static int readpipe(int fd, char *buf, int length)
static int hasSuffix(const char *name, const char *suffix)
static void SetMnemonicClass(const TClassRef &cls)
static void DeleteAllChannels()
void SetAddress(unsigned int tmpadd)
static TChannel * GetChannel(unsigned int temp_address, bool warn=false)
void SetIntegration(const TPriorityValue< int > &tmp)
void SetNumber(const TPriorityValue< int > &tmp)
void AddENGCoefficient(Float_t temp, size_t range=0)
const char * GetDigitizerTypeString() const
void SetName(const char *tmpName) override
static void AddChannel(TChannel *, Option_t *opt="")
static size_t GetNumberOfChannels()
void SetDigitizerType(const TPriorityValue< std::string > &tmp)
static void SetEpicsNameList(const std::vector< std::string > &names)
static TGRSIOptions * Get(int argc=0, char **argv=nullptr)
Do not use!
TMidas_EVENT_HEADER * GetEventHeader()
return pointer to the event header
void Clear(Option_t *opt="") override
clear event for reuse
bool IsGoodSize() const
validate the event length
uint32_t GetDataSize() const override
return the event size
void SwapBytesEventHeader()
convert event header between little-endian (Linux-x86) and big endian (MacOS-PPC)
Reader for MIDAS .mid files.
bool OutOpen(const char *filename)
Open output file.
void OutClose()
Close output file.
std::string fLastError
error string from last errno
std::string Status(bool long_file_description=true) override
bool Open(const char *filename) override
Open input file.
uint32_t fCurrentBufferSize
void SetMaxBufferSize(int maxsize)
~TMidasFile() override
destructor
void SetRunInfo(uint32_t time)
int Read(std::shared_ptr< TRawEvent > event) override
Read one event from the file.
std::string fOutFilename
name of the currently open file
int GetSubRunNumber() override
void * fOutGzFile
zlib compressed output file reader
std::vector< char > fWriteBuffer
bool Write(const std::shared_ptr< TMidasEvent > &midasEvent, Option_t *opt="")
Write one event to the output file.
int fFile
open input file descriptor
void Skip(size_t nofEvents) override
Skip nofEvents from the file.
void Close() override
Close input file.
bool fDoByteSwap
"true" if file has to be byteswapped
void FillBuffer(const std::shared_ptr< TMidasEvent > &midasEvent, Option_t *opt="")
TMidasFile()
default constructor
void * fGzFile
zlib compressed input file reader
int fOutFile
open output file descriptor
int fLastErrno
errno from the last operation
void ReadMoreBytes(size_t bytes)
std::shared_ptr< TMidasEvent > fOdbEvent
void * fPoFile
popen() input file reader
int GetRunNumber() override
void SetOdbCycle(std::vector< int16_t > ppgCodes, std::vector< int > durations)
virtual const char * GetFilename() const
Get the name of this file.
size_t BufferSize() const
virtual size_t FileSize()
virtual std::string Filename() const
Get the name of this file.
void IncrementBytesRead(size_t val=1)
virtual size_t BytesRead()
void ResizeBuffer(size_t newSize)
static void SetRunComment(const char *run_comment)
static void SetRunStart(double tmp)
static int SubRunNumber()
static void SetRunInfo(int runnum=0, int subrunnum=-1)
static void ClearLibraryVersion()
static void SetDetectorInformation(TDetectorInformation *inf)
static void SetLibraryVersion(const char *ver)
static void SetRunTitle(const char *run_title)
static TPPG * Get(bool verbose=false)
std::vector< std::string > ReadStringArray(TXMLNode *node)
const char * GetNodeName(TXMLNode *)
std::vector< double > ReadDoubleArray(TXMLNode *node)
TXMLNode * FindPath(const char *path, TXMLNode *node=nullptr)
std::vector< int > ReadIntArray(TXMLNode *node)
uint16_t fEventId
event id