#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace RAT; using namespace RAT::Methods; using namespace RAT::PDFs; using namespace RAT::Optimisers; using namespace RAT::PMTSelectors; using namespace RAT::DS; using namespace RAT::Classifiers; #include using namespace std; #include using namespace ROOT; ScintFitter::ScintFitter() : Processor("scintFitter") { fQuadSeed = MethodFactory::Get()->GetMethod( "quad" ); fPositionTime = MethodFactory::Get()->GetMethod( "positionTimeLikelihood" ); fMuonWater = MethodFactory::Get()->GetMethod( "MuonWater" ); fMuonScintillator = MethodFactory::Get()->GetMethod( "MuonScintillator" ); fPositionANN = MethodFactory::Get()->GetMethod( "positionANN" ); fPowell = OptimiserFactory::Get()->GetOptimiser( "powell" ); fNullSelector = PMTSelectorFactory::Get()->GetPMTSelector( "null" ); fET1D = PDFFactory::Get()->GetPDF( "et1d" ); fEnergyMethod = MethodFactory::Get()->GetMethod( "energyRThetaFunctional" ); fITR = ClassifierFactory::Get()->GetClassifier( "ITR" ); fQPDT = ClassifierFactory::Get()->GetClassifier( "QPDT" ); fTimingPeaks = ClassifierFactory::Get()->GetClassifier( "timingPeaks" ); fMeanTime = ClassifierFactory::Get()->GetClassifier( "meanTime" ); fPreTriggerHits = ClassifierFactory::Get()->GetClassifier( "preTriggerHits" ); fIsoRegions = ClassifierFactory::Get()->GetClassifier( "isoRegions" ); fEarlyTime = ClassifierFactory::Get()->GetClassifier( "earlyTime" ); fBiPoCumulTimeResid = ClassifierFactory::Get()->GetClassifier( "BiPoCumulTimeResid" ); fBiPo212LikelihoodDiff = ClassifierFactory::Get()->GetClassifier( "BiPoLikelihoodDiff-212" ); fBiPo214LikelihoodDiff = ClassifierFactory::Get()->GetClassifier( "BiPoLikelihoodDiff-214" ); fBiPoLikelihoodDiffOptimiser = OptimiserFactory::Get()->GetOptimiser( "grid-55" ); fBiPo212Classifier = ClassifierFactory::Get()->GetClassifier("AlphaBetaClassifier-212_wPSD"); fBiPo214Classifier = ClassifierFactory::Get()->GetClassifier("AlphaBetaClassifier-214_wPSD"); fBerkeleyAlphaBeta = ClassifierFactory::Get()->GetClassifier("BerkeleyAlphaBeta"); fGridOptimiser = OptimiserFactory::Get()->GetOptimiser("grid-80"); fMuonClassifier = ClassifierFactory::Get()->GetClassifier( "muon" ); fNearAVAngular = ClassifierFactory::Get()->GetClassifier( "nearAVAngular" ); // Now combine the components where appropriate dynamic_cast< OptimisedMethod* >( fPositionTime )->SetOptimiser( fPowell ); dynamic_cast< SelectorMethod* >( fPositionTime )->AddPMTSelector( fNullSelector ); dynamic_cast< PDFMethod* >( fPositionTime )->SetPDF( fET1D ); dynamic_cast< OptimisedClassifier* >( fBiPo212LikelihoodDiff )->SetOptimiser( fBiPoLikelihoodDiffOptimiser ); dynamic_cast< OptimisedClassifier* >( fBiPo214LikelihoodDiff )->SetOptimiser( fBiPoLikelihoodDiffOptimiser ); dynamic_cast< OptimisedClassifier* >( fBiPo212Classifier )->SetOptimiser(fGridOptimiser); dynamic_cast< OptimisedClassifier* >( fBiPo214Classifier )->SetOptimiser(fGridOptimiser); fCutOff = 3.0; // Maximum nhit for which quad cannot run } ScintFitter::~ScintFitter() { delete fQuadSeed; delete fPositionTime; delete fPowell; delete fNullSelector; delete fET1D; delete fEnergyMethod; delete fITR; delete fQPDT; delete fTimingPeaks; delete fMeanTime; delete fPreTriggerHits; delete fIsoRegions; delete fEarlyTime; delete fBiPoCumulTimeResid; delete fBiPo212LikelihoodDiff; delete fBiPo214LikelihoodDiff; delete fBiPoLikelihoodDiffOptimiser; delete fBiPo212Classifier; delete fBiPo214Classifier; delete fBerkeleyAlphaBeta; delete fGridOptimiser; delete fMuonClassifier; delete fMuonWater; delete fMuonScintillator; } void ScintFitter::BeginOfRun( DS::Run& run ) { // First, call the individual begin-of-run functions fQuadSeed->BeginOfRun( run ); fPositionTime->BeginOfRun( run ); fPositionANN->BeginOfRun( run ); fPowell->BeginOfRun( run ); fNullSelector->BeginOfRun( run ); fET1D->BeginOfRun( run ); fEnergyMethod->BeginOfRun( run ); fITR->BeginOfRun( run ); fQPDT->BeginOfRun( run ); fTimingPeaks->BeginOfRun( run ); fMeanTime->BeginOfRun( run ); fPreTriggerHits->BeginOfRun( run ); fIsoRegions->BeginOfRun( run ); fEarlyTime->BeginOfRun( run ); fBiPoCumulTimeResid->BeginOfRun( run ); fBiPo212LikelihoodDiff->BeginOfRun( run ); fBiPo214LikelihoodDiff->BeginOfRun( run ); fBiPo212Classifier->BeginOfRun( run ); fBiPo214Classifier->BeginOfRun( run ); fBerkeleyAlphaBeta->BeginOfRun( run ); fMuonClassifier->BeginOfRun( run ); fMuonWater->BeginOfRun( run ); fMuonScintillator->BeginOfRun( run ); fNearAVAngular->BeginOfRun( run ); } Processor::Result ScintFitter::DSEvent( DS::Run& run, DS::Entry& ds ) { for( size_t iEV = 0; iEV < ds.GetEVCount(); iEV++ ) Event( run, ds.GetEV( iEV ) ); return OK; } void ScintFitter::EndOfRun( DS::Run& run ) { // Finally ,call the individual end-of-run functions fQuadSeed->EndOfRun( run ); fPositionTime->EndOfRun( run ); fPositionANN->EndOfRun( run ); fPowell->EndOfRun( run ); fNullSelector->EndOfRun( run ); fET1D->EndOfRun( run ); fEnergyMethod->EndOfRun( run ); fITR->EndOfRun( run ); fQPDT->EndOfRun( run ); fTimingPeaks->EndOfRun( run ); fMeanTime->EndOfRun( run ); fPreTriggerHits->EndOfRun( run ); fIsoRegions->EndOfRun( run ); fEarlyTime->EndOfRun( run ); fBiPoCumulTimeResid->EndOfRun( run ); fBiPo212LikelihoodDiff->EndOfRun( run ); fBiPo214LikelihoodDiff->EndOfRun( run ); fBiPo212Classifier->EndOfRun( run ); fBiPo214Classifier->EndOfRun( run ); fBerkeleyAlphaBeta->EndOfRun( run ); fMuonClassifier->EndOfRun( run ); fMuonClassifier->EndOfRun( run ); fMuonWater->EndOfRun( run ); fMuonScintillator->EndOfRun( run ); fNearAVAngular->EndOfRun( run ); } Processor::Result ScintFitter::Event( DS::Run& run, DS::EV& ev ) { // ScintFitter Logic: // This is a simple overview of the logic that is expressed in the next 80 lines // /// 0. See if event was caused by a muon (muon datacleaning tag /// check), if so, run the muon fitter routines, else continue. \n /// 1. Fit the position & time as the seedResult from quad. /// if nhits < fNhitCutoff then abort the fit and return no FitResult. \n /// 2. Fit the position & time as the scintResult using the positionTimeLikelihood, powell, null and /// seedResult as seed. /// If this fails then abort the fit and return no FitResult. \n /// 3. Fit the energy, using the scintResult as seed (or seedResult if the /// positionTimeLikelihood result is invalid). /// If this fails then abort the fit and return no FitResult. \n /// 4. Run itr with scintResult as seed \n /// 5. Run qpdt with scintResult as seed. \n /// 6. Run timingPeaks \n /// 7. Run meanTime with scintResult as seed \n /// 8. Run preTriggerHits \n /// 9. Run isoRegions with scintResult as seed \n /// 10. Run earlyTime with scintResult as seed \n /// 11. Run BiPoCumulTimeResid with scintResult as seed \n /// 12. Run BiPoLikelihoodDiff with scintResult as seed and grid-55 as optimiser /// for both 212BiPo and 214BiPo PDFs \n /// 14. Run AlphaBetaClassifier with scintResult as seed and grid-80 as optimiser /// for both 212_wPSD and 214_wPSD PDFs \n /// 15. Run BerkeleyAlphaBeta with scintResult as seed \n TStopwatch timer; timer.Start( true ); const size_t currentPass = MetaInformation::Get()->GetCurrentPass(); ev.AddFitterPass( currentPass ); // Ensure the EV knows fitters were run for this pass ev.AddClassifierPass( currentPass ); // Ensure the EV knows classifiers were run for this pass vector pmtData; for( size_t iPMTCal =0; iPMTCal < ev.GetCalPMTs().GetCount(); iPMTCal++ ) pmtData.push_back( FitterPMT( ev.GetCalPMTs().GetPMT( iPMTCal ) ) ); // if event was tagged as muon, run muon fitting routines const DS::DataQCFlags& dcFlags = ev.GetDataCleaningFlags(); const DU::DataCleaningBits& dcBits = DU::Utility::Get()->GetDataCleaningBits(); // If the data cleaning tags have processed and the muon tag is set for this pass then run the muon fitter bool is_muon = false; Int_t dcPassNumber = dcFlags.GetLatestPass(); if( dcFlags.ExistFlags( dcPassNumber )) is_muon = (dcFlags.GetApplied(dcPassNumber).Get(dcBits.GetBitIndex( "muontag" )) && !dcFlags.GetFlags(dcPassNumber).Get(dcBits.GetBitIndex( "muontag" ))); if( is_muon ) { fMuonClassifier->SetEventData( pmtData, &ev, &run ); try { ClassifierResult muon = fMuonClassifier->GetClassification() ; ev.SetClassifierResult( currentPass, fMuonClassifier->GetName(), muon ); const bool scintMedium = muon.GetClassification("medium"); FitResult muonResult; if( scintMedium ) { fMuonScintillator->SetEventData( pmtData, &ev, &run ); muonResult = fMuonScintillator->GetBestFit(); } else { fMuonWater->SetEventData( pmtData, &ev, &run ); muonResult = fMuonWater->GetBestFit(); } timer.Stop(); muonResult.SetExecutionTime( timer.RealTime() ); return SetMuonResult( muonResult, ev, currentPass ); } catch( Classifier::ClassifierFailError& error ) { warn << "ScintFitter::Event: Muon classifier failed " << error.what() << ", quiting." << newline; return Processor::OK; } catch( Method::MethodFailError& error ) { warn << "ScintFitter::Event: Muon classification failed: "<< error.what() << ", quitting." << newline; return Processor::OK; } } // Initialise the seed fQuadSeed->SetEventData( pmtData, &ev, &run ); // Run the seed method FitResult seedResult; try { if( ev.GetCalPMTs().GetCount() > fCutOff ) seedResult = fQuadSeed->GetBestFit(); else { warn << "ScintFitter::Event: insufficient points for quad to run, exiting" << newline; return Processor::FAIL; } } catch( Method::MethodFailError& error ) { warn << "ScintFitter::Event: Seed failed " << error.what() << ", continuing." << newline; } // Now initialise the position time method fPositionTime->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededMethod* >( fPositionTime )->DefaultSeed();; dynamic_cast< SeededMethod* >( fPositionTime )->SetSeed( seedResult ); FitResult scintResult; // Run the position time method try { FitResult positionResult = fPositionTime->GetBestFit(); scintResult.SetVertex(0, positionResult.GetVertex(0)); SetFOMs(scintResult, positionResult, "Position"); } catch( Method::MethodFailError& error ) { warn << "ScintFitter::Event: Main method failed " << error.what() << ", exiting" << newline; return Processor::FAIL; } // Now initialise the energy method fEnergyMethod->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededMethod* >( fEnergyMethod )->DefaultSeed(); if( scintResult.GetValid() ) dynamic_cast< SeededMethod* >( fEnergyMethod )->SetSeed( scintResult ); else if( seedResult.GetValid() ) dynamic_cast< SeededMethod* >( fEnergyMethod )->SetSeed( seedResult ); else warn << "ScintFitter::Event: No seed for the energy method." << newline; // Run the energy method try { FitVertex vertex = scintResult.GetVertex(0); FitResult energyResult = fEnergyMethod->GetBestFit(); FitVertex energyVertex = energyResult.GetVertex(0); vertex.SetEnergy( energyVertex.GetEnergy(), energyVertex.ValidEnergy() ); vertex.SetPositiveEnergyError( energyVertex.GetPositiveEnergyError(), energyVertex.ValidEnergy() ); vertex.SetNegativeEnergyError( energyVertex.GetNegativeEnergyError(), energyVertex.ValidEnergy() ); scintResult.SetVertex( 0, vertex ); SetFOMs(scintResult, energyResult, "Energy"); } catch( Method::MethodFailError& error ) { warn << "ScintFitter::Event: Energy method failed " << error.what() << ", exiting" << newline; return Processor::FAIL; } // Initialise and run the PositionANN fitter // (note, this is stores a fit result, not classifier result) fPositionANN->SetEventData( pmtData, &ev, &run ); try{ ev.SetFitResult( currentPass, fPositionANN->GetName() + ":scintFitter", fPositionANN->GetBestFit() ); } catch( Method::MethodFailError& error ) { warn << error.what() << newline; } // Initialise and run the NearAVAngular classifier fNearAVAngular->SetEventData( pmtData, &ev, &run ); try{ ev.SetClassifierResult( currentPass, fNearAVAngular->GetName() + ":scintFitter", fNearAVAngular->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the ITR classifier fITR->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fITR )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fITR )->SetSeed( scintResult ); try { ev.SetClassifierResult( currentPass, fITR->GetName() + ":scintFitter", fITR->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the QPDT classifier fQPDT->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fQPDT )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fQPDT )->SetSeed( scintResult ); try { ev.SetClassifierResult( currentPass, fQPDT->GetName() + ":scintFitter", fQPDT->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the TimingPeaks classifier fTimingPeaks->SetEventData( pmtData, &ev, &run ); try { ev.SetClassifierResult( currentPass, fTimingPeaks->GetName() + ":scintFitter", fTimingPeaks->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the MeanTime classifier fMeanTime->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fMeanTime )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fMeanTime )->SetSeed( scintResult ); try { ev.SetClassifierResult( currentPass, fMeanTime->GetName() + ":scintFitter", fMeanTime->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the PreTriggerHits classifier fPreTriggerHits->SetEventData( pmtData, &ev, &run ); try { ev.SetClassifierResult( currentPass, fPreTriggerHits->GetName() + ":scintFitter", fPreTriggerHits->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the IsoRegions classifier fIsoRegions->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fIsoRegions )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fIsoRegions )->SetSeed( scintResult ); try { ev.SetClassifierResult( currentPass, fIsoRegions->GetName() + ":scintFitter", fIsoRegions->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the EarlyTime classifier fEarlyTime->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fEarlyTime )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fEarlyTime )->SetSeed( scintResult ); try { ev.SetClassifierResult( currentPass, fEarlyTime->GetName() + ":scintFitter", fEarlyTime->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the BiPoCumulTimeResid classifier fBiPoCumulTimeResid->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fBiPoCumulTimeResid )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fBiPoCumulTimeResid )->SetSeed( scintResult ); try { ev.SetClassifierResult ( currentPass, fBiPoCumulTimeResid->GetName() + ":scintFitter", fBiPoCumulTimeResid->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } // Now initialise and run the BiPoLikelihoodDiff classifiers fBiPo212LikelihoodDiff->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fBiPo212LikelihoodDiff )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fBiPo212LikelihoodDiff )->SetSeed( scintResult ); try { ev.SetClassifierResult ( currentPass, fBiPo212LikelihoodDiff->GetName() + ":212:scintFitter", fBiPo212LikelihoodDiff->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } fBiPo214LikelihoodDiff->SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fBiPo214LikelihoodDiff )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fBiPo214LikelihoodDiff )->SetSeed( scintResult ); try { ev.SetClassifierResult ( currentPass, fBiPo214LikelihoodDiff->GetName() + ":214:scintFitter", fBiPo214LikelihoodDiff->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } fBiPo212Classifier->SetEventData(pmtData,&ev,&run); dynamic_cast< SeededClassifier* >( fBiPo212Classifier )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fBiPo212Classifier )->SetSeed( scintResult ); try{ ev.SetClassifierResult( currentPass, fBiPo212Classifier->GetName()+":212:scintFitter",fBiPo212Classifier->GetClassification() ); } catch ( Classifier::ClassifierFailError & error ) { warn<SetEventData(pmtData,&ev,&run); dynamic_cast< SeededClassifier* >( fBiPo214Classifier )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fBiPo214Classifier )->SetSeed( scintResult ); try{ ev.SetClassifierResult( currentPass, fBiPo214Classifier->GetName()+":214:scintFitter",fBiPo214Classifier->GetClassification() ); } catch ( Classifier::ClassifierFailError & error ) { warn<SetEventData( pmtData, &ev, &run ); dynamic_cast< SeededClassifier* >( fBerkeleyAlphaBeta )->DefaultSeed(); dynamic_cast< SeededClassifier* >( fBerkeleyAlphaBeta )->SetSeed( scintResult ); try { ev.SetClassifierResult ( currentPass, fBerkeleyAlphaBeta->GetName() + ":scintFitter", fBerkeleyAlphaBeta->GetClassification() ); } catch( Classifier::ClassifierFailError& error ) { warn << error.what() << newline; } timer.Stop(); scintResult.SetExecutionTime( timer.RealTime() ); return SetResult(scintResult, ev, currentPass); } Processor::Result ScintFitter::SetResult( DS::FitResult& scintResult, DS::EV& ev, size_t currentPass) { ev.SetFitResult( currentPass, "scintFitter", scintResult ); // Now set the 0 vertex as the default fit vertex, if the fit is valid DS::FitVertex& defaultVertex = scintResult.GetVertex(0); // Only the position, energy and time are calculated by the scintFitter, so the DS::INVALID flag must be set for direction defaultVertex.SetDirection(TVector3(DS::INVALID, DS::INVALID, DS::INVALID),false); defaultVertex.SetDirectionErrors(TVector3(DS::INVALID, DS::INVALID, DS::INVALID),false); ev.SetDefaultFitVertex( "scintFitter", defaultVertex ); return Processor::OK; } Processor::Result ScintFitter::SetMuonResult( DS::FitResult& scintResult, DS::EV& ev, size_t currentPass) { ev.SetFitResult( currentPass, "scintFitter", scintResult ); // Now set the 0 vertex as the default fit vertex, if the fit is valid ev.SetDefaultFitVertex( "scintFitter", scintResult.GetVertex(0) ); return Processor::OK; } void ScintFitter::SetFOMs( DS::FitResult& fitResult, const DS::FitResult& partialResult, const string& prefix ) { vector fomNames = partialResult.GetFOMNames(); for(vector::const_iterator iter = fomNames.begin(); iter != fomNames.end(); ++iter) fitResult.SetFOM( (prefix+*iter), partialResult.GetFOM(*iter) ); }