#ifndef DETECTOR_H #define DETECTOR_H #include #include #include namespace manticore { // Forward reference. class Graybody; /** \brief %Detector base class. Concrete detector instances are characterized by the following: - reference wavelength - reference bandwidth - spectral response curve - color correction factor By default this class will compute the reference bandwidth and color correction factor automatically from the response curve using the equations \f[ {\Delta\lambda\over \lambda_0} = {\Delta\nu\over \nu_0} = \int R(\nu){d\nu\over\nu} \f] and \f[ CCF = {\int F_\nu R(\nu)d\nu\over \Delta\nu F_{\nu_0}}, \f] where \f$\lambda_0\f$ and \f$\nu_0\f$ are the reference wavelength and frequency, respectively, and \f$F_\nu\f$ is the model flux density under consideration. If the color correction prescription is inappropriate, concrete detector classes can override the calculation. \note This class assumes all integrals are performed in frequency space; but to match common reference, the nominal band center and width are given as wavelengths. Once initialized, an instance may be safely shared among multiple threads (but ccf() is thread-safe only if the Graybody instance is thread-local). \warning Clients **must** call init() on instances to populate detector parameters prior to any further usage. */ class Detector { public: /// Default constructor. Detector(bool extend = true) noexcept : extend_(extend) { } /// Destructor. ~Detector() { if (integ_) { gsl_integration_workspace_free(integ_); } if (spline_) { gsl_spline_free(spline_); } } /// Official detector name. virtual std::string name() const = 0; /// Initializes detector characteristics. virtual void init(); /// Reference band center frequency (Hz). virtual double freqBand() const noexcept { return center_; } /// Effective flux-conversion bandwidth \f$\Delta\nu\f$ (Hz). /// \details /// The band-weighted total flux \f$F\f$ is related to the reported /// flux density \f$f_\nu\f$ by \f$F = \Delta\nu\cdotf_\nu\f$. virtual double freqWidth() const noexcept { return width_; } /// Frequency range containing significant response. virtual std::pair freqRange() const noexcept { return freqRange_; } /// Whether extended source detection is enabled. bool isExtended() const noexcept { return extend_; } /// Absolute spectral response function. /// \param[in] nu Frequency (Hz). virtual double response(double nu) const; /// Color correction factor. /// \param[in] gray Graybody model. /// \param[in] T Temperature (K). /// \param[in] Sigma Mass surface density (g/cm^2). virtual double ccf(const Graybody &gray, double T, double Sigma = 1.0) const; protected: /// Integral subdivision limit. static constexpr size_t subLimit = 512; /// Integration rule key. static constexpr int intKey = GSL_INTEG_GAUSS41; /// Detector response table type. using tableType = std::vector>; /// Calculates effective bandwidth using standard prescription. void calcWidth(); /// Response edge frequencies (Hz). std::pair freqRange_; /// Spectral response table. tableType resp_; /// Default to extended (else point) source observation. bool extend_; double center_ = 0.0, ///< Effective band center (Hz). width_ = 0.0; ///< Effective (flux) bandwidth (Hz). /// Integration workspace. gsl_integration_workspace *integ_ = nullptr; /// Response interpolator. gsl_spline *spline_ = nullptr; }; } // namespace manticore #endif // DETECTOR_H