{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Comparing various values from ISIS and USGSCSM cameras for a Messenger MDIS NAC PDS3 image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ale\n",
    "from ale.drivers.messenger_drivers import MessengerMdisPds3NaifSpiceDriver\n",
    "from ale.formatters.usgscsm_formatter import to_usgscsm\n",
    "import json\n",
    "import os\n",
    "from pysis import isis\n",
    "import pvl\n",
    "import numpy as np\n",
    "import knoten\n",
    "import csmapi\n",
    "from knoten import csm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cassini: data/cassini/kernels/mk/\n",
      "dawn: spice/dawn-m_a-spice-6-v1.0/dawnsp_1000/extras/mk\n",
      "kaguya: spice/SELENE/kernels/mk/\n",
      "lro: spice/lro-l-spice-6-v1.0/lrosp_1000/extras/mk/\n",
      "mdis: spice/mess-e_v_h-spice-6-v1.0/messsp_1000/extras/mk\n",
      "mro: spice/mro-m-spice-6-v1.0/mrosp_1000/extras/mk\n",
      "spice_root: spice/\n",
      "\n",
      "MDIS spice directory: spice/mess-e_v_h-spice-6-v1.0/messsp_1000/extras/mk\n"
     ]
    }
   ],
   "source": [
    "# printing config displays the yaml formatted string\n",
    "print(ale.config)\n",
    "\n",
    "# config object is a dictionary so it has the same access patterns \n",
    "print('MDIS spice directory:', ale.config['mdis'])\n",
    "\n",
    "# updating config for new MDIS path in this notebook \n",
    "# Note: this will not change the path in `.ale/config.yml`. This change only lives in the notebook.\n",
    "# ale.config['mdis'] = ''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# change to desired PDS3 image path \n",
    "fileName = 'EN1072174528M.IMG'\n",
    "\n",
    "# metakernels are furnsh-ed when entering the context (with block) with a driver instance\n",
    "# most driver constructors simply accept an image path \n",
    "with MessengerMdisPds3NaifSpiceDriver(fileName) as driver:\n",
    "    # Get rotation from target_frame to j2000\n",
    "    j2000 = driver.frame_chain\n",
    "    target_frame = j2000.find_child_frame(driver.target_frame_id)\n",
    "    rotation = target_frame.rotation_to(j2000)\n",
    "    \n",
    "    # Apply rotation to sensor position and velocity\n",
    "    j2000RotationPos = rotation._rots.apply(driver.sensor_position[0])\n",
    "    j2000RotationVel = rotation._rots.apply(driver.sensor_position[1])\n",
    "\n",
    "    # pass driver instance into formatter function\n",
    "    usgscsmString = to_usgscsm(driver)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load the json encoded string ISD\n",
    "usgscsm_dict = json.loads(usgscsmString)\n",
    "\n",
    "# strip the image file extension and append .json \n",
    "jsonFile = os.path.splitext(fileName)[0] + '.json'\n",
    "\n",
    "# write to disk \n",
    "with open(jsonFile, 'w') as fp:\n",
    "    json.dump(usgscsm_dict, fp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CONSTRUCTED CAMERA\n"
     ]
    }
   ],
   "source": [
    "# Constructs a camera model using usgscsm\n",
    "model=\"USGS_ASTRO_FRAME_SENSOR_MODEL\"  # Make sure this matches your camera model\n",
    "plugin = csmapi.Plugin.getList()[0]\n",
    "isd = csmapi.Isd(fileName)\n",
    "warns = csmapi.WarningList()\n",
    "if plugin.canModelBeConstructedFromISD(isd, model, warns):\n",
    "    print(\"CONSTRUCTED CAMERA\")\n",
    "    camera = plugin.constructModelFromISD(isd, model)\n",
    "else:\n",
    "    print(\"CAN'T CONSTRUCT CAMERA\")\n",
    "    for item in warns:\n",
    "        print(item.getMessage())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Ingest image and spiceinit it\n",
    "cube = os.path.splitext(fileName)[0] + '.cub'\n",
    "isis.mdis2isis(from_=fileName, to=cube)\n",
    "isis.spiceinit(from_=cube, shape='ellipsoid')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Grab campt output on spiceinit'd cube and load it as a pvl\n",
    "output = isis.campt(from_=cube)\n",
    "pvl_output = pvl.loads(output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 124.214954  , -139.13882436,  -79.08708214])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Grab body fixed coordinates from campt pvl output\n",
    "campt_bodyfixed = pvl_output['GroundPoint']['BodyFixedCoordinate']\n",
    "campt_bodyfixed = np.asarray(campt_bodyfixed.value) * 1000\n",
    "\n",
    "# Grab body fixed coordinates from csm\n",
    "ale_bodyfixed = csm.generate_ground_point(0, (256 - .5, 256 - .5), camera)\n",
    "ale_bodyfixed = np.array([ale_bodyfixed.x, ale_bodyfixed.y, ale_bodyfixed.z])\n",
    "\n",
    "# Compare the two body fixed coordinates\n",
    "ale_bodyfixed - campt_bodyfixed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ -66.51548142, -182.55737144,  248.80339983]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Grab sensor position from isd\n",
    "ale_position = usgscsm_dict['sensor_position']['positions']\n",
    "ale_position = np.asarray(ale_position)\n",
    "\n",
    "# Grab spacecraft position from campt pvl output\n",
    "campt_position = pvl_output['GroundPoint']['SpacecraftPosition']\n",
    "campt_position = np.asarray(campt_position.value) * 1000\n",
    "\n",
    "# Compare the two positions\n",
    "ale_position - campt_position"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Grab InstrumentPosition table from the isis cube using tabledump\n",
    "instrument_pos_table = str(isis.tabledump(from_=cube, name='InstrumentPosition'))\n",
    "parsed_string = instrument_pos_table.split(',')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 215.13810917, -126.54603034,  193.27785975]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Grab sensor position from the table dump output\n",
    "isis_j2000_pos = np.asarray([float(parsed_string[6][4:]), float(parsed_string[7]), float(parsed_string[8])]) * 1000\n",
    "\n",
    "# Grab ALE's sensor position\n",
    "ale_j2000_pos = np.asarray(j2000RotationPos)\n",
    "\n",
    "# Compare the two sensor positions that are in the j2000 reference frame\n",
    "ale_j2000_pos - isis_j2000_pos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.00183497, -1.69444679, -0.87865924]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Grab velocities from the table dump output\n",
    "isis_j2000_vel = np.asarray([float(parsed_string[9]), float(parsed_string[10]), float(parsed_string[11])]) * 1000\n",
    "\n",
    "# Grab ALE's velocities\n",
    "ale_j2000_vel = np.asarray(j2000RotationVel)\n",
    "\n",
    "# Compare the two velocity lists that are in the j2000 reference frame\n",
    "ale_j2000_vel - isis_j2000_vel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 3.20945290e-05 -4.88871593e-03 -4.34349143e-03]\n",
      "[ -66.51548142 -182.55737144  248.80339983]\n"
     ]
    }
   ],
   "source": [
    "# Grab spacecraft position and body fixed look vector from csm\n",
    "locus = camera.imageToRemoteImagingLocus(csmapi.ImageCoord(256 - .5, 256 - .5))\n",
    "csm_bodyfixedLV = np.asarray([locus.direction.x, locus.direction.y, locus.direction.z])\n",
    "csm_position = np.asarray([locus.point.x, locus.point.y, locus.point.z])\n",
    "\n",
    "# Grab spacecraft position and body fixed look vector from campt pvl output\n",
    "campt_bodyfixedLV = np.asarray(pvl_output['GroundPoint']['LookDirectionBodyFixed'])\n",
    "campt_position = pvl_output['GroundPoint']['SpacecraftPosition']\n",
    "campt_position = np.asarray(campt_position.value) * 1000\n",
    "\n",
    "# Compute the differences\n",
    "print(csm_bodyfixedLV - campt_bodyfixedLV)\n",
    "print(csm_position - campt_position)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
