/***************************************************************************
* GEbounds.cpp - Energy boundary class *
* ----------------------------------------------------------------------- *
* copyright (C) 2009-2015 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 GEbounds.cpp
* @brief Energy boundary class implementation
* @author Juergen Knoedlseder
*/
/* __ Includes ___________________________________________________________ */
#ifdef HAVE_CONFIG_H
#include
#endif
#include
//#include
#include "GException.hpp"
#include "GTools.hpp"
#include "GEbounds.hpp"
#include "GFits.hpp"
#include "GFitsTable.hpp"
#include "GFitsBinTable.hpp"
#include "GFitsTableDoubleCol.hpp"
#include "GXmlElement.hpp"
/* __ Method name definitions ____________________________________________ */
#define G_READ_XML "GEbounds::read(GXmlElement&)"
#define G_WRITE_XML "GEbounds::write(GXmlElement&)"
#define G_REMOVE "GEbounds::remove(int&)"
#define G_EMIN "GEbounds::emin(int&)"
#define G_EMAX "GEbounds::emax(int&)"
#define G_EMEAN "GEbounds::emean(int&)"
#define G_ELOGMEAN "GEbounds::elogmean(int&)"
#define G_EWIDTH "GEbounds::ewidth(int&)"
#define G_INSERT_ENG "GEbounds::insert_eng(int&, GEnergy&, GEnergy&)"
/* __ Macros _____________________________________________________________ */
/* __ Coding definitions _________________________________________________ */
/* __ Debug definitions __________________________________________________ */
/*==========================================================================
= =
= Constructors/destructors =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Constructor
***************************************************************************/
GEbounds::GEbounds(void)
{
// Initialise class members for clean destruction
init_members();
// Return
return;
}
/***********************************************************************//**
* @brief Copy constructor
*
* @param[in] ebds Energy boundaries.
***************************************************************************/
GEbounds::GEbounds(const GEbounds& ebds)
{
// Initialise class members for clean destruction
init_members();
// Copy members
copy_members(ebds);
// Return
return;
}
/***********************************************************************//**
* @brief XML element constructor
*
* @param[in] xml XML element.
*
* Constructs energy bounds from an XML element.
***************************************************************************/
GEbounds::GEbounds(const GXmlElement& xml)
{
// Initialise members
init_members();
// Read energy boundaries from XML element
read(xml);
// Return
return;
}
/***********************************************************************//**
* @brief Single energy band constructor
*
* @param[in] emin Minimum energy of the interval.
* @param[in] emax Maximum energy of the interval.
*
* Constructs energy bounds for one (emin, emax) energy band.
***************************************************************************/
GEbounds::GEbounds(const GEnergy& emin, const GEnergy& emax)
{
// Initialise members
init_members();
// Append energies
append(emin, emax);
// Return
return;
}
/***********************************************************************//**
* @brief Interval constructor
*
* @param[in] num Number of energy intervals.
* @param[in] emin Minimum energy of first interval.
* @param[in] emax Maximum energy of last interval.
* @param[in] log Use logarithmic spacing? (defaults to true).
*
* Constructs energy boundaries by defining @p num successive energy
* intervals between @p emin and @p emax. The @p log parameter controls
* whether the energy spacing is logarihmic (default) or linear.
***************************************************************************/
GEbounds::GEbounds(const int& num, const GEnergy& emin, const GEnergy& emax,
const bool& log)
{
// Initialise members
init_members();
// Set intervals
if (log) {
this->set_log(num, emin, emax);
}
else {
this->set_lin(num, emin, emax);
}
// Return
return;
}
/***********************************************************************//**
* @brief Load constructor
*
* @param[in] filename FITS filename.
* @param[in] extname FITS extension name (defaults to "EBOUNDS").
***************************************************************************/
GEbounds::GEbounds(const std::string& filename, const std::string& extname)
{
// Initialise members
init_members();
// Load FITS file
load(filename, extname);
// Return
return;
}
/***********************************************************************//**
* @brief Destructor
***************************************************************************/
GEbounds::~GEbounds(void)
{
// Free members
free_members();
// Return
return;
}
/*==========================================================================
= =
= Operators =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Assignment operator
*
* @param[in] ebds Energy boundaries to be assigned.
* @return Energy boundaries.
***************************************************************************/
GEbounds& GEbounds::operator=(const GEbounds& ebds)
{
// Execute only if object is not identical
if (this != &ebds) {
// Free members
free_members();
// Initialise private members for clean destruction
init_members();
// Copy members
copy_members(ebds);
} // endif: object was not identical
// Return this object
return *this;
}
/*==========================================================================
= =
= Public methods =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Clear energy boundaries
***************************************************************************/
void GEbounds::clear(void)
{
// Free members
free_members();
// Initialise private members
init_members();
// Return
return;
}
/***********************************************************************//**
* @brief Clone energy boundaries
*
* @return Pointer to deep copy of energy boundaries.
***************************************************************************/
GEbounds* GEbounds::clone(void) const
{
return new GEbounds(*this);
}
/***********************************************************************//**
* @brief Append energy interval
*
* @param[in] emin Minimum energy of interval.
* @param[in] emax Maximum energy of interval.
*
* Appends an energy interval to the end of the energy boundaries
* container.
***************************************************************************/
void GEbounds::append(const GEnergy& emin, const GEnergy& emax)
{
// Append interval at the end
insert_eng(m_num, emin, emax);
// Return
return;
}
/***********************************************************************//**
* @brief Insert energy interval
*
* @param[in] emin Minimum energy of interval.
* @param[in] emax Maximum energy of interval.
*
* Inserts an energy interval into the energy boundaries after the first
* boundary that has a minimum energy smaller than @p emin. The method
* implicitely assumes that the intervals are ordered by increasing minimum
* energy.
***************************************************************************/
void GEbounds::insert(const GEnergy& emin, const GEnergy& emax)
{
// Determine index at which interval should be inserted
int inx = 0;
for (; inx < m_num; ++inx) {
if (emin < m_min[inx])
break;
}
// Insert interval
insert_eng(inx, emin, emax);
// Return
return;
}
/***********************************************************************//**
* @brief Merge all overlapping or connecting successive energy intervals
*
* Merges all overlapping or connecting successive energy intervals. The
* method implicitely assumes that the intervals are ordered by increasing
* minimum energy.
*
* Note that the method does not actually reduce the memory size but just
* updates the information on the number of elements in the array.
***************************************************************************/
void GEbounds::merge(void)
{
// Find overlaps
int i = 0;
int num = m_num;
while (i < num-1) {
// If current energy interval overlaps with successor then merge both
// intervals, move all remaining intervals one position up, and
// reduce the number of elements
if (m_min[i+1] <= m_max[i]) {
m_min[i] = (m_min[i] < m_min[i+1]) ? m_min[i] : m_min[i+1];
m_max[i] = (m_max[i] > m_max[i+1]) ? m_max[i] : m_max[i+1];
for (int k = i+2; k < num; ++k) {
m_min[k-1] = m_min[k];
m_max[k-1] = m_max[k];
}
num--;
}
// Otherwise increment interval index
else {
i++;
}
} // endwhile: there were still intervals to check
// Update number of elements in object
m_num = num;
// Return
return;
}
/***********************************************************************//**
* @brief Merge energy interval into energy boundaries
*
* @param[in] emin Minimum energy of interval.
* @param[in] emax Maximum energy of interval.
*
* Inserts an energy interval into the energy boundaries after the first
* boundary that has a minimum energy smaller than @p emin and then merges
* any overlapping or connecting energy boundaries. The method implicitely
* assumes that the intervals are ordered by increasing minimum energy.
***************************************************************************/
void GEbounds::merge(const GEnergy& emin, const GEnergy& emax)
{
// Determine index at which interval should be inserted
int inx = 0;
for (; inx < m_num; ++inx) {
if (emin < m_min[inx])
break;
}
// Insert interval
insert_eng(inx, emin, emax);
// Merge any overlapping energy intervals
merge();
// Return
return;
}
/***********************************************************************//**
* @brief Remove energy interval
*
* @param[in] index Energy interval index (0,...,size()-1).
*
* Removes energy interval at @p index from the energy boundaries container.
* All intervals after the specified @p index are moved forward by one
* position.
*
* Note that the method does not actually reduce the memory size but just
* updates the information on the number of elements in the array.
***************************************************************************/
void GEbounds::remove(const int& index)
{
#if defined(G_RANGE_CHECK)
// If index is outside boundary then throw an error
if (index < 0 || index >= m_num) {
throw GException::out_of_range(G_REMOVE, index, 0, m_num-1);
}
#endif
// Move all elements located after index forward
for (int i = index+1; i < m_num; ++i) {
m_min[i-1] = m_min[i];
m_min[i-1] = m_max[i];
}
// Reduce number of elements by one
m_num--;
// Update attributes
set_attributes();
// Return
return;
}
/***********************************************************************//**
* @brief Reserve space for energy intervals
*
* @param[in] num Number of elements.
*
* This method does nothing (it is needed to satisfy the GContainer
* interface).
***************************************************************************/
void GEbounds::reserve(const int& num)
{
// Return
return;
}
/***********************************************************************//**
* @brief Append energy boundaries
*
* @param[in] ebds Energy boundaries.
*
* Append energy boundaries to the container.
***************************************************************************/
void GEbounds::extend(const GEbounds& ebds)
{
// Do nothing if energy boundaries are empty
if (!ebds.is_empty()) {
// Allocate new intervals
int num = m_num+ebds.size();
GEnergy* min = new GEnergy[num];
GEnergy* max = new GEnergy[num];
// Initialise index
int inx = 0;
// Copy existing intervals
for (; inx < m_num; ++inx) {
min[inx] = m_min[inx];
max[inx] = m_max[inx];
}
// Append intervals
for (int i = 0; i < ebds.size(); ++i, ++inx) {
min[inx] = ebds.m_min[i];
max[inx] = ebds.m_max[i];
}
// Free memory
if (m_min != NULL) delete [] m_min;
if (m_max != NULL) delete [] m_max;
// Set new memory
m_min = min;
m_max = max;
// Set number of elements
m_num = num;
// Set attributes
set_attributes();
} // endif: energy boundaries were not empty
// Return
return;
}
/***********************************************************************//**
* @brief Set linearly spaced energy intervals
*
* @param[in] num Number of energy intervals.
* @param[in] emin Minimum energy of first interval.
* @param[in] emax Maximum energy of last interval.
*
* Creates @p num linearly spaced energy boundaries running from @p emin to
* @p emax.
***************************************************************************/
void GEbounds::set_lin(const int& num, const GEnergy& emin, const GEnergy& emax)
{
// Initialise members
clear();
// Compute bin width
GEnergy ebin = (emax - emin)/double(num);
// Append boundaries
GEnergy min = emin;
GEnergy max = emin + ebin;
for (int i = 0; i < num; ++i) {
append(min, max);
min += ebin;
max += ebin;
}
// Set attributes
set_attributes();
// Return
return;
}
/***********************************************************************//**
* @brief Set logarithmically spaced energy intervals
*
* @param[in] num Number of energy intervals.
* @param[in] emin Minimum energy of first interval.
* @param[in] emax Maximum energy of last interval.
*
* Creates @p num logarithmically spaced energy boundaries running from
* @p emin to @p emax.
***************************************************************************/
void GEbounds::set_log(const int& num, const GEnergy& emin, const GEnergy& emax)
{
// Initialise members
clear();
// Compute bin width
double elogmin = std::log10(emin.MeV());
double elogmax = std::log10(emax.MeV());
double elogbin = (elogmax - elogmin)/double(num);
// Append boundaries
GEnergy min;
GEnergy max;
for (int i = 0; i < num; ++i) {
min.MeV(std::pow(10.0, double(i)*elogbin + elogmin));
max.MeV(std::pow(10.0, double(i+1)*elogbin + elogmin));
append(min, max);
}
// Set attributes
set_attributes();
// Return
return;
}
/***********************************************************************//**
* @brief Load energy boundaries from FITS file
*
* @param[in] filename FITS filename.
* @param[in] extname FITS extension name (defaults to "EBOUNDS").
*
* Loads the energy boundaries from FITS file.
***************************************************************************/
void GEbounds::load(const std::string& filename, const std::string& extname)
{
// Allocate FITS file
GFits file;
// Open FITS file
file.open(filename);
// Get energy boundary table
const GFitsTable& table = *file.table(extname);
// Read energy boundaries from table
read(table);
// Close FITS file
file.close();
// Return
return;
}
/***********************************************************************//**
* @brief Save energy boundaries into FITS file
*
* @param[in] filename FITS filename.
* @param[in] clobber Overwrite any existing file (defaults to false)?
* @param[in] extname Energy boundary extension name (defaults to "EBOUNDS").
* @param[in] unit Energy units (defaults to "keV")
*
* Saves the energy boundaries into extension @p extname of a FITS file.
***************************************************************************/
void GEbounds::save(const std::string& filename,
const bool& clobber,
const std::string& extname,
const std::string& unit) const
{
// Allocate FITS file
GFits file;
// Write energy boundaries to FITS file
write(file, extname, unit);
// Save to file
file.saveto(filename, clobber);
// Return
return;
}
/***********************************************************************//**
* @brief Read energy boundaries from FITS table
*
* @param[in] table FITS table.
*
* Reads the energy boundaries from a FITS table. The method interprets the
* energy units provide in the FITS header. If no energy units are found it
* is assumed that the energies are stored in units of keV.
***************************************************************************/
void GEbounds::read(const GFitsTable& table)
{
// Free members
free_members();
// Initialise attributes
init_members();
// Extract energy boundary information from FITS table
m_num = table.integer("NAXIS2");
if (m_num > 0) {
// Allocate memory
m_min = new GEnergy[m_num];
m_max = new GEnergy[m_num];
// Get units
std::string emin_unit = table["E_MIN"]->unit();
std::string emax_unit = table["E_MAX"]->unit();
if (emin_unit.empty()) {
emin_unit = "keV";
}
if (emax_unit.empty()) {
emax_unit = "keV";
}
// Copy information
for (int i = 0; i < m_num; ++i) {
m_min[i](table["E_MIN"]->real(i), emin_unit);
m_max[i](table["E_MAX"]->real(i), emax_unit);
}
// Set attributes
set_attributes();
} // endif: there were channels to read
// Return
return;
}
/***********************************************************************//**
* @brief Write energy boundaries into FITS object
*
* @param[in] file FITS file.
* @param[in] extname Energy boundary extension name (defaults to "EBOUNDS")
* @param[in] unit Energy units (defaults to "keV")
*
* Writes the energy boundaries into a FITS object. The @p unit parameter
* specifies in which unit the energies are written. By default, the energy
* units are keV.
*
* @todo Write header keywords.
***************************************************************************/
void GEbounds::write(GFits& file,
const std::string& extname,
const std::string& unit) const
{
// Create energy boundary columns
GFitsTableDoubleCol cemin = GFitsTableDoubleCol("E_MIN", m_num);
GFitsTableDoubleCol cemax = GFitsTableDoubleCol("E_MAX", m_num);
// Fill energy boundary columns
for (int i = 0; i < m_num; ++i) {
cemin(i) = m_min[i](unit);
cemax(i) = m_max[i](unit);
}
// Set energy units
cemin.unit(unit);
cemax.unit(unit);
// Create binary table
GFitsBinTable* table = new GFitsBinTable(m_num);
table->append(cemin);
table->append(cemax);
table->extname(extname);
// Write to FITS file
file.append(*table);
// Free table
delete table;
// Return
return;
}
/***********************************************************************//**
* @brief Read energy boundaries from XML element
*
* @param[in] xml XML element.
*
* @exception GException::invalid_value
* Invalid XML format encountered.
*
* Read energy boundaries from an XML element. The format of the energy
* boundaries is
*
*
*
* The units of the @a emin and @a emax parameters are MeV.
***************************************************************************/
void GEbounds::read(const GXmlElement& xml)
{
// Clear energy boundaries
clear();
// Get energy boundaries parameter
const GXmlElement* par = gammalib::xml_get_par(G_READ_XML, xml,
"EnergyBoundaries");
// Extract position attributes
if (par->has_attribute("emin") && par->has_attribute("emax")) {
double emin = gammalib::todouble(par->attribute("emin"));
double emax = gammalib::todouble(par->attribute("emax"));
append(GEnergy(emin, "MeV"), GEnergy(emax, "MeV"));
}
else {
std::string msg = "Attributes \"emin\" and/or \"emax\" not found"
" in XML parameter \"EnergyBoundaries\"."
" Please verify the XML format.";
throw GException::invalid_value(G_READ_XML, msg);
}
// Set attribues
set_attributes();
// Return
return;
}
/***********************************************************************//**
* @brief Write energy boundaries into XML element
*
* @param[in] xml XML element.
*
* Writes energy boundaries into an XML element. The format of the energy
* boundaries is
*
*
*
* The units of the @a emin and @a emax parameters are MeV.
*
* This method does nothing if the energy boundaries are empty.
***************************************************************************/
void GEbounds::write(GXmlElement& xml) const
{
// Continue only if there are energy boundaries
if (!is_empty()) {
// Get parameter
GXmlElement* par = gammalib::xml_need_par(G_WRITE_XML, xml,
"EnergyBoundaries");
// Write attributes
par->attribute("emin", gammalib::str(emin().MeV()));
par->attribute("emax", gammalib::str(emax().MeV()));
} // endif: energy boundaries were not empty
// Return
return;
}
/***********************************************************************//**
* @brief Returns energy bin index for a given energy
*
* @param[in] eng Energy.
* @return Bin index.
*
* Returns the energy boundary bin index for a given energy. By convention,
* the limits for an energy bin are defined as
*
* min <= energy < max
*
* i.e. and energy equals to max falls above the largest energy.
*
* If the energy falls outside all boundaries, -1 is returned.
***************************************************************************/
int GEbounds::index(const GEnergy& eng) const
{
// Initialise index with 'not found'
int index = -1;
// Search all energy boundaries for containment
for (int i = 0; i < m_num; ++i) {
if (eng >= m_min[i] && eng < m_max[i]) {
index = i;
break;
}
}
// Return index
return index;
}
/***********************************************************************//**
* @brief Returns minimum energy for a given energy interval
*
* @param[in] index Energy interval index (0,...,size()-1).
* @return Minimum energy of interval.
*
* @exception GException::out_of_range
* Specified index is out of range.
***************************************************************************/
GEnergy GEbounds::emin(const int& index) const
{
#if defined(G_RANGE_CHECK)
// If index is outside boundary then throw an error
if (index < 0 || index >= m_num) {
throw GException::out_of_range(G_EMIN, index, 0, m_num-1);
}
#endif
// Return
return (m_min[index]);
}
/***********************************************************************//**
* @brief Returns maximum energy for a given energy interval
*
* @param[in] index Energy interval index (0,...,size()-1).
* @return Maximum energy of interval.
*
* @exception GException::out_of_range
* Specified index is out of range.
***************************************************************************/
GEnergy GEbounds::emax(const int& index) const
{
#if defined(G_RANGE_CHECK)
// If index is outside boundary then throw an error
if (index < 0 || index >= m_num) {
throw GException::out_of_range(G_EMAX, index, 0, m_num-1);
}
#endif
// Return
return (m_max[index]);
}
/***********************************************************************//**
* @brief Returns mean energy for a given energy interval
*
* @param[in] index Energy interval index (0,...,size()-1).
* @return Mean energy of interval.
*
* @exception GException::out_of_range
* Specified index is out of range.
*
* Computes the mean energy
* \f$0.5 * (E_{\rm min} + E_{\rm max})\f$
* for the energy interval @p index.
***************************************************************************/
GEnergy GEbounds::emean(const int& index) const
{
#if defined(G_RANGE_CHECK)
// If index is outside boundary then throw an error
if (index < 0 || index >= m_num) {
throw GException::out_of_range(G_EMEAN, index, 0, m_num-1);
}
#endif
// Compute mean energy
GEnergy emean = 0.5 * (m_min[index] + m_max[index]);
// Return
return emean;
}
/***********************************************************************//**
* @brief Returns logarithmic mean energy for a given energy interval
*
* @param[in] index Energy interval index (0,...,size()-1).
* @return Logarithmic mean energy of interval.
*
* @exception GException::out_of_range
* Specified index is out of range.
*
* Computes the logarithmic mean energy
* \f$10^{0.5 * (\log E_{\rm min} + \log E_{\rm max})}\f$
* for the energy interval @p index.
***************************************************************************/
GEnergy GEbounds::elogmean(const int& index) const
{
#if defined(G_RANGE_CHECK)
// If index is outside boundary then throw an error
if (index < 0 || index >= m_num) {
throw GException::out_of_range(G_ELOGMEAN, index, 0, m_num-1);
}
#endif
// Compute logarithmic mean energy
GEnergy elogmean;
elogmean.MeV(std::sqrt(m_min[index].MeV() * m_max[index].MeV()));
// Return
return elogmean;
}
/***********************************************************************//**
* @brief Returns energy interval width
*
* @param[in] index Energy interval index (0,...,size()-1).
* @return Energy interval width.
*
* @exception GException::out_of_range
* Specified index is out of range.
***************************************************************************/
GEnergy GEbounds::ewidth(const int& index) const
{
#if defined(G_RANGE_CHECK)
// If index is outside boundary then throw an error
if (index < 0 || index >= m_num) {
throw GException::out_of_range(G_EWIDTH, index, 0, m_num-1);
}
#endif
// Return
return (m_max[index]-m_min[index]);
}
/***********************************************************************//**
* @brief Checks whether energy boundaries contain energy
*
* @param[in] eng Energy to be checked.
* @return True if energy falls in at least one interval, false otherwise.
*
* Checks if the energy @p eng falls in at least one of the energy intervals.
* The method exits when the first matching interval has been found.
***************************************************************************/
bool GEbounds::contains(const GEnergy& eng) const
{
// Initialise test
bool found = false;
// Test all energy boundaries
for (int i = 0; i < m_num; ++i) {
if (eng >= m_min[i] && eng <= m_max[i]) {
found = true;
break;
}
}
// Return result
return found;
}
/***********************************************************************//**
* @brief Print energy boundaries
*
* @param[in] chatter Chattiness (defaults to NORMAL).
* @return String containing energy boundary information.
***************************************************************************/
std::string GEbounds::print(const GChatter& chatter) const
{
// Initialise result string
std::string result;
// Continue only if chatter is not silent
if (chatter != SILENT) {
// Append Header
result.append("=== GEbounds ===");
// Append information
result.append("\n"+gammalib::parformat("Number of intervals"));
result.append(gammalib::str(size()));
result.append("\n"+gammalib::parformat("Energy range"));
result.append(emin().print());
result.append(" - ");
result.append(emax().print());
// If there are multiple energy bins then append them
if (chatter >= EXPLICIT) {
if (size() > 1) {
for (int i = 0; i < size(); ++i) {
result.append("\n");
result.append(gammalib::parformat("Energy interval "));
result.append(gammalib::str(i));
result.append(emin(i).print());
result.append(" - ");
result.append(emax(i).print());
}
}
} // endif: chatter was less than explicit
} // endif: chatter was not silent
// Return
return result;
}
/*==========================================================================
= =
= Private methods =
= =
==========================================================================*/
/***********************************************************************//**
* @brief Initialise class members
***************************************************************************/
void GEbounds::init_members(void)
{
// Initialise members
m_num = 0;
m_emin.clear();
m_emax.clear();
m_min = NULL;
m_max = NULL;
// Return
return;
}
/***********************************************************************//**
* @brief Copy class members
*
* @param[in] ebds Energy boundaries.
***************************************************************************/
void GEbounds::copy_members(const GEbounds& ebds)
{
// Copy attributes
m_num = ebds.m_num;
m_emin = ebds.m_emin;
m_emax = ebds.m_emax;
// Copy arrays
if (m_num > 0) {
m_min = new GEnergy[m_num];
m_max = new GEnergy[m_num];
for (int i = 0; i < m_num; ++i) {
m_min[i] = ebds.m_min[i];
m_max[i] = ebds.m_max[i];
}
}
// Return
return;
}
/***********************************************************************//**
* @brief Delete class members
***************************************************************************/
void GEbounds::free_members(void)
{
// Free memory
if (m_min != NULL) delete [] m_min;
if (m_max != NULL) delete [] m_max;
// Signal free pointers
m_min = NULL;
m_max = NULL;
// Return
return;
}
/***********************************************************************//**
* @brief Set class attributes
*
* Determines the minimum and maximum energy from all intervals. If no
* interval is present the minimum and maximum energies are cleared.
***************************************************************************/
void GEbounds::set_attributes(void)
{
// If there are intervals then determine the minimum and maximum
// energy from these intervals ...
if (m_num > 0) {
m_emin = m_min[0];
m_emax = m_max[0];
for (int i = 1; i < m_num; ++i) {
if (m_min[i] < m_emin) m_emin = m_min[i];
if (m_max[i] > m_emax) m_emax = m_max[i];
}
}
// ... otherwise clear the minimum and maximum energy
else {
m_emin.clear();
m_emax.clear();
}
// Return
return;
}
/***********************************************************************//**
* @brief Insert energy interval
*
* @param[in] index Index after with interval is inserted.
* @param[in] emin Minimum energy of interval.
* @param[in] emax Maximum energy of interval.
*
* @exception GException::invalid_argument
* Minimum energy larger than maximum energy
*
* Inserts an energy interval after the specified @p index in the energy
* boundaries. The method does not reorder the intervals by energy, instead
* the client needs to determine the approriate @p index.
*
* Invalid parameters do not produce any exception, but are handled
* transparently. If the interval is invalid (i.e. @p emin > @p emax) an
* exception is thrown. If the @p index is out of the valid range, the
* index will be adjusted to either the first or the last element.
***************************************************************************/
void GEbounds::insert_eng(const int& index,
const GEnergy& emin,
const GEnergy& emax)
{
// Throw an exception if energy interval is invalid
if (emin > emax) {
std::string msg = "Invalid energy interval specified. Minimum"
" energy "+emin.print(NORMAL)+" can not be"
" larger than maximum energy "+
emax.print(NORMAL)+".";
throw GException::invalid_argument(G_INSERT_ENG, msg);
}
// Set index
int inx = index;
// If inx is out of range then adjust it
if (inx < 0) inx = 0;
if (inx > m_num) inx = m_num;
// Allocate new intervals
int num = m_num+1;
GEnergy* min = new GEnergy[num];
GEnergy* max = new GEnergy[num];
// Copy intervals before index to be inserted
for (int i = 0; i < inx; ++i) {
min[i] = m_min[i];
max[i] = m_max[i];
}
// Insert interval
min[inx] = emin;
max[inx] = emax;
// Copy intervals after index to be inserted
for (int i = inx+1; i < num; ++i) {
min[i] = m_min[i-1];
max[i] = m_max[i-1];
}
// Free memory
if (m_min != NULL) delete [] m_min;
if (m_max != NULL) delete [] m_max;
// Set new memory
m_min = min;
m_max = max;
// Set number of elements
m_num = num;
// Set attributes
set_attributes();
// Return
return;
}