#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace RAT; using std::string; using std::vector; WaterBlind::WaterBlind() : DataCleaningProc("waterblindlow0",1), fHighNhit(0.0),fMedNhit(0.0),fLowNhit(0.0),fOnline(0.0),fPass(0),fBlindnessFlag(0),fRunTypeWord(0x0), fUnblindTriggerBits(0x1400) { } void WaterBlind::BeginOfRun(DS::Run& run) { fPass = MetaInformation::Get()->GetCurrentPass(); // Get the length of the run DBLinkPtr runDB = DB::Get()->GetLink("RUN"); try{ // Now grab the starting and end time, so that we can determine the // run duration // Start time is also used to determine the time segment double start_day = runDB->GetD("start_day"); double start_sec = runDB->GetD("start_sec"); double start_nsc = runDB->GetD("start_nsc"); double stop_day = runDB->GetD("stop_day"); double stop_sec = runDB->GetD("stop_sec"); double stop_nsc = runDB->GetD("stop_nsc"); // Start time in seconds since Jan 1st 2010 fFirstTime = start_day*86400 + start_sec + start_nsc/(1.0e9); // End time in seconds since Jan 1st 2010 fLastTime = stop_day*86400 + stop_sec + stop_nsc/(1.0e9); fRunTypeWord = runDB->GetI("runtype"); } catch(RAT::DBNotFoundError &e){ Log::Die("WaterBlind::BeginOfRun: No start/end time found in RUN.ratdb."); } // Initialise parameters the lower and upper limits of the high and low energy blindness bins DBLinkPtr blindDB = DB::Get()->GetLink("BLINDNESS","water"); fHighNhit = blindDB->GetD("nhit_high"); fMedNhit = blindDB->GetD("nhit_med"); fLowNhit = blindDB->GetD("nhit_low"); // Would like the ability to keep certain triggers, e.g. PGT, PED, as unblind std::string force_unblinded_bits = blindDB->GetS("unblind_triggers"); DU::TrigBits bits = DU::Utility::Get()->GetTrigBits(); fUnblindTriggerBits = bits.GetMask(force_unblinded_bits); if (fUnblindTriggerBits != 0) { info << "WaterBlind::BeginOfRun: Forcing events with the following bits to be unblinded :" << newline; info << "WaterBlind::BeginOfRun: Trigger names : [ " << force_unblinded_bits << " ]" << newline; info << "WaterBlind::BeginOfRun: Bitmask : [ 0x" << &std::hex << fUnblindTriggerBits << &std::dec << " ]" << newline; } // Get some blindness bits from the data cleaning DU as references const DU::DataCleaningBits &fDCBits = DU::Utility::Get()->GetDataCleaningBits(); fDCBlindnessLow = fDCBits.GetBitIndex("waterblindlow0"); fDCBlindnessHigh = fDCBits.GetBitIndex("waterblindhigh9"); // Some run level inputs: // - Get a flag set by the processing which will indicate whether // or not a run is to be blinded. // - The data will be split into time-ordered segments, the order // of which will be randomised by the nearline. Get the boundaries // of each segment. DBLinkPtr blindRunDB = DB::Get()->GetLink("BLINDNESS_RUN_LEVEL"); try{ fBlindnessFlag = blindRunDB->GetI("apply_blindness_flag"); } catch(RAT::DBNotFoundError &e){ if(run.GetMCFlag() == 1) warn << "WaterBlind: Unable to find blindness flag in BLINDNESS_RUN_LEVEL (which sets whether this run is to be blinded)." << endl; else Log::Die("WaterBlind: Unable to find blindness flag in BLINDNESS_RUN_LEVEL (which sets whether this run is to be blinded).",0); } // Check run meets criteria for us to apply blindness to the whole run // 1. The apply_blindness_flag is high // 2. The run type physics bit is set fBlindRun = (fBlindnessFlag) && (fRunTypeWord & kPhysicsRun); if (fBlindRun) { info << "WaterBlind::BeginOfRun : This run [ " << run.GetRunID() << " ] will be blinded" << newline; // Get the time segments for this run. // Also get the correction to be used to compensate for the fraction of tubes online DBLinkPtr blindChunkDB = DB::Get()->GetLink("BLINDNESS_CHUNKS"); try{ fBlind_start = blindChunkDB->GetDArray("chunk_start"); fBlind_end = blindChunkDB->GetDArray("chunk_stop"); fOnline = blindChunkDB->GetD("frac_online"); fHighNhit *= fOnline; fMedNhit *= fOnline; fLowNhit *= fOnline; info << "WaterBlind::BeginOfRun: Correcting by a factor of " << fOnline << " to account for offline tubes." << endl; } catch(RAT::DBNotFoundError &e){ if(run.GetMCFlag() == 1) warn << "WaterBlind: BLINDNESS_CHUNKS table is either missing or incomplete." << endl; else Log::Die("WaterBlind: BLINDNESS_CHUNKS table is either missing or incomplete.",0); } fChunkFail=false; // A flag to make sure we don't spam with a ton of warnings } } Processor::Result WaterBlind::DSEvent( DS::Run& , DS::Entry& ds ) { // Data is split into ten segments based on time within the run. // The nearline uses the run length to determine ten timing chunks which it // writes to a table. This processor then reads these in and assigns each event // a segment. // The event is then classified into a blindness catergory: open, 5-5.5 MeV and // above 5 MeV. For entries with multiple EV, all events are put in the most severe // (highest energy) blindness bit. // Exceptions are made for events with certain triggers (specified in the ratdb). // This is to ensure we don't blind PGT, PEDs or calibration events. // Data cleaning can have multiple passes. However, we want to ensure that we // have the same blindness in each pass. // If this is a first pass, go through the usual process. If a higher pass, we want // to copy from previous passes. int section=0; bool blindedHigh=false, blindedLow=false, unblindedTrig=false; if (fPass == 0) { if( ds.GetEVCount() > 0){ // Loop through EV to check if the nhits is in one of two blindness bins // and mark with a flag for(size_t j=0; j=fBlind_start[seg] && (time-fFirstTime)<=fBlind_end[seg]){ section=seg; break; } if(!fChunkFail && seg==9){ // Make checks for the cases of: // a) The events that arrive before the official start of run/gt valid by allowing 10 seconds leeway // b) Orphans if((time-fFirstTime)>=-10 && (time-fFirstTime)<=0) break; if(ev.GetTrigType()==0) break; // Event has made it to the end of the loop without being assigned warn << "WaterBlind: Event has landed outside the expected timing windows. Check the data in RUN and BLINDNESS_CHUNKS.ratdb." << endl; fChunkFail=true; } } // Check which nhit region the event is in if( nhits >= fMedNhit && nhits < fHighNhit ){ blindedHigh=true; // event in the "high" nhit blindness region } else if( nhits >= fLowNhit && nhits < fMedNhit ){ blindedLow=true; // event in the "low" nhit blindness region } else{ // event outside the blinded nhit range so leave unblinded // i.e. do nothing continue; } } // Set blindness bits for all EVs as determined by the EV with most severe blinding if(blindedHigh==true) blindedLow=false; // An EV with an unblinded trigger should keep all EVs unblind if(unblindedTrig==true){ blindedHigh=false; blindedLow=false; } // Check if this run is to be blinded by looking at the blindness flag set before // The run will not be blinded if the blindness flag was not set or if the run was // not a physics run. if(!fBlindRun){ blindedHigh=false; blindedLow=false; } // Apply and set bits for(size_t j=0; j0 ){ for(size_t j=0; j