Skip to content

Commit 0030ce4

Browse files
Light travel time can be almost unchanged; see #526
The light travel time routine can survive almost unchanged if instead of expecting NumPy broadcasting to make up for extra missing dimensions, we add an extra dimension to the observer’s position before calling, to avoid NumPy needing to do its own back-to-front dimension matching.
1 parent c8db673 commit 0030ce4

File tree

1 file changed

+101
-4
lines changed

1 file changed

+101
-4
lines changed

design/broadcasting.py

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ def main():
88

99
cfltt = _correct_for_light_travel_time # the original
1010
#cfltt = _correct_for_light_travel_time2 # possible replacement
11+
fcfltt = _correct_for_light_travel_time4 # possible replacement
1112

1213
print('==== One time, one observer, one target ====')
1314

@@ -42,15 +43,16 @@ def main():
4243
# Turn Earth into two observation positions.
4344
earth = planets['earth']
4445
earth._at = build_multi_at(earth._at)
46+
4547
observer = earth.at(t)
4648
print('observer', observer.position.au.shape)
4749

4850
target = planets['mars']
4951
target._at = build_multi_at(target._at) # Turn Mars into 2 planets.
5052
print('target', target.at(t).position.au.shape)
5153

52-
t = ts.tt(t.tt[:,None]) # What if we add a dimension to t?
53-
print('t', t.shape)
54+
# t = ts.tt(t.tt[:,None]) # What if we add a dimension to t?
55+
# print('t', t.shape)
5456

5557
r, v, t2, light_time = _correct_for_light_travel_time2(observer, target)
5658
print(t.shape, observer.position.km.shape, '->', r.shape)
@@ -78,8 +80,8 @@ def main():
7880
target._at = build_multi_at(target._at) # Turn Mars into 2 planets.
7981
print('target', target.at(t).position.au.shape)
8082

81-
t = ts.tt(t.tt[:,None]) # What if we add a dimension to t?
82-
print('t', t.shape)
83+
# t = ts.tt(t.tt[:,None]) # What if we add a dimension to t?
84+
# print('t', t.shape)
8385

8486
r, v, t2, light_time = _correct_for_light_travel_time3(observer, target)
8587
print(t.shape, observer.position.km.shape, '->', r.shape)
@@ -90,6 +92,52 @@ def main():
9092
print('Second planet:')
9193
print(r[:,:,1])
9294

95+
# Okay, so, the whole problem of broadcasting: is the only reason it
96+
# comes up because we have more targets than observers? What if we
97+
# ask folks to expand the observers array dimensions as well, so
98+
# that NumPy is never faced with arrays of different numbers of
99+
# dimensions, which is what triggers its unfortunate decision to
100+
# start matching at the ends of the arrays instead of their
101+
# beginnings?
102+
103+
print('==== N times, one observers, M targets'
104+
' [TRY: EXTRA OBSERVER DIMENSION] ====')
105+
106+
# So: time has its usual extra dimension to accommodate 4 times.
107+
t = ts.utc(2021, 2, 19, 13, [46, 47, 48, 49])
108+
planets = load('de421.bsp')
109+
110+
earth = planets['earth']
111+
observer = earth.at(t)
112+
print('observer', observer.position.au.shape)
113+
print('Supplementing dimensions')
114+
observer.position.au = observer.position.au[:,:,None]
115+
observer.velocity.au_per_d = observer.velocity.au_per_d[:,:,None]
116+
print('observer', observer.position.au.shape)
117+
118+
target = planets['mars']
119+
target._at = build_multi_at(target._at) # Turn Mars into 2 planets.
120+
print('target', target.at(t).position.au.shape)
121+
122+
# TODO: if we work out how we can expand the time's dimensions, as
123+
# in the following line, before earth.at(t) without raising an
124+
# exception, then the observer time would not be lacking a dimension
125+
# that would need to be expanded in
126+
127+
t = ts.tt(t.tt[:,None]) # What if we add a dimension to t?
128+
# print('t !!!!!!!!!!!!!!', t.shape)
129+
# print('t !!!!!!!!!!!!!!', t.whole.shape)
130+
# print('t !!!!!!!!!!!!!!', t.tdb_fraction.shape)
131+
132+
r, v, t2, light_time = _correct_for_light_travel_time4(observer, target)
133+
print(t.shape, observer.position.au.shape, '->', r.shape)
134+
135+
print('Does it look like a second planet 1 AU away at the same 4 times?')
136+
print('First planet:')
137+
print(r[:,:,0])
138+
print('Second planet:')
139+
print(r[:,:,1])
140+
93141
offset = array([0, 1])[None,None,:] # Dimensions: [xyz, time, offset]
94142

95143
def build_multi_at(_at):
@@ -262,6 +310,55 @@ def _correct_for_light_travel_time3(observer, target):
262310
tvelocity = tvelocity - cvelocity
263311
return tposition.T, tvelocity.T, t, light_time
264312

313+
# What if the observer had an extra dimension so it matches too?
314+
315+
def _correct_for_light_travel_time4(observer, target):
316+
"""Return a light-time corrected astrometric position and velocity.
317+
318+
Given an `observer` that is a `Barycentric` position somewhere in
319+
the solar system, compute where in the sky they will see the body
320+
`target`, by computing the light-time between them and figuring out
321+
where `target` was back when the light was leaving it that is now
322+
reaching the eyes or instruments of the `observer`.
323+
324+
"""
325+
t = observer.t
326+
ts = t.ts
327+
whole = t.whole
328+
tdb_fraction = t.tdb_fraction
329+
330+
cposition = observer.position.au
331+
cvelocity = observer.velocity.au_per_d
332+
333+
print('======', cposition.shape)
334+
# ?
335+
print('tdb_fraction before:', tdb_fraction.shape)
336+
tdb_fraction = tdb_fraction[:,None]
337+
print('tdb_fraction after:', tdb_fraction.shape)
338+
339+
tposition, tvelocity, gcrs_position, message = target._at(t)
340+
341+
distance = length_of(tposition - cposition)
342+
light_time0 = 0.0
343+
for i in range(10):
344+
print('i =', i)
345+
light_time = distance / C_AUDAY
346+
delta = light_time - light_time0
347+
if abs(max(delta)) < 1e-12:
348+
break
349+
350+
# We assume a light travel time of at most a couple of days. A
351+
# longer light travel time would best be split into a whole and
352+
# fraction, for adding to the whole and fraction of TDB.
353+
t2 = ts.tdb_jd(whole, tdb_fraction - light_time)
354+
355+
tposition, tvelocity, gcrs_position, message = target._at(t2)
356+
distance = length_of(tposition - cposition)
357+
light_time0 = light_time
358+
else:
359+
raise ValueError('light-travel time failed to converge')
360+
return tposition - cposition, tvelocity - cvelocity, t, light_time
361+
265362
_reconcile # So CI will think we used it, whether use above is commented or not
266363

267364
if __name__ == '__main__':

0 commit comments

Comments
 (0)