Exemple #1
0
def _make_new_meta_kernel(kernels, local_kernel_dir, new_pathname):
    path_values = spice.gcpool("PATH_VALUES", 0, 256)
    path_symbols = spice.gcpool("PATH_SYMBOLS", 0, 256)
    kernels_to_load = spice.gcpool("KERNELS_TO_LOAD", 0, 1024)

    s = "KPL/MK\n"
    s += "\\begindata\n"
    # PATH_VALUES
    s += "  PATH_VALUES     = (\n"
    path_base = Path(local_kernel_dir)
    for path_value in path_values:
        s += "    '" + str(path_base / path_value) + "'\n"
    s += "  )\n"
    # PATH_SYMBOLS
    s += "  PATH_SYMBOLS    = (\n"
    for path_symbol in path_symbols:
        s += "    '" + path_symbol + "'\n"
    s += "  )\n"
    # KERNELS_TO_LOAD
    s += "  KERNELS_TO_LOAD = (\n"
    for kernel in kernels_to_load:
        s += "    '" + kernel + "'\n"
    s += "  )\n"
    with open(new_pathname, "w") as f:
        f.write(s)
Exemple #2
0
def test_topo_frame_setup():
    # Check that the frame setup puts all the correct values in the kernel pool.

    latitude, longitude = 30, 25
    name, idnum, frame_dict, latlon = spice_utils.topo_frame_def(
        latitude, longitude)
    frame_strs = ["{}={}".format(k, v) for (k, v) in frame_dict.items()]
    spice.lmpool(frame_strs)

    for k, v in frame_dict.items():
        N, typecode = spice.dtpool(k)
        if typecode == 'N':
            res = spice.gdpool(k, 0, 100)
            if len(res) == 1:
                res = [int(res[0])]
            if N > 1:
                v = [float(it) for it in v.split(' ')]
                res = res.tolist()
            else:
                res = res[0]
                v = int(v)
            assert v == res
        else:
            res = spice.gcpool(k, 0, 100)[0]
            v = v.replace('\'', '')
            assert v == res
Exemple #3
0
def get_orientation_matrix(obsinfo, target, object_id):
    iau_frame = f"IAU_{target}"
    frcode = spice.namfrm(iau_frame)
    if frcode == 0:
        frame_name = f"FRAME_{object_id}_NAME"
        _n, iau_frame = spice.gcpool(frame_name, 0, 1)
        frcode = spice.namfrm(iau_frame)
    mtx = spice.pxform(iau_frame, obsinfo.fov.frame, obsinfo.et)
    # rot = get_boresight_rotation_matrix(obsinfo['boresight'])
    # return spice.mxm(rot, mtx)
    return mtx
Exemple #4
0
def _meta_kernel_to_urls(meta_kernel, url, local_kernel_dir, remote_root):
    spice.ldpool(meta_kernel)
    path_values = spice.gcpool("PATH_VALUES", 0, 256)
    path_symbols = spice.gcpool("PATH_SYMBOLS", 0, 256)
    kernels_to_load = spice.gcpool("KERNELS_TO_LOAD", 0, 1024)

    symbols = {}
    for path_value, path_symbol in zip(path_values, path_symbols):
        symbols[f"${path_symbol}"] = path_value

    url_base = urllib.parse.urljoin(url, remote_root)
    path_base = Path(local_kernel_dir)
    kernel_urls = []
    for kernel in kernels_to_load:
        for key in symbols:
            if key in kernel:
                kernel = kernel.replace(key, symbols[key])
        remote_url = urllib.parse.urljoin(url_base, kernel)
        local_path = str(path_base / kernel)
        kernel_urls.append((remote_url, local_path))
    return kernel_urls
Exemple #5
0
    def correct_lt_to_surface(self):
        """
        Returns if light time correction should be made to the surface instead of
        to the center of the body. This is defined by a keyword in ISIS IAKs.
        If the keyword is not defined in any loaded kernels then False is returned.

        Expects ikid to be defined. This should be an integer containing the
        Naif Id code of the instrument.
        """
        try:
            surface_correct = spice.gcpool(
                'INS{}_LT_SURFACE_CORRECT'.format(self.ikid), 0, 1)[0]
            return surface_correct.upper() == "TRUE"
        except:
            return False
