Skip to content
U.S. flag

An official website of the United States government

Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

Tutorial: Instantiating a CSM Camera Model from Image

Goals in this tutorial:

  • Generate Image Support Data (ISD) for an image
  • Instantiate a CSM camera model
  • Perform a simple ground to image call

CSM - The Community Sensor Model

For more info on CSM, see Sensor Models.

Also see Sensor Model Software: USGSCSM for the USGS's implementation of CSM in its software.

1. Prerequisites, Install Knoten

The knoten installation may take a little longer than usual due to the many dependencies (including ALE) involved.

conda install -c conda-forge knoten=0.2.1

2. Generate an ISD from a Cube

We will use MRO data located in the data/image_to_ground folder containing a cube and necessary kernels for ISD (Image Support Data) generation.
Note: If your cube already has attached spice data, do you not have to specify kernels in the props param and can pass in an empty dict {} instead.

import ale
import json
import knoten
import os

# Set local data directory and paths
data_dir = '../data/image_to_ground'
cube_file = os.path.join(data_dir, 'B10_013341_1010_XN_79S172W.cub')
isd_file = os.path.join(data_dir, 'isd_file.json')

# Set local kernel paths
props = {
    'kernels': [
        os.path.join(data_dir, 'B10_013341_1010_XN_79S172W_0.bsp'),
        os.path.join(data_dir, 'B10_013341_1010_XN_79S172W_1.bsp'),
        os.path.join(data_dir, 'mro_ctx_v11.ti'),
        os.path.join(data_dir, 'mro_sc_psp_090526_090601_0_sliced_-74000.bc'),
        os.path.join(data_dir, 'mro_sc_psp_090526_090601_1_sliced_-74000.bc'),
        os.path.join(data_dir, 'mro_sclkscet_00082_65536.tsc'),
        os.path.join(data_dir, 'mro_v16.tf'),
        os.path.join(data_dir, 'naif0012.tls'),
        os.path.join(data_dir, 'pck00008.tpc')
    ]
}

# Generate the ISD string from the cube's label
isd_str = ale.loads(
    label=cube_file,
    formatter="ale",
    props=props,
    indent=2,
    verbose=False,
    only_isis_spice=False,
    only_naif_spice=False
)

# Write the ISD string to file 'isd_file.json'
with open(isd_file, "w") as file:
    file.write(isd_str)

3. Create a Community Sensor Model

We will use Knoten's implementation of CSM as the library supports line scanner types of sensor models in the usgscsm library.

sensor_model = knoten.csm.create_csm(isd_file, verbose=False)

4. Convert image coordinates into ground coordinates

# Create an image coordinate at line = 206 and sample = 206
image_coord = knoten.csmapi.ImageCoord(206, 206)

# Convert the image coordinates to ground coordinates with desired precision of 0.0
ground_coord = sensor_model.imageToGround(image_coord, 0.0)

# Output the ground coordinates
ground_coord.x, ground_coord.y, ground_coord.z
(-572485.2147483829, -79884.88742005036, -3326939.6184008163)

5. Convert ground coordinates into image coordinates

# Convert the image coordinates to ground coordinates with desired precision of 0.0
image_coord = sensor_model.groundToImage(ground_coord, 0.0)

# Output the image coordinates
image_coord.line, image_coord.samp
(205.99991086761267, 206.00000010379927)