def cassini_titan_altlatlon(tempdatetime): et = spice.datetime2et(tempdatetime) state, ltime = spice.spkezr('CASSINI', et, 'IAU_TITAN', 'NONE', 'TITAN') lon, lat, alt = spice.recpgr('TITAN', state[:3], spice.bodvrd('TITAN', 'RADII', 3)[1][0], 2.64e-4) return alt, lat * spice.dpr(), lon * spice.dpr()
def cassini_altlatlon(utc, target='TITAN', output=False): state = cassini_phase(utc) lon, lat, alt = spice.recpgr(target, state[:3], spice.bodvrd(target, 'RADII', 3)[1][0], 2.64e-4) if output: print("ALtitude", alt) print("Latitude", lat * spice.dpr()) print("Longtitude", lon * spice.dpr()) return alt, lat * spice.dpr(), lon * spice.dpr()
def printBoresights(angleSeparationA, angleSeparationB): """input manual rotation angles from SPICE kernels to calculate new and old boresight""" oldSoBoresight = [0.0, 0.0, 1.0] oldUVISBoresight = [0.0, 0.0, 1.0] rotationMatrixSoUVIS = sp.pxform("TGO_NOMAD_SO", "TGO_NOMAD_UVIS_OCC", sp.utc2et("2018 APR 01 00:00:00 UTC")) oldSoBoresightUVIS = np.dot(oldSoBoresight, rotationMatrixSoUVIS.T) oldBoresightSeparation = sp.vsep(oldUVISBoresight, oldSoBoresightUVIS) * sp.dpr() * 60.0 print("oldBoresightSeparation") print(oldBoresightSeparation) print("angleSeparationB") print(angleSeparationB) #####SAVE THIS IT WORKS!!!###### newSoBoresightTGO = np.asfarray([ -1.0 * np.sin(angleSeparationB / sp.dpr()), \ np.sin(angleSeparationA / sp.dpr()) * np.cos(angleSeparationB / sp.dpr()), \ np.cos(angleSeparationA / sp.dpr()) * np.cos(angleSeparationB / sp.dpr())]) print("newSoBoresightTGO, vnorm = %0.6f" % sp.vnorm(newSoBoresightTGO)) print(newSoBoresightTGO) newUVISBoresightTGO = np.asfarray( [-0.922221097920913, -0.386613383297695, 0.006207330031467]) oldSoBoresightTGO = np.asfarray([-0.92156, -0.38819, 0.00618]) oldUVISBoresightTGO = np.asfarray( [-0.92207347097, -0.3869614566418, 0.0064300242046]) oldNewSoBoresightSeparation = sp.vsep(newSoBoresightTGO, oldSoBoresightTGO) * sp.dpr() * 60.0 print("oldNewSoBoresightSeparation") print(oldNewSoBoresightSeparation) oldNewUVISBoresightSeparation = sp.vsep( newUVISBoresightTGO, oldUVISBoresightTGO) * sp.dpr() * 60.0 print("oldNewUVISBoresightSeparation") print(oldNewUVISBoresightSeparation) newSoUVISBoresightSeparation = sp.vsep( newSoBoresightTGO, newUVISBoresightTGO) * sp.dpr() * 60.0 print("newSoUVISBoresightSeparation") print(newSoUVISBoresightSeparation) oldSoUVISBoresightSeparation = sp.vsep( oldSoBoresightTGO, oldUVISBoresightTGO) * sp.dpr() * 60.0 print("oldSoUVISBoresightSeparation") print(oldSoUVISBoresightSeparation)
def get_sun_sizes(utc_start, utc_end, step_size): """get sun angular size and time steps given start and end times""" #spice constants abcorr = "None" #tolerance = "1" #method = "Intercept: ellipsoid" #prec = 3 #shape = "Ellipsoid" #load spiceypy kernels os.chdir(KERNEL_DIRECTORY) sp.furnsh(KERNEL_DIRECTORY + os.sep + METAKERNEL_NAME) print(sp.tkvrsn("toolkit")) os.chdir(BASE_DIRECTORY) utctimestart = sp.str2et(utc_start) utctimeend = sp.str2et(utc_end) durationseconds = utctimeend - utctimestart nsteps = int(np.floor(durationseconds / step_size)) timesteps = np.arange(nsteps) * step_size + utctimestart ref = "J2000" observer = "-143" target = "SUN" #get TGO-SUN pos tgo2sunpos = [ sp.spkpos(target, time, ref, abcorr, observer)[0] for time in timesteps ] sunaxes = sp.bodvrd("SUN", "RADII", 3)[1][0] #get mars axis values return ([np.arctan((sunaxes*2.0)/np.linalg.norm(tgo2sunVector))*sp.dpr()*60.0 \ for tgo2sunVector in tgo2sunpos], timesteps)
def get_geometry_info(obs2refmtx, fov, width, height): cvec = spice.vhat(fov.bounds_rect.center_vec) cvec_ref = spice.mxv(obs2refmtx, cvec) # Azimuth in the upward direction of the screen mvec = spice.vhat(fov.bounds_rect.top_vec) mvec_ref = spice.mxv(obs2refmtx, mvec) pa, dist = vec_padist(cvec_ref, mvec_ref) pos_angle = pa * spice.dpr() # Pixel resolution up to the center of the screen top edge vp = viewport_frustum(fov.bounds_rect, width, height, mvec) angle_res = dist / (height / 2.0 - vp[1]) * spice.dpr() _, ra, dec = spice.recrad(cvec_ref) return pos_angle, angle_res, ra * spice.dpr(), dec * spice.dpr()
def dataToPickle(): orbits_begin = {1:'2016-07-31T19:46:02', 2:'2016-09-23T03:44:48', 3:'2016-11-15T05:36:45', 4:'2017-01-07T03:11:30', 5:'2017-02-28T22:55:48', 6:'2017-04-22T19:14:57'} file_dict = {} metaKernel = 'juno_2019_v03.tm' spice.furnsh(metaKernel) start_time = datetime.datetime.strptime(orbits_begin[1],'%Y-%m-%dT%H:%M:%S') end_time = datetime.datetime.strptime(orbits_begin[2],'%Y-%m-%dT%H:%M:%S') data_folder = pathlib.Path(r'..\data\fgm') p = re.compile(r'\d{7}') for parent,child,files in os.walk(data_folder): for name in files: if name.endswith('.csv'): file_path = os.path.join(data_folder,name) search = p.search(name).group() date = datetime.datetime.strptime(search,'%Y%j') if date.date() >= start_time.date() and date.date() <= end_time.date(): iso_date = date.strftime('%Y-%m-%d') if iso_date not in file_dict.keys(): file_dict[iso_date] = [file_path] elif iso_date in file_dict.keys() and file_dict[iso_date] != file_path: file_dict[iso_date].append(file_path) for date in file_dict.keys(): fgmdf = pd.DataFrame(data={'TIME':[],'BX':[],'BY':[],'BZ':[],'LAT':[]}) save_date = datetime.datetime.strptime(date,'%Y-%m-%d') file_list = file_dict[date] for file in file_list: temp = pd.read_csv(file) datetime_list = temp['SAMPLE UTC'] time_list = [datetime.datetime.fromisoformat(i).strftime('%H:%M:%S') for i in datetime_list] for index,time in enumerate(datetime_list): position, lighttime = spice.spkpos('JUNO',spice.utc2et(time),'IAU_JUPITER','NONE','JUPITER') vectorPos = spice.vpack(position[0],position[1],position[2]) radii,longitude,latitude = spice.reclat(vectorPos) lat = latitude*spice.dpr() if lat >= -10 and lat <= 10: fgmdf = fgmdf.append({'TIME':time,'BX':temp['BX PLANETOCENTRIC'][index],'BY':temp['BY PLANETOCENTRIC'][index],'BZ':temp['BZ PLANETOCENTRIC'][index],'LAT':lat},ignore_index=True) fgmdf = fgmdf.sort_values(by=['TIME']) save_name = f'{save_date.strftime("%Y%m%d")}' save_path = pathlib.Path(f'..\data\pickledfgm\jno_fgm_{save_name}.pkl') pickledf = fgmdf.to_pickle(save_path) print(f'Saved pickle {date}')
def findBoresightUsed(et, boresight_vectors, boresight_names): obs2SunVector = sp.spkpos("SUN", et, SPICE_REFERENCE_FRAME, SPICE_ABERRATION_CORRECTION, SPICE_OBSERVER) v_norm = obs2SunVector[0]/sp.vnorm(obs2SunVector[0]) v_sep_min = 999.0 for boresight_vector, boresight_name in zip(boresight_vectors, boresight_names): v_sep = sp.vsep(v_norm, boresight_vector) * sp.dpr() * 60.0 #arcmins difference if v_sep < v_sep_min: v_sep_min = v_sep boresight_found = boresight_name return boresight_found, v_sep_min
def caps_ramdirection_azielv(tempdatetime, observ='titan'): """ Returns the azimuth and elevation of the ramdirection """ ram_unit = cassini_ramdirection_SCframe(tempdatetime, observ=observ) sc2CAPS = np.array(([0, -1, 0], [-1, 0, 0], [0, 0, -1])) ram_unit_CAPS = spice.mxv(sc2CAPS, ram_unit) # print(ram_unit_CAPS) ram_unit_azielv = np.array(spice.reclat(ram_unit_CAPS)[1:]) * spice.dpr() return ram_unit_azielv[0], ram_unit_azielv[1]
def __init__(self, inst_id): fov = spice.getfov(inst_id, Fov.MAX_ROOMS) self._shape = fov[0] self._frame = fov[1] self._boresight = fov[2] self._nbounds = fov[3] self._bounds = fov[4] self._bounds_rect = self._calc_bounds_rect() self._fovmax = self._calc_fovmax() self._fovy = ( spice.vsep(self.bounds_rect.center_vec, self.bounds_rect.top_vec) * 2.0 * spice.dpr()) self._aspect = self.bounds_rect.aspect
def positionData(self): # spice.furnsh(self.meta) #loads the meta kernel that will load all kernels needed time = spice.utc2et(self.time) self.position, lighttime = spice.spkpos( 'JUNO', time, 'IAU_JUPITER', 'NONE', 'JUPITER' ) #Finds the position in cartesian coords relative to jupiter pos = spice.vpack(self.position[0], self.position[1], self.position[2]) #Packs the position into a vector self.distance, self.longitude, self.latitude = spice.reclat( pos) #Finds radial dist, latitide and longitude self.latitude *= spice.dpr() self.distance /= 69911
def __init__(self, inst, et, abcorr, obsrvr, width, height, mag_limit): # input parameter self.inst = inst self.et = et self.abcorr = abcorr self.obsrvr = obsrvr self.width = width self.height = height # parameters equivalent to input parameter self.date = spice.et2utc(et, "ISOC", 3) self.inst_id = spice.bodn2c(inst) # Instrument FOV self.fov = Fov(self.inst_id) self.fov_in_degrees = self.fov.fovmax * 2.0 * spice.dpr() # geometry information self.pos, _ = spice.spkpos(obsrvr, et, self.fov.frame, abcorr, "SUN") self.obs2refmtx = spice.pxform(self.fov.frame, "J2000", et) self.ref2obsmtx = spice.pxform("J2000", self.fov.frame, et) # screen information pos_angle, angle_res, ra, dec = get_geometry_info( self.obs2refmtx, self.fov, width, height ) self.center = self.fov.bounds_rect.center_vec self.pos_angle = pos_angle self.angle_res = angle_res self.ra = ra self.dec = dec # searched objects self.solar_objects = search_solar_objects(self) self.stars = search_stars(self, mag_limit)
Created on Mon Sep 3 11:31:52 2018 @author: iant """ import spiceypy as sp import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D method = "Ellipsoid" target = "MARS" fixref = "IAU_MARS" abcorr = "None" obsrvr = "SUN" spoint = sp.latrec(3390, -24.6 / sp.dpr(), 18.3 / sp.dpr()) et = sp.utc2et("2003 OCT 28, 00:00:00") step = 60 for loop in range(100): time = et + step * loop time_string = sp.et2utc(time, "C", 0) sza = sp.ilumin(method, target, time, fixref, abcorr, obsrvr, spoint)[3] * sp.dpr() def writeLog(file_name, lines_to_write): """function to append log file""" # global LOG_PATHS logFile = open(file_name + ".csv", 'w')
#make pointing vectors between tgo and sun positions line_vectors = tgo2sun_pos #np.asfarray([[tgo_vec[0]-sun_vec[0],tgo_vec[1]-sun_vec[1],tgo_vec[2]-sun_vec[2]] for tgo_vec,sun_vec in zip(list(tgo_pos),list(sun_pos))]) #calculate surface tangent point using pointing vectors and tgo position vs time print("Calculating tangent points") tangent_coords = np.asfarray([ sp.npedln(mars_axes[0], mars_axes[1], mars_axes[2], line_point, line_vector)[0] for line_point, line_vector in zip( list(line_points), list(line_vectors)) ]) tangent_lonlats1 = np.asfarray([ sp.reclat(tangent_coord) for tangent_coord in list(tangent_coords) ]) tangent_lonlats = np.asfarray( [[tangent_lonlat[1] * sp.dpr(), tangent_lonlat[2] * sp.dpr()] for tangent_lonlat in list(tangent_lonlats1)]) tangent_lsts = [ sp.et2lst(time, 499, (tangent_lonlat[0] / sp.dpr()), "PLANETOCENTRIC")[3] for time, tangent_lonlat in zip(list(times), list(tangent_lonlats)) ] tangent_lsts_hours = np.asfarray([ np.float(tangent_lst[0:2]) + np.float(tangent_lst[3:5]) / 60.0 + np.float(tangent_lst[6:8]) / 3600.0 for tangent_lst in tangent_lsts ]) nadir_lonlats = np.asfarray( [sp.reclat(mars2tgo) for mars2tgo in list(mars2tgo_pos)])[:, 1:3] * sp.dpr() nadir_lsts = [
def lsubs(et): return sp.lspcn("MARS", et, abcorr) * sp.dpr()
def do_main(argv): sp.kclear() halfpi, dpr = sp.halfpi(), sp.dpr() fnck = 'out.bc' target = 'TEMPEL 1' frame = 'DIF_SPACECRAFT' for arg in argv: if arg.startswith('--ck='): fnck = arg[5:] elif arg.startswith('--target='): target = arg[9:] elif arg.startswith('--k='): sp.furnsh(arg[4:]) else: assert False, 'Unknown argument [{0}]'.format(arg) frameid = sp.gipool('FRAME_{0}'.format(frame), 0, 1)[0] scid = sp.gipool('CK_{0}_SPK'.format(frameid), 0, 1)[0] scname = sp.bodc2s(scid, 99) cover = sp.stypes.SPICEDOUBLE_CELL(200) sp.scard(0, cover) cover = sp.ckcov(fnck, frameid, False, "INTERVAL", 0.0, "TDB") sp.furnsh(fnck) vbore = sp.vpack(-1, 0, 0) vorbitnorm = sp.vpack(0, 1, 0) for ipair in range(sp.wncard(cover)): et0, etend = sp.wnfetd(cover, 0) etlast, ettca, niter = et0, (et0 + etend) * 0.5, 0 while ettca != etlast and niter < 20: etlast = ettca state6 = sp.spkezr(target, ettca, "j2000", "none", scname)[0] vpos, vvel = state6[:3], state6[3:] det = sp.vdot(vvel, vpos) / sp.vdot(vvel, vvel) ettca -= det niter += 1 print(dict( TCAtdb=sp.etcal(ettca, 99), niter=niter, )) et = et0 ets, boreerrs, orbitnormerrs = list(), list(), list() while et <= etend: state6 = sp.spkezr(target, et, frame, "none", scname)[0] vpos, vvel = state6[:3], state6[3:] ets.append(et - et0) boreerrs.append(dpr * sp.vsep(vbore, vpos)) orbitnormerrs.append(dpr * (sp.vsep(vbore, vorbitnorm) - halfpi)) et += max([0.01, 0.1 * abs(cos(sp.vsep(vpos, vvel)))]) try: plt.plot(ets, orbitnormerrs, 'o', label='Orbit normal error') plt.plot(ets, boreerrs, 'o', label='Boresight error') plt.axvline(ettca - et0, label='TCA') plt.xlabel('Time, s past {0} TDB'.format(sp.etcal(et0, 99))) plt.ylabel('Error, deg') plt.legend(loc='best') plt.show() except: if do_debug: import traceback as tb tb.print_exc() print(boreerrs[::1000]) print(orbitnormerrs[::1000])
def caps_crosstrack_latlon(time, negwindspeed, poswindspeed, anodes=False): anode_vecs = [] anode_seps = [[], [], [], [], [], [], [], []] beamanodes = [] # print(time) beamanodes.append(np.mean(ELS_ramanodes(time)) + 1) state = cassini_phase(time.strftime('%Y-%m-%dT%H:%M:%S')) # crossvec = caps_crosstrack(time, windspeed) * abs(windspeed) * 1e-3 #Old Method crossvec, anode1, anode8 = caps_crosstrack_spice( time, np.mean([negwindspeed, poswindspeed])) # SPICE Plane method crossvec_neg = crossvec * 1e-3 crossvec_pos = crossvec * 1e-3 print("crossvec", crossvec_neg, crossvec_pos) newstate_neg = list(state[:3]) + list(crossvec_neg) newstate_pos = list(state[:3]) + list(crossvec_pos) transformed_state_neg = spice.xfmsta(newstate_neg, 'RECTANGULAR', 'Latitudinal', "TITAN") transformed_state_pos = spice.xfmsta(newstate_pos, 'RECTANGULAR', 'Latitudinal', "TITAN") print("test state", newstate_neg, newstate_pos) print("test xfmsta", transformed_state_neg, transformed_state_pos) alt = transformed_state_neg[0] lon = transformed_state_neg[1] * spice.dpr() lat = transformed_state_neg[2] * spice.dpr() if anodes: anode_vecs.append(caps_all_anodes(time)) for anodecounter, i in enumerate(anode_vecs[-1]): anode_seps[anodecounter].append( spice.vsep(spice.vhat(state[3:]), spice.vhat(anode_vecs[-1][anodecounter])) * spice.dpr()) print("anode_vecs", anode_vecs) print("anode_seps", anode_seps) dvec_neg = [ transformed_state_neg[4], transformed_state_neg[5], transformed_state_neg[3] ] dvec_pos = [ transformed_state_pos[4], transformed_state_pos[5], transformed_state_pos[3] ] print("dvec xfmsta", dvec_neg, dvec_pos) print(lon, lat, alt) titanrad = spice.bodvrd('TITAN', 'RADII', 3)[1][0] # Get Titan Radius mag_test_neg = spice.unorm([ dvec_neg[0] * (alt + titanrad) * 1e3, dvec_neg[1] * (alt + titanrad) * 1e3, dvec_neg[2] * 1e3 ]) mag_test_pos = spice.unorm([ dvec_pos[0] * (alt + titanrad) * 1e3, dvec_pos[1] * (alt + titanrad) * 1e3, dvec_pos[2] * 1e3 ]) # Convert Lat/Lon from rad/s to m/s, convert Alt from km/s to m/s. Forms Unit Vector here print("mag test", mag_test_pos) dlon_neg = mag_test_neg[0][0] * abs(negwindspeed) dlat_neg = mag_test_neg[0][1] * abs(negwindspeed) dalt_neg = mag_test_neg[0][2] * abs(negwindspeed) dlon_pos = mag_test_pos[0][0] * abs(poswindspeed) dlat_pos = mag_test_pos[0][1] * abs(poswindspeed) dalt_pos = mag_test_pos[0][2] * abs(poswindspeed) return lon, lat, alt, dlon_neg, dlat_neg, dalt_neg, dlon_pos, dlat_pos, dalt_pos
typein = "PLANETOCENTRIC" body = 499 etStart = sp.utc2et("2018MAR24-11:50:00 UTC") etEnd = sp.utc2et("2020MAR24-11:50:00 UTC") ets = np.linspace(etStart, etEnd, num=180) writeOutput("UTC Time, LSubS, Longitude, Latitude, Local Solar Time") for et in list(ets): lSubS = lsubs(et) terminatorPoints = sp.edterm(trmtyp, source, target, et, ref, abcorr, observer, npts) terminatorLatLonsRad = np.asfarray([ sp.reclat(terminatorPoint)[1:3] for terminatorPoint in terminatorPoints[2] ]) terminatorLatLonsDeg = terminatorLatLonsRad * sp.dpr() terminatorLSTs = [ sp.et2lst(et, body, terminatorLatLonRad[0], typein)[3] for terminatorLatLonRad in list(terminatorLatLonsRad) ] for index, terminatorLST in enumerate(terminatorLSTs): writeOutput("%s,%0.2f,%0.2f,%0.2f,%s" % (et2utc(et), lSubS, terminatorLatLonsDeg[index, 0], terminatorLatLonsDeg[index, 1], terminatorLST))
def mrotat(): # # Convert our UTC string to seconds past J2000 TDB. # timstr = '2007 JAN 1 00:00:00' et = spiceypy.str2et(timstr) # # Look up the apparent position of the Earth relative # to the Moon's center in the IAU_MOON frame at ET. # [imoonv, ltime] = spiceypy.spkpos('earth', et, 'iau_moon', 'lt+s', 'moon') # #Express the Earth direction in terms of longitude #and latitude in the IAU_MOON frame. # [r, lon, lat] = spiceypy.reclat(imoonv) print('\n' 'Moon-Earth direction using low accuracy\n' 'PCK and IAU_MOON frame:\n' 'Earth lon (deg): {0:15.6f}\n' 'Earth lat (deg): {1:15.6f}\n'.format(lon * spiceypy.dpr(), lat * spiceypy.dpr())) # # Look up the apparent position of the Earth relative # to the Moon's center in the MOON_ME frame at ET. # [mmoonv, ltime] = spiceypy.spkpos('earth', et, 'moon_me', 'lt+s', 'moon') # # Express the Earth direction in terms of longitude # and latitude in the MOON_ME frame. # [r, lon, lat] = spiceypy.reclat(mmoonv) print('Moon-Earth direction using high accuracy\n' 'PCK and MOON_ME frame:\n' 'Earth lon (deg): {0:15.6f}\n' 'Earth lat (deg): {1:15.6f}\n'.format(lon * spiceypy.dpr(), lat * spiceypy.dpr())) # # Find the angular separation of the Earth position # vectors in degrees. # sep = spiceypy.dpr() * spiceypy.vsep(imoonv, mmoonv) print('For IAU_MOON vs MOON_ME frames:') print('Moon-Earth vector separation angle (deg): ' '{:15.6f}\n'.format(sep)) # # Look up the apparent position of the Earth relative # to the Moon's center in the MOON_PA frame at ET. # [pmoonv, ltime] = spiceypy.spkpos('earth', et, 'moon_pa', 'lt+s', 'moon') # # Express the Earth direction in terms of longitude # and latitude in the MOON_PA frame. # [r, lon, lat] = spiceypy.reclat(pmoonv) print('Moon-Earth direction using high accuracy\n' 'PCK and MOON_PA frame:\n' 'Earth lon (deg): {0:15.6f}\n' 'Earth lat (deg): {1:15.6f}\n'.format(lon * spiceypy.dpr(), lat * spiceypy.dpr())) # # Find the angular separation of the Earth position # vectors in degrees. # sep = spiceypy.dpr() * spiceypy.vsep(pmoonv, mmoonv) print('For MOON_PA vs MOON_ME frames:') print('Moon-Earth vector separation angle (deg): ' '{:15.6f}\n'.format(sep)) # # Find the apparent sub-Earth point on the Moon at ET # using the MOON_ME frame. # [msub, trgepc, srfvec] = spiceypy.subpnt('near point: ellipsoid', 'moon', et, 'moon_me', 'lt+s', 'earth') # # Display the sub-point in latitudinal coordinates. # [r, lon, lat] = spiceypy.reclat(msub) print('Sub-Earth point on Moon using high accuracy\n' 'PCK and MOON_ME frame:\n' 'Sub-Earth lon (deg): {0:15.6f}\n' 'Sub-Earth lat (deg): {1:15.6f}\n'.format(lon * spiceypy.dpr(), lat * spiceypy.dpr())) # # Find the apparent sub-Earth point on the Moon at # ET using the MOON_PA frame. # [psub, trgepc, srfvec] = spiceypy.subpnt('near point: ellipsoid', 'moon', et, 'moon_pa', 'lt+s', 'earth') # # Display the sub-point in latitudinal coordinates. # [r, lon, lat] = spiceypy.reclat(psub) print('Sub-Earth point on Moon using high accuracy\n' 'PCK and MOON_PA frame:\n' 'Sub-Earth lon (deg): {0:15.6f}\n' 'Sub-Earth lat (deg): {1:15.6f}\n'.format(lon * spiceypy.dpr(), lat * spiceypy.dpr())) # # Find the distance between the sub-Earth points # in km. # dist = spiceypy.vdist(msub, psub) print('Distance between sub-Earth points (km): ' '{:15.6f}\n'.format(dist))
def __Geometry(self, boresight=''): #if self.geometry_flag is True and \ # self.time.window.all() == self.previous_tw.all(): # return distance = [] altitude = [] boresight_latitude = [] boresight_longitude = [] latitude = [] longitude = [] subpoint_xyz = [] subpoint_pgc = [] subpoint_pcc = [] zaxis_target_angle = [] myaxis_target_angle = [] yaxis_target_angle = [] xaxis_target_angle = [] beta_angle = [] qs, qx, qy, qz = [], [], [] ,[] x, y, z = [],[],[] tar = self.target time = self.time for et in time.window: try: # # Compute the distance # ptarg, lt = spiceypy.spkpos(tar.name, et, tar.frame, time.abcorr, self.name) x.append(ptarg[0]) y.append(ptarg[1]) z.append(ptarg[2]) vout, vmag = spiceypy.unorm(ptarg) distance.append(vmag) # # Compute the geometric sub-observer point. # if tar.frame == 'MARSIAU': tar_frame = 'IAU_MARS' else: tar_frame = tar.frame spoint, trgepc, srfvec = spiceypy.subpnt(tar.method, tar.name, et, tar_frame, time.abcorr, self.name) subpoint_xyz.append(spoint) # # Compute the observer's altitude from SPOINT. # dist = spiceypy.vnorm(srfvec) altitude.append(dist) # # Convert the sub-observer point's rectangular coordinates to # planetographic longitude, latitude and altitude. # spglon, spglat, spgalt = spiceypy.recpgr(tar.name, spoint, tar.radii_equ, tar.flat) # # Convert radians to degrees. # spglon *= spiceypy.dpr() spglat *= spiceypy.dpr() subpoint_pgc.append([spglon, spglat, spgalt]) # # Convert sub-observer point's rectangular coordinates to # planetocentric radius, longitude, and latitude. # spcrad, spclon, spclat = spiceypy.reclat(spoint) # # Convert radians to degrees. # spclon *= spiceypy.dpr() spclat *= spiceypy.dpr() subpoint_pcc.append([spclon, spclat, spcrad]) latitude.append(spclat) #TODO: Remove with list extraction longitude.append(spclon) # TODO: Remove with list extraction # # Compute the geometric sub-boresight point. # if tar.frame == 'MARSIAU': tar_frame = 'IAU_MARS' else: tar_frame = tar.frame if boresight: try: id = spiceypy.bodn2c(boresight) (shape,framen, bsight, n, bounds) = spiceypy.getfov(id, 80) mat = spiceypy.pxform(framen,tar_frame,et) except: framen = boresight bsight = 0,0,1 else: bsight = self.name try: if tar.method == 'INTERCEPT/ELLIPSOID': method = 'ELLIPSOID' else: method = tar.method spoint, trgepc, srfvec = spiceypy.sincpt(method, tar.name, et, tar_frame, time.abcorr, self.name, framen, bsight) # # Convert the sub-observer point's rectangular coordinates to # planetographic longitude, latitude and altitude. # spglon, spglat, spgalt = spiceypy.recpgr(tar.name, spoint, tar.radii_equ, tar.flat) # # Convert radians to degrees. # spglon *= spiceypy.dpr() spglat *= spiceypy.dpr() # # Convert sub-observer point's rectangular coordinates to # planetocentric radius, longitude, and latitude. # spcrad, spclon, spclat = spiceypy.reclat(spoint) # # Convert radians to degrees. # spclon *= spiceypy.dpr() spclat *= spiceypy.dpr() boresight_latitude.append(spclat) boresight_longitude.append(spclon) except: pass # # Compute the angle between the observer's S/C axis and the # geometric sub-observer point # obs_tar, ltime = spiceypy.spkpos(tar.name, et, 'J2000', time.abcorr, self.name) obs_zaxis = [0, 0, 1] obs_myaxis = [0, -1, 0] obs_yaxis = [0, 1, 0] obs_xaxis = [1, 0, 0] # # We need to account for when there is no CK attitude available. # try: matrix = spiceypy.pxform(self.frame, 'J2000', et) z_vecout = spiceypy.mxv(matrix, obs_zaxis) zax_target_angle = spiceypy.vsep(z_vecout, obs_tar) zax_target_angle *= spiceypy.dpr() zaxis_target_angle.append(zax_target_angle) my_vecout = spiceypy.mxv(matrix, obs_myaxis) myax_target_angle = spiceypy.vsep(my_vecout, obs_tar) myax_target_angle *= spiceypy.dpr() myaxis_target_angle.append(myax_target_angle) y_vecout = spiceypy.mxv(matrix, obs_myaxis) yax_target_angle = spiceypy.vsep(y_vecout, obs_tar) yax_target_angle *= spiceypy.dpr() yaxis_target_angle.append(yax_target_angle) x_vecout = spiceypy.mxv(matrix, obs_myaxis) xax_target_angle = spiceypy.vsep(x_vecout, obs_tar) xax_target_angle *= spiceypy.dpr() xaxis_target_angle.append(xax_target_angle) quat = spiceypy.m2q(spiceypy.invert(matrix)) qs.append(quat[0]) qx.append(-1*quat[1]) qy.append(-1*quat[2]) qz.append(-1*quat[3]) except: zaxis_target_angle.append(0.0) myaxis_target_angle.append(0.0) yaxis_target_angle.append(0.0) xaxis_target_angle.append(0.0) qs.append(0.0) qx.append(0.0) qy.append(0.0) qz.append(0.0) beta_angle.append(spiops.beta_angle(self.name, self.target.name, et)) except: boresight_latitude = 0 boresight_longitude = 0 distance = 0 altitude = 0 latitude = 0 longitude = 0 subpoint_xyz = [0,0,0] subpoint_pgc = [0,0,0] subpoint_pcc = [0,0,0] zaxis_target_angle = 0 myaxis_target_angle = 0 yaxis_target_angle = 0 xaxis_target_angle = 0 beta_angle = 0 (qx, qy, qz, qs) = 0, 0, 0, 0 (x, y, z) = 0, 0, 0 self.boresight_latitude = boresight_latitude self.boresight_longitude = boresight_longitude self.distance = distance self.altitude = altitude self.latitude = latitude self.longitude = longitude self.subpoint_xyz = subpoint_xyz self.subpoint_pgc = subpoint_pgc self.subpoint_pcc = subpoint_pcc self.zaxis_target_angle = zaxis_target_angle self.myaxis_target_angle = myaxis_target_angle self.yaxis_target_angle = yaxis_target_angle self.xaxis_target_angle = xaxis_target_angle self.beta_angle = beta_angle self.quaternions = [qx, qy, qz, qs] self.trajectory = [x,y,z] self.geometry_flag = True self.previous_tw = self.time.window return
import spiceypy as sp import traceback as tb do_debug = 'DEBUG' in os.environ ######################################################################## ### Parse command-line argument(s), setup parameters ### --hang=<cone half-angle, degrees> default_hang = 30.0 hangdeg = float( ([default_hang] + [s[7:] for s in sys.argv[1:] if s.startswith('--hang=')]).pop()) ### Conversion factors between degrees and radians dpr, rpd = sp.dpr(), sp.rpd() ### Cone half-angle and samples of Declinations, from 0 to (89.5-delta) decdegs = [(0.5 * decdec) - (decdec > 0 and 1e-6 or 0) for decdec in range(180)] ### Convert to radians hangrad = rpd * hangdeg decrads = [rpd * decdeg for decdeg in decdegs] ### Trig functions of same tansqhang = math.tan(hangrad)**2 sinhang = math.sin(hangrad) coshang = math.cos(hangrad) ### List of triples of tan(Dec) squared, cos(Dec), and Dec
def writeTimeLsToFile(): """make list of time vs ls""" SPICE_TARGET = "MARS" SPICE_ABERRATION_CORRECTION = "None" DATETIME_FORMAT = "%d/%m/%Y %H:%M" from datetime import datetime, timedelta linesToWrite = [] datetimeStart = datetime(2018, 3, 1, 0, 0, 0, 0) for hoursToAdd in range(0, 24*31*12*3, 6): #3 years newDatetime = (datetimeStart + timedelta(hours=hoursToAdd)).strftime(DATETIME_FORMAT) ls = sp.lspcn(SPICE_TARGET, sp.utc2et(str(datetimeStart + timedelta(hours=hoursToAdd))), SPICE_ABERRATION_CORRECTION) * sp.dpr() linesToWrite.append("%s\t%0.1f" %(newDatetime, ls)) writeOutput("Time_vs_Ls.txt", linesToWrite)
def analyseLineScan(hdf5Files, hdf5Filenames, titles): # referenceFrame = "TGO_NOMAD_UVIS_OCC" referenceFrame = "TGO_NOMAD_SO" # referenceFrame = "TGO_SPACECRAFT" fig, ax = plt.subplots(figsize=(FIG_X, FIG_Y)) #new boresight X direction is assumed to be zero if not calculated meanParFit = 0.0 #new boresight Y direction is assumed to be zero if not calculated meanPerpFit = 0.0 for fileIndex, hdf5File in enumerate(hdf5Files): #add indices bounding each pass across the sun if hdf5Filenames[fileIndex] in ["20180511_084630_0p3a_SO_1_C"]: lineScanCentreIndicesAll = [ range(60, 120, 1), range(280, 340, 1), range(400, 490, 1), range(630, 720, 1), range(760, 850, 1), range(990, 1060, 1), range(1150, 1200, 1) ] completeLineScanIndices = range(7) analyse = True parallel = True firstBinRow = 116 firstBinScience = 0 elif hdf5Filenames[fileIndex] in ["20180428_023343_0p3a_SO_1_C"]: lineScanCentreIndicesAll = [ range(230, 370, 1), range(380, 520, 1), range(520, 680, 1) ] completeLineScanIndices = range(3) analyse = False parallel = False firstBinRow = 116 firstBinScience = 0 elif hdf5Filenames[fileIndex] in ["20180522_221149_0p3a_SO_1_C"]: lineScanCentreIndicesAll = [ range(280, 300, 1), range(440, 470, 1), range(590, 650, 1), range(760, 815, 1), range(925, 970, 1), range(1100, 1120, 1) ] completeLineScanIndices = range(1, 5, 1) analyse = True parallel = False firstBinRow = 116 firstBinScience = 0 elif hdf5Filenames[fileIndex] in ["20180821_193241_0p3a_SO_1_C"]: lineScanCentreIndicesAll = [ range(60, 120, 1), range(280, 340, 1), range(400, 490, 1), range(630, 720, 1), range(760, 850, 1), range(990, 1060, 1), range(1150, 1200, 1) ] completeLineScanIndices = range(7) analyse = True parallel = True firstBinRow = 128 firstBinScience = 1 elif hdf5Filenames[fileIndex] in ["20180828_223824_0p3a_SO_1_C"]: lineScanCentreIndicesAll = [ range(60, 140, 1), range(250, 330, 1), range(430, 510, 1), range(610, 690, 1), range(790, 870, 1), range(960, 1030, 1), range(1150, 1220, 1) ] completeLineScanIndices = range(1, 5, 1) analyse = True parallel = False firstBinRow = 128 firstBinScience = 1 else: print("Error: please add filename and indices to list") detectorDataAll = get_dataset_contents(hdf5File, "Y")[0] print(detectorDataAll.shape) plt.figure() plt.plot(detectorDataAll[:, :, 200]) hdf5File = hdf5Files[fileIndex] print("Reading in file %i: %s" % (fileIndex + 1, obspaths[fileIndex])) detectorDataAll = get_dataset_contents(hdf5File, "Y")[0] binsAll = get_dataset_contents(hdf5File, "Bins")[0] observationTimeStringsAll = get_dataset_contents( hdf5File, "ObservationDateTime")[0] # hdf5File.close() centreBinIndices = np.where( binsAll[:, 0, 0] == firstBinRow)[0] #window stepping, so find 1st bin centreRowIndex = np.where(binsAll[firstBinScience, :, 0] == 128)[ 0] #then find which row is the centre of the detector in that bin centrePixelIndex = 200 detectorDataCentreFrames = detectorDataAll[ centreBinIndices, :, :] #get data for frames containing centre bins observationTimeStringsCentreFrames = observationTimeStringsAll[ centreBinIndices, :] observationTimesCentreFrames = np.asfarray([ np.mean( [sp.utc2et(timeCentreFrame[0]), sp.utc2et(timeCentreFrame[1])]) for timeCentreFrame in list(observationTimeStringsCentreFrames) ]) detectorDataCentrePixel = detectorDataCentreFrames[:, centreRowIndex, centrePixelIndex] #get data for detector centre row centreLineCentrePixel = detectorDataCentreFrames[:, centreRowIndex, centrePixelIndex].flatten( ) nFrames = centreLineCentrePixel.shape[0] maxValuesFrameIndices = [] maxValuesPixelCounts = [] plt.figure(figsize=(FIG_X, FIG_Y)) for lineScanCentreIndices in lineScanCentreIndicesAll: centreLineCentrePixelFit = polynomialFitSimple( np.arange(len(centreLineCentrePixel[lineScanCentreIndices])), centreLineCentrePixel[lineScanCentreIndices], 5) indexMaxValue = centreLineCentrePixelFit.argmax() maxValuesFrameIndices.append(lineScanCentreIndices[indexMaxValue]) maxValuesPixelCounts.append( centreLineCentrePixelFit[indexMaxValue]) plt.plot(lineScanCentreIndices, centreLineCentrePixelFit) plt.plot(centreLineCentrePixel) plt.scatter(maxValuesFrameIndices, maxValuesPixelCounts, c="k") maxValuesFrameIndices = np.asarray(maxValuesFrameIndices) maxValuesPixelCounts = np.asarray(maxValuesPixelCounts) maxValuesVectors = np.asfarray([ get_vector(datetime, referenceFrame) for datetime in observationTimesCentreFrames[maxValuesFrameIndices] ]) #find peak of curves (but don't use for calculation, only for plottingS) maxValuesPerpFit = polynomialFitSimple( maxValuesFrameIndices[completeLineScanIndices], maxValuesPixelCounts[completeLineScanIndices], 2, x_out=np.arange(nFrames)) plt.plot(np.arange(nFrames), maxValuesPerpFit) maxPerpIndex = maxValuesPerpFit.argmax() plt.scatter(maxPerpIndex, maxValuesPerpFit[maxPerpIndex]) unitVectors = np.asfarray([ get_vector(datetime, referenceFrame) for datetime in observationTimesCentreFrames ]) # marker_colour = np.log(detectorDataCentrePixel+1000).flatten() marker_colour = detectorDataCentrePixel.flatten() ax.set_xlim([-0.004, 0.004]) ax.set_ylim([-0.004, 0.004]) ax.set_xlabel("%s FRAME X" % referenceFrame) ax.set_ylabel("%s FRAME Y" % referenceFrame) ax.scatter(unitVectors[:, 0], unitVectors[:, 1], c=marker_colour, vmin=300000, alpha=0.5, cmap="jet", linewidths=0) ax.set_aspect("equal") ax.scatter(maxValuesVectors[:, 0], maxValuesVectors[:, 1], c="k") if analyse: if parallel: #mean X meanParFit = np.mean(maxValuesVectors[:, 0]) ax.scatter(0.0, 0.0, marker="x", c="k", s=160) ax.plot([meanParFit, meanParFit], [maxValuesVectors[0, 1], maxValuesVectors[-1, 1]], "k") vectorOrigin = [0.0, 0.0, 1.0] vectorNew = [meanParFit, meanPerpFit, 0.0] vectorNew[2] = np.sqrt(1.0 - vectorNew[0]**2 - vectorNew[1]**2) print("vectorNew (1 direction only)") print(vectorNew) angleSeparation = sp.vsep(vectorOrigin, vectorNew) * sp.dpr() * 60.0 print("angleSeparation (1 direction only)") print(angleSeparation) else: #mean Y meanPerpFit = np.mean(maxValuesVectors[:, 1]) ax.scatter(0.0, 0.0, marker="x", c="k", s=160) ax.plot([maxValuesVectors[0, 0], maxValuesVectors[-1, 0]], [meanPerpFit, meanPerpFit], "k") vectorOrigin = [0.0, 0.0, 1.0] vectorNew = [meanParFit, meanPerpFit, 0.0] vectorNew[2] = np.sqrt(1.0 - vectorNew[0]**2 - vectorNew[1]**2) print("vectorNew (1 direction only)") print(vectorNew) angleSeparation = sp.vsep(vectorOrigin, vectorNew) * sp.dpr() * 60.0 print("angleSeparation (1 direction only)") print(angleSeparation) if meanParFit != 0.0 and meanPerpFit != 0.0: """plot and label new/old boresights on plot""" ax.scatter(0.0, 0.0, marker="x", c="k", s=160) # ax.scatter(meanParFit,meanPerpFit, marker="x", c="k", s=160) offset = 0.0001 ax.text(0.0 + offset, 0.0 + offset * 1.5, "Origin") # ax.text(meanParFit+offset,meanPerpFit-offset*2.0,"New Boresight") ax.plot([meanParFit, meanParFit], [maxValuesVectors[0, 1], maxValuesVectors[-1, 1]], "k") ax.plot([meanParFit, meanParFit], [np.min(unitVectors[:, 1]), np.max(unitVectors[:, 1])], "k") circle1 = plt.Circle((0.0, 0.0), 10.0 / 60.0 / sp.dpr(), color='k', alpha=0.1) # circle1 = plt.Circle((meanParFit,meanPerpFit), 10.0/60.0/sp.dpr(), color='k', alpha=0.1) ax.add_artist(circle1)
def getFGMData(self,fgm_folder): #Mag data for each cooresponding crossing is found self.file_dict = {} p = re.compile(r'\d{7}') for parent,child,files in os.walk(fgm_folder): for file_name in files: if file_name.endswith('.csv'): file_path = os.path.join(fgm_folder,file_name) date = p.search(file_name).group() date_iso = datetime.datetime.strptime(date,'%Y%j').strftime('%Y-%m-%d') match = self.crossingdf.loc[self.crossingdf['DATE'] == date_iso] self.cdfdf = self.cdfdf.append(match,ignore_index = True) if date_iso not in self.file_dict.keys(): self.file_dict[date_iso] = file_path #The mag data is sorted through and two hours on either side of the crossing is pulled for row in self.cdfdf.itertuples(): date = row[1] time = row[2] type = row[3] crossing_stamp = datetime.datetime.strptime(f'{date}T{time}','%Y-%m-%dT%H:%M:%S') if date in self.file_dict.keys(): fgm_data = pd.read_csv(self.file_dict[date]) time_list = [datetime.datetime.fromisoformat(i) for i in fgm_data['SAMPLE UTC']] #crossing_index = min(time_list,key=lambda x: abs(x-crossing_stamp)) crossing_index_plus = time_list.index(min(time_list,key=lambda x: abs(x-(crossing_stamp+datetime.timedelta(hours=2))))) crossing_index_minus = time_list.index(min(time_list,key=lambda x: abs(x-(crossing_stamp-datetime.timedelta(hours=2))))) save_time_list = [i.isoformat() for i in time_list[crossing_index_minus:crossing_index_plus+1]] spice.furnsh('juno_2019_v03.tm') spice_time_list = [spice.utc2et(i) for i in save_time_list] position_list = [] latitude_list = [] x,y,z=[],[],[] for spice_time in spice_time_list: pos,lt = spice.spkpos('JUNO',spice_time,'IAU_JUPITER','NONE','JUPITER') pos_vec = spice.vpack(pos[0],pos[1],pos[2]) rad_pos,long,lat = spice.reclat(pos_vec) lat *= spice.dpr() rad_pos /= 69911 pos,lt = spice.spkpos('JUNO',spice_time,'IAU_SUN','NONE','JUPITER') x.append(pos[0]) y.append(pos[1]) z.append(pos[2]) position_list.append(rad_pos) latitude_list.append(lat) spice.kclear() file_save_date = crossing_stamp.strftime('%Y%jT%H%M%S') + f'_{type}' cdf_file = pycdf.CDF(f'..\crossings\cdf\jno_mag_{file_save_date}.cdf','') cdf_file.attrs['Author'] = 'Andrew Schok' cdf_file['TIME'] = save_time_list cdf_file['BX DATA'] = fgm_data['BX PLANETOCENTRIC'][crossing_index_minus:crossing_index_plus+1] cdf_file['BX DATA'].attrs['units'] = 'nT' cdf_file['BY DATA'] = fgm_data['BY PLANETOCENTRIC'][crossing_index_minus:crossing_index_plus+1] cdf_file['BY DATA'].attrs['units'] = 'nT' cdf_file['BZ DATA'] = fgm_data['BZ PLANETOCENTRIC'][crossing_index_minus:crossing_index_plus+1] cdf_file['BZ DATA'].attrs['units'] = 'nT' cdf_file['X POSITION'] = x cdf_file['X POSITION'].attrs['units'] = 'km' cdf_file['Y POSITION'] = y cdf_file['Y POSITION'].attrs['units'] = 'km' cdf_file['Z POSITION'] = z cdf_file['Z POSITION'].attrs['units'] = 'km' cdf_file['RADIAL DISTANCE'] = position_list cdf_file['RADIAL DISTANCE'].attrs['units'] = 'Rj' cdf_file['LATITUDE'] = latitude_list cdf_file['LATITUDE'].attrs['units'] = 'deg' cdf_file.close() print(f'Created CDF for {type} crossing {crossing_stamp.strftime("%Y-%m-%dT%H:%M:%S")}')
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
BASE_DIRECTORY = os.path.normcase(r"C:\Users\ithom\Dropbox\NOMAD\Python") KERNEL_DIRECTORY = os.path.normcase(r"D:\kernels\kernels\mk") FIG_X = 18 FIG_Y = 9 """load spiceypy kernels""" METAKERNEL_NAME = r"em16_ops_win.tm" os.chdir(KERNEL_DIRECTORY) sp.furnsh(KERNEL_DIRECTORY + os.sep + METAKERNEL_NAME) print(sp.tkvrsn("toolkit")) os.chdir(BASE_DIRECTORY) origin = np.asfarray([0.0, 0.0, 0.0]) #vectorOffsetX = 3.0**(-1/2) #vectorOffsetY = 3.0**(-1/2) vectorOffsetX = np.arcsin(1.9992 / sp.dpr()) #2 degrees vectorOffsetY = np.arcsin(15.0 * 88 / 90 / sp.dpr()) #15 vectorOffsetZ = np.sqrt(1.0 - vectorOffsetX**2 - vectorOffsetY**2) vector = np.asfarray([vectorOffsetX, vectorOffsetY, vectorOffsetZ]) vectorMagnitude = sp.vnorm(vector) #should be 1 vector2 = np.asfarray([0.0, 0.0, 1.0]) angleSeparation = sp.vsep(vector / vectorMagnitude, vector2) * sp.dpr() #X to Z #vectorA = np.asfarray([vector[0], 0.0, vector[2]])/sp.vnorm([vector[0], 0.0, vector[2]]) vectorA = np.asfarray([vector[0], 0.0, np.sqrt(1.0 - vector[0]**2)]) angleSeparationA = sp.vsep(vectorA / sp.vnorm(vectorA), vector2) * sp.dpr()
target = "SUN" datetime_start = datetime(year=2018, month=4, day=21) datetimes = [datetime_start + timedelta(days=x) for x in range(365 * 4)] date_strs = [datetime.strftime(x, "%Y-%m-%d") for x in datetimes] date_ets = [sp.str2et(x) for x in date_strs] tgo_pos = np.asfarray([ sp.spkpos(target, time, ref, abcorr, observer)[0] for time in list(date_ets) ]) tgo_dist = la.norm(tgo_pos, axis=1) code = sp.bodn2c(target) pradii = sp.bodvcd(code, 'RADII', 3) # 10 = Sun sun_radius = pradii[1][0] sun_diameter_arcmins = np.arctan(sun_radius / tgo_dist) * sp.dpr() * 60.0 * 2.0 fig, ax = plt.subplots(figsize=(FIG_X, FIG_Y - 1)) ax.plot_date(datetimes, sun_diameter_arcmins, linestyle="-", ms=0) ax.set_xlabel("Date") ax.set_ylabel("Solar diameter as seen from TGO (arcminutes)") ax.set_title("Apparent diameter of Sun since start of TGO mission") ax.xaxis.set_major_locator(MonthLocator(bymonth=None, interval=6, tz=None)) fig.tight_layout() if SAVE_FIGS: plt.savefig("sun_apparent_diameter.png")
def geometry(et, bsight, target, frame, sensor, observer=''): if not observer: observer = sensor # Time tag [UTC] # pixel id [(x,y)] # corner id [(x,y)] # Requested geometry # lat lon intersection (planetocentric) # lat lon subspacecraft # lat lon subsolar # target distance intersection # target angular diameter # local solar time intersection # phase angle intersection # emission angle intersection # incidence angle intersection # # We retrieve the camera information using GETFOV. More info available: # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/getfov_c.html # sensor_id = spiceypy.bodn2c(sensor) (shape, sensor_frame, ibsight, vectors, bounds) = spiceypy.getfov(sensor_id, 100) visible = spiceypy.fovtrg(sensor, target, 'ELLIPSOID', frame, 'LT+S', observer, et) if not visible: return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 tarid = spiceypy.bodn2c(target) n, radii = spiceypy.bodvrd(target, 'RADII', 3) re = radii[0] rp = radii[2] f = (re - rp) / re try: # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html # # For each pixel we compute the possible intersection with the target, if # the target is intersected we then compute the illumination angles. We # use the following SPICE APIs: SINCPT and ILLUMF # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/illumf_c.html # (spoint, trgepc, srfvec) = \ spiceypy.sincpt('ELLIPSOID', target, et, frame, 'LT+S', observer, sensor_frame, bsight) (tarlon, tarlat, taralt) = spiceypy.recgeo(spoint, re, f) tardis = spiceypy.vnorm(srfvec) # # Angular diameter # tarang = np.degrees( 2 * np.arctan(max(radii) / spiceypy.vnorm(spoint + srfvec))) # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/illumf_c.html # (trgenpc, srfvec, phase, incdnc, emissn, visiblef, iluminatedf) = \ spiceypy.illumf('ELLIPSOID', target, 'SUN', et, frame, 'LT+S', observer, spoint) phase *= spiceypy.dpr() incdnc *= spiceypy.dpr() emissn *= spiceypy.dpr() # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/et2lst_c.html # # VARIABLE I/O DESCRIPTION # -------- --- -------------------------------------------------- # et I Epoch in seconds past J2000 epoch. # body I ID-code of the body of interest. # lon I Longitude of surface point (RADIANS). # type I Type of longitude "PLANETOCENTRIC", etc. # timlen I Available room in output time string. # ampmlen I Available room in output `ampm' string. # hr O Local hour on a "24 hour" clock. # mn O Minutes past the hour. # sc O Seconds past the minute. # time O String giving local time on 24 hour clock. # ampm O String giving time on A.M./ P.M. scale. (hr, mn, sc, ltime, ampm) = \ spiceypy.et2lst(et, tarid, tarlon, 'PLANETOCENTRIC', 80, 80) # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subpnt_c.html # # Variable I/O Description # -------- --- -------------------------------------------------- # method I Computation method. # target I Name of target body. # et I Epoch in TDB seconds past J2000 TDB. # fixref I Body-fixed, body-centered target body frame. # abcorr I Aberration correction flag. # obsrvr I Name of observing body. # spoint O Sub-observer point on the target body. # trgepc O Sub-observer point epoch. # srfvec O Vector from observer to sub-observer point # (spoint, trgepc, srfev) = \ spiceypy.subpnt('INTERCEPT/ELLIPSOID', target, et, frame, 'LT+S', observer) (sublon, sublat, subalt) = spiceypy.recgeo(spoint, re, f) # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subslr_c.html # # Variable I/O Description # -------- --- -------------------------------------------------- # method I Computation method. # target I Name of target body. # et I Epoch in ephemeris seconds past J2000 TDB. # fixref I Body-fixed, body-centered target body frame. # abcorr I Aberration correction. # obsrvr I Name of observing body. # spoint O Sub-solar point on the target body. # trgepc O Sub-solar point epoch. # srfvec O Vector from observer to sub-solar point. # (spoint, trgepc, srfev) = \ spiceypy.subslr('INTERCEPT/ELLIPSOID', target, et, frame, 'LT+S', observer) (sunlon, sunlat, sunalt) = spiceypy.recgeo(spoint, re, f) return tarlon, tarlat, sublon, sublat, sunlon, sunlat, tardis, tarang, ltime, phase, emissn, incdnc except: return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
def caps_crosstrack_spice(tempdatetime, windspeed): et = spice.datetime2et(tempdatetime) sclkdp = spice.sce2c( -82, et) # converts an et to a continuous encoded sc clock (ticks) state, ltime = spice.spkezr("CASSINI", et, "IAU_TITAN", "NONE", "titan") ramdir = spice.vhat(state[3:6]) # print("ramdir",ramdir) # Gets Attitude sclkdp = spice.sce2c( -82, et) # converts an et to a continuous encoded sc clock (ticks) ckgp_output = spice.ckgp(-82000, sclkdp, 0, "IAU_TITAN") cmat = ckgp_output[0] print("cmat", cmat) ram_unit = spice.mxv(cmat, ramdir) # Ram Unit in SC coords # print("ram_unit", ram_unit) anglediff = spice.vsepg( ram_unit[:2], np.array([0, 1, 0]), 2) # Find azimuthal angle between normal boresight and ram direction # print("anglediff", anglediff * spice.dpr()) cassini_ram_mat = spice.rotate(-anglediff, 3) # print("cassini_ram_mat", cassini_ram_mat) # Rotates rotational axis with actuation # cassini_caps_mat = spice.ckgp(-82821, sclkdp, 0, 'CASSINI_CAPS_BASE')[0] # Rotation matrix of actuation # print("cassini_caps_mat", cassini_caps_mat) anode_rotational_axis = spice.mxv(cassini_ram_mat, np.array([1, 0, 0])) # Rotate with actuator print("Rotational Axis", anode_rotational_axis) rotationmatrix_1 = spice.spiceypy.axisar(anode_rotational_axis, -70 * spice.rpd()) rotationmatrix_2 = spice.spiceypy.axisar(anode_rotational_axis, 70 * spice.rpd()) ram_unit_rotated1 = spice.mxv(rotationmatrix_1, ram_unit) ram_unit_rotated2 = spice.mxv(rotationmatrix_2, ram_unit) scframe_spiceplane = spice.psv2pl([0, 0, 0], ram_unit_rotated1, ram_unit_rotated2) print("ram_unit", ram_unit, ram_unit_rotated1, ram_unit_rotated2) print("SC frame spice normal", spice.psv2pl([0, 0, 0], ram_unit_rotated1, ram_unit_rotated2)) cmat_t = spice.xpose(cmat) ram_unit_rotated1_titan = spice.mxv( cmat_t, ram_unit_rotated1) # Transform back to IAU Titan Frame ram_unit_rotated2_titan = spice.mxv( cmat_t, ram_unit_rotated2) # Transform back to IAU Titan Frame spiceplanenormal = spice.mxv(cmat_t, spice.pl2nvp(scframe_spiceplane)[0]) # Old method finding normal in titan frame # spiceplane = spice.psv2pl(state[:3], ram_unit_rotated1_titan, ram_unit_rotated2_titan) # spiceplanenormal = spice.pl2nvp(spiceplane)[0] print("SPICE NORMAL", spiceplanenormal) # print("Spice normal, sc frame", scframe_spicenormal_titan) if windspeed > 0: spiceplanenormal = -1 * spiceplanenormal print("spice plane fipped", windspeed, spiceplanenormal) print("vsep titan frame", spice.vsep(ramdir, spiceplanenormal) * spice.dpr()) return spiceplanenormal, ram_unit_rotated1_titan, ram_unit_rotated2_titan
--mags (Retrieve all magnitudes, phot_*_mean_mag) --heavy (Retrieve source_id, errors and corr. coeffs, , *error, *corr) --obspos=X,Y,Z (Observer position, km, triggers parallax correction) --obsvel=VX,VY,VZ (Observer velocity, km/s, triggers stellar aberration correction) --obsy=YYYY.ddd (Observer time, fractional year, triggers proper motion correction) """ import os import sys import pprint import sqlite3 as sl3 import spiceypy as sp import gaiaif_util as gifu dpr = sp.dpr() ### Allowed magnitude types magtypes = set('g bp rp'.split()) do_debug = 'DEBUG' in os.environ ######################################################################## def gaiaif(fov_vertices ,rtn_limit=200 ,magmin=None,magmax=None ,mag_type='g' ,radec_buffer=0.0 ### Not yet implemented ,gaia_sl3='gaia.sqlite3' ,j2000=False
def cassini_titan_test(flyby, anodes=False): times = [] states = [] lons, lats, alts = [], [], [] crossvecs_lonlatalts = [] crossvecs_lonlatalts_spicenormal = [] cmats = [] vecs = [] anode_vecs = [] anode_seps = [[], [], [], [], [], [], [], []] anodes1, anodes8 = [], [] crossvecs = [] angularseparations = [] beamanodes = [] spiceplanenormals = [] windsdf = pd.read_csv("crosswinds_full.csv", index_col=0, parse_dates=True) tempdf = windsdf[windsdf['Flyby'] == flyby] for tempdatetime, negwindspeed, poswindspeed in zip( pd.to_datetime(tempdf['Bulk Time']), tempdf["Negative crosstrack velocity"], tempdf["Positive crosstrack velocity"]): print("---------") print(tempdatetime) times.append(tempdatetime) beamanodes.append(np.mean(ELS_ramanodes(tempdatetime)) + 1) states.append(cassini_phase( tempdatetime.strftime('%Y-%m-%dT%H:%M:%S'))) # print(states[-1]) lon, lat, alt = spice.recpgr("TITAN", states[-1][:3], spice.bodvrd("TITAN", 'RADII', 3)[1][0], 1.44e-4) lons.append(lon * spice.dpr()) lats.append(lat * spice.dpr()) alts.append(alt) # vecs.append(cassini_act_2_titan(tempdatetime)) crossvec = caps_crosstrack(tempdatetime, np.mean([negwindspeed, poswindspeed])) print("crossvec", crossvec) testspicenormal, anode1, anode8 = caps_crosstrack_spice( tempdatetime, np.mean([negwindspeed, poswindspeed])) anodes1.append(anode1) anodes8.append(anode8) spiceplanenormals.append(testspicenormal) print("test spice normal", testspicenormal) jacobian = spice.dpgrdr("TITAN", states[-1][0], states[-1][1], states[-1][2], spice.bodvrd('TITAN', 'RADII', 3)[1][0], 1.44e-4) # print("jacobian", jacobian) crossvec_lonlatalt = spice.mxv(jacobian, spice.vhat(crossvec)) crossvec_lonlatalt_spicenormal = spice.mxv(jacobian, testspicenormal) # print("recpgr", lon, lat, alt) # print("crossvec latlon", crossvec_lonlatalt) # print("crossvec latlon vhat", spice.vhat(crossvec_latlon)) crossvecs.append(crossvec) crossvecs_lonlatalts.append(crossvec_lonlatalt) crossvecs_lonlatalts_spicenormal.append(crossvec_lonlatalt_spicenormal) # print("Time", tempdatetime) # print("position", states[-1][:3]) # print("velocity", spice.vhat(states[-1][3:])) # print("direction", spice.vhat(vecs[-1])) # if anodes: # anode_vecs.append(caps_all_anodes(tempdatetime)) # print("anode vecs 1 & 8", anode_vecs[-1][0], anode_vecs[-1][7]) # # spiceplanenormal = spice.psv2pl(states[-1][:3],anode_vecs[-1][0],anode_vecs[-1][7]) # # print("SPICE NORMAL", spice.pl2nvp(spiceplanenormal)) # # # # spiceplanenormals.append(-1*spice.pl2nvp(spiceplanenormal)[0]) # # print("Crossvec", crossvec) # for anodecounter, i in enumerate(anode_vecs[-1]): # # print(anodecounter,anode_vecs[-1][anodecounter]) # anode_seps[anodecounter].append( # spice.vsep(spice.vhat(states[-1][3:]), spice.vhat(anode_vecs[-1][anodecounter])) * spice.dpr()) # print("anodeseps",anode_seps) # print("Angular Separation", spice.vsep(spice.vhat(states[-1][3:]), spice.vhat(vecs[-1])) * spice.dpr()) x, y, z, u, v, w = [], [], [], [], [], [] for i in states: x.append(i[0]) y.append(i[1]) z.append(i[2]) # CAPS direction for i in vecs: u.append(i[0]) v.append(i[1]) w.append(i[2]) # Crosstrack u2, v2, w2 = [], [], [] for j in crossvecs: u2.append(j[0]) v2.append(j[1]) w2.append(j[2]) # SPICE plane normal u3, v3, w3 = [], [], [] for j in spiceplanenormals: u3.append(j[0]) v3.append(j[1]) w3.append(j[2]) # Ram Direction u1, v1, w1 = [], [], [] for i in states: u1.append(i[3]) v1.append(i[4]) w1.append(i[5]) fig = plt.figure() u = np.linspace(0, 2 * np.pi, 50) v = np.linspace(0, np.pi, 50) x_sphere = 2574.7 * np.outer(np.cos(u), np.sin(v)) y_sphere = 2574.7 * np.outer(np.sin(u), np.sin(v)) z_sphere = 2574.7 * np.outer(np.ones(np.size(u)), np.cos(v)) ax = fig.add_subplot(111, projection='3d') # Plot the surface # ax.plot_wireframe(x_sphere, y_sphere, z_sphere, color='b') # ax.plot(x, y, z, alpha=0.5, color='k') if anodes: for timecounter, (i, j) in enumerate(zip(anodes1, anodes8)): X = x[timecounter] Y = y[timecounter] Z = z[timecounter] # print(i) # for anodecounter, j in enumerate(i): # if anodecounter in [0, 7]: # ax.quiver(X, Y, Z, j[0], j[1], j[2], length=20, color='C' + str(anodecounter)) # print(timecounter, i, j) ax.quiver(X, Y, Z, i[0], i[1], i[2], length=30, color='C1') ax.quiver(X, Y, Z, j[0], j[1], j[2], length=30, color='C2') ax.quiver(x, y, z, u2, v2, w2, length=30, color='m') ax.quiver(x, y, z, u1, v1, w1, length=5, color='k') ax.quiver(x, y, z, u3, v3, w3, length=30, color='r') ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_zlabel("Z") ax.set_xlim(min(x), max(x)) ax.set_ylim(min(y), max(y)) ax.set_zlim(min(z), max(z)) dlat, dlon = [], [] for i in crossvecs_lonlatalts: dlat.append(i[1]) dlon.append(i[0]) dlat_spicenormal, dlon_spicenormal = [], [] for i in crossvecs_lonlatalts_spicenormal: dlat_spicenormal.append(i[1]) dlon_spicenormal.append(i[0]) fig2, ax2 = plt.subplots() ax2.plot(lons, lats) ax2.quiver(lons, lats, dlon, dlat) ax2.quiver(lons, lats, dlon_spicenormal, dlat_spicenormal, color='r') ax2.set_xlabel("Longitude") ax2.set_ylabel("Latitude") ax2.grid()