Exemple #6
0
    def swap_observer_target(self):
        """
        Returns if the observer and target should be swapped when determining the
        sensor state relative to the target. This is defined by a keyword in
        ISIS IAKs. If the keyword is not defined in any loaded kernels then False
        is returned.

        Expects ikid to be defined. This should be an integer containing the
        Naif Id code of the instrument.
        """
        try:
            swap = spice.gcpool('INS{}_SWAP_OBSERVER_TARGET'.format(self.ikid),
                                0, 1)[0]
            return swap.upper() == "TRUE"
        except:
            return False
Exemple #7
0
def _spice_setup(latitude, longitude):
    if not isinstance(latitude, (int, float)):
        latitude = latitude[0]
    if not isinstance(longitude, (int, float)):
        longitude = longitude[0]

    loadnew = True
    frameloaded = check_is_loaded('*LUNAR-TOPO*')
    if frameloaded:
        latlon = spice.gcpool('TOPO_LAT_LON', 0, 8)
        loadnew = not latlon == ["{:.4f}".format(l) for l in [latitude, longitude]]
    if loadnew:
        station_name, idnum, frame_specs, latlon = topo_frame_def(latitude, longitude, moon=True)
        spice.pcpool('TOPO_LAT_LON', latlon)
        frame_strs = ["{}={}".format(k, v) for (k, v) in frame_specs.items()]
        spice.lmpool(frame_strs)
Exemple #8
0
    def light_time_correction(self):
        """
        Returns the type of light time correciton and abberation correction to
        use in NAIF calls. Expects ikid to be defined. This must be the integer
        Naif id code of the instrument.

        This searches for the value of the NAIF keyword INS<ikid>_LIGHTTIME_CORRECTION.
        If the keyword is not defined, then this defaults to light time
        correction and abberation correction (LT+S).

        Returns
        -------
        : str
          The light time and abberation correction string for use in NAIF calls.
          See https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/abcorr.html
          for the different options available.
        """
        try:
            return spice.gcpool('INS{}_LIGHTTIME_CORRECTION'.format(self.ikid),
                                0, 1)[0]
        except:
            return 'LT+S'
Exemple #9
0
                                              self.lineTerm))


########################################################################
if "__main__" == __name__:
    # FURNSH the docstring above as a text kernel,
    # plus any other files on the command line,
    # and put values into kernel pool
    for arg in sys.argv:
        spice.furnsh(arg)
    # Get pairs of ET endpoints from kernel pool
    pts = list(spice.gdpool('PAIR_TIMES', 0, 100))
    nPETs = len(pts)
    # Set or clear debug flag
    try:
        doDebug = True if spice.gcpool("DEBUG", 0, 1, 999)[0] else False
    except:
        doDebug = False
    # Allocate cell of SpiceDoubles
    pws = stypes.SPICEDOUBLE_CELL(nPETs)
    # Add ET endpoints to cell
    pts.reverse()
    while pts:
        spice.appndd(pts.pop(), pws)
    # Convert those pairs of ET endpoints into confinement window
    pws = spice.wnvald(nPETs, nPETs, pws)
    assert (spice.wncard(pws) << 1) == nPETs
    pts = list(spice.gdpool('PAIR_TIMES', 0, 100))
    # Get the filename of, and read, the input XFR file
    filename = spice.gcpool("XPC_KERNEL", 0, 1, 999)[0]
    assert filename
