//private void Clusterizer::addHit(const unsigned int& pHitIndex) { debug("addHit"); uint64_t tEvent = _hitInfo[pHitIndex].eventNumber; unsigned short tCol = _hitInfo[pHitIndex].column-1; unsigned short tRow = _hitInfo[pHitIndex].row-1; unsigned short tFrame = _hitInfo[pHitIndex].frame; unsigned short tCharge = _hitInfo[pHitIndex].charge; _nEventHits++; if(tCharge>_maxHitCharge) // ommit hits with a Charge that is too high return; if(_nHits == 0) _framefirstHit = tFrame; if(tFrame > _framelastHit) _framelastHit = tFrame; if(tCol > _maxColHitPos) _maxColHitPos = tCol; if(tCol < _minColHitPos) _minColHitPos = tCol; if(tRow < _minRowHitPos) _minRowHitPos = tRow; if(tRow > _maxRowHitPos) _maxRowHitPos = tRow; if ((tCol > _maxColumn) || (tRow > _maxRow)){ std::stringstream tMessage; tMessage<<"The column/row value is out of range "<<tCol<<"/"<<tRow<<" > "<<_maxColumn<<"/"<<_maxRow<<". They have to start at 1!"; throw std::out_of_range(tMessage.str()); } if(_hitMap[(long)tCol + (long)tRow * (long)_maxColumn + (long)tFrame * (long)_maxColumn * (long)_maxRow] == -1){ _hitMap[(long)tCol + (long)tRow * (long)_maxColumn + (long)tFrame * (long)_maxColumn * (long)_maxRow] = tCharge; _hitIndexMap[(long)tCol + (long)tRow * (long)_maxColumn + (long)tFrame * (long)_maxColumn * (long)_maxRow] = pHitIndex; _nHits++; } else warning("addHit: event "+LongIntToStr(tEvent)+", attempt to add the same hit col/row/rel.frame="+IntToStr(tCol)+"/"+IntToStr(tRow)+"/"+IntToStr(tFrame)+" again, ignored!"); if (tCharge >= 0){ _chargeMap[(long)tCol + (long)tRow * (long)_maxColumn + (long)tCharge * (long)_maxColumn * (long)_maxRow] = tCharge; } if(_createClusterHitInfoArray){ if (_clusterHitInfo == 0) throw std::runtime_error("Cluster hit array is not defined and cannot be filled"); _clusterHitInfo[pHitIndex].eventNumber = _hitInfo[pHitIndex].eventNumber; _clusterHitInfo[pHitIndex].frame = _hitInfo[pHitIndex].frame; _clusterHitInfo[pHitIndex].column = _hitInfo[pHitIndex].column; _clusterHitInfo[pHitIndex].row = _hitInfo[pHitIndex].row; _clusterHitInfo[pHitIndex].charge = _hitInfo[pHitIndex].charge; _clusterHitInfo[pHitIndex].isSeed = 0; _clusterHitInfo[pHitIndex].clusterSize = 666; _clusterHitInfo[pHitIndex].nCluster = 666; } }
void Interpret::addEvent() { if (Basis::debugSet()) { std::stringstream tDebug; tDebug << "addEvent() " << _nEvents; debug(tDebug.str()); } if (tTotalHits == 0) { _nEmptyEvents++; if (_createEmptyEventHits) { addEventErrorCode(__NO_HIT); addHit(0, 0, 0, 0, 0, 0); } } if (tTriggerWord == 0) { addEventErrorCode(__NO_TRG_WORD); if (_firstTriggerNrSet) // set the last existing trigger number for events without trigger number if trigger numbers exist tEventTriggerNumber = _lastTriggerNumber; } if (tTriggerWord > 1) { addTriggerErrorCode(__TRG_NUMBER_MORE_ONE); if (Basis::warningSet()) warning(std::string("addEvent: # trigger words > 1 at event " + LongIntToStr(_nEvents))); } if (_useTdcTriggerTimeStamp && tTdcTimeStamp >= 254) addEventErrorCode(__TDC_OVERFLOW); storeEventHits(); if (tTotalHits > _nMaxHitsPerEvent) _nMaxHitsPerEvent = tTotalHits; histogramTriggerErrorCode(); histogramErrorCode(); if (_createMetaDataWordIndex) { if (_actualMetaWordIndex < _metaWordIndexLength) { _metaWordIndex[_actualMetaWordIndex].eventIndex = _nEvents; _metaWordIndex[_actualMetaWordIndex].startWordIdex = _startWordIndex; _metaWordIndex[_actualMetaWordIndex].stopWordIdex = _nDataWords - 1; _startWordIndex = _nDataWords - 1; _actualMetaWordIndex++; } else { std::stringstream tInfo; tInfo << "Interpret::addEvent(): meta word index array is too small " << _actualMetaWordIndex << ">=" << _metaWordIndexLength; throw std::out_of_range(tInfo.str()); } } _nEvents++; resetEventVariables(); }
void Interpret::addEventErrorCode(const unsigned short& pErrorCode) { if ((tErrorCode & pErrorCode) != pErrorCode) { //only add event error code if its not already set if (Basis::debugSet()) { std::stringstream tDebug; tDebug << "addEventErrorCode: " << (unsigned int) pErrorCode << " "; switch ((unsigned int) pErrorCode) { case __NO_ERROR: { tDebug << "NO ERROR"; break; } case __HAS_SR: { tDebug << "EVENT HAS SERVICE RECORD"; break; } case __NO_TRG_WORD: { tDebug << "EVENT HAS NO TRIGGER NUMBER"; break; } case __NON_CONST_LVL1ID: { tDebug << "EVENT HAS NON CONST LVL1ID"; break; } case __EVENT_INCOMPLETE: { tDebug << "EVENT HAS TOO LESS DATA HEADER"; break; } case __UNKNOWN_WORD: { tDebug << "EVENT HAS UNKNOWN WORDS"; break; } case __BCID_JUMP: { tDebug << "EVENT HAS JUMPING BCID NUMBERS"; break; } case __TRG_ERROR: { tDebug << "EVENT HAS AN EXTERNAL TRIGGER ERROR"; break; } case __TRUNC_EVENT: { tDebug << "EVENT HAS TOO MANY HITS AND WAS TRUNCATED"; break; } case __TDC_WORD: { tDebug << "EVENT HAS TDC WORD"; break; } case __MANY_TDC_WORDS: { tDebug << "EVENT HAS MORE THAN ONE VALID TDC WORD"; break; } case __TDC_OVERFLOW: { tDebug << "EVENT HAS TDC OVERFLOW"; break; } } debug(tDebug.str() + "\t" + LongIntToStr(_nEvents)); } tErrorCode |= pErrorCode; } }
bool Interpret::getHitsfromDataRecord(const unsigned int& pSRAMWORD, int& pColHit1, int& pRowHit1, int& pTotHit1, int& pColHit2, int& pRowHit2, int& pTotHit2) { //if (DATA_RECORD_MACRO(pSRAMWORD)){ //SRAM word is data record //check if the hit values are reasonable if ((DATA_RECORD_TOT1_MACRO(pSRAMWORD) == 0xF) || (DATA_RECORD_COLUMN1_MACRO(pSRAMWORD) < RAW_DATA_MIN_COLUMN) || (DATA_RECORD_COLUMN1_MACRO(pSRAMWORD) > RAW_DATA_MAX_COLUMN) || (DATA_RECORD_ROW1_MACRO(pSRAMWORD) < RAW_DATA_MIN_ROW) || (DATA_RECORD_ROW1_MACRO(pSRAMWORD) > RAW_DATA_MAX_ROW)) { warning(std::string("getHitsfromDataRecord: data record values (1. Hit) out of bounds at event " + LongIntToStr(_nEvents))); return false; } if ((DATA_RECORD_TOT2_MACRO(pSRAMWORD) != 0xF) && ((DATA_RECORD_COLUMN2_MACRO(pSRAMWORD) < RAW_DATA_MIN_COLUMN) || (DATA_RECORD_COLUMN2_MACRO(pSRAMWORD) > RAW_DATA_MAX_COLUMN) || (DATA_RECORD_ROW2_MACRO(pSRAMWORD) < RAW_DATA_MIN_ROW) || (DATA_RECORD_ROW2_MACRO(pSRAMWORD) > RAW_DATA_MAX_ROW))) { warning(std::string("getHitsfromDataRecord: data record values (2. Hit) out of bounds at event " + LongIntToStr(_nEvents))); return false; } //set first hit values if (DATA_RECORD_TOT1_MACRO(pSRAMWORD) <= _maxTot) { //ommit late/small hit and no hit TOT values for the TOT(1) hit pColHit1 = DATA_RECORD_COLUMN1_MACRO(pSRAMWORD); pRowHit1 = DATA_RECORD_ROW1_MACRO(pSRAMWORD); pTotHit1 = DATA_RECORD_TOT1_MACRO(pSRAMWORD); } //set second hit values if (DATA_RECORD_TOT2_MACRO(pSRAMWORD) <= _maxTot) { //ommit late/small hit and no hit (15) tot values for the TOT(2) hit pColHit2 = DATA_RECORD_COLUMN2_MACRO(pSRAMWORD); pRowHit2 = DATA_RECORD_ROW2_MACRO(pSRAMWORD); pTotHit2 = DATA_RECORD_TOT2_MACRO(pSRAMWORD); } return true; //} //return false; }
void Interpret::addHit(const unsigned char& pRelBCID, const unsigned short int& pLVLID, const unsigned char& pColumn, const unsigned short int& pRow, const unsigned char& pTot, const unsigned short int& pBCID) //add hit with event number, column, row, relative BCID [0:15], tot, trigger ID { if (tHitBufferIndex < __MAXHITBUFFERSIZE) { _hitBuffer[tHitBufferIndex].eventNumber = _nEvents; _hitBuffer[tHitBufferIndex].triggerNumber = tEventTriggerNumber; _hitBuffer[tHitBufferIndex].relativeBCID = pRelBCID; _hitBuffer[tHitBufferIndex].LVLID = pLVLID; _hitBuffer[tHitBufferIndex].column = pColumn; _hitBuffer[tHitBufferIndex].row = pRow; _hitBuffer[tHitBufferIndex].tot = pTot; _hitBuffer[tHitBufferIndex].BCID = pBCID; _hitBuffer[tHitBufferIndex].TDC = tTdcCount; _hitBuffer[tHitBufferIndex].TDCtimeStamp = tTdcTimeStamp; _hitBuffer[tHitBufferIndex].serviceRecord = tServiceRecord; _hitBuffer[tHitBufferIndex].triggerStatus = tTriggerError; _hitBuffer[tHitBufferIndex].eventStatus = tErrorCode; if ((tErrorCode & __NO_HIT) != __NO_HIT) //only count not virtual hits tTotalHits++; tHitBufferIndex++; } else { addEventErrorCode(__TRUNC_EVENT); //too many hits in the event, abort this event, add truncated flac addEvent(); if (Basis::warningSet()) warning(std::string("addHit: Hit buffer overflow prevented by splitting events at event " + LongIntToStr(_nEvents)), __LINE__); } }
bool Interpret::interpretRawData(unsigned int* pDataWords, const unsigned int& pNdataWords) { if (Basis::debugSet()) { std::stringstream tDebug; tDebug << "interpretRawData with " << pNdataWords << " words at total word " << _nDataWords; debug(tDebug.str()); } _hitIndex = 0; _actualMetaWordIndex = 0; int tActualCol1 = 0; //column position of the first hit in the actual data record int tActualRow1 = 0; //row position of the first hit in the actual data record int tActualTot1 = -1; //tot value of the first hit in the actual data record int tActualCol2 = 0; //column position of the second hit in the actual data record int tActualRow2 = 0; //row position of the second hit in the actual data record int tActualTot2 = -1; //tot value of the second hit in the actual data record for (unsigned int iWord = 0; iWord < pNdataWords; ++iWord) { //loop over the SRAM words if (_debugEvents) { if (_nEvents >= _startDebugEvent && _nEvents <= _stopDebugEvent) setDebugOutput(); else setDebugOutput(false); setInfoOutput(false); setWarningOutput(false); // FIXME: do not unset this always } correlateMetaWordIndex(_nEvents, _dataWordIndex); _nDataWords++; _dataWordIndex++; unsigned int tActualWord = pDataWords[iWord]; //take the actual SRAM word tActualTot1 = -1; //TOT1 value stays negative if it can not be set properly in getHitsfromDataRecord() tActualTot2 = -1; //TOT2 value stays negative if it can not be set properly in getHitsfromDataRecord() if (getTimefromDataHeader(tActualWord, tActualLVL1ID, tActualBCID)) { //data word is data header if true is returned _nDataHeaders++; if (tNdataHeader > _NbCID - 1) { //maximum event window is reached (tNdataHeader > BCIDs, mostly tNdataHeader > 15), so create new event if (_alignAtTriggerNumber) { addEventErrorCode(__TRUNC_EVENT); //too many data header in the event, abort this event, add truncated flac if (Basis::warningSet()) warning(std::string("addHit: Hit buffer overflow prevented by splitting events at event " + LongIntToStr(_nEvents)), __LINE__); } addEvent(); } if (tNdataHeader == 0) { //set the BCID of the first data header tStartBCID = tActualBCID; tStartLVL1ID = tActualLVL1ID; } else { tDbCID++; //increase relative BCID counter [0:15] if (_fEI4B) { if (tStartBCID + tDbCID > __BCIDCOUNTERSIZE_FEI4B - 1) //BCID counter overflow for FEI4B (10 bit BCID counter) tStartBCID = tStartBCID - __BCIDCOUNTERSIZE_FEI4B; } else { if (tStartBCID + tDbCID > __BCIDCOUNTERSIZE_FEI4A - 1) //BCID counter overflow for FEI4A (8 bit BCID counter) tStartBCID = tStartBCID - __BCIDCOUNTERSIZE_FEI4A; } if (tStartBCID + tDbCID != tActualBCID) { //check if BCID is increasing by 1s in the event window, if not close actual event and create new event with actual data header if (tActualLVL1ID == tStartLVL1ID) //happens sometimes, non inc. BCID, FE feature, only abort the LVL1ID is not constant (if no external trigger is used or) addEventErrorCode(__BCID_JUMP); else if (_alignAtTriggerNumber || _alignAtTdcWord) //rely here on the trigger number or TDC word and do not start a new event addEventErrorCode(__BCID_JUMP); else { tBCIDerror = true; //BCID number wrong, abort event and take actual data header for the first hit of the new event addEventErrorCode(__EVENT_INCOMPLETE); } } if (!tBCIDerror && tActualLVL1ID != tStartLVL1ID) { //LVL1ID not constant, is expected for CMOS pulse trigger/hit OR, but not for trigger word triggering addEventErrorCode(__NON_CONST_LVL1ID); if (Basis::infoSet()) info("interpretRawData: LVL1 is not constant: " + IntToStr(tActualLVL1ID) + "!=" + IntToStr(tStartLVL1ID) + " at event " + LongIntToStr(_nEvents)); } } tNdataHeader++; //increase data header counter if (Basis::debugSet()) debug(std::string(" ") + IntToStr(_nDataWords) + " DH LVL1ID/BCID " + IntToStr(tActualLVL1ID) + "/" + IntToStr(tActualBCID) + "\t" + LongIntToStr(_nEvents)); } else if (isTriggerWord(tActualWord)) { //data word is trigger word, is first word of the event data if external trigger is present _nTriggers++; //increase the total trigger number counter if (!_alignAtTriggerNumber) { // first word is not always the trigger number if (tNdataHeader > _NbCID - 1) addEvent(); } else if (_firstTriggerNrSet) { // use trigger number for event building, first word is trigger word in data stream addEvent(); } tTriggerWord++; //trigger event counter increase if (!_useTriggerTimeStamp) tTriggerNumber = TRIGGER_NUMBER_MACRO_NEW(tActualWord); //actual trigger number else tTriggerNumber = TRIGGER_TIME_STAMP_MACRO(tActualWord); //actual trigger number is a time stamp if (Basis::debugSet()) { if (!_useTriggerTimeStamp) debug(std::string(" ") + IntToStr(_nDataWords) + " TR NUMBER " + IntToStr(tTriggerNumber) + "\t WORD " + IntToStr(tActualWord) + "\t" + LongIntToStr(_nEvents)); else debug(std::string(" ") + IntToStr(_nDataWords) + " TR TIME STAMP " + IntToStr(tTriggerNumber) + "\t WORD " + IntToStr(tActualWord) + "\t" + LongIntToStr(_nEvents)); } //TLU error handling if (!_firstTriggerNrSet) _firstTriggerNrSet = true; else if (!_useTriggerTimeStamp && (_lastTriggerNumber + 1 != tTriggerNumber) && !(_lastTriggerNumber == _maxTriggerNumber && tTriggerNumber == 0)) { addTriggerErrorCode(__TRG_NUMBER_INC_ERROR); if (Basis::warningSet()) warning("interpretRawData: Trigger Number not increasing by 1 (old/new): " + IntToStr(_lastTriggerNumber) + "/" + IntToStr(tTriggerNumber) + " at event " + LongIntToStr(_nEvents)); } if (tTriggerWord == 1) // event trigger number is trigger number of first trigger word within the event tEventTriggerNumber = tTriggerNumber; _lastTriggerNumber = tTriggerNumber; } else if (getInfoFromServiceRecord(tActualWord, tActualSRcode, tActualSRcounter)) { //data word is service record if (Basis::debugSet()) debug(std::string(" ") + IntToStr(_nDataWords) + " SR " + IntToStr(tActualSRcode) + " (" + IntToStr(tActualSRcounter) + ") at event " + LongIntToStr(_nEvents)); addServiceRecord(tActualSRcode, tActualSRcounter); addEventErrorCode(__HAS_SR); _nServiceRecords++; } else if (isTdcWord(tActualWord)) { //data word is a tdc word addTdcValue(TDC_COUNT_MACRO(tActualWord)); _nTDCWords++; if (_useTdcTriggerTimeStamp && (TDC_TRIG_DIST_MACRO(tActualWord) > _maxTdcDelay)){ // of the trigger distance if > _maxTdcDelay the TDC word does not belong to this event, thus ignore it if (Basis::debugSet()) debug(std::string(" ") + IntToStr(_nDataWords) + " TDC COUNT " + IntToStr(TDC_COUNT_MACRO(tActualWord)) + "\t" + LongIntToStr(_nEvents) + "\t TRG DIST TIME STAMP " + IntToStr(TDC_TRIG_DIST_MACRO(tActualWord)) + "\t WORD " + IntToStr(tActualWord)); continue; } //create new event if the option to align at TDC words is active AND the previous event has seen already all needed data headers OR the previous event was not aligned at a TDC word if (_alignAtTdcWord && _firstTdcSet && ( (tNdataHeader > _NbCID - 1) || ((tErrorCode & __TDC_WORD) != __TDC_WORD) )) { addEvent(); } _firstTdcSet = true; if ((tErrorCode & __TDC_WORD) == __TDC_WORD) { //if the event has already a TDC word set __MANY_TDC_WORDS if (!_useTdcTriggerTimeStamp) // the first TDC word defines the event TDC value addEventErrorCode(__MANY_TDC_WORDS); else if (TDC_TRIG_DIST_MACRO(tActualWord) != 255) { // in trigger time measurement mode the valid TDC word (tTdcTimeStamp != 255) defines the event TDC value if (tTdcTimeStamp != 255) // there is already a valid TDC word for this event addEventErrorCode(__MANY_TDC_WORDS); else { tTdcTimeStamp = TDC_TRIG_DIST_MACRO(tActualWord); tTdcCount = TDC_COUNT_MACRO(tActualWord); } } } else { addEventErrorCode(__TDC_WORD); tTdcCount = TDC_COUNT_MACRO(tActualWord); if (!_useTdcTriggerTimeStamp) tTdcTimeStamp = TDC_TIME_STAMP_MACRO(tActualWord); else tTdcTimeStamp = TDC_TRIG_DIST_MACRO(tActualWord); } if (tTdcCount == 0) addEventErrorCode(__TDC_OVERFLOW); if (Basis::debugSet()) { if (_useTdcTriggerTimeStamp) debug(std::string(" ") + IntToStr(_nDataWords) + " TDC COUNT " + IntToStr(TDC_COUNT_MACRO(tActualWord)) + "\t" + LongIntToStr(_nEvents) + "\t TRG DIST TIME STAMP " + IntToStr(TDC_TRIG_DIST_MACRO(tActualWord)) + "\t WORD " + IntToStr(tActualWord)); else debug(std::string(" ") + IntToStr(_nDataWords) + " TDC COUNT " + IntToStr(TDC_COUNT_MACRO(tActualWord)) + "\t" + LongIntToStr(_nEvents) + "\t TIME STAMP " + IntToStr(TDC_TIME_STAMP_MACRO(tActualWord)) + "\t WORD " + IntToStr(tActualWord)); } } else if (isDataRecord(tActualWord)) { //data word is data record if true is returned if (getHitsfromDataRecord(tActualWord, tActualCol1, tActualRow1, tActualTot1, tActualCol2, tActualRow2, tActualTot2)) { tNdataRecord++; //increase data record counter for this event _nDataRecords++; //increase total data record counter if (tActualTot1 >= 0) //add hit if hit info is reasonable (TOT1 >= 0) addHit(tDbCID, tActualLVL1ID, tActualCol1, tActualRow1, tActualTot1, tActualBCID); if (tActualTot2 >= 0) //add hit if hit info is reasonable and set (TOT2 >= 0) addHit(tDbCID, tActualLVL1ID, tActualCol2, tActualRow2, tActualTot2, tActualBCID); if (Basis::debugSet()) { std::stringstream tDebug; tDebug << " " << _nDataWords << " DR COL1/ROW1/TOT1 COL2/ROW2/TOT2 " << tActualCol1 << "/" << tActualRow1 << "/" << tActualTot1 << " " << tActualCol2 << "/" << tActualRow2 << "/" << tActualTot2 << " rBCID " << tDbCID << "\t" << _nEvents; debug(tDebug.str()); } } } else { if (isOtherWord(tActualWord)) { //other for hit interpreting uninteressting data, else data word unknown _nOtherWords++; if (Basis::debugSet()) { unsigned int tAddress = 0; bool isShiftRegister = false; unsigned int tValue = 0; if (isAddressRecord(tActualWord, tAddress, isShiftRegister)) { if (isShiftRegister) debug(std::string(" ") + IntToStr(_nDataWords) + " ADDRESS RECORD SHIFT REG. " + IntToStr(tAddress) + " WORD " + IntToStr(tActualWord) + "\t" + LongIntToStr(_nEvents)); else debug(std::string(" ") + IntToStr(_nDataWords) + " ADDRESS RECORD GLOBAL REG. " + IntToStr(tAddress) + " WORD " + IntToStr(tActualWord) + "\t" + LongIntToStr(_nEvents)); } if (isValueRecord(tActualWord, tValue)) { debug(std::string(" ") + IntToStr(_nDataWords) + " VALUE RECORD " + IntToStr(tValue) + "\t" + LongIntToStr(_nEvents)); } } } else { addEventErrorCode(__UNKNOWN_WORD); _nUnknownWords++; if (Basis::warningSet()) warning("interpretRawData: " + IntToStr(_nDataWords) + " UNKNOWN WORD " + IntToStr(tActualWord) + " at event " + LongIntToStr(_nEvents)); if (Basis::debugSet()) debug(std::string(" ") + IntToStr(_nDataWords) + " UNKNOWN WORD " + IntToStr(tActualWord) + " at event " + LongIntToStr(_nEvents)); } } if (tBCIDerror) { //tBCIDerror is raised if BCID is not increasing by 1, most likely due to incomplete data transmission, so start new event, actual word is data header here if (Basis::warningSet()) warning("interpretRawData " + IntToStr(_nDataWords) + " BCID ERROR at event " + LongIntToStr(_nEvents)); addEvent(); _nIncompleteEvents++; getTimefromDataHeader(tActualWord, tActualLVL1ID, tStartBCID); tNdataHeader = 1; //tNdataHeader is already 1, because actual word is first data of new event tStartBCID = tActualBCID; tStartLVL1ID = tActualLVL1ID; } } return true; }