Skip to content

Can't create an AltAz frame with a fixed set of scalar coordinates and an array of obstimes. #11184

Closed

Description

@mkbrewer

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

  1. changed the title [-]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.[/+] on Dec 22, 2020
  2. pllim commented on Dec 22, 2020

    @pllim
    Member

    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 az and alt to the shape of my_times before trying to create aa.

    But then aa.transform_to(ICRS) will emit this warning:

    >>> aa.transform_to(ICRS)
    WARNING: AstropyDeprecationWarning: Transforming a frame instance to a frame class
    (as opposed to another frame instance) will not be supported in the future.
    Either explicitly instantiate the target frame, or first convert the source frame instance
    to a `astropy.coordinates.SkyCoord` and use its `transform_to()` method. [astropy.coordinates.baseframe]
    <ICRS Coordinate: (ra, dec) in deg
        [( 22.97205326, -23.06338212), ( 59.09045025, -23.01758926),
         ( 95.19478126, -22.94953892), (131.28290687, -22.8853718 ),
         (167.35889687, -22.84971288), (203.43138332, -22.8562365 ),
         (239.51030282, -22.90244092), (275.60315014, -22.9706063 ),
         (311.712296  , -23.03455409), (347.83364631, -23.06971796)]>

    @adrn , perhaps you can advise? Thanks!

  3. adrn commented on Dec 22, 2020

    @adrn
    Member

    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?

  4. mkbrewer commented on Dec 22, 2020

    @mkbrewer
    ContributorAuthor

    Yes. As I stated under "Actual behavior", that's what I had to do to get this to work.

    az = np.zeros(len(jd))
    alt = np.ones(len(jd)) * 90.0
    aa = AltAz(az=az * u.deg, alt=alt * u.deg, obstime=my_times, location=class_loc)
    

    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.

  5. mhvk commented on Dec 22, 2020

    @mhvk
    Contributor

    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 Time for 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():

    # Broadcast for a single position at multiple times, but don't attempt
    # to be more general here.
    if obstime and self.size == 1 and obstime.shape:
    self = np.broadcast_to(self, obstime.shape, subok=True)

  6. mhvk commented on Dec 22, 2020

    @mhvk
    Contributor

    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...

  7. added 5 commits that reference this issue on Aug 3, 2023
    3797b5b
    ba38c2e
    aa1989c
    1d45f88
    37cfed6
  8. added 5 commits that reference this issue on Aug 18, 2023
    99035b2
    9081d6a
    2f04b20
    7b82928
    5d84c35
  9. added 3 commits that reference this issue on Sep 30, 2023
    b19fb2a
    1f3a2b6
    33cca6f
  10. added a commit that references this issue on Oct 3, 2023
    00e64a9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions