-
Notifications
You must be signed in to change notification settings - Fork 33
Step By Step ALE Driver Creation
How to write an ALE driver for an instrument that is already implemented in ISIS. For these instructions, bracketted text should be replaced by names specific to your data/instruments.
-
ISIS Prerequisites
- Connect to the ISIS data area. (Internal link, connect to VPN to view)
- Clone and build ISIS locally.
-
Fork and clone the ALE repository.
- Fork the ALE repository
- Clone from your fork (with the recursive flag to clone submodules as well):
git clone --recurse-submodules -j8 [email protected]:[username]/ale.git
-
Setup an ALE environment
- Go to the base directory in your cloned ALE repo
- Create and activate a conda environment:
conda env create ale -f environment.yml conda activate ale
- Set variables and add ISIS binaries to PATH:
export ISISROOT=[myRepoLocation]/ISIS3 export PATH=$PATH:[myRepoLocation]/ISIS3/bin
- Uninstall any preexisting versions of ALE and link in the development version:
pip uninstall ale #run 2 or 3x to make sure python setup.py develop
-
Open/initialize related kernels and/or cubes for reference
- See Data Sources for where to find Kernels and Cubes
- Copy a Cube (and maybe the Kernels as well) to a local data area for testing.
- Ideally, use an uninitialized cub (not a lvl2 or lvl3).
- Level 0 - has spice data attached
- Level 1 - ingested with no processing
- Levels 2 & 3 - projected
- Open up the Cube in a text editor to make sure it is a Cube from the right instrument.
- Ideally, use an uninitialized cub (not a lvl2 or lvl3).
- In the local data area, make 2 copies of the Cube for testing, one with ALE and one with ISIS
[cubename].ale.cub [cubename].isis.cub
- Before you start developing you ale driver, initialise the ISIS Cube with spiceinit.
spiceinit from= [cubename].isis.cub
- ISIS's
spiceinit
uses the first driver that works, first looking for an ALE driver, then using an ISIS driver if all ALE drivers fail. If you need to initialize a cube with an ISIS driver later, temporarily put a line of code in the ALE driver that will cause it to fail.
-
Add a file for your driver
- Go to the
ale/base/drivers
drivers directory - If it doesn't already exist, create a python file with the name of the spacecraft followed by
_drivers
(e.g.hayabusa_drivers.py
) - You may want to copy the structure from another _driver class to start out
- Go to the
-
Write your class
- See Class Signature below to name class and select mixins.
- Add these common functions (and others as needed):
-
instrument_id
- map the sensor name to the spacecraft
- spacecraft name as shown in the NAIF Toolkit Docs
- Look in the Kernel for a more specific ID that might also include the instrument.
-
sensor_model_version
- Should almost always return 1
-
-
Perfect your ALE driver so you can spiceinit a cube with it.
- Run spiceinit on the ALE cube (
spiceinit from= [cubename].ale.cub
) - Look for errors from the ale driver (
[spacecraftname]_driver.py
). This should let you see what methods haven't been covered by mixins. You will need to write these methods yourself in the driver. - Based on the errors you receive, add necessary methods, test, and repeat until spiceinit succeeds with the ale driver and outputs a cube from
source = ale
(and notsource = isis
).- To set your ISIS conda environment to use your local ALE instance:
# Activate your ISIS conda environment $ conda activate isis3 # Check which ALE dependency ISIS is using $ conda list ale # Remove only ALE and not its dependencies $ conda remove --force ale # Install dev build to ISIS's conda dir $ cd <path-to-ale-repo>/ale/build $ rm -rf CMakeCache.txt $ cmake .. -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX/ $ make $ make install $ cd .. $ python setup.py develop # Rebuild ISIS to point to dev build $ cd ../ISIS3/build $ rm -rf CMakeCache.txt $ cmake -DJP2KFLAG=ON -Gninja <path-to-isis-repo>/ISIS3/isis $ ninja -j24 # Verify ALE dependency is dev build $ conda list ale
- To set your ISIS conda environment to use your local ALE instance:
- Run spiceinit on the ALE cube (
-
Compare Ale Cube to ISIS Cube
- Generate Labels for the ISIS and ALE Cubes
catlab from= [cubename].isis.cub to= [cubename]_isis.lbl catlab from= [cubename].ale.cub to= [cubename]_ale.lbl
- Compare ALE Label to the ISIS Label to check the accuracy (using the ISIS label as truth data).
vimdiff [cubename].isis.lbl [cubename].ale.lbl
- TODO: What values are particularly important to compare, and what are their difference tolerances?
- Generate Labels for the ISIS and ALE Cubes
-
Slice the Kernels
The Kernel Slicing notebook uses
ckslicer
,spkmerge
, andtoxfr
from the NAIF Toolkit Utilities. It attempts to extract info from the .cub/kernels to automatically generate the arguments needed to slice the kernels. If the Kernel Slicing notebook fails, you can slice the kernels manually by running the utilities with the appropriate arguments (see the user guides on the NAIF Toolkit Utilities page).- Go to the
notebooks
subdirectory and start ajupyter notebook
- Open the
KernelSlice.ipynb
notebook. - You will likely have to make minor changes to the Kernel Slicer's code, reflecting any unique functions in your driver, especially:
- Accessing the
cube_pvl
data structure for properties named differently in your driver. - The first few lines after the imports, with the locations of:
- Your test Cube
- The
isis_data
directory from the ISIS remote data area - An output directory
-
Note: Requires NAIF program
ckslicer
(MacOS) [internal devs may need to contact IT to install the software on their machine]
- Accessing the
⚠️ After slicing the kernels, remove any absolute paths (especially paths including /Users/yourusername/):- From the kernel slicing Jupyter Notebook and its output
- From the transfer kernels (it is safe to delete the metadata fields that include your absolute paths)
- Go to the
-
Copy Test Data
- In
tests/pytests/data
, make a directory named after your test cube. - See Test Data for what data you will need to copy into here.
- Copy an ISD into
tests/pytests/data/isds
(See Generating ISDs)
- In
-
Test with PyTest
- In
ale/pytests/
make a python file calledtest_[spacecraftname]_drivers.py
- To start out, you may want to look at the structure of another test.
- Make a
kernels
test function and a load test function. - Make a class with a test for each function you added to your driver. They should assert the value that was set in that function.
- if your driver function calls other functions (like scs2e or gdpool), you might want to patch a value in so the return is always the same.
- Run your test, fix mismatched asserts, and fix failing tests.
pytest tests/pytests/test_[spacecraft]_drivers.py
- In
- A combination of Documentation and Metadata
isisDataArea/isis_data/[spacecraftname]/kernels/ik
-
iak
(instead of ik) for addendum kernels
- Cubes contain metadata and an image from a spacecraft.
isisDataArea/isis_testData/isis/src/[spacecraftname]/unitTestData
- If the cube you want is absent, generate it with an ISIS program, documented here.
(look for an[instrument]2isis
program under the appropriate mission.) - Test Data can often be found here:
/isis_testData/isis/src/[spacecraft]/apps/[sensor]2isis/tsts/[varies]/input`
myRepoLocation/ISIS3/isis/src/[spacecraftname]/objs/[sensorname]/[sensorname].cpp
For more info on what a specific label or field might mean, check these sources:
- ISIS Label Dictionary
- NAIF Required Readings for SPICE (You may have to do a bit of digging here.)
- NAIF PDS Toolkit Docs
- Web search
The class signature for your driver should follow this format. See each letter below for guidance on how to name the class/what mixins to use.
# e.g, class HayabusaAmicaIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, RadialDistortion, Driver):
class [A][B][C][D]Driver ([E], [C], [D], [F], Driver):
The name of the spacecraft and/or mission (e.g. Messenger, Hayabusa, Galileo, Odyssey).
The name of the specific sensor on the spacecraft (e.g. AmicaCamera, NarrowAngleCamera, ThemisIr). Often shortened to an acronym or abbreviation (TO DO: When is it shortened and how do I find the short name?).
- Most common: IsisLabel
- PDS3Label is rare
- If dealing with an ISIS converted cube .lbl -> ISIS Label.
- If you haven't done a x_to_isis conversion -> PDS3
- Most common: NaifSpice
- IsisSpice is rare
- If the spice data is already attached, IsisSpice can use the data already attached
Can be found in ISIS Implementation.
Possibly from the instrument Kernel: see if the CENTER is in the middle of the square (framer) or the first line (line scan). Or the kernel documentation may say directly.
- RadialDistortion and then NoDistortion are the most common
- Usually can find in the IK or IAK in isis_data
- Look in Kernel or IAK for ODK, ODTK, Distortion, Optical
- TRANSX and TRANSY are distortion coefficients
lookup_table = {A:B}
- A - look in cube label (
isis_testdata/isis/src/[spacecraft name]/unitTestData
) - B - Google “NAIF SPICE Integer ID” and Ctrl + F the spacecraft name, OR look in the kernel for a more specific ID that might also include the instrument.
Usually just returns 1.
-
In the last cell of the
KernelSlice.ipynb
Jupyter Notebook, is thekernels
command. As the last step of the Kernel Slicing, run this command to generate a list of the necessary Kernels. -
For any Binary Kernels ending in
.bsp
or.bc
, the.xsp
and.xc
, Transfer Kernels generated in the Kernel Slicing output directory should take their place in the ALE test data for your instrument. -
For the rest of the Kernels listed (not ending in
.bsp
or.bc
), copy them into the the ALE test data for your instrument. -
Check if your test data folder is missing kernels (like
fk
andsclk
) and copy those kernels from theisis_data
area into your test data folder. -
Copy/paste the
naif0012.tls
kernel from another ALE test data area. -
Finally, the isis label (that we made with catlab, ending in
_isis.lbl
) is needed as truth data. Copy it into the ALE test data directory
For more info on these kernels and what each is for, see the Intro to Kernels or read more about specific Kernels in the NAIF Toolkit Docs.
ℹ️
Note
The process for generating ISDs may change soon. A Jupyter Notebook is being written to help with this process. If the Jupyter Notebook is complete, please document how to use it here and remove this notice.
To create an ISD (Image Support Data), you will need the output from spiceinitting a Cube.
spiceinit FROM=[cubename].ale.cub > [spacecraft][sensor]_isd.json
If your terminal has a long enough scrollback history, you can simply copy the output from the terminal instead of piping it to a file.
Open this data in a text editor. Keep only the JSON code block following ISD:
from the opening bracket to the corresponding closing bracket, excluding ISD:
at the start and everything before it, and excluding Group = Kernels
and everything after it at the end.
Sample output from spiceinit
// ...
Trying <class 'ale.drivers.hayabusa_drivers.HayabusaAmicaIsisLabelNaifSpiceDriver'>
Success with: <ale.drivers.hayabusa_drivers.HayabusaAmicaIsisLabelNaifSpiceDriver object at 0x169d29ed0>
ISD:
// Exclude everything before this
{
"isis_camera_version": 1,
"image_lines": 401,
"image_samples": 401,
"name_platform": "HAYABUSA",
"name_sensor": "HAYABUSA_AMICA",
"reference_height": {
"maxheight": 1000,
"minheight": -1000,
"unit": "m"
// ...
"velocities": [
[
3.591316801764071,
27.34212273912132,
12.079942252825946
]
],
"reference_frame": 1
}
}
// Exclude everthing after this
Group = Kernels
NaifFrameCode = -130102
LeapSecond = $base/kernels/lsk/naif0012.tls
TargetAttitudeShape = ($base/kernels/pck/pck00009.tpc,
// ...
You should end up with a file named [spacecraft][sensor]_isd.json
that contains the only the JSON data for the isd.