Commit f82edebf5b30082660b4e45cfcff9a317313b2af

Authored by Pierrick Martin
2 parents 0e5bb9e3 85d55d08

Merge branch 'devel' into 1044-implement-onoff-fitting

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
... ... @@ -6,3 +6,4 @@ Pierrick Martin (pierrick.martin@irap.omp.eu)
6 6 Michael Mayer (michael.mayer@desy.de)
7 7 Ellis Owen (Ellis.Owen@mpi-hd.mpg.de)
8 8 Anneli Schulz (anneli.schulz@desy.de)
  9 +
... ...
ChangeLog
1   -2014-01-17 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
  1 +2014-01-18 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
2 2  
3 3 * Version 0.8.0 released
4 4 ========================
... ... @@ -23,6 +23,8 @@
23 23 Put likelihood computation in GObservation class
24 24 Add broken power law spectral model
25 25 Add Gaussian spectral model
  26 + Update parameter files if necessary
  27 + Implement exact sky map pixel solid angle computation
26 28 Rename the following classes:
27 29 - GWcs => GSkyProjection
28 30 - GWcslib => GWcs
... ...
1   -New Features and Important Changes in GammaLib 00-08-00
  1 +vNew Features and Important Changes in GammaLib 00-08-00
2 2  
3 3 Author(s) : Juergen Knoedlseder
4 4  
5   -17 January 2014
  5 +18 January 2014
6 6  
7 7  
8 8 1. Introduction
... ... @@ -375,6 +375,11 @@ installed. This allows providing absolute paths for unit testing, a need
375 375 for the special valgrind rule in case that Sonar is used for quality
376 376 checking.
377 377  
  378 +The configuration script now updates any parameter files in the users
  379 +pfiles directory that is older than the system parameter files. This
  380 +corrects for problems that arose when parameter files in the pfiles
  381 +directory did not include all parameters necessary for the latest version.
  382 +
378 383  
379 384 4. Application module
380 385 ---------------------
... ... @@ -560,7 +565,12 @@ The GSkyPixel class now supports 1D and 2D pixelisations, allowing
560 565 a more generic usage of the class. Integer and double precision
561 566 values can be assigned from and to GSkyPixel for 1D pixelisations.
562 567  
563   -The GWcsAIT class has been added for Aitoff-Hammer projections.
  568 +The GWcsAIT class has been added for Aitoff projections.
  569 +
  570 +The solid angle of sky map pixels are now computed using the spherical
  571 +excess. This provides accurate solid angles even in case that the
  572 +pixels are highly distorted, for example at the poles of the Aitoff
  573 +projections.
564 574  
565 575  
566 576 13. Support module
... ...
1 1 GammaLib information
2 2 ====================
3   -Version: 00-08-00 (January 31st, 2013)
  3 +Version: 00-08-00 (18 January 2014)
