def spice_Intplt(et,stepBitNum): """ Testing interpolating spice results with two exact numbers """ step = 1.0/2.0**stepBitNum numStep = 2.0**stepBitNum et0 = np.floor(et) # The first integer before targeting time et et1 = np.ceil(et) # The first integer after targeting time et exctNumArray = np.linspace(et0,et1,numStep) exctNumNear = min(exctNumArray, key=lambda x:abs(x-et)) # find the closest exact number # Find two exact number around input time et if(exctNumNear>et): exctNum0 = exctNumNear - step exctNum1 = exctNumNear elif(exctNumNear == et): exctNum0 = et exctNum1 = et else: exctNum0 = exctNumNear exctNum1 = exctNumNear - step print exctNum0,exctNum1 state0,lt0 = spice.spkezr("EARTH",exctNum0,"J2000","NONE","SSB") state1,lt1 = spice.spkezr("EARTH",exctNum1,"J2000","NONE","SSB") state = [] lt = [] for i in range(6): state.append(np.interp(et,[exctNum0,exctNum1],[state0[i],state1[i]])) lt.append(np.interp(et,[exctNum0,exctNum1],[lt0,lt1])) stateOr,ltOr = spice.spkezr("EARTH",et,"J2000","NONE","SSB") return state,stateOr,np.array(state)-np.array(stateOr)
def spice_Intplt(et, stepBitNum): """ Testing interpolating spice results with two exact numbers """ step = 1.0 / 2.0**stepBitNum numStep = 2.0**stepBitNum et0 = np.floor(et) # The first integer before targeting time et et1 = np.ceil(et) # The first integer after targeting time et exctNumArray = np.linspace(et0, et1, numStep) exctNumNear = min( exctNumArray, key=lambda x: abs(x - et)) # find the closest exact number # Find two exact number around input time et if (exctNumNear > et): exctNum0 = exctNumNear - step exctNum1 = exctNumNear elif (exctNumNear == et): exctNum0 = et exctNum1 = et else: exctNum0 = exctNumNear exctNum1 = exctNumNear - step print exctNum0, exctNum1 state0, lt0 = spice.spkezr("EARTH", exctNum0, "J2000", "NONE", "SSB") state1, lt1 = spice.spkezr("EARTH", exctNum1, "J2000", "NONE", "SSB") state = [] lt = [] for i in range(6): state.append( np.interp(et, [exctNum0, exctNum1], [state0[i], state1[i]])) lt.append(np.interp(et, [exctNum0, exctNum1], [lt0, lt1])) stateOr, ltOr = spice.spkezr("EARTH", et, "J2000", "NONE", "SSB") return state, stateOr, np.array(state) - np.array(stateOr)
def test_smap(self): target = 'SMAP' et0 = spice.utc2et( '2016-06-01T12:00:00' ) dpr = spice.dpr() a,b,c = [spice.gdpool('BODY399_RADII',i,1)[1] for i in range(3)] ods = [] for deltatime in [0.1 * i for i in range(1080)]: et = et0 + deltatime stSmap,lsSmap = spice.spkezr( target, et, 'IAU_EARTH', 'NONE', 'EARTH' ) posn, veloc = stSmap[:3], stSmap[3:] stSun,lsSun = spice.spkezr( 'SUN', et0, 'IAU_EARTH', 'LT', 'EARTH' ) mtx = spice.pxform( 'SMAP_REFLECTOR', 'IAU_EARTH', et) boreEbf = spice.mxv( mtx, [1.0,0,0] ) point = spice.surfpt( posn, boreEbf, a, b, c) rsurfpt,lon,lat = spice.reclat( point ) utc = spice.et2utc( et, 'ISOC', 3 ) ods += [ OD(deltatime=deltatime,posn=posn,veloc=veloc,boreEbf=boreEbf ,utc=utc,point=point,rsurfpt=rsurfpt ,rsmap=spice.vnorm(posn),lat=lat,lon=lon ,raynge=spice.vnorm(spice.vsub(point,posn)) ,sunsep=spice.vsep( spice.ucrss(posn,veloc), stSun[:3] ) ) ] try: ### Moved matplotlib import to here so test runs to here at least from matplotlib import pyplot as plt plt.figure(1) keys = 'lat lon raynge'.split() secs = [od['deltatime'] for od in ods] for idx in range(len(keys)): scal = 1.0 if keys[idx] in 'rsurfpt rsmap raynge sunsep rp ecc t0 mu a P eccmean amean Pmean'.split() else dpr ordinate = [od[keys[idx]]*scal for od in ods] plt.subplot( 221+idx ) plt.plot( secs, ordinate ) plt.plot( secs, ordinate, '.') plt.title( keys[idx] ) plt.ylabel( '%s%s' % (keys[idx],'' if scal==1.0 else ', deg') ) if idx>1: plt.xlabel( 'T-T0, s' ) abscissa = [od['lon']*dpr for od in ods] ordinate = [od['lat']*dpr for od in ods] plt.subplot( 221+idx+1 ) plt.title( 'lon vs. lat' ) plt.plot( abscissa, ordinate ) plt.xlabel( 'lon, deg' ) plt.ylabel( 'lat, deg' ) plt.show() except: print( "Bypassed, or failed, matplotlib tests" )
def test_lmt(et, step): """ Testing how accurate that spice can distinguish two near by times(et) with littl time step et is the initial time step is the small time step """ et0 = et et1 = et + step print et0, et1, et1 - et0 state0, lt0 = spice.spkezr("EARTH", et0, "J2000", "NONE", "SSB") state1, lt1 = spice.spkezr("EARTH", et1, "J2000", "NONE", "SSB") diff = np.array(state0) - np.array(state1) print state0, state1 return diff
def test_lmt(et,step): """ Testing how accurate that spice can distinguish two near by times(et) with littl time step et is the initial time step is the small time step """ et0 = et et1 = et+step print et0,et1,et1-et0 state0,lt0 = spice.spkezr("EARTH",et0,"J2000","NONE","SSB") state1,lt1 = spice.spkezr("EARTH",et1,"J2000","NONE","SSB") diff = np.array(state0)-np.array(state1) print state0,state1 return diff
def get_v_sun(kernelMetaFile, utcStartTime): ''' compute radial component of CG towards/away from sun for given utcTime. v_sun: velocity component on the comet-sun-line. ''' spice.furnsh(kernelMetaFile) et = spice.str2et(utcStartTime) state, lightTime = spice.spkezr("CHURYUMOV-GERASIMENKO", et, "J2000", "NONE", "SUN") x = state[0] y = state[1] z = state[2] vx = state[3] vy = state[4] vz = state[5] r_length = np.sqrt(x**2 + y**2 + z**2) r_hat = np.zeros(3) v = np.zeros(3) r_hat[0] = x / r_length r_hat[1] = y / r_length r_hat[2] = z / r_length v[0] = r_hat[0] * vx v[1] = r_hat[1] * vy v[2] = r_hat[2] * vz v_sun = v[0] + v[1] + v[2] return v_sun
def getStateFromSpice(parent, body, epoch, referenceFrame='ECLIPJ2000'): global linearPoints state = list(spice.spkezr(body, epoch, referenceFrame, 'NONE', parent)[0]) velocity = kepler.Vector3(state[3], state[4], state[5]) for record in linearPoints: if epoch > record[0][0] and epoch < record[0][1]: i = 1 while i < len(record[1][0]): if epoch < record[1][0][i]: break i += 1 state1 = record[1][1][i - 1] state2 = record[1][1][i] ratio = (epoch - record[1][0][i - 1]) / (record[1][0][i] - record[1][0][i - 1]) velocity = state1.velocity.mul(1 - ratio).add( state2.velocity.mul(ratio)) break if epoch == 299024951.06256104: print( kepler.StateVector(kepler.Vector3(state[0], state[1], state[2]), velocity)) return kepler.StateVector(kepler.Vector3(state[0], state[1], state[2]), velocity)
def objPosVel2SSB(objname, et): """Convert a PosVel object to solar system barycenter coordinates. Returns a solar system object position and velocity in J2000 SSB coordinates. Requires SPK and LPSK kernels in J2000 SSB coordinates. """ load_kernels() return spice.spkezr(objname.upper(), et, "J2000", "NONE", "SSB")
def objPosVel2SSB(objname, et): """ objPosVel2SSB(objname, et) Returns a solar system object position and velocity in J2000 SSB coordinates. Requires SPK and LPSK kernels in J2000 SSB coordinates. """ return spice.spkezr(objname.upper(), et, "J2000", "NONE", "SSB")
def objPosVel(obj1, obj2, et): """Compute the difference of PosVel objects. Returns position/velocity vectors between obj1 and obj2 as a PosVel object at the given time. et is in spice format (TDB seconds past J2000 epoch) """ # TODO: # - maybe this should be a PosVel __init__ method instead? # - accept an astropy time rather than et as input? pv, _ = spice.spkezr(obj1, float(et), "J2000", "NONE", obj2) return PosVel(pv[:3]*u.km, pv[3:]*u.km/u.s, obj=obj1, origin=obj2)
def spkInterp(et, stepBitNum): """ This function interpolates earth state in one second with seveal exact points. To increase accuracy, each know point will be the exact number that can be represented by double precision. et is the target time stepBitNum determines that how small the step for exact points will be. And it is calculated by bits step = 1.0/2.0**stepBitNum """ step = 1.0 / 2.0**stepBitNum # Step from exact point numStep = 2.0**stepBitNum # Number of exact point et0 = np.floor(et) # Start point of interval etExctArray = np.linspace(et0, et0 + 1, numStep + 1) # Exact time point array stateArray = [] # Earth state array for each exact point ltArray = [] # light time state array for each exact point """ Calculate the earth state and lt for each exact point """ for data in etExctArray: stateExct, ltExct = spice.spkezr("EARTH", data, "J2000", "NONE", "SSB") stateArray.append(stateExct) ltArray.append(ltExct) stateArray = np.array(stateArray) # Transfer to numpy array ltArray = np.array(ltArray) # Transfer to numpy array state = [] # Earth state for target time lt = [] # lt for target time """ Interpolate for target time """ for i in range(6): state.append(np.interp(et, etExctArray, stateArray[:, i])) lt.append(np.interp(et, etExctArray, ltArray)) """ Return earth state and light time as list """ return state, lt
def spkInterp(et,stepBitNum): """ This function interpolates earth state in one second with seveal exact points. To increase accuracy, each know point will be the exact number that can be represented by double precision. et is the target time stepBitNum determines that how small the step for exact points will be. And it is calculated by bits step = 1.0/2.0**stepBitNum """ step = 1.0/2.0**stepBitNum # Step from exact point numStep = 2.0**stepBitNum # Number of exact point et0 = np.floor(et) # Start point of interval etExctArray = np.linspace(et0,et0+1,numStep+1) # Exact time point array stateArray = [] # Earth state array for each exact point ltArray = [] # light time state array for each exact point """ Calculate the earth state and lt for each exact point """ for data in etExctArray: stateExct,ltExct = spice.spkezr("EARTH",data,"J2000","NONE","SSB") stateArray.append(stateExct) ltArray.append(ltExct) stateArray = np.array(stateArray) # Transfer to numpy array ltArray = np.array(ltArray) # Transfer to numpy array state = [] # Earth state for target time lt = [] # lt for target time """ Interpolate for target time """ for i in range(6): state.append(np.interp(et,etExctArray,stateArray[:,i])) lt.append(np.interp(et,etExctArray,ltArray)) """ Return earth state and light time as list """ return state,lt
def objPosVel(obj1, obj2, et): """Returns PosVel instance from obj1 to obj2 at et (TDB sec past J2000)""" pv, _ = spice.spkezr(obj2, float(et), "J2000", "NONE", obj1) return PosVel(pv[:3] * u.km, pv[3:] * u.km / u.s, origin=obj1, obj=obj2)
def objPosVel(obj1, obj2, et): """Returns PosVel instance from obj1 to obj2 at et (TDB sec past J2000)""" pv, _ = spice.spkezr(obj2, float(et), "J2000", "NONE", obj1) return PosVel(pv[:3]*u.km, pv[3:]*u.km/u.s, origin=obj1, obj=obj2)
spice.et2utc(tomsZeroEpoch, 'ISOC', 1), firstTomsUTC, fnInput, )) ### Iterators twoDshape = surfLonDegs.shape rowIter, pixelIter = map(xrange, twoDshape) glintAngles = numpy.zeros(twoDshape, dtype=numpy.float32) for row in rowIter: ### Earth-Sun vector, convert to unit vector earth2Sun = spice.spkezr('SUN', tomsZeroEpoch + tomsOffsetTimes[row], 'IAU_EARTH', 'LT+S', 'EARTH')[0][:3] uvEarth2Sun = spice.vhat(earth2Sun) scAltKm = scAltKms[row] scLonDeg = scLonDegs[row] scLatDeg = scLatDegs[row] for pixel in pixelIter: glintAngles[row, pixel] = glintangle(scAltKm, scLonDeg, scLatDeg, surfLonDegs[row, pixel], surfLatDegs[row, pixel], uvEarth2Sun) ### Get top level groups for copying
def test_smap(self): target = 'SMAP' et0 = spice.utc2et('2016-06-01T12:00:00') dpr = spice.dpr() a, b, c = [spice.gdpool('BODY399_RADII', i, 1)[1] for i in range(3)] ods = [] for deltatime in [0.1 * i for i in range(1080)]: et = et0 + deltatime stSmap, lsSmap = spice.spkezr(target, et, 'IAU_EARTH', 'NONE', 'EARTH') posn, veloc = stSmap[:3], stSmap[3:] stSun, lsSun = spice.spkezr('SUN', et0, 'IAU_EARTH', 'LT', 'EARTH') mtx = spice.pxform('SMAP_REFLECTOR', 'IAU_EARTH', et) boreEbf = spice.mxv(mtx, [1.0, 0, 0]) point = spice.surfpt(posn, boreEbf, a, b, c) rsurfpt, lon, lat = spice.reclat(point) utc = spice.et2utc(et, 'ISOC', 3) ods += [ OD(deltatime=deltatime, posn=posn, veloc=veloc, boreEbf=boreEbf, utc=utc, point=point, rsurfpt=rsurfpt, rsmap=spice.vnorm(posn), lat=lat, lon=lon, raynge=spice.vnorm(spice.vsub(point, posn)), sunsep=spice.vsep(spice.ucrss(posn, veloc), stSun[:3])) ] try: ### Moved matplotlib import to here so test runs to here at least from matplotlib import pyplot as plt plt.figure(1) keys = 'lat lon raynge'.split() secs = [od['deltatime'] for od in ods] for idx in range(len(keys)): scal = 1.0 if keys[ idx] in 'rsurfpt rsmap raynge sunsep rp ecc t0 mu a P eccmean amean Pmean'.split( ) else dpr ordinate = [od[keys[idx]] * scal for od in ods] plt.subplot(221 + idx) plt.plot(secs, ordinate) plt.plot(secs, ordinate, '.') plt.title(keys[idx]) plt.ylabel('%s%s' % (keys[idx], '' if scal == 1.0 else ', deg')) if idx > 1: plt.xlabel('T-T0, s') abscissa = [od['lon'] * dpr for od in ods] ordinate = [od['lat'] * dpr for od in ods] plt.subplot(221 + idx + 1) plt.title('lon vs. lat') plt.plot(abscissa, ordinate) plt.xlabel('lon, deg') plt.ylabel('lat, deg') plt.show() except: print("Bypassed, or failed, matplotlib tests")
def _gatherorbitdata(delta="1d", scale=15, verbose=False): # print("Building orbit for planets with SPICE...") spice.kclear() # Load the kernels that this program requires. this_dir = os.path.dirname(os.path.realpath(__file__)) spice.furnsh(os.path.join(this_dir, 'epys.mk')) # convert starting epoch to ET et0 = spice.str2et('2024/05/07 00:00') rate = 24 * 2 # Every 30 mins days = [(et0 + (day * (86400 / rate))) for day in range(366 * rate)] # internal variables and constants planets = ("MERCURY", "VENUS", "EARTH") AU = consts.AU / 1000. # AU [km] argps = [] argpxys = [] xyvecs = [] nuvecs = [] for planet in planets: # print(" > {}".format(planet)) dates = [] rvec = [] # vector of centric radii xyvec = [] # vector of (x,y) coordinates nuvec = [] # vector of nu (True Anomaly) values incvec = [] # vector of inclination values for et in days: if verbose: print('ET Seconds Past J2000: {}'.format(et)) # Compute the apparent state of MERCURY as seen from # the SUN in ECLIPJ2000 starg, ltime = spice.spkezr(planet, et, 'ECLIPJ2000', 'NONE', 'SUN') x, y, z, vx, vy, vz = [el / AU * scale for el in starg] r = math.sqrt(x ** 2 + y ** 2 + z ** 2) if verbose: print('\nApparent state of MERCURY as seen from', ' Sun in the J2000:') print(' X = {:10.4f} km (LT+S)'.format(x)) print(' Y = {:10.4f} km (LT+S)'.format(y)) print(' Z = {:10.4f} km (LT+S)'.format(z)) print('VX = {:10.4f} km/s (LT+S)'.format(vx)) print('VY = {:10.4f} km/s (LT+S)'.format(vy)) print('VZ = {:10.4f} km/s (LT+S)'.format(vz)) # calculate orbital elements from the starg state vector elts = spice.oscelt(starg, et, planetmu('Sun')) # define a solver for Kepler's equation ks = pyasl.MarkleyKESolver() # solve for the Eccentric Anomaly (E) with the # Mean Anomaly (M = elts[5]) and the # Eccentricity (ecc = elts[1]) E = ks.getE(elts[5], elts[1]) # calculate the True Anomaly (nu) from E and ecc (elts[1]) nuarg1 = math.sqrt(1 - elts[1]) * math.cos(E / 2) nuarg2 = math.sqrt(1 + elts[1]) * math.sin(E / 2) # atan2 in python needs the arguments as (y,x) # rather than (x,y) ...? nu = 2 * math.atan2(nuarg2, nuarg1) rvec.append(r) # append r for each day xyvec.append((x, y)) # append (x,y) coords for each day nuvec.append(nu) # append True anomaly for each day # build date in ISO format date = '{} {}'.format(spice.et2utc(et, 'ISOC', 0).split('T')[0], spice.et2utc(et, 'ISOC', 0).split('T')[1]) dates.append(date) # append date for each day incvec.append(elts[2]) # append inc. for each day (rads) # print(date, nu * spice.dpr(), x, y, z, r, elts[0]) # for this planet find the argument of pericenter (argp): # find the index of the min. r value for calculated range. argpi = rvec.index(min(rvec)) # calculate argp x and y values and argp using atan2 argpxy = (xyvec[argpi][0], xyvec[argpi][1] * math.cos(incvec[argpi])) argp = math.degrees(math.atan2(argpxy[1], argpxy[0])) argpxys.append(argpxy) # append argp (x,y) coords. argps.append(argp) # append argp xyvecs.append(xyvec) # append (x,y) coords. vector nuvecs.append(nuvec) # append true anomaly vector spice.kclear() return days, dates, xyvecs, argps, argpxys, nuvecs
spice.furnsh(dot.join(__file__.split(dot)[:-1] + ['py'])) ### Set arguments for Geometry Finder call ### - Times when VENUS crosses equator of Jupiter (Zjup = 0) ### - abcorr='LT+S' - correct for light time and stellar aberration ### - Timestep of 10 days (spice.spd() = seconds per day) ### - nintvls - 450 seems to work here target, frame, abcorr, obsrvr = 'VENUS', 'IAU_JUPITER', 'LT+S', 'JUPITER' relate, crdsys, coord = '=', 'RECTANGULAR', 'Z' refval, adjust, step, nintvls = 0.0, 0.0, spice.spd()*10, 450 ### Range of ETs to test etlo,ethi = [spice.gdpool(s,0,1)[1] for s in 'ETLO ETHI'.split()] cnfine = spice.wninsd( etlo, ethi, spice.objects.Cell(spice.DataType.SPICE_DP,2)) ### Create DP window to receive results result = spice.objects.Cell(spice.DataType.SPICE_DP,500) ### Make the call to the generic Geometry Finder call cnfine, result = spice.gfposc( target, frame, abcorr, obsrvr, crdsys, coord, relate, refval, adjust, step, nintvls, cnfine, result ) ### Output results as four columns ### - Crossing ordinal ### - UTC of crossing as ISO calendar time ### - TDB of crossing as calendar time (no leapseconds) ### - The Z value of Venus in the Jupiter-centered IAU_JUPITER frame for i in xrange(spice.wncard(result)): et0,et1 = spice.wnfetd(result,i) assert et0 == et1 print( ( i+1, spice.et2utc(et0,'ISOC',3), spice.etcal(et0), spice.spkezr(target,et0,frame,abcorr,obsrvr)[0][2] ,) )