1
2 """module for coordinate manipulation (conversions, calculations etc.)
3
4 (c) 2007-2009 Matt Hilton
5
6 U{http://astlib.sourceforge.net}
7
8 """
9
10 import sys
11 import math
12 from PyWCSTools import wcscon
13
14
16 """Converts a delimited string of Hours:Minutes:Seconds format into decimal degrees.
17
18 @type RAString: string
19 @param RAString: coordinate string in H:M:S format
20 @type delimiter: string
21 @param delimiter: delimiter character in RAString
22 @rtype: float
23 @return: coordinate in decimal degrees
24
25 """
26
27 if delimiter=="":
28 RABits=str(RAString).split()
29 else:
30 RABits=str(RAString).split(delimiter)
31 if len(RABits)>1:
32 RAHDecimal=float(RABits[0])
33 if len(RABits)>1:
34 RAHDecimal=RAHDecimal+(float(RABits[1])/60.0)
35 if len(RABits)>2:
36 RAHDecimal=RAHDecimal+(float(RABits[2])/3600.0)
37 RADeg=(RAHDecimal/24.0)*360.0
38 else:
39 RADeg=float(RAString)
40
41 return RADeg
42
43
45 """Converts a delimited string of Degrees:Minutes:Seconds format into decimal degrees.
46
47 @type decString: string
48 @param decString: coordinate string in D:M:S format
49 @type delimiter: string
50 @param delimiter: delimiter character in decString
51 @rtype: float
52 @return: coordinate in decimal degrees
53
54 """
55
56 if delimiter=="":
57 decBits=str(decString).split()
58 else:
59 decBits=str(decString).split(delimiter)
60 if len(decBits)>1:
61 decDeg=float(decBits[0])
62 if decBits[0].find("-")!=-1:
63 if len(decBits)>1:
64 decDeg=decDeg-(float(decBits[1])/60.0)
65 if len(decBits)>2:
66 decDeg=decDeg-(float(decBits[2])/3600.0)
67 else:
68 if len(decBits)>1:
69 decDeg=decDeg+(float(decBits[1])/60.0)
70 if len(decBits)>2:
71 decDeg=decDeg+(float(decBits[2])/3600.0)
72 else:
73 decDeg=float(decString)
74
75 return decDeg
76
77
79 """Converts decimal degrees to string in Hours:Minutes:Seconds format with user specified
80 delimiter.
81
82 @type RADeg: float
83 @param RADeg: coordinate in decimal degrees
84 @type delimiter: string
85 @param delimiter: delimiter character in returned string
86 @rtype: string
87 @return: coordinate string in H:M:S format
88
89
90 """
91 hours=(RADeg/360.0)*24
92 if hours<10 and hours>=1:
93 sHours="0"+str(hours)[0]
94 elif hours>=10:
95 sHours=str(hours)[:2]
96 elif hours<1:
97 sHours="00"
98
99 if str(hours).find(".")==-1:
100 mins=float(hours)*60.0
101 else:
102 mins=float(str(hours)[str(hours).index("."):])*60.0
103 if mins<10 and mins>=1:
104 sMins="0"+str(mins)[:1]
105 elif mins>=10:
106 sMins=str(mins)[:2]
107 elif mins<1:
108 sMins="00"
109
110 secs=(hours-(float(sHours)+float(sMins)/60.0))*3600.0
111 if secs<10 and secs>0.001:
112 sSecs="0"+str(secs)[:str(secs).find(".")+4]
113 elif secs<0.0001:
114 sSecs="00.001"
115 else:
116 sSecs=str(secs)[:str(secs).find(".")+4]
117 if len(sSecs)<5:
118 sSecs=sSecs+"00"
119
120 if float(sSecs) == 60.000:
121 sSecs="00.00"
122 sMins=str(int(sMins)+1)
123 if int(sMins) == 60:
124 sMins="00"
125 sDeg=str(int(sDeg)+1)
126
127 return sHours+delimiter+sMins+delimiter+sSecs
128
129
131 """Converts decimal degrees to string in Degrees:Minutes:Seconds format with user specified
132 delimiter.
133
134 @type decDeg: float
135 @param decDeg: coordinate in decimal degrees
136 @type delimiter: string
137 @param delimiter: delimiter character in returned string
138 @rtype: string
139 @return: coordinate string in D:M:S format
140
141 """
142
143 if decDeg>0:
144 if decDeg<10 and decDeg>=1:
145 sDeg="0"+str(decDeg)[0]
146 elif decDeg>=10:
147 sDeg=str(decDeg)[:2]
148 elif decDeg<1:
149 sDeg="00"
150
151 if str(decDeg).find(".")==-1:
152 mins=float(decDeg)*60.0
153 else:
154 mins=float(str(decDeg)[str(decDeg).index("."):])*60
155 if mins<10 and mins>=1:
156 sMins="0"+str(mins)[:1]
157 elif mins>=10:
158 sMins=str(mins)[:2]
159 elif mins<1:
160 sMins="00"
161
162 secs=(decDeg-(float(sDeg)+float(sMins)/60.0))*3600.0
163 if secs<10 and secs>0:
164 sSecs="0"+str(secs)[:str(secs).find(".")+3]
165 elif secs<0.001:
166 sSecs="00.00"
167 else:
168 sSecs=str(secs)[:str(secs).find(".")+3]
169 if len(sSecs)<5:
170 sSecs=sSecs+"0"
171
172 if float(sSecs) == 60.00:
173 sSecs="00.00"
174 sMins=str(int(sMins)+1)
175 if int(sMins) == 60:
176 sMins="00"
177 sDeg=str(int(sDeg)+1)
178
179 return "+"+sDeg+delimiter+sMins+delimiter+sSecs
180
181 else:
182 if decDeg>-10 and decDeg<=-1:
183 sDeg="-0"+str(decDeg)[1]
184 elif decDeg<=-10:
185 sDeg=str(decDeg)[:3]
186 elif decDeg>-1:
187 sDeg="-00"
188
189 if str(decDeg).find(".")==-1:
190 mins=float(decDeg)*-60.0
191 else:
192 mins=float(str(decDeg)[str(decDeg).index("."):])*60
193 if mins<10 and mins>=1:
194 sMins="0"+str(mins)[:1]
195 elif mins>=10:
196 sMins=str(mins)[:2]
197 elif mins<1:
198 sMins="00"
199
200 secs=(decDeg-(float(sDeg)-float(sMins)/60.0))*3600.0
201 if secs>-10 and secs<0:
202 sSecs="0"+str(secs)[1:str(secs).find(".")+3]
203 elif secs>-0.001:
204 sSecs="00.00"
205 else:
206 sSecs=str(secs)[1:str(secs).find(".")+3]
207 if len(sSecs)<5:
208 sSecs=sSecs+"0"
209
210 if float(sSecs) == 60.00:
211 sSecs="00.00"
212 sMins=str(int(sMins)+1)
213 if int(sMins) == 60:
214 sMins="00"
215 sDeg=str(int(sDeg)-1)
216
217 return sDeg+delimiter+sMins+delimiter+sSecs
218
219
221 """Calculates the angular separation of two positions on the sky (specified in decimal
222 degrees) in decimal degrees, assuming a tangent plane projection (so separation has to be
223 <90 deg).
224
225 @type RADeg1: float
226 @param RADeg1: R.A. in decimal degrees for position 1
227 @type decDeg1: float
228 @param decDeg1: dec. in decimal degrees for position 1
229 @type RADeg2: float
230 @param RADeg2: R.A. in decimal degrees for position 2
231 @type decDeg2: float
232 @param decDeg2: dec. in decimal degrees for position 2
233 @rtype: float
234 @return: angular separation in decimal degrees
235
236 """
237 cRA=math.radians(float(RADeg1))
238 cDec=math.radians(float(decDeg1))
239
240 gRA=math.radians(float(RADeg2))
241 gDec=math.radians(float(decDeg2))
242
243 dRA=cRA-gRA
244 dDec=gDec-cDec
245 cosC=(math.sin(gDec)*math.sin(cDec))+(math.cos(gDec)*math.cos(cDec)*math.cos(gRA-cRA))
246 x=(math.cos(cDec)*math.sin(gRA-cRA))/cosC
247 y=((math.cos(gDec)*math.sin(cDec))-(math.sin(gDec)*math.cos(cDec)*math.cos(gRA-cRA)))/cosC
248 r=math.degrees(math.sqrt(x*x+y*y))
249
250 return r
251
252
253 -def convertCoords(inputSystem, outputSystem, coordX, coordY, epoch):
254 """Converts specified coordinates (given in decimal degrees) between J2000, B1950, and
255 Galactic.
256
257 @type inputSystem: string
258 @param inputSystem: system of the input coordinates (either "J2000", "B1950" or "GALACTIC")
259 @type outputSystem: string
260 @param outputSystem: system of the returned coordinates (either "J2000", "B1950" or
261 "GALACTIC")
262 @type coordX: float
263 @param coordX: longitude coordinate in decimal degrees, e.g. R. A.
264 @type coordY: float
265 @param coordY: latitude coordinate in decimal degrees, e.g. dec.
266 @type epoch: float
267 @param epoch: epoch of the input coordinates
268 @rtype: list
269 @return: coordinates in decimal degrees in requested output system
270
271
272 """
273
274 if inputSystem=="J2000" or inputSystem=="B1950" or inputSystem=="GALACTIC":
275 if outputSystem=="J2000" or outputSystem=="B1950" or outputSystem=="GALACTIC":
276
277 outCoords=wcscon.wcscon(wcscon.wcscsys(inputSystem),
278 wcscon.wcscsys(outputSystem), 0, 0, coordX, coordY, epoch)
279
280 return outCoords
281
282 raise Exception, "inputSystem and outputSystem must be 'J2000', 'B1950' or 'GALACTIC'"
283
284
285