4 4 Author: Juergen Knoedlseder (jurgen.knodlseder@irap.omp.eu)
5 5  
6 6  
... ... @@ -92,7 +92,7 @@ The file INSTALL details more about using configure. Also try
92 92 % ./configure --help.
93 93  
94 94 The `make check' command will run an extensive unit test to verify that
95   -GammaLib was correctly built. Make sure that all tests were successful.
  95 +GammaLib was correctly built. Make sure that all tests were successful.
96 96  
97 97  
98 98 Macintosh OS X Installation
... ... @@ -145,14 +145,14 @@ will generate a universal build which contains 32-bit and 64-bit code.
145 145  
146 146 BSD Installation
147 147 ================
148   -GammaLib has been tested on FreeBSD successfully. Follow the Linux
  148 +GammaLib has been tested on FreeBSD successfully. Follow the Linux
149 149 installation instructions above.
150 150  
151 151  
152 152 Solaris Installation
153 153 ====================
154 154 GammaLib compiles on Solaris and openSolaris using the GNU compiler
155   -collection. Follow the Linux installation instructions above.
  155 +collection. Follow the Linux installation instructions above.
156 156 GammaLib also compiles using the Sun Studio compiler, but due to
157 157 some unexpected handling of global variables, it is not fully
158 158 working (see "Known problems" below).
... ... @@ -175,11 +175,25 @@ extensive unit test by typing:
175 175 If everything works successfully you should see
176 176  
177 177 ===================
178   - All 18 tests passed
  178 + All 20 tests passed
179 179 ===================
180 180  
181   -at the end of the test. If no Python support was compiled in, the
182   -number of tests performed will be reduced by one.
  181 +or
  182 +
  183 +============================================================================
  184 +Testsuite summary for gammalib 0.8.0
  185 +============================================================================
  186 +# TOTAL: 20
  187 +# PASS: 20
  188 +# SKIP: 0
  189 +# XFAIL: 0
  190 +# FAIL: 0
  191 +# XPASS: 0
  192 +# ERROR: 0
  193 +============================================================================
  194 +
  195 +at the end of the test (depending on your automake version). If no Python
  196 +support was compiled in, the number of tests performed will be reduced by one.
183 197  
184 198  
185 199 Setting up your environment
... ... @@ -227,43 +241,50 @@ Documentation
227 241 =============
228 242 The doc directory (usually at /usr/local/gamma/share/doc/gammalib)
229 243 contains the most recent set of updated documentation for this release.
230   -A detailed documentation can be created using Doxygen by typing:
  244 +A detailed documentation can be created by typing:
  245 +
  246 + % make doc
231 247  
232   - % make doxygen
  248 +before installing the library. Two types of documentation exist:
  249 +* code documentation
  250 +* user documentation
233 251  
234   -before installing the library. Doxygen can be obtained from
235   -http://www.stack.nl/~dimitri/doxygen/
  252 +Code documentation is created using Doxygen. You need Doxygen on your
  253 +system to generate the code documentation. This includes man pages.
  254 +Doxygen can be obtained from http://www.stack.nl/~dimitri/doxygen/.
236 255  
237   -This is a development release and the documentation is largely, but
238   -not entirely up to date. We are working on it. Please be patient or
239   -volunteer to help.
  256 +User documentation is created using Sphinx. You need Sphinx on your
  257 +system to generate the user documentation. Sphinx can be obtained
  258 +from http://sphinx-doc.org/install.html.
240 259  
241 260  
242 261 Bug reports
243 262 ===========
244 263 To report or search for bugs, please use the GammaLib Bug Tracker at
245   -https://sourceforge.net/tracker/?group_id=282143&atid=1196795.
  264 +https://cta-redmine.irap.omp.eu/projects/gammalib. Before using the
  265 +tracker, please read
  266 +https://cta-redmine.irap.omp.eu/projects/gammalib/wiki/Submission_guidelines
246 267  
247 268  
248 269 Known problems
249 270 ==============
250 271 Python support
251 272 GammaLib comes with Python wrappers so that all classes can be
252   - directly used from Python. To compile-in Python support, GammaLib
  273 + directly used from Python. To compile-in Python support, GammaLib
253 274 needs the Python.h header file, which on many distributions is not
254 275 installed by default.
255 276 To make Python.h available, install the Python developer package
256   - in your distribution. Otherwise you will not be able to use GammaLib
  277 + in your distribution. Otherwise you will not be able to use GammaLib
257 278 from Python.
258 279  
259 280 Readline support
260 281 Many distributions do not have the readline header files and symbolic
261   - link to the shared library set up by default. The same is true for the
262   - ncurses library that is needed by readline. To properly compile-in
  282 + link to the shared library set up by default. The same is true for the
  283 + ncurses library that is needed by readline. To properly compile-in
263 284 readline support in GammaLib, make sure that the redline header files
264   - exist and that the symbolic links are set. In many distributions,
  285 + exist and that the symbolic links are set. In many distributions,
265 286 the shared redline and ncurses are located in /lib, while the symbolic
266   - links are in /usr/lib. Make sure that you have symbolic links with
  287 + links are in /usr/lib. Make sure that you have symbolic links with
267 288 names
268 289  
269 290 libreadline.so
... ... @@ -279,23 +300,23 @@ Readline support
279 300 Solaris
280 301 Although GammaLib builds on Solaris using the Sun compiler, there are
281 302 problems with global symbols in the shared library that prevent the
282   - model registry to work correctly. Furthermore, GammaLib is not able
  303 + model registry to work correctly. Furthermore, GammaLib is not able
283 304 to catch its own exceptions, which prevents the FITS interface to work
284 305 correctly.
285 306 GammaLib has however been built and tested successfully using the GNU
286 307 compiler, and this is the only build method that is currently supported.
287 308 Problems have also been encountered when compiling cfitsio versions
288   - more recent than 3.250. The problems have been reported to the cfitsio
289   - developer team, and are likely to be solved in the future. For the
  309 + more recent than 3.250. The problems have been reported to the cfitsio
  310 + developer team, and are likely to be solved in the future. For the
290 311 time being, it is recommended to use cfitsio version 3.250 on Solaris.
291 312  
292 313 OpenSolaris
293 314 On OpenSolaris, the same problems concerning the SunStudio compiler
294 315 occur as for Solaris, and also here, the GNU compiler is the recommended
295   - tool to build GammaLib. Also here, cfitsio version 3.250 is the
  316 + tool to build GammaLib. Also here, cfitsio version 3.250 is the
296 317 recommended library as more recent version feature relocation
297 318 problems. GammaLib has been tested using gcc 4.3.2 on
298   - OpenSolaris 2009.06. Make sure to create the symbolic links
  319 + OpenSolaris 2009.06. Make sure to create the symbolic links
299 320  
300 321 ln -s /usr/bin/gcc4.3.2 /usr/bin/gcc
301 322 ln -s /usr/bin/g++4.3.2 /usr/bin/g++
... ... @@ -303,12 +324,12 @@ OpenSolaris
303 324 which are not there by default to avoid excess warnings during
304 325 compilation.
305 326 For OpenSolaris 2009.06, no readline package is available, hence
306   - readline support is not readily available. Readline support can however
  327 + readline support is not readily available. Readline support can however
307 328 be enabled by directly installing the GNU ncurses and readline packages
308   - from source (http://ftp.gnu.org/gnu). This has been done successfully
309   - on OpenSolaris 2009.06 for ncurses-5.9 and readline-6.2. Make sure
  329 + from source (http://ftp.gnu.org/gnu). This has been done successfully
  330 + on OpenSolaris 2009.06 for ncurses-5.9 and readline-6.2. Make sure
310 331 to specify the `--with-shared' option when configuring ncurses, so
311   - that the shared library will be built and installed. Otherwise,
  332 + that the shared library will be built and installed. Otherwise,
