// $Id$ // // Author: David Lawrence July 14, 2006 // // // DEventSourceET methods // #include #include #include #include using namespace std; #include #include #include #include #include #include "DEventSourceET.h" // Sorting functions used to put TDC and ADC hits in geographic order bool ADCsort(DADC* const &thit1, DADC* const &thit2) { if(thit1->crate != thit2->crate)return thit1->crate < thit2->crate; if(thit1->slot != thit2->slot)return thit1->slot < thit2->slot; return thit1->channel < thit2->channel; } bool TDCsort(DTDC* const &thit1, DTDC* const &thit2) { if(thit1->crate != thit2->crate)return thit1->crate < thit2->crate; if(thit1->channel != thit2->channel)return thit1->channel < thit2->channel; if (thit1->tdc != thit2->tdc) return thit1->tdc < thit2->tdc; return thit1->slot < thit2->slot; } //---------------- // Constructor //---------------- DEventSourceET::DEventSourceET(const char* source_name):JEventSource(source_name) { /// Constructor for DEventSourceET object handle = 0; pthread_mutex_init(&buffer_mutex, NULL); buff_size = 500*1024; // Set buffer size to 50k runnumber = 0; string source(source_name); if(source.substr(0,3) == "ET:"){ OpenET(source); }else{ OpenFile(source); } } //---------------- // Destructor //---------------- DEventSourceET::~DEventSourceET() { // Close file/ET switch(source_type){ case SOURCE_TYPE_FILE: if(handle)evClose(handle); break; case SOURCE_TYPE_ET: break; } // Delete all buffers pthread_mutex_lock(&buffer_mutex); for(unsigned int i=0; i fields; unsigned int cutAt; string str = source; while( (cutAt = str.find(":")) != str.npos ){ if(cutAt > 0)fields.push_back(str.substr(0,cutAt)); str = str.substr(cutAt+1); } if(str.length() > 0)fields.push_back(str); string session = fields.size()>1 ? fields[1]:"none"; string station = fields.size()>2 ? fields[2]:"VIEWER"; int Nevents = fields.size()>3 ? atoi(fields[3].c_str()):1; cout<<"Opening ET session:"<length; if(event_size>buff_size){ cerr<<__FILE__<<":"<<__LINE__<<" Event size larger than buffer size!("< "<::iterator iter = in_use_buffers.begin(); for(; iter!=in_use_buffers.end(); iter++){ if(*iter == buff){ in_use_buffers.erase(iter); break; } } unused_buffers.push_back(buff); pthread_mutex_unlock(&buffer_mutex); } //---------------- // GetObjects //---------------- jerror_t DEventSourceET::GetObjects(JEvent &event, JFactory_base *factory) { /// This gets called through the virtual method of the /// JEventSource base class. It creates the objects of the type /// on which factory is based. // This is not done in the most efficient way. Here, we parse through // the entire buffer for each type of object requested. Ideally, we // would go through it only once. However, we don't have the factory // pointers readily available. It is also cumbersome to store the // objects until asked for since we would need to do it in a mult-thread // aware type way. The parsing of the EVIO data is relatively // fast though compared to the rest of the analysis so we take the // hit. // We must have a factory to hold the data if(!factory)throw RESOURCE_UNAVAILABLE; // The ref field of the JEvent is just the event buffer pointer. char *buff = (char*)event.GetRef(); if(!buff)throw RESOURCE_UNAVAILABLE; // Get name of data class we're trying to extract string dataClassName = factory->dataClassName(); string tag = factory->Tag(); if(dataClassName =="DTrigger" && tag=="") return Extract_DTrigger(buff, dynamic_cast*>(factory)); if(dataClassName =="DADC" && tag=="") return Extract_DADC(buff, dynamic_cast*>(factory)); if(dataClassName =="DTDC"){ // We're more efficient extracting TDC info for each crate // individually if(tag=="") return Extract_DTDC(buff, dynamic_cast*>(factory)); if(tag=="tage") return Extract_DTDC_tage(buff, dynamic_cast*>(factory)); if(tag=="tagt") return Extract_DTDC_tagt(buff, dynamic_cast*>(factory)); } if(dataClassName == "DEPICS") return Extract_DEPICS(buff, dynamic_cast*>(factory)); return OBJECT_NOT_AVAILABLE; } //---------------- // Extract_EventNumber //---------------- unsigned long DEventSourceET::Extract_EventNumber(const char *buff) { /// Scan through the given event buffer and find the eventid /// bank (if any) and get the event number from it. If no /// eventid bank is found, return 0, otherwise, the event number /// is returned. // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; // Loop over inner banks. const unsigned long *end_ptr = iptr + length-1; if(num!=0xcc)return 0; if(tag>=0x10)return 0; // only want physics events int i = 0; while(iptr100)break; // safeguard against infinite loops } return 0; } //---------------- // Extract_RunNumber //---------------- unsigned long DEventSourceET::Extract_RunNumber(const char *buff) { /// Look for Trigger Supervisor bank from which to extract run number // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; // Loop over inner banks. const unsigned long *end_ptr = iptr + length-1; if(num!=0xcc)return 0; if(tag>=0x10)return 0; // only want physics events int i = 0; while(iptr>8) == (head_ts2>>8)){ iptr+=2; // skip to start of TS2 data iptr++; // latch iptr++; // live1 iptr++; // live2 iptr++; // time if(*iptr != 0)runnumber = *iptr; break; } iptr += length+1; if(i++>100)break; // safeguard against infinite loops } // Note that runnumber is a member of DEventSourceET. If no // run number is found, we just recycle the last value. This // is useful in particular for EPICS events which have no run // number. return runnumber; } //---------------- // Extract_DTrigger //---------------- jerror_t DEventSourceET::Extract_DTrigger(const char *buff, JFactory *fac) { /// Get trigger information from Trigger Supervisor bank if(!fac)return OBJECT_NOT_AVAILABLE; vector data; // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; // Loop over inner banks. const unsigned long *end_ptr = iptr + length-1; if(num!=0xcc)return OBJECT_NOT_AVAILABLE; if(tag>=0x10)return OBJECT_NOT_AVAILABLE; // only want physics events int i = 0; while(iptr>8) == (head_ts2>>8)){ iptr+=2; DTrigger *trig = new DTrigger; trig->latch = *iptr++; trig->live1 = *iptr++; trig->live2 = *iptr++; data.push_back(trig); fac->CopyTo(data); return NOERROR; } iptr += length+1; if(i++>100)break; // safeguard against infinite loops } return OBJECT_NOT_AVAILABLE; } //---------------- // Extract_DADC //---------------- jerror_t DEventSourceET::Extract_DADC(const char *buff, JFactory *fac) { if(!fac)return OBJECT_NOT_AVAILABLE; vector data; // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; // Loop over inner banks. These should be EventID bank, and // ROC banks const unsigned long *end_ptr = iptr + length-1; if(num!=0xcc)return OBJECT_NOT_AVAILABLE; if(tag>=0x10)return OBJECT_NOT_AVAILABLE; // only want physics events int i = 0; while(iptr>16; int type = (head>>8)&0xff; if(tag==0x1 && type==0x1){ // This is from gluex_vme1 which has 2 v792 QDC and // 2 F1 TDC modules. The buffer from iptr+2 to // iptr+2+length-1 needs to be looped over to extract // the data for all modules const unsigned long *p = iptr + 2; const unsigned long *end_p = p + length-1; int adc_slot = 18; while(p < end_p){ // QCD(ADC) data is marked by 0xadc0c0da followed // by 0x00000000. TDC data is marked by 0xcdc0c0da // also followed by 0x00000000. if(*p == 0xadc0c0da){ // v792 QDC data p+=2; // advance to first word of data from module Extract_v792(tag, adc_slot++, p, data); // p is advanced past end of v792 data }else if(*p == 0xcdc0c0da){ // F1 TDC data p+=4; // There must be at least 4 words here to skip! }else{ // Hmmm... don't know this word. Advance 2 words since // markers should lie on 8-byte boundaries p+=2; } } } iptr += length+1; if(i++>100)break; // safeguard against infinite loops } sort(data.begin(), data.end(), ADCsort); fac->CopyTo(data); return NOERROR; } //---------------- // Extract_v792 //---------------- jerror_t DEventSourceET::Extract_v792(int roc_id, int adc_slot, const unsigned long* &iptr, vector &data) { unsigned long head = *iptr++; int nhits = (head>>8)&0x3f; for(int i=0; icrate = roc_id; adc->slot = adc_slot; adc->channel = (*iptr>>16)&0x1f; adc->adc = (*iptr)&0x0fff; adc->overflow = ((*iptr)>>12)&0x01; data.push_back(adc); } *iptr++; // skip trailer word return NOERROR; } //---------------- // Extract_DTDC //---------------- jerror_t DEventSourceET::Extract_DTDC(const char *buff, JFactory *fac) { if(!fac)return OBJECT_NOT_AVAILABLE; vector data; // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; // Loop over inner banks. These should be EventID bank, and // ROC banks const unsigned long *end_ptr = iptr + length-1; if(num!=0xcc)return OBJECT_NOT_AVAILABLE; if(tag>=0x10)return OBJECT_NOT_AVAILABLE; // only want physics events int i = 0; while(iptr>16; int type = (head>>8)&0xff; if(tag==0x1 && type==0x1){ // This is from gluex_vme1 which has 2 v792 QDC and // 2 F1 TDC modules. The buffer from iptr+2 to // iptr+2+length-1 needs to be looped over to extract // the data for all modules const unsigned long *p = iptr + 2; const unsigned long *end_p = p + length-1; while(p < end_p){ // QCD(ADC) data is marked by 0xadc0c0da followed // by 0x00000000. TDC data is marked by 0xcdc0c0da // also followed by 0x00000000. if(*p == 0xadc0c0da){ // v792 QDC data p+=4; // There must be at least 4 words here to skip! }else if(*p == 0xcdc0c0da){ // F1 TDC data p+=2; // advance to first word of data from module Extract_f1tdc(tag, (*p>>27), p, data); // p is advanced past end of v792 data }else{ // Hmmm... don't know this word. Advance 2 words since // markers should lie on 8-byte boundaries p+=2; } } } iptr += length+1; if(i++>100)break; // safeguard against infinite loops } sort(data.begin(), data.end(), TDCsort); fac->CopyTo(data); return NOERROR; } //---------------- // Extract_f1tdc //---------------- jerror_t DEventSourceET::Extract_f1tdc(int roc_id, int tdc_slot, const unsigned long* &iptr, vector &data) { int n=0; for(; n<1000; n++, iptr++){ if(((*iptr>>23)&0x1) != 0x1){ // header/trailer word. // NOTE: The F1 TDC will always put out a header word // for chip=0, channel=0. It will also put one out for // every chip whose "trigger time" differs by even one // bit, regardless of whether that channel had any data // for the event. A trailer for chip=7, channel=7 is also // always output so we use that to tell when we are done. if((*iptr&0x3f) == 0x3f)break; // chip 7, channel 7 continue; // skip header words } DTDC *tdc = new DTDC; tdc->crate = roc_id; tdc->slot = (*iptr>>27)&0x1f;; tdc->channel = ((*iptr>>16)&0x3f)>>1; // the last >>1 is to ignoe the LSB since we're in hi res mode tdc->tdc = (*iptr)&0xffff; data.push_back(tdc); } iptr++; // skip last trailer word. // if we're not on an 8-byte boundary, go ahead and skip // one more word to put us on one. The F1TDC pads an extra // word at the end of the data to do this so we can just // ignore it. if((n%2) == 0)iptr++; return NOERROR; } //---------------- // Extract_DTDC_tage //---------------- jerror_t DEventSourceET::Extract_DTDC_tage(const char *buff, JFactory *fac) { if(!fac)return OBJECT_NOT_AVAILABLE; vector data; // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; // Loop over inner banks. These should be EventID bank, and // ROC banks const unsigned long *end_ptr = iptr + length-1; if(num!=0xcc)return OBJECT_NOT_AVAILABLE; if(tag>=0x10)return OBJECT_NOT_AVAILABLE; // only want physics events int i = 0; while(iptr>16; int type = (head>>8)&0xff; if(tag==15 && type==0x1){ // This is from the TAGE crate const unsigned long *p = iptr + 2; const unsigned long *end_p = p + length-1; while(p < end_p){ // If none of bits 16-26 are set, then this is most // likely a header word. skip it. if((((*p)>>16)&0x3ff) == 0){p++; continue;} DTDC *tdc = new DTDC; tdc->crate=15; tdc->slot = (*p)>>27; tdc->channel = ((*p)>>17)&0x7f; tdc->tdc = (*p)&0xffff; data.push_back(tdc); p++; } } iptr += length+1; if(i++>100)break; // safeguard against infinite loops } sort(data.begin(), data.end(), TDCsort); fac->CopyTo(data); return NOERROR; } //---------------- // Extract_DTDC_tagt //---------------- jerror_t DEventSourceET::Extract_DTDC_tagt(const char *buff, JFactory *fac) { if(!fac)return OBJECT_NOT_AVAILABLE; vector data; // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; // Loop over inner banks. These should be EventID bank, and // ROC banks const unsigned long *end_ptr = iptr + length-1; if(num!=0xcc)return OBJECT_NOT_AVAILABLE; if(tag>=0x10)return OBJECT_NOT_AVAILABLE; // only want physics events int i = 0; while(iptr>16; int type = (head>>8)&0xff; if(tag==16 && type==0x1){ // This is from the TAGE2 crate const unsigned long *p = iptr + 2; const unsigned long *end_p = p + length-1; int slot=0; unsigned long word_id=0; while(p < end_p){ word_id= ((*p)>>27)&0x1f; if (word_id&0x8){ //Global header slot= (int)(*p)&0x1f; } else if (word_id&0x1){ //TDC header // do nothing for now } else if (word_id==0){ // Data word DTDC *tdc = new DTDC; tdc->crate=16; tdc->slot = slot; tdc->channel= ((*p)>>21)&0x1f; tdc->tdc = (*p)&0x1fffff; data.push_back(tdc); } p++; } } iptr += length+1; if(i++>100)break; // safeguard against infinite loops } sort(data.begin(), data.end(), TDCsort); fac->CopyTo(data); return NOERROR; } //---------------- // Extract_DEPICS //---------------- jerror_t DEventSourceET::Extract_DEPICS(const char *buff, JFactory *fac) { if(!fac)return OBJECT_NOT_AVAILABLE; vector data; // Get length tag, type, and num of outer bank const unsigned long *iptr = (const unsigned long*)buff; unsigned long length = *iptr++; // skip length word unsigned long head = *iptr++; int tag = head>>16; int num = head&0xff; if(num!=0xcc)return OBJECT_NOT_AVAILABLE; if(tag!=0x15)return OBJECT_NOT_AVAILABLE; // only want EPICS events unsigned int epics_time = *iptr++; // EPICS events were (accidentally) written with a 4-byte type // so that evio byte swaps the bank when it shouldn't. Actually, // it should for the first word which is the unix time, but the // remainder of the bank should not be. IF we are on a big endian // machine (e.g. PPC) then we need to swap the rest of the buffer // back. We only do this for files. typedef struct evfilestruct { FILE *file; int *buf; int *next; int left; int blksiz; int blknum; int rw; int magic; int evnum; /* last events with evnum so far */ int byte_swapped; } EVFILE; EVFILE *evfile = (EVFILE*)handle; if(evfile){ if(evfile->byte_swapped){ // Copied from evioswap.c (link errors calling swap_long()) char *d=(char*)iptr+4; for(unsigned long i=0; i items; string str((const char*)iptr); unsigned int cutAt; while( (cutAt = str.find("\n")) != str.npos ){ if(cutAt > 0)items.push_back(str.substr(0,cutAt)); str = str.substr(cutAt+1); } if(str.length() > 0)items.push_back(str); // Loop over items, splitting at "=" for(unsigned int i=0; iname = items[i].substr(0,cutAt); epics->value = items[i].substr(cutAt+1,items[i].size()); epics->time = epics_time; data.push_back(epics); } fac->CopyTo(data); return NOERROR; }