//////////////////////////////////////////////////////////////////// /// \class RAT::DU::EffectiveVelocity /// /// \brief Return the total transit time given the effective group velocities /// /// \author Phil G Jones /// \author Rob Stainforth -- contact person /// /// REVISION HISTORY: /// - 21 July 2011 : New File. /// - 2014-03-01 : P G Jones - refactor as part of ds review, moved from ds. /// - 2014-07-14 J.R.Wilson - change name of scint volume to inner_av /// - 2014-04-02 : M Mottram - updated to work with partial fill. /// - 2023-27-12 : W Parker - allow different velocities at different event radii /// /// /// \details This class loads effective velocity information from /// the database and will calculate the transit time taken given /// the loaded velocities. /// It can be used in RAT, ROOT or external programs that link to /// the libRATEvent library. /// //////////////////////////////////////////////////////////////////// #ifndef __RAT_DU_EffectiveVelocity__ #define __RAT_DU_EffectiveVelocity__ #include namespace RAT { namespace DU { class EffectiveVelocity : public TObject { public: /// Called at the start of a run, loads from the database void BeginOfRun(); /// Calculate the transit time by distance in the standard 3 SNO+ volumes /// /// @param[in] distInInnerAV the distance in the scintillator (inner AV) volume /// @param[in] distInAV the distance in the AV /// @param[in] distInWater the distance in the water (cavity) /// @param[in] nhits the nhits of the event /// @param[in] eventRadius the radius of the event /// @return the transit time inline double CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater ) const; inline double CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater, const int nhits ) const; inline double CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater, const double eventRadius ) const; inline double CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater, const int nhits, const double eventRadius ) const; /// Get the inner_av volume effective velocity /// /// @return the inner_av volume effective velocity double GetInnerAVVelocity() const { return fInnerAVVelocity.at(0); } /// Get the inner_av volume effective velocity for a given radius /// /// @return the inner_av volume effective velocity double GetInnerAVVelocity( const double eventRadius ); /// Get the av volume effective velocity /// /// @return the av volume effective velocity double GetAVVelocity() const { return fAVVelocity; } /// Get the water volume effective velocity /// /// @return the water volume effective velocity double GetWaterVelocity() const { return fWaterVelocity; } /// Get the offset time, represents transit time in PMTs /// /// @return the offset time double GetOffset() const { return fOffset; } // This ROOT macro adds dictionary methods to this class. // The number is 0 as this class is never, and should never be written to disc. // It assumes this class has no virtual methods, use ClassDef if change this. ClassDefNV( EffectiveVelocity, 0 ); private: std::vector fInnerAVVelocity; ///< Effective target (inner_av) effective velocity std::vector fInnerAVGradient; ///< Gradient for nhit scaling of inner_av effective velocity std::vector fInnerAVOffset; ///< Offset for nhit scaling of inner_av effective velocity double fAVVelocity; ///< Effective av effective velocity double fWaterVelocity; ///< Effective water effective velocity double fOffset; ///< Offset required from fit, time taken on average in PMT. double fScaleInnerAVVel = false; ///< Gets set to true if want to scale effective velocity with nhits unsigned int fNumberOfShells = 0; ///< Number of shells with different effective velocities std::vector < std::pair > fRadialRanges; // Range of radii each velocity applies to }; double EffectiveVelocity::CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater ) const { return distInInnerAV / fInnerAVVelocity.at(0) + distInAV / fAVVelocity + distInWater / fWaterVelocity + fOffset; } double EffectiveVelocity::CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater, const int nhits ) const { if( nhits < 0){ warn << "EffectiveVelocity::CalcByDistance: Nhits is negative. Using non-nhit-scaled effective velocity for scintillator\n"; return CalcByDistance(distInInnerAV, distInAV, distInWater); } if( !fScaleInnerAVVel || fInnerAVGradient.size() == 0 || fInnerAVOffset.size() == 0 ) return CalcByDistance(distInInnerAV, distInAV, distInWater); double innerAVVelocity = fInnerAVGradient.at(0) * nhits + fInnerAVOffset.at(0); return distInInnerAV / innerAVVelocity + distInAV / fAVVelocity + distInWater / fWaterVelocity + fOffset; } double EffectiveVelocity::CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater, const double eventRadius ) const { if( !fScaleInnerAVVel || fNumberOfShells == 0 ) return CalcByDistance(distInInnerAV, distInAV, distInWater); unsigned int shell_number = 0; for(unsigned int i_shell = 0; i_shell < fNumberOfShells; i_shell++){ if( eventRadius >= fRadialRanges.at(i_shell).first && eventRadius < fRadialRanges.at(i_shell).second ) { shell_number = i_shell; break; } } return distInInnerAV / fInnerAVVelocity.at(shell_number) + distInAV / fAVVelocity + distInWater / fWaterVelocity + fOffset; } double EffectiveVelocity::CalcByDistance( const double distInInnerAV, const double distInAV, const double distInWater, const int nhits, const double eventRadius ) const { if( nhits < 0){ warn << "EffectiveVelocity::CalcByDistance: Nhits is negative. Using non-nhit-scaled effective velocity for scintillator\n"; return CalcByDistance(distInInnerAV, distInAV, distInWater); } if( !fScaleInnerAVVel ) return CalcByDistance(distInInnerAV, distInAV, distInWater, eventRadius); if( fNumberOfShells == 0 ) return CalcByDistance(distInInnerAV, distInAV, distInWater, nhits); unsigned int shell_number = 0; for(unsigned int i_shell = 0; i_shell < fNumberOfShells; i_shell++){ if( eventRadius >= fRadialRanges.at(i_shell).first && eventRadius < fRadialRanges.at(i_shell).second ) { shell_number = i_shell; break; } } double innerAVVelocity = fInnerAVGradient.at(shell_number) * nhits + fInnerAVOffset.at(shell_number); return distInInnerAV / innerAVVelocity + distInAV / fAVVelocity + distInWater / fWaterVelocity + fOffset; } } // namespace DU } // namespace RAT #endif