//----------------------------------------------------------------------- // The GSI Online Offline Object Oriented (Go4) Project // Experiment Data Processing at EE department, GSI //----------------------------------------------------------------------- // Copyright (C) 2000- GSI Helmholtzzentrum für Schwerionenforschung GmbH // Planckstr. 1, 64291 Darmstadt, Germany // Contact: http://go4.gsi.de //----------------------------------------------------------------------- // This software can be used under the license agreements as stated // in Go4License.txt file which is part of the distribution. //----------------------------------------------------------------------- //////////////////////////////////// // Event Source for XSYS data format // V 1.0 24-Jan-2011 // Joern Adamczewski-Musch, GSI Darmstadt // j.adamczewski@gsi.de #ifndef TXSYSEVENTSOURCE_H #define TXSYSEVENTSOURCE_H #include "TGo4EventSource.h" #include #include "TGo4MbsEvent.h" #include "Riostream.h" using namespace std; #define XSYS_BUFSIZE 0x10000 #define XSYS_PROCID 0x55 class TXSYSRawEvent; class TGo4UserSourceParameter; #pragma pack(push, 1) /* JAM: * Taken from User Reference to XSYS\IUCF: Event-Analysis Language (EVAL) * The buffer header consists of two or more words. The first word is always total number of bytes in the header and data which follow; it is always even. This limits each buffer to 65534 bytes; if this is smaller than the physical buffer, then the buffer is usually padded with zeros. The second word contains a buffer-identification code in bits 15-10. The buffer-identification code may be '111001'B (binary) or '111010'B. Buffers originating in the MBD use the first form. Four-byte buffer header. If the code is '111001'B, then the buffer header is four bytes long, and bits 9-0 of the second word contains an integer which represents the number of words after the buffer header which are part of an event record which was started in the previous buffer. This number is also the offset in words from the buffer header to the first event-header word in the current buffer. The offset is zero if the event header immediately follows the buffer header. This provides verification for event records which span buffers. +---------------+---------------+ | buffer size (bytes) = 2*N | word 0 +---------------+---------------+ | 111001 | offset(words) = M | word 1 +---------------+---------------+ | M data words of last event | word 2:(M+1) +---------------+---------------+ | first event header | word M+2 . . . | last word in buffer | word N-1 +---------------+---------------+ Eight-byte buffer header. If the code is '111010'B, then the buffer header is eight or more bytes long, and bits 9-0 of the second word contains an even integer which represents the number of bytes in the buffer header. The third word contains an even which represents the number of bytes after the buffer header which are part of an event record which was started in the previous buffer. This number is also the offset in bytes from the buffer header to the first event-header word in the current buffer. The offset is zero if the event header immediately follows the buffer header. +---------------+---------------+ | buffer size (bytes) = 2*N | word 0 +---------------+---------------+ | 111010 |hdr size(bytes)=2*H| word 1 +---------------+---------------+ | offset (bytes) to next ev=2*M| word 2 +---------------+---------------+ | reserved | word 3 +---------------+---------------+ | extra header words if any | word 4+ +---------------+---------------+ . . . +---------------+---------------+ | M data words of last event | word H . . . +---------------+---------------+ | first event header | word H+M . . . | last word in buffer | word N-1 +---------------+---------------+ */ struct XSYS_buffer_head { Short_t fBufsize; Short_t fIdentity; Short_t fOffset; }; /* * The event header consists of two words: (1) event size in bytes; (2) flag and event-identification word. It is normally unnecessary for user code to refer to the header words; the fixed code generated by EVAL automatically scans each buffer for the event headers, and branches to user code according to the information in the identification word. The second header word is of the form '10ffffff eeeeeeee'B (binary), where the 'ffffff'B bits represent flag bits set by the MBD, and the 'eeeeeeee'B bits represent the MBD channel or event-stream number. Flag bits are usually zero; when polarization is controlled by the acquisition program, the low three flag bits represent the spin code. MBD channel numbers are in the range 0-7; event numbers 240-255 are reserved for software-generated "control" events. For buffers originating from the MBD, the two words of an event header are always contained in the same buffer; if only one word remains in a buffer, the next event header starts at the beginning of the next buffer. +---------------+---------------+ | event size (bytes) = 2*N | word 0 +---------------+---------------+ | 10ffffff | eeeeeeee | word 1 +---------------+---------------+ | first data word | word 2 . . . | last data word | word N-1 +---------------+---------------+ * */ struct XSYS_event_head { Short_t fEventsize; Short_t fFlag; }; /* Begin/Halt Record The data-acquisition process (XSORT) generates two software event records that are inserted into the event stream. The first is a BEGIN record, which is always the first event in an event data file, and the second is a HALT record, which is the last event of the file. The event identification numbers are 254 and 255, respectively. The replay process (XTPSORT) uses the BEGIN record when the file is opened to get the run number and title, but these records are not required for replay, unless user code requires them. If the HALT record is missing when an EOF is read, the replay process will enter the user event HALT routine, if it exists, with a dummy HALT record to ensure proper user processing. +---------------+---------------+ | event size (bytes) = 2*N | word 0 +---------------+---------------+ | 10ffffff | 1111111e | word 1 +---------------+---------------+ | byte offset to text | word 2 +---------------+---------------+ | reserved | word 3 +---------------+---------------+ | VMS time quadword | words 4-7 +---------------+---------------+ | run number longword | words 8-9 +---------------+---------------+ | run flag bits longword | words 10-11 +---------------+---------------+ | system id longword | words 12-13 +---------------+---------------+ | XSYS version longword | words 14-15 +---------------+---------------+ | buffer counter longwords| words 16-47 +---------------+---------------+ | event counter longwords | words 48- +---------------+---------------+ | ASCII text string | bytes (offset...) | . . . | +---------------+---------------+ A typical BEGIN/HALT record may be 416 bytes; note that words are numbered beginning at 0 above, which corresponds to word -1 in a FORMAT statement. The byte-offset-to-text indicates where the text records begin; this can be as low as 32 if counter longwords are not present, and it indicates how many counter longwords are actually present. The time quadword is the time in 100-nanosecond units since 1858.11.17 00:00 (astronomical base). The following bits are defined for the flag longword: bit 0 = newrun - new run bit 1 = datclr - data clear bit 2 = wasclr - data was clear bit 3 = tpeopenout - output tape open bit 4 = tpepause - pause bits 8,9 = poltype - polarization type Event records written before 1987.10.01 only use bit 0. Buffer counters correspond to counters shown by STATUS display. Event counters indicate the number of events for each identification number beginning at event 0; large id numbers may not be counted here. The text portion is an ASCII string with embedded CR-LF and terminated by a FF; It contains a series of keywords, each followed by an equal sign and an ASCII value. */ #define XSYS_RECORD_NEWRUN (1 << 0) #define XSYS_RECORD_DTCLR (1 << 1) #define XSYS_RECORD_WSCLR (1 << 2) #define XSYS_RECORD_TPOPEN (1 << 3) #define XSYS_RECORD_TPPAUSE (1 << 4) struct XSYS_event_record { Short_t fEventsize; Short_t fFlag; Short_t fTextOffset; Short_t fReserved; ULong64_t fVMSTime; UInt_t fRunNumber; UInt_t fRunFlags; UInt_t fSystemId; UInt_t fXSYSVersion; bool IsNewRun(){return (fRunFlags & XSYS_RECORD_NEWRUN);} bool IsDataClear(){return (fRunFlags & XSYS_RECORD_DTCLR);} bool IsDataWasClear(){return (fRunFlags & XSYS_RECORD_WSCLR);} bool IsTapeOpen(){return (fRunFlags & XSYS_RECORD_TPOPEN);} bool IsTapePause(){return (fRunFlags & XSYS_RECORD_TPPAUSE);} Char_t GetPolarizationType(){return ((fRunFlags >> 8) & 0x02);} void Print() { cout <<"--- XSYS Event record dump ---"<< endl; cout <<" XSYS version :0x"<< (hex) << fXSYSVersion<< endl; cout <<" Run Number:0x"<<(hex) < Date from VMS time:"; cout <<" year:"<<(dec) <= JGREG) { jalpha = (int) (((ja - 1867216) - 0.25) / 36524.25); ja = ja + 1 + jalpha - jalpha / 4; } jb = ja + 1524; jc = (int) (6680.0 + ((jb - 2439870) - 122.1) / 365.25); jd = 365 * jc + jc / 4; je = (int) ((jb - jd) / 30.6001); day = jb - jd - (int) (30.6001 * je); month = je - 1; if (month > 12) month = month - 12; year = jc - 4715; if (month > 2) year--; if (year <= 0) year--; double modjulsecs=(double) mjd(year,month,day) * 86400.0;; double deltasecs= (((double) vmstime)/ 1.0e+7) - modjulsecs; int deltaints= (int) deltasecs; hour=(int) deltasecs/3600.0; minute= (int)(deltasecs- hour*3600.0) /60; secs= (int)(deltasecs - minute*60 - hour*3600); //ULong64_t micros= (ULong64_t) ( vmstime - (ULong64_t) (modjulsecs + (double)minute*60.0+ (double)hour*3600.0 + (double) secs)*1e+7); ULong64_t micros= (ULong64_t) ( vmstime - (ULong64_t) (modjulsecs + deltaints)*1e+7); // cout << "micros: "<<(dec)< 24) { hour -=24; day++; } } /* code stolen from j.mcnamara*/ int mjd(int dateyear,int datemonth,int dateday) { int y = dateyear; int m = datemonth - 1; int d = dateday - 678882; d += 146097 * (y / 400); y %= 400; if (m >= 2){ m -= 2; }else { m += 10; --y; } y += (m / 12); m %= 12; if (m < 0) { m += 12; --y; } d += (306 * m + 5) / 10; d += 146097 * (y / 400); y %= 400; if (y < 0) { y += 400; d -= 146097; } d += (y & 3) * 365; y >>= 2; d += 1461 * (y % 25); y /= 25; d += (y & 3) * 36524; return d; } }; #pragma pack(pop) class TXSYSEventSource : public TGo4EventSource { public: TXSYSEventSource(); /** Create source specifying values directly */ TXSYSEventSource(const char* name, const char* args, Int_t port); /** Creat source from setup within usersource parameter object */ TXSYSEventSource(TGo4UserSourceParameter* par); virtual ~TXSYSEventSource(); /** Open the file or connection. */ virtual Int_t Open(); /** Close the file or connection. */ virtual Int_t Close(); /** This method checks if event class is suited for the source */ virtual Bool_t CheckEventClass(TClass* cl); /** This methods actually fills the target event class which is passed as pointer. * Uses the latest event which is referenced * by fxEvent or fxBuffer. Does _not_ fetch a new event * from source, therefore one source event may be used * to fill several TXSYSEvent classes. To get a new * event call NextEvent() before this method.*/ virtual Bool_t BuildEvent(TGo4EventElement* dest); const char* GetArgs() const { return fxArgs.Data(); } void SetArgs(const char* arg) { fxArgs=arg; } Int_t GetPort() const { return fiPort; } void SetPort(Int_t val) { fiPort=val; } protected: /* read next buffer from file into memory*/ Bool_t NextBuffer(); /* Fill next xsys event from buffer location into output structure*/ Bool_t NextEvent(TGo4MbsEvent* target); /* Read from input file and check*/ std::streamsize ReadFile(Char_t* dest, size_t len); private: Bool_t fbIsOpen; /** Optional argument string */ TString fxArgs; /** Optional port number */ Int_t fiPort; /** file that contains the data in ascii format. */ std::ifstream* fxFile; //! /* true if next buffer needs to be read from file*/ Bool_t fbNeedNewBuffer; /* true if current event is spanning to next buffer*/ Bool_t fbIsBufferSpanning; /* for spanned events: remember current event ids*/ TGo4SubEventHeader10 fxSubevHead; /* working buffer*/ Char_t* fxBuffer; //! /* actual size of bytes read into buffer most recently*/ std::streamsize fxBufsize; //! /* cursor in buffer*/ Short_t* fxCursor; //! /* points to end of buffer*/ Short_t* fxBufEnd; //! /* cursor on data from spanned event in current buffer*/ Short_t* fxPrevEventCursor; //! /* Length of previous event data of spanned event in shorts*/ Int_t fiPrevEventLen; /* Length of current event data in shorts*/ Int_t fiEventLen; /* temp buffer for spanned event*/ Short_t* fxSpanBuffer; //! /* current position in span buffer*/ Short_t* fxSpanCursor; //! /* header of last buffer read*/ XSYS_buffer_head* fxBufhead; /* header of current event*/ XSYS_event_head* fxEventhead; ClassDef(TXSYSEventSource, 1) }; #endif //TGO4MBSSOURCE_H