#ifndef __RUNANALYZER__ #define __RUNANALYZER__ #include "JSupport/JSupport.hh" #include "JSupport/JSupportToolkit.hh" #include "JSupport/JMultipleFileScanner.hh" #include "JDetector/JModuleRouter.hh" #include "JDetector/JDetectorToolkit.hh" #include "JROOT/JManager.hh" #include "JTools/JQuantile.hh" #include "TFile.h" #include "TH1D.h" #include "JRunHistograms.hh" using namespace std ; using namespace KM3NETDAQ ; using namespace JPP ; /** * \author rgruiz, adomi */ /** * Class dedicated to the analysis of %KM3NeT runs. * */ class RunAnalyzer { string inputFile; JDetector detector; JModuleRouter* router; JRA_Histograms histograms; int modulesPerString; JLimit_t numberOfTimeslices; JLimit_t numberOfSummaryslices; JLimit_t numberOfEvents; bool pmt_analysis; public : /** * Default constructor. */ RunAnalyzer(){} /** * Constructor. * * \param file Path to the file to be analyzed * \param detectorFile path to a detector file * \param nTimeslices Number of timeslices to be read * \param nSummaryslices Number of summary slices to be read * \param nEvents Number of frames to be read * \param pmtanalysis PMT analysis option */ RunAnalyzer (string file , string detectorFile , JLimit_t nTimeslices , JLimit_t nSummaryslices , JLimit_t nEvents, bool pmtanalysis): inputFile (file), router (NULL), numberOfTimeslices (nTimeslices), numberOfSummaryslices (nSummaryslices), numberOfEvents (nEvents), pmt_analysis (pmtanalysis) { try { load (detectorFile, detector); } catch(const JException & error) { cerr << "FATAL ERROR. Could not open detector file '" << detectorFile << "'." << endl; exit(1); } histograms = JRA_Histograms(detector); router = new JModuleRouter(detector); modulesPerString = JDETECTOR::getNumberOfModules (detector) / getNumberOfStrings (detector); } /** * Destructor. */ ~RunAnalyzer(){} /* * Function template used to read time ordered events from a tree. * * \param scanner A JTreeScanner * \param */ void iterateEventTree (JTreeScanner < JDAQEvent > & scanner) { while (scanner.hasNext()) { JDAQEvent event = *(scanner.next()); histograms.h_trigger.h_Snapshot_hits -> Fill((Double_t) event.size ()); histograms.h_trigger.h_Triggered_hits -> Fill((Double_t) event.size ()); histograms.h_trigger.h_Number_of_overlays -> Fill(event.getOverlays()); for (unsigned int i = 0; i != NUMBER_OF_TRIGGER_BITS; ++i) { if (event.hasTriggerBit(i)) { histograms.h_trigger.h_Trigger_bit_event -> Fill((Double_t) i); } } for (JDAQEvent::const_iterator hit = event.begin(); hit != event.end(); ++hit) { if (router->hasModule(hit->getModuleID())) { const JModule& module = router->getModule (hit->getModuleID()); histograms.h_trigger.h_pmt_distribution_triggered_hits->Fill(hit->getPMT()); histograms.h_trigger.h_tot_distribution_triggered_hits->Fill(hit->getToT()); int String = module.getString(); int Floor = module.getFloor(); histograms.h_trigger.h_Triggered_hits_per_module -> Fill(String , Floor); for (unsigned int i = 0; i != NUMBER_OF_TRIGGER_BITS; ++i) { if (hit -> hasTriggerBit(i)) { histograms.h_trigger.h_Trigger_bit_hit->Fill((Double_t) i); } } }else{ FATAL("JModuleRouter trying to access non existing identifier: "<< hit->getModuleID()); } } for (JDAQEvent::const_iterator hit = event.begin() ; hit != event.end() ; ++hit){ if (router->hasModule(hit->getModuleID())) { const JModule& module = router->getModule (hit->getModuleID()); int String = module.getString(); int Floor = module.getFloor(); int pmt = hit-> getPMT(); if(pmt_analysis == true){ (*histograms.h_trigger.m_Snapshot_hits_per_pmt)[MAKE_STRING("Detector/DU" + to_string(String))] -> Fill(pmt, Floor); } histograms.h_trigger.h_pmt_distribution_snapshot_hits -> Fill(hit->getPMT()); histograms.h_trigger.h_tot_distribution_snapshot_hits -> Fill(hit->getToT()); histograms.h_trigger.h_Snapshot_hits_per_module -> Fill(String, Floor); }else{ FATAL("JModuleRouter trying to access non existing identifier: "<< hit->getModuleID()); } } } } /* * Function template to read and process time ordered summary slices. * * \param scanner A JTreeScanner from which time ordered summary slices are accessed. */ void iterateSummarysliceTree (JTreeScanner < JDAQSummaryslice > & scanner) { std::map >> PMT_rate_quantiles; std::map > DOM_rate_quantiles; while (scanner.hasNext()){ JDAQSummaryslice slice = *(scanner.next()); for (JDAQSummaryslice::const_iterator frame = slice.begin() ; frame != slice.end() ; ++ frame) { if (router->hasModule(frame->getModuleID())) { const JModule& module = router->getModule (frame->getModuleID()); int string = module.getString(); int floor = module.getFloor (); PMT_rate_quantiles[string].resize(modulesPerString , vector (NUMBER_OF_PMTS)); JDAQFrameStatus status = frame -> getDAQFrameStatus(); int nFIFOcount = status.countFIFOStatus(); int nHRVcount = status.countHighRateVeto(); if (nHRVcount > 0) { histograms.h_summary.h_hrv_per_dom->Fill(string , floor); } if (status.testDAQStatus() == false) { histograms.h_summary.h_daq_status_per_dom->Fill(string , floor); } histograms.h_summary.h_fifo_per_dom->Fill(string , floor , nFIFOcount); if(pmt_analysis == true){ TH2D* h2 = (*histograms.h_summary.m_summary_rate_distribution)[MAKE_STRING("Detector/DU" + to_string(string) + "/F" + to_string(floor))]; double rate = 0; for (int i = 0 ; i < NUMBER_OF_PMTS ; i++){ rate += frame->getRate(i); h2->Fill(i , frame->getRate(i) * 1e-3); PMT_rate_quantiles[string][floor-1][i].put(frame->getRate(i)*1e-3); } DOM_rate_quantiles[string].resize(modulesPerString); DOM_rate_quantiles[string][floor-1].put(rate * 1e-3); } else { double rate = 0; for (int i = 0 ; i < NUMBER_OF_PMTS ; i++){ rate += frame->getRate(i); histograms.h_summary.h_pmt_rate_distribution->Fill(frame->getRate(i)*1e-3); } histograms.h_summary.h_dom_rate_distribution->Fill(rate*1e-3); DOM_rate_quantiles[string].resize(modulesPerString); DOM_rate_quantiles[string][floor-1].put(rate * 1e-3); } }else{ FATAL("JModuleRouter trying to access non existing identifier: "<< frame->getModuleID()); } } } for (std::map >::const_iterator i = DOM_rate_quantiles.begin() ; i!= DOM_rate_quantiles.end() ; ++i) { for (int j=1 ; j < modulesPerString + 1 ; j++) { if (i->second[j-1].getCount() > 0) histograms.h_summary.h_rate_summary->Fill(i->first, j, i->second[j-1].getMean()); } } if(pmt_analysis == true){ for (std::map > >::const_iterator i = PMT_rate_quantiles.begin() ; i!= PMT_rate_quantiles.end() ; ++i) { for (int j=0 ; j < modulesPerString ; j++){ for (int k=0 ; k < NUMBER_OF_PMTS ; k++){ if (i -> second[j][k].getCount() > 0){ (*histograms.h_summary.m_mean_summary_rate) [MAKE_STRING("Detector/DU" + to_string(i->first))]->Fill(k, j+1, i->second[j][k].getMean()); (*histograms.h_summary.m_mean_summary_rate_distribution)[MAKE_STRING("Detector/DU" + to_string(i->first))]->Fill( i->second[j][k].getMean()); } } } } } } /* * Function template to read and process time ordered timeslices. * * \param scanner A JTreeScanner from which time ordered timeslices are accessed. * \param frame_index_range the range of the indices of the frames to be accessed. */ template void iterateTimesliceTree (JTreeScanner < T > & scanner) { int ts_type = JIndexOf::value; std::map < int , std::map > DOM_rate_quantiles; double inverseFrameTimeSec = 1. / (1.0e-9 * getFrameTime()); while (scanner.hasNext()){ T slice = *(scanner.next()); for(auto & frame : slice) { if (router->hasModule(frame.getModuleID())) { const JModule& module = router->getModule (frame.getModuleID()); double rate = frame.numberOfHits * inverseFrameTimeSec; int string = module.getString(); int floor = module.getFloor (); DOM_rate_quantiles[string][floor].put(rate); vector pmt_hit_count (NUMBER_OF_PMTS , 0) ; if(pmt_analysis == true){ TH2D* h2 = (*histograms.h_timeslice.m_pmt_tot_distributions[ts_type])[MAKE_STRING("Detector/DU" + to_string(string) + "/F" + to_string(floor) + "/" + to_string(frame.getModuleID()))]; for (JDAQSuperFrame::const_iterator hit = frame.begin() ; hit != frame.end() ; ++hit){ h2 -> Fill(hit->getPMT() , hit->getToT()) ; pmt_hit_count[hit->getPMT()]++; } for (int pmt = 0 ; pmt != NUMBER_OF_PMTS ; ++pmt) { (*histograms.h_timeslice.m_pmt_rate_distributions[ts_type])[MAKE_STRING("Detector/DU" + to_string(string) + "/F" + to_string(floor))] -> Fill(pmt , 1e-3 * pmt_hit_count[pmt] * inverseFrameTimeSec); } } }else{ FATAL("JModuleRouter trying to access non existing identifier: "<< frame.getModuleID()); } } } for (std::map< int , std::map>::const_iterator i = DOM_rate_quantiles.begin() ; i != DOM_rate_quantiles.end() ; i++){ for (std::map::const_iterator j = i->second.begin() ; j != i->second.end() ; j++){ if (j->second.getCount() > 0) histograms.h_timeslice.h_dom_mean_rates[ts_type] -> Fill (i->first , j->first , j->second.getMean() ) ; } } } /* * Checks through the use of a JTreeScanner, if summary slices are present in the run file. * In case they are, the corresponding tree is iterated. * */ void readSummaryData() { JTreeScanner scanner(inputFile, numberOfSummaryslices); if (scanner.hasNext()) { histograms.initialize_summary_histograms(); scanner.rewind(); iterateSummarysliceTree(scanner); } } /* * Function template that checks through the use of a JTreeScanner, if objects of different timeslice classes are present in the run file. * In case they are, the corresponding tree is iterated. * */ template void readTimesliceData() { JTreeScanner scanner(inputFile, numberOfTimeslices); if(scanner.hasNext()) { histograms.initialize_timeslice_histograms (); scanner.rewind(); iterateTimesliceTree(scanner); } } /* * Function template that checks through the use of a JTreeScanner, if JDAQEvent objects are present in the run file. * In case they are, the corresponding tree is read. * */ void readEvents() { JTreeScanner scanner(inputFile, numberOfEvents); if(scanner.hasNext()) { histograms.initialize_trigger_histograms(); scanner.rewind(); iterateEventTree(scanner); } } /* * Returns the histograms produced from the data in the file. */ JRA_Histograms getHistograms(){ return histograms ; } }; #endif