@@ -32,9 +32,22 @@ def cirs_to_altaz(cirs_coo, altaz_frame):
3232 # we use the same obstime everywhere now that we know they're the same
3333 obstime = cirs_coo .obstime
3434
35- usrepr = cirs_coo .represent_as (UnitSphericalRepresentation )
36- cirs_ra = usrepr .lon .to (u .radian ).value
37- cirs_dec = usrepr .lat .to (u .radian ).value
35+ # if the data are UnitSphericalRepresentation, we can skip the distance calculations
36+ is_unitspherical = (isinstance (cirs_coo .data , UnitSphericalRepresentation ) or
37+ cirs_coo .cartesian .x .unit == u .one )
38+
39+ if is_unitspherical :
40+ usrepr = cirs_coo .represent_as (UnitSphericalRepresentation )
41+ cirs_ra = usrepr .lon .to (u .radian ).value
42+ cirs_dec = usrepr .lat .to (u .radian ).value
43+ else :
44+ # compute an "astrometric" ra/dec -i.e., the direction of the
45+ # displacement vector from the observer to the target in CIRS
46+ loccirs = altaz_frame .location .get_itrs (cirs_coo .obstime ).transform_to (cirs_coo )
47+ diffrepr = (cirs_coo .cartesian - loccirs .cartesian ).represent_as (UnitSphericalRepresentation )
48+
49+ cirs_ra = diffrepr .lon .to (u .radian ).value
50+ cirs_dec = diffrepr .lat .to (u .radian ).value
3851
3952 lon , lat , height = altaz_frame .location .to_geodetic ('WGS84' )
4053 xp , yp = get_polar_motion (obstime )
@@ -52,10 +65,9 @@ def cirs_to_altaz(cirs_coo, altaz_frame):
5265 altaz_frame .relative_humidity ,
5366 altaz_frame .obswl .value )
5467
55- az , zen , ha , obs_dec , obs_ra = erfa .atioq (cirs_ra , cirs_dec , astrom )
68+ az , zen , _ , _ , _ = erfa .atioq (cirs_ra , cirs_dec , astrom )
5669
57- dat = cirs_coo .data
58- if dat .get_name () == 'unitspherical' or dat .to_cartesian ().x .unit == u .one :
70+ if is_unitspherical :
5971 rep = UnitSphericalRepresentation (lat = u .Quantity (PIOVER2 - zen , u .radian , copy = False ),
6072 lon = u .Quantity (az , u .radian , copy = False ),
6173 copy = False )
@@ -95,32 +107,23 @@ def altaz_to_cirs(altaz_coo, cirs_frame):
95107
96108 # the 'A' indicates zen/az inputs
97109 cirs_ra , cirs_dec = erfa .atoiq ('A' , az , zen , astrom )* u .radian
98-
99- if isinstance ( altaz_coo . data , UnitSphericalRepresentation ):
100- distance = None
110+ if isinstance ( altaz_coo . data , UnitSphericalRepresentation ) or altaz_coo . cartesian . x . unit == u . one :
111+ cirs_at_aa_time = CIRS ( ra = cirs_ra , dec = cirs_dec , distance = None ,
112+ obstime = altaz_coo . obstime )
101113 else :
102- locitrs = altaz_coo .location .get_itrs (altaz_coo .obstime )
103-
104- # To compute the distance in a way that is reversible with cirs_to_altaz
105- # we use basic trigonometry. The altaz_coo's distance ("d") is one leg
106- # of a triangle, and the earth center -> EarthLocation distance ("r")
107- # is a neighboring leg. We can also easily get the angle between the
108- # earth center->target (calculated above by apio13), and
109- # earth center->EarthLocation vectors. This is a Side-Side-Angle
110- # situation, and the formula below is the trig formula to solve for
111- # the remaining side
112-
113- ucirs = cirs_frame .realize_frame (UnitSphericalRepresentation (lon = cirs_ra , lat = cirs_dec ))
114- delta = ucirs .separation (locitrs )
115- r = locitrs .spherical .distance
116- d = altaz_coo .distance
117-
118- sindoverd = np .sin (delta ) / d
119- distance = np .sin (delta + np .arcsin (r * sindoverd ))/ sindoverd
120-
121- #the final transform may be a no-op if the obstimes are the same
122- return CIRS (ra = cirs_ra , dec = cirs_dec , distance = distance ,
123- obstime = altaz_coo .obstime ).transform_to (cirs_frame )
114+ # treat the output of atoiq as an "astrometric" RA/DEC, so to get the
115+ # actual RA/Dec from the observers vantage point, we have to reverse
116+ # the vector operation of cirs_to_altaz (see there for more detail)
117+
118+ loccirs = altaz_coo .location .get_itrs (altaz_coo .obstime ).transform_to (cirs_frame )
119+
120+ astrometric_rep = SphericalRepresentation (lon = cirs_ra , lat = cirs_dec ,
121+ distance = altaz_coo .distance )
122+ newrepr = astrometric_rep + loccirs .cartesian
123+ cirs_at_aa_time = CIRS (newrepr , obstime = altaz_coo .obstime )
124+
125+ #this final transform may be a no-op if the obstimes are the same
126+ return cirs_at_aa_time .transform_to (cirs_frame )
124127
125128
126129@frame_transform_graph .transform (FunctionTransform , AltAz , AltAz )
0 commit comments