Exemple #10
0
def create_ck(kernels, frames_to_convert, fks, stop_ets, output_ck):
    """
  Create CK from FKs and times at which the FKs end being valid

  """

    ### FURNSH any kernels
    for kernel in kernels:
        sp.furnsh(kernel)

    ### Set last ET to None so it will be initialized in loop's first pass
    last_et = None

    ### Do not overwrite existing output CK
    assert (not sp.exists(output_ck)
            ) or dict()['Cannot overwrite existing CK[{}]'.format(output_ck)]

    ### Initialize CK handle to None
    ck_handle = None

    ### Loop over CKs
    while fks:

        ### Get FK and corresponding stop ET
        fk = fks.pop()
        stop_et = stop_ets.pop()

        ### Loop over reference frames (reffrms)
        for reffrm in frames_to_convert:

            ### Get reffrm ID, SCLK ID; N.B. latter comes from new FK
            reffrm_id = sp.gipool('FRAME_{}'.format(reffrm.upper()), 0, 1)[0]
            sclk_id = sp.gipool('CK_{}_{}'.format(reffrm_id, 'SCLK'), 0, 1)[0]

            ### Set start DP-SCLK of window for this old FK (outer loop)
            ### - Set to zero for first window
            ### - Covnert ET to DP-SCLK for subsequent windows
            if last_et is None: begtim = 0.0
            else: begtim = sp.sce2t(sclk_id, last_et)

            ### Load old FK, get RELATIVE frame name, get time-invariant
            ### matrix, and unload old FK
            sp.furnsh(fk)
            relative_reffrm = sp.gcpool(
                'TKFRAME_{}_{}'.format(reffrm_id, 'RELATIVE'), 0, 1, 99)[0]
            mtx = sp.pxform(relative_reffrm, reffrm, 0.0)
            sp.unload(fk)

            ### Covnert matrix to quaternion
            quat = sp.m2q(mtx)

            ### Calculate tick rate:  seconds per tick
            rate = (sp.sct2e(sclk_id, 1e3) - sp.sct2e(sclk_id, 0.)) / 1e3

            if doVerbose:
                ### if VERBOSE environment variable is present, log information
                print((
                    relative_reffrm,
                    reffrm,
                    fk,
                    last_et,
                    stop_et,
                    '{:010.3f}'.format(1. / rate),
                    quat,
                ))

            ### Set stop DP-SCLK of window
            if stop_et < -1e30:
                ### Use end of encoded DP_SCLK for final window
                endtim = sp.gdpool('SCLK_PARTITION_END_{}'.format(-sclk_id), 0,
                                   999)[-1]
            else:
                ### Else convert stop ET to DP-SCLK
                endtim = sp.sce2t(sclk_id, stop_et)

            if doDebug:
                ### Debug output
                pprint.pprint(
                    dict(fk=fk,
                         reffrm=reffrm,
                         reffrm_id=reffrm_id,
                         relative_reffrm=relative_reffrm,
                         rate=rate,
                         begtim=begtim,
                         endtim=endtim,
                         diff=endtim - begtim,
                         mtx=mtx,
                         quat=quat))

            ### Open CK, once
            if ck_handle is None:
                ck_handle = sp.ckopn(output_ck, 'ORX FK REPLACEMENT', 0)

            ### Write Type 2 CK segment with one record; angular velocity = 0
            sp.ckw02(ck_handle, begtim, endtim, reffrm_id, relative_reffrm,
                     '{}[{}]'.format(os.path.basename(fk), reffrm)[:40], 1,
                     [begtim], [endtim], [quat], [[0., 0., 0.]], [rate])

        ### Save stop ET for start ET of next pass
        last_et = stop_et

    ### Close CK
    if not (ck_handle is None): sp.ckcls(ck_handle)
Exemple #11
0
def main(argv_arg=sys.argv[1:]):
    """
  Process oommand-line arguments into input to create_ck and test_ck 
  methods

  """

    ### Process arguments

    ### Create set of non-kernel options
    non_kernel_opts = set('--test --create'.split())

    ### All arguments which are not in that set are SPICE kernels
    kernels = [arg for arg in argv_arg if not (arg in non_kernel_opts)]

    ### - Use this script as the lone SPICE kernel if none provided
    if not kernels:
        kernels = [__file__[-4:-1] == '.py' and __file__[:-1] or __file__]

    ### - FURNSH those kernels
    for kernel in kernels:
        sp.furnsh(kernel)

    ### Get frames to convert from FK to CK form
    frames_to_convert = sp.gcpool('FRAMES_TO_CONVERT', 0, 999, 99)
    assert frames_to_convert

    ### Get FK paths; use STPOOL in case paths are long
    fks = list()
    item = 0
    while True:
        ### - Use '+' for continuation
        ### - Read paths until exception; assume that indicates the end
        try:
            fks.append(sp.stpool('FKS', item, '+', 2048)[0])
        except:
            if doDebug:
                tb.print_exc()
                sys.stderr.write('\nN.B. Expected error; continuing ...\n\n')
            break
        item += 1

    ### Throw exception if no FKs were provided
    assert fks

    ### Get stop times for each FK, cast to list so .pop() is available
    stop_ets = list(sp.gdpool('STOP_ETS', 0, 999))

    ### Ensure there is a stop time for each FK
    assert len(fks) == len(stop_ets)

    ### Reverse order of FKs so .pop() will get items in order
    fks.reverse()
    stop_ets.reverse()

    ### Get output CK path
    output_ck = sp.stpool('OUTPUT_CK', 0, '+', 2048)[0]

    ### Unload all kernels
    sp.kclear()

    if '--create' in argv_arg:
        ### Call method to create CK; pass copies of fks and stop_ets
        create_ck(kernels, frames_to_convert, fks[:], stop_ets[:], output_ck)

    if '--test' in argv_arg:
        ### Call test method; pass copies of fks and stop_ets
        test_ck(kernels, frames_to_convert, fks[:], stop_ets[:], output_ck)
