-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobscode.py
144 lines (121 loc) · 3.55 KB
/
obscode.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python3
"""
Function read5c loads file obscode.dat. Currently supported is the current
style 5 column obscode.dat format, the format currently publicly accessible at
http://www.minorplanetcenter.net/iau/lists/ObsCodes.html.
The higher lever function siteXYZ is designed to take the output of read5c,
but should be general enough to also take output of a reader of the new
obscode.dat format.
"""
import collections
import math
__all__ = ['Site5c', 'read5c', 'siteXYZ']
Site5c = collections.namedtuple('Site5c', [
'blank', # bool: True if the parallax data is completely blank
'long', # float: parallax constant: east longitude of observatory in deg
'rcos', # float: parallax constant: ρ cos φ′
'rsin', # float: parallax constant: ρ sin φ′
'site', # string: site name
])
"""named tuple with fields for the five columns of obscode.dat
Parameters
----------
blank : bool
True if the parallax data is completely blank
long : float
parallax constant: east longitude of observatory in degrees
rcos : float
parallax constant: ρ cos φ′
rsin : float
parallax constant: ρ sin φ′
site : string
site name
"""
def parseLine(line):
"""
Parses a single line of obscode.dat.
Parameters
----------
line : str
A line of at least 30 characters. A line is valid if all three
parallax constants (long, rcos, and rsin) parse or if all three are
blank.
Returns
-------
Site5c
Site5c object for valid lines, None otherwise.
"""
pc = line[4:30]
blank = pc.isspace()
if blank:
long, rcos, rsin = 0., 0., 0.
else:
try:
long = float(pc[:9])
rcos = float(pc[9:17])
rsin = float(pc[17:])
except ValueError:
return None # invalid line
return Site5c(
blank=blank,
long=long,
rcos=rcos,
rsin=rsin,
site=line[30:].strip()
)
def read5c(fn='obscode.dat'):
"""
reads a file current style (5-column) obscode.dat into a dictionary.
This is the format currently publicly accessible at
http://www.minorplanetcenter.net/iau/lists/ObsCodes.html.
Parameters
----------
fn : string
filename to read, default is obscode.dat
Returns
-------
dictionary
Keys are the 3-character obscode strings, values are Site5c named tuples
of the parsed data.
Examples
--------
>>> sites = read5c('obscode.dat')
>>> sites['G96'].site
'Mt. Lemmon Survey'
"""
with open(fn) as f:
sites = {}
for line in f:
s = parseLine(line)
if s:
sites[line[:3]] = s
return sites
def siteXYZ(sites):
"""
computes geocentric site coordinates from parallax constants.
Parameters
----------
sites : dictionary
Typically the value returned from read5c. Keys are obscodes and values
must have attributes blank, rcos, rsin, and long.
Returns
-------
dictionary
Keys are the keys of the sites parameter, values are 3-tuples floats,
the geocentric coordinates, where blank = False and the 3-tuple
(None, None, None) where blank = True.
"""
ObservatoryXYZ = {}
for code, s in sites.items():
if not s.blank:
longitude = s.long * math.pi / 180
x = s.rcos * math.cos(longitude)
y = s.rcos * math.sin(longitude)
z = s.rsin
ObservatoryXYZ[code] = (x, y, z)
else:
ObservatoryXYZ[code] = (None, None, None)
return ObservatoryXYZ
if __name__ == '__main__':
import doctest
doctest.testmod()