Commit ac6b92b73346342caff539597a5d8b8e49db455d
1 parent
9f845a0c
Add shape() and ndim() methods to GSkyMap.
The shape() and ndim() methods allow the handling of images with more than three dimensions in GSkyMap. Now higher dimensional images are properly read and written by the class, and the shape() method allows setting of higher dimensional map parameters.
Showing
7 changed files
with
493 additions
and
182 deletions
ChangeLog
| 1 | -2016-04-25 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 1 | +2016-05-30 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 2 | 2 | |
| 3 | 3 | * Version 1.1.0 released |
| 4 | 4 | ========================= |
| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | Add GApplication::logFileClose() method. |
| 11 | 11 | Add GCTAObservation filename constructor (#1744). |
| 12 | 12 | Add gammalib::number() function (#1743). |
| 13 | + Add GSkyMap::shape() and ndim() methods (#1733). | |
| 13 | 14 | Add energy dispersion cube for stacked analysis (#1721). |
| 14 | 15 | Add GEnergy division operator. |
| 15 | 16 | Support Fermi LAT Pass 8 response functions (#1517) | ... | ... |
NEWS
| ... | ... | @@ -2,7 +2,7 @@ New Features and Important Changes in GammaLib 1.1.0 |
| 2 | 2 | |
| 3 | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | |
| 5 | -25 April 2016 | |
| 5 | +30 May 2016 | |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | 1. Introduction |
| ... | ... | @@ -25,6 +25,8 @@ The following methods have been added to the public interface: |
| 25 | 25 | - GFilename::path() |
| 26 | 26 | - GFilename::file() |
| 27 | 27 | - GCsv::append() |
| 28 | +- GSkyMap::shape() | |
| 29 | +- GSkyMap::ndim() | |
| 28 | 30 | - GModelSky::spatial() |
| 29 | 31 | - GModelSky::spectral() |
| 30 | 32 | - GModelSky::temporal() |
| ... | ... | @@ -210,6 +212,13 @@ A GSkyMap::publish() method has been added that publishes the sky map |
| 210 | 212 | on a Virtual Observatory Hub. This finally makes GammaLib interoperable |
| 211 | 213 | with VO imaging tools (#1231). |
| 212 | 214 | |
| 215 | +A shape member was added to the GSkyMap class to enable handling of | |
| 216 | +images with more than 3 dimensions. The shape() methods set or retrieve | |
| 217 | +the number of maps in each of the dimensions, the ndim() method returns | |
| 218 | +the number of dimensions. Note that a longitude and latitude dimensions | |
| 219 | +are not counted in the map dimensions, i.e. a 3D image cube with | |
| 220 | +longitude, latitude and a number of maps has a dimension of 1 (#1733). | |
| 221 | + | |
| 213 | 222 | |
| 214 | 223 | 13. Support module |
| 215 | 224 | ------------------ | ... | ... |
include/GSkyMap.hpp
| ... | ... | @@ -29,6 +29,7 @@ |
| 29 | 29 | |
| 30 | 30 | /* __ Includes ___________________________________________________________ */ |
| 31 | 31 | #include <string> |
| 32 | +#include <vector> | |
| 32 | 33 | #include "GBase.hpp" |
| 33 | 34 | #include "GSkyDir.hpp" |
| 34 | 35 | #include "GSkyPixel.hpp" |
| ... | ... | @@ -127,37 +128,44 @@ public: |
| 127 | 128 | double operator()(const GSkyDir& dir, const int& map = 0) const; |
| 128 | 129 | |
| 129 | 130 | // Methods |
| 130 | - void clear(void); | |
| 131 | - GSkyMap* clone(void) const; | |
| 132 | - std::string classname(void) const; | |
| 133 | - const int& npix(void) const; | |
| 134 | - const int& nx(void) const; | |
| 135 | - const int& ny(void) const; | |
| 136 | - const int& nmaps(void) const; | |
| 137 | - void nmaps(const int& nmaps); | |
| 138 | - GSkyPixel inx2pix(const int& index) const; | |
| 139 | - GSkyDir inx2dir(const int& index) const; | |
| 140 | - GSkyDir pix2dir(const GSkyPixel& pixel) const; | |
| 141 | - int pix2inx(const GSkyPixel& pixel) const; | |
| 142 | - int dir2inx(const GSkyDir& dir) const; | |
| 143 | - GSkyPixel dir2pix(const GSkyDir& dir) const; | |
| 144 | - double flux(const int& index, const int& map = 0) const; | |
| 145 | - double flux(const GSkyPixel& pixel, const int& map = 0) const; | |
| 146 | - double solidangle(const int& index) const; | |
| 147 | - double solidangle(const GSkyPixel& pixel) const; | |
| 148 | - bool contains(const GSkyDir& dir) const; | |
| 149 | - bool contains(const GSkyPixel& pixel) const; | |
| 150 | - const GSkyProjection* projection(void) const; | |
| 151 | - void projection(const GSkyProjection& proj); | |
| 152 | - const double* pixels(void) const; | |
| 153 | - GSkyMap extract(const int& map, const int& nmaps = 1) const; | |
| 154 | - void stack_maps(void); | |
| 155 | - void load(const GFilename& filename); | |
| 156 | - void save(const GFilename& filename, bool clobber = false) const; | |
| 157 | - void read(const GFitsHDU& hdu); | |
| 158 | - void write(GFits& file) const; | |
| 159 | - void publish(const std::string& name = "") const; | |
| 160 | - std::string print(const GChatter& chatter = NORMAL) const; | |
| 131 | + void clear(void); | |
| 132 | + GSkyMap* clone(void) const; | |
| 133 | + std::string classname(void) const; | |
| 134 | + const int& npix(void) const; | |
| 135 | + const int& nx(void) const; | |
| 136 | + const int& ny(void) const; | |
| 137 | + const int& nmaps(void) const; | |
| 138 | + void nmaps(const int& nmaps); | |
| 139 | + const std::vector<int>& shape(void) const; | |
| 140 | + void shape(const int& s1); | |
| 141 | + void shape(const int& s1, const int& s2); | |
| 142 | + void shape(const int& s1, const int& s2, const int& s3); | |
| 143 | + void shape(const std::vector<int>& shape); | |
| 144 | + int ndim(void) const; | |
| 145 | + GSkyPixel inx2pix(const int& index) const; | |
| 146 | + GSkyDir inx2dir(const int& index) const; | |
| 147 | + GSkyDir pix2dir(const GSkyPixel& pixel) const; | |
| 148 | + int pix2inx(const GSkyPixel& pixel) const; | |
| 149 | + int dir2inx(const GSkyDir& dir) const; | |
| 150 | + GSkyPixel dir2pix(const GSkyDir& dir) const; | |
| 151 | + double flux(const int& index, const int& map = 0) const; | |
| 152 | + double flux(const GSkyPixel& pixel, const int& map = 0) const; | |
| 153 | + double solidangle(const int& index) const; | |
| 154 | + double solidangle(const GSkyPixel& pixel) const; | |
| 155 | + bool contains(const GSkyDir& dir) const; | |
| 156 | + bool contains(const GSkyPixel& pixel) const; | |
| 157 | + const GSkyProjection* projection(void) const; | |
| 158 | + void projection(const GSkyProjection& proj); | |
| 159 | + const double* pixels(void) const; | |
| 160 | + GSkyMap extract(const int& map, const int& nmaps = 1) const; | |
| 161 | + void stack_maps(void); | |
| 162 | + void load(const GFilename& filename); | |
| 163 | + void save(const GFilename& filename, | |
| 164 | + const bool& clobber = false) const; | |
| 165 | + void read(const GFitsHDU& hdu); | |
| 166 | + void write(GFits& file) const; | |
| 167 | + void publish(const std::string& name = "") const; | |
| 168 | + std::string print(const GChatter& chatter = NORMAL) const; | |
| 161 | 169 | |
| 162 | 170 | private: |
| 163 | 171 | // Private methods |
| ... | ... | @@ -187,6 +195,7 @@ private: |
| 187 | 195 | int m_num_maps; //!< Number of maps (used for pixel allocation) |
| 188 | 196 | int m_num_x; //!< Number of pixels in x direction (only 2D) |
| 189 | 197 | int m_num_y; //!< Number of pixels in y direction (only 2D) |
| 198 | + std::vector<int> m_shape; //!< Shape of the maps | |
| 190 | 199 | GSkyProjection* m_proj; //!< Pointer to sky projection |
| 191 | 200 | double* m_pixels; //!< Pointer to skymap pixels |
| 192 | 201 | |
| ... | ... | @@ -337,6 +346,30 @@ const int& GSkyMap::nmaps(void) const |
| 337 | 346 | |
| 338 | 347 | |
| 339 | 348 | /***********************************************************************//** |
| 349 | + * @brief Returns shape of maps | |
| 350 | + * | |
| 351 | + * @return Shape of maps in the sky map object. | |
| 352 | + ***************************************************************************/ | |
| 353 | +inline | |
| 354 | +const std::vector<int>& GSkyMap::shape(void) const | |
| 355 | +{ | |
| 356 | + return m_shape; | |
| 357 | +} | |
| 358 | + | |
| 359 | + | |
| 360 | +/***********************************************************************//** | |
| 361 | + * @brief Returns dimension of maps | |
| 362 | + * | |
| 363 | + * @return Number of map dimensions. | |
| 364 | + ***************************************************************************/ | |
| 365 | +inline | |
| 366 | +int GSkyMap::ndim(void) const | |
| 367 | +{ | |
| 368 | + return m_shape.size(); | |
| 369 | +} | |
| 370 | + | |
| 371 | + | |
| 372 | +/***********************************************************************//** | |
| 340 | 373 | * @brief Returns pointer to sky projection |
| 341 | 374 | * |
| 342 | 375 | * @return Pointer to sky projection (NULL if no projection is defined). | ... | ... |
pyext/GSkyMap.i
| ... | ... | @@ -28,6 +28,10 @@ |
| 28 | 28 | #include "GSkyMap.hpp" |
| 29 | 29 | #include "GTools.hpp" |
| 30 | 30 | %} |
| 31 | +%include "std_vector.i" | |
| 32 | +namespace std { | |
| 33 | + %template(IntVector) vector<int>; | |
| 34 | +} | |
| 31 | 35 | |
| 32 | 36 | |
| 33 | 37 | /***********************************************************************//** |
| ... | ... | @@ -143,36 +147,43 @@ public: |
| 143 | 147 | double operator()(const GSkyDir& dir, const int& map = 0) const; |
| 144 | 148 | |
| 145 | 149 | // Methods |
| 146 | - void clear(void); | |
| 147 | - GSkyMap* clone(void) const; | |
| 148 | - std::string classname(void) const; | |
| 149 | - const int& npix(void) const; | |
| 150 | - const int& nx(void) const; | |
| 151 | - const int& ny(void) const; | |
| 152 | - const int& nmaps(void) const; | |
| 153 | - void nmaps(const int& nmaps); | |
| 154 | - GSkyPixel inx2pix(const int& index) const; | |
| 155 | - GSkyDir inx2dir(const int& index) const; | |
| 156 | - GSkyDir pix2dir(const GSkyPixel& pixel) const; | |
| 157 | - int pix2inx(const GSkyPixel& pixel) const; | |
| 158 | - int dir2inx(const GSkyDir& dir) const; | |
| 159 | - GSkyPixel dir2pix(const GSkyDir& dir) const; | |
| 160 | - double flux(const int& index, const int& map = 0) const; | |
| 161 | - double flux(const GSkyPixel& pixel, const int& map = 0) const; | |
| 162 | - double solidangle(const int& index) const; | |
| 163 | - double solidangle(const GSkyPixel& pixel) const; | |
| 164 | - bool contains(const GSkyDir& dir) const; | |
| 165 | - bool contains(const GSkyPixel& pixel) const; | |
| 166 | - const GSkyProjection* projection(void) const; | |
| 167 | - void projection(const GSkyProjection& proj); | |
| 168 | - const double* pixels(void) const; | |
| 169 | - GSkyMap extract(const int& map, const int& nmaps = 1) const; | |
| 170 | - void stack_maps(void); | |
| 171 | - void load(const GFilename& filename); | |
| 172 | - void save(const GFilename& filename, bool clobber = false) const; | |
| 173 | - void read(const GFitsHDU& hdu); | |
| 174 | - void write(GFits& file) const; | |
| 175 | - void publish(const std::string& name = "") const; | |
| 150 | + void clear(void); | |
| 151 | + GSkyMap* clone(void) const; | |
| 152 | + std::string classname(void) const; | |
| 153 | + const int& npix(void) const; | |
| 154 | + const int& nx(void) const; | |
| 155 | + const int& ny(void) const; | |
| 156 | + const int& nmaps(void) const; | |
| 157 | + void nmaps(const int& nmaps); | |
| 158 | + const std::vector<int>& shape(void) const; | |
| 159 | + void shape(const int& s1); | |
| 160 | + void shape(const int& s1, const int& s2); | |
| 161 | + void shape(const int& s1, const int& s2, const int& s3); | |
| 162 | + void shape(const std::vector<int>& shape); | |
| 163 | + int ndim(void) const; | |
| 164 | + GSkyPixel inx2pix(const int& index) const; | |
| 165 | + GSkyDir inx2dir(const int& index) const; | |
| 166 | + GSkyDir pix2dir(const GSkyPixel& pixel) const; | |
| 167 | + int pix2inx(const GSkyPixel& pixel) const; | |
| 168 | + int dir2inx(const GSkyDir& dir) const; | |
| 169 | + GSkyPixel dir2pix(const GSkyDir& dir) const; | |
| 170 | + double flux(const int& index, const int& map = 0) const; | |
| 171 | + double flux(const GSkyPixel& pixel, const int& map = 0) const; | |
| 172 | + double solidangle(const int& index) const; | |
| 173 | + double solidangle(const GSkyPixel& pixel) const; | |
| 174 | + bool contains(const GSkyDir& dir) const; | |
| 175 | + bool contains(const GSkyPixel& pixel) const; | |
| 176 | + const GSkyProjection* projection(void) const; | |
| 177 | + void projection(const GSkyProjection& proj); | |
| 178 | + const double* pixels(void) const; | |
| 179 | + GSkyMap extract(const int& map, const int& nmaps = 1) const; | |
| 180 | + void stack_maps(void); | |
| 181 | + void load(const GFilename& filename); | |
| 182 | + void save(const GFilename& filename, | |
| 183 | + const bool& clobber = false) const; | |
| 184 | + void read(const GFitsHDU& hdu); | |
| 185 | + void write(GFits& file) const; | |
| 186 | + void publish(const std::string& name = "") const; | |
| 176 | 187 | }; |
| 177 | 188 | |
| 178 | 189 | ... | ... |
src/sky/GSkyMap.cpp
| ... | ... | @@ -51,6 +51,7 @@ |
| 51 | 51 | #define G_CONSTRUCT_MAP "GSkyMap::GSkyMap(std::string&, std::string&,"\ |
| 52 | 52 | " double&, double&, double& double&, int&, int&, int&)" |
| 53 | 53 | #define G_NMAPS "GSkyMap::nmaps(int&)" |
| 54 | +#define G_SHAPE "GSkyMap::shape(std::vector<int>&)" | |
| 54 | 55 | #define G_OP_UNARY_ADD "GSkyMap::operator+=(GSkyMap&)" |
| 55 | 56 | #define G_OP_UNARY_SUB "GSkyMap::operator-=(GSkyMap&)" |
| 56 | 57 | #define G_OP_UNARY_MUL "GSkyMap::operator-=(GSkyMap&)" |
| ... | ... | @@ -95,6 +96,8 @@ |
| 95 | 96 | |
| 96 | 97 | /***********************************************************************//** |
| 97 | 98 | * @brief Void constructor |
| 99 | + * | |
| 100 | + * Constructs an empty sky map. | |
| 98 | 101 | ***************************************************************************/ |
| 99 | 102 | GSkyMap::GSkyMap(void) |
| 100 | 103 | { |
| ... | ... | @@ -110,6 +113,9 @@ GSkyMap::GSkyMap(void) |
| 110 | 113 | * @brief FITS file constructor |
| 111 | 114 | * |
| 112 | 115 | * @param[in] filename FITS file name. |
| 116 | + * | |
| 117 | + * Constructs a sky map by loading data from a FITS file. See the load() | |
| 118 | + * method for more information about the FITS formats that are supported. | |
| 113 | 119 | ***************************************************************************/ |
| 114 | 120 | GSkyMap::GSkyMap(const GFilename& filename) |
| 115 | 121 | { |
| ... | ... | @@ -130,12 +136,13 @@ GSkyMap::GSkyMap(const GFilename& filename) |
| 130 | 136 | * @param[in] coords Coordinate System (CEL or GAL). |
| 131 | 137 | * @param[in] nside Nside parameter. |
| 132 | 138 | * @param[in] order Pixel ordering (RING or NEST). |
| 133 | - * @param[in] nmaps Number of maps in set (default=1). | |
| 139 | + * @param[in] nmaps Number of maps in set. | |
| 134 | 140 | * |
| 135 | 141 | * @exception GException::skymap_bad_par |
| 136 | 142 | * Invalid sky map parameter. |
| 137 | 143 | * |
| 138 | - * Constructs sky map in Healpix pixelisation. | |
| 144 | + * Constructs @p nmaps identical all sky maps in Healpix pixelisation. All | |
| 145 | + * pixels of the sky maps will be initialised to values of zero. | |
| 139 | 146 | ***************************************************************************/ |
| 140 | 147 | GSkyMap::GSkyMap(const std::string& coords, |
| 141 | 148 | const int& nside, |
| ... | ... | @@ -155,9 +162,10 @@ GSkyMap::GSkyMap(const std::string& coords, |
| 155 | 162 | GHealpix* projection = new GHealpix(nside, order, coords); |
| 156 | 163 | m_proj = projection; |
| 157 | 164 | |
| 158 | - // Set number of pixels and number of maps | |
| 165 | + // Set number of pixels, number of maps and shape of maps | |
| 159 | 166 | m_num_pixels = projection->npix(); |
| 160 | 167 | m_num_maps = nmaps; |
| 168 | + m_shape.push_back(nmaps); | |
| 161 | 169 | |
| 162 | 170 | // Allocate pixels |
| 163 | 171 | alloc_pixels(); |
| ... | ... | @@ -183,7 +191,9 @@ GSkyMap::GSkyMap(const std::string& coords, |
| 183 | 191 | * @exception GException::skymap_bad_par |
| 184 | 192 | * Invalid sky map parameter. |
| 185 | 193 | * |
| 186 | - * Constructs sky map in World Coordinate System projection. | |
| 194 | + * Constructs @p nmaps identical all sky maps in World Coordinate System | |
| 195 | + * projection. All pixels of the sky maps will be initialised to values of | |
| 196 | + * zero. | |
| 187 | 197 | ***************************************************************************/ |
| 188 | 198 | GSkyMap::GSkyMap(const std::string& wcs, |
| 189 | 199 | const std::string& coords, |
| ... | ... | @@ -224,11 +234,12 @@ GSkyMap::GSkyMap(const std::string& wcs, |
| 224 | 234 | set_wcs(wcs, coords, crval1, crval2, crpix1, crpix2, cdelt1, cdelt2, |
| 225 | 235 | cd, pv2); |
| 226 | 236 | |
| 227 | - // Set number of pixels and number of maps | |
| 237 | + // Set number of pixels, number of maps and shape of maps | |
| 228 | 238 | m_num_x = nx; |
| 229 | 239 | m_num_y = ny; |
| 230 | 240 | m_num_pixels = m_num_x * m_num_y; |
| 231 | 241 | m_num_maps = nmaps; |
| 242 | + m_shape.push_back(nmaps); | |
| 232 | 243 | |
| 233 | 244 | // Allocate pixels |
| 234 | 245 | alloc_pixels(); |
| ... | ... | @@ -242,6 +253,8 @@ GSkyMap::GSkyMap(const std::string& wcs, |
| 242 | 253 | * @brief Copy constructor |
| 243 | 254 | * |
| 244 | 255 | * @param[in] map Sky map. |
| 256 | + * | |
| 257 | + * Constructs sky maps by copying data from another sky map object. | |
| 245 | 258 | ***************************************************************************/ |
| 246 | 259 | GSkyMap::GSkyMap(const GSkyMap& map) |
| 247 | 260 | { |
| ... | ... | @@ -280,6 +293,8 @@ GSkyMap::~GSkyMap(void) |
| 280 | 293 | * |
| 281 | 294 | * @param[in] map Sky map. |
| 282 | 295 | * @return Sky map. |
| 296 | + * | |
| 297 | + * Assigns one sky map to another. | |
| 283 | 298 | ***************************************************************************/ |
| 284 | 299 | GSkyMap& GSkyMap::operator=(const GSkyMap& map) |
| 285 | 300 | { |
| ... | ... | @@ -308,7 +323,7 @@ GSkyMap& GSkyMap::operator=(const GSkyMap& map) |
| 308 | 323 | * @param[in] value Value. |
| 309 | 324 | * @return Sky map. |
| 310 | 325 | * |
| 311 | - * Sets all pixels to the specified @p value. | |
| 326 | + * Sets all sky map pixels to the specified @p value. | |
| 312 | 327 | ***************************************************************************/ |
| 313 | 328 | GSkyMap& GSkyMap::operator=(const double& value) |
| 314 | 329 | { |
| ... | ... | @@ -335,7 +350,7 @@ GSkyMap& GSkyMap::operator=(const double& value) |
| 335 | 350 | * Mismatch between number of maps in skymap object. |
| 336 | 351 | * |
| 337 | 352 | * Adds the content of @p map to the skymap. The operator only works on sky |
| 338 | - * maps with an identical number of layers. The content is added by | |
| 353 | + * maps with an identical number of maps. The content is added by | |
| 339 | 354 | * bi-linearily interpolating the values in the source sky map, allowing thus |
| 340 | 355 | * for a reprojection of sky map values. |
| 341 | 356 | * |
| ... | ... | @@ -1043,6 +1058,11 @@ void GSkyMap::nmaps(const int& nmaps) |
| 1043 | 1058 | // Set number of maps |
| 1044 | 1059 | m_num_maps = nmaps; |
| 1045 | 1060 | |
| 1061 | + // Set shape of maps to linear array since we do not know how to | |
| 1062 | + // arrange the new maps | |
| 1063 | + m_shape.clear(); | |
| 1064 | + m_shape.push_back(nmaps); | |
| 1065 | + | |
| 1046 | 1066 | } // endif: map had pixels |
| 1047 | 1067 | |
| 1048 | 1068 | // Return |
| ... | ... | @@ -1051,6 +1071,116 @@ void GSkyMap::nmaps(const int& nmaps) |
| 1051 | 1071 | |
| 1052 | 1072 | |
| 1053 | 1073 | /***********************************************************************//** |
| 1074 | + * @brief Set one-dimensional shape of maps | |
| 1075 | + * | |
| 1076 | + * @param[in] s1 Axis length of first dimension. | |
| 1077 | + ***************************************************************************/ | |
| 1078 | +void GSkyMap::shape(const int& s1) | |
| 1079 | +{ | |
| 1080 | + // Initialise vector | |
| 1081 | + std::vector<int> shape; | |
| 1082 | + | |
| 1083 | + // Set vector elements | |
| 1084 | + shape.push_back(s1); | |
| 1085 | + | |
| 1086 | + // Call vector method | |
| 1087 | + this->shape(shape); | |
| 1088 | + | |
| 1089 | + // Return | |
| 1090 | + return; | |
| 1091 | +} | |
| 1092 | + | |
| 1093 | + | |
| 1094 | +/***********************************************************************//** | |
| 1095 | + * @brief Set two-dimensional shape of maps | |
| 1096 | + * | |
| 1097 | + * @param[in] s1 Axis length of first dimension. | |
| 1098 | + * @param[in] s2 Axis length of second dimension. | |
| 1099 | + ***************************************************************************/ | |
| 1100 | +void GSkyMap::shape(const int& s1, const int& s2) | |
| 1101 | +{ | |
| 1102 | + // Initialise vector | |
| 1103 | + std::vector<int> shape; | |
| 1104 | + | |
| 1105 | + // Set vector elements | |
| 1106 | + shape.push_back(s1); | |
| 1107 | + shape.push_back(s2); | |
| 1108 | + | |
| 1109 | + // Call vector method | |
| 1110 | + this->shape(shape); | |
| 1111 | + | |
| 1112 | + // Return | |
| 1113 | + return; | |
| 1114 | +} | |
| 1115 | + | |
| 1116 | + | |
| 1117 | +/***********************************************************************//** | |
| 1118 | + * @brief Set three-dimensional shape of maps | |
| 1119 | + * | |
| 1120 | + * @param[in] s1 Axis length of first dimension. | |
| 1121 | + * @param[in] s2 Axis length of second dimension. | |
| 1122 | + * @param[in] s3 Axis length of second dimension. | |
| 1123 | + ***************************************************************************/ | |
| 1124 | +void GSkyMap::shape(const int& s1, const int& s2, const int& s3) | |
| 1125 | +{ | |
| 1126 | + // Initialise vector | |
| 1127 | + std::vector<int> shape; | |
| 1128 | + | |
| 1129 | + // Set vector elements | |
| 1130 | + shape.push_back(s1); | |
| 1131 | + shape.push_back(s2); | |
| 1132 | + shape.push_back(s3); | |
| 1133 | + | |
| 1134 | + // Call vector method | |
| 1135 | + this->shape(shape); | |
| 1136 | + | |
| 1137 | + // Return | |
| 1138 | + return; | |
| 1139 | +} | |
| 1140 | + | |
| 1141 | + | |
| 1142 | +/***********************************************************************//** | |
| 1143 | + * @brief Set shape of maps | |
| 1144 | + * | |
| 1145 | + * @param[in] shape Shape vector. | |
| 1146 | + * | |
| 1147 | + * @exception GException::invalid_argument | |
| 1148 | + * Invalid shape factorisation specified. | |
| 1149 | + * | |
| 1150 | + * Defines a shape for the maps in the object. The shape specifies how the | |
| 1151 | + * maps are arranged in a n-dimensional array. | |
| 1152 | + ***************************************************************************/ | |
| 1153 | +void GSkyMap::shape(const std::vector<int>& shape) | |
| 1154 | +{ | |
| 1155 | + // Computes the resulting number of maps | |
| 1156 | + int nmaps = 0; | |
| 1157 | + if (shape.size() > 0) { | |
| 1158 | + nmaps = 1; | |
| 1159 | + for (int i = 0; i < shape.size(); ++i) { | |
| 1160 | + nmaps *= shape[i]; | |
| 1161 | + } | |
| 1162 | + } | |
| 1163 | + | |
| 1164 | + // Throw an exception if resulting number of maps is not equal to the | |
| 1165 | + // existing number of maps | |
| 1166 | + if (nmaps != m_num_maps) { | |
| 1167 | + std::string msg = "Sky map shaping requires "+gammalib::str(nmaps)+ | |
| 1168 | + " maps while "+gammalib::str(m_num_maps)+" maps " | |
| 1169 | + "are available. Please specify an appropriate " | |
| 1170 | + "factorisation or modify the number of available " | |
| 1171 | + "maps."; | |
| 1172 | + throw GException::invalid_argument(G_SHAPE, msg); | |
| 1173 | + } | |
| 1174 | + | |
| 1175 | + // Set shape | |
| 1176 | + m_shape = shape; | |
| 1177 | + | |
| 1178 | + // Return | |
| 1179 | + return; | |
| 1180 | +} | |
| 1181 | + | |
| 1182 | + | |
| 1183 | +/***********************************************************************//** | |
| 1054 | 1184 | * @brief Converts pixel index into sky map pixel |
| 1055 | 1185 | * |
| 1056 | 1186 | * @param[in] index Pixel index [0,...,npix()-1]. |
| ... | ... | @@ -1624,7 +1754,7 @@ bool GSkyMap::contains(const GSkyPixel& pixel) const |
| 1624 | 1754 | * @brief Extract maps into a new sky map object |
| 1625 | 1755 | * |
| 1626 | 1756 | * @param[in] map First map to extract |
| 1627 | - * @param[in] nmaps Number of maps to extract (default: 1) | |
| 1757 | + * @param[in] nmaps Number of maps to extract | |
| 1628 | 1758 | * @return Extracted map(s). |
| 1629 | 1759 | * |
| 1630 | 1760 | * @exception GException::out_of_range |
| ... | ... | @@ -1685,6 +1815,10 @@ GSkyMap GSkyMap::extract(const int& map, const int& nmaps) const |
| 1685 | 1815 | // Set number of maps |
| 1686 | 1816 | result.m_num_maps = nmaps; |
| 1687 | 1817 | |
| 1818 | + // Reset shape of maps since we do not know how to arrange the maps | |
| 1819 | + result.m_shape.clear(); | |
| 1820 | + result.m_shape.push_back(nmaps); | |
| 1821 | + | |
| 1688 | 1822 | // Return map |
| 1689 | 1823 | return result; |
| 1690 | 1824 | } |
| ... | ... | @@ -1726,6 +1860,10 @@ void GSkyMap::stack_maps(void) |
| 1726 | 1860 | // Set number of maps to 1 |
| 1727 | 1861 | m_num_maps = 1; |
| 1728 | 1862 | |
| 1863 | + // Reset shape of maps | |
| 1864 | + m_shape.clear(); | |
| 1865 | + m_shape.push_back(m_num_maps); | |
| 1866 | + | |
| 1729 | 1867 | } // endif: map had pixels |
| 1730 | 1868 | |
| 1731 | 1869 | // Return |
| ... | ... | @@ -1839,13 +1977,13 @@ void GSkyMap::load(const GFilename& filename) |
| 1839 | 1977 | * @brief Save sky map into FITS file |
| 1840 | 1978 | * |
| 1841 | 1979 | * @param[in] filename FITS file name. |
| 1842 | - * @param[in] clobber Overwrite existing file? (default: false) | |
| 1980 | + * @param[in] clobber Overwrite existing file? | |
| 1843 | 1981 | * |
| 1844 | 1982 | * Saves the sky map into a FITS file. If the file exists already the method |
| 1845 | 1983 | * will append the sky map to the FITS file in case that the @p clobber |
| 1846 | 1984 | * parameter is set to true. |
| 1847 | 1985 | ***************************************************************************/ |
| 1848 | -void GSkyMap::save(const GFilename& filename, bool clobber) const | |
| 1986 | +void GSkyMap::save(const GFilename& filename, const bool& clobber) const | |
| 1849 | 1987 | { |
| 1850 | 1988 | // Continue only if we have data to save |
| 1851 | 1989 | if (m_proj != NULL) { |
| ... | ... | @@ -2023,11 +2161,11 @@ std::string GSkyMap::print(const GChatter& chatter) const |
| 2023 | 2161 | // Append header |
| 2024 | 2162 | result.append("=== GSkyMap ==="); |
| 2025 | 2163 | |
| 2026 | - // Append information | |
| 2164 | + // Append number of pixels and number of maps | |
| 2027 | 2165 | result.append("\n"+gammalib::parformat("Number of pixels")); |
| 2028 | 2166 | result.append(gammalib::str(m_num_pixels)); |
| 2029 | - result.append("\n"+gammalib::parformat("Number of maps")); | |
| 2030 | - result.append(gammalib::str(m_num_maps)); | |
| 2167 | + | |
| 2168 | + // Append WCS dimension information | |
| 2031 | 2169 | if (m_proj != NULL && m_proj->size() == 2) { |
| 2032 | 2170 | result.append("\n"+gammalib::parformat("X axis dimension")); |
| 2033 | 2171 | result.append(gammalib::str(m_num_x)); |
| ... | ... | @@ -2035,6 +2173,27 @@ std::string GSkyMap::print(const GChatter& chatter) const |
| 2035 | 2173 | result.append(gammalib::str(m_num_y)); |
| 2036 | 2174 | } |
| 2037 | 2175 | |
| 2176 | + // Append number of maps | |
| 2177 | + result.append("\n"+gammalib::parformat("Number of maps")); | |
| 2178 | + result.append(gammalib::str(m_num_maps)); | |
| 2179 | + | |
| 2180 | + // Append shape of maps | |
| 2181 | + result.append("\n"+gammalib::parformat("Shape of maps")); | |
| 2182 | + if (m_shape.size() > 0) { | |
| 2183 | + std::string shape = "("; | |
| 2184 | + for (int i = 0; i < m_shape.size(); ++i) { | |
| 2185 | + if (i > 0) { | |
| 2186 | + shape += ", "; | |
| 2187 | + } | |
| 2188 | + shape += gammalib::str(m_shape[i]); | |
| 2189 | + } | |
| 2190 | + shape += ")"; | |
| 2191 | + result.append(shape); | |
| 2192 | + } | |
| 2193 | + else { | |
| 2194 | + result.append("not defined"); | |
| 2195 | + } | |
| 2196 | + | |
| 2038 | 2197 | // Append sky projection information |
| 2039 | 2198 | if (gammalib::reduce(chatter) > SILENT) { |
| 2040 | 2199 | if (m_proj != NULL) { |
| ... | ... | @@ -2068,6 +2227,7 @@ void GSkyMap::init_members(void) |
| 2068 | 2227 | m_num_maps = 0; |
| 2069 | 2228 | m_num_x = 0; |
| 2070 | 2229 | m_num_y = 0; |
| 2230 | + m_shape.clear(); | |
| 2071 | 2231 | m_proj = NULL; |
| 2072 | 2232 | m_pixels = NULL; |
| 2073 | 2233 | |
| ... | ... | @@ -2118,6 +2278,7 @@ void GSkyMap::copy_members(const GSkyMap& map) |
| 2118 | 2278 | m_num_maps = map.m_num_maps; |
| 2119 | 2279 | m_num_x = map.m_num_x; |
| 2120 | 2280 | m_num_y = map.m_num_y; |
| 2281 | + m_shape = map.m_shape; | |
| 2121 | 2282 | |
| 2122 | 2283 | // Copy computation cache |
| 2123 | 2284 | m_hascache = map.m_hascache; |
| ... | ... | @@ -2157,12 +2318,6 @@ void GSkyMap::free_members(void) |
| 2157 | 2318 | m_proj = NULL; |
| 2158 | 2319 | m_pixels = NULL; |
| 2159 | 2320 | |
| 2160 | - // Reset number of pixels | |
| 2161 | - m_num_pixels = 0; | |
| 2162 | - m_num_maps = 0; | |
| 2163 | - m_num_x = 0; | |
| 2164 | - m_num_y = 0; | |
| 2165 | - | |
| 2166 | 2321 | // Return |
| 2167 | 2322 | return; |
| 2168 | 2323 | } |
| ... | ... | @@ -2293,6 +2448,10 @@ void GSkyMap::read_healpix(const GFitsTable& table) |
| 2293 | 2448 | std::cout << "m_num_maps=" << m_num_maps << std::endl; |
| 2294 | 2449 | #endif |
| 2295 | 2450 | |
| 2451 | + // Initialise shape of maps | |
| 2452 | + m_shape.clear(); | |
| 2453 | + m_shape.push_back(m_num_maps); | |
| 2454 | + | |
| 2296 | 2455 | // Allocate pixels to hold the map |
| 2297 | 2456 | alloc_pixels(); |
| 2298 | 2457 | |
| ... | ... | @@ -2360,34 +2519,50 @@ void GSkyMap::read_healpix(const GFitsTable& table) |
| 2360 | 2519 | * |
| 2361 | 2520 | * @param[in] image FITS image. |
| 2362 | 2521 | * |
| 2522 | + * @exception GException::invalid_argument | |
| 2523 | + * FITS image has less than two dimensions | |
| 2363 | 2524 | * @exception GException::invalid_value |
| 2364 | - * WCS image has an invalid dimension or covers a too large | |
| 2365 | - * range. | |
| 2525 | + * Sky map covers more than 360 deg in longitude or 180 deg in | |
| 2526 | + * latitude | |
| 2527 | + * | |
| 2528 | + * Reads sky maps from a FITS image extension containing a set of maps given | |
| 2529 | + * in World Coordinate System. The method handles general n-dimensional | |
| 2530 | + * images and sets the map shape attribute according to the number of map | |
| 2531 | + * dimensions found in the FITS HDU. | |
| 2366 | 2532 | ***************************************************************************/ |
| 2367 | 2533 | void GSkyMap::read_wcs(const GFitsImage& image) |
| 2368 | 2534 | { |
| 2535 | + // Throw an exception if the FITS image is not at least a 2D image | |
| 2536 | + if (image.naxis() < 2) { | |
| 2537 | + std::string msg = "Sky map has "+gammalib::str(image.naxis())+ | |
| 2538 | + " dimensions, which is less than the two dimensions" | |
| 2539 | + " that are required for a WCS image."; | |
| 2540 | + throw GException::invalid_argument(G_READ_WCS, msg); | |
| 2541 | + } | |
| 2542 | + | |
| 2369 | 2543 | // Allocate WCS |
| 2370 | 2544 | alloc_wcs(image); |
| 2371 | 2545 | |
| 2372 | 2546 | // Read projection information from FITS header |
| 2373 | 2547 | m_proj->read(image); |
| 2374 | 2548 | |
| 2375 | - // Extract map dimension and number of maps from image | |
| 2549 | + // Clear map shape | |
| 2550 | + m_shape.clear(); | |
| 2551 | + | |
| 2552 | + // Extract map dimension, number of maps and map shape from FITS image | |
| 2553 | + m_num_x = image.naxes(0); | |
| 2554 | + m_num_y = image.naxes(1); | |
| 2376 | 2555 | if (image.naxis() == 2) { |
| 2377 | - m_num_x = image.naxes(0); | |
| 2378 | - m_num_y = image.naxes(1); | |
| 2379 | 2556 | m_num_maps = 1; |
| 2380 | - } | |
| 2381 | - else if (image.naxis() >= 3) { | |
| 2382 | - m_num_x = image.naxes(0); | |
| 2383 | - m_num_y = image.naxes(1); | |
| 2384 | - m_num_maps = image.naxes(2); | |
| 2557 | + m_shape.push_back(m_num_maps); | |
| 2385 | 2558 | } |
| 2386 | 2559 | else { |
| 2387 | - std::string msg = "Skymap has a dimension of "+ | |
| 2388 | - gammalib::str(image.naxis())+" but only dimensions " | |
| 2389 | - "of 2 or 3 are supported."; | |
| 2390 | - throw GException::invalid_value(G_READ_WCS, msg); | |
| 2560 | + m_num_maps = image.naxes(2); | |
| 2561 | + m_shape.push_back(m_num_maps); | |
| 2562 | + for (int i = 3; i < image.naxis(); ++i) { | |
| 2563 | + m_num_maps *= image.naxes(i); | |
| 2564 | + m_shape.push_back(image.naxes(i)); | |
| 2565 | + } | |
| 2391 | 2566 | } |
| 2392 | 2567 | #if defined(G_READ_WCS_DEBUG) |
| 2393 | 2568 | std::cout << "m_num_x=" << m_num_x << std::endl; |
| ... | ... | @@ -2405,23 +2580,10 @@ void GSkyMap::read_wcs(const GFitsImage& image) |
| 2405 | 2580 | alloc_pixels(); |
| 2406 | 2581 | |
| 2407 | 2582 | // Read image |
| 2408 | - if (image.naxis() == 2) { | |
| 2409 | - double* ptr = m_pixels; | |
| 2410 | - for (int iy = 0; iy < m_num_y; ++iy) { | |
| 2411 | - for (int ix = 0; ix < m_num_x; ++ix) { | |
| 2412 | - *ptr++ = image.pixel(ix,iy); | |
| 2413 | - } | |
| 2414 | - } | |
| 2415 | - } | |
| 2416 | - else { | |
| 2417 | - double* ptr = m_pixels; | |
| 2418 | - for (int imap = 0; imap < m_num_maps; ++imap) { | |
| 2419 | - for (int iy = 0; iy < m_num_y; ++iy) { | |
| 2420 | - for (int ix = 0; ix < m_num_x; ++ix) { | |
| 2421 | - *ptr++ = image.pixel(ix,iy,imap); | |
| 2422 | - } | |
| 2423 | - } | |
| 2424 | - } | |
| 2583 | + double* ptr = m_pixels; | |
| 2584 | + int size = m_num_pixels * m_num_maps; | |
| 2585 | + for (int i = 0; i < size; ++i) { | |
| 2586 | + *ptr++ = (double)image.pixel(i); | |
| 2425 | 2587 | } |
| 2426 | 2588 | |
| 2427 | 2589 | // Check if the map is too large |
| ... | ... | @@ -2570,12 +2732,22 @@ GFitsImageDouble* GSkyMap::create_wcs_hdu(void) const |
| 2570 | 2732 | if (size > 0) { |
| 2571 | 2733 | |
| 2572 | 2734 | // Set axis parameters for image construction |
| 2573 | - int naxis = (m_num_maps == 1) ? 2 : 3; | |
| 2574 | - int naxes[] = {m_num_x, m_num_y, m_num_maps}; | |
| 2735 | + int naxis = (m_num_maps == 1) ? 2 : 2 + ndim(); | |
| 2736 | + | |
| 2737 | + // Set dimensions of all axes | |
| 2738 | + int* naxes = new int[naxis]; | |
| 2739 | + naxes[0] = m_num_x; | |
| 2740 | + naxes[1] = m_num_y; | |
| 2741 | + for (int i = 0; i < ndim(); ++i) { | |
| 2742 | + naxes[2+i] = m_shape[i]; | |
| 2743 | + } | |
| 2575 | 2744 | |
| 2576 | 2745 | // Allocate image |
| 2577 | 2746 | hdu = new GFitsImageDouble(naxis, naxes); |
| 2578 | 2747 | |
| 2748 | + // Free dimensions of all axes | |
| 2749 | + delete [] naxes; | |
| 2750 | + | |
| 2579 | 2751 | // Store data in image |
| 2580 | 2752 | if (naxis == 2) { |
| 2581 | 2753 | double* ptr = m_pixels; | ... | ... |
test/test_GSky.cpp
| ... | ... | @@ -842,6 +842,12 @@ void TestGSky::test_GSkyMap(void) |
| 842 | 842 | GSkyMap map_dst("CAR", "GAL", 0.0, 0.0, -0.1, 0.1, 100, 100, 2); |
| 843 | 843 | GSkyMap map_new("CAR", "GAL", 0.0, 0.0, -0.1, 0.1, 100, 100, 2); |
| 844 | 844 | |
| 845 | + // Test map dimensions and shape | |
| 846 | + test_value(map_src.nmaps(), 2, "Check that sky map contains 2 maps"); | |
| 847 | + test_value(map_src.ndim(), 1, "Check that sky map has one dimension"); | |
| 848 | + test_value(map_src.shape().size(), 1, "Check that sky map has a shape size of 1"); | |
| 849 | + test_value(map_src.shape()[0], 2, "Check that sky map has 2 maps"); | |
| 850 | + | |
| 845 | 851 | // Fill map pixels |
| 846 | 852 | double total_src = 0.0; |
| 847 | 853 | for (int pix = 0; pix < map_src.npix(); ++pix) { |
| ... | ... | @@ -1027,6 +1033,50 @@ void TestGSky::test_GSkyMap(void) |
| 1027 | 1033 | test_value(total_extract, total_src, 1.0e-3, "Test extract() method with 2 maps"); |
| 1028 | 1034 | test_value(map_extract.nmaps(), 2, "Test extract() method with 2 maps"); |
| 1029 | 1035 | |
| 1036 | + // Define one more map for shaping manipulation | |
| 1037 | + GSkyMap map_shape("CAR", "GAL", 0.0, 0.0, -1.0, 1.0, 10, 10, 12); | |
| 1038 | + | |
| 1039 | + // Test initial map dimensions and shape | |
| 1040 | + test_value(map_shape.nmaps(), 12, "Check that sky map contains 12 maps"); | |
| 1041 | + test_value(map_shape.ndim(), 1, "Check that sky map has one dimension"); | |
| 1042 | + test_value(map_shape.shape().size(), 1, "Check that sky map has a shape size of 1"); | |
| 1043 | + test_value(map_shape.shape()[0], 12, "Check that sky map has 12 maps"); | |
| 1044 | + | |
| 1045 | + // Set new map shape | |
| 1046 | + map_shape.shape(3,4); | |
| 1047 | + | |
| 1048 | + // Test map dimensions and shape | |
| 1049 | + test_value(map_shape.nmaps(), 12, "Check that sky map contains 12 maps"); | |
| 1050 | + test_value(map_shape.ndim(), 2, "Check that sky map has two dimensions"); | |
| 1051 | + test_value(map_shape.shape().size(), 2, "Check that sky map has a shape size of 2"); | |
| 1052 | + test_value(map_shape.shape()[0], 3, "Check that sky map has 3 maps in first dimension"); | |
| 1053 | + test_value(map_shape.shape()[1], 4, "Check that sky map has 4 maps in second dimension"); | |
| 1054 | + | |
| 1055 | + // Set new map shape | |
| 1056 | + map_shape.shape(2,3,2); | |
| 1057 | + | |
| 1058 | + // Test map dimensions and shape | |
| 1059 | + test_value(map_shape.nmaps(), 12, "Check that sky map contains 12 maps"); | |
| 1060 | + test_value(map_shape.ndim(), 3, "Check that sky map has three dimensions"); | |
| 1061 | + test_value(map_shape.shape().size(), 3, "Check that sky map has a shape size of 3"); | |
| 1062 | + test_value(map_shape.shape()[0], 2, "Check that sky map has 2 maps in first dimension"); | |
| 1063 | + test_value(map_shape.shape()[1], 3, "Check that sky map has 3 maps in second dimension"); | |
| 1064 | + test_value(map_shape.shape()[2], 2, "Check that sky map has 2 maps in third dimension"); | |
| 1065 | + | |
| 1066 | + // Save map | |
| 1067 | + map_shape.save("test_map_shape.fits", true); | |
| 1068 | + | |
| 1069 | + // Load map | |
| 1070 | + GSkyMap map_load_shape("test_map_shape.fits"); | |
| 1071 | + | |
| 1072 | + // Test map dimensions and shape | |
| 1073 | + test_value(map_load_shape.nmaps(), 12, "Check that sky map contains 12 maps"); | |
| 1074 | + test_value(map_load_shape.ndim(), 3, "Check that sky map has three dimensions"); | |
| 1075 | + test_value(map_load_shape.shape().size(), 3, "Check that sky map has a shape size of 3"); | |
| 1076 | + test_value(map_load_shape.shape()[0], 2, "Check that sky map has 2 maps in first dimension"); | |
| 1077 | + test_value(map_load_shape.shape()[1], 3, "Check that sky map has 3 maps in second dimension"); | |
| 1078 | + test_value(map_load_shape.shape()[2], 2, "Check that sky map has 2 maps in third dimension"); | |
| 1079 | + | |
| 1030 | 1080 | // Exit test |
| 1031 | 1081 | return; |
| 1032 | 1082 | } | ... | ... |
test/test_GSky.py
| 1 | 1 | # ========================================================================== |
| 2 | 2 | # This module performs unit tests for the GammaLib sky module. |
| 3 | 3 | # |
| 4 | -# Copyright (C) 2012-2015 Juergen Knoedlseder | |
| 4 | +# Copyright (C) 2012-2016 Juergen Knoedlseder | |
| 5 | 5 | # |
| 6 | 6 | # This program is free software: you can redistribute it and/or modify |
| 7 | 7 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -71,6 +71,8 @@ class Test(gammalib.GPythonTestSuite): |
| 71 | 71 | self.name("sky") |
| 72 | 72 | |
| 73 | 73 | # Append tests |
| 74 | + self.append(self.test_methods, "Test sky map methods") | |
| 75 | + self.append(self.test_operators, "Test sky map operators") | |
| 74 | 76 | self.append(self.test_skymap_healpix, "Test HEALPix map") |
| 75 | 77 | self.append(self.test_skymap_ait, "Test AIT projection map") |
| 76 | 78 | self.append(self.test_skymap_azp, "Test AZP projection map") |
| ... | ... | @@ -80,11 +82,109 @@ class Test(gammalib.GPythonTestSuite): |
| 80 | 82 | self.append(self.test_skymap_stg, "Test STG projection map") |
| 81 | 83 | self.append(self.test_skymap_tan, "Test TAN projection map") |
| 82 | 84 | self.append(self.test_fk5_to_galactic, "Test FK5 to Galactic coordinate conversion") |
| 83 | - self.append(self.test_operators, "Test skymap operators") | |
| 84 | 85 | |
| 85 | 86 | # Return |
| 86 | 87 | return |
| 87 | 88 | |
| 89 | + # Test sky map methods | |
| 90 | + def test_methods(self): | |
| 91 | + """ | |
| 92 | + Test the sky map methods. | |
| 93 | + """ | |
| 94 | + # Setup sky maps | |
| 95 | + map = gammalib.GSkyMap("CAR", "CEL", 83.63, 22.01, -3.7, 2.6, 10, 8, 12) | |
| 96 | + | |
| 97 | + # Set sky map shape | |
| 98 | + map.shape(3,4) | |
| 99 | + | |
| 100 | + # Test map dimensions and shape | |
| 101 | + self.test_value(map.npix(), 80, "Check that sky map has 80 pixels"); | |
| 102 | + self.test_value(map.nx(), 10, "Check that sky map has X dimension of 10"); | |
| 103 | + self.test_value(map.ny(), 8, "Check that sky map has Y dimension of 8"); | |
| 104 | + self.test_value(map.nmaps(), 12, "Check that sky map contains 12 maps"); | |
| 105 | + self.test_value(map.ndim(), 2, "Check that sky map has two dimensions"); | |
| 106 | + self.test_value(len(map.shape()), 2, "Check that sky map has a shape size of 2"); | |
| 107 | + self.test_value(map.shape()[0], 3, "Check that sky map has 3 maps in first dimension"); | |
| 108 | + self.test_value(map.shape()[1], 4, "Check that sky map has 4 maps in second dimension"); | |
| 109 | + | |
| 110 | + # Set new map shape | |
| 111 | + map.shape(2,3,2); | |
| 112 | + | |
| 113 | + # Test map dimensions and shape | |
| 114 | + self.test_value(map.nmaps(), 12, "Check that sky map contains 12 maps"); | |
| 115 | + self.test_value(map.ndim(), 3, "Check that sky map has three dimensions"); | |
| 116 | + self.test_value(len(map.shape()), 3, "Check that sky map has a shape size of 3"); | |
| 117 | + self.test_value(map.shape()[0], 2, "Check that sky map has 2 maps in first dimension"); | |
| 118 | + self.test_value(map.shape()[1], 3, "Check that sky map has 3 maps in second dimension"); | |
| 119 | + self.test_value(map.shape()[2], 2, "Check that sky map has 2 maps in third dimension"); | |
| 120 | + | |
| 121 | + # Return | |
| 122 | + return | |
| 123 | + | |
| 124 | + # Test sky map operators | |
| 125 | + def test_operators(self): | |
| 126 | + """ | |
| 127 | + Test the sky map operators. | |
| 128 | + """ | |
| 129 | + # Setup sky maps | |
| 130 | + map = gammalib.GSkyMap("CAR", "CEL", 83.6331, 22.0145, -3.7, 2.6, 2, 2) | |
| 131 | + map[0] = 1.0 | |
| 132 | + map[1] = 2.0 | |
| 133 | + map[2] = 3.0 | |
| 134 | + map[3] = 4.0 | |
| 135 | + map_b = map.copy() | |
| 136 | + | |
| 137 | + # Addition operator | |
| 138 | + map += map_b | |
| 139 | + self.test_value(map[0], 2.0) | |
| 140 | + self.test_value(map[1], 4.0) | |
| 141 | + self.test_value(map[2], 6.0) | |
| 142 | + self.test_value(map[3], 8.0) | |
| 143 | + | |
| 144 | + # Multiplication operator | |
| 145 | + map *= map_b | |
| 146 | + self.test_value(map[0], 2.0) | |
| 147 | + self.test_value(map[1], 8.0) | |
| 148 | + self.test_value(map[2], 18.0) | |
| 149 | + self.test_value(map[3], 32.0) | |
| 150 | + | |
| 151 | + # Subtraction operator | |
| 152 | + map -= map_b | |
| 153 | + self.test_value(map[0], 1.0) | |
| 154 | + self.test_value(map[1], 6.0) | |
| 155 | + self.test_value(map[2], 15.0) | |
| 156 | + self.test_value(map[3], 28.0) | |
| 157 | + | |
| 158 | + # Division operator | |
| 159 | + map /= map_b | |
| 160 | + self.test_value(map[0], 1.0) | |
| 161 | + self.test_value(map[1], 3.0) | |
| 162 | + self.test_value(map[2], 5.0) | |
| 163 | + self.test_value(map[3], 7.0) | |
| 164 | + | |
| 165 | + # Scaling operator | |
| 166 | + map *= 2.0 | |
| 167 | + self.test_value(map[0], 2.0) | |
| 168 | + self.test_value(map[1], 6.0) | |
| 169 | + self.test_value(map[2], 10.0) | |
| 170 | + self.test_value(map[3], 14.0) | |
| 171 | + | |
| 172 | + # Division operator | |
| 173 | + map /= 2.0 | |
| 174 | + self.test_value(map[0], 1.0) | |
| 175 | + self.test_value(map[1], 3.0) | |
| 176 | + self.test_value(map[2], 5.0) | |
| 177 | + self.test_value(map[3], 7.0) | |
| 178 | + | |
| 179 | + # Access operator (tests also proper iteration) | |
| 180 | + sum = 0.0 | |
| 181 | + for pix in map: | |
| 182 | + sum += pix | |
| 183 | + self.test_value(sum, 16.0) | |
| 184 | + | |
| 185 | + # Return | |
| 186 | + return | |
| 187 | + | |
| 88 | 188 | # Generic skymap pixel transformation test |
| 89 | 189 | def test_skymap_pixels(self, pixels, map): |
| 90 | 190 | """ |
| ... | ... | @@ -315,68 +415,3 @@ class Test(gammalib.GPythonTestSuite): |
| 315 | 415 | |
| 316 | 416 | # Return |
| 317 | 417 | return |
| 318 | - | |
| 319 | - # Test skymap operators | |
| 320 | - def test_operators(self): | |
| 321 | - """ | |
| 322 | - Test the skymap operators. | |
| 323 | - """ | |
| 324 | - # Setup skymaps | |
| 325 | - map = gammalib.GSkyMap("CAR", "CEL", 83.6331, 22.0145, -3.7, 2.6, 2, 2) | |
| 326 | - map[0] = 1.0 | |
| 327 | - map[1] = 2.0 | |
| 328 | - map[2] = 3.0 | |
| 329 | - map[3] = 4.0 | |
| 330 | - map_b = map.copy() | |
| 331 | - | |
| 332 | - # Addition operator | |
| 333 | - map += map_b | |
| 334 | - self.test_value(map[0], 2.0) | |
| 335 | - self.test_value(map[1], 4.0) | |
| 336 | - self.test_value(map[2], 6.0) | |
| 337 | - self.test_value(map[3], 8.0) | |
| 338 | - | |
| 339 | - # Multiplication operator | |
| 340 | - map *= map_b | |
| 341 | - self.test_value(map[0], 2.0) | |
| 342 | - self.test_value(map[1], 8.0) | |
| 343 | - self.test_value(map[2], 18.0) | |
| 344 | - self.test_value(map[3], 32.0) | |
| 345 | - | |
| 346 | - # Subtraction operator | |
| 347 | - map -= map_b | |
| 348 | - self.test_value(map[0], 1.0) | |
| 349 | - self.test_value(map[1], 6.0) | |
| 350 | - self.test_value(map[2], 15.0) | |
| 351 | - self.test_value(map[3], 28.0) | |
| 352 | - | |
| 353 | - # Division operator | |
| 354 | - map /= map_b | |
| 355 | - self.test_value(map[0], 1.0) | |
| 356 | - self.test_value(map[1], 3.0) | |
| 357 | - self.test_value(map[2], 5.0) | |
| 358 | - self.test_value(map[3], 7.0) | |
| 359 | - | |
| 360 | - # Scaling operator | |
| 361 | - map *= 2.0 | |
| 362 | - self.test_value(map[0], 2.0) | |
| 363 | - self.test_value(map[1], 6.0) | |
| 364 | - self.test_value(map[2], 10.0) | |
| 365 | - self.test_value(map[3], 14.0) | |
| 366 | - | |
| 367 | - # Division operator | |
| 368 | - map /= 2.0 | |
| 369 | - self.test_value(map[0], 1.0) | |
| 370 | - self.test_value(map[1], 3.0) | |
| 371 | - self.test_value(map[2], 5.0) | |
| 372 | - self.test_value(map[3], 7.0) | |
| 373 | - | |
| 374 | - # Access operator (tests also proper iteration) | |
| 375 | - sum = 0.0 | |
| 376 | - for pix in map: | |
| 377 | - sum += pix | |
| 378 | - self.test_value(sum, 16.0) | |
| 379 | - | |
| 380 | - # Return | |
| 381 | - return | |
| 382 | - | |
| 383 | 418 | \ No newline at end of file | ... | ... |