コード例 #1
0
ファイル: moons.py プロジェクト: RichardHaythorn/cassinipy
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
コード例 #2
0
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()
コード例 #3
0
    def find_sub_pt(self):
        '''
            Finds the sub-observer point in the IAU_[target] frame
            and also the in the J2000 frame as seen from Earth.
            Also creates a vector from Earth to the sub-obs point in the 
            J2000 frame for future use.
        '''

        ## get the position of the sub-obs point in the J2000 frame
        self.subptvec, self.subptep, self.subpntobsvec = \
            spiceypy.subpnt('INTERCEPT/ELLIPSOID', self.target, \
                            self.et, self.target_frame, 'CN', 'EARTH')

        ## convert to lat/lon
        self.subptlon, self.subptlat, _ = \
            spiceypy.recpgr(self.target, self.subptvec, \
                            self.radii[0], self.flattening)

        ## convert the line of sight vector to J2000
        px1    = spiceypy.pxfrm2(self.target_frame, 'J2000', \
                                 self.subptep, self.et)

        self.subptJ2000 = np.matmul(px1, self.subpntobsvec)

        ## get the RA/DEC of the sub-obs point
        self.subRA, self.subDec = spiceypy.recrad(self.subptJ2000)[1:]
        self.RADec0 = np.array([self.subRA, self.subDec])
コード例 #4
0
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()
コード例 #5
0
ファイル: moons.py プロジェクト: RichardHaythorn/cassinipy
def cassini_altitude(dt, moon, target='CASSINI'):
    """

    :param dt:
    :param moon:
    :param target:
    :return:
    """
    et = spice.datetime2et(dt)
    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)

    return alt
コード例 #6
0
ファイル: tquakes.py プロジェクト: seap-udea/tQuakes
def bodyHA(body,et,qlon):
    import spiceypy as sp

    # SUB POINT POSITION
    pos=sp.subpnt("Intercept:  ellipsoid",
                  "EARTH",et,"IAU_EARTH","NONE",
                  body)
    lpos=sp.recpgr("EARTH",pos[0],REARTH,FEARTH);

    # LATITUDE AND LONGITUDE
    lon=lpos[0]*RAD
    lat=lpos[1]*RAD

    # print d2s(lon),d2s(lat)
    
    # DIFFERENCE IN LONGITUDE
    dlon=numpy.mod(qlon-lon,360)

    # HOUR ANGLE
    # H = LST - ALPHA
    ha=dlon

    return ha
コード例 #7
0
ファイル: maven_sc.py プロジェクト: irbdavid/maven
 def f(p):
     return spiceypy.recpgr(body, p, r, e)
コード例 #8
0
    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
