#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; 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"); fNeventsBurst = static_cast( fLClean->GetI("nevents_nhitburst") ); fNhitThreshold = static_cast( fLClean->GetI("nhit_threshold") ); } 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; } //reconstruct arrays of retrigger in the second pass based on the first event and //last event recorded down in the first pass. std::vector fFirstEventsTemp; std::vector fLastRetriggersTemp; bool foundDBTable = false; bool foundJSONFile = false; try{ DBLinkPtr fData = DB::Get()->GetLink("LIVETIME_CUT", "retriggercut"); if (fData->GetI("cutapplied") == 1) { fFirstEventsTemp = fData->GetIArray("firstburst"); fLastRetriggersTemp = fData->GetIArray("lastburst"); foundDBTable = true; } } catch(DBNotFoundError &e){ warn << "LivetimeCuts::BeginOfRun: Could not find retrigger cut info, Looking for .json file" << endl; } if (!foundDBTable) {//Reading .json file for retriggers if ratdb not found. try { std::ostringstream fname; fname << "livetimecut_retriggercut_" << 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 ((!foundDBTable) && (!foundJSONFile)) { warn << "LivetimeCuts::BeginOfRun: Could not find retriggercut info, retriggercut will not be applied.." << endl; } 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) { PushLastEvent(); std::string index = ""; std::string ratdbFileName = ""; if (fProcessPass == 1) { index = "retriggercut"; ratdbFileName = "Retriggers.ratdb"; fBurstEvents.clear(); } else if (fProcessPass == 2) { index = "burstcut"; ratdbFileName = "NhitBursts.ratdb"; } else if (fProcessPass == 3) { 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); if( EntryFilter(currentEV) ) continue;//filter out unwanted events. if( BurstProcessor(currentEV) != OKTRUE ){ pass = false;//if one event fail, they all fail. } } return pass ? OKTRUE : OKFALSE; } Processor::Result TPBurstCut::BurstProcessor(DS::EV& ev) { if (fBufferTime.size() < (fNeventsBurst - 1)) {//Push events to empty buffer PushToBuffer(ev); //should only be called at beginning return OKFALSE; } else if (WithinTimeWindow(ev)) {//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(ev.GetGTID()); for (size_t iev = 0; iev < fBufferGTID.size(); iev++) { fBurstEvents.push_back(fBufferGTID[iev]); } } fPassFlag = false; } PushToBuffer(ev); fBurstEvents.push_back(ev.GetGTID()); return OKTRUE; } else { fBufferTime.erase(fBufferTime.begin());//moving forward one step fBufferGTID.erase(fBufferGTID.begin()); if (fBufferTime.size() <= (fNeventsBurst - 2)) {//end of burst if (!fPassFlag) { PushLastEvent(); } fBufferTime.clear(); fBufferGTID.clear(); PushToBuffer(ev); fPassFlag = true; return OKFALSE; } else { return BurstProcessor (ev);//processing recursively, consult details in the livetime document } } } 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(DS::EV& ev) { fBufferTime.push_back(ev.GetUniversalTime()); fBufferGTID.push_back((int)ev.GetGTID()); } 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(DS::EV& ev) { std::vector TimeDiff(3); TimeDiff[0] = ev.GetUniversalTime().GetDays() - fBufferTime[0].GetDays(); TimeDiff[1] = ev.GetUniversalTime().GetSeconds() - fBufferTime[0].GetSeconds(); TimeDiff[2] = ev.GetUniversalTime().GetNanoSeconds() - fBufferTime[0].GetNanoSeconds(); double timeDifference = (double) (((double)((TimeDiff[0])*86400) + (double)(TimeDiff[1]))*1E9) + (double)(TimeDiff[2]); double timeWindow = (double)(fTwinBurst * 1000); return timeDifference < timeWindow; } } // namespace RAT