/*************************************************************************** * GEnergy.cpp - Energy class * * ----------------------------------------------------------------------- * * copyright (C) 2010-2014 by Juergen Knoedlseder * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ***************************************************************************/ /** * @file GEnergy.cpp * @brief Energy value class implementation * @author Juergen Knoedlseder */ /* __ Includes ___________________________________________________________ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "GEnergy.hpp" #include "GTools.hpp" #include "GException.hpp" /* __ Constants __________________________________________________________ */ /* __ Method name definitions ____________________________________________ */ #define G_CONSTRUCT "GEnergy::GEnergy(double&, std::string&)" #define G_OPERATOR1 "GEnergy::operator()(double&, std::string&)" #define G_OPERATOR2 "GEnergy::operator()(std::string&)" #define G_ANGSTROM_GET "GEnergy::Angstrom()" #define G_ANGSTROM_SET "GEnergy::Angstrom(double&)" #define G_LOG10_GET "GEnergy::log10(std::string&)" #define G_LOG10_SET "GEnergy::log10(double&, std::string&)" /* __ Macros _____________________________________________________________ */ /* __ Coding definitions _________________________________________________ */ /* __ Debug definitions __________________________________________________ */ /*========================================================================== = = = Constructors/destructors = = = ==========================================================================*/ /***********************************************************************//** * @brief Void constructor ***************************************************************************/ GEnergy::GEnergy(void) { // Initialise private members init_members(); // Return return; } /***********************************************************************//** * @brief Copy constructor * * @param[in] eng Energy. ***************************************************************************/ GEnergy::GEnergy(const GEnergy& eng) { // Initialise private members init_members(); // Copy members copy_members(eng); // Return return; } /***********************************************************************//** * @brief Energy constructor * * @param[in] eng Energy. * @param[in] unit Energy unit (one of erg(s), keV, MeV, GeV, TeV). * * Construct energy from an energy value and unit. The constructor interprets * the unit string and performs automatic conversion of the energy value. ***************************************************************************/ GEnergy::GEnergy(const double& eng, const std::string& unit) { // Initialise private members init_members(); // Set energy according to unit string this->operator()(eng, unit); // Return return; } /***********************************************************************//** * @brief Destructor ***************************************************************************/ GEnergy::~GEnergy(void) { // Free members free_members(); // Return return; } /*========================================================================== = = = Operators = = = ==========================================================================*/ /***********************************************************************//** * @brief Assignment operator * * @param[in] eng Energy. * @return Energy. ***************************************************************************/ GEnergy& GEnergy::operator=(const GEnergy& eng) { // Execute only if object is not identical if (this != &eng) { // Free members free_members(); // Initialise private members for clean destruction init_members(); // Copy members copy_members(eng); } // endif: object was not identical // Return return *this; } /***********************************************************************//** * @brief Unit set operator * * @param[in] eng Energy. * @param[in] unit Energy unit (one of erg(s), keV, MeV, GeV, TeV, Angstrom). * * @exception GException::invalid_argument * Invalid energy unit specified. * * Construct energy from an energy value and unit. The constructor interprets * the unit string and performs automatic conversion of the energy value. ***************************************************************************/ void GEnergy::operator()(const double& eng, const std::string& unit) { // Set energy according to unit string std::string eunit = gammalib::strip_whitespace(gammalib::tolower(unit)); if (eunit == "erg" || eunit == "ergs") { this->erg(eng); } else if (eunit == "kev") { this->keV(eng); } else if (eunit == "mev") { this->MeV(eng); } else if (eunit == "gev") { this->GeV(eng); } else if (eunit == "tev") { this->TeV(eng); } else if (eunit == "angstrom") { this->Angstrom(eng); } else { throw GException::invalid_argument(G_OPERATOR1, unit, "Valid energy units are \"erg(s)\", \"keV\", \"MeV\"," " \"GeV\", \"TeV\", or \"Angstrom\" (case insensitive)."); } // Return return; } /***********************************************************************//** * @brief Unit access operator * * @param[in] unit Energy unit (one of erg(s), keV, MeV, GeV, TeV, Angstrom). * @return Energy in requested units. * * @exception GException::invalid_argument * Invalid energy unit specified. * * Returns the energy in the requested units. ***************************************************************************/ double GEnergy::operator()(const std::string& unit) const { // Initialise energy double energy = 0.0; // Set energy according to unit string std::string eunit = gammalib::tolower(unit); if (eunit == "erg" || eunit == "ergs") { energy = this->erg(); } else if (eunit == "kev") { energy = this->keV(); } else if (eunit == "mev") { energy = this->MeV(); } else if (eunit == "gev") { energy = this->GeV(); } else if (eunit == "tev") { energy = this->TeV(); } else if (eunit == "angstrom") { energy = this->Angstrom(); } else { throw GException::invalid_argument(G_OPERATOR2, unit, "Valid energy units are \"erg(s)\", \"keV\", \"MeV\"," " \"GeV\", \"TeV\", or \"Angstrom\" (case insensitive)."); } // Return energy return energy; } /*========================================================================== = = = Public methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Clear instance ***************************************************************************/ void GEnergy::clear(void) { // Free members free_members(); // Initialise private members init_members(); // Return return; } /***********************************************************************//** * @brief Clone object * * @return Pointer to deep copy of energy. ***************************************************************************/ GEnergy* GEnergy::clone(void) const { // Clone this image return new GEnergy(*this); } /***********************************************************************//** * @brief Return energy in erg * * @return Energy in erg. ***************************************************************************/ double GEnergy::erg(void) const { // Compute energy double energy = m_energy * gammalib::MeV2erg; // Return energy return energy; } /***********************************************************************//** * @brief Return energy in keV * * @return Energy in keV. ***************************************************************************/ double GEnergy::keV(void) const { // Compute energy double energy = m_energy * 1.0e+3; // Return energy return energy; } /***********************************************************************//** * @brief Return energy in MeV * * @return Energy in MeV. ***************************************************************************/ double GEnergy::MeV(void) const { // Return energy return m_energy; } /***********************************************************************//** * @brief Return energy in GeV * * @return Energy in GeV. ***************************************************************************/ double GEnergy::GeV(void) const { // Compute energy double energy = m_energy * 1.0e-3; // Return energy return energy; } /***********************************************************************//** * @brief Return energy in TeV * * @return Energy in TeV. ***************************************************************************/ double GEnergy::TeV(void) const { // Compute energy double energy = m_energy * 1.0e-6; // Return energy return energy; } /***********************************************************************//** * @brief Return energy as wavelength in Angstrom * * @return Energy as wavelength in Angstrom (1e-10 metres). * * @exception GException::invalid_value * Cannot convert zero energy into a wavelength. ***************************************************************************/ double GEnergy::Angstrom(void) const { // Throw exception if energy is zero if (m_energy == 0) { throw GException::invalid_value(G_ANGSTROM_GET, "Cannot convert energy of 0 MeV into Angstrom."); } // Compute wavelength double wavelength = gammalib::MeV2Angstrom/m_energy; // Return wavelength in Angstrom return wavelength; } /***********************************************************************//** * @brief Return log10 of energy in erg * * @return Energy in log10 erg. * * Returns the log10 of the energy in erg. ***************************************************************************/ double GEnergy::log10erg(void) const { // Set offset const double offset = std::log10(gammalib::MeV2erg); // Return log10 energy return (log10MeV()+offset); } /***********************************************************************//** * @brief Return log10 of energy in keV * * @return Energy in log10 keV. * * Returns the log10 of the energy in keV. ***************************************************************************/ double GEnergy::log10keV(void) const { // Return log10 energy return (log10MeV()+3.0); } /***********************************************************************//** * @brief Return log10 of energy in MeV * * @return Energy in log10 MeV. * * Returns the log10 of the energy in MeV. The result is stored internally * and not recomputed when the method is called again with the same energy * value. This speeds up computation. In case that the energy is not positive * the method returns DBL_MIN. ***************************************************************************/ double GEnergy::log10MeV(void) const { // If required compute log10 of energy. if (!m_has_log10) { m_elog10 = (m_energy > 0.0) ? std::log10(m_energy) : DBL_MIN; m_has_log10 = true; } // Return log10 energy return m_elog10; } /***********************************************************************//** * @brief Return log10 of energy in GeV * * @return Energy in log10 GeV. * * Returns the log10 of the energy in GeV. ***************************************************************************/ double GEnergy::log10GeV(void) const { // Return log10 energy return (log10MeV()-3.0); } /***********************************************************************//** * @brief Return log10 of energy in TeV * * @return Energy in log10 TeV. * * Returns the log10 of the energy in TeV. ***************************************************************************/ double GEnergy::log10TeV(void) const { // Return log10 energy return (log10MeV()-6.0); } /***********************************************************************//** * @brief Set log10 of energy with unit specification * * @param[in] unit Unit of log10 of energy. * @return eng log10 of energy. * * @exception GException::invalid_argument * Unit argument is not valid. ***************************************************************************/ double GEnergy::log10(const std::string& unit) const { // Initialise result double logE = 0.0; // Set energy according to unit string std::string eunit = gammalib::tolower(unit); if (eunit == "erg" || eunit == "ergs") { logE = this->log10erg(); } else if (eunit == "kev") { logE = this->log10keV(); } else if (eunit == "mev") { logE = this->log10MeV(); } else if (eunit == "gev") { logE = this->log10GeV(); } else if (eunit == "tev") { logE = this->log10TeV(); } else { throw GException::invalid_argument(G_LOG10_GET, unit, "Valid energy units are \"erg(s)\", \"keV\", \"MeV\"," " \"GeV\", or \"TeV\" (case insensitive)."); } // Return return logE; } /***********************************************************************//** * @brief Set energy in erg * * @param[in] eng Energy in erg. ***************************************************************************/ void GEnergy::erg(const double& eng) { // Set energy m_energy = eng * gammalib::erg2MeV; // Signals that log10 of energy is not valid m_has_log10 = false; // Return return; } /***********************************************************************//** * @brief Set energy in keV * * @param[in] eng Energy in keV. ***************************************************************************/ void GEnergy::keV(const double& eng) { // Set energy m_energy = eng * 1.0e-3; // Signals that log10 of energy is not valid m_has_log10 = false; // Return return; } /***********************************************************************//** * @brief Set energy in MeV * * @param[in] eng Energy in MeV. ***************************************************************************/ void GEnergy::MeV(const double& eng) { // Set energy m_energy = eng; // Signals that log10 of energy is not valid m_has_log10 = false; // Return return; } /***********************************************************************//** * @brief Set energy in GeV * * @param[in] eng Energy in GeV. ***************************************************************************/ void GEnergy::GeV(const double& eng) { // Set energy m_energy = eng * 1.0e+3; // Signals that log10 of energy is not valid m_has_log10 = false; // Return return; } /***********************************************************************//** * @brief Set energy in TeV * * @param[in] eng Energy in TeV. ***************************************************************************/ void GEnergy::TeV(const double& eng) { // Set energy m_energy = eng * 1.0e+6; // Signals that log10 of energy is not valid m_has_log10 = false; // Return return; } /***********************************************************************//** * @brief Set energy from wavelength in Angstrom * * @param[in] wavelength Wavelength in Angstrom. * * @exception GException::invalid_argument * Cannot set energy from zero wavelength. ***************************************************************************/ void GEnergy::Angstrom(const double& wavelength) { // Throw exception if wavelength is zero if (wavelength == 0) { throw GException::invalid_argument(G_ANGSTROM_SET, "Cannot set energy from a wavelength that is zero."); } // Set energy m_energy = gammalib::MeV2Angstrom / wavelength; // Signals that log10 of energy is not valid m_has_log10 = false; // Return return; } /***********************************************************************//** * @brief Set log10 of energy in erg * * @param[in] eng log10 of energy in erg. ***************************************************************************/ void GEnergy::log10erg(const double& eng) { // Set offset const double offset = std::log10(gammalib::MeV2erg); // Set energy log10MeV(eng-offset); // Return return; } /***********************************************************************//** * @brief Set log10 of energy in keV * * @param[in] eng log10 of energy in keV. ***************************************************************************/ void GEnergy::log10keV(const double& eng) { // Set energy log10MeV(eng-3.0); // Return return; } /***********************************************************************//** * @brief Set log10 of energy in MeV * * @param[in] eng log10 of energy in MeV. ***************************************************************************/ void GEnergy::log10MeV(const double& eng) { // Set energy m_elog10 = eng; m_energy = std::pow(10.0, eng); m_has_log10 = true; // Return return; } /***********************************************************************//** * @brief Set log10 of energy in GeV * * @param[in] eng log10 of energy in GeV. ***************************************************************************/ void GEnergy::log10GeV(const double& eng) { // Set energy log10MeV(eng+3.0); // Return return; } /***********************************************************************//** * @brief Set log10 of energy in TeV * * @param[in] eng log10 of energy in TeV. ***************************************************************************/ void GEnergy::log10TeV(const double& eng) { // Set energy log10MeV(eng+6.0); // Return return; } /***********************************************************************//** * @brief Set log10 of energy with unit specification * * @param[in] eng log10 of energy. * @param[in] unit Unit of log10 of energy. * * @exception GException::invalid_argument * Unit argument is not valid. ***************************************************************************/ void GEnergy::log10(const double& eng, const std::string& unit) { // Set energy according to unit string std::string eunit = gammalib::tolower(unit); if (eunit == "erg" || eunit == "ergs") { this->log10erg(eng); } else if (eunit == "kev") { this->log10keV(eng); } else if (eunit == "mev") { this->log10MeV(eng); } else if (eunit == "gev") { this->log10GeV(eng); } else if (eunit == "tev") { this->log10TeV(eng); } else { throw GException::invalid_argument(G_LOG10_SET, unit, "Valid energy units are \"erg(s)\", \"keV\", \"MeV\"," " \"GeV\", or \"TeV\" (case insensitive)."); } // Return return; } /***********************************************************************//** * @brief Print energy * * @param[in] chatter Chattiness (defaults to NORMAL). * @return String containing energy information. ***************************************************************************/ std::string GEnergy::print(const GChatter& chatter) const { // Initialise result string std::string result; // Continue only if chatter is not silent if (chatter != SILENT) { // Append energy if (TeV() >= 1000.0) { result.append(gammalib::str(TeV()/1000.0)+" PeV"); } else if (GeV() >= 1000.0) { result.append(gammalib::str(TeV())+" TeV"); } else if (MeV() >= 1000.0) { result.append(gammalib::str(GeV())+" GeV"); } else if (keV() >= 1000.0) { result.append(gammalib::str(MeV())+" MeV"); } else { result.append(gammalib::str(keV())+" keV"); } // VERBOSE: append energy and log10 energy if (chatter == VERBOSE) { result.append(" (E="+gammalib::str(m_energy)); if (m_has_log10) { result.append(", log10(E)="+gammalib::str(m_elog10)+")"); } else { result.append(", no log10(E) value)"); } } } // endif: chatter was not silent // Return return result; } /*========================================================================== = = = Private methods = = = ==========================================================================*/ /***********************************************************************//** * @brief Initialise class members ***************************************************************************/ void GEnergy::init_members(void) { // Initialise members m_energy = 0.0; m_elog10 = DBL_MIN; m_has_log10 = false; // Return return; } /***********************************************************************//** * @brief Copy class members * * @param[in] eng Energy. ***************************************************************************/ void GEnergy::copy_members(const GEnergy& eng) { // Copy time m_energy = eng.m_energy; m_elog10 = eng.m_elog10; m_has_log10 = eng.m_has_log10; // Return return; } /***********************************************************************//** * @brief Delete class members ***************************************************************************/ void GEnergy::free_members(void) { // Return return; }