#include #include namespace RAT { void ThresholdFlasherCut::BeginOfRun(DS::Run&) { fLClean = DB::Get()->GetLink("DATACLEANING",fName); fEventCounter = 0; fHitCounter.resize(9728,0); fIgnoreChannel.resize(9728,0); fAdjacentHits = fLClean->GetI("adjacent_channels"); fAdjacentMaxed = fLClean->GetI("adjacent_channels_maxed"); fIgnoreThreshold = fLClean->GetD("ignore_channel_threshold"); fUnCalQHSLow = fLClean->GetI("uncalQHS_low"); fUnCalQHSHigh = fLClean->GetI("uncalQHS_high"); fUnCalQHLLow = fLClean->GetI("uncalQHL_low"); fUnCalQHLHigh = fLClean->GetI("uncalQHL_high"); fUnCalQLXLow = fLClean->GetI("uncalQLX_low"); fUnCalQLXHigh = fLClean->GetI("uncalQLX_high"); fCalQHSLow = fLClean->GetI("calQHS_low"); fCalQHSHigh = fLClean->GetI("calQHS_high"); fCalQHLLow = fLClean->GetI("calQHL_low"); fCalQHLHigh = fLClean->GetI("calQHL_high"); fCalQLXLow = fLClean->GetI("calQLX_low"); fCalQLXHigh = fLClean->GetI("calQLX_high"); } Processor::Result ThresholdFlasherCut::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; } Processor::Result ThresholdFlasherCut::Event(DS::Entry&, DS::EV& ev) { fPassFlag = true; DS::CalPMTs cPMTs = ev.GetCalPMTs(); DS::UncalPMTs uPMTs = ev.GetUncalPMTs(); // Try uncalibrated channels first for (size_t iPMT = 0; iPMT < uPMTs.GetCount(); iPMT++){ DS::PMTUncal uPMT = ev.GetUncalPMTs().GetPMT(iPMT); int id = uPMT.GetID(); int channel = uPMT.GetChannel(); float uqhs = uPMT.GetQHS(); float uqhl = uPMT.GetQHL(); float uqlx = uPMT.GetQLX(); // Keep track of hits on each PMT fHitCounter[id]+=1; // If channel is very low or very high in charge if((uqlx < fUnCalQLXLow || uqhs < fUnCalQHSLow || uqhl < fUnCalQHLLow) || (uqlx > fUnCalQLXHigh || uqhs > fUnCalQHSHigh || uqhl > fUnCalQHLHigh)){ // If there are four channels around a high charge hit that // might have missed the cross-talk throw away the event. int nchannels_vthr = CountChannelsAboveThreshold(id, channel); // Keep track of high/low charge hits on each PMT fIgnoreChannel[id] += 1; // If at any point the number of high charge hits on a channel is greater than 10% of the // total number of hits on that channel in the run, than do NOT flag the event as bad, because // this is likely due to a bad channel. Wait for 10 hits on the channel before // imposing this check. if(nchannels_vthr >= fAdjacentMaxed && (fIgnoreChannel[id]/fHitCounter[id] < fIgnoreThreshold || fHitCounter[id] < 10)){ fPassFlag = false; } } } // Now try calibrated channels for (size_t iPMT = 0; iPMT < cPMTs.GetCount(); iPMT++){ DS::PMTCal cPMT = ev.GetCalPMTs().GetPMT(iPMT); int id = cPMT.GetID(); int channel = cPMT.GetChannel(); float qhs = cPMT.GetQHS(); float qhl = cPMT.GetQHL(); float qlx = cPMT.GetQLX(); // Keep track of hits on each PMT fHitCounter[id]+=1; // If channel is very low or very high in charge if((qlx < fCalQLXLow || qhs < fCalQHSLow || qhl < fCalQHLLow) || (qlx > fCalQLXHigh || qhs > fCalQHSHigh || qhl > fCalQHLHigh)){ // If there are four channels around a high charge hit that // might have missed the cross-talk throw away the event. int nchannels_vthr = CountChannelsAboveThreshold(id, channel); // Keep track of high/low charge hits on each PMT fIgnoreChannel[id] += 1; if(nchannels_vthr >= fAdjacentMaxed && (fIgnoreChannel[id]/fHitCounter[id] < fIgnoreThreshold || fHitCounter[id] < 10)){ fPassFlag = false; } } } fEventCounter++; UpdateMask(ev); return fPassFlag ? OKFALSE : OKTRUE; } int ThresholdFlasherCut::CountChannelsAboveThreshold(int id, int channel){ int nchannels_vthr = 0; // Loop over 10 nearest channels const RAT::DU::ChanHWStatus& chanHWStatus = RAT::DU::Utility::Get()->GetChanHWStatus(); for(int i = -fAdjacentHits; i < fAdjacentHits; i++){ // If the channel is on the same FEC if(channel + i < 32 && channel + i > 0 && i != 0){ // Find the absolute threshold and threshold above the noise int vthr = chanHWStatus.GetThreshold(id+i); int zvthr = chanHWStatus.GetThresholdAboveNoise(id+i); // If threshold above noise is greater than 25 or if the // threshold is greather than 200, we might not see the crosstalk // on the flasher, so count the "missed" crosstalk channel if(zvthr > 25 || vthr > 200){ nchannels_vthr++; } } } return nchannels_vthr; } } // namespace RAT