CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-spiceypy

A Python wrapper for the NAIF CSPICE Toolkit providing essential tools for spacecraft navigation and planetary science calculations

Overview
Eval results
Files

dsk-shape-models.mddocs/

DSK (Digital Shape Kernels)

Advanced 3D shape model operations for celestial bodies using Digital Shape Kernels. DSK files contain high-fidelity surface representations that enable precise geometric calculations, ray tracing, and surface analysis for irregularly shaped objects like asteroids, comet nuclei, and small moons.

Capabilities

DSK File Operations

Create, open, and manage DSK files containing 3D shape model data.

def dskopn(fname: str, ifname: str, ncomch: int) -> int:
    """
    Open new DSK file for writing.
    
    Parameters:
    - fname: str, DSK file name
    - ifname: str, internal file name  
    - ncomch: int, number of comment characters
    
    Returns:
    int: file handle
    """

def dskcls(handle: int) -> None:
    """
    Close DSK file.
    
    Parameters:
    - handle: int, file handle
    
    Returns:
    None
    """

Type 2 DSK Operations

Handle Type 2 DSK segments (triangular plate models).

def dskw02(handle: int, center: int, surfid: int, dclass: int, frame: str, corsys: int, corpar: ndarray, mncor1: float, mxcor1: float, mncor2: float, mxcor2: float, mncor3: float, mxcor3: float, first: float, last: float, nv: int, vrtces: ndarray, np: int, plates: ndarray, spaixd: ndarray, spaixi: ndarray) -> None:
    """
    Write Type 2 DSK segment to file.
    
    Parameters:
    - handle: int, file handle
    - center: int, central body ID
    - surfid: int, surface ID
    - dclass: int, data class
    - frame: str, reference frame
    - corsys: int, coordinate system  
    - corpar: ndarray, coordinate parameters
    - mncor1, mxcor1: float, coordinate 1 bounds
    - mncor2, mxcor2: float, coordinate 2 bounds
    - mncor3, mxcor3: float, coordinate 3 bounds
    - first, last: float, time bounds
    - nv: int, number of vertices
    - vrtces: ndarray, vertex coordinates
    - np: int, number of plates
    - plates: ndarray, plate vertex indices
    - spaixd: ndarray, spatial index (double)
    - spaixi: ndarray, spatial index (integer)
    
    Returns:
    None
    """

def dskb02(handle: int, center: int, surfid: int, dclass: int, frame: str, corsys: int, corpar: ndarray, mncor1: float, mxcor1: float, mncor2: float, mxcor2: float, mncor3: float, mxcor3: float, first: float, last: float) -> None:
    """
    Begin new Type 2 DSK segment.
    
    Parameters:
    - handle: int, file handle
    - center: int, central body ID
    - surfid: int, surface ID
    - dclass: int, data class
    - frame: str, reference frame
    - corsys: int, coordinate system
    - corpar: ndarray, coordinate parameters
    - mncor1, mxcor1: float, coordinate 1 bounds
    - mncor2, mxcor2: float, coordinate 2 bounds  
    - mncor3, mxcor3: float, coordinate 3 bounds
    - first, last: float, time bounds
    
    Returns:
    None
    """

Shape Model Queries

Query shape model data and perform geometric calculations.

def dskobj(dsk: str) -> List[int]:
    """
    Get object IDs for bodies in DSK file.
    
    Parameters:
    - dsk: str, DSK file name
    
    Returns:
    List[int]: body ID codes
    """

def dsksrf(dsk: str, bodyid: int) -> List[int]:
    """
    Get surface IDs for body in DSK file.
    
    Parameters:
    - dsk: str, DSK file name
    - bodyid: int, body ID code
    
    Returns:
    List[int]: surface ID codes
    """

def dskgd(dsk: str, bodyid: int, surfid: int) -> SpiceDSKDescr:
    """
    Get DSK descriptor for specified surface.
    
    Parameters:
    - dsk: str, DSK file name
    - bodyid: int, body ID code
    - surfid: int, surface ID code
    
    Returns:
    SpiceDSKDescr: DSK descriptor
    """

