Commit 65300dd7c766fdfd5fa44e962f4074d60f731d6e
Merge branch 'issue_1017_jk' into integration
Conflicts: ChangeLog
Showing
5 changed files
with
161 additions
and
28 deletions
ChangeLog
| ... | ... | @@ -24,6 +24,7 @@ |
| 24 | 24 | Add broken power law spectral model |
| 25 | 25 | Add Gaussian spectral model |
| 26 | 26 | Update parameter files if necessary |
| 27 | + Implement exact sky map pixel solid angle computation | |
| 27 | 28 | Rename the following classes: |
| 28 | 29 | - GWcs => GSkyProjection |
| 29 | 30 | - GWcslib => GWcs | ... | ... |
NEWS
| 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 | |
| ... | ... | @@ -565,7 +565,12 @@ The GSkyPixel class now supports 1D and 2D pixelisations, allowing |
| 565 | 565 | a more generic usage of the class. Integer and double precision |
| 566 | 566 | values can be assigned from and to GSkyPixel for 1D pixelisations. |
| 567 | 567 | |
| 568 | -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. | |
| 569 | 574 | |
| 570 | 575 | |
| 571 | 576 | 13. Support module | ... | ... |
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 = 13796.8200974; // 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 = 11206.8536502; // 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.47925, -0.02580905077, | |
| 770 | 772 | 300000, 0, |
| 771 | 773 | 1, 0, |
| 772 | - 2.933677595, 0.06639644824, | |
| 774 | + 2.93353, 0.06639644824, | |
| 773 | 775 | 6.550723074e-05, 1.945714239e-06, |
| 774 | 776 | -1.833781187, -0.0160819, |
| 775 | 777 | 1000000, 0, | ... | ... |
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_USE_TRIGO_FOR_SOLIDANGLE // Use trigonometric functions | |
| 59 | 60 | |
| 60 | 61 | /* __ Debug definitions __________________________________________________ */ |
| 61 | 62 | //#define G_DIR2XY_DEBUG // Debug dir2xy |
| ... | ... | @@ -425,34 +426,158 @@ void GWcs::write(GFitsHDU& 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 defined(G_USE_TRIGO_FOR_SOLIDANGLE) | |
| 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) { | |
| 453 | 474 | |
| 454 | - // Compute solid angle | |
| 455 | - double solidangle = 0.5*(h*(a+b)); | |
| 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 = std::acos((cos_a34-cos_a24*cos_a23)/(sin_a24*sin_a23)); | |
| 490 | + double angle3 = std::acos((cos_a24-cos_a34*cos_a23)/(sin_a34*sin_a23)); | |
| 491 | + double angle4 = std::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); | |
| 504 | + | |
| 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 = std::acos((cos_a24-cos_a12*cos_a14)/(sin_a12*sin_a14)); | |
| 517 | + double angle2 = std::acos((cos_a14-cos_a12*cos_a24)/(sin_a12*sin_a24)); | |
| 518 | + double angle4 = std::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 vectors | |
| 558 | + #else | |
| 559 | + | |
| 560 | + // Get vectors to pixel corners | |
| 561 | + GVector vec1 = dir1.celvector(); | |
| 562 | + GVector vec2 = dir2.celvector(); | |
| 563 | + GVector vec3 = dir3.celvector(); | |
| 564 | + GVector vec4 = dir4.celvector(); | |
| 565 | + | |
| 566 | + // Compute inner angles of pixel corners | |
| 567 | + double angle1 = gammalib::acos(cross(vec2, (cross(vec1, vec2))) * | |
| 568 | + cross(vec2, (cross(vec3, vec2)))); | |
| 569 | + double angle2 = gammalib::acos(cross(vec3, (cross(vec2, vec3))) * | |
| 570 | + cross(vec3, (cross(vec4, vec3)))); | |
| 571 | + double angle3 = gammalib::acos(cross(vec4, (cross(vec3, vec4))) * | |
| 572 | + cross(vec4, (cross(vec1, vec4)))); | |
| 573 | + double angle4 = gammalib::acos(cross(vec1, (cross(vec4, vec1))) * | |
| 574 | + cross(vec1, (cross(vec2, vec1)))); | |
| 575 | + | |
| 576 | + // Use Girard equation for excess area to determine solid angle | |
| 577 | + double solidangle = gammalib::deg2rad * gammalib::deg2rad + | |
| 578 | + (angle1 + angle2 + angle3 + angle4) - | |
| 579 | + gammalib::twopi; | |
| 580 | + #endif | |
| 456 | 581 | |
| 457 | 582 | // Return solid angle |
| 458 | 583 | return solidangle; | ... | ... |