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 }