src/obs/GEnergy.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *                        GEnergy.cpp - Energy class                       *
00003  * ----------------------------------------------------------------------- *
00004  *  copyright (C) 2010-2014 by Juergen Knoedlseder                         *
00005  * ----------------------------------------------------------------------- *
00006  *                                                                         *
00007  *  This program is free software: you can redistribute it and/or modify   *
00008  *  it under the terms of the GNU General Public License as published by   *
00009  *  the Free Software Foundation, either version 3 of the License, or      *
00010  *  (at your option) any later version.                                    *
00011  *                                                                         *
00012  *  This program is distributed in the hope that it will be useful,        *
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
00015  *  GNU General Public License for more details.                           *
00016  *                                                                         *
00017  *  You should have received a copy of the GNU General Public License      *
00018  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
00019  *                                                                         *
00020  ***************************************************************************/
00021 /**
00022  * @file GEnergy.cpp
00023  * @brief Energy value class implementation
00024  * @author Juergen Knoedlseder
00025  */
00026 
00027 /* __ Includes ___________________________________________________________ */
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 #include <cfloat>
00032 #include <cmath>
00033 #include "GEnergy.hpp"
00034 #include "GTools.hpp"
00035 #include "GException.hpp"
00036 
00037 /* __ Constants __________________________________________________________ */
00038 
00039 /* __ Method name definitions ____________________________________________ */
00040 #define G_CONSTRUCT                 "GEnergy::GEnergy(double&, std::string&)"
00041 #define G_OPERATOR1              "GEnergy::operator()(double&, std::string&)"
00042 #define G_OPERATOR2                       "GEnergy::operator()(std::string&)"
00043 #define G_ANGSTROM_GET                                  "GEnergy::Angstrom()"
00044 #define G_ANGSTROM_SET                           "GEnergy::Angstrom(double&)"
00045 #define G_LOG10_GET                            "GEnergy::log10(std::string&)"
00046 #define G_LOG10_SET                   "GEnergy::log10(double&, std::string&)"
00047 
00048 /* __ Macros _____________________________________________________________ */
00049 
00050 /* __ Coding definitions _________________________________________________ */
00051 
00052 /* __ Debug definitions __________________________________________________ */
00053 
00054 
00055 /*==========================================================================
00056  =                                                                         =
00057  =                         Constructors/destructors                        =
00058  =                                                                         =
00059  ==========================================================================*/
00060 
00061 /***********************************************************************//**
00062  * @brief Void constructor
00063  ***************************************************************************/
00064 GEnergy::GEnergy(void)
00065 {
00066     // Initialise private members
00067     init_members();
00068   
00069     // Return
00070     return;
00071 }
00072 
00073 
00074 /***********************************************************************//**
00075  * @brief Copy constructor
00076  *
00077  * @param[in] eng Energy.
00078  ***************************************************************************/
00079 GEnergy::GEnergy(const GEnergy& eng)
00080 { 
00081     // Initialise private members
00082     init_members();
00083 
00084     // Copy members
00085     copy_members(eng);
00086 
00087     // Return
00088     return;
00089 }
00090 
00091 
00092 /***********************************************************************//**
00093  * @brief Energy constructor
00094  *
00095  * @param[in] eng Energy.
00096  * @param[in] unit Energy unit (one of erg(s), keV, MeV, GeV, TeV).
00097  *
00098  * Construct energy from an energy value and unit. The constructor interprets
00099  * the unit string and performs automatic conversion of the energy value. 
00100  ***************************************************************************/
00101 GEnergy::GEnergy(const double& eng, const std::string& unit)
00102 { 
00103     // Initialise private members
00104     init_members();
00105 
00106     // Set energy according to unit string
00107     this->operator()(eng, unit);
00108 
00109     // Return
00110     return;
00111 }
00112 
00113 
00114 /***********************************************************************//**
00115  * @brief Destructor
00116  ***************************************************************************/
00117 GEnergy::~GEnergy(void)
00118 {
00119     // Free members
00120     free_members();
00121 
00122     // Return
00123     return;
00124 }
00125 
00126 
00127 /*==========================================================================
00128  =                                                                         =
00129  =                               Operators                                 =
00130  =                                                                         =
00131  ==========================================================================*/
00132 
00133 /***********************************************************************//**
00134  * @brief Assignment operator
00135  *
00136  * @param[in] eng Energy.
00137  * @return Energy.
00138  ***************************************************************************/
00139 GEnergy& GEnergy::operator=(const GEnergy& eng)
00140 { 
00141     // Execute only if object is not identical
00142     if (this != &eng) {
00143 
00144         // Free members
00145         free_members();
00146 
00147         // Initialise private members for clean destruction
00148         init_members();
00149 
00150         // Copy members
00151         copy_members(eng);
00152 
00153     } // endif: object was not identical
00154   
00155     // Return
00156     return *this;
00157 }
00158 
00159 
00160 /***********************************************************************//**
00161  * @brief Unit set operator
00162  *
00163  * @param[in] eng Energy.
00164  * @param[in] unit Energy unit (one of erg(s), keV, MeV, GeV, TeV, Angstrom).
00165  *
00166  * @exception GException::invalid_argument
00167  *            Invalid energy unit specified.
00168  *
00169  * Construct energy from an energy value and unit. The constructor interprets
00170  * the unit string and performs automatic conversion of the energy value. 
00171  ***************************************************************************/
00172 void GEnergy::operator()(const double& eng, const std::string& unit)
00173 { 
00174     // Set energy according to unit string
00175     std::string eunit = gammalib::strip_whitespace(gammalib::tolower(unit));
00176     if (eunit == "erg" || eunit == "ergs") {
00177         this->erg(eng);
00178     }
00179     else if (eunit == "kev") {
00180         this->keV(eng);
00181     }
00182     else if (eunit == "mev") {
00183         this->MeV(eng);
00184     }
00185     else if (eunit == "gev") {
00186         this->GeV(eng);
00187     }
00188     else if (eunit == "tev") {
00189         this->TeV(eng);
00190     }
00191     else if (eunit == "angstrom") {
00192         this->Angstrom(eng);
00193     }
00194     else {
00195         throw GException::invalid_argument(G_OPERATOR1, unit,
00196               "Valid energy units are \"erg(s)\", \"keV\", \"MeV\","
00197               " \"GeV\", \"TeV\", or \"Angstrom\" (case insensitive).");
00198     }
00199 
00200     // Return
00201     return;
00202 }
00203 
00204 
00205 /***********************************************************************//**
00206  * @brief Unit access operator
00207  *
00208  * @param[in] unit Energy unit (one of erg(s), keV, MeV, GeV, TeV, Angstrom).
00209  * @return Energy in requested units.
00210  *
00211  * @exception GException::invalid_argument
00212  *            Invalid energy unit specified.
00213  *
00214  * Returns the energy in the requested units.
00215  ***************************************************************************/
00216 double GEnergy::operator()(const std::string& unit) const
00217 { 
00218     // Initialise energy
00219     double energy = 0.0;
00220 
00221     // Set energy according to unit string
00222     std::string eunit = gammalib::tolower(unit);
00223     if (eunit == "erg" || eunit == "ergs") {
00224         energy = this->erg();
00225     }
00226     else if (eunit == "kev") {
00227         energy = this->keV();
00228     }
00229     else if (eunit == "mev") {
00230         energy = this->MeV();
00231     }
00232     else if (eunit == "gev") {
00233         energy = this->GeV();
00234     }
00235     else if (eunit == "tev") {
00236         energy = this->TeV();
00237     }
00238     else if (eunit == "angstrom") {
00239         energy = this->Angstrom();
00240     }
00241     else {
00242         throw GException::invalid_argument(G_OPERATOR2, unit,
00243               "Valid energy units are \"erg(s)\", \"keV\", \"MeV\","
00244               " \"GeV\", \"TeV\", or \"Angstrom\" (case insensitive).");
00245     }
00246   
00247     // Return energy
00248     return energy;
00249 }
00250 
00251 
00252 /*==========================================================================
00253  =                                                                         =
00254  =                             Public methods                              =
00255  =                                                                         =
00256  ==========================================================================*/
00257 
00258 /***********************************************************************//**
00259  * @brief Clear instance
00260  ***************************************************************************/
00261 void GEnergy::clear(void)
00262 {
00263     // Free members
00264     free_members();
00265 
00266     // Initialise private members
00267     init_members();
00268     
00269     // Return
00270     return; 
00271 }
00272 
00273 
00274 /***********************************************************************//**
00275  * @brief Clone object
00276  *
00277  * @return Pointer to deep copy of energy.
00278  ***************************************************************************/
00279 GEnergy* GEnergy::clone(void) const
00280 {
00281     // Clone this image
00282     return new GEnergy(*this);
00283 }
00284 
00285 
00286 /***********************************************************************//**
00287  * @brief Return energy in erg
00288  *
00289  * @return Energy in erg.
00290  ***************************************************************************/
00291 double GEnergy::erg(void) const
00292 {
00293     // Compute energy
00294     double energy = m_energy * gammalib::MeV2erg;
00295     
00296     // Return energy
00297     return energy; 
00298 }
00299 
00300 
00301 /***********************************************************************//**
00302  * @brief Return energy in keV
00303  *
00304  * @return Energy in keV.
00305  ***************************************************************************/
00306 double GEnergy::keV(void) const
00307 {
00308     // Compute energy
00309     double energy = m_energy * 1.0e+3;
00310     
00311     // Return energy
00312     return energy; 
00313 }
00314 
00315 
00316 /***********************************************************************//**
00317  * @brief Return energy in MeV
00318  *
00319  * @return Energy in MeV.
00320  ***************************************************************************/
00321 double GEnergy::MeV(void) const
00322 {
00323     // Return energy
00324     return m_energy;
00325 }
00326 
00327 
00328 /***********************************************************************//**
00329  * @brief Return energy in GeV
00330  *
00331  * @return Energy in GeV.
00332  ***************************************************************************/
00333 double GEnergy::GeV(void) const
00334 {
00335     // Compute energy
00336     double energy = m_energy * 1.0e-3;
00337     
00338     // Return energy
00339     return energy; 
00340 }
00341 
00342 
00343 /***********************************************************************//**
00344  * @brief Return energy in TeV
00345  *
00346  * @return Energy in TeV.
00347  ***************************************************************************/
00348 double GEnergy::TeV(void) const
00349 {
00350     // Compute energy
00351     double energy = m_energy * 1.0e-6;
00352     
00353     // Return energy
00354     return energy; 
00355 }
00356 
00357 
00358 /***********************************************************************//**
00359  * @brief Return energy as wavelength in Angstrom
00360  *
00361  * @return Energy as wavelength in Angstrom (1e-10 metres).
00362  *
00363  * @exception GException::invalid_value
00364  *            Cannot convert zero energy into a wavelength.
00365  ***************************************************************************/
00366 double GEnergy::Angstrom(void) const
00367 {
00368     // Throw exception if energy is zero
00369     if (m_energy == 0) {
00370         throw GException::invalid_value(G_ANGSTROM_GET,
00371               "Cannot convert energy of 0 MeV into Angstrom.");
00372     }
00373 
00374     // Compute wavelength
00375     double wavelength = gammalib::MeV2Angstrom/m_energy;
00376     
00377     // Return wavelength in Angstrom
00378     return wavelength; 
00379 }
00380 
00381 
00382 /***********************************************************************//**
00383  * @brief Return log10 of energy in erg
00384  *
00385  * @return Energy in log10 erg.
00386  *
00387  * Returns the log10 of the energy in erg.
00388  ***************************************************************************/
00389 double GEnergy::log10erg(void) const
00390 {
00391     // Set offset
00392     const double offset = std::log10(gammalib::MeV2erg);
00393 
00394     // Return log10 energy
00395     return (log10MeV()+offset); 
00396 }
00397 
00398 
00399 /***********************************************************************//**
00400  * @brief Return log10 of energy in keV
00401  *
00402  * @return Energy in log10 keV.
00403  *
00404  * Returns the log10 of the energy in keV.
00405  ***************************************************************************/
00406 double GEnergy::log10keV(void) const
00407 {
00408     // Return log10 energy
00409     return (log10MeV()+3.0); 
00410 }
00411 
00412 
00413 /***********************************************************************//**
00414  * @brief Return log10 of energy in MeV
00415  *
00416  * @return Energy in log10 MeV.
00417  *
00418  * Returns the log10 of the energy in MeV. The result is stored internally
00419  * and not recomputed when the method is called again with the same energy
00420  * value. This speeds up computation. In case that the energy is not positive
00421  * the method returns DBL_MIN.
00422  ***************************************************************************/
00423 double GEnergy::log10MeV(void) const
00424 {
00425     // If required compute log10 of energy.
00426     if (!m_has_log10) {
00427         m_elog10    = (m_energy > 0.0) ? std::log10(m_energy) : DBL_MIN;
00428         m_has_log10 = true;
00429     }
00430     
00431     // Return log10 energy
00432     return m_elog10; 
00433 }
00434 
00435 
00436 /***********************************************************************//**
00437  * @brief Return log10 of energy in GeV
00438  *
00439  * @return Energy in log10 GeV.
00440  *
00441  * Returns the log10 of the energy in GeV.
00442  ***************************************************************************/
00443 double GEnergy::log10GeV(void) const
00444 {
00445     // Return log10 energy
00446     return (log10MeV()-3.0); 
00447 }
00448 
00449 
00450 /***********************************************************************//**
00451  * @brief Return log10 of energy in TeV
00452  *
00453  * @return Energy in log10 TeV.
00454  *
00455  * Returns the log10 of the energy in TeV.
00456  ***************************************************************************/
00457 double GEnergy::log10TeV(void) const
00458 {
00459     // Return log10 energy
00460     return (log10MeV()-6.0); 
00461 }
00462 
00463 
00464 /***********************************************************************//**
00465  * @brief Set log10 of energy with unit specification
00466  *
00467  * @param[in] unit Unit of log10 of energy.
00468  * @return eng log10 of energy.
00469  *
00470  * @exception GException::invalid_argument
00471  *            Unit argument is not valid.
00472  ***************************************************************************/
00473 double GEnergy::log10(const std::string& unit) const
00474 {
00475     // Initialise result
00476     double logE = 0.0;
00477 
00478     // Set energy according to unit string
00479     std::string eunit = gammalib::tolower(unit);
00480     if (eunit == "erg" || eunit == "ergs") {
00481         logE = this->log10erg();
00482     }
00483     else if (eunit == "kev") {
00484         logE = this->log10keV();
00485     }
00486     else if (eunit == "mev") {
00487         logE = this->log10MeV();
00488     }
00489     else if (eunit == "gev") {
00490         logE = this->log10GeV();
00491     }
00492     else if (eunit == "tev") {
00493         logE = this->log10TeV();
00494     }
00495     else {
00496         throw GException::invalid_argument(G_LOG10_GET, unit,
00497               "Valid energy units are \"erg(s)\", \"keV\", \"MeV\","
00498               " \"GeV\", or \"TeV\" (case insensitive).");
00499     }
00500     
00501     // Return
00502     return logE;
00503 }
00504 
00505 
00506 /***********************************************************************//**
00507  * @brief Set energy in erg
00508  *
00509  * @param[in] eng Energy in erg.
00510  ***************************************************************************/
00511 void GEnergy::erg(const double& eng)
00512 {
00513     // Set energy
00514     m_energy = eng * gammalib::erg2MeV;
00515 
00516     // Signals that log10 of energy is not valid
00517     m_has_log10 = false;
00518 
00519     // Return
00520     return;
00521 }
00522 
00523 
00524 /***********************************************************************//**
00525  * @brief Set energy in keV
00526  *
00527  * @param[in] eng Energy in keV.
00528  ***************************************************************************/
00529 void GEnergy::keV(const double& eng)
00530 {
00531     // Set energy
00532     m_energy = eng * 1.0e-3;
00533     
00534     // Signals that log10 of energy is not valid
00535     m_has_log10 = false;
00536 
00537     // Return
00538     return;
00539 }
00540 
00541 
00542 /***********************************************************************//**
00543  * @brief Set energy in MeV
00544  *
00545  * @param[in] eng Energy in MeV.
00546  ***************************************************************************/
00547 void GEnergy::MeV(const double& eng)
00548 {
00549     // Set energy
00550     m_energy = eng;
00551     
00552     // Signals that log10 of energy is not valid
00553     m_has_log10 = false;
00554 
00555     // Return
00556     return;
00557 }
00558 
00559 
00560 /***********************************************************************//**
00561  * @brief Set energy in GeV
00562  *
00563  * @param[in] eng Energy in GeV.
00564  ***************************************************************************/
00565 void GEnergy::GeV(const double& eng)
00566 {
00567     // Set energy
00568     m_energy = eng * 1.0e+3;
00569     
00570     // Signals that log10 of energy is not valid
00571     m_has_log10 = false;
00572 
00573     // Return
00574     return;
00575 }
00576 
00577 
00578 /***********************************************************************//**
00579  * @brief Set energy in TeV
00580  *
00581  * @param[in] eng Energy in TeV.
00582  ***************************************************************************/
00583 void GEnergy::TeV(const double& eng)
00584 {
00585     // Set energy
00586     m_energy = eng * 1.0e+6;
00587     
00588     // Signals that log10 of energy is not valid
00589     m_has_log10 = false;
00590 
00591     // Return
00592     return;
00593 }
00594 
00595 
00596 /***********************************************************************//**
00597  * @brief Set energy from wavelength in Angstrom
00598  *
00599  * @param[in] wavelength Wavelength in Angstrom.
00600  *
00601  * @exception GException::invalid_argument
00602  *            Cannot set energy from zero wavelength.
00603  ***************************************************************************/
00604 void GEnergy::Angstrom(const double& wavelength)
00605 {
00606     // Throw exception if wavelength is zero
00607     if (wavelength == 0) {
00608         throw GException::invalid_argument(G_ANGSTROM_SET,
00609               "Cannot set energy from a wavelength that is zero.");
00610     }
00611 
00612     // Set energy
00613     m_energy = gammalib::MeV2Angstrom / wavelength;
00614     
00615     // Signals that log10 of energy is not valid
00616     m_has_log10 = false;
00617 
00618     // Return
00619     return;
00620 }
00621 
00622 
00623 /***********************************************************************//**
00624  * @brief Set log10 of energy in erg
00625  *
00626  * @param[in] eng log10 of energy in erg.
00627  ***************************************************************************/
00628 void GEnergy::log10erg(const double& eng)
00629 {
00630     // Set offset
00631     const double offset = std::log10(gammalib::MeV2erg);
00632 
00633     // Set energy
00634     log10MeV(eng-offset);
00635     
00636     // Return
00637     return;
00638 }
00639 
00640 
00641 /***********************************************************************//**
00642  * @brief Set log10 of energy in keV
00643  *
00644  * @param[in] eng log10 of energy in keV.
00645  ***************************************************************************/
00646 void GEnergy::log10keV(const double& eng)
00647 {
00648     // Set energy
00649     log10MeV(eng-3.0);
00650     
00651     // Return
00652     return;
00653 }
00654 
00655 
00656 /***********************************************************************//**
00657  * @brief Set log10 of energy in MeV
00658  *
00659  * @param[in] eng log10 of energy in MeV.
00660  ***************************************************************************/
00661 void GEnergy::log10MeV(const double& eng)
00662 {
00663     // Set energy
00664     m_elog10    = eng;
00665     m_energy    = std::pow(10.0, eng);
00666     m_has_log10 = true;
00667     
00668     // Return
00669     return;
00670 }
00671 
00672 
00673 /***********************************************************************//**
00674  * @brief Set log10 of energy in GeV
00675  *
00676  * @param[in] eng log10 of energy in GeV.
00677  ***************************************************************************/
00678 void GEnergy::log10GeV(const double& eng)
00679 {
00680     // Set energy
00681     log10MeV(eng+3.0);
00682     
00683     // Return
00684     return;
00685 }
00686 
00687 
00688 /***********************************************************************//**
00689  * @brief Set log10 of energy in TeV
00690  *
00691  * @param[in] eng log10 of energy in TeV.
00692  ***************************************************************************/
00693 void GEnergy::log10TeV(const double& eng)
00694 {
00695     // Set energy
00696     log10MeV(eng+6.0);
00697     
00698     // Return
00699     return;
00700 }
00701 
00702 
00703 /***********************************************************************//**
00704  * @brief Set log10 of energy with unit specification
00705  *
00706  * @param[in] eng log10 of energy.
00707  * @param[in] unit Unit of log10 of energy.
00708  *
00709  * @exception GException::invalid_argument
00710  *            Unit argument is not valid.
00711  ***************************************************************************/
00712 void GEnergy::log10(const double& eng, const std::string& unit)
00713 {
00714     // Set energy according to unit string
00715     std::string eunit = gammalib::tolower(unit);
00716     if (eunit == "erg" || eunit == "ergs") {
00717         this->log10erg(eng);
00718     }
00719     else if (eunit == "kev") {
00720         this->log10keV(eng);
00721     }
00722     else if (eunit == "mev") {
00723         this->log10MeV(eng);
00724     }
00725     else if (eunit == "gev") {
00726         this->log10GeV(eng);
00727     }
00728     else if (eunit == "tev") {
00729         this->log10TeV(eng);
00730     }
00731     else {
00732         throw GException::invalid_argument(G_LOG10_SET, unit,
00733               "Valid energy units are \"erg(s)\", \"keV\", \"MeV\","
00734               " \"GeV\", or \"TeV\" (case insensitive).");
00735     }
00736     
00737     // Return
00738     return;
00739 }
00740 
00741 
00742 /***********************************************************************//**
00743  * @brief Print energy
00744  *
00745  * @param[in] chatter Chattiness (defaults to NORMAL).
00746  * @return String containing energy information.
00747  ***************************************************************************/
00748 std::string GEnergy::print(const GChatter& chatter) const
00749 {
00750     // Initialise result string
00751     std::string result;
00752 
00753     // Continue only if chatter is not silent
00754     if (chatter != SILENT) {
00755 
00756         // Append energy
00757         if (TeV() >= 1000.0) {
00758             result.append(gammalib::str(TeV()/1000.0)+" PeV");
00759         }
00760         else if (GeV() >= 1000.0) {
00761             result.append(gammalib::str(TeV())+" TeV");
00762         }
00763         else if (MeV() >= 1000.0) {
00764             result.append(gammalib::str(GeV())+" GeV");
00765         }
00766         else if (keV() >= 1000.0) {
00767             result.append(gammalib::str(MeV())+" MeV");
00768         }
00769         else {
00770             result.append(gammalib::str(keV())+" keV");
00771         }
00772 
00773         // VERBOSE: append energy and log10 energy
00774         if (chatter == VERBOSE) {
00775             result.append(" (E="+gammalib::str(m_energy));
00776             if (m_has_log10) {
00777                 result.append(", log10(E)="+gammalib::str(m_elog10)+")");
00778             }
00779             else {
00780                 result.append(", no log10(E) value)");
00781             }
00782         }
00783 
00784     } // endif: chatter was not silent
00785 
00786     // Return
00787     return result;
00788 }
00789 
00790 
00791 /*==========================================================================
00792  =                                                                         =
00793  =                             Private methods                             =
00794  =                                                                         =
00795  ==========================================================================*/
00796 
00797 /***********************************************************************//**
00798  * @brief Initialise class members
00799  ***************************************************************************/
00800 void GEnergy::init_members(void)
00801 {
00802     // Initialise members
00803     m_energy    = 0.0;
00804     m_elog10    = DBL_MIN;
00805     m_has_log10 = false;
00806   
00807     // Return
00808     return;
00809 }
00810 
00811 
00812 /***********************************************************************//**
00813  * @brief Copy class members
00814  *
00815  * @param[in] eng Energy.
00816  ***************************************************************************/
00817 void GEnergy::copy_members(const GEnergy& eng)
00818 {
00819     // Copy time
00820     m_energy    = eng.m_energy;
00821     m_elog10    = eng.m_elog10;
00822     m_has_log10 = eng.m_has_log10;
00823     
00824     // Return
00825     return;
00826 }
00827 
00828 
00829 /***********************************************************************//**
00830  * @brief Delete class members
00831  ***************************************************************************/
00832 void GEnergy::free_members(void)
00833 {
00834     // Return
00835     return;
00836 }

Generated on Tue Jan 24 12:37:24 2017 for GammaLib by  doxygen 1.4.7