#include #include #include #include #include #include #include #include namespace RAT { void MissedMuonFollowerCut::BeginOfRun(DS::Run&) { fLClean = DB::Get()->GetLink("DATACLEANING",fName); fNhitMin = static_cast( fLClean->GetI("primary_nhit_threshold") ); fSecondaryNhitMin = static_cast( fLClean->GetI("secondary_nhit_threshold") ); fTimeWindow = fLClean->GetD("time_window"); fLastHighNHitGTID = 0; fInWindow = false; // Initialize various DB/Table/Column names fDBName = "MissedMuonFollower.ratdb"; fDBTableName = "MISSEDMUONFOLLOWER"; fDBGTIDColumnName = "gtid_missedmuons"; fDBDaysColumnName = "days_missedmuons"; fDBSecondsColumnName = "secs_missedmuons"; fDBNanoSecondsColumnName = "nsecs_missedmuons"; if (fProcessPass == 2){ bool foundDBFile = false; try { DBLinkPtr MissedMuonsDB = DB::Get()->GetLink(fDBTableName); fEventStore = MissedMuonsDB->GetIArray(fDBGTIDColumnName); foundDBFile = true; } catch (const DBNotFoundError &e) { warn << "MissedMuonFollowerCut::BeginOfRun: Couldn't access DB." "Attempting to use local file.\n"; foundDBFile = false; } if(!foundDBFile) { try { std::vector contents = DBJsonLoader::parse(fDBName); fEventStore = contents[0]->GetIArray(fDBGTIDColumnName); } catch (const FileError &e) { warn << "MissedMuonFollowerCut::BeginOfRun: " "Couldn't find file of Missed Muon GTIDS. " "Results of this cut won't be useful\n"; } catch (const DBWrongTypeError &e) { // Will occur if there were no missed muons // found previously. Nothing to do. } } } } Processor::Result MissedMuonFollowerCut::DSEvent(DS::Run&, DS::Entry& ds) { bool pass = true; // If any triggered event fails, they all fail for( size_t iEV = 0; iEV < ds.GetEVCount(); iEV++ ) { if( Event(ds, ds.GetEV(iEV)) != OKTRUE ) pass = false; } return pass ? OKTRUE : OKFALSE; } // Used for comparing times between two events. Returns the time difference // between the arguements in nanoseconds double MissedMuonFollowerCut::TimeDiff(DS::UniversalTime time_a, DS::UniversalTime time_b) { UInt_t sec_a(time_a.GetSeconds()), sec_b(time_b.GetSeconds()); UInt_t days_a(time_a.GetDays()), days_b(time_b.GetDays()); double nsec_a(time_a.GetNanoSeconds()), nsec_b(time_b.GetNanoSeconds()); // 86400 seconds in a day return ((days_a - days_b)*86400 + (sec_a - sec_b)*1e9) + (nsec_a - nsec_b); } Processor::Result MissedMuonFollowerCut::Event(DS::Entry&, DS::EV& ev) { fPassFlag = true; if (fProcessPass == 1) { unsigned int nhit = ev.GetUncalPMTs().GetCount(); // For pass 1 the idea is to just find all events greater than some // threshold nhit that happen closer in time than some threshold time. // Then store all the GTIDs that match that criteria in a file // check trigger word to make sure there was a valid physics event. // throw out pedestal, and ext_a triggers if (BitManip::TestBit(ev.GetTrigType(), DU::TrigBits::Pedestal) || BitManip::TestBit(ev.GetTrigType(), DU::TrigBits::EXTASY)) { return fPassFlag ? OKFALSE : OKTRUE; } if (!fInWindow && nhit >= fNhitMin) { // If you're not in a window and a potential 'missed muon' // occurs then jot down the event gtid and time. // And begin a window fInWindow = true; fLastHighNHitGTID = ev.GetGTID(); fTimeOfLastHighNhit = ev.GetUniversalTime(); } else if (fInWindow && nhit >= fSecondaryNhitMin && TimeDiff(ev.GetUniversalTime(), fTimeOfLastHighNhit) <= fTimeWindow) { // If you're in a window and a event with high enough nhit // to be a follower occurs. // Then save to DB/JSON that event and time. // Then also say you're no longer in an mmf window b/c this one // has been properly marked already. // Unless this event is above the primary nhit threshold... // then this is the 'start' of the next follower window fEventStore.push_back(fLastHighNHitGTID); fDaysTimeStore.push_back((int)fTimeOfLastHighNhit.GetDays()); fSecsTimeStore.push_back((int)fTimeOfLastHighNhit.GetSeconds()); fNSecsTimeStore.push_back((int)fTimeOfLastHighNhit.GetNanoSeconds()); // Check if event is above primary nhit threshold, if it isn't // reset the window. if( nhit >= fNhitMin) { fLastHighNHitGTID = ev.GetGTID(); fTimeOfLastHighNhit = ev.GetUniversalTime(); } else { fInWindow = false; } } else if (fInWindow && TimeDiff(ev.GetUniversalTime(), fTimeOfLastHighNhit) > fTimeWindow) { fInWindow = false; } return fPassFlag ? OKFALSE : OKTRUE; } else { // fProcessPass == 2 // For pass two just need to mark all events with a GTID that was // flagged in pass 1 int gtid = ev.GetGTID(); DS::UniversalTime time = ev.GetUniversalTime(); DS::UniversalTime mostRecentMissedMuon; for (size_t i=0;i