LAL  7.5.0.1-b72065a
TranslateAngles.c
Go to the documentation of this file.
1 //
2 // Copyright (C) 2004, 2005, 2015 Reinhard Prix
3 // Copyright (C) 2013 Matt Pitkin
4 // Copyright (C) 2007 Chris Messenger
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with with program; see the file COPYING. If not, write to the
18 // Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 // MA 02110-1301 USA
20 //
21 
22 #include <math.h>
23 #include <ctype.h>
24 #include <errno.h>
25 
26 #include <lal/StringInput.h>
27 #include <lal/LALConstants.h>
28 #include <lal/LALString.h>
29 #include <lal/TranslateAngles.h>
30 
31 // ==================== function definitions ====================
32 
33 ///
34 /// Translate a string representing an angle in the form "degrees:minutes:seconds" into radians. The string
35 /// could also just contain "degrees:minutes" or "degrees", where the absent parts are set to zero.
36 ///
37 /// It requires that the minutes and seconds values are between 0 to 60. Degrees are allowed to be a
38 /// positive or negative integer between [-360, 360].
39 /// An example would be: XLALTranslateDMStoRAD ( &radians, "-06:52:16.875" );
40 ///
41 int
42 XLALTranslateDMStoRAD ( REAL8 *radians, const CHAR *dms )
43 {
44  XLAL_CHECK ( dms != NULL, XLAL_EINVAL, "Angle input string 'dms' is NULL" );
45  XLAL_CHECK ( radians != NULL, XLAL_EINVAL );
46 
47  XLAL_CHECK ( !isspace(dms[0]), XLAL_EINVAL, "No initial whitespace allowed in input string '%s'\n", dms );
48  XLAL_CHECK ( dms[strlen(dms)-1] != ':', XLAL_EINVAL, "No trailing colons allowed in input string '%s'\n", dms );
49 
50  REAL8 s = 0.;
51  INT4 d = 0, m = 0;
52  int numitems = sscanf(dms, "%d:%d:%lf", &d, &m, &s);
53 
54  XLAL_CHECK ( numitems == 3 || numitems == 2 || numitems == 1, XLAL_EINVAL, "Angle input string '%s' not in format 'degs:mins:secs'", dms );
55  XLAL_CHECK ( d >= -360 && d <= 360, XLAL_EDOM, "Degrees '%d' outside of valid range of [-360,360] deg\n", d );
56  XLAL_CHECK ( m >= 0 && m < 60, XLAL_EDOM, "Minutes '%d' outside of the valid range of [0, 59] mins", m );
57  XLAL_CHECK ( s >= 0 && s < 60, XLAL_EDOM, "Seconds '%lf' outside of the valid range of [0, 60) secs", s );
58 
59  // check if there's a minus sign, and apply to minutes and seconds (degrees would already have it)
60  // Note that this is the reason we don't accept initial whitespace in the input string
61  REAL8 sig = 1;
62  if ( dms[0] == '-' ) {
63  sig = -1;
64  }
65 
66  // now convert the pieces from degrees to radians
67  (*radians) = (LAL_PI/180.0) * ( d + (sig*m / 60.0) + (sig*s / 3600.0) );
68 
69  return XLAL_SUCCESS;
70 
71 } // XLALTranslateDMStoRAD()
72 
73 ///
74 /// Translate a string representing an angle in the form "hours:minutes:seconds" into radians. The string
75 /// could also just contain "hours:minutes" or "hours", where the absent parts are set to zero.
76 ///
77 /// It requires that the hours value to be within [0, 23] hours, and the minutes and seconds values are within [0, 60).
78 /// An example would be: XLALTranslateHMStoRAD( &radians, "12:05:07.765" );
79 ///
80 int
81 XLALTranslateHMStoRAD ( REAL8 *radians, const CHAR *hms )
82 {
83  XLAL_CHECK_REAL8( hms != NULL, XLAL_EINVAL, "Angle input string 'hms' is NULL" );
84  XLAL_CHECK ( radians != NULL, XLAL_EINVAL );
85 
86  XLAL_CHECK ( hms[strlen(hms)-1] != ':', XLAL_EINVAL, "No trailing colons allowed in input string '%s'\n", hms );
87 
88  REAL8 s = 0.;
89  INT4 h = 0, m = 0;
90  int numitems = sscanf(hms, "%d:%d:%lf", &h, &m, &s);
91 
92  XLAL_CHECK_REAL8 ( numitems == 3 || numitems == 2 || numitems == 1, XLAL_EINVAL, "Angle input string '%s' not in format 'hours:mins:secs'\n", hms );
93  XLAL_CHECK_REAL8 ( h >= 0 && h < 24, XLAL_EDOM, "Hours value '%d' must be within [0, 23]\n", h );
94  XLAL_CHECK_REAL8 ( m >= 0 && m < 60, XLAL_EDOM, "Minutes value '%d' must be within [0 to 59]\n", m );
95  XLAL_CHECK_REAL8 ( s >= 0 && s < 60, XLAL_EDOM, "Seconds value '%lf' must be within [0,60)\n", s );
96 
97  /* convert from hh:mm:ss to radians */
98  const REAL8 hour2deg = 360./24.;
99  const REAL8 deg2rad = LAL_PI/180.0;
100  const REAL8 hour2rad = hour2deg * deg2rad;
101 
102  (*radians) = hour2rad * ( h + (m / 60.0) + (s / 3600.0) );
103 
104  return XLAL_SUCCESS;
105 
106 } // XLALTranslateHMStoRAD()
107 
108 
109 ///
110 /// Translate (longitude, right-ascencsion, RA) radians into hours:minutes:seconds (HMS) format, returns allocated string.
111 ///
112 CHAR *
114 {
115  XLAL_CHECK_NULL ( (radians>=0.0) && (radians < LAL_TWOPI), XLAL_EDOM, "RA %g not in range [0, 2pi) rad\n", radians );
116 
117  REAL8 remainderH = radians * 24.0/LAL_TWOPI;
118  INT4 hours = (INT4) floor ( remainderH );
119  remainderH -= hours;
120  INT4 minutes = (INT4) floor ( remainderH * 60.0 );
121  remainderH -= minutes / 60.0;
122  REAL8 seconds = remainderH * 3600.0;
123  INT4 roundedSec = (INT4) round ( seconds * 10000000 ) / 10000000; // round to 1e-7s accuracy
124  if ( roundedSec == 60 )
125  {
126  seconds = 0;
127  minutes ++;
128  if ( minutes == 60 )
129  {
130  minutes = 60;
131  hours ++;
132  if ( hours == 24 ) {
133  hours = 0;
134  }
135  }
136  }
137  CHAR hms[256];
138  snprintf ( hms, sizeof(hms)-1, "%02d:%02d:%010.7f", hours, minutes, seconds ); // output format taken from tempo2
139 
140  return XLALStringDuplicate ( hms );
141 
142 } // XLALTranslateRADtoHMS()
143 
144 ///
145 /// Translate (latitude, declination, DEC) radians into "sign*degrees:minutes:seconds" (DMS) format, returns allocated string
146 ///
147 CHAR *
149 {
150  XLAL_CHECK_NULL ( (radians >= -LAL_PI_2) && (radians < LAL_PI_2), XLAL_EDOM, "DEC %g not in range [-pi/2, pi/2) rad\n", radians);
151 
152  CHAR sign = (radians < 0) ? '-' : '+';
153 
154  REAL8 remainderDeg = fabs ( radians * 360.0/LAL_TWOPI );
155 
156  INT4 degrees = (INT4) floor ( remainderDeg );
157  remainderDeg -= degrees;
158  INT4 arcmins = (INT4) floor ( remainderDeg * 60.0 );
159  remainderDeg -= arcmins / 60.0;
160  REAL8 arcsecs = remainderDeg * 3600.0;
161  INT4 roundedArcsecs = (INT4) round ( arcsecs * 100000 ) / 100000; // round to 1e-5 arcsec accuracy
162  if ( roundedArcsecs == 60 )
163  {
164  arcsecs = 0;
165  arcmins ++;
166  if ( arcmins == 60 )
167  {
168  arcmins = 0;
169  degrees ++;
170  }
171  }
172 
173  CHAR dms[256];
174  snprintf ( dms, sizeof(dms)-1, "%c%02d:%02d:%08.5f", sign, degrees, arcmins, arcsecs );
175 
176  return XLALStringDuplicate ( dms );
177 
178 } // XLALTranslateRADtoDMS()
static int sign(int s)
Definition: LALStringTest.c:27
#define LAL_PI_2
pi/2
Definition: LALConstants.h:181
#define LAL_PI
Archimedes's constant, pi.
Definition: LALConstants.h:179
#define LAL_TWOPI
2*pi is circumference of a circle divided by its radius
Definition: LALConstants.h:180
double REAL8
Double precision real floating-point number (8 bytes).
char CHAR
One-byte signed integer, see Headers LAL(Atomic)Datatypes.h for more details.
int32_t INT4
Four-byte signed integer.
char * XLALStringDuplicate(const char *s)
Like strdup but uses LAL allocation routines (free with LALFree).
Definition: LALString.c:89
static const INT4 m
Definition: Random.c:80
int XLALTranslateHMStoRAD(REAL8 *radians, const CHAR *hms)
Translate a string representing an angle in the form "hours:minutes:seconds" into radians.
CHAR * XLALTranslateRADtoHMS(REAL8 radians)
Translate (longitude, right-ascencsion, RA) radians into hours:minutes:seconds (HMS) format,...
int XLALTranslateDMStoRAD(REAL8 *radians, const CHAR *dms)
Translate a string representing an angle in the form "degrees:minutes:seconds" into radians.
CHAR * XLALTranslateRADtoDMS(REAL8 radians)
Translate (latitude, declination, DEC) radians into "sign*degrees:minutes:seconds" (DMS) format,...
#define XLAL_CHECK(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns an integ...
Definition: XLALError.h:810
#define XLAL_CHECK_REAL8(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns a REAL8.
Definition: XLALError.h:870
#define XLAL_CHECK_NULL(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns a pointe...
Definition: XLALError.h:825
@ XLAL_SUCCESS
Success return value (not an error number)
Definition: XLALError.h:401
@ XLAL_EDOM
Input domain error.
Definition: XLALError.h:410
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409