Repository navigation
Closed
Description
Description
A colleague has data from a telescope that just points at the zenith and records the data that it sees along with the time. He asked me how he could find the ICRS coordinates that this telescope was seeing as a function of time. I gave him an example script that I thought should do this, but it failed. Perhaps I'm just doing something wrong here, but I couldn't see anything in the documentation that said that this can't be done.
Expected behavior
I expected an array of ICRS positions in RA/Dec.
Actual behavior
It bombed. The only way I could get it to work was to create arrays of alt and az with the same dimension as obstime.
Steps to Reproduce
Here's the script.
import numpy as np
from astropy.time import Time
from astropy.coordinates import EarthLocation, AltAz, ICRS
import astropy.units as u
jd = 2459205.5 + np.arange(0.0, 1.0, 0.1)
my_times = Time(jd, format='jd')
print (my_times)
class_lat = -22.959748*u.deg
class_lon = -67.787260*u.deg
class_elev= 5186*u.m
class_loc = EarthLocation.from_geodetic(class_lon,class_lat,class_elev)
aa = AltAz(az=0.0 * u.deg, alt=90.0 * u.deg, obstime=my_times, location=class_loc)
radec = aa.transform_to(ICRS)
print (radec)
And here's the output.
[2459205.5 2459205.6 2459205.7 2459205.8 2459205.9 2459206. 2459206.1
2459206.2 2459206.3 2459206.4]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/attributes.py in __get__(self, instance, frame_cls)
111 out = out._apply(np.broadcast_to, shape=instance_shape,
--> 112 subok=True)
113 else:~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/time/core.py in _apply(self, method, format, cls, *args, **kwargs)
1055 if apply_method:
-> 1056 jd1 = apply_method(jd1)
1057 jd2 = apply_method(jd2)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/time/core.py in <lambda>(array)
1045 if callable(method):
-> 1046 apply_method = lambda array: method(array, *args, **kwargs)
1047 <__array_function__ internals> in broadcast_to(*args, **kwargs)~/anaconda3/envs/hera/lib/python3.7/site-packages/numpy/lib/stride_tricks.py in broadcast_to(array, shape, subok)
179 """
--> 180 return _broadcast_to(array, shape, subok=subok, readonly=True)
181 ~/anaconda3/envs/hera/lib/python3.7/site-packages/numpy/lib/stride_tricks.py in _broadcast_to(array, shape, subok, readonly)
117 if not shape and array.shape:
--> 118 raise ValueError('cannot broadcast a non-scalar to a scalar array')
119 if any(size < 0 for size in shape):ValueError: cannot broadcast a non-scalar to a scalar arrayDuring handling of the above exception, another exception occurred:ValueError Traceback (most recent call last)
<ipython-input-6-3711448b41bf> in <module>
13 class_loc = EarthLocation.from_geodetic(class_lon,class_lat,class_elev)
14
---> 15 aa = AltAz(az=0.0 * u.deg, alt=90.0 * u.deg, obstime=my_times, location=class_loc)
16 radec = aa.transform_to(ICRS)
17 print (radec)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/builtin_frames/altaz.py in __init__(self, *args, **kwargs)
105
106 def __init__(self, *args, **kwargs):
--> 107 super().__init__(*args, **kwargs)
108
109 @property~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/baseframe.py in __init__(self, copy, representation_type, differential_type, *args, **kwargs)
599 # Validate attribute b
[2459205.5 2459205.6 2459205.7 2459205.8 2459205.9 2459206. 2459206.1
2459206.2 2459206.3 2459206.4]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/attributes.py in __get__(self, instance, frame_cls)
111 out = out._apply(np.broadcast_to, shape=instance_shape,
--> 112 subok=T
[2459205.5 2459205.6 2459205.7 2459205.8 2459205.9 2459206. 2459206.1
2459206.2 2459206.3 2459206.4]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/attributes.py in __get__(self, instance, frame_cls)
111 out = out._apply(np.broadcast_to, shape=instance_shape,
--> 112 subok=True)
113 else:~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/time/core.py in _apply(self, method, format, cls, *args, **kwargs)
1055 if apply_method:
-> 1056 jd1 = apply_method(jd1)
1057 jd2 = apply_method(jd2)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/time/core.py in <lambda>(array)
1045 if callable(method):
-> 1046 apply_method = lambda array: method(array, *args, **kwargs)
1047 <__array_function__ internals> in broadcast_to(*args, **kwargs)~/anaconda3/envs/hera/lib/python3.7/site-packages/numpy/lib/stride_tricks.py in broadcast_to(array, shape, subok)
179 """
--> 180 return _broadcast_to(array, shape, subok=subok, readonly=True)
181 ~/anaconda3/envs/hera/lib/python3.7/site-packages/numpy/lib/stride_tricks.py in _broadcast_to(array, shape, subok, readonly)
117 if not shape and array.shape:
--> 118 raise ValueError('cannot broadcast a non-scalar to a scalar array')
119 if any(size < 0 for size in shape):ValueError: cannot broadcast a non-scalar to a scalar arrayDuring handling of the above exception, another exception occurred:ValueError Traceback (most recent call last)
<ipython-input-6-3711448b41bf> in <module>
13 class_loc = EarthLocation.from_geodetic(class_lon,class_lat,class_elev)
14
---> 15 aa = AltAz(az=0.0 * u.deg, alt=90.0 * u.deg, obstime=my_times, location=class_loc)
16 radec = aa.transform_to(ICRS)
17 print (radec)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/builtin_frames/altaz.py in __init__(self, *args, **kwargs)
105
106 def __init__(self, *args, **kwargs):
--> 107 super().__init__(*args, **kwargs)
108
109 @property~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/baseframe.py in __init__(self, copy, representation_type, differential_type, *args, **kwargs)
599 # Validate attribute by getting it. If the instance has data,
600 # this also checks its shape is OK. If not, we do it below.
--> 601 values[fnm] = getattr(self, fnm)
602 else:
603 setattr(self, '_' + fnm, fdefault)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/attributes.py in __get__(self, instance, frame_cls)
118 "attribute {} should be scalar or have shape {}, "
119 "but is has shape {} and could not be broadcast."
--> 120 .format(self.name, instance_shape, out.shape))
121
122 converted = TrueValueError: attribute obstime should be scalar or have shape (), but is has shape (10,) and could not be broadcast. rue)
113 else:~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/time/core.py in _apply(self, method, format, cls, *args, **kwargs)
1055 if apply_method:
-> 1056 jd1 = apply_method(jd1)
1057 jd2 = apply_method(jd2)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/time/core.py in <lambda>(array)
1045 if callable(method):
-> 1046 apply_method = lambda array: method(array, *args, **kwargs)
1047 <__array_function__ internals> in broadcast_to(*args, **kwargs)~/anaconda3/envs/hera/lib/python3.7/site-packages/numpy/lib/stride_tricks.py in broadcast_to(array, shape, subok)
179 """
--> 180 return _broadcast_to(array, shape, subok=subok, readonly=True)
181 ~/anaconda3/envs/hera/lib/python3.7/site-packages/numpy/lib/stride_tricks.py in _broadcast_to(array, shape, subok, readonly)
117 if not shape and array.shape:
--> 118 raise ValueError('cannot broadcast a non-scalar to a scalar array')
119 if any(size < 0 for size in shape):ValueError: cannot broadcast a non-scalar to a scalar arrayDuring handling of the above exception, another exception occurred:ValueError Traceback (most recent call last)
<ipython-input-6-3711448b41bf> in <module>
13 class_loc = EarthLocation.from_geodetic(class_lon,class_lat,class_elev)
14
---> 15 aa = AltAz(az=0.0 * u.deg, alt=90.0 * u.deg, obstime=my_times, location=class_loc)
16 radec = aa.transform_to(ICRS)
17 print (radec)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/builtin_frames/altaz.py in __init__(self, *args, **kwargs)
105
106 def __init__(self, *args, **kwargs):
--> 107 super().__init__(*args, **kwargs)
108
109 @property~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/baseframe.py in __init__(self, copy, representation_type, differential_type, *args, **kwargs)
599 # Validate attribute by getting it. If the instance has data,
600 # this also checks its shape is OK. If not, we do it below.
--> 601 values[fnm] = getattr(self, fnm)
602 else:
603 setattr(self, '_' + fnm, fdefault)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/attributes.py in __get__(self, instance, frame_cls)
118 "attribute {} should be scalar or have shape {}, "
119 "but is has shape {} and could not be broadcast."
--> 120 .format(self.name, instance_shape, out.shape))
121
122 converted = TrueValueError: attribute obstime should be scalar or have shape (), but is has shape (10,) and could not be broadcast. y getting it. If the instance has data,
600 # this also checks its shape is OK. If not, we do it below.
--> 601 values[fnm] = getattr(self, fnm)
602 else:
603 setattr(self, '_' + fnm, fdefault)~/anaconda3/envs/hera/lib/python3.7/site-packages/astropy/coordinates/attributes.py in __get__(self, instance, frame_cls)
118 "attribute {} should be scalar or have shape {}, "
119 "but is has shape {} and could not be broadcast."
--> 120 .format(self.name, instance_shape, out.shape))
121
122 converted = TrueValueError: attribute obstime should be scalar or have shape (), but is has shape (10,) and could not be broadcast.
System Details
Astropy 4.2
Activity
[-]Can't create an AltAz frame with a fixed set of scalar coordinates and an array on obstimes.[/-][+]Can't create an AltAz frame with a fixed set of scalar coordinates and an array of obstimes.[/+]pllim commentedon Dec 22, 2020
There is an example in https://docs.astropy.org/en/latest/coordinates/index.html#id4 but looks like it is doing the opposite of what you are trying to do? A workaround is to broadcast your
azandaltto the shape ofmy_timesbefore trying to createaa.But then
aa.transform_to(ICRS)will emit this warning:@adrn , perhaps you can advise? Thanks!
adrn commentedon Dec 22, 2020
The warning is expected and a result of #10475 - that line just needs to be changed to
aa.transform_to(ICRS()).On the specific issue here, while it's hard to make broadcasting assumptions when both the coordinate data and the obstime have arbitrary shapes, in this case (with scalar coordinate data) I think it is unambiguous, so I think this is a bug and we should support it! Thoughts @mhvk?
mkbrewer commentedon Dec 22, 2020
Yes. As I stated under "Actual behavior", that's what I had to do to get this to work.
I raised this issue as it is my understanding that Astropy should be able to evaluate a single position at multiple times. Perhaps that is a misunderstanding on my part, but I was unable to find anything in the documentation that stated otherwise.
mhvk commentedon Dec 22, 2020
I agree we should support this. Why we do not is to be honest a bit lost in the mists of time - I think it mostly boils down to having to be careful what exactly defines the shape of a coordinate (or
Timefor that matter): is it the actual representation/time, or a combination with the shapes of all the attributes? I guess we are now finding out it should be the latter (or perhaps more specifically, that any actual representation data should be broadcast as needed). I think it can be done, though needs quite a bit of care and some good test cases...p.s. This is something we have already worked around before, suggesting even more that we might as well generalize that. E.g., in
EarthLocation.get_itrs():astropy/astropy/coordinates/earth.py
Lines 648 to 651 in 9c79f08
mhvk commentedon Dec 22, 2020
p.s. Classified this as medium effort to get everything done. But I think just ensuring that input longitude and latitude get broadcast on input - which would solve the specific issue raised here - should be relatively little effort, just change the check in the initializer to a broadcast + copy as needed. The main effort would in writing tests...
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes
Broadcast frames over both data and attributes (#15121)