#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace RAT { void TPBurstCut::BeginOfRun(DS::Run& run) { fPassFlag = true; fPushFlag = false; fDepletionPass = false; fCurrentBurstEnd = -1.0; DBLinkPtr fRun = DB::Get()->GetLink("RUN"); DS::UniversalTime stopTemp((UInt_t)fRun->GetI("stop_day"), (UInt_t)fRun->GetI("stop_sec"), (UInt_t)fRun->GetD("stop_nsc")); DS::UniversalTime startTemp((UInt_t)fRun->GetI("start_day"), (UInt_t)fRun->GetI("start_sec"), (UInt_t)fRun->GetD("start_nsc")); fStartTime = startTemp; fLength = 9999999999.0; fLength = ExtractTimeIndex(stopTemp); std::string burstType = ""; if (fBurstType == "ambe") { burstType = "_" + fBurstType; } else { if (fBurstType != "") { warn << "LivetimeCuts::BeginOfRun: burst type " << fBurstType <<" not recognized, default burst parameters will be used." << endl; } } if (fProcessPass == 1) {//Pass1: retrigger cut fLClean = DB::Get()->GetLink("DATACLEANING","retriggercut"); fTwinBurst = fLClean->GetI("twin_retrigger"); fNeventsBurst = 2; fNhitThreshold = 0; } else if (fProcessPass == 2) {//Pass2: nhit burst cut fLClean = DB::Get()->GetLink("DATACLEANING","tpburstcut"); fTwinBurst = fLClean->GetI("twin_nhitburst" + burstType); fNeventsBurst = static_cast( fLClean->GetI("nevents_nhitburst" + burstType) ); fNhitThreshold = static_cast( fLClean->GetI("nhit_threshold" + burstType) ); readTables("retriggercut", run); } else if (fProcessPass == 3) {//Pass3: CAEN Loss Burst Cut fLClean = DB::Get()->GetLink("DATACLEANING","caenlosscut"); fTwinBurst = fLClean->GetI("twin_caenloss"); fNeventsBurst = fLClean->GetI("nevents_caenlossburst");; fNhitThreshold = 0; readTables("retriggercut", run); } else if (fProcessPass == 4) { fDepletionPass = true; fLClean = DB::Get()->GetLink("DATACLEANING","tpburstcut"); fTwinBurst = fLClean->GetI("twin_nhitburst" + burstType); readTables("burstcut", run); } else if (fProcessPass == 5) { fDepletionPass = true; fLClean = DB::Get()->GetLink("DATACLEANING","caenlosscut"); fTwinBurst = fLClean->GetI("twin_caenloss"); readTables("caenlosscut", run); } } void TPBurstCut::readTables(std::string index, DS::Run& run) { std::vector fFirstEventsTemp; std::vector fLastRetriggersTemp; bool foundLocalTable = false; bool foundDBTable = false; bool foundJSONFile = false; std::string ratdbFileName; if (index == "burstcut") { ratdbFileName = "NhitBursts.ratdb"; } else if (index == "caenlosscut") { ratdbFileName = "CaenLossBursts.ratdb"; } foundLocalTable = DB::Get()->DB::LoadFile(ratdbFileName); if (foundLocalTable) { DBLinkPtr fData = DB::Get()->GetLink("LIVETIME_CUT", index); if (fData->GetI("cutapplied") == 1) { fFirstEventsTemp = fData->GetIArray("firstburst"); fLastRetriggersTemp = fData->GetIArray("lastburst"); foundDBTable = true; } } else { try{ DBLinkPtr fData = DB::Get()->GetLink("LIVETIME_CUT", index); if (fData->GetI("cutapplied") == 1) { fFirstEventsTemp = fData->GetIArray("firstburst"); fLastRetriggersTemp = fData->GetIArray("lastburst"); } foundDBTable = true; } catch(DBNotFoundError &e){ warn << "LivetimeCuts::BeginOfRun: Could not find table, Looking for .json file" << endl; } } if (!foundDBTable) {//Reading .json file for retriggers if ratdb not found. try { std::ostringstream fname; fname << "livetimecut_" << index <<"_" << run.GetRunID() << ".json"; std::vector contents = DBJsonLoader::parse(fname.str()); json::Value firstEventTemp = contents[0]->GetJSON("firstburst"); json::Value lastEventTemp = contents[0]->GetJSON("lastburst"); foundJSONFile = true; for (int j = 0; j < (int)firstEventTemp.getArraySize(); j++) { int firstgtid = firstEventTemp[j].cast(); int lastgtid = lastEventTemp[j].cast(); fFirstEventsTemp.push_back(firstgtid); fLastRetriggersTemp.push_back(lastgtid); } } catch(DBNotFoundError &e){ warn << "LivetimeCuts::BeginOfRun: Could not find retriggercut.json file" << endl; } } if ((foundLocalTable == 0) && (!foundDBTable) && (!foundJSONFile)) { warn << "LivetimeCuts::BeginOfRun: Could not find table info, table will not be applied.." << endl; } else { if (fDepletionPass) { fFirstEvents = fFirstEventsTemp; fLastEvents = fLastRetriggersTemp; } else { for (int i = 0 ; i < fFirstEventsTemp.size(); i++){ for (int gtid = fFirstEventsTemp[i] + 1; gtid <= fLastRetriggersTemp[i]; gtid++) { fRetriggerReadout.push_back(gtid); } } } } } void TPBurstCut::EndOfRun(DS::Run& run) { if (!fDepletionPass) { PushLastEvent(); } std::string index = ""; std::string ratdbFileName = ""; if (fProcessPass == 1) { index = "retriggercut"; ratdbFileName = "Retriggers.ratdb"; fBurstEvents.clear(); } else if ((fProcessPass == 2) || (fProcessPass == 4)) { index = "burstcut"; ratdbFileName = "NhitBursts.ratdb"; } else if ((fProcessPass == 3) || (fProcessPass == 5)) { index = "caenlosscut"; ratdbFileName = "CaenLossBursts.ratdb"; } std::ostringstream jsonName; jsonName << "livetimecut_" << index << "_" << run.GetRunID() << ".json"; DBTable table; table.SetJSON("burst", fBurstEvents); table.SetJSON("firstburst",fFirstEvents); table.SetJSON("lastburst",fLastEvents); table.SaveAs(jsonName.str()); RAT::DBTable BCTable("LIVETIME_CUT"); BCTable.SetI("version", 2); BCTable.SetPassNumber(-1); BCTable.SetRunRange(run.GetRunID(), run.GetRunID()); BCTable.SetI("cutapplied", !fFirstEvents.empty()); BCTable.SetIndex(index); BCTable.SetIArray("burst", fBurstEvents); BCTable.SetIArray("firstburst",fFirstEvents); BCTable.SetIArray("lastburst",fLastEvents); BCTable.SaveAs(ratdbFileName); // Clear all vectors fFirstEvents.clear(); fBurstEvents.clear(); fLastEvents.clear(); fRetriggerReadout.clear(); fBufferTime.clear(); fBufferGTID.clear(); } void TPBurstCut::SetI(const std::string& param, const int value) { DataCleaningProc::SetI(param,value); if (param == "pass") { fProcessPass= value; } } Processor::Result TPBurstCut::DSEvent(DS::Run& run, DS::Entry& ds) { bool pass = true; for( size_t iEV = 0; iEV < ds.GetEVCount(); iEV++ ) { DS::EV& currentEV = ds.GetEV(iEV); RAT::DS::UniversalTime currentTime = currentEV.GetUniversalTime(); double currentTimeIndex = ExtractTimeIndex(currentTime); if (currentTimeIndex == -1.0) continue; int currentGTID = currentEV.GetGTID(); if (fDepletionPass) { PushToBuffer(currentGTID, currentTimeIndex); std::vector::iterator timeWindowSearch = fBufferTime.begin(); while ((currentTimeIndex - *timeWindowSearch) > (double)(fTwinBurst * 1.0E-6)) { timeWindowSearch++; } fBufferGTID.erase(fBufferGTID.begin(), fBufferGTID.begin() + (timeWindowSearch - fBufferTime.begin())); fBufferTime.erase(fBufferTime.begin(), timeWindowSearch); DepletionProcessor(currentGTID, currentTimeIndex); continue; } if( EntryFilter(currentEV) ) continue;//filter out unwanted events. if ((currentTimeIndex != -1.0) && ( BurstProcessor(currentGTID, currentTimeIndex) != OKTRUE )) { pass = false;//if one event fail, they all fail. } } return pass ? OKTRUE : OKFALSE; } Processor::Result TPBurstCut::BurstProcessor(int currentGTID, double currentTimeIndex) { if (fBufferTime.size() < (fNeventsBurst - 1)) {//Push events to empty buffer PushToBuffer(currentGTID, currentTimeIndex); //should only be called at beginning return OKFALSE; } else if (WithinTimeWindow(currentTimeIndex)) {//burst events if (fPassFlag) { //This means the burst just started, have to write down first event(s) if (fProcessPass == 1) { fFirstEvents.push_back(fBufferGTID[0]); } else { fFirstEvents.push_back(currentGTID); for (size_t iev = 0; iev < fBufferGTID.size(); iev++) { fBurstEvents.push_back(fBufferGTID[iev]); } } fPassFlag = false; } PushToBuffer(currentGTID, currentTimeIndex); fBurstEvents.push_back(currentGTID); return OKTRUE; } else { fBufferTime.erase(fBufferTime.begin());//moving forward one step fBufferGTID.erase(fBufferGTID.begin()); bool backCheck = (currentTimeIndex - *(fBufferTime.end() - (fNeventsBurst - 1))) > (double)(fTwinBurst * 1.0E-6); if ((backCheck) || (fBufferTime.size() <= (fNeventsBurst - 2))) {//end of burst if (!fPassFlag) { PushLastEvent(); } fBufferTime.clear(); fBufferGTID.clear(); PushToBuffer(currentGTID, currentTimeIndex); fPassFlag = true; return OKFALSE; } else { return BurstProcessor (currentGTID, currentTimeIndex);//processing recursively, consult details in the livetime document } } } void TPBurstCut::DepletionProcessor(int currentGTID, double currentTimeIndex) { std::vector::iterator depletionStart; std::vector::iterator depletionEnd; depletionStart = find (fFirstEvents.begin(), fFirstEvents.end(), currentGTID); depletionEnd = find (fLastEvents.begin(), fLastEvents.end(), currentGTID); if (depletionStart != fFirstEvents.end()) { for (size_t iev = 0; iev < fBufferGTID.size(); iev++) { fBurstEvents.push_back(fBufferGTID[iev]); } fPushFlag = true; } if (depletionEnd != fLastEvents.end()) { fCurrentBurstEnd = currentTimeIndex + (double)(fTwinBurst * 1.0E-6); } if ((fCurrentBurstEnd != -1.0) && (currentTimeIndex >= fCurrentBurstEnd)) { fCurrentBurstEnd = -1.0; fPushFlag = false; } if (fPushFlag) { fBurstEvents.push_back(currentGTID); } } bool TPBurstCut::EntryFilter(DS::EV& ev) { int pulsegt_bit = DU::TrigBits::GetBitIndex("PulseGT"); int pedestal_bit = DU::TrigBits::GetBitIndex("Pedestal"); int extasy_bit = DU::TrigBits::GetBitIndex("EXTASY"); std::vector::iterator retriggerSearch; Int_t mtcd_trig_word = ev.GetTrigType(); if ((fProcessPass == 3) && (ev.DigitiserExists())) return true; if (ev.GetNhits() <= fNhitThreshold) return true; if ((mtcd_trig_word == 0)|| ((mtcd_trig_word & (1 << pulsegt_bit)) != 0) || ((mtcd_trig_word & (1 << pedestal_bit)) != 0) || ((mtcd_trig_word & (1 << extasy_bit)) != 0)) return true; //This is slow, so put it at last layer. if (fProcessPass != 1) { retriggerSearch = find (fRetriggerReadout.begin(), fRetriggerReadout.end(), ev.GetGTID()); if (retriggerSearch != fRetriggerReadout.end()) return true; } return false; } void TPBurstCut::PushToBuffer(int GTID, double timeIndex) { if (timeIndex != -1.0) { fBufferTime.push_back(timeIndex); fBufferGTID.push_back(GTID); } } void TPBurstCut::PushLastEvent() { if (fFirstEvents.size() == (fLastEvents.size() + 1)) { if (fProcessPass == 1) { fLastEvents.push_back(fBurstEvents.back()); if (fFirstEvents.back() > fLastEvents.back()) { warn << "TPBurstCut::DSEvent: a GTID reset has just occured."; std::vector::iterator GTIDReset = find (fBurstEvents.begin(), fBurstEvents.end(), fFirstEvents.back()); for (std::vector::iterator iReset = (GTIDReset + 1); iReset < fBurstEvents.end(); iReset++) { if (*iReset < *(iReset - 1)) { fFirstEvents.push_back(*iReset); fLastEvents.insert((fLastEvents.end() - 1) , *(iReset - 1)); } } } } else { fLastEvents.push_back(*(fBurstEvents.end() - fNeventsBurst)); } } else if (fFirstEvents.size() != fLastEvents.size()) { warn << "TPBurstCut::DSEvent: End of Burst and Start of Burst array size mismatch, losing one or more bursts." << "\n"; size_t shrinkSize = fFirstEvents.size() < fLastEvents.size() ? fFirstEvents.size() : fLastEvents.size(); while (fFirstEvents.size() > shrinkSize) fFirstEvents.erase(fFirstEvents.end()); while(fLastEvents.size() > shrinkSize) fLastEvents.erase(fLastEvents.end()); } } bool TPBurstCut::WithinTimeWindow(double timeIndex) { if (timeIndex == -1.0) return false; double timeDifference = timeIndex - fBufferTime[0]; double timeWindow = (double)(fTwinBurst * 1.0E-6); return timeDifference < timeWindow; } double TPBurstCut::ExtractTimeIndex(DS::UniversalTime& inputTime) { std::vector TimeDiff(3); TimeDiff[0] = (double)inputTime.GetDays() - (double)fStartTime.GetDays(); TimeDiff[1] = (double)inputTime.GetSeconds() - (double)fStartTime.GetSeconds(); TimeDiff[2] = (double)inputTime.GetNanoSeconds() - (double)fStartTime.GetNanoSeconds(); double timeDifference = (double)((TimeDiff[0])*86400) + (double)(TimeDiff[1]) + (double)((TimeDiff[2]) * 1.0E-9); if ((timeDifference < 0) || (timeDifference > fLength)) { return -1.0; } return timeDifference; } } // namespace RAT