コード例 #9
0
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()
コード例 #10
0
    def project(self, get_illum=True, use_full_image=False):
        '''
            retrieve the planetographic coordinates of the center 
            of each pixel in the image

            Parameters
            ----------
            get_illum : bool
                flag to also retrieve illumination angles (incidence,
                emission and phase), and get a Lambertian correction 
                [default: True]
            use_full_image : bool
                flag to process the full image, or use a bounding box
                of 1.2*(planetary radius) around the center to speed up
                computation. Turn off if bounding box produces errors.
                [default: False]
        '''
        if not use_full_image:
            maxsize = np.max([self.obsa, self.obsb])*self.platecal.scale

            xstart, ystart = np.asarray(self.R2P0 - 1.2*maxsize, dtype=int)
            xend, yend     = np.asarray(self.R2P0 + 1.2*maxsize, dtype=int)
            xstart = max([xstart, 0])
            ystart = max([ystart, 0])
            xend   = min([xend, self.nx])
            yend   = min([yend, self.ny])
        else:
            xstart = 0
            xend   = self.nx
            ystart = 0
            yend   = self.ny

        ## create the empty arrays to hold the values
        imgshape = self.img.shape[:2]
        self.lat = -1000.*np.ones(imgshape)
        self.lon = -1000.*np.ones(imgshape)

        if get_illum:
            self.incidence  = np.zeros(imgshape)
            self.emission   = np.zeros(imgshape)
            self.phase      = np.zeros(imgshape)
            self.solar_corr = np.zeros(imgshape)

        for j in range(ystart, yend):
            if(j%10 == 0):
                print("\r %3d/%3d"%(j, yend), end='')
            for i in range(xstart, xend):

                ## find the vector that refers to this pixel 
                pix     = np.array([i,j], dtype=float)
                RADeci  = self.pix2radec(pix)
                veci = spiceypy.radrec(1., RADeci[0], RADeci[1])

                ## check for the intercept
                try:
                    spoint, ep, srfvec = \
                        spiceypy.sincpt(\
                            "Ellipsoid", self.target, self.et,\
                            self.target_frame, "CN", "EARTH",\
                            "J2000", veci)
                except Exception as e: 
                    continue

                ## if the intercept works, determine the planetographic
                ## lat/lon values
                loni, lati, alt = \
                    spiceypy.recpgr(self.target, spoint, \
                                    self.radii[0], self.flattening)

                self.lat[j,i] = np.degrees(lati)
                self.lon[j,i] = np.degrees(loni)

                if get_illum:
                    _, _, phasei, inci, emissi = \
                        spiceypy.ilumin("Ellipsoid", self.target, \
                                self.et, self.target_frame, "CN",\
                                "EARTH", spoint) 

                    ## apply Lambertian correction
                    mu = np.cos(emissi); mu0 = np.cos(inci)
                    self.solar_corr[j,i] = 1./mu0

                    ## save the 
                    self.phase[j,i]      = phasei
                    self.incidence[j,i]  = inci
                    self.emission[j,i]   = emissi

        img = self.img.copy()
        if get_illum:
            if(len(img.shape) > 2):
                for i in range(img.shape[2]):
                    img[:,:,i] *= self.solar_corr


        ## plot them out
        fig = plt.figure(figsize=(8,15))
        ax1 = fig.add_subplot(311)
        ax2 = fig.add_subplot(312)
        ax3 = fig.add_subplot(313)

        ax1.imshow(self.lon, vmin=0., vmax=360.)
        ax1.contour(self.lon, np.arange(0., 360., 15.), colors='k')
        ax2.imshow(self.lat, vmin=-90., vmax=90.)
        ax2.contour(self.lat, np.arange(-90, 90., 15.), colors='k')
        ax3.imshow(img)
        ax3.contour(self.lon, np.arange(0., 360., 30.), colors='k', linewidths=0.5)
        ax3.contour(self.lat, np.arange(-90, 90., 30.), colors='k', linewidths=0.5)


        ax1.set_title("Longitude")
        ax2.set_title("Latitude")

        plt.tight_layout()
        plt.show()
コード例 #11
0
    def vector_params(self, vector) : 

        ret = np.full(shape = [len(self.keys)], fill_value = -1000.0)
        
        # Calculate the distance of the boresight and the center of the target
        origin = np.array([0.0, 0.0, 0.0])
        nearpoint, rayradius = spice.nplnpt(self.scloc, vector, origin)

        # Get the intercept to calculate the radius of of the target 
        normal = spice.surfpt(origin, 1000.0 * nearpoint, self.radii[0], self.radii[1], self.radii[2])
        ret[self.map['limb_distance']] = rayradius - spice.vnorm(normal)
    
        # Calculate the 'occultation' latitude and longitude 
        ret[self.map['bodyintercept']], ret[self.map['limb_lat']], ret[self.map['limb_lon']] = spice.reclat(nearpoint) 

        # Test if the boresight intersects with our target surface 
        try: 
            point = spice.surfpt(self.scloc, vector, self.radii[0], self.radii[1], self.radii[2])
            intercept = True
        except: 
            intercept = False
    
        if (intercept) : 
        
            # Get some angles 
            ret[self.map['phase']], ret[self.map['incidence']], ret[self.map['emission']] = spice.illum(self.target, self.et , self.abcorr, self.spacecraft, point)

            # Calculate the planetocentric coordinates 
            distance, ret[self.map['lon']], ret[self.map['lat']] = spice.reclat(point)
            ret[self.map['losdist']] = spice.vnorm(self.scloc - point)
            
             # Calculate the planetographic coordinates
            ret[self.map['lon_graphic']], ret[self.map['lat_graphic']], bodyintercept = spice.recpgr(self.target, point, self.radii[0], self.flattening)
            
            # Get the localtime, and convert to decimal hours 
            hr, min, sc, time, ampm = spice.et2lst(self.et, self.target_id, ret[self.map['lon']], 'PLANETOCENTRIC')
            ret[self.map['localtime']] = hr + min / 60.0 + sc / 3600.0
            
        # For the angles, convert radians to degrees
        for key in self.angles : 
            if (ret[self.map[key]] != -1000.0) : 
                    ret[self.map[key]] = np.rad2deg(ret[self.map[key]])

        # Makes sure longitudes wrap 0 to 360, spice returns the Earth-like -180 to 180. 
        longitudes = ['lon', 'limb_lon', 'lon_graphic']
        for key in longitudes : 
            ret[self.map[key]] = ret[self.map[key]] % 360

        return np.array(ret)