312 333 relocation errors may occur during compilation of GammaLib.
313 334  
314 335  
... ...
configure.ac
... ... @@ -2,7 +2,7 @@
2 2 # Configuration for GammaLib - a versatile toolbox for high-level analysis #
3 3 # of astronomical gamma-ray data #
4 4 # ------------------------------------------------------------------------- #
5   -# Copyright (C) 2006-2013 Juergen Knoedlseder #
  5 +# Copyright (C) 2006-2014 Juergen Knoedlseder #
6 6 # ------------------------------------------------------------------------- #
7 7 # #
8 8 # This program is free software: you can redistribute it and/or modify #
... ...
dev/release_gammalib.sh
... ... @@ -65,20 +65,6 @@ fi
65 65 echo "Create LaTeX documentation"
66 66 cd $sourcedir/doc
67 67 #
68   -cd um/latex
69   -latex gammalib_um.tex
70   -dvips gammalib_um.dvi -o gammalib_um.ps
71   -ps2pdf gammalib_um.ps
72   -cd ../..
73   -mv um/latex/gammalib_um.pdf .
74   -#
75   -cd dev/coding
76   -latex gammalib_coding.tex
77   -dvips gammalib_coding.dvi -o gammalib_coding.ps
78   -ps2pdf gammalib_coding.ps
79   -cd ../..
80   -mv dev/coding/gammalib_coding.pdf .
81   -#
82 68 cd dev/inst
83 69 latex gammalib_inst.tex
84 70 dvips gammalib_inst.dvi -o gammalib_inst.ps
... ...
doc/source/user_manual/modules/model.rst
... ... @@ -89,11 +89,11 @@ Power law
89 89 The ``GModelSpectralPlaw`` class implements the power law function
90 90  
91 91 .. math::
92   - \frac{dN}{dE} = N_0 \left( \frac{E}{E_0} \right)^{\gamma}
  92 + \frac{dN}{dE} = k_0 \left( \frac{E}{E_0} \right)^{\gamma}
93 93  
94 94 where the parameters in the XML definition have the following mappings:
95 95  
96   -* :math:`N_0` = ``Prefactor``
  96 +* :math:`k_0` = ``Prefactor``
97 97 * :math:`\gamma` = ``Index``
98 98 * :math:`E_0` = ``Scale``
99 99  
... ... @@ -145,12 +145,12 @@ Exponentially cut-off power law
145 145 The ``GModelSpectralExpPlaw`` class implements the exponentially cut-off power law function
146 146  
147 147 .. math::
148   - \frac{dN}{dE} = N_0 \left( \frac{E}{E_0} \right)^{\gamma}
  148 + \frac{dN}{dE} = k_0 \left( \frac{E}{E_0} \right)^{\gamma}
