From b59f1ce11d099ad1d5ebf6d505dd0e5ce9e96284 Mon Sep 17 00:00:00 2001 From: Jürgen Knödlseder Date: Wed, 18 Nov 2020 08:56:42 +0100 Subject: [PATCH] Add GSkyDirs container class (#3324) --- ChangeLog | 3 ++- NEWS | 6 ++++-- README.md | 2 +- doc/source/admin/release_history/2.0.rst | 2 ++ include/GHealpix.hpp | 17 ++++++++++------- include/GSkyDirs.hpp | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/GammaLib.hpp | 3 ++- include/Makefile.am | 1 + pyext/GHealpix.i | 16 ++++++++-------- pyext/GSkyDirs.i | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pyext/gammalib/sky.i | 6 +++--- src/obs/GEnergies.cpp | 2 +- src/sky/GHealpix.cpp | 16 ++++++++-------- src/sky/GSkyDirs.cpp | 417 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/sky/GSkyMap.cpp | 3 ++- src/sky/Makefile.am | 3 ++- test/test_GSky.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/test_GSky.hpp | 1 + test/test_GSky.py | 2 ++ 19 files changed, 855 insertions(+), 34 deletions(-) create mode 100644 include/GSkyDirs.hpp create mode 100644 pyext/GSkyDirs.i create mode 100644 src/sky/GSkyDirs.cpp diff --git a/ChangeLog b/ChangeLog index 575377f..0a17940 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -2020-11-17 +2020-11-18 * Version 2.0.0 released ======================== @@ -14,6 +14,7 @@ Add GIntegrals class (#3328) Remove implicit conversion warnings (#3324) Add gammalib::tmpnam() function (#3324) + Add GSkyDirs container class (#3324) Implement vectorised response computation (#3203) Implement analytical gradients for the radial Gaussian model in a stacked analysis (#3203) diff --git a/NEWS b/NEWS index d0410b0..09ae5fa 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ New Features and Important Changes in GammaLib 2.0.0 -17 November 2020 +18 November 2020 1. Introduction @@ -15,6 +15,7 @@ The following classes have been added: - GFunctions - GIntegrals - GResponseVectorCache +- GSkyDirs - GCTAModelSkyCube The following classes have been removed: @@ -141,7 +142,8 @@ Added GOptimizerLM::npars() and GOptimizerLM::nfree() methods. 12. Sky module -------------- -None +Added GSkyDirs container class to hold sky directions. The GHealpix::boundaries() +method now returns an instance of GSkyDirs (#3324). 13. Support module diff --git a/README.md b/README.md index 10d5472..d210a51 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ GammaLib information ==================== -* Version: 2.0.0.dev (17 November 2020) +* Version: 2.0.0.dev (18 November 2020) [![Build Status](https://cta-jenkins.irap.omp.eu/buildStatus/icon?job=gammalib-integrate-os)](https://cta-jenkins.irap.omp.eu/job/gammalib-integrate-os/) diff --git a/doc/source/admin/release_history/2.0.rst b/doc/source/admin/release_history/2.0.rst index 760ccb3..34b3e60 100644 --- a/doc/source/admin/release_history/2.0.rst +++ b/doc/source/admin/release_history/2.0.rst @@ -51,6 +51,8 @@ New features Add ``GFunctions`` abstract base class and ``GIntegrals`` class * [`3324 `_] - Add ``gammalib::tmpnam()`` function +* [`3324 `_] - + Add ``GSkyDirs`` container class * [`3074 `_] - Add ``GSkyModel`` ``flux_error()`` and ``eflux_error()`` methods diff --git a/include/GHealpix.hpp b/include/GHealpix.hpp index 92b30eb..41ca949 100644 --- a/include/GHealpix.hpp +++ b/include/GHealpix.hpp @@ -34,6 +34,9 @@ #include "GSkyPixel.hpp" #include "GBilinear.hpp" +/* __ Forward declarations _______________________________________________ */ +class GSkyDirs; + /***********************************************************************//** * @class GHealpix @@ -75,13 +78,13 @@ public: virtual std::string print(const GChatter& chatter = NORMAL) const; // Other methods - const int& npix(void) const; - const int& nside(void) const; - std::string ordering(void) const; - void ordering(const std::string& ordering); - std::vector neighbours(const GSkyPixel& pixel) const; - std::vector boundaries(const GSkyPixel& pixel, const int& step = 1) const; - double max_pixrad(void) const; + const int& npix(void) const; + const int& nside(void) const; + std::string ordering(void) const; + void ordering(const std::string& ordering); + std::vector neighbours(const GSkyPixel& pixel) const; + GSkyDirs boundaries(const GSkyPixel& pixel, const int& step = 1) const; + double max_pixrad(void) const; private: // Private methods diff --git a/include/GSkyDirs.hpp b/include/GSkyDirs.hpp new file mode 100644 index 0000000..8b55139 --- /dev/null +++ b/include/GSkyDirs.hpp @@ -0,0 +1,191 @@ +/*************************************************************************** + * GSkyDirs.hpp - Sky directions container class * + * ----------------------------------------------------------------------- * + * copyright (C) 2020 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 GSkyDirs.hpp + * @brief Sky directions container class definition + * @author Juergen Knoedlseder + */ + +#ifndef GSKYDIRS_HPP +#define GSKYDIRS_HPP + +/* __ Includes ___________________________________________________________ */ +#include +#include +#include "GContainer.hpp" +#include "GSkyDir.hpp" + +/* __ Forward declarations _______________________________________________ */ + +/* __ Constants __________________________________________________________ */ + + +/***********************************************************************//** + * @class GSkyDirs + * + * @brief Sky directions container class + * + * This class is a container for sky directions. Sky directions are + * implemented by the GSkyDir class. + ***************************************************************************/ +class GSkyDirs : public GContainer { + +public: + // Constructors and destructors + GSkyDirs(void); + explicit GSkyDirs(const GSkyDir& dir); + GSkyDirs(const GSkyDirs& dirs); + virtual ~GSkyDirs(void); + + // Operators + GSkyDirs& operator=(const GSkyDirs& dirs); + GSkyDir& operator[](const int& index); + const GSkyDir& operator[](const int& index) const; + + // Methods + void clear(void); + GSkyDirs* clone(void) const; + std::string classname(void) const; + GSkyDir& at(const int& index); + const GSkyDir& at(const int& index) const; + int size(void) const; + bool is_empty(void) const; + GSkyDir& append(const GSkyDir& dir); + GSkyDir& insert(const int& index, const GSkyDir& dir); + void remove(const int& index); + void reserve(const int& num); + void extend(const GSkyDirs& dirs); + std::string print(const GChatter& chatter = NORMAL) const; + +protected: + // Protected methods + void init_members(void); + void copy_members(const GSkyDirs& dirs); + void free_members(void); + + // Protected data members + std::vector m_dirs; //!< List of sky directions +}; + + +/***********************************************************************//** + * @brief Return class name + * + * @return String containing the class name ("GSkyDirs"). + ***************************************************************************/ +inline +std::string GSkyDirs::classname(void) const +{ + return ("GSkyDirs"); +} + + +/***********************************************************************//** + * @brief Return reference to sky direction + * + * @param[in] index Sky direction index [0,...,size()-1]. + * + * Returns a reference to the sky direction with the specified @p index. + ***************************************************************************/ +inline +GSkyDir& GSkyDirs::operator[](const int& index) +{ + return (m_dirs[index]); +} + + +/***********************************************************************//** + * @brief Return reference to sky direction (const version) + * + * @param[in] index Sky direction index [0,...,size()-1]. + * + * Returns a const reference to the sky direction with the specified + * @p index. + ***************************************************************************/ +inline +const GSkyDir& GSkyDirs::operator[](const int& index) const +{ + return (m_dirs[index]); +} + + +/***********************************************************************//** + * @brief Return reference to sky direction + * + * @param[in] index Sky directions index [0,...,size()-1]. + * + * @exception GException::out_of_range + * Sky directions index is out of range. + * + * Returns a reference to the sky directions with the specified @p index. + ***************************************************************************/ +inline +GSkyDir& GSkyDirs::at(const int& index) +{ + // Return child element using const method + return const_cast((this)->at(index)); +} + + +/***********************************************************************//** + * @brief Return number of sky directions in container + * + * @return Number of sky directions in container. + * + * Returns the number of sky directions in the sky directions container. + ***************************************************************************/ +inline +int GSkyDirs::size(void) const +{ + return ((int)m_dirs.size()); +} + + +/***********************************************************************//** + * @brief Signals if there are no sky directions in container + * + * @return True if container is empty, false otherwise. + * + * Signals if the sky directions container does not contain any sky + * direction. + ***************************************************************************/ +inline +bool GSkyDirs::is_empty(void) const +{ + return (m_dirs.empty()); +} + + +/***********************************************************************//** + * @brief Reserves space for sky directions in container + * + * @param[in] num Number of sky directions. + * + * Reserves space for @p num sky directions in the container. + ***************************************************************************/ +inline +void GSkyDirs::reserve(const int& num) +{ + m_dirs.reserve(num); + return; +} + +#endif /* GSKYDIRS_HPP */ diff --git a/include/GammaLib.hpp b/include/GammaLib.hpp index e5f7a41..e84743f 100644 --- a/include/GammaLib.hpp +++ b/include/GammaLib.hpp @@ -143,8 +143,9 @@ * Analysis support services * ***************************************************************************/ -/* __ Skymap handling ____________________________________________________ */ +/* __ Sky handling _______________________________________________________ */ #include "GSkyDir.hpp" +#include "GSkyDirs.hpp" #include "GHorizDir.hpp" #include "GSkyPixel.hpp" #include "GSkyMap.hpp" diff --git a/include/Makefile.am b/include/Makefile.am index 2a8ec44..d752580 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -107,6 +107,7 @@ pkginclude_HEADERS = GammaLib.hpp \ GTestSuites.hpp \ GTestCase.hpp \ GSkyDir.hpp \ + GSkyDirs.hpp \ GHorizDir.hpp \ GSkyPixel.hpp \ GSkyMap.hpp \ diff --git a/pyext/GHealpix.i b/pyext/GHealpix.i index b020035..b681706 100644 --- a/pyext/GHealpix.i +++ b/pyext/GHealpix.i @@ -1,7 +1,7 @@ /*************************************************************************** * GHealpix.i - Healpix projection class * * ----------------------------------------------------------------------- * - * copyright (C) 2010-2018 by Jurgen Knodlseder * + * copyright (C) 2010-2020 by Jurgen Knodlseder * * ----------------------------------------------------------------------- * * * * This program is free software: you can redistribute it and/or modify * @@ -60,13 +60,13 @@ public: virtual GBilinear interpolator(const GSkyDir& dir) const; // Other methods - const int& npix(void) const; - const int& nside(void) const; - std::string ordering(void) const; - void ordering(const std::string& ordering); - std::vector neighbours(const GSkyPixel& pixel) const; - std::vector boundaries(const GSkyPixel& pixel, const int& step = 1) const; - double max_pixrad(void) const; + const int& npix(void) const; + const int& nside(void) const; + std::string ordering(void) const; + void ordering(const std::string& ordering); + std::vector neighbours(const GSkyPixel& pixel) const; + GSkyDirs boundaries(const GSkyPixel& pixel, const int& step = 1) const; + double max_pixrad(void) const; }; diff --git a/pyext/GSkyDirs.i b/pyext/GSkyDirs.i new file mode 100644 index 0000000..f6ea5d8 --- /dev/null +++ b/pyext/GSkyDirs.i @@ -0,0 +1,137 @@ +/*************************************************************************** + * GSkyDirs.i - Sky directions container class * + * ----------------------------------------------------------------------- * + * copyright (C) 2020 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 GSkyDirs.i + * @brief Sky directions container class definition + * @author Juergen Knoedlseder + */ +%{ +/* Put headers and other declarations here that are needed for compilation */ +#include "GSkyDirs.hpp" +#include "GException.hpp" +#include "GTools.hpp" +%} + + +/***********************************************************************//** + * @class GSkyDirs + * + * @brief Sky directions container class + ***************************************************************************/ +class GSkyDirs : public GContainer { + +public: + // Constructors and destructors + GSkyDirs(void); + explicit GSkyDirs(const GSkyDir& dir); + GSkyDirs(const GSkyDirs& dirs); + virtual ~GSkyDirs(void); + + // Methods + void clear(void); + GSkyDirs* clone(void) const; + std::string classname(void) const; + GSkyDir& at(const int& index); + const GSkyDir& at(const int& index) const; + int size(void) const; + bool is_empty(void) const; + GSkyDir& append(const GSkyDir& dir); + GSkyDir& insert(const int& index, const GSkyDir& dir); + void remove(const int& index); + void reserve(const int& num); + void extend(const GSkyDirs& dirs); +}; + + +/***********************************************************************//** + * @brief GSkyDirs class extension + ***************************************************************************/ +%extend GSkyDirs { + GSkyDir& __getitem__(const int& index) { + // Counting from start, e.g. [2] + if (index >= 0 && index < self->size()) { + return (*self)[index]; + } + // Counting from end, e.g. [-1] + else if (index < 0 && self->size()+index >= 0) { + return (*self)[self->size()+index]; + } + else { + throw GException::out_of_range("__getitem__(int)", index, self->size()); + } + } + GSkyDirs* __getitem__(PyObject *param) { + if (PySlice_Check(param)) { + Py_ssize_t start = 0; + Py_ssize_t stop = 0; + Py_ssize_t step = 0; + Py_ssize_t len = self->size(); + if (PythonSlice_GetIndices(param, len, &start, &stop, &step) == 0) { + GSkyDirs* dirs = new GSkyDirs; + if (step > 0) { + for (int i = (int)start; i < (int)stop; i += (int)step) { + dirs->append((*self)[i]); + } + } + else { + for (int i = (int)start; i > (int)stop; i += (int)step) { + dirs->append((*self)[i]); + } + } + return dirs; + } + else { + throw GException::invalid_argument("__getitem__(PyObject)", + "Invalid slice indices"); + } + } + else { + throw GException::invalid_argument("__getitem__(PyObject)",""); + } + } + void __setitem__(const int& index, const GSkyDir& val) { + // Counting from start, e.g. [2] + if (index >= 0 && index < self->size()) { + (*self)[index] = val; + } + // Counting from end, e.g. [-1] + else if (index < 0 && self->size()+index >= 0) { + (*self)[self->size()+index] = val; + } + else { + throw GException::out_of_range("__setitem__(int)", index, self->size()); + } + } + GSkyDirs copy() { + return (*self); + } +%pythoncode { + def __getstate__(self): + state = tuple([x for x in self]), + return state + def __setstate__(self, state): + self.__init__() + size = len(state[0]) + self.reserve(size) + for x in state[0]: + self.append(x) +} +}; diff --git a/pyext/gammalib/sky.i b/pyext/gammalib/sky.i index 1bcc34e..3a1aa0e 100644 --- a/pyext/gammalib/sky.i +++ b/pyext/gammalib/sky.i @@ -41,9 +41,8 @@ %include stl.i %include "std_vector.i" namespace std { - %template(vectori) vector; - %template(vectord) vector; - %template(vectorskydir) vector; + %template(vectori) vector; + %template(vectord) vector; }; /* __ Include GammaLib typemaps __________________________________________ */ @@ -112,6 +111,7 @@ namespace std { /* __ Skymap handling ____________________________________________________ */ %include "GSkyDir.i" +%include "GSkyDirs.i" %include "GHorizDir.i" %include "GSkyPixel.i" %include "GSkyMap.i" diff --git a/src/obs/GEnergies.cpp b/src/obs/GEnergies.cpp index fd7eb3f..dd97939 100644 --- a/src/obs/GEnergies.cpp +++ b/src/obs/GEnergies.cpp @@ -120,7 +120,7 @@ GEnergies::GEnergies(const GEbounds& ebounds) /***********************************************************************//** * @brief Copy constructor * - * @param energies Energy container. + * @param energies[in] Energy container. * * Construct energy container by copying from another energy container. ***************************************************************************/ diff --git a/src/sky/GHealpix.cpp b/src/sky/GHealpix.cpp index 1c74760..0514e30 100644 --- a/src/sky/GHealpix.cpp +++ b/src/sky/GHealpix.cpp @@ -33,6 +33,7 @@ #include "GTools.hpp" #include "GMath.hpp" #include "GVector.hpp" +#include "GSkyDirs.hpp" #include "GHealpix.hpp" /* __ Method name definitions ____________________________________________ */ @@ -696,7 +697,7 @@ std::vector GHealpix::neighbours(const GSkyPixel& pixel) const * @param[in] step Number of returned points (4*step, defaults to 4). * @return Array of pixel boundaries. * - * The method returns a vector with sky directions along the boundary of a + * The method returns a container of sky directions along the boundary of a * HealPix pixel. By default, the 4 corners of HealPix pixel will be * returned. The first point corresponds to the northernmost corner, the * subsequent points follow the pixel boundary through west, south and east @@ -706,8 +707,7 @@ std::vector GHealpix::neighbours(const GSkyPixel& pixel) const * This method has been adapted from the boundaries() function located in the * file healpix_base.cc in Healpix version 3.20. ***************************************************************************/ -std::vector GHealpix::boundaries(const GSkyPixel& pixel, - const int& step) const +GSkyDirs GHealpix::boundaries(const GSkyPixel& pixel, const int& step) const { // Throw an exception if sky map pixel is not 1D if (!pixel.is_1D()) { @@ -719,7 +719,7 @@ std::vector GHealpix::boundaries(const GSkyPixel& pixel, } // Allocate boundaries - std::vector boundaries; + GSkyDirs boundaries; // Determine pixel index and face number int ix; @@ -742,19 +742,19 @@ std::vector GHealpix::boundaries(const GSkyPixel& pixel, // First coordinate xyf2loc(xc+dc-i*d, yc+dc, face, &z, &phi); - boundaries.push_back(loc2dir(z, phi)); + boundaries.append(loc2dir(z, phi)); // Second coordinate xyf2loc(xc-dc, yc+dc-i*d, face, &z, &phi); - boundaries.push_back(loc2dir(z, phi)); + boundaries.append(loc2dir(z, phi)); // Third coordinate xyf2loc(xc-dc+i*d, yc-dc, face, &z, &phi); - boundaries.push_back(loc2dir(z, phi)); + boundaries.append(loc2dir(z, phi)); // Forth coordinate xyf2loc(xc+dc, yc-dc+i*d, face, &z, &phi); - boundaries.push_back(loc2dir(z, phi)); + boundaries.append(loc2dir(z, phi)); } // endfor: looped over step size diff --git a/src/sky/GSkyDirs.cpp b/src/sky/GSkyDirs.cpp new file mode 100644 index 0000000..7db5b9e --- /dev/null +++ b/src/sky/GSkyDirs.cpp @@ -0,0 +1,417 @@ +/*************************************************************************** + * GSkyDirs.cpp - Sky directions container class * + * ----------------------------------------------------------------------- * + * copyright (C) 2020 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 GSkyDirs.cpp + * @brief Sky directions container class implementation + * @author Juergen Knoedlseder + */ + +/* __ Includes ___________________________________________________________ */ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "GTools.hpp" +#include "GException.hpp" +#include "GFilename.hpp" +#include "GSkyDirs.hpp" +/* +#include "GEbounds.hpp" +#include "GFits.hpp" +#include "GFitsTable.hpp" +#include "GFitsBinTable.hpp" +#include "GFitsTableCol.hpp" +#include "GFitsTableDoubleCol.hpp" +*/ + +/* __ Method name definitions ____________________________________________ */ +#define G_AT "GSkyDirs::at(int&)" +#define G_INSERT "GSkyDirs::insert(int&, GSkyDir&)" +#define G_REMOVE "GSkyDirs::remove(int&)" + +/* __ Macros _____________________________________________________________ */ + +/* __ Coding definitions _________________________________________________ */ + +/* __ Debug definitions __________________________________________________ */ + + +/*========================================================================== + = = + = Constructors/destructors = + = = + ==========================================================================*/ + +/***********************************************************************//** + * @brief Void constructor + * + * Constructs empty sky directions container. + ***************************************************************************/ +GSkyDirs::GSkyDirs(void) +{ + // Initialise members + init_members(); + + // Return + return; +} + + +/***********************************************************************//** + * @brief Single sky direction constructor + * + * @param[in] dir Sky directions. + * + * Constructs sky directions container from a single sky direction. + ***************************************************************************/ +GSkyDirs::GSkyDirs(const GSkyDir& dir) +{ + // Initialise members + init_members(); + + // Append sky direction + append(dir); + + // Return + return; +} + + +/***********************************************************************//** + * @brief Copy constructor + * + * @param[in] dir Sky directions. + * + * Construct sky directions container by copying from another sky directions + * container. + ***************************************************************************/ +GSkyDirs::GSkyDirs(const GSkyDirs& dirs) +{ + // Initialise members + init_members(); + + // Copy members + copy_members(dirs); + + // Return + return; +} + + +/***********************************************************************//** + * @brief Destructor + ***************************************************************************/ +GSkyDirs::~GSkyDirs(void) +{ + // Free members + free_members(); + + // Return + return; +} + + +/*========================================================================== + = = + = Operators = + = = + ==========================================================================*/ + +/***********************************************************************//** + * @brief Assignment operator + * + * @param[in] dirs Sky direction container. + * @return Sky direction container. + ***************************************************************************/ +GSkyDirs& GSkyDirs::operator=(const GSkyDirs& dirs) +{ + // Execute only if object is not identical + if (this != &dirs) { + + // Free members + free_members(); + + // Initialise members + init_members(); + + // Copy members + copy_members(dirs); + + } // endif: object was not identical + + // Return this object + return *this; +} + + +/*========================================================================== + = = + = Public methods = + = = + ==========================================================================*/ + +/***********************************************************************//** + * @brief Clear sky directions container + * + * Removes all sky directions from the container. + ***************************************************************************/ +void GSkyDirs::clear(void) +{ + // Free members + free_members(); + + // Initialise members + init_members(); + + // Return + return; +} + + +/***********************************************************************//** + * @brief Clone sky directions container + * + * @return Pointer to deep copy of sky directions container + * + * Makes a deep copy of the sky directions container instance. + ***************************************************************************/ +GSkyDirs* GSkyDirs::clone(void) const +{ + return new GSkyDirs(*this); +} + + +/***********************************************************************//** + * @brief Return reference to sky direction (const version) + * + * @param[in] index Sky directions index [0,...,size()-1]. + * + * @exception GException::out_of_range + * Sky directions index is out of range. + * + * Returns a reference to the sky directions with the specified @p index. + ***************************************************************************/ +const GSkyDir& GSkyDirs::at(const int& index) const +{ + // Raise exception if index is out of range + if (index < 0 || index >= size()) { + throw GException::out_of_range(G_AT, "Sky direction", index, size()); + } + + // Return reference + return m_dirs[index]; +} + + +/***********************************************************************//** + * @brief Append sky direction to container + * + * @param[in] dir Sky direction. + * @return Reference to appended sky direction. + * + * Appends sky direction to the container by making a deep copy of the sky + * direction. + ***************************************************************************/ +GSkyDir& GSkyDirs::append(const GSkyDir& dir) +{ + // Append sky direction to list + m_dirs.push_back(dir); + + // Return reference + return m_dirs[size()-1]; +} + + +/***********************************************************************//** + * @brief Insert sky direction into container + * + * @param[in] index Sky direction index (0,...,size()-1). + * @param[in] dir Sky direction. + * + * @exception GException::out_of_range + * Sky direction index is out of range. + * + * Inserts a sky direction @p dir into the container before the sky + * direction with the specified @p index. + ***************************************************************************/ +GSkyDir& GSkyDirs::insert(const int& index, const GSkyDir& dir) +{ + // Compile option: raise exception if index is out of range + #if defined(G_RANGE_CHECK) + if (is_empty()) { + if (index > 0) { + throw GException::out_of_range(G_INSERT, "Sky direction", index, + size()); + } + } + else { + if (index < 0 || index >= size()) { + throw GException::out_of_range(G_INSERT, "Sky direction", index, + size()); + } + } + #endif + + // Inserts sky direction + m_dirs.insert(m_dirs.begin()+index, dir); + + // Return reference + return m_dirs[index]; +} + + +/***********************************************************************//** + * @brief Remove sky direction from container + * + * @param[in] index Sky direction index (0,...,size()-1). + * + * @exception GException::out_of_range + * Sky direction index is out of range. + * + * Remove sky direction of specified @p index from container. + ***************************************************************************/ +void GSkyDirs::remove(const int& index) +{ + // Compile option: raise exception if index is out of range + #if defined(G_RANGE_CHECK) + if (index < 0 || index >= size()) { + throw GException::out_of_range(G_REMOVE, "Sky direction", index, size()); + } + #endif + + // Erase sky direction from container + m_dirs.erase(m_dirs.begin() + index); + + // Return + return; +} + + +/***********************************************************************//** + * @brief Append sky directions container + * + * @param[in] dirs Sky directions container. + * + * Append sky directions container to the container. + ***************************************************************************/ +void GSkyDirs::extend(const GSkyDirs& dirs) +{ + // Do nothing if sky directions container is empty + if (!dirs.is_empty()) { + + // Get size. Note that we extract the size first to avoid an + // endless loop that arises when a container is appended to + // itself. + int num = dirs.size(); + + // Reserve enough space + reserve(size() + num); + + // Loop over all elements and append them to container + for (int i = 0; i < num; ++i) { + m_dirs.push_back(dirs[i]); + } + + } // endif: sky directions container was not empty + + // Return + return; +} + + +/***********************************************************************//** + * @brief Print sky directions container information + * + * @param[in] chatter Chattiness. + * @return String containing sky directions container information. + ***************************************************************************/ +std::string GSkyDirs::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("=== GSkyDirs ==="); + + // Append sky direction container information + result.append("\n"+gammalib::parformat("Number of directions")); + result.append(gammalib::str(size())); + + // EXPLICIT: Append sky directions + if (chatter >= EXPLICIT) { + for (int i = 0; i < size(); ++i) { + result.append("\n"); + result.append(gammalib::parformat("Direction "+gammalib::str(i))); + result.append(m_dirs[i].print(chatter)); + } + } + + } // endif: chatter was not silent + + // Return result + return result; +} + + +/*========================================================================== + = = + = Private methods = + = = + ==========================================================================*/ + +/***********************************************************************//** + * @brief Initialise class members + ***************************************************************************/ +void GSkyDirs::init_members(void) +{ + // Initialise members + m_dirs.clear(); + + // Return + return; +} + + +/***********************************************************************//** + * @brief Copy class members + * + * @param[in] dirs Sky directions container. + ***************************************************************************/ +void GSkyDirs::copy_members(const GSkyDirs& dirs) +{ + // Copy attributes + m_dirs = dirs.m_dirs; + + // Return + return; +} + + +/***********************************************************************//** + * @brief Delete class members + ***************************************************************************/ +void GSkyDirs::free_members(void) +{ + // Return + return; +} diff --git a/src/sky/GSkyMap.cpp b/src/sky/GSkyMap.cpp index 205998e..03878cb 100644 --- a/src/sky/GSkyMap.cpp +++ b/src/sky/GSkyMap.cpp @@ -38,6 +38,7 @@ #include "GFitsImage.hpp" #include "GFitsImageDouble.hpp" #include "GFitsTableDoubleCol.hpp" +#include "GSkyDirs.hpp" #include "GSkyMap.hpp" #include "GHealpix.hpp" #include "GWcsRegistry.hpp" @@ -1607,7 +1608,7 @@ double GSkyMap::flux(const GSkyPixel& pixel, const int& map) const GSkyDir centre = healpix->pix2dir(pixel); // Get boundaries - std::vector boundaries = healpix->boundaries(pixel, 3); + GSkyDirs boundaries = healpix->boundaries(pixel, 3); // Compute intensities double i0 = this->operator()(centre, map); diff --git a/src/sky/Makefile.am b/src/sky/Makefile.am index e3faf2d..71efd6b 100644 --- a/src/sky/Makefile.am +++ b/src/sky/Makefile.am @@ -1,7 +1,7 @@ ############################################################################# # Makefile.am for sky module # # ------------------------------------------------------------------------- # -# Copyright (C) 2016-2018 Juergen Knoedlseder # +# Copyright (C) 2016-2020 Juergen Knoedlseder # # ------------------------------------------------------------------------- # # # # This program is free software: you can redistribute it and/or modify # @@ -26,6 +26,7 @@ INCLUDES = -I$(top_srcdir)/include \ # Define sources for this directory sources = GSkyDir.cpp \ + GSkyDirs.cpp \ GHorizDir.cpp \ GSkyPixel.cpp \ GSkyMap.cpp \ diff --git a/test/test_GSky.cpp b/test/test_GSky.cpp index 58a6e36..5723286 100644 --- a/test/test_GSky.cpp +++ b/test/test_GSky.cpp @@ -63,6 +63,8 @@ void TestGSky::set(void){ "Test GWcs"); append(static_cast(&TestGSky::test_GSkyDir), "Test GSkyDir"); + append(static_cast(&TestGSky::test_GSkyDirs), + "Test GSkyDirs"); append(static_cast(&TestGSky::test_GSkyPixel), "Test GSkyPixel"); append(static_cast(&TestGSky::test_GSkyMap_healpix_construct), @@ -356,6 +358,65 @@ void TestGSky::test_GSkyDir(void) } +/*************************************************************************** + * @brief Test GSkyDirs class + ***************************************************************************/ +void TestGSky::test_GSkyDirs(void) +{ + // Manipulate GSkyDirs starting from an empty object + GSkyDirs dirs; + test_value(dirs.size(), 0, "GSkyDirs should have zero size."); + test_assert(dirs.is_empty(), "GSkyDirs should be empty."); + + // Add a sky direction + dirs.append(GSkyDir()); + test_value(dirs.size(), 1, "GSkyDirs should have 1 sky direction."); + test_assert(!dirs.is_empty(), "GSkyDirs should not be empty."); + + // Remove sky direction + dirs.remove(0); + test_value(dirs.size(), 0, "GSkyDirs should have zero size."); + test_assert(dirs.is_empty(), "GSkyDirs should be empty."); + + // Append two sky directions + dirs.append(GSkyDir()); + dirs.append(GSkyDir()); + test_value(dirs.size(), 2, "GSkyDirs should have 2 sky directions."); + test_assert(!dirs.is_empty(), "GSkyDirs should not be empty."); + + // Clear object + dirs.clear(); + test_value(dirs.size(), 0, "GSkyDirs should have zero size."); + test_assert(dirs.is_empty(), "GSkyDirs should be empty."); + + // Insert two sky directions + dirs.insert(0, GSkyDir()); + dirs.insert(0, GSkyDir()); + test_value(dirs.size(), 2, "GSkyDirs should have 2 sky directions."); + test_assert(!dirs.is_empty(), "GSkyDirs should not be empty."); + + // Extend sky directios + dirs.extend(dirs); + test_value(dirs.size(), 4, "GSkyDirs should have 4 sky directions."); + test_assert(!dirs.is_empty(), "GSkyDirs should not be empty."); + + // Create 4 sky directions + dirs.clear(); + for (int i = 0; i < 4; ++i) { + GSkyDir dir; + dir.radec_deg(double(i), double(i)); + dirs.append(dir); + } + for (int i = 0; i < 4; ++i) { + test_value(dirs[i].ra_deg(), double(i)); + test_value(dirs[i].dec_deg(), double(i)); + } + + // Return + return; +} + + /***********************************************************************//** * @brief Test GSkyPixel class * diff --git a/test/test_GSky.hpp b/test/test_GSky.hpp index 7e107ee..373d9b1 100644 --- a/test/test_GSky.hpp +++ b/test/test_GSky.hpp @@ -43,6 +43,7 @@ public: virtual std::string classname(void) const { return "TestGSky"; } void test_GWcs(void); void test_GSkyDir(void); + void test_GSkyDirs(void); void test_GSkyPixel(void); void test_GSkyMap_healpix_construct(void); void test_GSkyMap_healpix_io(void); diff --git a/test/test_GSky.py b/test/test_GSky.py index c4cb5c8..3a7376d 100755 --- a/test/test_GSky.py +++ b/test/test_GSky.py @@ -594,6 +594,7 @@ class Test(gammalib.GPythonTestSuite): test_support.pickeling(self, gammalib.GHealpix()) test_support.pickeling(self, gammalib.GHorizDir()) test_support.pickeling(self, gammalib.GSkyDir()) + test_support.pickeling(self, gammalib.GSkyDirs()) test_support.pickeling(self, gammalib.GSkyMap()) test_support.pickeling(self, gammalib.GSkyPixel()) test_support.pickeling(self, gammalib.GSkyRegionCircle()) @@ -629,6 +630,7 @@ class Test(gammalib.GPythonTestSuite): test_support.pickeling(self, gammalib.GHealpix(4)) test_support.pickeling(self, horizdir) test_support.pickeling(self, gammalib.GSkyDir(dir)) + test_support.pickeling(self, gammalib.GSkyDirs(dir)) test_support.pickeling(self, gammalib.GSkyMap(map)) test_support.pickeling(self, gammalib.GSkyPixel(1.0)) test_support.pickeling(self, gammalib.GSkyPixel(2.0,3.0)) -- libgit2 0.21.4