Surface Intersection

Find intersections between rays and DSK shape models.

def dskxv(pri: bool, target: str, nsurf: int, srflst: List[int], et: float, fixref: str, vtx: ndarray, raydir: ndarray) -> Tuple[ndarray, bool]:
    """
    Compute ray-surface intercept using DSK data.
    
    Parameters:
    - pri: bool, prioritize closer surfaces
    - target: str, target body name
    - nsurf: int, number of surfaces
    - srflst: List[int], surface ID list
    - et: float, ephemeris time
    - fixref: str, body-fixed reference frame
    - vtx: ndarray, ray vertex
    - raydir: ndarray, ray direction vector
    
    Returns:
    Tuple[ndarray, bool]: (intercept_point, found)
    """

def dskxsi(pri: bool, target: str, nsurf: int, srflst: List[int], et: float, fixref: str, vtx: ndarray, raydir: ndarray) -> Tuple[ndarray, int, int, float, float, bool]:
    """
    Compute ray-surface intercept with extended information.
    
    Parameters:
    - pri: bool, prioritize closer surfaces
    - target: str, target body name
    - nsurf: int, number of surfaces
    - srflst: List[int], surface ID list  
    - et: float, ephemeris time
    - fixref: str, body-fixed reference frame
    - vtx: ndarray, ray vertex
    - raydir: ndarray, ray direction vector
    
    Returns:
    Tuple[ndarray, int, int, float, float, bool]: (point, handle, dladsc, dscdsc, dc, found)
    """

Plate Model Access

Access triangular plate data from Type 2 DSK segments.

def dskv02(handle: int, dladsc: SpiceDLADescr, start: int, room: int) -> Tuple[int, ndarray]:
    """
    Fetch vertices from Type 2 DSK segment.
    
    Parameters:
    - handle: int, DSK file handle
    - dladsc: SpiceDLADescr, DLA descriptor
    - start: int, start index (1-based)
    - room: int, number of vertices to fetch
    
    Returns:
    Tuple[int, ndarray]: (n, vertices)
    """

def dskp02(handle: int, dladsc: SpiceDLADescr, start: int, room: int) -> Tuple[int, ndarray]:
    """
    Fetch plates from Type 2 DSK segment.
    
    Parameters:
    - handle: int, DSK file handle
    - dladsc: SpiceDLADescr, DLA descriptor
    - start: int, start index (1-based)
    - room: int, number of plates to fetch
    
    Returns:
    Tuple[int, ndarray]: (n, plates)
    """

def dskz02(handle: int, dladsc: SpiceDLADescr) -> Tuple[int, int]:
    """
    Get vertex and plate counts from Type 2 DSK segment.
    
    Parameters:
    - handle: int, DSK file handle
    - dladsc: SpiceDLADescr, DLA descriptor
    
    Returns:
    Tuple[int, int]: (nv, np) vertex and plate counts
    """

Normal Vector Computation

Compute surface normal vectors at intercept points.

def dskn02(handle: int, dladsc: SpiceDLADescr, plid: int) -> ndarray:
    """
    Compute outward normal vector for Type 2 DSK plate.
    
    Parameters:
    - handle: int, DSK file handle
    - dladsc: SpiceDLADescr, DLA descriptor
    - plid: int, plate ID (1-based)
    
    Returns:
    ndarray: outward normal unit vector
    """

DSK Tolerance Management

Manage numerical tolerances for DSK operations.

def dskgtl(keywrd: str) -> float:
    """
    Get DSK tolerance or margin parameter.
    
    Parameters:
    - keywrd: str, parameter keyword
    
    Returns:
    float: parameter value
    """

def dskstl(keywrd: str, dpval: float) -> None:
    """
    Set DSK tolerance or margin parameter.
    
    Parameters:
    - keywrd: str, parameter keyword
    - dpval: float, parameter value
    
    Returns:
    None
    """

