Jpp 19.3.0
the software that should make you happy
Loading...
Searching...
No Matches
JAstronomy.hh
Go to the documentation of this file.
1#ifndef __JASTRONOMY__JASTRONOMY__
2#define __JASTRONOMY__JASTRONOMY__
3
4#include <istream>
5#include <ostream>
6#include <limits>
7#include <time.h>
8
9#include "JLang/JException.hh"
10#include "JLang/JManip.hh"
11#include "JLang/JEquals.hh"
12
13#include "JMath/JConstants.hh"
14#include "JMath/JMatrix3D.hh"
15#include "JMath/JSVD3D.hh"
16
17#include "JUTM/JUTMGrid.hh"
18
21
22#include "slalib/slalib.h"
23
24/**
25 * \file
26 *
27 * Interface methods for SLALIB and auxiliary classes and methods for astronomy.
28 * \author mdejong, fhuang, azegarelli
29 */
30namespace JASTRONOMY {}
31namespace JPP { using namespace JASTRONOMY; }
32
33namespace JASTRONOMY {
34
36 using JLANG::JEquals;
37 using JMATH::PI;
38 using JGEOMETRY3D::JAngle3D; //!< polar angles [rad]
39 using JGEOMETRY3D::JDirection3D; //!< Cartesian coordinates
40 using JUTM::getUTMZone;
42
43 static const double NUMBER_OF_SECONDS_PER_HOUR = 60.0 * 60.0;
47
48 static const double LATITUDE_MIN_DEG = -80.0; //!< Minimal latitude angle [deg] of UTM for meridian convergence angle calculation
49 static const double LATITUDE_MAX_DEG = 84.0; //!< Maximal latitude angle [deg] of UTM for meridian convergence angle calculation
50
51 static const double MJD_EPOCH = 40587.0; //!< MJD of the Unix Epoch, i.e.\ 00:00 Jan 1 1970 (UTC) [d]
52 static const double MJD_EPOCH_S = MJD_EPOCH * NUMBER_OF_SECONDS_PER_DAY; //!< MJD of the Unix Epoch, i.e.\ 00:00 Jan 1 1970 (UTC) [s]
53
54
55 /**
56 * Ellipsoid.
57 */
58 struct JEllipsoid {
59 /**
60 * Get ellipsoid.
61 *
62 * \return Earth ellipsoid
63 */
64 const JEllipsoid& getEllipsoid() const
65 {
66 return static_cast<const JEllipsoid&>(*this);
67 }
68
69 double radius_m; //!< Ellipsoid radius [m];
70 double eccentricity; //!< Ellipsoid eccentricity squared
71 };
72
73
74 /**
75 * Earth ellipsoid according WGS84.
76 */
77 static const JEllipsoid EARTH_WGS84 = { 6378137.0, 0.00669438 };
78
79
80 /**
81 * Get MJD time given UTC time.
82 *
83 * \param t1_s UTC time [s]
84 * \return MJD time [s]
85 */
86 double getTimeMJD(time_t t1_s)
87 {
88 return t1_s + MJD_EPOCH_S;
89 }
90
91
92 /**
93 * Get UTC time given MJD time.
94 *
95 * \param t1_s MJD time [s]
96 * \return UTC time [s]
97 */
98 double getTimeUTC(time_t t1_s)
99 {
100 return t1_s - MJD_EPOCH_S;
101 }
102
103
104 /**
105 * Convert angle to radians.
106 *
107 * \param angle angle [deg]
108 * \return angle [rad]
109 */
110 inline double getRadians(const double angle)
111 {
112 return PI * angle / 180.0;
113 }
114
115
116 /**
117 * Convert angle to degrees.
118 *
119 * \param angle angle [rad]
120 * \return angle [deg]
121 */
122 inline double getDegrees(const double angle)
123 {
124 return 180.0 * angle / PI;
125 }
126
127
128 /**
129 * Convert angle to radians.
130 *
131 * \param angle angle [deg]
132 * \param amin arcminutes
133 * \param asec arcseconds
134 * \return angle [rad]
135 */
136 inline double getRadians(const int angle,
137 const int amin,
138 const double asec)
139 {
140 return PI * ((double) angle +
141 (double) amin / 60.0 +
142 (double) asec / 3600.0) / 180.0;
143 }
144
145
146 /**
147 * Convert hour angle to radians.
148 *
149 * \param hour hour
150 * \param min minutes
151 * \param sec seconds
152 * \return angle [rad]
153 */
154 inline double getHourAngle(const int hour,
155 const int min,
156 const double sec)
157 {
158 double ha = PI * ((double) hour / 12.0 +
159 (double) min / 720.0 +
160 (double) sec / 43200.0);
161
162 if (ha > PI) {
163 ha -= 2*PI;
164 }
165
166 return ha;
167 }
168
169
170 /**
171 * Forward declarations.
172 */
173 struct angle_type_rad;
174 struct angle_type_deg;
175 struct J2000;
176 struct JSourceLocation;
179
180
181 /**
182 * Auxiliary data structure for pair of angles.
183 */
184 struct angle_type :
185 public JEquals<angle_type>
186 {
187 /**
188 * Check equality.
189 *
190 * \param angle pair of angles
191 * \param precision precision
192 * \return true if angles are equal; else false
193 */
194 bool equals(const angle_type& angle,
195 const double precision = std::numeric_limits<double>::min()) const
196 {
197 return (fabs(this->_theta_ - angle._theta_) <= precision &&
198 fabs(this->_phi_ - angle._phi_) <= precision);
199 }
200
201
202 /**
203 * Read pair of angles from input stream.
204 *
205 * \param in input stream
206 * \param object pair of angles
207 * \return input stream
208 */
209 friend inline std::istream& operator>>(std::istream& in, angle_type& object)
210 {
211 return in >> object._theta_
212 >> object._phi_;
213 }
214
215 /**
216 * Write pair of angles to output stream.
217 *
218 * \param out output stream
219 * \param object pair of angles
220 * \return output stream
221 */
222 friend inline std::ostream& operator<<(std::ostream& out, const angle_type& object)
223 {
224 return out << FIXED(12,7) << object._theta_ << ' '
225 << FIXED(12,7) << object._phi_;
226 }
227
228 protected:
229 /**
230 * Default constructor.
231 */
233 _theta_(0.0),
234 _phi_ (0.0)
235 {}
236
237
238 /**
239 * Constructor.
240 *
241 * \param theta theta
242 * \param phi phi
243 */
244 angle_type(const double theta,
245 const double phi) :
246 _theta_(theta),
247 _phi_ (phi)
248 {}
249
250 double _theta_;
251 double _phi_;
252 };
253
254
255 /**
256 * Auxiliary data structure for pair of angles.
257 */
259 public angle_type
260 {
261 /**
262 * Default constructor.
263 */
266
267
268 /**
269 * Constructor.
270 *
271 * \param theta theta [rad]
272 * \param phi phi [rad]
273 */
274 angle_type_rad(const double theta,
275 const double phi) :
276 angle_type(theta, phi)
277 {}
278
279
280 /**
281 * Conversion constructor.
282 *
283 * \param angle angle [deg]
284 */
285 angle_type_rad(const angle_type_deg& angle);
286
287
288 /**
289 * Convert angle.
290 *
291 * \param angle angle [rad]
292 */
293 void set(const angle_type_deg& angle)
294 {
295 static_cast<angle_type_rad&>(*this) = angle_type_rad(angle);
296 }
297
298
299 friend struct angle_type_deg;
300 friend struct J2000;
301 };
302
303
304 /**
305 * Auxiliary data structure for pair of angles.
306 */
308 public angle_type
309 {
310 /**
311 * Default constructor.
312 */
315
316
317 /**
318 * Constructor.
319 *
320 * \param theta theta [deg]
321 * \param phi phi [deg]
322 */
323 angle_type_deg(const double theta,
324 const double phi) :
325 angle_type(theta, phi)
326 {}
327
328
329 /**
330 * Conversion constructor.
331 *
332 * \param angle angle [rad]
333 */
334 angle_type_deg(const angle_type_rad& angle);
335
336
337 /**
338 * Convert angle.
339 *
340 * \param angle angle [rad]
341 */
342 void set(const angle_type_rad& angle)
343 {
344 static_cast<angle_type_deg&>(*this) = angle_type_deg(angle);
345 }
346
347
348 friend struct angle_type_rad;
349 };
350
351
352 /**
353 * Conversion constructor.
354 *
355 * \param angle angle [deg]
356 */
358 angle_type(getRadians(angle._theta_), getRadians(angle._phi_))
359 {}
360
361
362 /**
363 * Conversion constructor.
364 *
365 * \param angle angle [rad]
366 */
368 angle_type(getDegrees(angle._theta_), getDegrees(angle._phi_))
369 {}
370
371
372 /**
373 * Conversion of source location.
374 */
375 struct J2000 {
376 /**
377 * Conversion options.
378 */
380 FROM = -1,
381 TO = +1
382 };
383
384
385 /**
386 * Convert source location according J2000 at given time.
387 * Adapted from <tt>aanet/astro/Astro.cc</tt>
388 *
389 * \param t1_s time since MJD [s]
390 * \param location source location
391 * \param option option
392 * \return source location
393 */
394 static inline angle_type_rad convert(const double t1_s, const angle_type_rad& location, const J2000::CONVERSION option)
395 {
396 using namespace JPP;
397
398 // --- get the rotation matrix ----
399 // NOTE: (from seatray Astro): Julian epoch of J2000 time definition is 2000,
400 // corresponding by definition to 2451545.0 TT (unmodified) Julian date!
401
402 double mjd = t1_s / NUMBER_OF_SECONDS_PER_DAY; // [days]
403 double epoch = 2000;
404 double R[3][3] {};
405
406 slaPrenut(epoch, mjd, R); // SLALIB function to get the matrix of precession and nutation
407
408 JMatrix3D M = JMatrix3D(R[0][0], R[0][1], R[0][2],
409 R[1][0], R[1][1], R[1][2],
410 R[2][0], R[2][1], R[2][2]);
411
412 M.transpose(); // transpose 'cause of fortan matrix convention
413
414 if (option == J2000::TO) {
415
416 JSVD3D V(M);
417
418 M = V.invert();
419 }
420
421 // convert (declination, right ascension) to polar coordinates (theta, phi)
422
423 JDirection3D v(JAngle3D(PI/2 - location._theta_, location._phi_));
424
425 // apply transformation
426
427 v.transform(M);
428
429 // convert polar coordinates (theta, phi) to (declination, right ascension)
430
431 return angle_type_rad(PI/2 - v.getTheta(), v.getPhi());
432 }
433 };
434
435
436 /**
437 * Location of astrophysical source.
438 */
440 public angle_type_rad
441 {
442 /**
443 * Default constructor.
444 */
447
448
449 /**
450 * Constructor.
451 *
452 * \param dec declination [rad]
453 * \param ra right ascension [rad]
454 */
455 JSourceLocation(const double dec,
456 const double ra) :
457 angle_type_rad(dec, ra)
458 {}
459
460
461 /**
462 * Conversion constructor.
463 *
464 * \param t1_s time since MJD [s]
465 * \param location source location
466 */
467 JSourceLocation(const double t1_s, const JSourceLocationJ2000& location);
468
469
470 /**
471 * Constructor.
472 *
473 * \param angle polar angles [rad]
474 */
475 JSourceLocation(const JAngle3D& angle) :
476 angle_type_rad(PI/2 - angle.getTheta(), angle.getPhi())
477 {}
478
479
480 /**
481 * Get source location.
482 *
483 * \return source location
484 */
486 {
487 return static_cast<const JSourceLocation&>(*this);
488 }
489
490
491 /**
492 * Type conversion operator.
493 *
494 * \return polar angles [rad]
495 */
496 operator JAngle3D() const
497 {
498 return JAngle3D(PI/2 - _theta_, _phi_);
499 }
500
501
502 double getDeclination() const { return _theta_; } //!< Get declination.
503 double getRightAscension() const { return _phi_; } //!< Get right ascension.
504
505
506 /**
507 * Dot product.
508 *
509 * \param location source location
510 * \return dot product
511 */
512 inline double getDot(const JSourceLocation& location) const
513 {
514 return
515 cos(this->_theta_) * cos(location._theta_) * cos(this->_phi_ - location._phi_) +
516 sin(this->_theta_) * sin(location._theta_);
517 }
518 };
519
520
521 /**
522 * Location of astrophysical source.
523 */
525 public angle_type_rad
526 {
527 /**
528 * Default constructor.
529 */
532
533
534 /**
535 * Constructor.
536 *
537 * \param dec declination [rad]
538 * \param ra right ascension [rad]
539 */
540 JSourceLocationJ2000(const double dec,
541 const double ra) :
542 angle_type_rad(dec, ra)
543 {}
544
545
546 /**
547 * Conversion constructor.
548 *
549 * \param t1_s time since MJD [s]
550 * \param location source location
551 */
552 JSourceLocationJ2000(const double t1_s, const JSourceLocation& location);
553
554
555 /**
556 * Conversion constructor.
557 *
558 * \param location source location
559 */
561
562
563 /**
564 * Constructor.
565 *
566 * \param angle polar angles [rad]
567 */
569 angle_type_rad(PI/2 - angle.getTheta(), angle.getPhi())
570 {}
571
572
573 /**
574 * Get source location.
575 *
576 * \return source location
577 */
579 {
580 return static_cast<const JSourceLocationJ2000&>(*this);
581 }
582
583
584 /**
585 * Type conversion operator.
586 *
587 * \return polar angles [rad]
588 */
589 operator JAngle3D() const
590 {
591 return JAngle3D(PI/2 - _theta_, _phi_);
592 }
593
594
595 double getDeclination() const { return _theta_; } //!< Get declination.
596 double getRightAscension() const { return _phi_; } //!< Get right ascension.
597
598
599 /**
600 * Dot product.
601 *
602 * \param location source location
603 * \return dot product
604 */
605 inline double getDot(const JSourceLocationJ2000& location) const
606 {
607 return
608 cos(this->_theta_) * cos(location._theta_) * cos(this->_phi_ - location._phi_) +
609 sin(this->_theta_) * sin(location._theta_);
610 }
611 };
612
613
614 /**
615 * Conversion constructor.
616 *
617 * \param t1_s time since MJD [s]
618 * \param location source location
619 */
620 JSourceLocation::JSourceLocation(const double t1_s, const JSourceLocationJ2000& location) :
621 angle_type_rad(J2000::convert(t1_s, location, J2000::FROM))
622 {}
623
624
625 /**
626 * Conversion constructor.
627 *
628 * \param t1_s time since MJD [s]
629 * \param location source location
630 */
632 angle_type_rad(J2000::convert(t1_s, location, J2000::TO))
633 {}
634
635
636 /**
637 * Location of astrophysical source in Galactic coordinates.
638 */
640 public angle_type_rad
641 {
642 /**
643 * Default constructor.
644 */
647
648
649 /**
650 * Constructor.
651 *
652 * \param latitude Galactic latitude [rad]
653 * \param longitude Galactic longitude [rad]
654 */
655 JGalacticCoordinates(const double latitude,
656 const double longitude) :
657 angle_type_rad(latitude, longitude)
658 {}
659
660
661 /**
662 * Constructor.
663 *
664 * \param location source location
665 */
667
668
669 /**
670 * Constructor.
671 *
672 * \param angle polar angles [rad]
673 */
675 angle_type_rad(PI/2 - angle.getTheta(), angle.getPhi())
676 {}
677
678
679 /**
680 * Get Galactic coordinates.
681 *
682 * \return Galactic coordinates
683 */
685 {
686 return static_cast<const JGalacticCoordinates&>(*this);
687 }
688
689
690 /**
691 * Type conversion operator.
692 *
693 * \return polar angles [rad]
694 */
695 operator JAngle3D() const
696 {
697 return JAngle3D(PI/2 - _theta_, _phi_);
698 }
699
700
701 double getLatitude() const { return _theta_; } //!< Get latitude.
702 double getLongitude() const { return _phi_; } //!< Get longitude.
703
704
705 /**
706 * Dot product.
707 *
708 * \param location source location
709 * \return dot product
710 */
711 inline double getDot(const JGalacticCoordinates& location) const
712 {
713 return
714 cos(this->_theta_) * cos(location._theta_) * cos(this->_phi_ - location._phi_) +
715 sin(this->_theta_) * sin(location._theta_);
716 }
717 };
718
719
720 /**
721 * Conversion constructor.
722 *
723 * \param location source location
724 */
726 {
727 double lat = location.getLatitude();
728 double lon = location.getLongitude();
729
730 slaGaleq(lon, lat, &this->_phi_, &this->_theta_);
731 }
732
733
734 /**
735 * Constructor.
736 *
737 * \param location source location
738 */
740 {
741 double dec = location.getDeclination();
742 double ra = location.getRightAscension();
743
744 slaEqgal(ra, dec, &this->_phi_, &this->_theta_);
745 }
746
747
748 /**
749 * Direction of incident neutrino.
750 */
752 public angle_type_rad
753 {
754 /**
755 * Default constructor.
756 */
759
760
761 /**
762 * Constructor.
763 *
764 * \param zenith zenith [rad]
765 * \param azimuth azimuth [rad]
766 */
767 JNeutrinoDirection(const double zenith,
768 const double azimuth) :
769 angle_type_rad(zenith, azimuth)
770 {}
771
772
773 /**
774 * Constructor.
775 *
776 * \param angle polar angles [rad]
777 */
779 angle_type_rad(angle.getTheta(), angle.getPhi())
780 {}
781
782
783 /**
784 * Get neutrino direction.
785 *
786 * \return neutrino direction
787 */
789 {
790 return static_cast<const JNeutrinoDirection&>(*this);
791 }
792
793
794 /**
795 * Type conversion operator.
796 *
797 * \return polar angles [rad]
798 */
799 operator JAngle3D() const
800 {
801 return JAngle3D(_theta_, _phi_);
802 }
803
804
805 double getZenith() const { return _theta_; } //!< Get zenith.
806 double getAzimuth() const { return _phi_; } //!< Get azimuth.
807
808
809 /**
810 * Dot product.
811 *
812 * \param dir neutrino direction
813 * \return dot product
814 */
815 inline double getDot(const JNeutrinoDirection& dir) const
816 {
817 return
818 sin(this->_theta_) * sin(dir._theta_) * cos(this->_phi_ - dir._phi_) +
819 cos(this->_theta_) * cos(dir._theta_);
820 }
821 };
822
823
824 /**
825 * Location of detector.
826 */
828 public angle_type_rad
829 {
830 /**
831 * Default constructor.
832 */
835
836
837 /**
838 * Constructor.
839 *
840 * \param latitude latitude
841 * \param longitude longitude
842 */
843 JGeographicalLocation(const double latitude,
844 const double longitude) :
845 angle_type_rad(latitude, longitude)
846 {}
847
848
849 /**
850 * Constructor.
851 *
852 * \param degreesNorth degrees North
853 * \param minutesNorth minutes North
854 * \param degreesEast degrees East
855 * \param minutesEast minutes East
856 */
857 JGeographicalLocation(const int degreesNorth,
858 const int minutesNorth,
859 const int degreesEast,
860 const int minutesEast) :
861 angle_type_rad(getRadians((double) degreesNorth + (double) minutesNorth / 60.0),
862 getRadians((double) degreesEast + (double) minutesEast / 60.0))
863 {}
864
865
866 /**
867 * Constructor.
868 *
869 * \param angle polar angles [rad]
870 */
872 angle_type_rad(PI/2 - angle.getTheta(), angle.getPhi())
873 {}
874
875
876 /**
877 * Get geographical location.
878 *
879 * \return geographical location
880 */
882 {
883 return static_cast<const JGeographicalLocation&>(*this);
884 }
885
886
887 /**
888 * Type conversion operator.
889 *
890 * \return polar angles [rad]
891 */
892 operator JAngle3D() const
893 {
894 return JAngle3D(PI/2 - _theta_, _phi_);
895 }
896
897
898 double getLatitude() const { return _theta_; } //!< Get latitude.
899 double getLongitude() const { return _phi_; } //!< Get longitude.
900
901
902 /**
903 * Dot product.
904 *
905 * \param location location
906 * \return dot product
907 */
908 inline double getDot(const JGeographicalLocation& location) const
909 {
910 return
911 sin(this->_theta_) * sin(location._theta_) +
912 cos(this->_theta_) * cos(location._theta_) * cos(this->_phi_ - location._phi_);
913 }
914 };
915
916
917 /**
918 * Get Meridian convergence angle
919 *
920 * The meridian convergence angle is the angle between the true meridian of a point on the surface of the earth's ellipsoid and
921 * the Prime Meridian of the projection zone where the point is located, that is, the angle between the coordinate north and
922 * the true north of the Gaussian plane rectangular coordinate system.
923 * see https://gis.stackexchange.com/questions/115531/calculating-grid-convergence-true-north-to-grid-north
924 *
925 * \param location geographical location
926 * \return meridian convergence angle [rad]
927 */
929 {
930 const double omega = location.getLongitude() - getUTMLongitude(getUTMZone(location.getLongitude()));
931 const double gamma = atan(tan(omega) * sin(location.getLatitude()));
932
933 return gamma;
934 }
935
936
937 /**
938 * Get Meridian convergence angle
939 *
940 * Angular difference of the UTM Northing direction to the geodetic North. It is positive to the East.
941 * For example, for ANTARES, convergence angle = -1.93 deg E, i.e. UTM North pointing a bit towards the geographical West.
942 * Code from <tt>aanet/evt/Det.cc</tt>.
943 *
944 * \param location geographical location
945 * \param ellipsoid Earth ellipsoid
946 * \return meridian convergence angle [rad]
947 */
949 {
950 const double latitude_deg = getDegrees(location.getLatitude());
951
952 if (latitude_deg > LATITUDE_MAX_DEG ||
953 latitude_deg < LATITUDE_MIN_DEG) {
955 "UTM coordinate system not defined for given Latitude: "
956 << latitude_deg << " [deg] <> [" << FIXED(5,2) << LATITUDE_MAX_DEG << "," << FIXED(5,2) << LATITUDE_MIN_DEG << "]");
957 }
958
959 // detector position, longitude and latitude in rad
960 const double lambda = location.getLongitude();
961 const double phi = location.getLatitude();
962
963 // find UTM zone and central meridian
964 // longitude of the central meridian of UTM zone in rad
965 const double omega = lambda - getUTMLongitude(getUTMZone(location.getLongitude()));
966
967 const double rho = ellipsoid.radius_m*(1.-ellipsoid.eccentricity)/pow(1.-ellipsoid.eccentricity*pow(sin(phi),2),3./2.);
968 const double nu = ellipsoid.radius_m/sqrt(1-ellipsoid.eccentricity*pow(sin(phi),2.));
969 const double psi = nu/rho;
970 const double t = tan(phi);
971
972 // power series for convergence angle
973 const double gamma = sin(phi) * omega
974 - sin(phi) * pow(omega,3.)/3. * pow(cos(phi),2.) * (2.*pow(psi,2.)-psi)
975 - sin(phi) * pow(omega,5.)/15. * pow(cos(phi),4.) * (pow(psi,4.)*(11.-24.*pow(t,2.))-
976 pow(psi,3.)*(11.-36.*pow(t,2.))+
977 2.*pow(psi,2.)*(1.-7.*pow(t,2.))+
978 psi*pow(t,2.)
979 )
980 - sin(phi) * pow(omega,7.)/315. * pow(cos(phi),6.) * (17.-26.*pow(t,2.)+2.*pow(t,4.));
981
982 return gamma;
983 }
984
985
986 /**
987 * Auxiliary class to make coordinate transformations for a specific geographical location of the detector.
988 *
989 * Note that SLALIB reference system corresponds to (x,y,z) = (N,E,up).
990 */
991 class JAstronomy :
993 public JEllipsoid
994 {
995 public:
996
997 /**
998 * Constructor.
999 *
1000 * \param location location of detector
1001 * \param ellipsoid Earth ellipsoid
1002 */
1007
1008
1009 /**
1010 * Get direction pointing to source given time and source location.
1011 *
1012 * \param t1_s time since MJD [s]
1013 * \param pos source location
1014 * \return direction of neutrino
1015 */
1016 JNeutrinoDirection getNeutrinoDirection(const double t1_s, const JSourceLocation& pos) const
1017 {
1018 double longitude = this->getLongitude();
1019 double latitude = this->getLatitude();
1020
1021 // Convert current mjd (UTC) to local sidereal time,
1022 // taking into account the Equation of the Equinoxes:
1023 // Note: LST = GMST + local longitude, where l.l. is +/- if east/west of prime meridian
1024
1025 double mjd = t1_s / NUMBER_OF_SECONDS_PER_DAY; // [days]
1026
1027 double gmst = slaGmst(mjd); // gmst = Greenwich mean sidereal time
1028 double eqeqx = slaEqeqx(mjd); // Note: Equation of the Equinoxes < 1.15 secs
1029 double lst = gmst + longitude + eqeqx;
1030
1031 // Transform time-independent equatorial coordinates to time-dependent equatorial coordinates (i.e.\ ra->ha):
1032
1033 double dec = pos.getDeclination();
1034 double ra = pos.getRightAscension();
1035 double ha = lst - ra;
1036
1037 // Convert time-dependent equatorial coordinates to local horizontal coordinates:
1038 // Note: azimuth: [0,2pi] and elevation: [-pi,pi]
1039
1040 double azimuth;
1041 double elevation;
1042
1043 slaDe2h(ha, dec, latitude, &azimuth, &elevation);
1044
1045 double theta = -elevation + PI/2.0;
1046 double phi = -azimuth + PI/2.0;
1047
1049
1050 // invert direction
1051
1052 theta = PI - theta;
1053 phi = phi + PI;
1054
1055 if (phi > PI) {
1056 phi -= 2.0*PI;
1057 }
1058
1059 return JNeutrinoDirection(theta, phi);
1060 }
1061
1062
1063 /**
1064 * Get location of source given time and neutrino direction.
1065 *
1066 * \param t1_s time since MJD [s]
1067 * \param dir direction of neutrino
1068 * \return source location
1069 */
1070 JSourceLocation getSourceLocation(const double t1_s, const JNeutrinoDirection& dir) const
1071 {
1072 double longitude = this->getLongitude();
1073 double latitude = this->getLatitude();
1074
1075 double theta = dir.getZenith();
1076 double phi = dir.getAzimuth();
1077
1078 // invert direction
1079
1080 theta = PI - theta;
1081 phi = phi - PI;
1082
1083 if (phi < PI) {
1084 phi += 2.0*PI;
1085 }
1086
1088
1089 double elevation = -theta + PI/2.0;
1090 double azimuth = -phi + PI/2.0;
1091
1092 double ha;
1093 double dec;
1094
1095 slaDh2e(azimuth, elevation, latitude, &ha, &dec);
1096
1097 double mjd = t1_s / NUMBER_OF_SECONDS_PER_DAY; // [days]
1098
1099 double gmst = slaGmst(mjd); // gmst = Greenwich mean sidereal time
1100 double eqeqx = slaEqeqx(mjd); // Note: Equation of the Equinoxes < 1.15 secs
1101 double lst = gmst + longitude + eqeqx;
1102 double ra = lst - ha;
1103
1104 return JSourceLocation(dec, ra);
1105 }
1106 };
1107
1108
1109 // detector locations
1110
1111 static const JGeographicalLocation ANTARES(42, 48, 06, 10);
1112 static const JGeographicalLocation SICILY (36, 16, 16, 06);
1113 static const JGeographicalLocation PYLOS (36, 33, 16, 06);
1114 static const JGeographicalLocation ARCA (0.63342, 0.27883);
1115 static const JGeographicalLocation ORCA (0.74702, 0.10511);
1116
1117 // source locations
1118
1119 static const JSourceLocation GALACTIC_CENTER(-0.5062816, -1.633335);
1120 static const JSourceLocation RXJ1713 (getRadians(-39, -46, 0.0), getHourAngle(17, 13, 7));
1121 static const JSourceLocation VELAX (getRadians(-45, -10, -35.2), getHourAngle( 8, 35, 20.66));
1122}
1123
1124#endif
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
I/O manipulators.
Mathematical constants.
static Ellipsoid ellipsoid[]
Auxiliary class to make coordinate transformations for a specific geographical location of the detect...
JSourceLocation getSourceLocation(const double t1_s, const JNeutrinoDirection &dir) const
Get location of source given time and neutrino direction.
JNeutrinoDirection getNeutrinoDirection(const double t1_s, const JSourceLocation &pos) const
Get direction pointing to source given time and source location.
JAstronomy(const JGeographicalLocation &location, const JEllipsoid &ellipsoid=EARTH_WGS84)
Constructor.
Data structure for angles in three dimensions.
Definition JAngle3D.hh:35
Data structure for direction in three dimensions.
JDirection3D & transform(const JMatrix3D &T)
Transform.
double getTheta() const
Get theta angle.
Definition JVersor3D.hh:128
double getPhi() const
Get phi angle.
Definition JVersor3D.hh:144
Exception for accessing a value in a collection that is outside of its range.
JMatrix3D & transpose()
Transpose.
Singular value decomposition.
Definition JSVD3D.hh:27
const JMatrix3D & invert(const double precision=1.0e-12) const
Get inverted matrix.
Definition JSVD3D.hh:192
void convert(std::ostream &out, const Header &header, const CSV &csv)
Definition csv2code.hh:29
static const JSourceLocation VELAX(getRadians(-45, -10, -35.2), getHourAngle(8, 35, 20.66))
static const JGeographicalLocation PYLOS(36, 33, 16, 06)
double getHourAngle(const int hour, const int min, const double sec)
Convert hour angle to radians.
static const JSourceLocation GALACTIC_CENTER(-0.5062816, -1.633335)
static const double NUMBER_OF_SECONDS_PER_YEAR
Definition JAstronomy.hh:45
double getMeridianConvergenceAngle(const JGeographicalLocation &location)
Get Meridian convergence angle.
double getTimeMJD(time_t t1_s)
Get MJD time given UTC time.
Definition JAstronomy.hh:86
static const JSourceLocation RXJ1713(getRadians(-39, -46, 0.0), getHourAngle(17, 13, 7))
static const double NUMBER_OF_SECONDS_PER_DAY
Definition JAstronomy.hh:44
static const JGeographicalLocation ARCA(0.63342, 0.27883)
static const double NUMBER_OF_SECONDS_PER_SEDERIAL_DAY
Definition JAstronomy.hh:46
double getDegrees(const double angle)
Convert angle to degrees.
static const double LATITUDE_MAX_DEG
Maximal latitude angle [deg] of UTM for meridian convergence angle calculation.
Definition JAstronomy.hh:49
static const double LATITUDE_MIN_DEG
Minimal latitude angle [deg] of UTM for meridian convergence angle calculation.
Definition JAstronomy.hh:48
static const double NUMBER_OF_SECONDS_PER_HOUR
Definition JAstronomy.hh:43
static const JGeographicalLocation ORCA(0.74702, 0.10511)
static const JEllipsoid EARTH_WGS84
Earth ellipsoid according WGS84.
Definition JAstronomy.hh:77
static const double MJD_EPOCH
MJD of the Unix Epoch, i.e. 00:00 Jan 1 1970 (UTC) [d].
Definition JAstronomy.hh:51
static const double MJD_EPOCH_S
MJD of the Unix Epoch, i.e. 00:00 Jan 1 1970 (UTC) [s].
Definition JAstronomy.hh:52
double getRadians(const double angle)
Convert angle to radians.
double getTimeUTC(time_t t1_s)
Get UTC time given MJD time.
Definition JAstronomy.hh:98
static const JGeographicalLocation ANTARES(42, 48, 06, 10)
static const JGeographicalLocation SICILY(36, 16, 16, 06)
static const double PI
Mathematical constants.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
int getUTMZone(const double longitude)
Get UTM zone for given longitude.
Definition JUTMGrid.hh:47
static double getUTMLongitude(const int zone)
Get longitude of the central meridian for given UTM zone.
Definition JUTMGrid.hh:59
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Conversion of source location.
CONVERSION
Conversion options.
static angle_type_rad convert(const double t1_s, const angle_type_rad &location, const J2000::CONVERSION option)
Convert source location according J2000 at given time.
double eccentricity
Ellipsoid eccentricity squared.
Definition JAstronomy.hh:70
const JEllipsoid & getEllipsoid() const
Get ellipsoid.
Definition JAstronomy.hh:64
double radius_m
Ellipsoid radius [m];.
Definition JAstronomy.hh:69
Location of astrophysical source in Galactic coordinates.
JGalacticCoordinates()
Default constructor.
double getDot(const JGalacticCoordinates &location) const
Dot product.
double getLongitude() const
Get longitude.
double getLatitude() const
Get latitude.
JGalacticCoordinates(const JAngle3D &angle)
Constructor.
const JGalacticCoordinates & getGalacticCoordinates() const
Get Galactic coordinates.
JGalacticCoordinates(const double latitude, const double longitude)
Constructor.
double getLongitude() const
Get longitude.
JGeographicalLocation(const JAngle3D &angle)
Constructor.
JGeographicalLocation()
Default constructor.
double getDot(const JGeographicalLocation &location) const
Dot product.
JGeographicalLocation(const int degreesNorth, const int minutesNorth, const int degreesEast, const int minutesEast)
Constructor.
JGeographicalLocation(const double latitude, const double longitude)
Constructor.
const JGeographicalLocation & getGeographicalLocation() const
Get geographical location.
double getLatitude() const
Get latitude.
Direction of incident neutrino.
JNeutrinoDirection(const double zenith, const double azimuth)
Constructor.
double getZenith() const
Get zenith.
const JNeutrinoDirection & getNeutrinoDirection() const
Get neutrino direction.
JNeutrinoDirection()
Default constructor.
JNeutrinoDirection(const JAngle3D &angle)
Constructor.
double getDot(const JNeutrinoDirection &dir) const
Dot product.
double getAzimuth() const
Get azimuth.
Location of astrophysical source.
const JSourceLocationJ2000 & getSourceLocation() const
Get source location.
JSourceLocationJ2000(const JAngle3D &angle)
Constructor.
JSourceLocationJ2000(const double dec, const double ra)
Constructor.
JSourceLocationJ2000()
Default constructor.
double getDot(const JSourceLocationJ2000 &location) const
Dot product.
double getRightAscension() const
Get right ascension.
double getDeclination() const
Get declination.
Location of astrophysical source.
const JSourceLocation & getSourceLocation() const
Get source location.
double getRightAscension() const
Get right ascension.
JSourceLocation()
Default constructor.
double getDot(const JSourceLocation &location) const
Dot product.
JSourceLocation(const double dec, const double ra)
Constructor.
double getDeclination() const
Get declination.
JSourceLocation(const JAngle3D &angle)
Constructor.
Auxiliary data structure for pair of angles.
angle_type_deg(const double theta, const double phi)
Constructor.
void set(const angle_type_rad &angle)
Convert angle.
angle_type_deg()
Default constructor.
Auxiliary data structure for pair of angles.
angle_type_rad()
Default constructor.
angle_type_rad(const double theta, const double phi)
Constructor.
void set(const angle_type_deg &angle)
Convert angle.
Auxiliary data structure for pair of angles.
angle_type()
Default constructor.
friend std::istream & operator>>(std::istream &in, angle_type &object)
Read pair of angles from input stream.
friend std::ostream & operator<<(std::ostream &out, const angle_type &object)
Write pair of angles to output stream.
bool equals(const angle_type &angle, const double precision=std::numeric_limits< double >::min()) const
Check equality.
angle_type(const double theta, const double phi)
Constructor.
Template definition of auxiliary base class for comparison of data structures.
Definition JEquals.hh:84