def cirs_to_observed(cirs_coo, observed_frame): if (np.any(observed_frame.location != cirs_coo.location) or np.any(cirs_coo.obstime != observed_frame.obstime)): cirs_coo = cirs_coo.transform_to(CIRS(obstime=observed_frame.obstime, location=observed_frame.location)) # if the data are UnitSphericalRepresentation, we can skip the distance calculations is_unitspherical = (isinstance(cirs_coo.data, UnitSphericalRepresentation) or cirs_coo.cartesian.x.unit == u.one) # We used to do "astrometric" corrections here, but these are no longer necesssary # CIRS has proper topocentric behaviour usrepr = cirs_coo.represent_as(UnitSphericalRepresentation) cirs_ra = usrepr.lon.to_value(u.radian) cirs_dec = usrepr.lat.to_value(u.radian) # first set up the astrometry context for CIRS<->observed astrom = erfa_astrom.get().apio(observed_frame) if isinstance(observed_frame, AltAz): lon, zen, _, _, _ = erfa.atioq(cirs_ra, cirs_dec, astrom) lat = PIOVER2 - zen else: _, _, lon, lat, _ = erfa.atioq(cirs_ra, cirs_dec, astrom) if is_unitspherical: rep = UnitSphericalRepresentation(lat=u.Quantity(lat, u.radian, copy=False), lon=u.Quantity(lon, u.radian, copy=False), copy=False) else: # since we've transformed to CIRS at the observatory location, just use CIRS distance rep = SphericalRepresentation(lat=u.Quantity(lat, u.radian, copy=False), lon=u.Quantity(lon, u.radian, copy=False), distance=cirs_coo.distance, copy=False) return observed_frame.realize_frame(rep)
def icrs_to_altaz(icrs_coo, altaz_frame): # if the data are UnitSphericalRepresentation, we can skip the distance calculations is_unitspherical = (isinstance(icrs_coo.data, UnitSphericalRepresentation) or icrs_coo.cartesian.x.unit == u.one) # first set up the astrometry context for ICRS<->AltAz astrom = erfa_astrom.get().apco(altaz_frame) # correct for parallax to find BCRS direction from observer (as in erfa.pmpx) if is_unitspherical: srepr = icrs_coo.spherical else: observer_icrs = CartesianRepresentation(astrom['eb'], unit=u.au, xyz_axis=-1, copy=False) srepr = (icrs_coo.cartesian - observer_icrs).represent_as(SphericalRepresentation) # convert to topocentric CIRS cirs_ra, cirs_dec = atciqz(srepr, astrom) # now perform AltAz conversion az, zen, ha, odec, ora = erfa.atioq(cirs_ra, cirs_dec, astrom) alt = PIOVER2 - zen if is_unitspherical: aa_srepr = UnitSphericalRepresentation(az << u.radian, alt << u.radian, copy=False) else: aa_srepr = SphericalRepresentation(az << u.radian, alt << u.radian, srepr.distance, copy=False) return altaz_frame.realize_frame(aa_srepr)
def cirs_to_altaz(cirs_coo, altaz_frame): if np.any(cirs_coo.obstime != altaz_frame.obstime): # the only frame attribute for the current CIRS is the obstime, but this # would need to be updated if a future change allowed specifying an # Earth location algorithm or something cirs_coo = cirs_coo.transform_to(CIRS(obstime=altaz_frame.obstime)) # we use the same obstime everywhere now that we know they're the same obstime = cirs_coo.obstime # if the data are UnitSphericalRepresentation, we can skip the distance calculations is_unitspherical = (isinstance(cirs_coo.data, UnitSphericalRepresentation) or cirs_coo.cartesian.x.unit == u.one) if is_unitspherical: usrepr = cirs_coo.represent_as(UnitSphericalRepresentation) cirs_ra = usrepr.lon.to_value(u.radian) cirs_dec = usrepr.lat.to_value(u.radian) else: # compute an "astrometric" ra/dec -i.e., the direction of the # displacement vector from the observer to the target in CIRS loccirs = altaz_frame.location.get_itrs( cirs_coo.obstime).transform_to(cirs_coo) diffrepr = ( cirs_coo.cartesian - loccirs.cartesian).represent_as(UnitSphericalRepresentation) cirs_ra = diffrepr.lon.to_value(u.radian) cirs_dec = diffrepr.lat.to_value(u.radian) # first set up the astrometry context for CIRS<->AltAz astrom = erfa_astrom.get().apio13(altaz_frame) az, zen, _, _, _ = erfa.atioq(cirs_ra, cirs_dec, astrom) if is_unitspherical: rep = UnitSphericalRepresentation(lat=u.Quantity(PIOVER2 - zen, u.radian, copy=False), lon=u.Quantity(az, u.radian, copy=False), copy=False) else: # now we get the distance as the cartesian distance from the earth # location to the coordinate location locitrs = altaz_frame.location.get_itrs(obstime) distance = locitrs.separation_3d(cirs_coo) rep = SphericalRepresentation(lat=u.Quantity(PIOVER2 - zen, u.radian, copy=False), lon=u.Quantity(az, u.radian, copy=False), distance=distance, copy=False) return altaz_frame.realize_frame(rep)
def _erfa_check(ira, idec, astrom): """ This function does the same thing the astropy layer is supposed to do, but all in erfa """ cra, cdec = erfa.atciq(ira, idec, 0, 0, 0, 0, astrom) az, zen, ha, odec, ora = erfa.atioq(cra, cdec, astrom) alt = np.pi / 2 - zen cra2, cdec2 = erfa.atoiq('A', az, zen, astrom) ira2, idec2 = erfa.aticq(cra2, cdec2, astrom) dct = locals() del dct['astrom'] return dct
def cirs_to_altaz(cirs_coo, altaz_frame): if np.any(cirs_coo.obstime != altaz_frame.obstime): # the only frame attribute for the current CIRS is the obstime, but this # would need to be updated if a future change allowed specifying an # Earth location algorithm or something cirs_coo = cirs_coo.transform_to(CIRS(obstime=altaz_frame.obstime)) # we use the same obstime everywhere now that we know they're the same obstime = cirs_coo.obstime # if the data are UnitSphericalRepresentation, we can skip the distance calculations is_unitspherical = (isinstance(cirs_coo.data, UnitSphericalRepresentation) or cirs_coo.cartesian.x.unit == u.one) if is_unitspherical: usrepr = cirs_coo.represent_as(UnitSphericalRepresentation) cirs_ra = usrepr.lon.to_value(u.radian) cirs_dec = usrepr.lat.to_value(u.radian) else: # compute an "astrometric" ra/dec -i.e., the direction of the # displacement vector from the observer to the target in CIRS loccirs = altaz_frame.location.get_itrs( cirs_coo.obstime).transform_to(cirs_coo) diffrepr = ( cirs_coo.cartesian - loccirs.cartesian).represent_as(UnitSphericalRepresentation) cirs_ra = diffrepr.lon.to_value(u.radian) cirs_dec = diffrepr.lat.to_value(u.radian) lon, lat, height = altaz_frame.location.to_geodetic('WGS84') xp, yp = get_polar_motion(obstime) # first set up the astrometry context for CIRS<->AltAz jd1, jd2 = get_jd12(obstime, 'utc') astrom = erfa.apio13( jd1, jd2, get_dut1utc(obstime), lon.to_value(u.radian), lat.to_value(u.radian), height.to_value(u.m), xp, yp, # polar motion # all below are already in correct units because they are QuantityFrameAttribues altaz_frame.pressure.value, altaz_frame.temperature.value, altaz_frame.relative_humidity.value, altaz_frame.obswl.value) az, zen, _, _, _ = erfa.atioq(cirs_ra, cirs_dec, astrom) if is_unitspherical: rep = UnitSphericalRepresentation(lat=u.Quantity(PIOVER2 - zen, u.radian, copy=False), lon=u.Quantity(az, u.radian, copy=False), copy=False) else: # now we get the distance as the cartesian distance from the earth # location to the coordinate location locitrs = altaz_frame.location.get_itrs(obstime) distance = locitrs.separation_3d(cirs_coo) rep = SphericalRepresentation(lat=u.Quantity(PIOVER2 - zen, u.radian, copy=False), lon=u.Quantity(az, u.radian, copy=False), distance=distance, copy=False) return altaz_frame.realize_frame(rep)