-
Notifications
You must be signed in to change notification settings - Fork 1
/
observer_sees_planets.py
213 lines (160 loc) · 6.82 KB
/
observer_sees_planets.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#
# Generates the positions of planets as seen from the Earth
#
# Allows us to label planets in the LASCO C2, C3 field of view
# for example, 2000/05/15 11:18
# See http://sci.esa.int/soho/18976-lasco-c3-image-showing-the-positions-of-the-planets/
#
#
import json
import os
from copy import deepcopy
import numpy as np
from astropy.coordinates import get_body
from astropy.time import Time
import astropy.units as u
from sunpy.coordinates import frames
# Where to store the data
directory = os.path.expanduser('~/hvp/hvorgobjects/output/json')
# Bodies
body_names = ('mercury', 'saturn', 'jupiter', 'venus')
# Days we want to calculate positions for
# transit_of_venus_2012 = Time('2012-06-05 00:00:00')
# n_days = 2
#multiple_planets = Time('2000-05-01 00:00:00')
#n_days = 28
try_a_year = Time('2000-01-01 00:00:00')
n_days = 365
# Which times?
initial_time = try_a_year
# Time step
dt = 30*u.minute
# duration
duration = 1 * u.day
# Where are we looking from - the observer
observer_name = 'earth'
# Write a file only when the bisy has an angular separation from the Sun
# less than the maximum below
maximum_angular_separation = 10 * u.deg
# Format the output time as requested.
def format_time_output(t):
"""
Format the time output.
Parameters
----------
t : `~astropy.time.Time`
The time that is to be formatted.
Returns
-------
format_time_output
The input time in the requested format.
"""
# Returns as an integer number of seconds
return int(np.rint(t.unix * 1000))
def file_name_format(observer_name, body_name, t, file_type='json'):
"""
The file name format that has been decided upon for the output.
Parameters
----------
observer_name : `~str`
The name of the observer.
body_name : `~str`
The body that is observed.
t : `~astropy.time.Time`
A time that signifies the time range of information in the file.
file_type : '~str`
The file type that will be written.
Returns
-------
file_name_format
The filename in the requested format
"""
tc = deepcopy(t)
tc.out_subfmt = 'date'
return '{:s}_{:s}_{:s}.{:s}'.format(observer_name, body_name, str(tc), file_type)
def distance_format(d, scale=1*u.au):
"""
Returns the distances in the requested format
Parameters
----------
d : `~astropy.unit`
A distance in units convertible to kilometers.
scale : `~astropy.unit`
The scale the input unit is measured in.
Returns
-------
distance_format : `~float`
A floating point number that is implicitly measured in the input scale.
"""
return (d / scale).decompose().value
# Go through each of the bodies
for body_name in body_names:
# Pick the next start time
for n in range(0, n_days):
start_time = initial_time + n*u.day
# Reset the positions directory for the new start time
positions = dict()
positions[observer_name] = dict()
positions[observer_name][body_name] = dict()
# Reset the counter to the new start time
t = start_time
# Information to screen
print('Body = {:s}, day = {:s}'.format(body_name, str(t)))
# If True, then the day contains at least one
# valid position
save_file_for_this_duration = False
# Calculate the positions in the duration
while t - start_time < duration:
# The location of the observer
earth_location = get_body('earth', t).transform_to(frames.HeliographicStonyhurst)
# Shift the observer out to 1 AU
observer_location = SkyCoord(lon=earth_location.lon,
lat=earth_location.lat,
radius= 1*u.au,
obstime=t,
frame=frames.HeliographicStonyhurst)
# The location of the body
this_body = get_body(body_name, t)
# The position of the body as seen from the observer location
position = this_body.transform_to(observer_location)
# Transform to Helioprojective
position = position.transform_to(frames.Helioprojective)
# Position of the Sun as seen by the observer
sun_position = get_body('sun', t).transform_to(observer_location)
# Angular distance of the body from the Sun
angular_separation = sun_position.separation(position)
# We only want to write out data when the body is close
# to the Sun. This will reduce the number and size of
# files that we have to store.
if np.abs(angular_separation) <= maximum_angular_separation:
# Valid position, so set the flag
save_file_for_this_duration = True
# Information to screen
print('Body = {:s}, angular separation = {:s} degrees'.format(body_name, str(angular_separation.value)))
# time index is unix time stamp in milliseconds - cast to ints
t_index = format_time_output(t)
positions[observer_name][body_name][t_index] = dict()
# store the positions of the
positions[observer_name][body_name][t_index]["x"] = position.Tx.value
positions[observer_name][body_name][t_index]["y"] = position.Ty.value
# location of the body in HCC
body_hcc = this_body.transform_to(frames.Heliocentric)
# location of the observer in HCC
observer_hcc = observer_location.transform_to(frames.Heliocentric)
# Distance from the observer to the body
distance_observer_to_body = np.sqrt((body_hcc.x - observer_hcc.x)**2 + (body_hcc.y - observer_hcc.y)**2 + (body_hcc.z - observer_hcc.z)**2)
positions[observer_name][body_name][t_index]["distance_observer_to_body_au"] = distance_format(distance_observer_to_body)
# Distance of the body from the Sun
distance_body_to_sun = np.sqrt(body_hcc.x**2 + body_hcc.y**2 + body_hcc.z**2)
positions[observer_name][body_name][t_index]["distance_body_to_sun_au"] = distance_format(distance_body_to_sun)
# Is the body behind the plane of the Sun?
positions[observer_name][body_name][t_index]["behind_plane_of_sun"] = str(body_hcc.z.value < 0)
# Move the counter forward
t += dt
# Open the JSON file and dump out the positional information
# if valid information was generated
if save_file_for_this_duration:
file_path = os.path.join(directory, file_name_format(observer_name, body_name, start_time))
f = open(file_path, 'w')
json.dump(positions, f)
f.close()