Commit 302c8f9374e0991ba075dc0f716f9ed4e7df7b3a
Merge branch 'issue_1017' into issue_1017_jk
Conflicts: src/sky/GWcs.cpp
Showing
3 changed files
with
146 additions
and
38 deletions
ChangeLog
| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | Put likelihood computation in GObservation class |
| 24 | 24 | Add broken power law spectral model |
| 25 | 25 | Add Gaussian spectral model |
| 26 | + Implement exact sky map pixel solid angle computation | |
| 26 | 27 | Rename the following classes: |
| 27 | 28 | - GWcs => GSkyProjection |
| 28 | 29 | - 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 | |
| ... | ... | @@ -560,7 +560,12 @@ The GSkyPixel class now supports 1D and 2D pixelisations, allowing |
| 560 | 560 | a more generic usage of the class. Integer and double precision |
| 561 | 561 | values can be assigned from and to GSkyPixel for 1D pixelisations. |
| 562 | 562 | |
| 563 | -The GWcsAIT class has been added for Aitoff-Hammer projections. | |
| 563 | +The GWcsAIT class has been added for Aitoff projections. | |
| 564 | + | |
| 565 | +The solid angle of sky map pixels are now computed using the spherical | |
| 566 | +excess. This provides accurate solid angles even in case that the | |
| 567 | +pixels are highly distorted, for example at the poles of the Aitoff | |
| 568 | +projections. | |
| 564 | 569 | |
| 565 | 570 | |
| 566 | 571 | 13. Support module | ... | ... |
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,7 +426,27 @@ void GWcs::write(GFitsHDU& hdu) const |
| 425 | 426 | * |
| 426 | 427 | * @param[in] pixel Pixel index (x,y) |
| 427 | 428 | * |
| 428 | -TODO:: UPDATE THIS DOCSTRING (+link to wikipedia) | |
| 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 | + * | |
| 429 | 450 | ***************************************************************************/ |
| 430 | 451 | double GWcs::solidangle(const GSkyPixel& pixel) const |
| 431 | 452 | { |
| ... | ... | @@ -435,47 +456,128 @@ double GWcs::solidangle(const GSkyPixel& pixel) const |
| 435 | 456 | GSkyDir dir3 = pix2dir(GSkyPixel(pixel.x()+0.5, pixel.y()+0.5)); |
| 436 | 457 | GSkyDir dir4 = pix2dir(GSkyPixel(pixel.x()-0.5, pixel.y()+0.5)); |
| 437 | 458 | |
| 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 | + | |
| 438 | 465 | // Compute angular distances between pixel corners |
| 439 | 466 | double a12 = dir1.dist(dir2); |
| 440 | - double a13 = dir1.dist(dir3); | |
| 441 | 467 | double a14 = dir1.dist(dir4); |
| 442 | 468 | double a23 = dir2.dist(dir3); |
| 443 | - double a24 = dir2.dist(dir4); | |
| 444 | 469 | double a34 = dir3.dist(dir4); |
| 445 | 470 | |
| 446 | - // Angle 1 | |
| 447 | - double a = a13; | |
| 448 | - double b = a34; | |
| 449 | - double c = a14; | |
| 450 | - double angle1 = std::acos((std::cos(a) - std::cos(b)*std::cos(c))/(std::sin(b)*std::sin(c))); | |
| 451 | - | |
| 452 | - // Angle 2 | |
| 453 | - a = a24; | |
| 454 | - b = a23; | |
| 455 | - c = a34; | |
| 456 | - double angle2 = std::acos((std::cos(a) - std::cos(b)*std::cos(c))/(std::sin(b)*std::sin(c))); | |
| 457 | - | |
| 458 | - // Angle 3 | |
| 459 | - a = a13; | |
| 460 | - b = a12; | |
| 461 | - c = a23; | |
| 462 | - double angle3 = std::acos((std::cos(a) - std::cos(b)*std::cos(c))/(std::sin(b)*std::sin(c))); | |
| 463 | - | |
| 464 | - // Angle 4 | |
| 465 | - a = a24; | |
| 466 | - b = a14; | |
| 467 | - c = a12; | |
| 468 | - double angle4 = std::acos((std::cos(a) - std::cos(b)*std::cos(c))/(std::sin(b)*std::sin(c))); | |
| 469 | - | |
| 470 | - /* | |
| 471 | - std::cout << angle1 << " "; | |
| 472 | - std::cout << angle2 << " "; | |
| 473 | - std::cout << angle3 << " "; | |
| 474 | - std::cout << angle4 << " " << std::endl; | |
| 475 | - */ | |
| 476 | - | |
| 477 | - // http://mathworld.wolfram.com/SphericalPolygon.html | |
| 478 | - double solidangle = (angle1 + angle2 + angle3 + angle4) - (2.0 * gammalib::pi); | |
| 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 = 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 | |
| 479 | 581 | |
| 480 | 582 | // Return solid angle |
| 481 | 583 | return solidangle; | ... | ... |