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
Exemplo n.º 2
0
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
Exemplo n.º 5
0
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
Exemplo n.º 11
0
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()
Exemplo n.º 12
0
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
Exemplo n.º 13
0
 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
Exemplo n.º 14
0
    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
Exemplo n.º 16
0
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)
Exemplo n.º 17
0
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)
Exemplo n.º 18
0
    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
Exemplo n.º 19
0
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
Exemplo n.º 20
0
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
Exemplo n.º 21
0
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)
Exemplo n.º 23
0
    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
Exemplo n.º 24
0
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
Exemplo n.º 27
0
    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
Exemplo n.º 28
0
    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)
Exemplo n.º 29
0
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
Exemplo n.º 30
0
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
Exemplo n.º 31
0
 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
Exemplo n.º 32
0
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))
Exemplo n.º 33
0
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
Exemplo n.º 34
0
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
Exemplo n.º 35
0
 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)
Exemplo n.º 36
0
# (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)
Exemplo n.º 37
0
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
Exemplo n.º 38
0
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'
Exemplo n.º 39
0
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()
Exemplo n.º 40
0
 def f(t):
     pos, lt = spiceypy.spkpos("SUN", t, 'IAU_MARS', "NONE", "MARS")
     return np.array(pos)
Exemplo n.º 41
0
 def f(t):
     pos, lt = spiceypy.spkpos("SUN", t, 'IAU_' + body, "NONE", body)
     return np.array(pos)
Exemplo n.º 42
0
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