Skip to content

Creating a driver for an ISIS sensor model

Kristin edited this page Apr 6, 2020 · 5 revisions

Pick your sensor model.

Some sensor models cover multiple instruments so watch out for that! For example, the MDIS sensor model in ISIS supports both NAC and WAC images.

Find a cube to use as a test image.

You will want a spiceinit’d and unspiceinit’d version of the cube. Go to PILOT and find an image. Test cubes are also in $ISISDATA/mission_name/testData/. For example, /usgs/cpkgs/isis3/isis_data/messenger/testData/EW0031509051D.cub is a spiceinit’d MDIS WAC cube

Extract kernels from the spiceinit’d cube and convert them to transfer format.

You can use the kernel slicing notebook to do this.

Extract the information we need from the spiceinit’d cube.

We need the following:

  1. InstrumentPointing Table
  2. InstrumentPosition Table
  3. BodyRotation Table
  4. SunPosition Table
  5. NaifKeywords Object

Create a json object to test against.

For example here’s the InstrumentPointing table from EW0031509051D.cub:

Object = Table
  Name                = InstrumentPointing
  StartByte           = 1122377
  Bytes               = 64
  Records             = 1
  ByteOrder           = Lsb
  TimeDependentFrames = (-236890, -236892, -236880, -236000, 1)
  ConstantFrames      = (-236800, -236890)
  ConstantRotation    = (6.32597991633385e-06, -0.9999484094199,
                         0.010157679784231, -6.22745790674593e-04,
                         -0.010157681754072, -0.99994821550371,
                         0.99999980607381, 1.6938907748432e-21,
                         -6.22777920148769e-04)
  CkTableStartTime    = 176293972.98331
  CkTableEndTime      = 176293972.98331
  CkTableOriginalSize = 1
  FrameTypeCode       = 3
  Description         = "Created by spiceinit"
  Kernels             = ($messenger/kernels/ck/msgr_0508_v04.bc,
                         $messenger/kernels/ck/msgr_mdis_sc040812_150430v1.bc,
                         $messenger/kernels/ck/msgr_mdis_sc050727_100302_sub_v-
                         1.bc,
                         $messenger/kernels/ck/msgr_mdis_gm040819_150430v1.bc,
                         $messenger/kernels/fk/msgr_v231.tf)
tabledump from=EW0031509051D.cub name=InstrumentPointing
J2000Q0,J2000Q1,J2000Q2,J2000Q3,AV1,AV2,AV3,ET
0.83916767084107,-0.17917144340698,0.13221815611789,-0.49619912663709,-2.78375051960417e-05,-3.6543121530637e-05,-7.46424524560798e-05,176293972.98331

This should look like the following in the to_isis json output

{‘InstrumentPointing’ :
'TimeDependentFrames' : [-236890, -236892, -236880, -236000, 1],
‘CkTableStartTime’ : 176293972.98331,
‘CkTableEndTime’ : 176293972.98331,
‘CkTableOriginalSize’ : 1,
‘ConstantFrames’ : [-236800, -236890],
‘ConstantRotation’ : [6.32597991633385e-06, -0.9999484094199, 0.010157679784231, -6.22745790674593e-04, -0.010157681754072, -0.99994821550371, 0.99999980607381, 1.6938907748432e-21, -6.22777920148769e-04],
‘EphemerisTimes’ : [176293972.98331],
‘Quaternions’ : [[0.83916767084107,-0.17917144340698,0.13221815611789,-0.49619912663709]],
‘AngularVelocities’ : [[-2.78375051960417e-05,-3.6543121530637e-05,-7.46424524560798e-05]]
}

You do not need to worry about StartByte, Bytes, Records, ByteOrder, FrameTypeCode, Description, or Kernels. The ISIS table code and spiceinit will handle those.

Create a load test

Create a load test using the test data you got from the cube. Create a fixture with your JSON test data and then your actual test should look somewhat like this:

@pytest.mark.parametrize("label_type", ['isis3'])
@pytest.mark.parametrize("formatter", ['isis'])
def test_load(test_kernels, label_type, formatter, isis_compare_dict):
    label_file = get_image_label('st_2385617364_x', label_type)
    isd_str = ale.loads(label_file, props={'kernels': test_kernels}, formatter=formatter)
    isd_obj = json.loads(isd_str)

    assert compare_dicts(isd_obj, isis_compare_dict) == []

If this test fails, you will get an error that no driver exists for the image. So, while creating the driver, it may be useful to directly call the driver and formatter. That looks like this:

@pytest.mark.parametrize("label_type", ['isis3'])
@pytest.mark.parametrize("formatter", ['isis'])
def test_load(test_kernels, label_type, formatter, isis_compare_dict):
    
    class AleJsonEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj, set):
                return list(obj)
            if isinstance(obj, np.integer):
                return int(obj)
            elif isinstance(obj, np.floating):
                return float(obj)
            elif isinstance(obj, np.ndarray):
                return obj.tolist()
            elif isinstance(obj, datetime.date):
                return obj.isoformat()
            return json.JSONEncoder.default(self, obj)

    label_file = get_image_label('st_2385617364_x', label_type)
    with HayabusaAmicaIsisLabelNaifSpiceDriver(label_file, props={'kernels': test_kernels}) as driver:
        isd_str = json.dumps(to_isis(driver), cls=AleJsonEncoder)
    isd_obj = json.loads(isd_str)

    assert compare_dicts(isd_obj, isis_compare_dict) == []

You need to define the encoder class to ensure the JSON dumps call homogenizes all of the data.

Start writing your driver

See Adding New Drivers for how to do this part.