/********************************************************************\ RawDataCTX.cc Class for raw data handling of the DRS 2-based DAQ Oliver Grimm \********************************************************************/ #include "RawDataCTX.h" // *** Constructor RawDataCTX::RawDataCTX(bool BeSilent) { RHeader = new RunHeader; EHeader = new EventHeader; FileOpen = false; Silent = BeSilent; } // *** Destructor RawDataCTX::~RawDataCTX() { if(FileOpen) CloseDataFile(); delete RHeader; delete EHeader; } // *** Open raw data file CTX_ErrCode RawDataCTX::OpenDataFile(char *Filename, FILE *fptr) { // Close file if currently open if(FileOpen) CloseDataFile(); // Open file if ((Rawfile = fopen(Filename, "r")) == NULL) { if(!Silent) printf("Error: Could not open file: %s\n", Filename); return CTX_FOPEN; } // Read run header if (fread(RHeader, sizeof(RunHeader), 1, Rawfile) != 1) { if(!Silent) printf("Error: Could not read run header\n"); fclose(Rawfile); return CTX_RHEADER; } // Check magic number of run header if (RHeader->MagicNum!=MAGICNUM_OPEN && RHeader->MagicNum!=MAGICNUM_CLOSED && RHeader->MagicNum!=MAGICNUM_ERROR) { if(!Silent) printf("Error: Magic number of run header incorrect\n"); fclose(Rawfile); return CTX_RHEADER; } // Check if version of this software is not older than raw data format if (RHeader->DataFormat > DATA_FORMAT) { if(!Silent) printf("Error: Data format too new, incompatible with this read-out routine\n"); fclose(Rawfile); return CTX_VERSION; } // Check if allocated headers are long enough if (RHeader->RunHeaderSize>sizeof(RunHeader) || RHeader->BoardStructureSize>sizeof(BoardStructure) || RHeader->EventHeaderSize>sizeof(EventHeader)) { if(!Silent) printf("Error: Header size(s) too long (there must be a problem with the data version!)\n"); fclose(Rawfile); return CTX_VERSION; } // Read board structures BStruct = new BoardStructure [RHeader->NBoards]; for(unsigned int i=0; iNBoards; i++) { if(fread(&BStruct[i], RHeader->BoardStructureSize, 1, Rawfile) != 1) { if(!Silent) printf("Error: Could not read board structure of board number %d\n",i+1); fclose(Rawfile); delete[] BStruct; return CTX_BSTRUCT; } } // Initialize variables Data = NULL; FileOpen = true; // If requested, print run header (including board structures) to file if(fptr != NULL) { fprintf(fptr, "Magic number %x (%s)\n", RHeader->MagicNum, RHeader->MagicNum==MAGICNUM_CLOSED?"OK":(RHeader->MagicNum==MAGICNUM_OPEN?"File not closed":"Error")); fprintf(fptr, "Data format: %u\n", RHeader->DataFormat); fprintf(fptr, "Software revision: %d\n", RHeader->SoftwareRevision); fprintf(fptr, "Run header size: %d\n", RHeader->RunHeaderSize); fprintf(fptr, "Event header size: %d\n", RHeader->EventHeaderSize); fprintf(fptr, "Board structure size: %d\n", RHeader->BoardStructureSize); fprintf(fptr, "Description: %s\n", RHeader->Description); fprintf(fptr, "Identification: %u\n", RHeader->Identification); fprintf(fptr, "Run type: %u\n", RHeader->Type); fprintf(fptr, "Run number: %u\n", RHeader->RunNumber); fprintf(fptr, "File number: %u\n", RHeader->FileNumber); fprintf(fptr, "Events: %u\n", RHeader->Events); fprintf(fptr, "Boards: %u\n", RHeader->NBoards); fprintf(fptr, "Chips/board: %u\n", RHeader->NChips); fprintf(fptr, "Channels/chip: %u\n", RHeader->NChannels); fprintf(fptr, "Samples: %u\n", RHeader->Samples); fprintf(fptr, "Offset: %u\n", RHeader->Offset); fprintf(fptr, "Bytes/sample: %u\n", RHeader->NBytes); fprintf(fptr, "Start second: %u - UTC %s", RHeader->StartSecond, asctime(gmtime((time_t *) &RHeader->StartSecond))); fprintf(fptr, " microsecond: %u\n", RHeader->StartMicrosecond); fprintf(fptr, "End second: %u - UTC %s", RHeader->EndSecond, asctime(gmtime((time_t *) &RHeader->EndSecond))); fprintf(fptr, " microsecond: %u\n", RHeader->EndMicrosecond); for (unsigned int i=0; iNBoards; i++) { fprintf(fptr, "*** Board %d ***\n", i); fprintf(fptr, "Serial number: %d\n", BStruct[i].SerialNo); fprintf(fptr, "Sampling frequency: %.3f GHz\n", BStruct[i].NomFreq); fprintf(fptr, "Temperature: %.3f deg C\n", BStruct[i].BoardTemp); fprintf(fptr, "Scale factor: %.3f\n", BStruct[i].ScaleFactor); } } return CTX_OK; } // *** Close raw data file CTX_ErrCode RawDataCTX::CloseDataFile() { if(!FileOpen) return CTX_NOTOPEN; if (fclose(Rawfile) == EOF) { if(!Silent) perror("Could not close file"); return CTX_FCLOSE; } delete[] BStruct; delete[] Data; FileOpen = false; return CTX_OK; } // *** Read next event from file CTX_ErrCode RawDataCTX::ReadEvent(unsigned int EventNo, FILE *fptr) { if (!FileOpen) { if(!Silent) printf("Error: No data file open.\n"); return CTX_NOTOPEN; } // Move file pointer to desired event header (if zero read next event) bool SEEK_OK=true; if (EventNo!=0 && fseek(Rawfile, RHeader->RunHeaderSize+RHeader->BoardStructureSize*RHeader->NBoards, SEEK_SET) != 0) SEEK_OK=false; while(SEEK_OK) { if (fread(EHeader, RHeader->EventHeaderSize, 1, Rawfile) != 1) { if (feof(Rawfile)==0) { if (!Silent) printf("Error: Could not read event header\n"); return CTX_EHEADER; } else return CTX_EOF; } else { if (EHeader->EventNumber==EventNo || EventNo==0) break; if (fseek(Rawfile, EHeader->EventSize, SEEK_CUR) != 0) SEEK_OK = false; } } if(!SEEK_OK) { if(!Silent) printf("Error: Could not move to requested event\n"); return CTX_SEEK; } // Allocate memory for event data (enlarge if necessary) if(Data==NULL || (sizeof(Data) < EHeader->EventSize)) { delete[] Data; Data = new char[EHeader->EventSize]; } // Read event data if(fread(Data, 1, EHeader->EventSize, Rawfile) != EHeader->EventSize) { if(!Silent) printf("Error: Could not read (all) event data\n"); return CTX_DATA; } // If requested, print event header to file if(fptr != NULL) { fprintf(fptr, "Event number: %u\n", EHeader->EventNumber); fprintf(fptr, "Time [sec]: %u - UTC %s", EHeader->Second, asctime(gmtime((time_t *) &EHeader->Second))); fprintf(fptr, "Time [usec]: %u\n", EHeader->Microsecond); fprintf(fptr, "Trigger type: 0x%0X\n", EHeader->TriggerType); fprintf(fptr, "Size [byte]: %u\n", EHeader->EventSize); } return CTX_OK; } // *** Check if file currently open bool RawDataCTX::IsFileOpen() { return FileOpen; }