GammaLib 2.0.0
Loading...
Searching...
No Matches
GWcsMOL.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GWcsMOL.cpp - Mollweide's projection class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2015-2021 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GWcsMOL.cpp
23 * @brief Mollweide's projection class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GException.hpp"
32#include "GMath.hpp"
33#include "GTools.hpp"
34#include "GWcsMOL.hpp"
35#include "GWcsRegistry.hpp"
36
37/* __ Method name definitions ____________________________________________ */
38#define G_PRJ_X2S "GWcsMOL::prj_x2s(int, int, int, int, double*, double*,"\
39 " double*, double*, int*)"
40#define G_PRJ_S2X "GWcsMOL::prj_s2x(int, int, int, int, double*, double*,"\
41 " double*, double*, int*)"
42
43/* __ Macros _____________________________________________________________ */
44#define copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X))
45
46/* __ Coding definitions _________________________________________________ */
47
48/* __ Debug definitions __________________________________________________ */
49//#define G_DEBUG_PRJ //!< Debug GWcsMOL::prj_x2s
50
51/* __ Local prototypes ___________________________________________________ */
52
53/* __ Constants __________________________________________________________ */
54
55/* __ Globals ____________________________________________________________ */
57const GWcsRegistry g_wcs_mol_registry(&g_wcs_mol_seed);
58
59
60/*==========================================================================
61 = =
62 = Constructors/destructors =
63 = =
64 ==========================================================================*/
65
66/***********************************************************************//**
67 * @brief Void constructor
68 ***************************************************************************/
70{
71 // Initialise class members
73
74 // Return
75 return;
76}
77
78
79/***********************************************************************//**
80 * @brief Constructor
81 *
82 * @param[in] coords Coordinate system.
83 * @param[in] crval1 X value of reference pixel.
84 * @param[in] crval2 Y value of reference pixel.
85 * @param[in] crpix1 X index of reference pixel (starting from 1).
86 * @param[in] crpix2 Y index of reference pixel (starting from 1).
87 * @param[in] cdelt1 Increment in x direction at reference pixel [deg].
88 * @param[in] cdelt2 Increment in y direction at reference pixel [deg].
89 ***************************************************************************/
90GWcsMOL::GWcsMOL(const std::string& coords,
91 const double& crval1, const double& crval2,
92 const double& crpix1, const double& crpix2,
93 const double& cdelt1, const double& cdelt2) :
94 GWcs(coords, crval1, crval2, crpix1, crpix2, cdelt1, cdelt2)
95
96{
97 // Initialise class members
99
100 // Setup WCS derived parameters
101 wcs_set();
102
103 // Return
104 return;
105}
106
107
108/***********************************************************************//**
109 * @brief Copy constructor
110 *
111 * @param[in] wcs World Coordinate System.
112 ***************************************************************************/
113GWcsMOL::GWcsMOL(const GWcsMOL& wcs) : GWcs(wcs)
114{
115 // Initialise class members for clean destruction
116 init_members();
117
118 // Copy members
119 copy_members(wcs);
120
121 // Return
122 return;
123}
124
125
126/***********************************************************************//**
127 * @brief Destructor
128 ***************************************************************************/
130{
131 // Free members
132 free_members();
133
134 // Return
135 return;
136}
137
138
139/*==========================================================================
140 = =
141 = Operators =
142 = =
143 ==========================================================================*/
144
145/***********************************************************************//**
146 * @brief Assignment operator
147 *
148 * @param[in] wcs World Coordinate System.
149 * @return World Coordinate System.
150 ***************************************************************************/
152{
153 // Execute only if object is not identical
154 if (this != &wcs) {
155
156 // Copy base class members
157 this->GWcs::operator=(wcs);
158
159 // Free members
160 free_members();
161
162 // Initialise private members for clean destruction
163 init_members();
164
165 // Copy members
166 copy_members(wcs);
167
168 } // endif: object was not identical
169
170 // Return this object
171 return *this;
172}
173
174
175/*==========================================================================
176 = =
177 = Public methods =
178 = =
179 ==========================================================================*/
180
181/***********************************************************************//**
182 * @brief Clear instance
183 *
184 * This method properly resets the object to an initial state.
185 ***************************************************************************/
187{
188 // Free class members (base and derived classes, derived class first)
189 free_members();
190 this->GWcs::free_members();
192
193 // Initialise members
195 this->GWcs::init_members();
196 init_members();
197
198 // Return
199 return;
200}
201
202
203/***********************************************************************//**
204 * @brief Clone instance
205 *
206 * @return Pointer to deep copy of Mollweide projection.
207 ***************************************************************************/
209{
210 return new GWcsMOL(*this);
211}
212
213
214
215/***********************************************************************//**
216 * @brief Print WCS information
217 *
218 * @param[in] chatter Chattiness (defaults to NORMAL).
219 * @return String containing WCS information.
220 ***************************************************************************/
221std::string GWcsMOL::print(const GChatter& chatter) const
222{
223 // Initialise result string
224 std::string result;
225
226 // Continue only if chatter is not silent
227 if (chatter != SILENT) {
228
229 // Append header
230 result.append("=== GWcsMOL ===");
231
232 // Append information
233 result.append(wcs_print(chatter));
234
235 } // endif: chatter was not silent
236
237 // Return result
238 return result;
239}
240
241
242/*==========================================================================
243 = =
244 = Private methods =
245 = =
246 ==========================================================================*/
247
248/***********************************************************************//**
249 * @brief Initialise class members
250 ***************************************************************************/
252{
253 // Return
254 return;
255}
256
257
258/***********************************************************************//**
259 * @brief Copy class members
260 *
261 * @param[in] wcs World Coordinate System.
262 ***************************************************************************/
264{
265 // Return
266 return;
267}
268
269
270/***********************************************************************//**
271 * @brief Delete class members
272 ***************************************************************************/
274{
275 // Return
276 return;
277}
278
279
280/***********************************************************************//**
281 * @brief Setup of projection
282 *
283 * This method sets up the projection information. The method has been
284 * adapted from the wcslib function prj.c::molset (version 4.20).
285 *
286 * Given and/or returned:
287 * m_r0 Reset to 180/pi if 0.
288 * m_phi0 Reset to 0.0 if undefined.
289 * m_theta0 Reset to 0.0 if undefined.
290 *
291 * Returned:
292 * m_x0 Fiducial offset in x.
293 * m_y0 Fiducial offset in y.
294 * m_w[0] sqrt(2)*r0
295 * m_w[1] sqrt(2)*r0/90
296 * m_w[2] 1/(sqrt(2)*r0)
297 * m_w[3] 90/r0
298 * m_w[4] 2/pi
299 ***************************************************************************/
300void GWcsMOL::prj_set(void) const
301{
302 // Signal that projection has been set (needs to be done before calling
303 // the prj_off() method to avoid an endless loop)
304 m_prjset = true;
305
306 // Initialise projection parameters
307 m_w.assign(5, 0.0);
308
309 // Set undefined parameters
310 if (m_r0 == 0.0) {
312 }
313
314 // Precompute
316 m_w[1] = m_w[0]/90.0;
317 m_w[2] = 1.0/m_w[0];
318 m_w[3] = 90.0/m_r0;
319 m_w[4] = 2.0/gammalib::pi;
320
321 // Compute fiducial offset
322 prj_off(0.0, 0.0);
323
324 // Return
325 return;
326}
327
328
329/***********************************************************************//**
330 * @brief Pixel-to-spherical deprojection
331 *
332 * @param[in] nx X vector length.
333 * @param[in] ny Y vector length (0=no replication).
334 * @param[in] sxy Input vector step.
335 * @param[in] spt Output vector step.
336 * @param[in] x Vector of projected x coordinates.
337 * @param[in] y Vector of projected y coordinates.
338 * @param[out] phi Longitude of the projected point in native spherical
339 * coordinates [deg].
340 * @param[out] theta Latitude of the projected point in native spherical
341 * coordinates [deg].
342 * @param[out] stat Status return value for each vector element
343 *
344 * Deproject pixel (x,y) coordinates in the plane of projection to native
345 * spherical coordinates (phi,theta).
346 *
347 * This method has been adapted from the wcslib function prj.c::molx2s()
348 * (version 4.20). The interface follows very closely that of wcslib. In
349 * contrast to the wcslib routine, however, the method assumes that the
350 * projection has been setup previously (as this will be done by the
351 * constructor).
352 ***************************************************************************/
353void GWcsMOL::prj_x2s(int nx, int ny, int sxy, int spt,
354 const double* x, const double* y,
355 double* phi, double* theta, int* stat) const
356{
357 // Set tolerance
358 const double tol = 1.0e-12;
359
360 // Initialize projection if required
361 if (!m_prjset) {
362 prj_set();
363 }
364
365 // Set value replication length mx,my
366 int mx;
367 int my;
368 if (ny > 0) {
369 mx = nx;
370 my = ny;
371 }
372 else {
373 mx = 1;
374 my = 1;
375 ny = nx;
376 }
377
378 // Initialise status code and statistics
379 int status = 0;
380 int n_invalid = 0;
381
382 // Do x dependence
383 const double* xp = x;
384 int rowoff = 0;
385 int rowlen = nx * spt;
386 for (int ix = 0; ix < nx; ++ix, rowoff += spt, xp += sxy) {
387 double xj = *xp + m_x0;
388 double s = m_w[3] * xj;
389 double t = std::abs(xj) - tol;
390 double* phip = phi + rowoff;
391 double* thetap = theta + rowoff;
392 for (int iy = 0; iy < my; ++iy, phip += rowlen, thetap += rowlen) {
393 *phip = s;
394 *thetap = t;
395 }
396 }
397
398 // Do y dependence
399 const double* yp = y;
400 double* phip = phi;
401 double* thetap = theta;
402 int* statp = stat;
403 for (int iy = 0; iy < ny; ++iy, yp += sxy) {
404
405 // Initialise status
406 int istat = 0;
407
408 // Compute some stuff
409 double yj = *yp + m_y0;
410 double y0 = yj / m_r0;
411 double r = 2.0 - y0 * y0;
412 double s = 0.0;
413
414 // Check limits
415 if (r <= tol) {
416 if (r < -tol) {
417 istat = 1;
418 status = 3;
419 n_invalid++;
420 #if defined(G_DEBUG_PRJ)
421 std::cout << "prj_x2s(Phi)..:";
422 std::cout << " nx=" << nx;
423 std::cout << " ny=" << ny;
424 std::cout << " iy=" << iy;
425 std::cout << " yp=" << *yp;
426 std::cout << " yj=" << yj;
427 std::cout << " y0=" << y0;
428 std::cout << " phip=" << *phip;
429 std::cout << " r=" << r;
430 std::cout << " s=" << s;
431 std::cout << std::endl;
432 #endif
433 }
434 else {
435 istat = -1; // OK if fabs(x) < tol whence phi = 0.0
436 }
437 r = 0.0;
438 s = 0.0;
439 }
440 else {
441 r = std::sqrt(r);
442 s = 1.0 / r;
443 }
444
445 // Compute z and t
446 double z = yj * m_w[2];
447 if (std::abs(z) > 1.0) {
448 if (std::abs(z) > 1.0+tol) {
449 istat = 1;
450 status = 3;
451 n_invalid++;
452 #if defined(G_DEBUG_PRJ)
453 std::cout << "prj_x2s(Phi)..:";
454 std::cout << " nx=" << nx;
455 std::cout << " ny=" << ny;
456 std::cout << " iy=" << iy;
457 std::cout << " yp=" << *yp;
458 std::cout << " yj=" << yj;
459 std::cout << " y0=" << y0;
460 std::cout << " phip=" << *phip;
461 std::cout << " r=" << r;
462 std::cout << " s=" << s;
463 std::cout << " z=" << z;
464 std::cout << std::endl;
465 #endif
466 z = 0.0;
467 }
468 else {
469 z = copysign(1.0, z) + y0 * r / gammalib::pi;
470 }
471 }
472 else {
473 z = std::asin(z) * m_w[4] + y0 * r / gammalib::pi;
474 }
475 if (std::abs(z) > 1.0) {
476 if (std::abs(z) > 1.0+tol) {
477 istat = 1;
478 status = 3;
479 n_invalid++;
480 #if defined(G_DEBUG_PRJ)
481 std::cout << "prj_x2s(Phi)..:";
482 std::cout << " nx=" << nx;
483 std::cout << " ny=" << ny;
484 std::cout << " iy=" << iy;
485 std::cout << " yp=" << *yp;
486 std::cout << " yj=" << yj;
487 std::cout << " y0=" << y0;
488 std::cout << " phip=" << *phip;
489 std::cout << " r=" << r;
490 std::cout << " s=" << s;
491 std::cout << " z=" << z;
492 std::cout << std::endl;
493 #endif
494 z = 0.0;
495 }
496 else {
497 z = copysign(1.0, z);
498 }
499 }
500 double t = std::asin(z) * gammalib::rad2deg;
501
502 // Do ...
503 for (int ix = 0; ix < mx; ++ix, phip += spt, thetap += spt, statp += spt) {
504
505 // Set status flag
506 if (istat < 0 && *thetap >= 0.0) {
507 *statp = 1;
508 status = 3;
509 n_invalid++;
510 }
511 else {
512 *statp = 0;
513 }
514
515 // Set values
516 *phip *= s;
517 *thetap = t;
518
519 }
520
521 } // endfor: did y dependence
522
523 // Check status code
524 gammalib::check_prj_x2s_status(G_PRJ_X2S, status, n_invalid);
525
526 // Do boundary checking
527 status = prj_bchk(1.0e-11, nx, my, spt, phi, theta, stat);
528
529 // Check status code
531
532 // Return
533 return;
534}
535
536
537/***********************************************************************//**
538 * @brief Generic spherical-to-pixel projection
539 *
540 * @param[in] nphi Longitude vector length.
541 * @param[in] ntheta Latitude vector length (0=no replication).
542 * @param[in] spt Input vector step.
543 * @param[in] sxy Output vector step.
544 * @param[in] phi Longitude vector of the projected point in native spherical
545 * coordinates [deg].
546 * @param[in] theta Latitude vector of the projected point in native spherical
547 * coordinates [deg].
548 * @param[out] x Vector of projected x coordinates.
549 * @param[out] y Vector of projected y coordinates.
550 * @param[out] stat Status return value for each vector element (always 0)
551 *
552 * Project native spherical coordinates (phi,theta) to pixel (x,y)
553 * coordinates in the plane of projection.
554 *
555 * This method has been adapted from the wcslib function prj.c::mols2x()
556 * (version 4.20). The interface follows very closely that of wcslib. In
557 * contrast to the wcslib routine, however, the method assumes that the
558 * projection has been setup previously (as this will be done by the
559 * constructor).
560 ***************************************************************************/
561void GWcsMOL::prj_s2x(int nphi, int ntheta, int spt, int sxy,
562 const double* phi, const double* theta,
563 double* x, double* y, int* stat) const
564{
565 // Set tolerance
566 const double tol = 1.0e-13;
567
568 // Initialize projection if required
569 if (!m_prjset) {
570 prj_set();
571 }
572
573 // Set value replication length mphi,mtheta
574 int mphi;
575 int mtheta;
576 if (ntheta > 0) {
577 mphi = nphi;
578 mtheta = ntheta;
579 }
580 else {
581 mphi = 1;
582 mtheta = 1;
583 ntheta = nphi;
584 }
585
586 // Initialise status code and statistics
587 int status = 0;
588 int n_invalid = 0;
589
590 // Do phi dependence
591 const double* phip = phi;
592 int rowoff = 0;
593 int rowlen = nphi * sxy;
594 for (int iphi = 0; iphi < nphi; ++iphi, rowoff += sxy, phip += spt) {
595 double xi = m_w[1] * (*phip);
596 double* xp = x + rowoff;
597 for (int itheta = 0; itheta < mtheta; ++itheta) {
598 *xp = xi;
599 xp += rowlen;
600 }
601 }
602
603 // Do theta dependence
604 const double* thetap = theta;
605 double* xp = x;
606 double* yp = y;
607 int* statp = stat;
608 for (int itheta = 0; itheta < ntheta; ++itheta, thetap += spt) {
609
610 // Compute xi and eta
611 double xi = 0.0;
612 double eta = 0.0;
613 if (std::abs(*thetap) == 90.0) {
614 xi = 0.0;
615 eta = copysign(m_w[0], *thetap);
616 }
617 else if (*thetap == 0.0) {
618 xi = 1.0;
619 eta = 0.0;
620 }
621 else {
622 double u = gammalib::pi * std::sin(*thetap * gammalib::deg2rad);
623 double v0 = -gammalib::pi;
624 double v1 = gammalib::pi;
625 double v = u;
626 for (int k = 0; k < 100; ++k) {
627 double resid = (v - u) + std::sin(v);
628 if (resid < 0.0) {
629 if (resid > -tol) {
630 break;
631 }
632 v0 = v;
633 }
634 else {
635 if (resid < tol) {
636 break;
637 }
638 v1 = v;
639 }
640 v = 0.5 * (v0 + v1);
641 }
642 double gamma = 0.5 * v;
643 xi = std::cos(gamma);
644 eta = std::sin(gamma) * m_w[0];
645 }
646 eta -= m_y0;
647
648 // Do ...
649 for (int iphi = 0; iphi < mphi; ++iphi, xp += sxy, yp += sxy, statp += sxy) {
650 *xp = xi * (*xp) - m_x0;
651 *yp = eta;
652 *statp = 0;
653 }
654
655 } // endfor: theta dependence
656
657 // Check status code
658 gammalib::check_prj_s2x_status(G_PRJ_S2X, status, n_invalid);
659
660 // Return
661 return;
662}
Exception handler interface definition.
Mathematical function definitions.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
#define G_PRJ_X2S
Definition GWcsAIT.cpp:38
#define G_PRJ_S2X
Definition GWcsAIT.cpp:40
const GWcsMOL g_wcs_mol_seed
Definition GWcsMOL.cpp:56
#define copysign(X, Y)
Definition GWcsMOL.cpp:44
Mollweide's projection class definition.
World Coordinate Projection registry class interface definition.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
Mollweide's projection class definition.
Definition GWcsMOL.hpp:43
void prj_set(void) const
Setup of projection.
Definition GWcsMOL.cpp:300
void copy_members(const GWcsMOL &wcs)
Copy class members.
Definition GWcsMOL.cpp:263
void init_members(void)
Initialise class members.
Definition GWcsMOL.cpp:251
GWcsMOL(void)
Void constructor.
Definition GWcsMOL.cpp:69
void prj_x2s(int nx, int ny, int sxy, int spt, const double *x, const double *y, double *phi, double *theta, int *stat) const
Pixel-to-spherical deprojection.
Definition GWcsMOL.cpp:353
virtual std::string print(const GChatter &chatter=NORMAL) const
Print WCS information.
Definition GWcsMOL.cpp:221
virtual ~GWcsMOL(void)
Destructor.
Definition GWcsMOL.cpp:129
virtual void clear(void)
Clear instance.
Definition GWcsMOL.cpp:186
void free_members(void)
Delete class members.
Definition GWcsMOL.cpp:273
virtual GWcsMOL * clone(void) const
Clone instance.
Definition GWcsMOL.cpp:208
void prj_s2x(int nphi, int ntheta, int spt, int sxy, const double *phi, const double *theta, double *x, double *y, int *stat) const
Generic spherical-to-pixel projection.
Definition GWcsMOL.cpp:561
GWcsMOL & operator=(const GWcsMOL &wcs)
Assignment operator.
Definition GWcsMOL.cpp:151
Interface definition for the WCS registry class.
Abstract world coordinate system base class.
Definition GWcs.hpp:51
void free_members(void)
Delete class members.
Definition GWcs.cpp:1066
int prj_bchk(const double &tol, const int &nphi, const int &ntheta, const int &spt, double *phi, double *theta, int *stat) const
Performs bounds checking on native spherical coordinates.
Definition GWcs.cpp:3281
void prj_off(const double &phi0, const double &theta0) const
Compute fiducial offset to force (x,y) = (0,0) at (phi0,theta0)
Definition GWcs.cpp:3232
virtual GWcs & operator=(const GWcs &wcs)
Assignment operator.
Definition GWcs.cpp:180
std::string wcs_print(const GChatter &chatter=NORMAL) const
Print WCS information.
Definition GWcs.cpp:1642
void init_members(void)
Initialise class members.
Definition GWcs.cpp:962
void wcs_set(void) const
Setup of World Coordinate System.
Definition GWcs.cpp:1262
bool m_prjset
Projection is set.
Definition GWcs.hpp:211
std::vector< double > m_w
Intermediate values.
Definition GWcs.hpp:217
double m_y0
Fiducial y offset.
Definition GWcs.hpp:216
double m_x0
Fiducial x offset.
Definition GWcs.hpp:215
double m_r0
Radius of the generating sphere.
Definition GWcs.hpp:212
const double pi
Definition GMath.hpp:35
const double deg2rad
Definition GMath.hpp:43
const double sqrt_two
Definition GMath.hpp:54
void check_prj_s2x_status(const std::string &origin, const int &status, const int &number)
Checks status of GWcs::prj_s2x method.
void check_prj_x2s_status(const std::string &origin, const int &status, const int &number)
Checks status of GWcs::prj_x2s method.
const double rad2deg
Definition GMath.hpp:44