def get_spice_target(body_name): """ Return the HelioPy target object Parameters ---------- body_name : `~str` The name of the SPICE target object. Returns ------- `~heliopy.space.Trajectory` """ # Parker Solar Probe (also sometimes referred to as Solar Probe Plus or SPP) if body_name == 'psp': spacecraft_kernels.load('psp') target = spice.Trajectory('SPP') elif body_name == 'stereo_a': spacecraft_kernels.load('stereo_a') target = spice.Trajectory('STEREO AHEAD') elif body_name == 'stereo_b': spacecraft_kernels.load('stereo_b') target = spice.Trajectory('STEREO BEHIND') elif body_name == 'soho': spacecraft_kernels.load('soho') target = spice.Trajectory('SOHO') else: target = None return target
def get_sc_lonlat_test(kernel, scname, frame, starttime, endtime, res_in_days): ''' make spacecraft positions kernel,scname,frame,starttime, endtime,res_in_days 'psp_pred','SPP','HEEQ',datetime(2018, 8,13),'datetime(2024, 8,13), 1 kernels: psp_pred, stereoa_pred, frames: ECLIPJ2000 HEE HEEQ, HCI frames https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/frames.html Appendix. ``Built in'' Inertial Reference Frames ''' spice.furnish(spicedata.get_kernel(kernel)) sc = spice.Trajectory(scname) sc_time = [] while starttime < endtime: sc_time.append(starttime) starttime += timedelta(days=res_in_days) sc_time_num = mdates.date2num(sc_time) sc.generate_positions(sc_time, 'Sun', frame) sc.change_units(astropy.units.AU) sc_r, sc_lat, sc_lon = cart2sphere(sc.x, sc.y, sc.z) screc = np.rec.array([sc_time_num, sc_r, sc_lon, sc_lat, sc.x, sc.y, sc.z], dtype=[('time', 'f8'), ('r', 'f8'), ('lon', 'f8'), ('lat', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8')]) return screc
def get_insitu_position_time(time1,insitu_location_string,insitu_str,insitu_kernel): insitu_exist=True if insitu_location_string=='PSP': #exclude if time before launch time if parse_time(time1).plot_date < parse_time(datetime.datetime(2018, 8, 13)).plot_date: insitu_exist=False if insitu_location_string=='Solo': if parse_time(time1).plot_date < parse_time(datetime.datetime(2020, 3, 1)).plot_date: insitu_exist=False if insitu_location_string=='Bepi': if parse_time(time1).plot_date < parse_time(datetime.datetime(2018, 10, 24)).plot_date: insitu_exist=False if insitu_location_string=='STB': if parse_time(time1).plot_date > parse_time(datetime.datetime(2014, 9, 27)).plot_date: insitu_exist=False if insitu_location_string=='Ulysses': #cut off ulysses when no decent in situ data is available anymore if parse_time(time1).plot_date > parse_time(datetime.datetime(2008, 5, 1)).plot_date: insitu_exist=False if insitu_exist == True: #insitu_kernel=spicedata.get_kernel('insitu_trajectories') #this needs to be an array, so make two similar times and take the first entry later insitu_time=[parse_time(time1).datetime,parse_time(time1).datetime] insitu=spice.Trajectory(insitu_str) frame='HEEQ' insitu.generate_positions(insitu_time,'Sun',frame) insitu.change_units(astropy.units.AU) [insitu_r, insitu_lat, insitu_lon]=hd.cart2sphere(insitu.x,insitu.y,insitu.z) #Earth position to Earth L1 if insitu_str=='3': insitu_r[0]=insitu_r[0]-1.5*1e6/AU insitu_time=np.array(insitu_time)[0] insitu_r=np.array(insitu_r)[0] insitu_lat=np.array(insitu_lat)[0] insitu_lon=np.array(insitu_lon)[0] else: insitu_time=np.nan insitu_r=np.nan insitu_lat=np.nan insitu_lon=np.nan return [insitu_time,insitu_r,np.degrees(insitu_lat),np.degrees(insitu_lon)]
def test_spice_sunpy_equivalence(): # Check that SPICE coordinates and the sunpy coordinates we associate # with those coordinates are the same t = ['1992-12-21'] b0 = Latitude(sunpy.coordinates.sun.B0(t)) l0 = sunpy.coordinates.sun.L0(t, light_travel_time_correction=False) earth = spice.Trajectory('Earth') earth.generate_positions(t, 'Sun', 'IAU_SUN') assert u.allclose(earth.coords.lon, l0, **_tols) assert u.allclose(earth.coords.lat, b0, **_tols)
def extractSolOrbit(self): """ Get the SPICE orbit data for SolO and put into coordsCarrington """ import heliopy.data.spice as spicedata import heliopy.spice as spice spicedata.get_kernel("solo") solo = spice.Trajectory("Solar Orbiter") times = list(self.df.index.to_pydatetime()) solo.generate_positions(times, 'Sun', 'IAU_SUN') # Is in KM self.coordsCarrington = solo.coords.transform_to( frame=frames.HeliographicCarrington)
def test_spice(): orbiter_kernel = spicedata.get_kernel('solo_2020') spice.furnish(orbiter_kernel) orbiter = spice.Trajectory('Solar Orbiter') # Generate 1000 days of data starttime = datetime(2020, 3, 1) times = [starttime + n * timedelta(days=1) for n in range(1000)] orbiter.generate_positions(times, 'Sun', 'ECLIPJ2000') assert orbiter.times == times # Check it works with numpy arrays too times = np.array(times) orbiter.generate_positions(times, 'Sun', 'ECLIPJ2000')
def kernel_loader(spacecraft: Union[int, str] = 2) -> spice.Trajectory: """ :param spacecraft: 1 or 2 for Helios 1 or 2, can also be 'ulysses' :return: unfurnished orbiter """ if spacecraft == 1 or spacecraft == 2: if spacecraft == 1: orbiter_kernel = spice_data.get_kernel('helios1_rec') else: orbiter_kernel = spice_data.get_kernel('helios2') spice.furnish(orbiter_kernel) orbiter = spice.Trajectory('Helios ' + str(spacecraft)) # elif spacecraft == 'ulysses': # orbiter_kernel = spice_data.get_kernel(str(spacecraft)) # spice.furnish(orbiter_kernel) # orbiter = spice.Trajectory(spacecraft) else: raise NotImplementedError('The only probes that can be imported are Helios 1 , Helios 2 and Ulysses') return orbiter
def get_planet_orbit(planet: str, start_date: str = '20/01/1976', end_date: str = '01/10/1979', interval: float = 1) -> spice.Trajectory: """ Finds the orbiter for a given planet :param planet: planet that we want to analyse :param start_date: start date of analysis :param end_date: end date of analysis :param interval: interval between each date in the orbiter, defaults to 1 :return: orbiter of the planet """ orbiter_kernel = spice_data.get_kernel('planet_trajectories') spice.furnish(orbiter_kernel) orbiter = spice.Trajectory(planet) start_time = datetime.strptime(start_date, '%d/%m/%Y') end_time = datetime.strptime(end_date, '%d/%m/%Y') times = [] while start_time < end_time: times.append(start_time) start_time = start_time + timedelta(days=interval) orbiter.generate_positions(times, 'Sun', 'ECLIPJ2000') orbiter.change_units(u.au) return orbiter
#sys.exit() ########################################## MAKE TRAJECTORIES ############################ ########################################## PSP starttime = datetime(2018, 8, 13) endtime = datetime(2025, 8, 31) psp_time = [] while starttime < endtime: psp_time.append(starttime) starttime += timedelta(days=res_in_days) psp_time_num = mdates.date2num(psp_time) spice.furnish(spicedata.get_kernel('psp_pred')) psp = spice.Trajectory('SPP') psp.generate_positions(psp_time, 'Sun', frame) print('PSP pos') psp.change_units(astropy.units.AU) [psp_r, psp_lat, psp_lon] = cart2sphere(psp.x, psp.y, psp.z) print('PSP conv') ############################################## BepiColombo starttime = datetime(2018, 10, 21) endtime = datetime(2025, 11, 2) bepi_time = [] while starttime < endtime: bepi_time.append(starttime) starttime += timedelta(days=res_in_days)
def solo_trajectory(): orbiter_kernel = spicedata.get_kernel('helios1') spice.furnish(orbiter_kernel) return spice.Trajectory('Helios 1')
its orbit for the first year. """ import heliopy.data.spice as spicedata import heliopy.spice as spice from datetime import datetime, timedelta import astropy.units as u import numpy as np ############################################################################### # Load the solar orbiter spice kernel. heliopy will automatically fetch and # load the latest kernel spicedata.get_kernel('psp') spicedata.get_kernel('psp_pred') psp = spice.Trajectory('SPP') ############################################################################### # Generate a time for every day between starttime and endtime starttime = datetime(2018, 8, 14) endtime = starttime + timedelta(days=365) times = [] while starttime < endtime: times.append(starttime) starttime += timedelta(hours=6) ############################################################################### # Generate positions psp.generate_positions(times, 'Sun', 'ECLIPJ2000') psp.change_units(u.au)
def psp_xyz(dtime): psp = spice.Trajectory('SPP') psp.generate_positions([dtime], 'Sun', 'IAU_SUN') psp.change_units(u.au) return np.array([psp.x.value, psp.y.value, psp.z.value])[:, 0]
def loc(dtime, body): traj = spice.Trajectory(body) traj.generate_positions([dtime], 'Sun', 'IAU_SUN') traj_coord = traj.coords traj_coord.representation_type = 'spherical' return traj_coord
# an hourly data cadence. starttime = '2018-10-22' endtime = '2018-11-21' psp_data = psp.merged_mag_plasma(starttime, endtime) print(psp_data.columns) ############################################################################### # Generate the PSP trajectory. # # We take the timestamps from the previously loaded data, and use `heliopy.spice` # to generate the trajectory at these times. times = psp_data.index spicedata.get_kernel('psp') spicedata.get_kernel('psp_pred') psp_traj = spice.Trajectory('SPP') psp_traj.generate_positions(times, 'Sun', 'IAU_SUN') psp_coords = psp_traj.coords print(psp_coords) ############################################################################### # Take a sample of the radial velocity. # # Here we start by getting the radial velocity `Variable` from the model, and # then use the PSP corodinate information to sample it. vr_model = model['vr'] vr_sampled = vr_model.sample_at_coords(psp_coords.lon, psp_coords.lat, psp_coords.radius) ############################################################################### # We can now plot a comparison between the model and in-situ measurements.
def solo_trajectory(): orbiter_kernel = spicedata.get_kernel('solo') spice.furnish(orbiter_kernel) return spice.Trajectory('Solar Orbiter')
# - Working with SPICE kernels # - Built-in support for: # - Helios, Juno, **PSP**, **Solar Orbiter**, STEREO, Ulysses # - Can work with custom SPICE kernels # ``heliopy.spice`` example # --- # In[11]: from heliopy import spice import heliopy.data.spice as spicedata # Download and load Solar Orbiter predicted SPICE kernel spice.furnish(spicedata.get_kernel('solo_2020')) solo = spice.Trajectory('Solar Orbiter') # In[12]: # Specify times at which to sample the trajectory from datetime import datetime, timedelta starttime = datetime(2020, 2, 20) times = [starttime + timedelta(days=i) for i in range(365)] # Generate the trajectory solo.generate_positions(times, 'Sun', 'ECLIPJ2000') # Print first 3 positions print('Positions:', solo.x[:3], solo.y[:3], solo.z[:3], sep='\n') # In[13]:
def earth_trajectory(times): traj = spice.Trajectory('earth') traj.generate_positions(times, 'Sun', 'IAU_SUN') return traj
def make_positions(): ########################################## PSP starttime =datetime(2018, 8,13) endtime = datetime(2025, 8, 31) psp_time = [] while starttime < endtime: psp_time.append(starttime) starttime += timedelta(days=res_in_days) psp_time_num=mdates.date2num(psp_time) spice.furnish(spicedata.get_kernel('psp_pred')) psp=spice.Trajectory('SPP') psp.generate_positions(psp_time,'Sun',frame) print('PSP pos') psp.change_units(astropy.units.AU) [psp_r, psp_lat, psp_lon]=cart2sphere(psp.x,psp.y,psp.z) print('PSP conv') ############################################## BepiColombo starttime =datetime(2018, 10, 21) endtime = datetime(2025, 11, 2) bepi_time = [] while starttime < endtime: bepi_time.append(starttime) starttime += timedelta(days=res_in_days) bepi_time_num=mdates.date2num(bepi_time) spice.furnish(spicedata.get_kernel('bepi_pred')) bepi=spice.Trajectory('BEPICOLOMBO MPO') # or BEPICOLOMBO MMO bepi.generate_positions(bepi_time,'Sun',frame) bepi.change_units(astropy.units.AU) [bepi_r, bepi_lat, bepi_lon]=cart2sphere(bepi.x,bepi.y,bepi.z) print('Bepi') #################################################### Solar Orbiter starttime = datetime(2020, 3, 1) endtime = datetime(2026, 1, 1) solo_time = [] while starttime < endtime: solo_time.append(starttime) starttime += timedelta(days=res_in_days) solo_time_num=mdates.date2num(solo_time) spice.furnish(spicedata.get_kernel('solo_2020')) solo=spice.Trajectory('Solar Orbiter') solo.generate_positions(solo_time, 'Sun',frame) solo.change_units(astropy.units.AU) [solo_r, solo_lat, solo_lon]=cart2sphere(solo.x,solo.y,solo.z) print('Solo') plt.figure(1, figsize=(12,9)) plt.plot_date(psp_time,psp_r,'-', label='R') plt.plot_date(psp_time,psp_lat,'-',label='lat') plt.plot_date(psp_time,psp_lon,'-',label='lon') plt.ylabel('AU / RAD') plt.legend() plt.figure(2, figsize=(12,9)) plt.plot_date(bepi_time,bepi_r,'-', label='R') plt.plot_date(bepi_time,bepi_lat,'-',label='lat') plt.plot_date(bepi_time,bepi_lon,'-',label='lon') plt.title('Bepi Colombo position '+frame) plt.ylabel('AU / RAD') plt.legend() plt.figure(3, figsize=(12,9)) plt.plot_date(solo_time,solo_r,'-', label='R') plt.plot_date(solo_time,solo_lat,'-',label='lat') plt.plot_date(solo_time,solo_lon,'-',label='lon') plt.title('Solar Orbiter position '+frame) plt.ylabel('AU / RAD') plt.legend() ########### plots ######## R with all three plt.figure(4, figsize=(16,10)) plt.plot_date(psp_time,psp.r,'-',label='PSP') plt.plot_date(bepi_time,bepi.r,'-',label='Bepi Colombo') plt.plot_date(solo_time,solo.r,'-',label='Solar Orbiter') plt.legend() plt.title('Heliocentric distance of heliospheric observatories') plt.ylabel('AU') plt.savefig('results/positions_plots/bepi_psp_solo_R.png') ##### Longitude all three plt.figure(5, figsize=(16,10)) plt.plot_date(psp_time,psp_lon*180/np.pi,'-',label='PSP') plt.plot_date(bepi_time,bepi_lon*180/np.pi,'-',label='Bepi Colombo') plt.plot_date(solo_time,solo_lon*180/np.pi,'-',label='Solar Orbiter') plt.legend() plt.title(frame+' longitude') plt.ylabel('DEG') plt.savefig('results/positions_plots/bepi_psp_solo_longitude_'+frame+'.png') ############# Earth for mercury, venusus, STA #https://docs.heliopy.org/en/stable/data/spice.html planet_kernel=spicedata.get_kernel('planet_trajectories') starttime =datetime(2018, 1, 1) endtime = datetime(2028, 12, 31) earth_time = [] while starttime < endtime: earth_time.append(starttime) starttime += timedelta(days=res_in_days) earth_time_num=mdates.date2num(earth_time) earth=spice.Trajectory('399') #399 for Earth, not barycenter (because of moon) earth.generate_positions(earth_time,'Sun',frame) earth.change_units(astropy.units.AU) [earth_r, earth_lat, earth_lon]=cart2sphere(earth.x,earth.y,earth.z) print('Earth') ################ mercury mercury_time_num=earth_time_num mercury=spice.Trajectory('1') #barycenter mercury.generate_positions(earth_time,'Sun',frame) mercury.change_units(astropy.units.AU) [mercury_r, mercury_lat, mercury_lon]=cart2sphere(mercury.x,mercury.y,mercury.z) print('mercury') ################# venus venus_time_num=earth_time_num venus=spice.Trajectory('2') venus.generate_positions(earth_time,'Sun',frame) venus.change_units(astropy.units.AU) [venus_r, venus_lat, venus_lon]=cart2sphere(venus.x,venus.y,venus.z) print('venus') ############### Mars mars_time_num=earth_time_num mars=spice.Trajectory('4') mars.generate_positions(earth_time,'Sun',frame) mars.change_units(astropy.units.AU) [mars_r, mars_lat, mars_lon]=cart2sphere(mars.x,mars.y,mars.z) print('mars') #############stereo-A sta_time_num=earth_time_num spice.furnish(spicedata.get_kernel('stereo_a_pred')) sta=spice.Trajectory('-234') sta.generate_positions(earth_time,'Sun',frame) sta.change_units(astropy.units.AU) [sta_r, sta_lat, sta_lon]=cart2sphere(sta.x,sta.y,sta.z) print('STEREO-A') #save positions if high_res_mode: pickle.dump([psp_time,psp_time_num,psp_r,psp_lon,psp_lat,bepi_time,bepi_time_num,bepi_r,bepi_lon,bepi_lat,solo_time,solo_time_num,solo_r,solo_lon,solo_lat], open( 'positions_plots/psp_solo_bepi_'+frame+'_1min.p', "wb" ) ) sys.exit() else: psp=np.rec.array([psp_time_num,psp_r,psp_lon,psp_lat, psp.x, psp.y,psp.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) bepi=np.rec.array([bepi_time_num,bepi_r,bepi_lon,bepi_lat,bepi.x, bepi.y,bepi.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) solo=np.rec.array([solo_time_num,solo_r,solo_lon,solo_lat,solo.x, solo.y,solo.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) sta=np.rec.array([sta_time_num,sta_r,sta_lon,sta_lat,sta.x, sta.y,sta.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) earth=np.rec.array([earth_time_num,earth_r,earth_lon,earth_lat, earth.x, earth.y,earth.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) venus=np.rec.array([venus_time_num,venus_r,venus_lon,venus_lat, venus.x, venus.y,venus.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) mars=np.rec.array([mars_time_num,mars_r,mars_lon,mars_lat, mars.x, mars.y,mars.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) mercury=np.rec.array([mercury_time_num,mercury_r,mercury_lon,mercury_lat,mercury.x, mercury.y,mercury.z],dtype=[('time','f8'),('r','f8'),('lon','f8'),('lat','f8'),('x','f8'),('y','f8'),('z','f8')]) pickle.dump([psp, bepi, solo, sta, earth, venus, mars, mercury,frame], open( 'results/positions_psp_solo_bepi_sta_planets_'+frame+'_2hours.p', "wb" ) ) #load with [psp, bepi, solo, sta, earth, venus, mars, mercury,frame]=pickle.load( open( 'positions_psp_solo_bepi_sta_planets_HCI_6hours_2018_2025.p', "rb" ) ) end=time.time() print( 'generate position took time in seconds:', round((end-start),1) )
def test_coord_err(): t = ['1992-12-21'] earth = spice.Trajectory('Earth') earth.generate_positions(t, 'Sun', 'IAU_SUN', abcorr='LT') with pytest.raises(NotImplementedError): earth.coords
from datetime import datetime, timedelta import matplotlib.pyplot as plt import numpy as np import astropy.units as u import heliopy.data.spice as spicedata import heliopy.spice as spice ############################################################################### # Load the Solar Orbiter spice kernel. HelioPy will automatically fetch and # load the latest kernel. We can then inspect the kernel to check what the # date coverage is for Solar Orbiter. kernels = spicedata.get_kernel('solo') solo = spice.Trajectory('Solar Orbiter') coverage = kernels[0].coverage(spice.Body('Solar Orbiter')) print(coverage) ############################################################################### # Next we define a set of times at which to sample the orbit. starttime = coverage[0] times = [starttime + timedelta(days=i) for i in range(1, 5 * 365)] ############################################################################### # Generate positions. "IAU_SUN" is a Carrington frame of reference. solo.generate_positions(times, 'Sun', 'IAU_SUN') coords = solo.coords ############################################################################### # Plot radial distance and elevation as a function of time
def get_satellite_position_heliopy(satname, timestamp, refframe='J2000', refobject='Sun', rlonlat=False, returnobj=False): """Uses Heliopy's spice to get position information. Will automatically download required kernels. Returns positions in km. Parameters ========== satname : str Satellite name. Currently available: ['stereo_a', 'stereo_a_pred', 'earth'] timestamp : datetime / list of datetimes Datetime objects to iterate through and return positions for. refframe : str String denoting reference frame to use for position. refobject : str (default='Sun') String for reference onject, e.g. 'Sun' or 'Earth' rlonlat : bool (default=False) If True, returns coordinates in (r, lon, lat) format, not (x,y,z). returnobj : bool (default=False) If True, returns heliopy.Trajectory object instead of arrays. Returns ======= If returnobj: returns heliopy.spice.Trajectory object. else: returns tuple of (x,y,z) or (r,lon,lat) if rlonlat=True """ if isinstance(timestamp, datetime): timestamp = [timestamp] elif isinstance(timestamp, list): pass else: logger.warning( "get_satellite_position_heliopy: Don't recognise input timestamp format!" ) if 'stereoa' in satname.lower().replace('-', '').replace('_', ''): if 'pred' in satname.lower(): heliostr = 'stereo_a_pred' else: heliostr = 'stereo_a' satstr = 'STEREO AHEAD' elif 'stereob' in satname.lower().replace('-', '').replace('_', ''): if 'pred' in satname.lower(): heliostr = 'stereo_b_pred' else: heliostr = 'stereo_b' satstr = 'STEREO BEHIND' elif satname.lower() in [ 'mercury', 'venus', 'earth', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune' ]: heliostr = 'planet_trajectories' satstr = satname hspice.furnish(spicedata.get_kernel(heliostr)) pos = hspice.Trajectory(satstr) pos.generate_positions(timestamp, refobject, refframe) if returnobj: return pos #pos.change_units('AU') if rlonlat: r, theta, phi = cart2sphere(pos.x, pos.y, pos.z) return (r, phi, theta) else: return (pos.x, pos.y, pos.z)