149 149 \exp \left( \frac{-E}{\tt E_{\rm cut}} \right)
150 150  
151 151 where the parameters in the XML definition have the following mappings:
152 152  
153   -* :math:`N_0` = ``Prefactor``
  153 +* :math:`k_0` = ``Prefactor``
154 154 * :math:`\gamma` = ``Index``
155 155 * :math:`E_0` = ``Scale``
156 156 * :math:`E_{\rm cut}` = ``Cutoff``
... ... @@ -174,7 +174,7 @@ The ``GModelSpectralBrokenPlaw`` class implements the broken power law function
174 174  
175 175 .. math::
176 176  
177   - \frac{dN}{dE} = N_0 \times \left \{
  177 + \frac{dN}{dE} = k_0 \times \left \{
178 178 \begin{eqnarray}
179 179 \left( \frac{E}{E_b} \right)^{\gamma_1} & {\rm if\,\,} E < E_b \\
180 180 \left( \frac{E}{E_b} \right)^{\gamma_2} & {\rm otherwise}
... ... @@ -183,7 +183,7 @@ The ``GModelSpectralBrokenPlaw`` class implements the broken power law function
183 183  
184 184 where the parameters in the XML definition have the following mappings:
185 185  
186   -* :math:`N_0` = ``Prefactor``
  186 +* :math:`k_0` = ``Prefactor``
187 187 * :math:`\gamma_1` = ``Index1``
188 188 * :math:`\gamma_2` = ``Index2``
189 189 * :math:`E_b` = ``BreakValue``
... ... @@ -199,6 +199,33 @@ The XML format for specifying a broken power law is:
199 199 <parameter name="Index2" scale="-1" value="2.70" min="0.01" max="1000.0" free="1"/>
200 200 </spectrum>
201 201  
  202 +
  203 +Gaussian
  204 +^^^^^^^^
  205 +
  206 +The ``GModelSpectralGauss`` class implements the gaussian function
  207 +
  208 +.. math::
  209 + \frac{dN}{dE} = \frac{N_0}{\sqrt{2\pi}\sigma}
  210 + \exp \left( \frac{-(E-\bar{E})^2}{2 \sigma^2} \right)
  211 +
  212 +where the parameters in the XML definition have the following mappings:
  213 +
  214 +* :math:`N_0` = ``Normalization``
  215 +* :math:`\bar{E}` = ``Mean``
  216 +* :math:`\sigma` = ``Sigma``
  217 +
  218 +The XML format for specifying a Gaussian is:
  219 +
  220 +.. code-block:: xml
  221 +
  222 + <spectrum type="Gaussian">
  223 + <parameter name="Normalization" scale="1e-10" value="1.0" min="1e-07" max="1000.0" free="1"/>
  224 + <parameter name="Mean" scale="1e6" value="5.0" min="0.01" max="100.0" free="1"/>
  225 + <parameter name="Sigma" scale="1e6" value="1.0" min="0.01" max="100.0" free="1"/>
  226 + </spectrum>
  227 +
  228 +
202 229 Node function
203 230 ^^^^^^^^^^^^^
204 231  
... ... @@ -231,11 +258,11 @@ Log parabola
231 258 The ``GModelSpectralLogParabola`` class implements the log parabola function
232 259  
233 260 .. math::
234   - \frac{dN}{dE} = N_0 \left( \frac{E}{E_0} \right)^{\gamma+\eta \ln(E/E_0)}
  261 + \frac{dN}{dE} = k_0 \left( \frac{E}{E_0} \right)^{\gamma+\eta \ln(E/E_0)}
235 262  
236 263 where the parameters in the XML definition have the following mappings:
237 264  
238   -* :math:`N_0` = ``Prefactor``
  265 +* :math:`k_0` = ``Prefactor``
239 266 * :math:`\gamma` = ``Index``
240 267 * :math:`\eta` = ``Curvature``
241 268 * :math:`E_0` = ``Scale``
... ...
include/GModelSpectralGauss.hpp
... ... @@ -182,7 +182,7 @@ GEnergy GModelSpectralGauss::mean(void) const
182 182 /***********************************************************************//**
183 183 * @brief Set mean energy
184 184 *
185   - * @param[in] Mean energy.
  185 + * @param[in] mean Mean energy.
186 186 ***************************************************************************/
187 187 inline
188 188 void GModelSpectralGauss::mean(const GEnergy& mean)
... ... @@ -208,7 +208,7 @@ GEnergy GModelSpectralGauss::sigma(void) const
208 208 /***********************************************************************//**
209 209 * @brief Set energy width
210 210 *
211   - * @param[in] Energy width
  211 + * @param[in] sigma Energy width.
212 212 ***************************************************************************/
213 213 inline
214 214 void GModelSpectralGauss::sigma(const GEnergy& sigma)
... ...
inst/com/test/test_COM.cpp
1 1 /***************************************************************************
2 2 * test_COM.cpp - test COM classes *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2012-2013 by Juergen Knoedlseder *
  4 + * copyright (C) 2012-2014 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -580,7 +580,7 @@ void TestGCOMOptimize::test_binned_optimizer(void)
580 580 47, 0,
581 581 29.9617, 0.377506,
582 582 49, 0,
583   - 27.9993, 0.372603};
  583 + 27.9992, 0.372603};
584 584 test_try("Perform LM optimization");
585 585 try {
586 586 GOptimizerLM opt;
... ...
inst/cta/test/test_CTA.cpp
1 1 /***************************************************************************
2 2 * test_CTA.cpp - Test CTA classes *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2010-2013 by Juergen Knoedlseder *
  4 + * copyright (C) 2010-2014 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -335,7 +335,8 @@ void TestGCTAResponse::test_response_irf_diffuse(void)
335 335 {
336 336 // Set reference value
337 337 //double ref = 13803.800313356;
338   - const double ref = 13803.5186374;
  338 + //const double ref = 13803.5186374;
  339 + const double ref = 13803.6932774; // After GWcs::solidangle improvement
339 340  
340 341 // Set parameters
341 342 double src_ra = 201.3651;
... ... @@ -412,7 +413,8 @@ void TestGCTAResponse::test_response_npred_diffuse(void)
412 413 {
413 414 // Set reference value
414 415 //double ref = 11212.26274; // npred_spec precision of 1e-6
415   - const double ref = 11212.437464; // npred_spec precision of 1e-5
  416 + //const double ref = 11212.437464; // npred_spec precision of 1e-5
  417 + const double ref = 11212.4370702; // After GWcs::solidangle improvement
416 418  
417 419 // Set parameters
418 420 double src_ra = 201.3651;
... ... @@ -766,10 +768,10 @@ void TestGCTAOptimize::test_binned_optimizer(void)
766 768 double fit_results[] = {83.6331, 0,
767 769 22.0145, 0,
768 770 5.616410411e-16, 1.904730785e-17,
769   - -2.481781246, -0.02580905077,
  771 + -2.48178, -0.02580905077,
770 772 300000, 0,
771 773 1, 0,
772   - 2.933677595, 0.06639644824,
  774 + 2.93368, 0.06639644824,
773 775 6.550723074e-05, 1.945714239e-06,
774 776 -1.833781187, -0.0160819,
775 777 1000000, 0,
... ...
src/fits/GFits.cpp
... ... @@ -1213,19 +1213,32 @@ void GFits::saveto(const std::string&amp; filename, const bool&amp; clobber)
1213 1213 // Expand environment variables
1214 1214 std::string fname = gammalib::expand_env(filename);
1215 1215  
  1216 + // Create gzipped file name version
  1217 + std::string gzfname = fname + ".gz";
  1218 +
1216 1219 // Debug header
1217 1220 #if defined(G_DEBUG)
1218 1221 std::cout << "GFits::saveto(\"" << fname << "\", " << clobber << ")"
1219 1222 << " (size=" << size() << ") -->" << std::endl;
1220 1223 #endif
1221 1224  
1222   - // If overwriting has been specified then remove any existing file ...
  1225 + // If overwriting has been specified then remove any existing file. We
  1226 + // consider here also the possibility that the file is gzipped, but
  1227 + // the file name does not contain the .gz extension.
1223 1228 if (clobber) {
1224   - std::remove(fname.c_str());
  1229 + if (gammalib::file_exists(fname)) {
  1230 + std::remove(fname.c_str());
  1231 + }
  1232 + else {
  1233 + if (gammalib::file_exists(gzfname)) {
  1234 + std::remove(gzfname.c_str());
  1235 + }
  1236 + }
1225 1237 }
1226 1238  
1227   - // ... otherwise, if file exists then throw an exception
1228   - else if (gammalib::file_exists(fname)) {
  1239 + // Otherwise, if file exists then throw an exception
  1240 + else if (gammalib::file_exists(fname) ||
  1241 + gammalib::file_exists(gzfname)) {
1229 1242 throw GException::fits_file_exist(G_SAVETO, fname);
1230 1243 }
1231 1244  
... ... @@ -1393,7 +1406,7 @@ void GFits::free_members(void)
1393 1406 // If FITS file has been opened then close it now
1394 1407 if (m_fitsfile != NULL) {
1395 1408  
1396   - // If file has been created but not yet save then delete the file
  1409 + // If file has been created but not yet saved then delete the file
1397 1410 // now. We do not worry about the status in this case.
1398 1411 if (m_created) {
1399 1412 int status = 0;
... ...
src/fits/GFitsHDU.cpp
1 1 /***************************************************************************
2 2 * GFitsHDU.cpp - FITS HDU handling class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2008-2013 by Juergen Knoedlseder *
  4 + * copyright (C) 2008-2014 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -29,6 +29,7 @@
29 29 #include <config.h>
30 30 #endif
31 31 #include <iostream>
  32 +#include <cstdlib>
32 33 #include "GException.hpp"
33 34 #include "GTools.hpp"
34 35 #include "GFitsCfitsio.hpp"
... ... @@ -511,10 +512,3 @@ void GFitsHDU::free_members(void)
511 512 // Return
512 513 return;
513 514 }
514   -
515   -
516   -/*==========================================================================
517   - = =
518   - = Friends =
519   - = =
520   - ==========================================================================*/
... ...
src/sky/GWcs.cpp
... ... @@ -56,6 +56,7 @@
56 56  
57 57 /* __ Coding definitions _________________________________________________ */
58 58 //#define G_LIN_MATINV_FORCE_PC // Force PC usage
  59 +#define G_SOLIDANGLE_OPTION 2 // 1=sin/cos, 2=tan, 3=vectors
59 60  
60 61 /* __ Debug definitions __________________________________________________ */
61 62 //#define G_DIR2XY_DEBUG // Debug dir2xy
... ... @@ -425,34 +426,213 @@ void GWcs::write(GFitsHDU&amp; hdu) const
425 426 *
426 427 * @param[in] pixel Pixel index (x,y)
427 428 *
428   - * Estimate solid angles of pixel by computing the coordinates in the 4 pixel
429   - * corners. The surface is computed using a cartesian approximation:
430   - * a
431   - * 1-----5-----2 a+b
432   - * / | h \ where A = h ---
433   - * 4-------6-------3 2
434   - * b
435   - * This is a brute force technique that works sufficiently well for non-
436   - * rotated sky maps. Something more intelligent should be implemented in
437   - * the future.
  429 + * Estimates solid angles of pixels using the Girard equation for excess
  430 + * area - see: http://mathworld.wolfram.com/SphericalPolygon.html
  431 + *
  432 + *
  433 + * Below, the definiton of the pixel cornes and sides are shown as used
  434 + * within the code.
  435 + *
  436 + * a12
  437 + * 1---------2
  438 + * |\ /|
  439 + * | \a13 / |
  440 + * | \ / |
  441 + * | \ / |
  442 + * a14| X |a23
  443 + * | / \ |
  444 + * | / \ |
  445 + * | /a24 \ |
  446 + * |/ \|
  447 + * 4---------3
  448 + * a34
  449 + *
438 450 ***************************************************************************/
439 451 double GWcs::solidangle(const GSkyPixel& pixel) const
440 452 {
441   - // Get the sky directions of the 6 points
  453 + // Get the sky directions of the 4 points
442 454 GSkyDir dir1 = pix2dir(GSkyPixel(pixel.x()-0.5, pixel.y()-0.5));
443 455 GSkyDir dir2 = pix2dir(GSkyPixel(pixel.x()+0.5, pixel.y()-0.5));
444 456 GSkyDir dir3 = pix2dir(GSkyPixel(pixel.x()+0.5, pixel.y()+0.5));
445 457 GSkyDir dir4 = pix2dir(GSkyPixel(pixel.x()-0.5, pixel.y()+0.5));
446   - GSkyDir dir5 = pix2dir(GSkyPixel(pixel.x(), pixel.y()-0.5));
447   - GSkyDir dir6 = pix2dir(GSkyPixel(pixel.x(), pixel.y()+0.5));
448 458  
449   - // Compute distances between sky directions
450   - double a = dir1.dist(dir2);
451   - double b = dir3.dist(dir4);
452   - double h = dir5.dist(dir6);
  459 + // Compile option 1: Use triginometric function
  460 + #if G_SOLIDANGLE_OPTION == 1
  461 +
  462 + // Initialise solid angle
  463 + double solidangle = 0.0;
  464 +
  465 + // Compute angular distances between pixel corners
  466 + double a12 = dir1.dist(dir2);
  467 + double a14 = dir1.dist(dir4);
  468 + double a23 = dir2.dist(dir3);
  469 + double a34 = dir3.dist(dir4);
  470 +
  471 + // Special case: a12 or a14 is zero, then pixel is a triangle composed
  472 + // of [2,3,4]
  473 + if (a12 <= 0.0 || a14 <= 0.0) {
  474 +
  475 + // Compute diagonals
  476 + double a24 = dir2.dist(dir4);
  477 +
  478 + // Compute sines
  479 + double sin_a23 = std::sin(a23);
  480 + double sin_a24 = std::sin(a24);
  481 + double sin_a34 = std::sin(a34);
  482 +
  483 + // Compute cosines
  484 + double cos_a23 = std::cos(a23);
  485 + double cos_a24 = std::cos(a24);
  486 + double cos_a34 = std::cos(a34);
  487 +
  488 + // Compute angles
  489 + double angle2 = gammalib::acos((cos_a34-cos_a24*cos_a23)/(sin_a24*sin_a23));
  490 + double angle3 = gammalib::acos((cos_a24-cos_a34*cos_a23)/(sin_a34*sin_a23));
  491 + double angle4 = gammalib::acos((cos_a23-cos_a24*cos_a34)/(sin_a24*sin_a34));
  492 +
  493 + // Compute excess area to determine solid angle
  494 + solidangle = (angle2 + angle3 + angle4) - gammalib::pi;
  495 +
  496 + }
  497 +
  498 + // Special case: a23 or a 34 is zero, then pixel is a triangle composed
  499 + // of [1,2,4]
  500 + else if (a23 <= 0.0 || a34 <= 0.0) {
  501 +
  502 + // Compute diagonals
  503 + double a24 = dir2.dist(dir4);
453 504  
454   - // Compute solid angle
455   - double solidangle = 0.5*(h*(a+b));
  505 + // Compute sines
  506 + double sin_a12 = std::sin(a12);
  507 + double sin_a14 = std::sin(a14);
  508 + double sin_a24 = std::sin(a24);
  509 +
  510 + // Compute cosines
  511 + double cos_a12 = std::cos(a12);
  512 + double cos_a14 = std::cos(a14);
  513 + double cos_a24 = std::cos(a24);
  514 +
  515 + // Compute angles
  516 + double angle1 = gammalib::acos((cos_a24-cos_a12*cos_a14)/(sin_a12*sin_a14));
  517 + double angle2 = gammalib::acos((cos_a14-cos_a12*cos_a24)/(sin_a12*sin_a24));
  518 + double angle4 = gammalib::acos((cos_a12-cos_a14*cos_a24)/(sin_a14*sin_a24));
  519 +
  520 + // Compute excess area to determine solid angle
  521 + solidangle = (angle1 + angle2 + angle4) - gammalib::pi;
  522 +
  523 + }
  524 +
  525 + // Otherwise we have a polygon
  526 + else {
  527 +
  528 + // Compute diagonals
  529 + double a13 = dir1.dist(dir3);
  530 + double a24 = dir2.dist(dir4);
  531 +
  532 + // Compute sines
  533 + double sin_a12 = std::sin(a12);
  534 + double sin_a14 = std::sin(a14);
  535 + double sin_a23 = std::sin(a23);
  536 + double sin_a34 = std::sin(a34);
  537 +
  538 + // Compute cosines
  539 + double cos_a12 = std::cos(a12);
  540 + double cos_a13 = std::cos(a13);
  541 + double cos_a14 = std::cos(a14);
  542 + double cos_a23 = std::cos(a23);
  543 + double cos_a24 = std::cos(a24);
  544 + double cos_a34 = std::cos(a34);
  545 +
  546 + // Compute angles
  547 + double angle1 = std::acos((cos_a13-cos_a34*cos_a14)/(sin_a34*sin_a14));
  548 + double angle2 = std::acos((cos_a24-cos_a23*cos_a34)/(sin_a23*sin_a34));
  549 + double angle3 = std::acos((cos_a13-cos_a12*cos_a23)/(sin_a12*sin_a23));
  550 + double angle4 = std::acos((cos_a24-cos_a14*cos_a12)/(sin_a14*sin_a12));
  551 +
  552 + // Use Girard equation for excess area to determine solid angle
  553 + solidangle = (angle1 + angle2 + angle3 + angle4) - gammalib::twopi;
  554 +
  555 + } // endif: we had a polynom
  556 +
  557 + // Compile option 2: Use Huilier's theorem
  558 + #elif G_SOLIDANGLE_OPTION == 2
  559 +
  560 + // Initialise solid angle
  561 + double solidangle = 0.0;
  562 +
  563 + // Compute angular distances between pixel corners
  564 + double a12 = dir1.dist(dir2);
  565 + double a14 = dir1.dist(dir4);
  566 + double a23 = dir2.dist(dir3);
  567 + double a24 = dir2.dist(dir4);
  568 + double a34 = dir3.dist(dir4);
  569 +
  570 + // Special case: a12 or a14 is zero, then pixel is a triangle composed
  571 + // of [2,3,4]
  572 + if (a12 <= 0.0 || a14 <= 0.0) {
  573 + double s = 0.5 * (a23 + a34 + a24);
  574 + solidangle = 4.0 * std::atan(std::sqrt(std::tan(0.5*s) *
  575 + std::tan(0.5*(s-a23)) *
  576 + std::tan(0.5*(s-a34)) *
  577 + std::tan(0.5*(s-a24))));
  578 + }
  579 +
  580 + // Special case: a23 or a 34 is zero, then pixel is a triangle composed
  581 + // of [1,2,4]
  582 + else if (a23 <= 0.0 || a34 <= 0.0) {
  583 + double s = 0.5 * (a12 + a24 + a14);
  584 + solidangle = 4.0 * std::atan(std::sqrt(std::tan(0.5*s) *
  585 + std::tan(0.5*(s-a12)) *
  586 + std::tan(0.5*(s-a24)) *
  587 + std::tan(0.5*(s-a14))));
  588 + }
  589 +
  590 + // Otherwise we have a polygon
  591 + else {
  592 +
  593 + // Triangle 1 [1,2,4]
  594 + double s1 = 0.5 * (a12 + a24 + a14);
  595 + double excess1 = std::atan(std::sqrt(std::tan(0.5*s1) *
  596 + std::tan(0.5*(s1-a12)) *
  597 + std::tan(0.5*(s1-a24)) *
  598 + std::tan(0.5*(s1-a14))));
  599 +
  600 + // Triangle 2 [2,3,4]
  601 + double s2 = 0.5 * (a23 + a34 + a24);
  602 + double excess2 = std::atan(std::sqrt(std::tan(0.5*s2) *
  603 + std::tan(0.5*(s2-a23)) *
  604 + std::tan(0.5*(s2-a34)) *
  605 + std::tan(0.5*(s2-a24))));
  606 +
  607 + // Determine solid angle
  608 + solidangle = 4.0 * (excess1 + excess2);
  609 +
  610 + } // endif: we had a polynom
  611 +
  612 + // Compile option 3: Use vectors
  613 + #else
  614 +
  615 + // Get vectors to pixel corners
  616 + GVector vec1 = dir1.celvector();
  617 + GVector vec2 = dir2.celvector();
  618 + GVector vec3 = dir3.celvector();
  619 + GVector vec4 = dir4.celvector();
  620 +
  621 + // Compute inner angles of pixel corners
  622 + double angle1 = gammalib::acos(cross(vec2, (cross(vec1, vec2))) *
  623 + cross(vec2, (cross(vec3, vec2))));
  624 + double angle2 = gammalib::acos(cross(vec3, (cross(vec2, vec3))) *
  625 + cross(vec3, (cross(vec4, vec3))));
  626 + double angle3 = gammalib::acos(cross(vec4, (cross(vec3, vec4))) *
  627 + cross(vec4, (cross(vec1, vec4))));
  628 + double angle4 = gammalib::acos(cross(vec1, (cross(vec4, vec1))) *
  629 + cross(vec1, (cross(vec2, vec1))));
  630 +
  631 + // Use Girard equation for excess area to determine solid angle
  632 + double solidangle = gammalib::deg2rad * gammalib::deg2rad +
  633 + (angle1 + angle2 + angle3 + angle4) -
  634 + gammalib::twopi;
  635 + #endif
456 636  
457 637 // Return solid angle
458 638 return solidangle;
... ...