Exemple #12
0
def test_ck(kernels, frames_to_convert, fks, stop_ets, output_ck):
    """
  Text CK against FKs at times at which the FKs are valid

  """

    ### Load base kernels (LSK, new FK, SCLK)
    for kernel in kernels + [output_ck]:
        sp.furnsh(kernel)

    ### Set last ET to None so it will be initialized in loop's first pass
    last_et = None

    ### Create dict of info; keys will be new FK filenames
    dt = dict()

    while fks:

        ### Pop FK and stop ET off of lists
        fk = fks.pop()
        stop_et = stop_ets.pop()

        ### Create dict for this FK
        dt[fk] = dict()

        ### Loop over refernce frames
        for reffrm in frames_to_convert:

            ### Get reffrm ID, SCLK ID; N.B. latter comes from new FK
            reffrm_id = sp.gipool('FRAME_{}'.format(reffrm.upper()), 0, 1)[0]
            sclk_id = sp.gipool('CK_{}_{}'.format(reffrm_id, 'SCLK'), 0, 1)[0]

            ### Set start DP-SCLK of window for this old FK (outer loop)
            ### - Set to zero for first window
            ### - Covnert ET to DP-SCLK for subsequent windows
            if last_et is None: et_lo = sp.sct2e(sclk_id, 0.)
            else: et_lo = last_et

            ### Load old FK, get RELATIVE frame name, get time-invariant
            ### matrix, and unload old FK
            sp.furnsh(fk)
            relative_reffrm = sp.gcpool(
                'TKFRAME_{}_{}'.format(reffrm_id, 'RELATIVE'), 0, 1, 99)[0]
            sp.unload(fk)

            ### Get ETs at which to do the tests:
            ### - 10s after start of window
            ### - 10s before end of window, or 1e6s after start if last window
            if stop_et < -1e30:
                et_test_lo = et_lo + 10.
                et_test_hi = et_lo + 1e6
            else:
                et_delta = min([10., (stop_et - et_lo) / 3.])
                et_test_lo = et_lo + et_delta
                et_test_hi = stop_et - et_delta

            ### Save the relative reffrm, the reffrm, the window, and an empty
            ### dict for this reffrm under this FK
            dt[fk][reffrm] = (relative_reffrm, et_test_lo, et_test_hi, dict())

        ### For next pass
        last_et = stop_et

    ### Clear all kernels, and test
    sp.kclear()
    assert 0 == sp.ktotal('all')

    ### Load base kernels including new FK and new CK
    for kernel in kernels + [output_ck]:
        sp.furnsh(kernel)

    ### Loop over old FKs, reffrms, and ETs
    for fk in dt:

        for reffrm in dt[fk]:

            ### Retrieve relative reffrm, ETs and quat dict
            relative_reffrm, et_test_lo, et_test_hi, dtquat = dt[fk][reffrm]

            for et in (
                    et_test_lo,
                    et_test_hi,
            ):

                ### Lookup CK-based matrix, convrt to and save quat at each ET
                dtquat[et] = sp.m2q(sp.pxform(relative_reffrm, reffrm, et))

    ### Loop over the old FKs again
    for fk in dt:

        ### Clear all kernels, and test
        sp.kclear()
        assert 0 == sp.ktotal('all')

        ### Load only the old FK
        sp.furnsh(fk)

        ### Loop over reffrms, and ETs
        for reffrm in dt[fk]:

            relative_reffrm, et_test_lo, et_test_hi, dtquat = dt[fk][reffrm]

            for et in (
                    et_test_lo,
                    et_test_hi,
            ):

                ### Calculate norm of difference of CK-based and FK-based quats
                quat_error = round(
                    sp.vnorm(dtquat[et] -
                             sp.m2q(sp.pxform(relative_reffrm, reffrm, et))),
                    16)

                ### Output that norm as an error for each case, which norm
                ### should be zero
                print(
                    dict(fk=fk,
                         quat_error=quat_error,
                         relative_reffrm=relative_reffrm,
                         reffrm=reffrm,
                         et='{:015.4f}'.format(et)))
    ### SPICE names of Clock, minute hand, hour hand
    sClock, sMinute, sHour = sNames = "CLOCK MINUTE HOUR".split()

    ### SPICE works in seconds; get seconds per minute, per hour, per day
    spm = sp.convrt(1.0, 'minutes', 'seconds')
    sph = sp.convrt(1.0, 'hours', 'seconds')
    hpd = sp.convrt(1.0, 'days', 'hours')
    spd = sp.spd()

    ### Other constants:  2*PI; degrees/radian
    twopi = sp.twopi()
    dpr = sp.dpr()

    ### Get start time (TDB) and SPK filename from kernel pool
    et0 = sp.gdpool('ET0', 0, 1)[0]
    fnClockSpk = sp.gcpool('CLOCKSPK', 0, 1, 99)[0]

    ### Make clock SPK if it does not exist
    if not os.path.exists(fnClockSpk):

        ### Orbital period formula:
        ###
        ###   T = 2 PI (a*3 / mu))**(1/2)
        ###
        ### where
        ###
        ###    T = orbital period
        ###    a = length of semi-major axis
        ###   mu = GM, standard gravitational parameter
        ###        => G is the gravitational constant
        ###        => M is the mass of the more massive body (CLOCK, here)
