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());
62 std::stringstream str;
67static int hasSuffix(
const char* name,
const char* suffix)
70 const char* s = strstr(name, suffix);
75 return static_cast<int>((s - name) + strlen(suffix) == strlen(name));
109 std::ifstream in(
GetFilename(), std::ifstream::in | std::ifstream::binary);
110 in.seekg(0, std::ifstream::end);
118 if(strncmp(filename,
"ssh://", 6) == 0) {
119 const char* name = filename + 6;
120 const char* s = strstr(name,
"/");
124 fLastError.assign(
"TMidasFile::Open: Invalid ssh:// URI. Should be: ssh://user@host/file/path/...");
128 const char* remoteFile = s + 1;
130 std::string remoteHost;
131 for(s = name; *s !=
'/'; s++) {
135 pipe =
"ssh -e none -T -x -n ";
142 pipe +=
" | gzip -dc";
143 }
else if(
hasSuffix(remoteFile,
".bz2") != 0) {
144 pipe +=
" | bzip2 -dc";
146 }
else if(strncmp(filename,
"dccp://", 7) == 0) {
147 const char* name = filename + 7;
151 pipe +=
" /dev/fd/1";
154 pipe +=
" | gzip -dc";
155 }
else if(
hasSuffix(filename,
".bz2") != 0) {
156 pipe +=
" | bzip2 -dc";
158 }
else if(strncmp(filename,
"pipein://", 9) == 0) {
165 }
else if(
hasSuffix(filename,
".bz2") != 0) {
173 if(pipe.length() > 0) {
174 fprintf(stderr,
"TMidasFile::Open: Reading from pipe: %s\n", pipe.c_str());
175 fPoFile = popen(pipe.c_str(),
"r");
202 if((*(gzFile*)
fGzFile) ==
nullptr) {
209 fLastError.assign(
"Do not know how to read compressed MIDAS files");
248 std::cout <<
"Attempting normal open of file " << filename << std::endl;
259 std::cout <<
"Opened output file " << filename <<
"; return fOutFile is " <<
fOutFile << std::endl;
271 std::cout <<
"Opened gz file successfully" << std::endl;
273 if(gzsetparams(*(gzFile*)
fOutGzFile, 1, Z_DEFAULT_STRATEGY) != Z_OK) {
274 std::cout <<
"Cannot set gzparams" << std::endl;
276 fLastError.assign(
"zlib gzsetparams() error");
279 std::cout <<
"setparams for gz file successfully" << std::endl;
283 fLastError.assign(
"Do not know how to write compressed MIDAS files");
294 int rd = read(fd, buf, length);
315 if(event ==
nullptr) {
318 std::shared_ptr<TMidasEvent> midasEvent = std::static_pointer_cast<TMidasEvent>(event);
330 std::cout <<
"Swapping bytes" << std::endl;
331 midasEvent->SwapBytesEventHeader();
333 if(!midasEvent->IsGoodSize()) {
339 size_t eventSize = midasEvent->GetDataSize();
351 midasEvent->SwapBytes(
false);
364 for(
size_t i = 0; i < nofEvents; ++i) {
379 std::cout <<
"Swapping bytes" << std::endl;
424 assert(!
"Cannot get here");
435 }
else if(rd != bytes) {
449 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetEventId() & 0xFF));
450 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetEventId() >> 8));
452 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTriggerMask() & 0xFF));
453 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTriggerMask() >> 8));
455 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetSerialNumber() & 0xFF));
456 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetSerialNumber() >> 8) & 0xFF));
457 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetSerialNumber() >> 16) & 0xFF));
458 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetSerialNumber() >> 24));
460 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTimeStamp() & 0xFF));
461 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetTimeStamp() >> 8) & 0xFF));
462 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetTimeStamp() >> 16) & 0xFF));
463 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetTimeStamp() >> 24));
465 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetDataSize() & 0xFF));
466 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetDataSize() >> 8) & 0xFF));
467 fWriteBuffer.push_back(
static_cast<char>((midasEvent->GetDataSize() >> 16) & 0xFF));
468 fWriteBuffer.push_back(
static_cast<char>(midasEvent->GetDataSize() >> 24));
470 for(
size_t i = 0; i < midasEvent->GetDataSize(); i++) {
490 assert(!
"Cannot get here");
511 assert(!
"Cannot get here");
518 std::cout <<
"TMidasFile: error on write event header, return " << wr <<
", size requested " <<
sizeof(
TMidas_EVENT_HEADER) << std::endl;
522 if(strncmp(opt,
"q", 1) != 0) {
523 std::cout <<
"Written event header to outfile , return is " << wr << std::endl;
528 wr = gzwrite(*(gzFile*)
fOutGzFile, (
char*)midasEvent->GetData(), midasEvent->GetDataSize());
530 assert(!
"Cannot get here");
533 wr = write(
fOutFile, midasEvent->GetData(), midasEvent->GetDataSize());
536 if(strncmp(opt,
"q", 1) != 0) {
537 std::cout <<
"Written event to outfile , return is " << wr << std::endl;
555 pclose(
reinterpret_cast<FILE*
>(
fPoFile));
574 if(
static_cast<unsigned int>(!
fWriteBuffer.empty()) != 0u) {
598 std::size_t foundslash =
Filename().rfind(
'/');
599 std::size_t found =
Filename().rfind(
".mid");
600 if(found == std::string::npos) {
603 std::size_t found2 =
Filename().rfind(
'-');
604 if((found2 < foundslash && foundslash != std::string::npos) || found2 == std::string::npos) {
607 if(found2 < foundslash && foundslash != std::string::npos) {
608 found2 = std::string::npos;
611 if(found2 == std::string::npos ||
Filename().compare(found2 + 4, 4,
".mid") != 0) {
612 temp =
Filename().substr(found - 5, 5);
614 temp =
Filename().substr(found - 9, 5);
616 return atoi(temp.c_str());
626 std::size_t foundslash =
Filename().rfind(
'/');
627 std::size_t found =
Filename().rfind(
'-');
628 if((found < foundslash && foundslash != std::string::npos) || found == std::string::npos) {
631 if(found < foundslash && foundslash != std::string::npos) {
632 found = std::string::npos;
634 if(found != std::string::npos) {
635 std::string temp =
Filename().substr(found + 1, 3);
636 return atoi(temp.c_str());
650 std::cout <<
DYELLOW <<
"\tskipping odb information stored in file." <<
RESET_COLOR << std::endl;
656 }
catch(std::exception& e) {
657 std::cout <<
"Got exception '" << e.what() <<
"' trying to read " <<
fOdbEvent->GetDataSize() <<
" bytes (or words?) from:" << std::endl;
658 std::cout <<
fOdbEvent->GetData() << std::endl;
669 std::cout <<
DYELLOW <<
"\tskipping odb channel information stored in file." <<
RESET_COLOR << std::endl;
675 if(!node->HasChildren()) {
678 node = node->GetChildren();
683 expt = node->GetText();
686 if(!node->HasNextNode()) {
689 node = node->GetNextNode();
691 if(expt ==
"tigress") {
693 }
else if(expt.find(
"grif") != std::string::npos) {
696 }
else if(expt ==
"tigdaq") {
699 std::cerr <<
RED <<
"Unknown experiment name \"" << expt <<
"\", ODB won't be read!" <<
RESET_COLOR << std::endl;
707 TXMLNode* node =
fOdb->
FindPath(
"/Runinfo/Start time binary");
708 if(node !=
nullptr) {
709 std::stringstream str(node->GetText());
710 unsigned int odbTime = 0;
713 std::cout <<
"Warning, ODB start time of first subrun (" << odbTime <<
") does not match midas time of first event in this subrun (" << time <<
")!" << std::endl;
718 node =
fOdb->
FindPath(
"/Experiment/Run parameters/Run Title");
719 if(node !=
nullptr) {
721 std::cout <<
"Title: " <<
DBLUE << node->GetText() <<
RESET_COLOR << std::endl;
724 if(node !=
nullptr) {
725 node =
fOdb->
FindPath(
"/Experiment/Run parameters/Comment");
727 std::cout <<
"Comment: " <<
DBLUE << node->GetText() <<
RESET_COLOR << std::endl;
735 TXMLNode* node =
fOdb->
FindPath(
"/Equipment/Epics/Settings/Names");
746 std::string path =
"/DAQ/PSC";
749 std::cout <<
"using GRIFFIN path to analyzer info: " << path <<
"..." << std::endl;
755 std::cout <<
"using GRIFFIN path to analyzer info: " << path <<
"..." << std::endl;
764 temp.append(
"/chan");
769 temp.append(
"/datatype");
775 temp.append(
"/DetType");
778 std::cout <<
"failed to find ODB path " << path <<
"/datatype, using " << type.size() <<
" entries from " << path <<
"/DetType instead" << std::endl;
782 temp.append(
"/gain");
787 temp.append(
"/offset");
793 temp.append(
"/quadratic");
798 temp.append(
"/digitizer");
802 if((address.size() == names.size()) && (names.size() == gains.size()) && (gains.size() == offsets.size()) &&
803 (offsets.size() == type.size())) {
806 for(
size_t x = 0; x < address.size(); x++) {
808 if(tempChan ==
nullptr) {
811 tempChan->
SetName(names.at(x).c_str());
817 if(x < quads.size()) {
820 if(x < digitizer.size()) {
828 std::cout <<
BG_WHITE DRED <<
"problem parsing odb data, arrays are different sizes, channels not set." <<
RESET_COLOR << std::endl;
836 if(node ==
nullptr) {
837 std::cerr << R
"(Failed to find "/PPG/Current" in ODB!)" << std::endl;
841 if(!node->HasChildren()) {
842 std::cout <<
"Node has no children, can't read ODB cycle" << std::endl;
845 std::string currentCycle =
"/PPG/Cycles/";
846 currentCycle.append(node->GetChildren()->GetContent());
848 temp.append(
"/PPGcodes");
850 if(node ==
nullptr) {
851 std::cerr << R
"(Failed to find ")" << temp << R"(" in ODB!)" << std::endl;
857 std::vector<int16_t> ppgCodes;
858 for(
auto& code : tmpCodes) {
859 if(((code >> 16) & 0xffff) != (code & 0xffff)) {
860 std::cout <<
DRED <<
"Found ppg code in the ODB with high bits (0x" << std::hex << (code >> 16)
861 <<
") != low bits (" << (code & 0xffff) << std::dec <<
")" <<
RESET_COLOR << std::endl;
863 ppgCodes.push_back(code & 0xffff);
866 temp.append(
"/durations");
868 if(node ==
nullptr) {
869 std::cerr << R
"(Failed to find ")" << temp << R"(" in ODB!)" << std::endl;
874 if(durations.size() != ppgCodes.size()) {
875 std::cerr <<
"Mismatching sizes of ppg codes (" << ppgCodes.size() <<
") and duration (" << durations.size() <<
")" << std::endl;
886 std::string typepath =
"/Equipment/Trigger/settings/Detector Settings";
887 std::map<int, std::pair<std::string, std::string>> typemap;
890 if(typenode->HasChildren()) {
891 TXMLNode* typechild = typenode->GetChildren();
894 if(tname.length() > 0 && typechild->HasChildren()) {
896 TXMLNode* grandchild = typechild->GetChildren();
899 if(grandchildname.compare(0, 7,
"Digitis") == 0) {
900 std::string dname = grandchild->GetText();
901 typemap[typecounter] = std::make_pair(tname, dname);
904 if(!grandchild->HasNextNode()) {
907 grandchild = grandchild->GetNextNode();
910 if(!typechild->HasNextNode()) {
913 typechild = typechild->GetNextNode();
917 std::string path =
"/Analyzer/Shared Parameters/Config";
919 if(test ==
nullptr) {
920 path.assign(
"/Analyzer/Parameters/Cathode/Config");
922 std::cout <<
"using TIGRESS path to analyzer info: " << path <<
"..." << std::endl;
924 std::string temp = path;
925 temp.append(
"/FSCP");
930 temp.append(
"/Name");
935 temp.append(
"/Type");
951 if((address.size() == gains.size()) && (gains.size() == offsets.size()) && offsets.size() == type.size()) {
954 std::cout <<
BG_WHITE DRED <<
"problem parsing odb data, arrays are different sizes, channels not set." <<
RESET_COLOR << std::endl;
955 std::cout <<
DRED <<
"\taddress.size() = " << address.size() <<
RESET_COLOR << std::endl;
956 std::cout <<
DRED <<
"\tnames.size() = " << names.size() <<
RESET_COLOR << std::endl;
957 std::cout <<
DRED <<
"\tgains.size() = " << gains.size() <<
RESET_COLOR << std::endl;
958 std::cout <<
DRED <<
"\toffsets.size() = " << offsets.size() <<
RESET_COLOR << std::endl;
959 std::cout <<
DRED <<
"\ttype.size() = " << type.size() <<
RESET_COLOR << std::endl;
963 for(
size_t x = 0; x < address.size(); x++) {
965 if(tempChan ==
nullptr) {
968 if(x < names.size()) {
969 tempChan->
SetName(names.at(x).c_str());
973 int temp_integration = 0;
974 if(type.at(x) != 0) {
978 temp_integration = 25;
980 temp_integration = 125;
998 std::string path =
"/DAQ/PSC";
1001 std::cout <<
"using TIGRESS path to analyzer info: " << path <<
"..." << std::endl;
1004 temp.append(
"/PSC");
1007 std::cout <<
"using TIGRESS path to analyzer info: " << path <<
"..." << std::endl;
1010 temp.append(
"/MSC");
1016 temp.append(
"/chan");
1021 temp.append(
"/datatype");
1027 temp.append(
"/DetType");
1030 std::cout <<
"failed to find ODB path " << path <<
"/datatype, using " << type.size() <<
" entries from " << path <<
"/DetType instead" << std::endl;
1034 temp.append(
"/gain");
1039 temp.append(
"/offset");
1045 temp.append(
"/quadratic");
1050 temp.append(
"/digitizer");
1054 if((address.size() == names.size()) && (names.size() == gains.size()) && (gains.size() == offsets.size()) && (gains.size() == offsets.size()) &&
1055 (offsets.size() == type.size())) {
1057 for(
size_t x = 0; x < address.size(); x++) {
1059 if(tempChan ==
nullptr) {
1062 tempChan->
SetName(names.at(x).c_str());
1068 if(x < quads.size()) { tempChan->
AddENGCoefficient(
static_cast<Float_t
>(quads.at(x))); }
1073 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