def cassini_surfintercerpt(utc, output=False): target = 'TITAN' fixref = 'IAU_TITAN' dref = 'IAU_TITAN' method = 'ELLIPSOID' abcorr = 'NONE' obsrvr = 'CASSINI' state = cassini_phase(utc) dvec = spice.vhat(-state[:3]) et = spice.str2et(utc) [point, trgepc, srfvec] = spice.sincpt(method, target, et, fixref, abcorr, obsrvr, dref, dvec) temp = spice.reclat(point) radius = temp[0] colat = 90 + spice.convrt(temp[1], "RADIANS", "DEGREES") lon = np.mod(spice.convrt(temp[2], "RADIANS", "DEGREES"), 360) if output: print("Distance to Intercept Point", spice.vnorm(srfvec)) print("Radius", radius) print("Colatitude", colat) print("Longtitude", lon) return point, [radius, colat, lon], spice.vnorm(srfvec)
def convertAst(a): pos1 = sp.convrt(a[0], 'KM', 'AU') pos2 = sp.convrt(a[1], 'KM', 'AU') pos3 = sp.convrt(a[2], 'KM', 'AU') vel1 = a[3] * (86400 / 149597870.700) vel2 = a[4] * (86400 / 149597870.700) vel3 = a[5] * (86400 / 149597870.700) return np.array([pos1, pos2, pos3, vel1, vel2, vel3])
def search_stars(obsinfo, mag_limit=7.0): query = ("SELECT" " CATALOG_NUMBER,RA,DEC,VISUAL_MAGNITUDE,PARLAX,SPECTRAL_TYPE" " FROM HIPPARCOS") nmrows, _error, _errmsg = spice.ekfind(query) stars = [] for row in range(nmrows): ra = spice.ekgd(1, row, 0)[0] * spice.rpd() dec = spice.ekgd(2, row, 0)[0] * spice.rpd() mag = spice.ekgd(3, row, 0)[0] vec = spice.radrec(1.0, ra, dec) tvec = spice.mxv(obsinfo.ref2obsmtx, vec) _tpa, tdist = vec_padist(obsinfo.center, tvec) if tdist < obsinfo.fov.fovmax and mag < mag_limit: parallax = spice.ekgd(4, row, 0)[0] spectral = spice.ekgc(5, row, 0)[0] distance = 1.0 / np.tan(parallax * spice.rpd()) distance = spice.convrt(distance, "AU", "km") pos = tvec * distance vp = viewport_frustum(obsinfo.fov.bounds_rect, obsinfo.width, obsinfo.height, pos) star = { "hip_id": spice.ekgi(0, row, 0)[0], "position": tvec, "ra": ra, "dec": dec, "spectral_type": spectral, "visual_magnitude": mag, "distance": distance, "image_pos": vp[0:2], "color": get_star_color(spectral), } stars.append(star) return stars
if __name__ == "__main__": # Script expects first argument to be a UTC timestamp if len(sys.argv) > 1: input_utc = sys.argv[1] else: input_utc = '2016-01-12T22:35:07.584' # default for testing # Load the necessary data files sp.furnsh(KERNELS) # Convert input time to ephemeris time epoch = sp.str2et(input_utc) # State (position and velocity in cartesian coordinates) # of Kepler (-227) as seen from EARTH in the J2000 coordinate frame. state, lt, = sp.spkezr("-227", epoch, "J2000", "NONE", "EARTH") # Show the output print("Input time = {}".format(input_utc)) print("") print("# Position of Kepler in the geocentric J2000 frame") print("X = {:.8f} AU".format(sp.convrt(state[0], 'km', 'AU'))) print("Y = {:.8f} AU".format(sp.convrt(state[1], 'km', 'AU'))) print("Z = {:.8f} AU".format(sp.convrt(state[2], 'km', 'AU'))) print("") print("# Velocity of Kepler in the geocentric J2000 frame") print("dX = {:.8f} AU/s".format(sp.convrt(state[3], 'km', 'AU'))) print("dY = {:.8f} AU/s".format(sp.convrt(state[4], 'km', 'AU'))) print("dZ = {:.8f} AU/s".format(sp.convrt(state[5], 'km', 'AU'))) # As a sanity check, print the speed speed = (state[3]**2 + state[4]**2 + state[5]**2)**.5 print("") print("# Orbital speed [sqrt(dX^2 + dY^2 + dZ^2)]") print("Speed = {:.8f} AU/s".format(sp.convrt(speed, 'km', 'AU')))
# from the Sun STATE_VEC_JUPITER, _ = spiceypy.spkgeo(targ=5, \ et=SAMPLE_ET, \ ref='ECLIPJ2000', \ obs=10) # Get the G*M value of the Sun _, GM_SUN = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1) GM_SUN = GM_SUN[0] # Compute the orbital elements of Jupiter ... ORB_ELEM_JUPITER = spiceypy.oscltx(STATE_VEC_JUPITER, SAMPLE_ET, GM_SUN) # ... extract the semi-major axis and convert it from km to AU A_JUPITER_KM = ORB_ELEM_JUPITER[-2] A_JUPITER_AU = spiceypy.convrt(A_JUPITER_KM, 'km', 'AU') #%% # Set the inclination range (however, only from 0 to 90 degrees) and convert # the degrees values to radians INCL_RANGE_DEG = np.linspace(0, 90, 100) INCL_RANGE_RAD = np.radians(INCL_RANGE_DEG) # Set an array for the eccentricity E_RANGE = np.linspace(0, 1, 100) # Tisserand parameter w.r.t. to Jupiter as a lambda function (a is the # semi-major axis, i is the inclination and e is the eccentricty of the # object) tisserand_jup = lambda a, i, e: (A_JUPITER_AU / a) \
def main(): # **Load necessary kernels from metafile** f_manage_kernels( r"E:\Data Science Projects\Space Science\SpaceScience-P2-SSBandSunWobbling\references\SPICE_kernels_metafile_P2.txt" ) # **Compute position of SSB wrt Sun** #First, we compute the position vectors of the SSB wrt the Sun at a #randomly chosen time. Let's choose the time as my birthday (24 April 1988, #9AM). init_time_utc = dt.datetime(year=1988,\ month=4,\ day=24,\ hour=9,\ minute=0,\ second=0) #We shall convert this time from UTC to ET. init_time_et, init_time_utc_str = f_convert_utc_to_et(init_time_utc) #Compute the position of SSB wrt Sun SSB_position_init = f_calc_position(init_time_et) #Report position print(f"On {init_time_utc_str}: \n\nPosition of SSB wrt Sun: \n \ X-axis = {SSB_position_init[0]} km \n \ Y-axis = {SSB_position_init[1]} km \n \ Z-axis = {SSB_position_init[2]} km") #Compute distance of SSB from Sun in km SSB_sun_distance = math.sqrt(SSB_position_init[0]**2.0 \ + SSB_position_init[1]**2.0 \ + SSB_position_init[2]**2.0) #Convert km to AU SSB_sun_distance_AU = spiceypy.convrt(SSB_sun_distance, 'km', 'AU') #Report value print(f"Distance between SSB and Sun in km: {SSB_sun_distance} km") print(f"Distance between SSB and Sun in AU: {SSB_sun_distance_AU} AU") # **visualise the SSB wrt Sun** #We need to first scale the distance to the radius of the Sun using bodvcd #function. _, radii_sun = spiceypy.bodvcd(bodyid=10, item='RADII', maxn=3) radius_sun = radii_sun[0] #Scale position of SSB to radius of Sun SSB_position_init_scaled = f_scale_distance(SSB_position_init, radius_sun) #Plot using matplotlib # We only plot the x, y components (view on the ecliptic plane) SSB_position_init_scaled_xy = SSB_position_init_scaled[0:2] fig,ax = f_plot_SSB_position(SSB_position_init_scaled_xy[0],\ SSB_position_init_scaled_xy[1]) #Add plot title plt.title(f"Position of SSB wrt Centre of Sun on {init_time_utc_str}") #Annotate SSB datapoint SSB_label = "SSB ({:.2f},{:.2f})".format(SSB_position_init_scaled_xy[0],\ SSB_position_init_scaled_xy[1]) plt.annotate(SSB_label,(SSB_position_init_scaled_xy[0],\ SSB_position_init_scaled_xy[1]+0.1)) # Saving the figure in high quality plt.savefig( r'E:\Data Science Projects\Space Science\SpaceScience-P2-SSBandSunWobbling\reports\figures\SSB_WRT_SUN_INIT.png', dpi=300) plt.show() # === Compute position of SSB wrt Sun over a certain time period === #Now we shall look the change in position of SSB wrt Sun over a certain #time period. Let us choose a time period of 30 years starting from the #time chosen in previous section. delta_days = 30 * 365 end_time_utc = init_time_utc + dt.timedelta(days=delta_days) end_time_et, end_time_utc_str = f_convert_utc_to_et(end_time_utc) # **Side Note** #Here we can see why it is important to change time from UTC to ET. The #conversion helps to take into account leap years as well. When we use UTC, #the total number of seconds in the given time period of 30 years is: #30years*365days*24hours*60minutes*60seconds print("Covered UTC time interval in seconds: %s\n" % (30 * 365 * 24 * 60 * 60)) #The number of seconds after converting to ET are: print("Covered ET time interval in seconds: %s\n" \ %(end_time_et - init_time_et)) #The printed results show that there is a difference of 13.0000644 seconds #between the two calculated time intervals. These are the leapseconds #added while converting UTC to ET. While these 13 seconds do not matter #much in the current program, they could have critical impact on space #mission projects. A lot can happen in 13 seconds in space. #The Earth moves about 390 km through space in 13 seconds. #The ISS travels almost 105 km around the Earth in 13 seconds. #An space-walking astronaut with a punctured suit has only 15 seconds #before losing consciousness. #**End of Side Note** #**Record SSB position for each day** # Create a numpy array that covers a time interval in delta = 1 day step time_interval_et = np.linspace(init_time_et, end_time_et, delta_days) #Compute SSB position wrt Sun for each day #Set an empty list to store x, y, z components for each time step SSB_position_interval = [] #Compute position of SSB wrt sun for each time step. for time_interval_et_f in time_interval_et: _position = f_calc_position(time_interval_et_f) #Append the result to the final list SSB_position_interval.append(_position) #Convert the list to a numpy array SSB_position_interval = np.array(SSB_position_interval) #Scale the position values using the Sun's radius SSB_position_interval_scaled = f_scale_distance(SSB_position_interval,\ radius_sun) #Plot using matplotlib # We only plot the x, y components (view on the ecliptic plane) SSB_position_interval_scaled_xy = SSB_position_interval_scaled[:, 0:2] fig,ax = f_plot_SSB_position(SSB_position_interval_scaled_xy[:,0],\ SSB_position_interval_scaled_xy[:,1]) #Add plot title plt.title(f"Position of SSB wrt Centre of Sun between {init_time_utc_str}\ and {end_time_utc_str}") #Add annotations plt.annotate("Day 1",(SSB_position_interval_scaled_xy[0,0],\ SSB_position_interval_scaled_xy[0,1]+0.1)) plt.annotate("30 yrs later",(SSB_position_interval_scaled_xy[-1,0]-0.1,\ SSB_position_interval_scaled_xy[-1,1]-0.1)) # Saving the figure in high quality plt.savefig( r'E:\Data Science Projects\Space Science\SpaceScience-P2-SSBandSunWobbling\reports\figures\SSB_WRT_SUN_30_YEARS.png', dpi=300) plt.show() # === How many days is the SSB outside the Sun? === #First, we compute the euclidean distance between the SSB and Sun. SSB_position_interval_scaled = np.linalg.norm(SSB_position_interval_scaled,\ axis=1) print('\nComputation time: %s days' % delta_days) # Compute number of days outside the Sun SSB_outside_sun_days = len(np.where(SSB_position_interval_scaled > 1)[0]) print('Fraction of time where the SSB\n' \ 'was outside the Sun: %.2f %%' \ % (100 * SSB_outside_sun_days / delta_days)) # === When was SSB closest to the Sun? === #Find minimum euclidean distance in selected time interval SSB_position_interval_scaled = list(SSB_position_interval_scaled) SSB_position_interval_scaled_min = min(SSB_position_interval_scaled) #Find day when distance was minimum SSB_min_day = SSB_position_interval_scaled.index( SSB_position_interval_scaled_min) #Convert that day to UTC SSB_min_day_utc = init_time_utc + dt.timedelta(days=SSB_min_day) #Report print(f"\nSSB was closest to centre of Sun on {SSB_min_day_utc},") print(f"i.e. {round(SSB_min_day/365,2)} years later.") print( f"It was only {round(SSB_position_interval_scaled_min*radius_sun,2)} km away." ) # === When was SSB farthest from the Sun? === #Find maximum euclidean distance in selected time interval SSB_position_interval_scaled = list(SSB_position_interval_scaled) SSB_position_interval_scaled_max = max(SSB_position_interval_scaled) #Find day when distance was minimum SSB_max_day = SSB_position_interval_scaled.index( SSB_position_interval_scaled_max) #Convert that day to UTC SSB_max_day_utc = init_time_utc + dt.timedelta(days=SSB_max_day) #Report print(f"\nSSB was farthest from centre of Sun on {SSB_max_day_utc},") print(f"i.e. {round(SSB_max_day/365,2)} years later.") print( f"It was {round(SSB_position_interval_scaled_max*radius_sun,2)} km away." )
######################################################################## if "__main__" == __name__: ### FURNSH (SPICE furnish operation i.e. load kernel ) this script as a kernel, ### as well as any command-line arguments ### - skip any argument th at is --debug map(sp.furnsh, [arg for arg in sys.argv if arg != '--debug']) ### Set debug flag to True if --debug was an argument, else to False doDebug = '--debug' in sys.argv ### SPICE names of Clock, minute hand, hour hand sClock, sMinute, sHour = sNames = "CLOCK MINUTE HOUR".split() ### SPICE works in seconds; get seconds per minute, per hour, per day spm = sp.convrt(1.0, 'minutes', 'seconds') sph = sp.convrt(1.0, 'hours', 'seconds') hpd = sp.convrt(1.0, 'days', 'hours') spd = sp.spd() ### Other constants: 2*PI; degrees/radian twopi = sp.twopi() dpr = sp.dpr() ### Get start time (TDB) and SPK filename from kernel pool et0 = sp.gdpool('ET0', 0, 1)[0] fnClockSpk = sp.gcpool('CLOCKSPK', 0, 1, 99)[0] ### Make clock SPK if it does not exist if not os.path.exists(fnClockSpk):
#%% # Get the G*M value for the Sun _, GM_SUN_PRE = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1) GM_SUN = GM_SUN_PRE[0] #%% # Compute the orbital elements of Ceres using the computed state vector CERES_ORBITAL_ELEMENTS = spiceypy.oscltx(state=CERES_STATE_VECTOR, \ et=DATETIME_ET, \ mu=GM_SUN) # Set and convert the semi-major axis and perihelion from km to AU CERES_SEMI_MAJOR_AU = spiceypy.convrt(CERES_ORBITAL_ELEMENTS[9], \ inunit='km', outunit='AU') CERES_PERIHELION_AU = spiceypy.convrt(CERES_ORBITAL_ELEMENTS[0], \ inunit='km', outunit='AU') # Set the eccentricity CERES_ECC = CERES_ORBITAL_ELEMENTS[1] # Set and convert miscellaneous angular values from radians to degrees: # inc: Inclination # lnode: Longitude of ascending node # argp: Argument of perihelion CERES_INC_DEG = np.degrees(CERES_ORBITAL_ELEMENTS[2]) CERES_LNODE_DEG = np.degrees(CERES_ORBITAL_ELEMENTS[3]) CERES_ARGP_DEG = np.degrees(CERES_ORBITAL_ELEMENTS[4]) # Set the orbit period. Convert from seconds to years
AST_2020JX1_ARGP_DEG, \ AST_2020JX1_I_DEG], \ cov=AST_2020JX1_COV_MAT, size=1000) #%% # Store all re-samples now in a pandas dataframe. Consider the order of the # orbital elements as defined by the covariance matrix ast_2020_jx1_df = pd.DataFrame([]) # Eccentricity ast_2020_jx1_df.loc[:, 'ECC'] = AST_2020_JX1_SAMPLE[:, 0] # Perihelion (convert AU to km) ast_2020_jx1_df.loc[:, 'PERIH_KM'] = \ spiceypy.convrt(AST_2020_JX1_SAMPLE[:, 1], 'AU', 'km') # Epoch in JD ast_2020_jx1_df.loc[:, 'EPOCH_JD'] = AST_2020_JX1_SAMPLE[:, 2] # Convert Epoch given in JD to Ephemeris Time ast_2020_jx1_df.loc[:, 'EPOCH_ET'] = \ ast_2020_jx1_df['EPOCH_JD'].apply(lambda x: \ spiceypy.utc2et(str(x) + ' JD')) # Longitude of ascending node, argument of periapsis and the inclination # (in radians) ast_2020_jx1_df.loc[:, 'LNODE_RAD'] = np.radians(AST_2020_JX1_SAMPLE[:, 3]) ast_2020_jx1_df.loc[:, 'ARGP_RAD'] = np.radians(AST_2020_JX1_SAMPLE[:, 4]) ast_2020_jx1_df.loc[:, 'I_RAD'] = np.radians(AST_2020_JX1_SAMPLE[:, 5])
def main(): # ** Convert today's time at midnight from UTC to ephemeric time ET ** #Get today's date date_today_utc = dt.datetime.today() #Convert datetime to string, replacing time with midnight date_today_utc = date_today_utc.strftime('%Y-%m-%dT00:00:00') #Get time conversion information from a lsk kernel 'naif0012.tls' spiceypy.furnsh( 'E:\Data Science Projects\Space Science\SpaceScience-P1-EarthStateVectors\data\external\_kernels\lsk/naif0012.tls' ) #Convert UTC to ET using SPICE function 'utc2et' et_today = spiceypy.utc2et(date_today_utc) # ** Compute the position and velocity of the Earth with respect to the Sun ** #First load a spk kernel 'de432s.bsp' for positional information of planets. # How to find the relevant kernel? # At https://naif.jpl.nasa.gov/pub/naif/ we navigate to generic_kernels/spk/ # planets, since we are trying to find the trajectory of our planet. We # browse the aa_summaries.txt file. The last line of each summary shows the # time range covered in each kernel. The time period of de432s is suitable. spiceypy.furnsh( 'E:\Data Science Projects\Space Science\SpaceScience-P1-EarthStateVectors\data\external/_kernels/spk/de432s.bsp' ) #Use spkgeo function to compute Earth state vectors earth_state_wrt_sun, earth_sun_lt = spiceypy.spkgeo(targ=399, \ et=et_today, \ ref='ECLIPJ2000', \ obs=10) #Report position vector of Earth print(f"Position of Earth wrt Sun on {date_today_utc} is: \n \ {earth_state_wrt_sun}", file=outfile) #Check whether computation is correct # # We check the veracity of the computed position vectors by using the result # to compute the distance between Earth and Sun. If it is around 1 AU, then # the computation is satisfactory. ("around" 1AU because Earth's orbit is # elliptical, ot perfectly circular) # #Compute distance between Earth and Sun in km earth_sun_distance = math.sqrt(earth_state_wrt_sun[0]**2.0 \ + earth_state_wrt_sun[1]**2.0 \ + earth_state_wrt_sun[2]**2.0) #Convert km to AU earth_sun_distance_AU = spiceypy.convrt(earth_sun_distance, 'km', 'AU') #Report value print(f"Current distance between the Earth and the Sun in AU: \ {earth_sun_distance_AU}", file=outfile) # ** Compute Orbital Speed of Earth ** #First we compute actual current orbital speed of Earth around Sun earth_orb_speed_wrt_sun = math.sqrt(earth_state_wrt_sun[3]**2.0 \ + earth_state_wrt_sun[4]**2.0 \ + earth_state_wrt_sun[5]**2.0) #Report current orbital speed of Earth print(f"Current orbital speed of the Earth around the Sun in km/s: \ {earth_orb_speed_wrt_sun}", file=outfile) #Now we compute theoretical orbital speed of Earth around Sun # # For this, we need the equation to determine the orbital speed. We assume # that the Sun's mass is greater than the mass of the Earth and we assume # that our planet is moving on an almost circular orbit. The orbit velocity # $v_{\text{orb}}$ can be approximated with, where $G$ is the gravitational # constant, $M$ is the mass of the Sun and $r$ is the distance between the # Earth and the Sun: # \begin{align} # v_{\text{orb}}\approx\sqrt{\frac{GM}{r}} # \end{align} # # The G*M values for different objects are found in a pck file 'gm_de431.tpc' # #Load pck kernel for G*M value spiceypy.furnsh( 'E:\Data Science Projects\Space Science\SpaceScience-P1-EarthStateVectors\data\external/_kernels/pck/gm_de431.tpc' ) _, GM_SUN = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1) #Compute theoretical orbital speed v_orb_func = lambda gm, r: math.sqrt(gm / r) earth_orb_speed_wrt_sun_theory = v_orb_func(GM_SUN[0], earth_sun_distance) #Report theoretical value print(f"Theoretical orbital speed of the Earth around the Sun in km/s: \ {earth_orb_speed_wrt_sun_theory}", file=outfile)
# Compute the state vectors corresponding orbital elements comet_67p_df.loc[:, 'STATE_VEC_ORB_ELEM'] = \ comet_67p_df.apply(lambda x: spiceypy.oscltx(state=x['STATE_VEC'], \ et=x['ET'], \ mu=GM_SUN), \ axis=1) #%% # Assign miscellaneous orbital elements as individual columns # Set the perihelion. Convert km to AU comet_67p_df.loc[:, 'PERIHELION_AU'] = \ comet_67p_df['STATE_VEC_ORB_ELEM'].apply(lambda x: \ spiceypy.convrt(x[0], \ inunit='km', \ outunit='AU')) # Set the eccentricity comet_67p_df.loc[:, 'ECCENTRICITY'] = \ comet_67p_df['STATE_VEC_ORB_ELEM'].apply(lambda x: x[1]) # Set the inclination in degrees comet_67p_df.loc[:, 'INCLINATION_DEG'] = \ comet_67p_df['STATE_VEC_ORB_ELEM'].apply(lambda x: np.degrees(x[2])) # Set the longitude of ascending node in degrees comet_67p_df.loc[:, 'LONG_OF_ASC_NODE_DEG'] = \ comet_67p_df['STATE_VEC_ORB_ELEM'].apply(lambda x: np.degrees(x[3])) # Set the argument of perihelion in degrees
ceres_df.loc[:, 'UTC_PARSED'] = DATETIME_RANGE.strftime('%Y-%j') # Convert the date-time to Ephemeris Time ceres_df.loc[:, 'ET_TIME'] = ceres_df['UTC_TIME'] \ .apply(lambda x: spiceypy.utc2et(str(x))) #%% # Compute the distance between Ceres and the Sun and convert the resulting # distance value given in km to AU ceres_df.loc[:, 'DIST_SUN_AU'] = \ ceres_df['ET_TIME'].apply(lambda x: \ spiceypy.convrt( \ spiceypy.vnorm( \ spiceypy.spkgps(targ=CERES_ID, \ et=x, \ ref='ECLIPJ2000', \ obs=10)[0]), \ 'km', 'AU')) # # Compute the distance between Ceres and the Earth and convert the resulting # distance value given in km to AU ceres_df.loc[:, 'DIST_EARTH_AU'] = \ ceres_df['ET_TIME'].apply(lambda x: \ spiceypy.convrt( \ spiceypy.vnorm( \ spiceypy.spkgps(targ=CERES_ID, \ et=x, \ ref='ECLIPJ2000', \ obs=399)[0]), \ 'km', 'AU'))
# Connect to the comet database CON = sqlite3.connect('../_databases/_comets/mpc_comets.db') # Extract orbit data of the comet C/2019 Y4 (ATLAS) ATLAS_ORB_EL = pd.read_sql('SELECT NAME, PERIHELION_AU, ' \ 'ECCENTRICITY, INCLINATION_DEG, ' \ 'LONG_OF_ASC_NODE_DEG, ARG_OF_PERIH_DEG, ' \ 'MEAN_ANOMALY_DEG, EPOCH_ET ' \ 'FROM comets_main ' \ 'WHERE NAME="C/2019 Y4 (ATLAS)"', CON) # Convert the perihelion, that is given in AU, to km ATLAS_ORB_EL.loc[:, 'PERIHELION_KM'] = \ ATLAS_ORB_EL['PERIHELION_AU'].apply(lambda x: \ spiceypy.convrt(x, inunit='AU', \ outunit='km')) # Convert all angular parameters to radians, since the entries in the database # are stored in degrees. The for-loop iterates through all column names that # contain the word "DEG" for angle_col_name in [col for col in ATLAS_ORB_EL.columns if 'DEG' in col]: ATLAS_ORB_EL.loc[:, angle_col_name.replace('DEG', 'RAD')] = \ np.radians(ATLAS_ORB_EL[angle_col_name]) # Add the G*M value of the Sun ATLAS_ORB_EL.loc[:, 'SUN_GM'] = GM_SUN #%% # Extract all orbital elements / information in a SPICE compatible order (see # function conics)
""" Compare gaiaif_util.py corrections for parallax and stellar aberration to equivalent correction in SPICE """ import os import math import fov_cmd import sqlite3 as sl3 import spiceypy as sp import gaiaif_util as gifu ### Setup debugging and conversions; define some string constants do_debug = 'DEBUG' in os.environ rpd, aupkm = sp.rpd(), sp.convrt(1., 'km', 'au') ( earth, ssb, j2000, none, LT, LTS, ra_dec, declination, equals, ) = 'earth 0 j2000 none lt lt+s ra/dec declination ='.upper().split() sp.furnsh('de421.bsp') gaia_db = 'gaia.sqlite3'
import os import sys import math import numpy import spiceypy as sp try: dpr except: dpr = sp.dpr() ### degree / Radian rpd = sp.rpd() ### Radian / degree rpmas = sp.convrt(1.,'arcseconds','radians') * 1e-3 ### Radian / milliarcsecond aupkm = sp.convrt(1.,'km','au') ### Astonomical Unit / kilometer recip_clight = 1.0 / sp.clight() ######################################################################## class FOV(object): """ Field-Of-View (FOV) and methods to determine if a ray is inside the FOV Attributes .L Length of FOV argument to .__init__ .fovtype FOV type: FOV.CIRCLETYPE; RADECBOXTYPE;,.POLYGONTYPE .radecdegs List of [RA,Dec] pairs of input vectors/vertices, degrees .uvfovxyzs List of Unit vectors of [X,Y,Z] triples of input vectors .hangdeg Cone half-angle for circle FOV, degrees .hangrad Cone half-angle for circle FOV, radians .radec_boxes List of lists: FOV bounding boxes; ralo,rahi,declo,dechi .convex True is FOV is convex, else False
EARTH_STATE_WRT_SUN, EARTH_SUN_LT = sp.spkgeo(targ=399 \ ,et=ET_TODAY_MIDNIGHT \ ,ref='ECLIPJ2000' \ ,obs=10 ) print("state vector of the earth wrt the sun for \"today\" (midnight): {0}". format(EARTH_STATE_WRT_SUN)) # check AU EARTH_SUN_DISTANCE = math.sqrt(EARTH_STATE_WRT_SUN[0] ** 2 \ + EARTH_STATE_WRT_SUN[1] ** 2 \ + EARTH_STATE_WRT_SUN[2] ** 2 ) EARTH_SUN_DISTANCE_AU = sp.convrt(EARTH_SUN_DISTANCE, 'km', 'AU') print('CURRENT distance between Earth and Sun in AU: {0}'.format( EARTH_SUN_DISTANCE_AU)) EARTH_ORB_SPEED_WRT_SUN = math.sqrt(EARTH_STATE_WRT_SUN[3] ** 2 \ + EARTH_STATE_WRT_SUN[4] ** 2 \ + EARTH_STATE_WRT_SUN[5] ** 2 ) print('Current orbital speed of earth and around the sun in km/s: {0}'.format( EARTH_ORB_SPEED_WRT_SUN)) _, GM_SUN = sp.bodvcd(bodyid=10, item='GM', maxn=1) V_ORB_FUNC = lambda gm, r: math.sqrt(gm / r) EARTH_ORB_SPEED_WRT_SUN_THEORY = V_ORB_FUNC(GM_SUN[0], EARTH_SUN_DISTANCE)
#%% # Let's compute a state vector of the comet Hale-Bopp as an example # Extract the G*M value of the Sun and assign it to a constant _, GM_SUN_PRE = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1) GM_SUN = GM_SUN_PRE[0] # Get the Hale-Bopp data HALE_BOPP_DF = c_df.loc[c_df['Designation_and_name'].str.contains('Hale-Bopp')] # Set an array with orbital elements in a required format for the conics # function. Note: the mean anomaly is 0 degrees and will be set as a default # value in the SQLite database HALE_BOPP_ORB_ELEM = [spiceypy.convrt(HALE_BOPP_DF['Perihelion_dist'] \ .iloc[0], 'AU', 'km'), \ HALE_BOPP_DF['e'].iloc[0], \ np.radians(HALE_BOPP_DF['i'].iloc[0]), \ np.radians(HALE_BOPP_DF['Node'].iloc[0]), \ np.radians(HALE_BOPP_DF['Peri'].iloc[0]), \ 0.0, \ HALE_BOPP_DF['EPOCH_ET'].iloc[0], \ GM_SUN] #%% # Compute the state vector for midnight 2020-05-10 HALE_BOPP_ST_VEC = spiceypy.conics(HALE_BOPP_ORB_ELEM, \ spiceypy.utc2et('2020-05-10')) # Compare with results from https://ssd.jpl.nasa.gov/horizons.cgi
# In[14]: print(Earth_Sun_Light_Time) # In[15]: Earth_Sun_Dinstance = math.sqrt(Earth_State_Sun[0]**2.0 + Earth_State_Sun[1]**2.0 + Earth_State_Sun[2]**2.0) # In[16]: Earth_Sun_Dinstance_AU = spiceypy.convrt(Earth_Sun_Dinstance, 'km', 'AU') print('Current distance between the Earth and the Sun in AU:', Earth_Sun_Dinstance_AU) # In[17]: velocity = math.sqrt(Earth_State_Sun[3]**2.0 + Earth_State_Sun[4]**2.0 + Earth_State_Sun[5]**2.0) print('Current orbital speed of the Earth around the Sun in km/s:', velocity)
def get_planet_magnitude(object_id, pos_planet, pos_basis): """ Planet and Moon magnitudes """ planet_abs_mag = { 199: -0.42, # OBJECT_ID_MERCURY 299: -4.40, # OBJECT_ID_VENUS 399: -2.96, # OBJECT_ID_EARTH 499: -1.52, # OBJECT_ID_MARS 599: -9.40, # OBJECT_ID_JUPITER 699: -8.68, # OBJECT_ID_SATURN 799: -7.19, # OBJECT_ID_URANUS 899: -6.87, # OBJECT_ID_NEPTUNE 999: -1.00, # OBJECT_ID_PLUTO } # distance between each objects in AU d_planet_basis = spice.vdist(pos_planet, pos_basis) d_planet_basis = spice.convrt(d_planet_basis, "km", "AU") d_planet_sun = spice.vnorm(pos_planet) d_planet_sun = spice.convrt(d_planet_sun, "km", "AU") d_sun_basis = spice.vnorm(pos_basis) d_sun_basis = spice.convrt(d_sun_basis, "km", "AU") if object_id == OBJECT_ID_SUN: return -27.3 + 5.0 * np.log10(d_sun_basis) elif object_id == OBJECT_ID_MOON: return 0.38 elif object_id in [ OBJECT_ID_MERCURY, OBJECT_ID_VENUS, OBJECT_ID_EARTH, OBJECT_ID_MARS, OBJECT_ID_JUPITER, OBJECT_ID_SATURN, OBJECT_ID_URANUS, OBJECT_ID_NEPTUNE, OBJECT_ID_PLUTO, ]: pass else: return None mag = planet_abs_mag[object_id] mag += 5.0 * np.log10(d_planet_basis * d_planet_sun) if object_id <= OBJECT_ID_JUPITER: pa = 0.0 tpa = (d_planet_sun**2 + d_planet_basis**2 - d_sun_basis) / (2.0 * d_planet_sun * d_planet_basis) tpa = np.clip(tpa, -1.0, 1.0) pa = np.degrees(np.arccos(tpa)) if object_id == OBJECT_ID_MERCURY: mag += (0.0380 - 0.000273 * pa + 0.000002 * pa * pa) * pa elif object_id == OBJECT_ID_VENUS: mag += (0.0009 + 0.000239 * pa - 0.00000065 * pa * pa) * pa elif object_id == OBJECT_ID_MARS: mag += 0.016 * pa elif object_id == OBJECT_ID_JUPITER: mag += 0.005 * pa elif object_id == OBJECT_ID_SATURN: mag -= 1.1 * 0.3 return mag