//////////////////////////////////////////////////////////////////// /// \file PlotHitTimeResiduals.cc /// /// \brief Functions to plot hit time residuals. /// /// \author P G Jones /// /// REVISION HISTORY:\n /// 2014-03-27 : P G Jones - First Revision.\n /// /// \details EV Calibrated hit times are plotted minus transit times /// based on the MC position or the fitted position. /// //////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /// Plot the hit time residuals for the MC position /// /// @param[in] fileName of the RAT::DS root file to analyse /// @return the histogram plot TH1D* PlotHitTimeResidualsMCPosition( const std::string& fileName ) { TH1D* hHitTimeResiduals = new TH1D( "hHitTimeResidualsMC", "Hit time residuals using the MC position", 1000, -500.0, 500.0 ); // If this is being done on data that does not require remote database connection // eg.: a simple simulation with default run number (0) // We can disable the remote connections: // // NOTE: Don't do this if you are using real data!!! RAT::DB::Get()->SetAirplaneModeStatus(true); RAT::DU::DSReader dsReader( fileName ); size_t fPSUPSystemId = RAT::DU::Point3D::GetSystemId("innerPMT"); // RAT::DU::Utility::Get()->GetLightPathCalculator() must be called *after* the RAT::DU::DSReader constructor. RAT::DU::LightPathCalculator lightPath = RAT::DU::Utility::Get()->GetLightPathCalculator(); // To calculate the light's path const RAT::DU::GroupVelocity& groupVelocity = RAT::DU::Utility::Get()->GetGroupVelocity(); // To get the group velocity const RAT::DU::PMTInfo& pmtInfo = RAT::DU::Utility::Get()->GetPMTInfo(); // The PMT positions etc.. for( size_t iEntry = 0; iEntry < dsReader.GetEntryCount(); iEntry++ ) { const RAT::DS::Entry& rDS = dsReader.GetEntry( iEntry ); RAT::DU::Point3D eventPosition(fPSUPSystemId, rDS.GetMC().GetMCParticle(0).GetPosition()); // At least 1 is somewhat guaranteed for( size_t iEV = 0; iEV < rDS.GetEVCount(); iEV++ ) { const RAT::DS::EV& rEV = rDS.GetEV( iEV ); const RAT::DS::CalPMTs& calibratedPMTs = rEV.GetCalPMTs(); for( size_t iPMT = 0; iPMT < calibratedPMTs.GetCount(); iPMT++ ) { const RAT::DS::PMTCal& pmtCal = calibratedPMTs.GetPMT( iPMT ); RAT::DU::Point3D pmtPos(fPSUPSystemId, pmtInfo.GetPosition( pmtCal.GetID() ) ); lightPath.CalcByPosition( eventPosition, pmtPos ); double distInInnerAV = lightPath.GetDistInInnerAV(); double distInAV = lightPath.GetDistInAV(); double distInWater = lightPath.GetDistInWater(); const double transitTime = groupVelocity.CalcByDistance( distInInnerAV, distInAV, distInWater ); // Assumes a 400nm photon // Time residuals estimate the photon emission time relative to the event start so subtract off the transit time // hit times are relative to the trigger time, which will depend on event time and detector position so correct for that to line up events // The 390ns corrects for the electronics delays and places the pulse in the middle of the window hHitTimeResiduals->Fill( pmtCal.GetTime() - transitTime - 390 + rDS.GetMCEV(iEV).GetGTTime()); } } } hHitTimeResiduals->GetYaxis()->SetTitle( "Count per 1 ns bin" ); hHitTimeResiduals->GetXaxis()->SetTitle( "Hit time residuals [ns]" ); hHitTimeResiduals->Draw(); return hHitTimeResiduals; } /// Plot the hit time residuals for the fit position /// /// @param[in] fileName of the RAT::DS root file to analyse /// @return the histogram plot TH1D* PlotHitTimeResidualsFitPosition( const std::string& fileName, std::string fitName = "") { TH1D* hHitTimeResiduals = new TH1D( "hHitTimeResidualsFit", "Hit time residuals using the Fit position", 1000, -500.0, 500.0 ); // If this is being done on data that does not require remote database connection // eg.: a simple simulation with default run number (0) // We can disable the remote connections: // // NOTE: Don't do this if you are using real data!!! RAT::DB::Get()->SetAirplaneModeStatus(true); RAT::DU::DSReader dsReader( fileName ); size_t fPSUPSystemId = RAT::DU::Point3D::GetSystemId("innerPMT"); // RAT::DU::Utility::Get()->GetLightPathCalculator() must be called *after* the RAT::DU::DSReader constructor. RAT::DU::LightPathCalculator lightPath = RAT::DU::Utility::Get()->GetLightPathCalculator(); // To calculate the light's path const RAT::DU::GroupVelocity& groupVelocity = RAT::DU::Utility::Get()->GetGroupVelocity(); // To get the group velocity const RAT::DU::PMTInfo& pmtInfo = RAT::DU::Utility::Get()->GetPMTInfo(); // The PMT positions etc.. for( size_t iEntry = 0; iEntry < dsReader.GetEntryCount(); iEntry++ ) { const RAT::DS::Entry& rDS = dsReader.GetEntry( iEntry ); for( size_t iEV = 0; iEV < rDS.GetEVCount(); iEV++ ) { const RAT::DS::EV& rEV = rDS.GetEV( iEV ); // grab the fit information if(fitName == "") fitName = rEV.GetDefaultFitName(); RAT::DU::Point3D eventPosition(fPSUPSystemId); double eventTime; try{ const RAT::DS::FitVertex& rVertex = rEV.GetFitResult(fitName).GetVertex(0); if(!(rVertex.ValidPosition() && rVertex.ValidTime())) continue; // fit invalid eventPosition.SetXYZ(fPSUPSystemId, rVertex.GetPosition()); eventTime = rVertex.GetTime(); } catch(const RAT::DS::FitCollection::NoResultError&){ // no fit result by the name of fitName continue; } catch (const RAT::DS::FitResult::NoVertexError&){ // no fit vertex continue; } catch(const RAT::DS::FitVertex::NoValueError&){ // position or time missing continue; } // DataNotFound --> implies no fit results are present, don't catch. // calculate time residuals const RAT::DS::CalPMTs& calibratedPMTs = rEV.GetCalPMTs(); for( size_t iPMT = 0; iPMT < calibratedPMTs.GetCount(); iPMT++ ) { const RAT::DS::PMTCal& pmtCal = calibratedPMTs.GetPMT( iPMT ); RAT::DU::Point3D pmtPos(fPSUPSystemId, pmtInfo.GetPosition( pmtCal.GetID() ) ); lightPath.CalcByPosition( eventPosition, pmtPos ); double distInInnerAV = lightPath.GetDistInInnerAV(); double distInAV = lightPath.GetDistInAV(); double distInWater = lightPath.GetDistInWater(); const double transitTime = groupVelocity.CalcByDistance( distInInnerAV, distInAV, distInWater ); // Assumes a 400nm photon // Time residuals estimate the photon emission time relative to the event start so subtract off the transit time and eventTime hHitTimeResiduals->Fill( pmtCal.GetTime() - transitTime - eventTime); } } } hHitTimeResiduals->GetYaxis()->SetTitle( "Count per 1 ns bin" ); hHitTimeResiduals->GetXaxis()->SetTitle( "Hit time residuals [ns]" ); hHitTimeResiduals->Draw(); return hHitTimeResiduals; } /// Plot both the MC and Fitted position residuals /// /// @param[in] fileName of the RAT::DS root file to analyse void PlotHitTimeResiduals( const std::string& fileName ) { gStyle->SetFillColor( kWhite ); TCanvas* c1 = new TCanvas(); TH1D* mc = PlotHitTimeResidualsMCPosition( fileName ); TH1D* fit = PlotHitTimeResidualsFitPosition( fileName ); mc->Draw(); fit->SetLineColor( kGreen + 2 ); fit->Draw("SAME"); TLegend* t1 = new TLegend( 0.7, 0.7, 0.9, 0.9 ); t1->AddEntry( mc, "MC Position", "l" ); t1->AddEntry( fit, "Fit Position", "l" ); t1->Draw(); c1->Update(); }