Exemple #14
0
def gen_frame_dict(mk, report=False):
    #
    # Frame names are as follows:
    # r'FRAME_-?[0-9]*_NAME'
    #
    frame_dict = {}

    spiceypy.furnsh(mk)

    start = 1
    n_items = 9999
    template = 'FRAME_*_NAME'
    try:
        cvals = spiceypy.gnpool(template, start, n_items)
        if report: print(f'Number of reference frames defined: {len(cvals)}')
    except SpiceyError:
        print('No frames definitions present')
        return

    #
    # Okay, now we know something about the kernel pool
    # variables of interest to us. Let's find out more...
    #
    for cval in cvals:

        #
        # We check the type of variable:
        # C (character) or N (numeric), of each pool
        # variable name in the cvals array. It has to
        # be a character
        #
        start = 0
        n_items = 20
        [dim, type] = spiceypy.dtpool(cval)

        if type == 'C':
            cvars = spiceypy.gcpool(cval, start, n_items)
            #
            # The variable (list) should be unique
            #
            if len(cvars) > 1:
                spiceypy.kclear()
                raise Exception(f'Variable {cval} is incorrect')

            #
            # We build the frames dictionary
            #
            frmclass = spiceypy.gipool(cval.replace('NAME', 'CLASS'), start,
                                       n_items)
            frmid = spiceypy.gipool(cval.replace('NAME', 'CLASS_ID'), start,
                                       n_items)
            frmcentr = spiceypy.gipool(cval.replace('NAME', 'CENTER'), start,
                                       n_items)

            if frmclass[0] == 4:
                try:
                    varname = cval.replace('FRAME','TKFRAME').replace('NAME', 'RELATIVE')
                    frmrelat = spiceypy.gcpool(varname, start, n_items)
                except:
                    frmrelat = ['ERROR']
            else:
                frmrelat = ['N/A']


            frame_dict[cvars[0]] = { 'name': cvars[0],
                                     'class':frmclass[0],
                                     'id': frmid[0],
                                     'center': frmcentr[0],
                                     'relative': frmrelat[0]
                                    }

            if report:
                print(f'  CLASS: {frmclass[0]}  NAME: {cvars[0]} ')


        else:
            spiceypy.kclear()
            raise Exception(f'Variable {cval} is incorrect')

    spiceypy.kclear()

    return frame_dict