Common Usage Patterns

Ray-Surface Intersection

import spiceypy as spice
import numpy as np

# Load DSK file
spice.furnsh("asteroid_shape.bsp")

# Define ray from spacecraft to surface
spacecraft_pos = np.array([100.0, 0.0, 0.0])  # km
look_direction = np.array([-1.0, 0.0, 0.0])   # toward surface

# Find intersection with asteroid surface
target = "ASTEROID"
et = spice.str2et("2023-01-01T12:00:00")
frame = "ASTEROID_FIXED"

intercept, found = spice.dskxv(
    True,         # prioritize closer surfaces
    target,       # target body
    0,            # use all surfaces
    [],           # surface list (empty = all)
    et,           # time
    frame,        # reference frame  
    spacecraft_pos,  # ray vertex
    look_direction   # ray direction
)

if found:
    print(f"Surface intercept at: {intercept} km")
    
    # Get extended intersection information
    point, handle, dladsc, dscdsc, dc, found = spice.dskxsi(
        True, target, 0, [], et, frame, spacecraft_pos, look_direction
    )
    
    if found:
        # Get surface normal at intercept
        plate_id = int(dc)  # plate ID from intersection
        normal = spice.dskn02(handle, dladsc, plate_id)
        print(f"Surface normal: {normal}")

Creating DSK File from Shape Model

import numpy as np

# Open new DSK file
handle = spice.dskopn("asteroid_model.bsp", "Asteroid Shape Model", 0)

# Define shape model parameters
center = 1000023  # asteroid ID
surface_id = 1
data_class = 1
frame = "ASTEROID_FIXED"
coord_sys = 1  # rectangular coordinates
coord_params = np.zeros(10)

# Time bounds (entire mission)
first_time = spice.str2et("2020-01-01")
last_time = spice.str2et("2025-12-31")

# Coordinate bounds (computed from shape model)
min_x, max_x = -50.0, 50.0
min_y, max_y = -30.0, 30.0  
min_z, max_z = -25.0, 25.0

# Begin Type 2 DSK segment
spice.dskb02(
    handle, center, surface_id, data_class, frame,
    coord_sys, coord_params,
    min_x, max_x, min_y, max_y, min_z, max_z,
    first_time, last_time
)

# Add plate model data (vertices and triangular plates)
# vertices: N x 3 array of vertex coordinates
# plates: M x 3 array of vertex indices for each triangular plate
# spatial_index_double, spatial_index_int: acceleration structures

spice.dskw02(
    handle, center, surface_id, data_class, frame,
    coord_sys, coord_params,
    min_x, max_x, min_y, max_y, min_z, max_z,
    first_time, last_time,
    len(vertices), vertices,
    len(plates), plates,
    spatial_index_double, spatial_index_int
)

# Close DSK file
spice.dskcls(handle)

Querying DSK File Contents

# Get all objects in DSK file
dsk_file = "asteroid_model.bsp"
body_ids = spice.dskobj(dsk_file)
print(f"Bodies in DSK: {body_ids}")

# Get surfaces for each body
for body_id in body_ids:
    surface_ids = spice.dsksrf(dsk_file, body_id)
    print(f"Body {body_id} surfaces: {surface_ids}")
    
    # Get DSK descriptor for each surface
    for surface_id in surface_ids:
        dsk_desc = spice.dskgd(dsk_file, body_id, surface_id)
        print(f"Surface {surface_id} descriptor: {dsk_desc}")

Install with Tessl CLI

npx tessl i tessl/pypi-spiceypy

docs

ck-orientation.md

coordinate-systems.md

data-structures.md

dsk-shape-models.md

e-kernels.md

ephemeris-trajectories.md

error-handling.md

event-finding.md

geometry-surface.md

index.md

kernel-management.md

low-level-file-access.md

physical-constants.md

reference-frames.md

spacecraft-clock.md

time-systems.md

vector-matrix.md

tile.json