def test_transforms_diff(sc): # note that arguably this *should* fail for the no-distance cases: 3D # information is necessary to truly solve this, hence the xfail if not sc.distance.unit.is_equivalent(u.m): pytest.xfail('Should fail for no-distance cases') else: trans = sc.transform_to(PrecessedGeocentric(equinox='B1975')) assert isinstance(trans.frame, PrecessedGeocentric)
def test_precessed_geocentric_different_obstime(): # Create two PrecessedGeocentric frames with different obstime precessedgeo1 = PrecessedGeocentric(obstime='2021-09-07') precessedgeo2 = PrecessedGeocentric(obstime='2021-06-07') # GCRS->PrecessedGeocentric should give different results for the two frames gcrs_coord = GCRS(10 * u.deg, 20 * u.deg, 3 * u.AU, obstime=precessedgeo1.obstime) pg_coord1 = gcrs_coord.transform_to(precessedgeo1) pg_coord2 = gcrs_coord.transform_to(precessedgeo2) assert not pg_coord1.is_equivalent_frame(pg_coord2) assert not allclose(pg_coord1.cartesian.xyz, pg_coord2.cartesian.xyz) # Looping back to GCRS should return the original coordinate loopback1 = pg_coord1.transform_to(gcrs_coord) loopback2 = pg_coord2.transform_to(gcrs_coord) assert loopback1.is_equivalent_frame(gcrs_coord) assert loopback2.is_equivalent_frame(gcrs_coord) assert_allclose(loopback1.cartesian.xyz, gcrs_coord.cartesian.xyz) assert_allclose(loopback2.cartesian.xyz, gcrs_coord.cartesian.xyz)
def test_precessedgeocentric_loopback(): from_coo = PrecessedGeocentric(1 * u.deg, 2 * u.deg, 3 * u.AU, obstime='2001-01-01', equinox='2001-01-01') # Change just the obstime to_frame = PrecessedGeocentric(obstime='2001-06-30', equinox='2001-01-01') explicit_coo = from_coo.transform_to(ICRS()).transform_to(to_frame) implicit_coo = from_coo.transform_to(to_frame) # Confirm that the explicit transformation changes the coordinate assert not allclose(explicit_coo.ra, from_coo.ra, rtol=1e-10) assert not allclose(explicit_coo.dec, from_coo.dec, rtol=1e-10) assert not allclose(explicit_coo.distance, from_coo.distance, rtol=1e-10) # Confirm that the loopback matches the explicit transformation assert_allclose(explicit_coo.ra, implicit_coo.ra, rtol=1e-10) assert_allclose(explicit_coo.dec, implicit_coo.dec, rtol=1e-10) assert_allclose(explicit_coo.distance, implicit_coo.distance, rtol=1e-10) # Change just the equinox to_frame = PrecessedGeocentric(obstime='2001-01-01', equinox='2001-06-30') explicit_coo = from_coo.transform_to(ICRS()).transform_to(to_frame) implicit_coo = from_coo.transform_to(to_frame) # Confirm that the explicit transformation changes the direction but not the distance assert not allclose(explicit_coo.ra, from_coo.ra, rtol=1e-10) assert not allclose(explicit_coo.dec, from_coo.dec, rtol=1e-10) assert allclose(explicit_coo.distance, from_coo.distance, rtol=1e-10) # Confirm that the loopback matches the explicit transformation assert_allclose(explicit_coo.ra, implicit_coo.ra, rtol=1e-10) assert_allclose(explicit_coo.dec, implicit_coo.dec, rtol=1e-10) assert_allclose(explicit_coo.distance, implicit_coo.distance, rtol=1e-10)
def test_precessed_geocentric(): assert PrecessedGeocentric().equinox.jd == Time('J2000').jd gcrs_coo = GCRS(180 * u.deg, 2 * u.deg, distance=10000 * u.km) pgeo_coo = gcrs_coo.transform_to(PrecessedGeocentric()) assert np.abs(gcrs_coo.ra - pgeo_coo.ra) > 10 * u.marcsec assert np.abs(gcrs_coo.dec - pgeo_coo.dec) > 10 * u.marcsec assert_allclose(gcrs_coo.distance, pgeo_coo.distance) gcrs_roundtrip = pgeo_coo.transform_to(GCRS()) assert_allclose(gcrs_coo.ra, gcrs_roundtrip.ra) assert_allclose(gcrs_coo.dec, gcrs_roundtrip.dec) assert_allclose(gcrs_coo.distance, gcrs_roundtrip.distance) pgeo_coo2 = gcrs_coo.transform_to(PrecessedGeocentric(equinox='B1850')) assert np.abs(gcrs_coo.ra - pgeo_coo2.ra) > 1.5 * u.deg assert np.abs(gcrs_coo.dec - pgeo_coo2.dec) > 0.5 * u.deg assert_allclose(gcrs_coo.distance, pgeo_coo2.distance) gcrs2_roundtrip = pgeo_coo2.transform_to(GCRS()) assert_allclose(gcrs_coo.ra, gcrs2_roundtrip.ra) assert_allclose(gcrs_coo.dec, gcrs2_roundtrip.dec) assert_allclose(gcrs_coo.distance, gcrs2_roundtrip.distance)
def TEME2ECI_pos(Pos_TEME, t): T = Time(t, format='jd', scale='utc') dist_vect = norm(Pos_TEME, axis=0) ra_vect = np.arctan2(Pos_TEME[1], Pos_TEME[0]) dec_vect = np.arcsin(Pos_TEME[2] / dist_vect) Pos_TEME_SC = PrecessedGeocentric(ra=ra_vect * u.rad, dec=dec_vect * u.rad, distance=dist_vect * u.m, equinox=T, obstime=T) Pos_ECI_SC = Pos_TEME_SC.transform_to(GCRS(obstime=T)) Pos_ECI = np.vstack(Pos_ECI_SC.cartesian.xyz.value) return Pos_ECI
def ECI2TEME_pos(Pos_ECI, t): T = Time(t, format='jd', scale='utc') precessed_frame = PrecessedGeocentric(equinox=T, obstime=T) dist_vect = norm(Pos_ECI, axis=0) ra_vect = np.arctan2(Pos_ECI[1], Pos_ECI[0]) dec_vect = np.arcsin(Pos_ECI[2] / dist_vect) Pos_ECI_SC = GCRS(ra=ra_vect * u.rad, dec=dec_vect * u.rad, distance=dist_vect * u.m, obstime=T) Pos_TEME_SC = Pos_ECI_SC.transform_to(precessed_frame) Pos_TEME = np.vstack(Pos_TEME_SC.cartesian.xyz.value) return Pos_TEME
def get_sun_P(time='now'): """ Return the position (P) angle for the Sun at a specified time, which is the angle between geocentric north and solar north as seen from Earth, measured eastward from geocentric north. The range of P is +/-26.3 degrees. Parameters ---------- time : various Time to use as `~astropy.time.Time` or in a parse_time-compatible format Returns ------- out : `~astropy.coordinates.Angle` The position angle """ obstime = parse_time(time) # Define the frame where its Z axis is aligned with geocentric north geocentric = PrecessedGeocentric(equinox=obstime, obstime=obstime) return _sun_north_angle_to_z(geocentric)
def currentgeocentframe(time) : # Generate a PrecessedGeocentric frame for the current equinox. time_ep = 2000. + (time.jd - thorconsts.J2000) / 365.25 eq = "J%7.2f" % (time_ep) # print eq return PrecessedGeocentric(equinox = eq)
# -*- coding: utf-8 -*- """ Created on Sat Feb 1 16:59:43 2020 https://qiita.com/phyblas/items/a801b0f319742245ad2e @author: PC """ from astropy.coordinates import SkyCoord, PrecessedGeocentric b1875 = PrecessedGeocentric(equinox='B1875') b1875_hokkyoku = SkyCoord(ra=0, dec=90, unit='deg', frame=b1875) print(b1875_hokkyoku) b1875_hokkyoku_icrs = b1875_hokkyoku.transform_to('icrs') print(b1875_hokkyoku_icrs)
def obj_sight(date,objname,lonstr,latstr,tzinhours,approx=True): """ date: string, date of observing. objname : string, name of sun, moon or planet in solar system. lonstr : string, longitute of observing location on earth. latstr : string, latitute of observing location on earth. ltzinhours : float, time zone in hours of observing location. approx : bool, True for delta_ut1_utc=0 return : print out rise time, set time, transit time and cooresponding alt/az. """ lon=Angle(lonstr) lat=Angle(latstr) if objname=='sun': r_obj=const.R_sun.to('m').value else: if objname=="moon": r_obj=1737000 #halfdisk=Angle(diskanglestr)*0.5 date=Time(Time(date,out_subfmt='date').iso) times=date+np.linspace(0.,1440.,1441)*TimeDelta(60,format='sec') # 每分鐘計算位置 deltat=tzinhours*TimeDelta(3600,format='sec') a=const.R_earth.to('m').value # 地球半徑 with solar_system_ephemeris.set('jpl'): n=len(times) gmttimes=times-deltat # 世界時間 UTC # 標的物在真赤道座標系統座標 bodies=get_body(objname,gmttimes).transform_to(PrecessedGeocentric(equinox=gmttimes)) if approx: gmttimes.delta_ut1_utc = 0. sides=gmttimes.sidereal_time('apparent', 'greenwich')+lon # local sidereal time x=bodies.cartesian.x.to('m').value # x,y,z為標的物在及時赤道座標系統的直角座標 y=bodies.cartesian.y.to('m').value z=bodies.cartesian.z.to('m').value px=np.array(a*np.cos(lat)*np.cos(sides)) # px,py,pz 為觀測地在真赤道座標系統的直角坐標 py=np.array(a*np.cos(lat)*np.sin(sides)) pz=np.array(a*np.sin(lat)*np.ones(n)) positions=np.vstack((px,py,pz)).T # n x 3 array objs=np.vstack((x,y,z)).T # n x 3 array # e_z 的每一行為天頂方向單位向量,e_n的每一行為地表往北單位向量,e_e的每一行為地表往東單位向量 e_z=np.vstack((np.cos(lat)*np.cos(sides),np.cos(lat)*np.sin(sides),np.sin(lat)*np.ones(n))) # 3 x n e_n=np.vstack((-np.sin(lat)*np.cos(sides),-np.sin(lat)*np.sin(sides),np.cos(lat)*np.ones(n))) # 3 x n e_e=np.vstack((-np.sin(sides),np.cos(sides),np.zeros(n))) # 3 x n coords=np.zeros((n,3)) # coords 的每一列代表標的物在地表座標系統的直角坐標 az=np.zeros(n) # az 標的物的方位角,北方為0,往東為正,正東方90度,正南方180度,正西方270度。 alt=np.zeros(n) # alt 標的物的仰角 for i in range(n): coords[i]=np.array(np.vstack((e_e[:,i],e_n[:,i],e_z[:,i]))).dot(objs[i]-positions[i]) r=np.sqrt(coords[i][0]**2+coords[i][1]**2) rho=np.sqrt(coords[i][0]**2+coords[i][1]**2+coords[i][2]**2) alt[i]=np.arcsin(coords[i][2]/rho)*180/np.pi az[i]=np.arctan2(coords[i][0],coords[i][1])*180/np.pi if az[i]<0: az[i]=az[i]+360 if objname=="sun" or objname=="moon" : halfdisk=np.arcsin(r_obj/rho)*180/np.pi*u.deg else : halfdisk=0*u.deg thresh=-(halfdisk+Angle("0d34m0s")).deg # 大氣折射,讓光線轉彎了34角分 altdiff=alt-thresh # altdif 變號的時候就是標的物升起或沉沒的區間,用內插進行估計 for i in range(len(times)-1): if altdiff[i]*altdiff[i+1] <=0 : t=times[i]+(times[i+1]-times[i])*(0-altdiff[i])/(altdiff[i+1]-altdiff[i]) if altdiff[i]<0: print("出",t,"方位",az[i]) else: print("沒",t,"方位",az[i]) if not (az[i] // 180 == az[i+1] // 180) and alt[i]>0: if np.abs(az[i]-180)<30: ratio=(180-az[i])/(az[i+1]-az[i]) t=times[i]+(times[i+1]-times[i])*ratio print("中天",t,"仰角",alt[i]+(alt[i+1]-alt[i])*ratio,"方位","南") else: left=az[i] right=az[i+1] if left>300: left=left-360 if right>300: right=right-360 ratio=(0-left)/(az[i+1]-az[i]) t=times[i]+(times[i+1]-times[i])*ratio print("中天",t,"仰角",alt[i]+(alt[i+1]-alt[i])*ratio,"方位","南")