def Location(et, ingress, sv, when): Coords = np.ones(3) [tgopos, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.target) [mexpos, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs) [states, _] = spice.spkezr(sv.target, et - when, sv.fframe, 'NONE', sv.obs) sc2scvector = states[0:3] velocity = states[3:6] relativespeed = np.linalg.norm(velocity) # e9 because we are converting from km to m (SPICE outputs km, but constants in m) veldopp = (relativespeed / constants.c) * 437.1e9 displacement = np.linalg.norm(sc2scvector) sc2scunitvector = np.true_divide(sc2scvector, displacement) # Extract the triaxial dimensions of Mars marsrad = spice.bodvrd(sv.front, 'RADII', 3) # For the ray that connects MEX and TGO, find the point on this ray that is closest to the Martian surface [nearestpoint, alt] = spice.npedln(marsrad[1][0], marsrad[1][1], marsrad[1][2], tgopos, sc2scunitvector) # THERE IS MORE SETTINGS ON THIS [radius, lon, lat] = spice.reclat(nearestpoint) # Rad -> Deg , frame inversion required (hence the negative 180) lon = 180 - (lon * (-180 / math.pi)) lat = lat * (-180 / math.pi) MexNadirTGOAngle = spice.vsep(-mexpos, -sc2scvector) MexNadirTGOAngle = MexNadirTGOAngle * (180 / math.pi) # produce a string of the date and time, because an ephemeris time is not human-readable date_time = spice.timout(et, 'MM-DD HR:MN:SC') ingress_date_time = spice.timout(ingress, 'MM-DD HR:MN:SC') return lon, lat, displacement, nearestpoint, alt, relativespeed, date_time, ingress_date_time, veldopp, MexNadirTGOAngle
def calculate_orientations(mid_time, interframe_delay, frame_number=0): et = mid_time et = et + (frame_number * interframe_delay) jupiter_state, lt = spice.spkpos('JUPITER', et, 'IAU_SUN', 'NONE', 'SUN') jupiter_state = np.array(jupiter_state) spacecraft_state, lt = spice.spkpos('JUNO_SPACECRAFT', et, 'IAU_JUPITER', 'NONE', 'JUPITER') spacecraft_state = np.array(spacecraft_state) m = spice.pxform("IAU_JUPITER", "J2000", et) jupiter_rotation = np.array( ((m[0][0], m[0][1], m[0][2], 0.0), (m[1][0], m[1][1], m[1][2], 0.0), (m[2][0], m[2][1], m[2][2], 0.0), (0.0, 0.0, 0.0, 1.0))) m = spice.pxform("JUNO_SPACECRAFT", "IAU_JUPITER", et) spacecraft_orientation = np.array( ((m[0][0], m[0][1], m[0][2], 0.0), (m[1][0], m[1][1], m[1][2], 0.0), (m[2][0], m[2][1], m[2][2], 0.0), (0.0, 0.0, 0.0, 1.0))) m = spice.pxform("JUNO_JUNOCAM_CUBE", "JUNO_SPACECRAFT", et) instrument_cube_orientation = np.array( ((m[0][0], m[0][1], m[0][2], 0.0), (m[1][0], m[1][1], m[1][2], 0.0), (m[2][0], m[2][1], m[2][2], 0.0), (0.0, 0.0, 0.0, 1.0))) m = spice.pxform("JUNO_JUNOCAM", "IAU_JUPITER", et) instrument_orientation = np.array( ((m[0][0], m[0][1], m[0][2], 0.0), (m[1][0], m[1][1], m[1][2], 0.0), (m[2][0], m[2][1], m[2][2], 0.0), (0.0, 0.0, 0.0, 1.0))) return spacecraft_orientation, jupiter_state, spacecraft_state, jupiter_rotation, instrument_cube_orientation, instrument_orientation
def occSurfaceTrace(et, sv): altTrace = 0 marsrad = spice.bodvrd(sv.front, 'RADII', 3) trace = np.zeros([600, 2]) for i in range(600): # Find relative positions of TGO and MEX [targetpos, _] = spice.spkpos(sv.front, et - i, sv.fframe, 'NONE', sv.target) [sc2scvector, _] = spice.spkpos(sv.target, et - i, sv.fframe, 'NONE', sv.obs) [obspos, _] = spice.spkpos(sv.front, et - i, sv.fframe, 'NONE', sv.obs) # Find the unit vector between the SCs displacement = math.sqrt(((sc2scvector[0])**2) + ((sc2scvector[1])**2) + ((sc2scvector[2])**2)) unitvector = np.true_divide(sc2scvector, displacement) # Find the point this unit vector is closest to the Mars [rectangularCoords, alt] = spice.npedln(marsrad[1][0], marsrad[1][1], marsrad[1][2], targetpos, unitvector) [radius, lon, lat] = spice.reclat(rectangularCoords) # Rad -> Deg , frame inversion required (hence the negative 180) trace[i, 1] = (lon * (-180 / math.pi)) trace[i, 0] = lat * (-180 / math.pi) altTrace = np.append(altTrace, alt) altTrace = altTrace[1:] return trace, altTrace
def ElectricCall(time): process_id = getpid() print("Process ID:", process_id) epoch = 636491202.20059 target = '-143' obs = '-41' #need a funtion that can interpolate between times at 10 Hz, then just sub those positions into the next function #MEX TGO positions to be created in this function with 10 Hz interpolation samplingfrequency = 1 referencedirection = [0, 0, 0] result = np.zeros([samplingfrequency]) overshoot = np.zeros([samplingfrequency]) #636491202.20059 #MEX,TGO, Distance = ephemerides(636491202,time, samplingfrequency) #mex = MEX[:,0] ; tgo = TGO[0] for i in range(samplingfrequency): [tgo1, _] = spice.spkpos('MARS', epoch - time, 'IAU_MARS', 'NONE', target) [mex1, _] = spice.spkpos('MARS', epoch - time, 'IAU_MARS', 'NONE', obs) dis = mex1 - tgo1 Distance = np.linalg.norm(dis) #print(f"Progess:{(i/samplingfrequency)*100} %") #mex = MEX[:,i]+0 ; tgo = TGO[:,i]+0 mex = mex1 tgo = tgo1 initialangle, xyzpoints = producegeometrymeter( mex, tgo) #make 2D for huge speed improvements. Bending, S, referencedirection = flatbending(xyzpoints, initialangle, mex, tgo, referencedirection) result = S #result[i] = np.stack((ElectricDistance, Distance), axis = 0) return S
def write_positions( utc_start, utc_end, steps, ): """ Write positions of earth and moon in output file. Input: -utc_start str (format YYYYmmdd) -utc_end str (format YYYYmmdd) -steps int """ # read kernel files paths and some constants from config dark_side_path = os.path.dirname( os.path.dirname(os.path.realpath(__file__))) config = configparser.ConfigParser() config.read(os.path.join(dark_side_path, "config", "config.ini")) spk_kernel = config["spice"]["spk_kernel"] lsk_kernel = config["spice"]["lsk_kernel"] reference_frame = config["spice"]["reference_frame"] aberration_correction = config["spice"]["aberration_correction"] # load kernels spice.furnsh(spk_kernel) spice.furnsh(lsk_kernel) # compute ET times et_start = spice.str2et(format_date_for_spice(utc_start)) et_end = spice.str2et(format_date_for_spice(utc_end)) times = [x * (et_end - et_start) / steps + et_start for x in range(steps)] # load positions earth_positions, _ = spice.spkpos("EARTH", times, reference_frame, aberration_correction, "SUN") moon_positions, _ = spice.spkpos("MOON", times, reference_frame, aberration_correction, "EARTH") # create output dir output_dir = os.path.join( dark_side_path, "data", ) if not os.path.exists(output_dir): os.makedirs(output_dir) # write results in output files write_output_file(os.path.join(output_dir, "earth.txt"), [ "{:15.8f}, {:15.8f}, {:15.8f}".format(pos[0], pos[1], pos[2]) for pos in earth_positions ]) write_output_file(os.path.join(output_dir, "moon.txt"), [ "{:15.8f}, {:15.8f}, {:15.8f}".format(pos[0], pos[1], pos[2]) for pos in moon_positions ]) write_output_file(os.path.join(output_dir, "times.txt"), [ "{}".format(format_date_from_spice(spice.et2utc(time, "C", 0))) for time in times ])
def get_Sun_and_Moon_Positions(yr, mon, day, hr, mi, sec): # # Convert the given UTC inputs into the necessary string format # yr_string = str(yr) # if mon < 10: mon_string = '0' + str(mon) else: mon_string = str(mon) # if day < 10: day_string = '0' + str(day) else: day_string = str(day) # if hr < 10: hr_string = '0' + str(hr) else: hr_string = str(hr) # if mi < 10: mi_string = '0' + str(mi) else: mi_string = str(mi) # if sec < 10: sec_string = '0' + str(sec) else: sec_string = str(sec) # # Create the total string needed for the epoch of interest # epoch_UTC = mon_string + '-' + day_string + '-' + yr_string + ' ' + hr_string +\ ':' + mi_string + ':' + sec_string # epoch_UTC = epoch_UTC + ' TDB' # get et value et = spice.str2et( epoch_UTC ) # converts to a numeric vector -- this is seconds since J2000 in tbd -- barycentric dynamical time #Run spkpos as a vectorized function rECIF_Moon_J2000, vECIF_Moon_J2000 = spice.spkpos('Moon', et, 'J2000', 'NONE', 'Earth') rECIF_Sun_J2000, vECIF_Sun_J2000 = spice.spkpos('Sun', et, 'J200', 'NONE', 'Earth') rECIF_Moon_J2000 = np.array(rECIF_Moon_J2000) # Convert from list in np array rECIF_Sun_J2000 = np.array(rECIF_Sun_J2000) # vECIF_Moon_J2000 = np.array(vECIF_Moon_J2000) vECIF_Sun_J2000 = np.array(vECIF_Sun_J2000) return rECIF_Moon_J2000, rECIF_Sun_J2000, vECIF_Moon_J2000, vECIF_Sun_J2000
def producegeometrylamda(et, sv, when): [TGO, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.target) [MEX, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs) dist = math.floor(spice.vdist(TGO, MEX)) print(dist) # NEED TO PRODUCE VECTOR OF SZA AND HEIGHTS THAT ARE 'DIST' LONG [13242.9 m] *comp expensive # start by making DIST length vector, 3 height, for every meter from mex to tgo # MAYBE FIND THE UNIT VECTOR AND ADD ONE IN ITS DIRECTION!! angleseparation = (spice.vsep(MEX, TGO)) * (180 / math.pi ) # angle taken a mars center initialangle = (spice.vsep(-MEX, (TGO - MEX))) * ( 180 / math.pi ) # angle taken at mars-MEX-tgo, that points to tgo. needed for the bending functions original starting angle #script needs to work via periods of ray and not meters. [totalperiods is the main iterable, not meters] vacuumwavelength = constants.c / 437.1e6 scale = 1 # scale =10, means we are itertating per 100 wavelenghts instead of 1000 (default 1000 because SPICE works in km) wavelengthsinameter = 1 / vacuumwavelength a = wavelengthsinameter * dist * scale total1000periods = math.floor(a) # ~that many thousands of periods remainingdistance = (vacuumwavelength / scale) * ( (wavelengthsinameter * dist * scale) - total1000periods ) # quanitfy the remaineder, this distance can # added later, this remaining portion is extreamly high altitude (near Target) and has no refractive effects. therfor simply added (km) #total1000periods = total1000periods.astype(int) sc2sc = TGO - MEX norm = np.linalg.norm(sc2sc) unitsc2sc = sc2sc / (norm * vacuumwavelength * scale ) #this needs to shrink if the repeatable expands points = np.empty([3, total1000periods]) sza = np.empty([1, total1000periods]) marsrad = spice.bodvrd(sv.front, 'RADII', 3) flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0] equatorialradii = marsrad[1][0] # find direction of sun, it will not change much during the occultation. so only calc it once [SUN, _] = spice.spkpos(sv.front, et, sv.fframe, 'NONE', 'SUN') for i in range(total1000periods): point = MEX + ( i * unitsc2sc ) #move along ray, 1000 wavelength distance at a time (685 m). but unitsc2sc is in km... sza[0, i] = spice.vsep(SUN, point) points[:, i] = spice.recgeo(point, equatorialradii, flatteningcoefficient) points[0, i] = (points[0, i] * (-180 / math.pi)) points[1, i] = (points[1, i] * (-180 / math.pi)) print((i / math.floor(total1000periods)) * 100) ray = np.concatenate((points, sza), axis=0) print('stop here') return ray, dist, angleseparation, initialangle, total1000periods, vacuumwavelength, remainingdistance
def GeoCall(time): epoch = 636491202.20059 target = '-143' obs = '-41' process_id = getpid() print("Process ID:", process_id) [tgo1, _] = spice.spkpos('MARS', epoch - time, 'IAU_MARS', 'NONE', target) [mex1, _] = spice.spkpos('MARS', epoch - time, 'IAU_MARS', 'NONE', obs) dis = mex1 - tgo1 result = np.linalg.norm(dis) return result
def producegeometrymeter(et, sv, when): [TGO, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.target) [MEX, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs) dist = math.floor(spice.vdist(TGO, MEX)) print(dist) # NEED TO PRODUCE VECTOR OF SZA AND HEIGHTS THAT ARE 'DIST' LONG [13242.9 m] *comp expensive # start by making DIST length vector, 3 height, for every meter from mex to tgo # MAYBE FIND THE UNIT VECTOR AND ADD ONE IN ITS DIRECTION!! angleseparation = (spice.vsep(MEX, TGO)) # angle taken a mars center initialangle = (spice.vsep(-MEX, (TGO - MEX))) * ( 180 / math.pi ) # angle taken at mars-MEX-tgo, that points to tgo. needed for the bending functions original starting angle #script needs to work via periods of ray and not meters. [totalperiods is the main iterable, not meters] scale = 0.1 # scale =10, means we are itertating per 100 wavelenghts instead of 1000 (default 1000 because SPICE works in km) dist = math.floor(dist) # km sc2sc = TGO - MEX norm = np.linalg.norm(sc2sc) unitsc2sc = sc2sc / norm #this needs to shrink if the repeatable expands points = np.empty([3, dist]) sza = np.empty([1, dist]) angleprogression = np.empty([1, dist]) xyzpoints = np.zeros([3, dist]) marsrad = spice.bodvrd(sv.front, 'RADII', 3) flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0] equatorialradii = marsrad[1][0] # find direction of sun, it will not change much during the occultation. so only calc it once [SUN, _] = spice.spkpos(sv.front, et, sv.fframe, 'NONE', 'SUN') for i in range(dist): xyzpoint = MEX + ( i * unitsc2sc ) #move along ray, 1000 wavelength distance at a time (685 m). but unitsc2sc is in km... xyzpoints[:, i] = xyzpoint sza[0, i] = spice.vsep(SUN, xyzpoint) angleprogression[0, i] = (spice.vsep(xyzpoint, MEX)) * (180 / math.pi) points[:, i] = spice.recgeo(xyzpoint, equatorialradii, flatteningcoefficient) points[0, i] = (points[0, i] * (-180 / math.pi)) points[1, i] = (points[1, i] * (-180 / math.pi)) print((i / math.floor(dist)) * 100) ray = np.concatenate((points, sza), axis=0) #plt.plot(angleprogression[0,:], ray[2,:]) #plt.show() # ray is in lat/lon/alt + sza and xyzpoints is cartesian, both describe the same thing return ray, dist, unitsc2sc, angleseparation, initialangle, MEX, TGO, xyzpoints, angleprogression
def earlyclearance(et, sv): [Mars_TGO, _] = spice.spkpos(sv.front, et - 60, sv.fframe, 'NONE', sv.target) [Mars_MEX, _] = spice.spkpos(sv.front, et - 60, sv.fframe, 'NONE', sv.obs) [spiceTGO_MEX, _] = spice.spkpos(sv.target, et - 60, sv.fframe, 'NONE', sv.obs) #TGO_MEX = Mars_TGO - Mars_MEX #testangle = spice.vsep(spiceTGO_MEX,TGO_MEX) * (180/math.pi) # We use a negative Mars_TGO vector because we want the opposite direction(going to Mars) clearanceangle = spice.vsep(-Mars_TGO, spiceTGO_MEX) * (180 / math.pi) return clearanceangle
def generateEphemeris(datesFile, bsp, dexxx, leapSec, nameFile): #Load the asteroid and planetary ephemeris and the leap second (in order) spice.furnsh(dexxx) spice.furnsh(leapSec) spice.furnsh(bsp) #Values specific for extract all comments of header from bsp files (JPL, NIMA) source = {'NIMA':(45, 'ASTEROID_SPK_ID ='), 'JPL':(74, 'Target SPK ID :')} n, key = source['NIMA'] idspk = findIDSPK(n, key) if idspk == '': n, key = source['JPL'] idspk = findIDSPK(n, key) #Read the file with dates with open(datesFile, 'r') as inFile: dates = inFile.read().splitlines() n = len(dates) #Convert dates from utc to et format datesET = [spice.utc2et(utc) for utc in dates] #Compute geocentric positions (x,y,z) for each date with light time correction rAst, ltAst = spice.spkpos(idspk, datesET, 'J2000', 'LT', 'EARTH') rSun, ltSun = spice.spkpos('SUN', datesET, 'J2000', 'NONE', 'EARTH') elongation = [angle(rAst[i], rSun[i]) for i in range(n)] data = [spice.recrad(xyz) for xyz in rAst] distance, rarad, decrad = zip(*data) #================= for graphics ================= tempFile = open('radec.txt', 'w') for row in data: tempFile.write(str(row[1]) + ' ' + str(row[2]) + '\n') tempFile.close() #================================================ ra = [ra2HMS(alpha) for alpha in rarad] dec = [dec2DMS(delta) for delta in decrad] #Convert cartesian to angular coordinates and save it in a ascii file outFile = open(nameFile,'w') outFile.write('\n\n Data Cal. UTC' + ' '.ljust(51) + 'R.A.__(ICRF//J2000.0)__DEC') outFile.write(' '.ljust(43) + 'DIST (km)' + ' '.ljust(24) + 'S-O-A\n') for i in range(n): outFile.write(dates[i] + ' '.ljust(44) + ra[i] + ' ' + dec[i] + ' '.ljust(35)) outFile.write('{:.16E}'.format(distance[i]) + ' '.ljust(17)) outFile.write('{:.4f}'.format(elongation[i]) + '\n') outFile.close()
def sunDistanceAU(time: str, target: str) -> float: """Returns distance in AU between Sun and observed body from MRO.""" base_kernel_path = Path(isis.environ["ISIS3DATA"]) / "base" / "kernels" lsk = sorted(Path(base_kernel_path / "lsk").glob("naif*.tls"))[-1] pck = sorted(Path(base_kernel_path / "spk").glob("de*.bsp"))[-1] sat = sorted(Path(base_kernel_path / "spk").glob("mar*.bsp"))[-1] sclk = sorted( Path( Path(isis.environ["ISIS3DATA"]) / "mro" / "kernels" / "sclk" ).glob("MRO_SCLKSCET.*.65536.tsc") )[-1] spiceypy.furnsh([str(lsk), str(pck), str(sat), str(sclk)]) et = spiceypy.scs2e(-74999, time) targ = target.lower() if targ == "sky" or targ == "cal" or targ == "phobos" or targ == "deimos": targ = "mars" (sunv, lt) = spiceypy.spkpos(targ, et, "J2000", "LT+S", "sun") sunkm = spiceypy.vnorm(sunv) # Return in AU units return sunkm / 1.49597870691e8
def update_text(date_time): obs2SunVector = sp.spkpos("SUN", date_time, referenceFrame, SPICE_ABERRATION_CORRECTION, SPICE_OBSERVER)[0] obs2SunUnitVector = obs2SunVector / sp.vnorm(obs2SunVector) # obs2SunAngle = sp.vsep(obs2SunUnitVector, np.asfarray([0.0, 0.0, 1.0])) return obs2SunUnitVector
def _jacobian_newtonian(self, t, y): lower_left = np.zeros([3, 3]) for planet in self.gm_dictionary: gm = self.gm_dictionary[planet] planet_position = spice.spkpos(planet, t, 'J2000', 'NONE', 'SOLAR SYSTEM BARYCENTER')[0] * 1000 rvec = planet_position - y[0:3] r = norm(rvec) lower_left += np.array( [[ 3 * gm * (rvec[0]**2) * r**(-5) - gm * r**(-3), 3 * gm * rvec[0] * rvec[1] * r**(-5), 3 * gm * rvec[0] * rvec[2] * r**(-5) ], [ 3 * gm * rvec[0] * rvec[1] * r**(-5), 3 * gm * (rvec[1]**2) * r**(-5) - gm * r**(-3), 3 * gm * rvec[2] * rvec[1] * r**(-5) ], [ 3 * gm * rvec[0] * rvec[2] * r**(-5), 3 * gm * rvec[2] * rvec[1] * r**(-5), 3 * gm * (rvec[2]**2) * r**(-5) - gm * r**(-3) ]]) jacobian = np.array( [[0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1], [lower_left[0, 0], lower_left[0, 1], lower_left[0, 2], 0, 0, 0], [lower_left[1, 0], lower_left[1, 1], lower_left[1, 2], 0, 0, 0], [lower_left[2, 0], lower_left[2, 1], lower_left[2, 2], 0, 0, 0]]) return jacobian
def get_target_xyz(t): """ Returns the vectors of the Horizons body at a certain time t. Arguments: t: days Julian date of observation Returns: xyz: numpy array A position vector of the observed object uvw: numpy array An instantaneous velocity vector of the observed object radec: numpy array The right ascension and declination of the observed object """ state, lighttime = spice.spkezr(name, t, 'J2000', cor, loc) pos, lighttime = spice.spkpos(name, t, 'J2000', cor, loc) range, ra, dec = spice.recrad(pos) xyz = np.array([state[0], state[1], state[2] ]) / 149597870.7 #6.68459e-9 uvw = np.array([state[3], state[4], state[5] ]) / 149597870.7 * 24. * 3600. #*6.68459e-9 radec = np.array([ra, dec]) return xyz, uvw, radec * 180 / np.pi
def CarringtonLongitude(Date, ut): ''' Get MESSENGER's Carrington longitude ''' n = np.size(ut) et = np.zeros((n, ), dtype='float64') lon = np.zeros(n, dtype='float64') sp.furnsh(lsk_path) sp.furnsh(spk_kernel) sp.furnsh(spk_kernel2) sp.furnsh(pck_kernel) if np.size(Date) == 1: et[0] = utc2et(Date, 0.0) et = et[0] + ut * 3600.0 else: ud = np.unique(Date) for i in range(0, ud.size): use = np.where(Date == ud[i])[0] tmp = utc2et(ud[i], 0.0) et[use] = tmp + ut[use] * 3600.0 pos, lt = sp.spkpos('MESSENGER', et, 'IAU_SUN', 'NONE', 'SUN') pos = np.array(pos) lon = np.arctan2(pos.T[1], pos.T[0]) * 180 / np.pi sp.unload(lsk_path) sp.unload(spk_kernel) sp.unload(spk_kernel2) sp.unload(pck_kernel) return (lon)
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 position(self, jd, of='TESS', relative_to='EARTH'): """ Returns position of TESS for the given timestamps as geocentric XYZ-coordinates in kilometers. Parameters: jd (ndarray): Time in Julian Days where position of TESS should be calculated. of (string, optional): Object for which to calculate position for. Default='TESS'. relative_to (string, optional): Object for which to calculate position relative to. Default='EARTH'. Returns: ndarray: Position of TESS as geocentric XYZ-coordinates in kilometers. .. codeauthor:: Rasmus Handberg <*****@*****.**> """ # Convert JD to Ephemeris Time: jd = np.atleast_1d(jd) times = [spiceypy.unitim(j, 'JDTDB', 'ET') for j in jd] # Get positions as a 2D array of (x,y,z) coordinates in km: try: positions, lt = spiceypy.spkpos(of, times, 'J2000', 'NONE', relative_to) positions = np.atleast_2d(positions) except SpiceyError as e: if 'SPICE(SPKINSUFFDATA)' in e.value: raise InadequateSpiceException( "Inadequate SPICE kernels available") else: raise return positions
def lon_lat_r(body, time, earth_radius=6371e3): """ Use SPICE software to get longitude and latitude of the point on Earth at which <body> is in zenith and the distance between the barycenters of Earth and <body> at a specified <time> (in UTC). We're pretending the earth is a sphere here, as is commonly done in tidal studies (and presumably is done in the ocean model this is fed into). Input: body - SPICE name of the body (e.g. "SUN" or "MOON") time - date and time in datetime format (UTC) earth_radius - radius of the earth (default 6371e3 m) Output: lon, lat - longitude and latitude at which <body> is in zenith r - range of the body (distance between barycenters) """ # convert UTC time to ephemeris time time = spice.str2et(str(time) + " UTC") # get position in rectangular coordinate system (body frame of Earth) pos_rec, _ = spice.spkpos(body, time, "ITRF93", "NONE", "EARTH") # transform to geodetic coordinates assuming zero flatness (to get lat/lon) pos_geo = spice.recgeo(pos_rec, earth_radius / 1e3, 0) # transform to range, right ascension, declination (to get range) pos_rad = spice.recrad(pos_rec) # isolate coordinates we'll need (and convert from km to m) lon = pos_geo[0] lat = pos_geo[1] r = pos_rad[0] * 1e3 return lon, lat, r
def nearest_moon(dt, target='CASSINI'): """ :param dt: :param target: :return: """ et = spice.datetime2et(dt) moondict = {} NAIFIDS = range(601, 654, 1) for x in NAIFIDS: moon = spice.bodc2s(x) frame = 'IAU_' + moon.upper() observ = moon.upper() corrtn = 'NONE' state, ltime = spice.spkpos(target, et, frame, corrtn, observ) # TODO do full calculation of altitude lon, lat, alt = spice.recpgr( moon.upper(), state, spice.bodvrd(moon.upper(), 'RADII', 3)[1][0], 2.64e-4) moondict[moon] = alt sorteddict = OrderedDict(sorted(moondict.items(), key=lambda t: t[1])) return sorteddict
def soldir_from_titan(): #Only use for one flyby for counter, flyby in enumerate(flybys): tempdf = windsdf[windsdf['Flyby'] == flyby] i = pd.to_datetime(tempdf['Bulk Time']).iloc[0] et = spice.datetime2et(i) sundir, ltime = spice.spkpos('SUN', et, 'IAU_TITAN', "LT+S", 'TITAN') return sundir
def getNacCenterAndRotationAtTime(imname): ''' Extract the rotation of the spacecraft and its position for the given picture Notice that WAV and NAC can be considered aligned on the same axis and centred in the spacecraft so it can be used the same way independently by the camera :param imname: the input picture filename :return: the centre and the rotation matrix of the spacecraft ''' os.chdir(spice_kernels_dir) # or spyceypy will not work spiceypy.furnsh(spice_kernels_dir + os.path.sep + furnsh_file) #load the kernels from furnsh tstr = extractTimeString( imname) # get only the time string from the filename t = spiceypy.str2et(tstr) # transform the string to a time # get the position of Rosetta spacecraft in 67p refence frame, centred in 67P + light time corr (not really needed) pos = spiceypy.spkpos("ROSETTA", t, "67P/C-G_CK", "LT+S", "67P/C-G")[0] # pos = spiceypy.spkpos("ROSETTA", t, "ROS_OSIRIS_NAC", "LT+S", "67P/C-G")[0] print("Found position: {}".format(pos)) #and the rotation - we use NAC but it is the same for the WAC # R = spiceypy.pxform("67P/C-G_CK", "ROS_OSIRIS_NAC", t); # rotation matrix of the nac camera, in respect to 67P reference frame R = spiceypy.pxform("ROS_OSIRIS_NAC", "67P/C-G_CK", t) return np.array(pos), np.array(R)
def generate_positions(self, times, observing_body, frame): """ Generate positions from a spice kernel. Parameters ---------- times : iterable of `datetime` An iterable (e.g. a `list`) of `datetime` objects at which the positions are calculated. observing_body : str The observing body. Output position vectors are given relative to the position of this body. See https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html for a list of bodies. frame : str The coordinate system to return the positions in. See https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/frames.html for a list of frames. """ # Spice needs a funny set of times fmt = '%b %d, %Y' spice_times = [spiceypy.str2et(time.strftime(fmt)) for time in times] observing_body = observing_body # 'None' specifies no light-travel time correction positions, lightTimes = spiceypy.spkpos(self.target, spice_times, frame, 'None', observing_body) positions = np.array(positions) * u.km self._times = times self._positions = positions self._x = positions[:, 0] self._y = positions[:, 1] self._z = positions[:, 2] self._generated = True self._observing_body = observing_body
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 producegeometrymeter(et, sv, when): [TGO, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.target) [MEX, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs) dist = math.floor(spice.vdist(TGO, MEX)) angleseparation = (spice.vsep(MEX, TGO)) # angle taken a mars center initialangle = (spice.vsep(-MEX, (TGO - MEX))) * ( 180 / math.pi ) # angle taken at mars-MEX-tgo, that points to tgo. needed for the bending functions original starting angle #script needs to work via periods of ray and not meters. [totalperiods is the main iterable, not meters] sc2sc = TGO - MEX norm = np.linalg.norm(sc2sc) unitsc2sc = sc2sc / norm #this needs to shrink if the repeatable expands points = np.empty([3, dist]) sza = np.empty([1, dist]) angleprogression = np.empty([1, dist]) xyzpoints = np.zeros([3, dist]) marsrad = spice.bodvrd(sv.front, 'RADII', 3) flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0] equatorialradii = marsrad[1][0] # find direction of sun, it will not change much during the occultation. so only calc it once [SUN, _] = spice.spkpos(sv.front, et, sv.fframe, 'NONE', 'SUN') for i in range(dist): xyzpoint = MEX + ( i * unitsc2sc ) #move along ray, 1000 wavelength distance at a time (685 m). but unitsc2sc is in km... xyzpoints[:, i] = xyzpoint sza[0, i] = spice.vsep(SUN, xyzpoint) angleprogression[0, i] = (spice.vsep(xyzpoint, MEX)) * (180 / math.pi) points[:, i] = spice.recgeo(xyzpoint, equatorialradii, flatteningcoefficient) points[0, i] = (points[0, i] * (-180 / math.pi)) points[1, i] = (points[1, i] * (-180 / math.pi)) ray = np.concatenate((points, sza), axis=0) # important for when sza is included #plt.plot(angleprogression[0,:], ray[2,:]) #plt.show() # ray is in lat/lon/alt + sza and xyzpoints is cartesian, both describe the same thing return initialangle, MEX, TGO, xyzpoints
def TangentPointAltitude(time): epoch = 636491202.20059 target = '-143' obs = '-41' alt = np.zeros(len(time) + 1) for i in time: [tgo, _] = spice.spkpos('MARS', epoch - i, 'IAU_MARS', 'NONE', target) [mex, _] = spice.spkpos('MARS', epoch - i, 'IAU_MARS', 'NONE', obs) [states, _] = spice.spkezr(target, epoch - i, 'IAU_MARS', 'NONE', obs) sc2scvector = states[0:3] displacement = np.linalg.norm(sc2scvector) sc2scunitvector = np.true_divide(sc2scvector, displacement) marsrad = spice.bodvrd('MARS', 'RADII', 3) _, alt[i] = spice.npedln(marsrad[1][0], marsrad[1][1], marsrad[1][2], tgo, sc2scunitvector) return alt * 1000
def target_to_object(self, object): """Object should be string of body, e.g. 'SUN'. Output has (object_vector[3], lighttime) # Potential TODO: spkezp would be faster, but it uses body codes instead of names """ output = spice.spkpos(object, self.et, self.ref_frame, self.corr, self.target) return output
def getPos(self, time, frame='HCI', obs='SUN'): # TODO: Error checking for valid observer name, frame name, input time is a datetime # Convert input datetime to string and parse to ephemeris time et = self.__convertDateToET(time) return (spice.spkpos(targ=str(self.ID), et=et, ref=frame, abcorr='NONE', obs=str(self.naifID(obs)))[0] / 149.6e+6, self.__solDistanceInAU(et) / 149.6e+6)
def dist(x, ele_ast, Gm): #x[0] is time and x[1] is true anomaly M_A = toMean(x[1], ele_ast[1]) pos_earth = sp.spkpos('EARTH', x[0], 'J2000', 'LT+S', 'SUN') ele = np.zeros(8) ele[0:4] = ele_ast[0:4] ele[5] = M_A ele[6] = 0 ele[7] = Gm xyz_asteroid = sp.conics(ele, 0)[0:3] d = np.linalg.norm(pos_earth[1] - xyz_asteroid) return d
def selframe_axis(et): moon_obsever,lt = spice.spkpos('moon',et,'GROUNDSTATION_TOPO','LT+S','399123') sun_observer,lt = spice.spkpos('sun',et,'GROUNDSTATION_TOPO','LT+S','399123') dis_moon = np.linalg.norm(moon_obsever) dis_sun = np.linalg.norm(sun_observer) axis_x = moon_obsever/dis_moon ele_ref_obs=90. azi_ref_obs=0. ele_ref_obs=deg2rad(ele_ref_obs) azi_ref_obs=deg2rad(azi_ref_obs) ref_obs=pol2car((ele_ref_obs,azi_ref_obs)) axis_y=cross_prod(axis_x,ref_obs) # i_obs is NOT normalized axis_y=normalize(axis_y) axis_z = np.cross(axis_x,axis_y) return axis_x,axis_y,axis_z
def _gravity_newtonian(self, r, planet, t): '''Newtonian gravitational acceleration from specified planet. planet: name of planet (string) time: astropy.Time object ''' planet_gm = self.gm_dictionary[planet] planet_position = spice.spkpos(planet, t, 'J2000', 'NONE', 'SOLAR SYSTEM BARYCENTER')[0] * 1000 planet_displacement = planet_position - r planet_distance = norm(planet_displacement) magnitude = planet_gm / (planet_distance**2) direction = planet_displacement / planet_distance return magnitude * direction
def sun_angles(time): """Return the angle between SC-Y and the sun direction (0. = Y to sun)""" a = spiceypy.spkpos('SUN', time, 'MAVEN_SPACECRAFT', 'NONE', 'MAVEN')[0] e = np.arctan( np.sqrt(a[1]**2. + a[2]**2.) / a[0]) * 180./np.pi f = np.arctan( np.sqrt(a[0]**2. + a[2]**2.) / a[1]) * 180./np.pi g = np.arctan( np.sqrt(a[0]**2. + a[1]**2.) / a[2]) * 180./np.pi if e < 0.: e = e + 180. if f < 0.: f = f + 180. if g < 0.: g = g + 180. return np.array((e,f,g))
def get_Earth_Sun_coords(t, ABCORR): """ Get Earth (Geocentric) and solar (Heliocentric) ephemeris (km) relative to solar system Barycenter at times t """ FRAME = 'J2000' OBSERVER = '0' # Solar System Barycenter (SSB) N = len(t) # TODO: vectorize?? xyzEarth = np.empty((N, 3), np.float128) xyzSun = np.empty((N, 3), np.float128) ltEarth = np.empty(N) ltSun = np.empty(N) for i, t in enumerate(t): # Ephemeris time (seconds since J2000 TDB) et = spice.utc2et(str(t)) # Earth geocenter wrt SSB in J2000 coordiantes xyzEarth[i], ltEarth[i] = spice.spkpos(OBSERVER, et, FRAME, ABCORR, 'earth') # Sun heliocenter wrt SSB in J2000 coordiantes xyzSun[i], ltSun[i] = spice.spkpos(OBSERVER, et, FRAME, ABCORR, '10') return xyzSun, xyzEarth
def getTargetPosition(target, craft, camera, time): """ get position of target in world coordinates relative to the observing craft. """ # get target code targetId = spice.bodn2c(target) # eg 'Jupiter'->599 # get spacecraft instrument spacecraft = -31 if craft=='Voyager1' else -32 spacecraftBus = spacecraft * 1000 spacecraftScanPlatform = spacecraftBus - 100 spacecraftNarrowCamera = spacecraftScanPlatform - 1 spacecraftWideCamera = spacecraftScanPlatform - 2 # instrument = spacecraftBus # use for NAIF continuous kernels instrument = spacecraftScanPlatform # use for PDS discrete kernels # get ephemeris time # note: target and spacecraft locations are stored relative to J2000 # time is utc time as string ephemerisTime = spice.str2et(time) # seconds since J2000 (will be negative) # sclkch = spice.sce2s(spacecraft, ephemerisTime) # spacecraft clock ticks, string # sclkdp = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double clockTicks = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double # print 'clockTicks',clockTicks # get position of target relative to spacecraft # this is the direction from craft to target in ECLIPB1950 frame observer = 'Voyager ' + craft[-1] # eg 'Voyager 1' frame = 'ECLIPB1950' # coordinate frame abberationCorrection = 'NONE' position, lightTime = spice.spkpos(target, ephemerisTime, frame, abberationCorrection, observer) # print 'target position relative to observer', position return position
def f(t): try: pos, lt = spiceypy.spkpos(target, t, frame, correction, observer) except spiceypy.support_types.SpiceyError: return np.empty(3) + np.nan return np.array(pos)
# (which is [0,0,1]) and then rotate this vector into the comet centric # frame of reference for the given time t. rVirtis_hat = np.array([0,0,1]) R = spice.pxform('ROS_OSIRIS_NAC','67P/C-G_CK', et) rVirtis_hat = np.dot(R, rVirtis_hat) nPixelsX = 3 nPixelsY = 3 pVectors = pointing_vectors(nPixelsX, nPixelsY) ################################################################################ # compute coordinates of S/C and Sun in the comet body centric frame m2km = 1000 observer = 'CHURYUMOV-GERASIMENKO' corr = 'NONE' frame = '67P/C-G_CK' rSC, lt = spice.spkpos('ROSETTA', et, frame, corr, observer) rSC = np.array(rSC, dtype=float) * m2km rSC_hat = rSC / np.linalg.norm(rSC) rSun, lt = spice.spkpos("SUN", et, frame, corr, observer) rSun = np.array(rSun, dtype=float) rSun_hat = rSun / np.linalg.norm(rSun) rCG, lt = spice.spkpos("CHURYUMOV-GERASIMENKO", et, frame, corr, "ROSETTA") rCG = np.array(rCG, dtype=float) * m2km rCG_hat = rCG / np.linalg.norm(rCG) ################################################################################ # compute plotting coordinates fStretch = np.linalg.norm(rSC) center = np.zeros(3)
def vgMap(filterVolumes=None, optionOverwrite=False, directCall=True): "Build up 2d color map" # # cmd = "echo $ISISROOT" # cmd = "env | ag ^ISIS" # s = lib.system(cmd) # print s # load SPICE kernels (data files) with camera and target positions, etc libspice.loadKernels() # read small dbs into memory # centeringInfo = lib.readCsv(config.dbCentering) # when to turn centering on/off retargetingInfo = lib.readCsv(config.dbRetargeting) # remapping listed targets csvPositions, fPositions = lib.openCsvReader(config.dbPositions) # for target size # # dictionary to keep track of last image file in target sequence (eg for Ariel flyby) # lastImageInTargetSequence = {} # size of 2d map mymax = 800 mxmax = 2 * mymax mxcenter = mxmax/2 mycenter = mymax/2 # set up blank mapping arrays: h(x,y) = (hx(x,y), hy(x,y)) # h tells map where to pull its pixels from - ie map(mx,my) = im(h(mx,my)) hx = np.zeros((mymax,mxmax),np.float32) hy = np.zeros((mymax,mxmax),np.float32) # make blank maps for each color channel #. each system-craft-target-camera-channel will need its own png map file to write to and colorize from # store in a map folder # bluemap = np.zeros((mymax,mxmax),np.float32) bluemap = np.zeros((mymax,mxmax),np.uint8) # each might also need a count map, if wind up averaging things together to smooth things out # would prefer to avoid it if possible though - adds more complexity and i/o countmap = np.zeros((mymax,mxmax),np.uint8) # iterate through all available images, filter on desired volume or image csvFiles, fFiles = lib.openCsvReader(config.dbFiles) nfile = 1 for rowFiles in csvFiles: volume = rowFiles[config.colFilesVolume] fileId = rowFiles[config.colFilesFileId] # filter to given volume # if volume!=filterVolume: continue # get image properties filter = rowFiles[config.colFilesFilter] system = rowFiles[config.colFilesSystem] craft = rowFiles[config.colFilesCraft] target = rowFiles[config.colFilesTarget] camera = rowFiles[config.colFilesCamera] time = rowFiles[config.colFilesTime] note = rowFiles[config.colFilesNote] # relabel target field if necessary target = lib.retarget(retargetingInfo, fileId, target) #. skip others if fileId!='C1465335': continue # get cube filename cubefile = lib.getFilepath('import', volume, fileId) if not os.path.isfile(cubefile): # print 'warning file not found', cubefile continue #. for now # get folders importSubfolder = lib.getSubfolder('import', volume) jpegSubfolder = importSubfolder + 'jpegs/' # mapSubfolder = importSubfolder + 'maps/' mapSubfolder = importSubfolder #. for now lib.mkdir(jpegSubfolder) lib.mkdir(mapSubfolder) # export as jpeg imagefile = jpegSubfolder + fileId + '.jpg' # if not os.path.isfile(imagefile): if 1: cmd = "isis2std from=%s to=%s format=jpeg" % (cubefile, imagefile) print cmd lib.system(cmd) # print 'Volume %s mapping %d: %s \r' % (volume,nfile,infile), # print 'Volume %s mapping %d: %s' % (volume,nfile,infile) nfile += 1 # get target code, eg Jupiter targetId = spice.bodn2c(target) # eg 'Jupiter'->599 # print target, targetId # get instrument spacecraft = -31 if craft=='Voyager1' else -32 spacecraftBus = spacecraft * 1000 # eg -31000 spacecraftScanPlatform = spacecraftBus - 100 # eg -31100 spacecraftNarrowCamera = spacecraftScanPlatform - 1 # eg -31101 spacecraftWideCamera = spacecraftScanPlatform - 2 # eg -31102 # instrument = spacecraftBus # eg -31000, use for NAIF continuous kernels instrument = spacecraftScanPlatform # eg -31100, use for PDS discrete kernels # get ephemeris time ephemerisTime = spice.str2et(time) # seconds since J2000 (will be negative) # world coordinate frame to use # (ECLIPB1950 is how the voyager and planet positions are encoded) frame = 'ECLIPB1950' # get world-to-camera matrix (camera pointing matrix) # C is a transformation matrix from ELIPB1950 to the instrument-fixed frame # at the given time C = getCameraMatrix(frame, spacecraft, instrument, ephemerisTime) print 'C=camera pointing matrix - transform world to camera coords' print C # get world-to-body matrix # B = getBodyMatrix(frame, targetId, ephemerisTime) B = spice.tipbod(frame, targetId, ephemerisTime) print 'B=world to body/target frame matrix' print B # get boresight vector # this is just the third row of the C-matrix, *per spice docs* boresight = C[2] print 'boresight pointing vector',boresight # get location of prime meridian rotationRate = 870.5366420 # deg/day for great red spot primeMeridian = rotationRate /24/60/60 * ephemerisTime # deg print 'primeMeridian (deg)', primeMeridian % 360 primeMeridianRadians = primeMeridian * math.pi/180 # get target position in world coordinates # ie vector from craft to target # and distance observer = 'Voyager ' + craft[-1] # eg Voyager 1 abberationCorrection = 'NONE' position, lightTime = spice.spkpos(target, ephemerisTime, frame, abberationCorrection, observer) # position = getObserverToTargetVector(frame, observer, target, ephemerisTime) distance = libspice.getDistance(position) posnormal = position / distance print 'target position relative to observer',position print 'distance in km',distance print 'position normalized', posnormal # see how different boresight and position vector are dot = np.dot(boresight, posnormal) theta = math.acos(dot) * 180/math.pi print 'angle between boresight and position vector', theta # what longitudes are visible? #.. get from position of craft visibleLongitudesMin = 0 visibleLongitudesMax = math.pi # get tilt of north pole relative to image y-axis npRadians = getNorthPoleAngle(target, position, C, B, camera) # get axial tilt rotation matrix cc = math.cos(npRadians) ss = math.sin(npRadians) mTilt = np.array([[cc,-ss],[ss,cc]]) # get expected angular size (as fraction of frame) and radius imageFraction = lib.getImageFraction(csvPositions, fileId) targetRadiusPx = int(400*imageFraction) #.param # read the (centered) image im = cv2.imread(imagefile) # draw the target's north pole on image # im = drawNorthPole(im) # build hx,hy arrays, which tell map where to pull pixels from in source image # m: map (0 to mxmax, 0 to mymax) r = targetRadiusPx # pixels for mx in xrange(mxmax): # eg 0 to 1600 for my in xrange(mymax): # eg 0 to 800 # q: map (0 to 2pi, -1 to 1) qx = float(mx) / mxmax * 2 * math.pi + primeMeridianRadians qx = qx % (2 * math.pi) # 0 to 2pi qy = -float(my-mycenter)/mycenter # 1 to -1 # s: image (-1 to 1, -1 to 1) sx = -math.sqrt(1 - qy**2) * math.cos(qx) # -1 to 1 sy = qy # 1 to -1 # rotate s to account for axial tilt relative to camera up axis # ie s = mTilt * s s = np.array([sx,sy]) s = np.dot(mTilt,s) sx,sy = s # p: image (0 to 800, 0 to 800) px = sx * r + 400 # 0 to 800 py = -sy * r + 400 # 0 to 800 # hx[my][mx] = px # hy[my][mx] = py visible = (qx >= visibleLongitudesMin) and (qx <= visibleLongitudesMax) if visible: hx[my][mx] = px hy[my][mx] = py else: hx[my][mx] = 0 hy[my][mx] = 0 # do map projection map = cv2.remap(im, hx, hy, cv2.INTER_LINEAR) map = map[:,:,0] # map = np.array(map, np.float32) libimg.show(map) # save map as png file mapfile = mapSubfolder + fileId + '-map.png' cv2.imwrite(mapfile, map) sys.exit(0) # #. now need to blend this into the main map for this filter # # print type(map[0][0]) # # print type(bluemap[0][0]) # # bluemap = cv2.addWeighted(bluemap, 0.5, map, 0.5, 0) # # ret, countzero = cv2.threshold(countmap, 0,255, cv2.THRESH_BINARY) # # ret, countone = cv2.threshold(countmap, 0,255, cv2.THRESH_BINARY) # # countzero = 255-countone # # ret, mapMask = cv2.threshold(map, 1, 255, cv2.THRESH_BINARY) # # mapMask = cv2.bitwise_and(countzero, mapMask) # # c = mapMask & 1 # # countmap += c # # libimg.show(countmap) # # ret, mapnonzero = cv2.threshold(map, 0,1, cv2.THRESH_BINARY) # ret, mapnonzero = cv2.threshold(map, 1,1, cv2.THRESH_BINARY) # countmapPlusOne = countmap + 1 # countmap2 = countmap + 1-mapnonzero # base = np.array(bluemap, np.float32) # # base = base * countmap / countmapPlusOne # base = base * countmap2 / countmapPlusOne # newmap = np.array(map, np.float32) # newmap = newmap / countmapPlusOne # newbase = base + newmap # newbase = np.array(newbase, np.uint8) # # increment countmap where map image data exists # countmap += mapnonzero # # countmap = cv2.bitwise_and(countmap, mapnonzero) # countmap = np.clip(countmap, 0, 4) # bluemap = newbase # libimg.show(bluemap) # # # libimg.show(mapMask) # # mapMaskInv = 255-mapMask # # # libimg.show(mapMaskInv) # # bluemapSame = cv2.bitwise_and(bluemap, mapMaskInv) # # bluemapChange = cv2.bitwise_and(bluemap, mapMask) # # bluemapChange = cv2.addWeighted(bluemapChange, 0.5, map, 0.5, 0) # # # bluemapNew = cv2.bitwise_and(map, mapMask) # # bluemap = bluemapSame + bluemapChange # # # bluemap = bluemapSame + bluemapNew # # libimg.show(bluemap) # # bluemap = cv2.bitwise_and(bluemap, mapMaskInv) # # libimg.show(bluemap) # # bluemap = bluemap + map # # libimg.show(bluemap) # # if nfile>0: # # if nfile>3: # # if nfile>5: # if nfile>8: # sys.exit(0) fPositions.close() fFiles.close() print
spice.furnsh('Voyager_2.m05016u.merged.bsp') # spice.furnsh('jup100.bsp') # jupiter satellite data (20mb) # get ephemeris time (seconds since J2000) etStart = spice.str2et(utcStart) etStop = spice.str2et(utcStop) # get time range nsteps = 50 etTimes = [i*(etStop-etStart)/nsteps + etStart for i in range(nsteps)] # get vectors from observer to target # see http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkpos_c.html frame = 'J2000' abcorr = 'NONE' # abberation correction positions, lightTimes = spice.spkpos(target, etTimes, frame, abcorr, observer) # # spice.furnsh('kernels/naif0012.tls') # load leap second data # # spice.furnsh('kernels/Voyager_1.a54206u_V0.2_merged.bsp') # voyager 1 data # # get field values # # volume,fileid,phase,craft,target,time,instrument,filter,note # # volume = row[config.filesColVolume] # eg 5101 # # fileId = row[config.filesColFileId] # eg C1385455 # # phase = row[config.filesColPhase] # eg Jupiter # # craft = row[config.filesColCraft] # eg Voyager1 # # target = row[config.filesColTarget] # eg Io # target = 'Jupiter'
def vgPlot(): "create plot for each system flyby" loadSpice() #. loop through these, save each file to stepxx_maps/map-Jupiter-Voyager1.jpg etc #. crop each file when done to a square #. vg titles could use these for titlepage for each system flyby #. might as well draw info on maps here - Voyager 1 at Jupiter, date, etc - futura font # note: azimuthElevation values were determined with the plot viewer class Flyby: bodies = None date = None ndays = None axisMax = 1e6 # km axisCenter = (0,0,0) azimuthElevation = None flybys = [] flyby = Flyby() flyby.bodies = ['Jupiter', 'Voyager 1', 'Io', 'Europa', 'Ganymede', 'Callisto'] flyby.date = "1979-03-05" flyby.ndays = 4 flyby.axisMax = 1e6 # km flyby.axisCenter = (0.6e6,-0.2e6,0) flyby.azimuthElevation = (-100,48) flybys.append(flyby) flyby = Flyby() flyby.bodies = ['Saturn', 'Voyager 1','Titan','Enceladus','Rhea','Mimas','Tethys','Dione'] flyby.date = "1980-11-12" flyby.ndays = 3 flyby.axisMax = 0.6e6 # km flyby.axisCenter = (-0.4e6,-0.4e6,0) flyby.azimuthElevation = (80,97) flybys.append(flyby) flyby = Flyby() flyby.bodies = ['Jupiter', 'Voyager 2', 'Io', 'Europa', 'Ganymede', 'Callisto'] flyby.date = "1979-07-09" flyby.ndays = 5 flyby.axisMax = 1e6 # km flyby.axisCenter = (-0.2e6,0,0) flyby.azimuthElevation = (102,107) flybys.append(flyby) flyby = Flyby() flyby.bodies = ['Saturn','Voyager 2','Titan','Enceladus','Rhea','Mimas','Tethys','Dione'] flyby.date = "1981-08-26" flyby.ndays = 2 flyby.axisMax = 0.6e6 # km flyby.axisCenter = (-0.2e6,0.1e6,0) flyby.azimuthElevation = (172,82) flybys.append(flyby) flyby = Flyby() flyby.bodies = ['Uranus','Voyager 2','Ariel','Miranda','Oberon','Titania','Umbriel'] flyby.date = "1986-01-25" flyby.ndays = 2 flyby.axisMax = 0.4e6 # km flyby.azimuthElevation = (-82,-7) flybys.append(flyby) flyby = Flyby() flyby.bodies = ['Neptune','Voyager 2','Triton'] # proteus not in kernels flyby.date = "1989-08-25" flyby.ndays = 2 flyby.axisMax = 1e6 # km flyby.azimuthElevation = (-62,40) flybys.append(flyby) for flyby in flybys: planet = flyby.bodies[0] observer = flyby.bodies[1] print 'Generating plot for %s at %s' % (observer, planet) nsteps = 100 # plot density # get ephemeris time around closest approach (seconds since J2000) etClosest = int(spice.str2et(flyby.date)) etStart = int(etClosest - flyby.ndays * 24*60*60 / 2) etEnd = int(etClosest + flyby.ndays * 24*60*60 / 2) etStep = int((etEnd - etStart) / nsteps) # initialize data structs ets = [] positions = [] minDist = {} minPos = {} for body in flyby.bodies: minDist[body] = 9e15 # loop over time range, get positions for et in xrange(etStart, etEnd, etStep): row = [] for body in flyby.bodies: # get position of body (voyager or moon) relative to planet (eg Jupiter). # position is an (x,y,z) coordinate in the given frame of reference. frame = 'J2000' abberationCorrection = 'NONE' position, lightTime = spice.spkpos(planet, et, frame, abberationCorrection, body) # save time and position to arrays ets.append(et) row.append(position) # find closest approach of voyager to each body if body==observer: # voyager posVoyager = position # save for other bodies # distance = int(libspice.getDistance(position)) # if distance < minDist[body]: # minDist[body] = distance # minPos[body] = position elif body==planet: pass else: # get distance to voyager, km posToVoyager = position-posVoyager distance = int(libspice.getDistance(posToVoyager)) if distance < minDist[body]: minDist[body] = distance minPos[body] = position positions.append(row) # make the map plotMap(flyby, positions, minPos) # all done - clean up the kernels spice.kclear()
def f(t): pos, lt = spiceypy.spkpos("SUN", t, 'IAU_MARS', "NONE", "MARS") return np.array(pos)
def f(t): pos, lt = spiceypy.spkpos("SUN", t, 'IAU_' + body, "NONE", body) return np.array(pos)
def get_satellite_position(satname, timestamp, kernelpath=None, kernellist=None, refframe="J2000", refobject='SUN', rlonlat=False): """ Returns satellite position from the reference frame of the Sun. Files here: https://sohowww.nascom.nasa.gov/solarsoft/stereo/gen/data/spice/depm/ahead/ and https://stereo-ssc.nascom.nasa.gov/data/moc_sds/ahead/data_products/ephemerides/ Parameters ========== satname : str Name of satellite. Recognised strings: 'stereo' timestamp : datetime.datetime object / list of dt objs Times of positions to return. kernelpath : str (default=None) Optional path to directory containing kernels, else local "kernels" is used. kernellist : str (default=None) Optional list of kernels in directory kernelpath, else local list is used. refframe : str (default='J2000') See SPICE Required Reading Frames. J2000 is standard, HEE/HEEQ are heliocentric. 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). Returns ======= position : array(x,y,z), list of arrays for multiple timestamps Position of satellite in x, y, z with reference frame refframe and Earth as observing body. Returns (r,lon,lat) if rlonlat==True. """ if 'stereo' in satname.lower(): if 'ahead' in satname.lower() or 'a' in satname.lower(): satstr = 'STEREO AHEAD' if 'behind' in satname.lower() or 'b' in satname.lower(): satstr = 'STEREO BEHIND' elif 'dscovr' in satname.lower(): satstr = 'DSCOVR' logger.error("get_satellite_position: DSCOVR kernels not yet implemented!") else: satstr = satname.upper() logger.warning("get_satellite_position: No specific SPICE kernels for {} satellite!".format(satname)) if kernellist == None: kernellist = required_kernels[satstr] if kernelpath == None: kernelpath = os.path.join('data/kernels') logger.info("get_satellite_position: Reading SPICE kernel files from {}".format(kernelpath)) for k in kernellist: spiceypy.furnsh(os.path.join(kernelpath, k)) time = spiceypy.datetime2et(timestamp) position, lighttimes = spiceypy.spkpos(satstr, time, refframe, 'NONE', refobject) if rlonlat: if len(position) > 3: return np.asarray([spiceypy.reclat(x) for x in position]) return spiceypy.reclat(position) else: return position