diff --git a/include/usgscsm/UsgsAstroFrameSensorModel.h b/include/usgscsm/UsgsAstroFrameSensorModel.h
index 087206e367dd6cb00f6c51ba1b1b8bc0c18b19c4..fb9052a1531b7eaef9c61819f0587944b3f88121 100644
--- a/include/usgscsm/UsgsAstroFrameSensorModel.h
+++ b/include/usgscsm/UsgsAstroFrameSensorModel.h
@@ -5,7 +5,7 @@
 #include <cmath>
 #include <iostream>
 #include <vector>
-
+#include <gtest/gtest.h>
 #include "RasterGM.h"
 #include "CorrelationModel.h"
 
@@ -298,8 +298,11 @@ class UsgsAstroFrameSensorModel : public csm::RasterGM {
 
     static const std::string _SENSOR_MODEL_NAME;
 
-
-  protected:
+protected:
+    FRIEND_TEST(FrameIsdTest, setFocalPlane1);
+    FRIEND_TEST(FrameIsdTest, Jacobian1);
+    FRIEND_TEST(FrameIsdTest, setFocalPlane_AllCoefficientsOne);
+    FRIEND_TEST(FrameIsdTest, distortMe_AllCoefficientsOne);
 
     virtual bool setFocalPlane(double dx,double dy,double &undistortedX,double &undistortedY) const;
     virtual void distortionFunction(double ux, double uy, double &dx, double &dy) const;
@@ -307,6 +310,7 @@ class UsgsAstroFrameSensorModel : public csm::RasterGM {
                                     double &Jxy, double &Jyx, double &Jyy) const;
 
 
+
   private:
 
     // Input parameters
diff --git a/jupyter_notebooks/UsgsAstroFrameSensorModelTesting.ipynb b/jupyter_notebooks/UsgsAstroFrameSensorModelTesting.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1a87cb486359a878c70ee9ceb1cdd77c4c32ff7f
--- /dev/null
+++ b/jupyter_notebooks/UsgsAstroFrameSensorModelTesting.ipynb
@@ -0,0 +1,693 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true
+   },
+   "source": [
+    "# Image to ground\n",
+    "\n",
+    "## by Kaj Williams and Jesse Mapel\n",
+    "## Notes: includes rotation."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 284,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy as np\n",
+    "from __future__ import print_function, division"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 285,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "Samples = 7.5\n",
+    "Lines = 7.5\n",
+    "\n",
+    "# optical center (pixels) in x,y direction\n",
+    "Cx=7.5  \n",
+    "Cy=7.5  \n",
+    "\n",
+    "# focal length (m)\n",
+    "F=50.0e-3 \n",
+    "\n",
+    "# size of pixels in world units (m)\n",
+    "Px=1.0e-4 \n",
+    "Py=1.0e-4\n",
+    "\n",
+    "# observer position:\n",
+    "obs_x=1000.0\n",
+    "obs_y=0.0\n",
+    "obs_z=0.0\n",
+    "\n",
+    "# radius of body (m):\n",
+    "major_radius=10.0\n",
+    "minor_radius=10.0\n",
+    "\n",
+    "#Rotation:\n",
+    "omega=0\n",
+    "phi=-np.pi/2.\n",
+    "kappa=np.pi"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Calculation of camera look vector:\n",
+    "$\\begin{bmatrix}\\mathbf{x} & \\mathbf{y} & \\mathbf{z} \\end{bmatrix}= \n",
+    "\\begin{bmatrix}\\mathbf{Samples} & \\mathbf{Lines} & \\mathbf{1} \\end{bmatrix}\n",
+    "\\begin{bmatrix}\n",
+    "\\mathbf{P_y} & \\mathbf{0} & \\mathbf{0}\\\\\n",
+    "\\mathbf{0} & \\mathbf{P_x} & \\mathbf{0}\\\\\n",
+    "\\mathbf{-C_y P_y} & \\mathbf{-C_x P_x} & \\mathbf{F} \n",
+    "\\end{bmatrix}\n",
+    "\\begin{bmatrix}\n",
+    "\\mathbf{sin(\\phi)} & \\mathbf{-sin(\\omega)cos(\\phi)} & \\mathbf{cos(\\omega)cos(\\phi)}\\\\\n",
+    "\\mathbf{-cos(\\phi)sin(\\kappa)} & \\mathbf{cos(\\omega)cos(\\kappa)-sin(\\omega)sin(\\phi)sin(\\kappa)} & \\mathbf{cos(\\omega)cos(\\kappa)+sin(\\omega)sin(\\phi)sin(\\kappa)}\\\\\n",
+    "\\mathbf{cos(\\phi)cos(\\omega)} & \\mathbf{cos(\\omega)sin(\\kappa)+sin(\\omega)sin(\\phi)cos(\\kappa)} & \\mathbf{cos(\\omega)sin(\\kappa)-sin(\\omega)sin(\\phi)cos(\\kappa)} \n",
+    "\\end{bmatrix}\n",
+    "$"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 286,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "image_vector = np.array([Samples, Lines, 1], dtype=float)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 287,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "camera_array = np.array([[Py, 0, 0],[0, Px,0],[-Cy*Py,-Cx*Px,F]], dtype=float)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 288,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#Compute the camera look vector and normalize it:\n",
+    "camera_look_vector = np.matmul(np.transpose(image_vector),camera_array)\n",
+    "camera_look_vector=camera_look_vector/np.linalg.norm(camera_look_vector,2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 289,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "rotation_matrix=np.ndarray(shape=(3,3), dtype=float, order='F')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 290,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "rotation_matrix[0,0]=np.cos(phi)*np.cos(kappa)\n",
+    "rotation_matrix[1,0]=np.cos(omega)*np.sin(kappa)+np.sin(omega)*np.sin(phi)*np.cos(kappa)\n",
+    "rotation_matrix[2,0]=np.sin(omega)*np.sin(kappa)-np.cos(omega)*np.sin(phi)*np.cos(kappa)\n",
+    "rotation_matrix[0,1]=-np.cos(phi)*np.sin(kappa)\n",
+    "rotation_matrix[1,1]=np.cos(omega)*np.cos(kappa)-np.sin(omega)*np.sin(phi)*np.sin(kappa)\n",
+    "rotation_matrix[2,1]=np.sin(omega)*np.cos(kappa)+np.cos(omega)*np.sin(phi)*np.sin(kappa)\n",
+    "rotation_matrix[0,2]=np.sin(phi)\n",
+    "rotation_matrix[1,2]=-np.sin(omega)*np.cos(phi)\n",
+    "rotation_matrix[2,2]=np.cos(omega)*np.cos(phi)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 291,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[[-6.12323400e-17 -7.49879891e-33 -1.00000000e+00]\n",
+      " [ 1.22464680e-16 -1.00000000e+00 -0.00000000e+00]\n",
+      " [-1.00000000e+00 -1.22464680e-16  6.12323400e-17]]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(rotation_matrix)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 292,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "look_vector=np.matmul(np.transpose(camera_look_vector),rotation_matrix)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 293,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "After accounting for rotation,  look vector x,y,z:  [-1.0000000e+00 -1.2246468e-16  6.1232340e-17]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(\"After accounting for rotation,  look vector x,y,z: \",look_vector)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 294,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "a:1.0 b:-2000.0 c:999900.0 radius_squared_ratio:1.0\n"
+     ]
+    }
+   ],
+   "source": [
+    "radius_squared_ratio =major_radius**2/minor_radius**2\n",
+    "a=look_vector[0]**2 + look_vector[1]**2 + radius_squared_ratio*look_vector[2]**2\n",
+    "b=2*(look_vector[0]*obs_x+look_vector[1]*obs_y+radius_squared_ratio*look_vector[2]*obs_z)\n",
+    "c=obs_x**2+obs_y**2+radius_squared_ratio*obs_z**2-major_radius**2\n",
+    "discriminant=b**2-4.0*a*c\n",
+    "print('a:{} b:{} c:{} radius_squared_ratio:{}'.format(a,b,c,radius_squared_ratio))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 295,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "400.0"
+      ]
+     },
+     "execution_count": 295,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "if discriminant<0 :\n",
+    "    discriminant=0 # closest intersection\n",
+    "discriminant"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 296,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "990.0"
+      ]
+     },
+     "execution_count": 296,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "distance=(-b-np.sqrt(discriminant))/(2*a)\n",
+    "distance"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 297,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "obs_vector=np.array([obs_x, obs_y, obs_z])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 298,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "ground_point = obs_vector+distance*look_vector"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 299,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Planet coords. x,y,z:  [ 1.00000000e+01 -1.21240033e-13  6.06200166e-14]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(\"Planet coords. x,y,z: \",ground_point)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true
+   },
+   "source": [
+    "# Ground to Image\n",
+    "### Notes: very basic implementation."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 300,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Look vector:\n",
+    "x=0\n",
+    "y=0\n",
+    "z=-1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "$\\begin{bmatrix}\\mathbf{Samples} & \\mathbf{Lines} & \\mathbf{1} \\end{bmatrix}=\n",
+    "\\begin{bmatrix}\\mathbf{x} & \\mathbf{y} & \\mathbf{z}& \\mathbf{1} \\end{bmatrix} \n",
+    "\\begin{bmatrix}\n",
+    "\\mathbf{0} & \\mathbf{1/P_x} & \\mathbf{0}\\\\\n",
+    "\\mathbf{1/P_y} & \\mathbf{0} & \\mathbf{0}\\\\\n",
+    "\\mathbf{0} & \\mathbf{0} & \\mathbf{0}\\\\\n",
+    "\\mathbf{C_y} & \\mathbf{C_x} & \\mathbf{1} \n",
+    "\\end{bmatrix}\n",
+    "$"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 301,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "ground_vector=np.array([x, y, z,1], dtype=float)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 302,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "camera_array = np.array([[0, 1/Px, 0],[1/Py, 0,0],[0,0,0],[Cy,Cx,1]], dtype=float)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 303,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "Image_coords = np.matmul(np.transpose(ground_vector),camera_array)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 304,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Image coords. x,y,z:  [7.5 7.5 1. ]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(\"Image coords. x,y,z: \",Image_coords)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true
+   },
+   "source": [
+    "# Radial Distortion Model\n",
+    "\n",
+    "### The following code is for the Brown-Conrady model, implemented as the \"division model\" approach:\n",
+    "### https://en.wikipedia.org/wiki/Distortion_(optics)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 305,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#Radial distortion coefficients:\n",
+    "# if K1>0 then pincushion distortion.\n",
+    "# If K1<0 then barrel distortion.\n",
+    "K1=0.1\n",
+    "K2=0.0\n",
+    "\n",
+    "# Distortion center x,y:\n",
+    "Xc=7.5\n",
+    "Yc=7.5\n",
+    "\n",
+    "# Distorted coords x,y:\n",
+    "Xd=8.0\n",
+    "Yd=8.0\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 306,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#helper expression for r^2:\n",
+    "r2=(Xd-Xc)*(Xd-Xc)+(Yd-Yc)*(Yd-Yc)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "$X_u=X_c+\\frac{(X_d-X_c)}{(1+K_1 r^2+K_2 r^4)}$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "$Y_u=Y_c+\\frac{(Y_d-Y_c)}{(1+K_1 r^2+K_2 r^4)}$"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 307,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "X_undistorted = Xc+(Xd-Xc)/(1+K1*r2+K2*r2*r2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 308,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "Y_undistorted = Yc+(Yd-Yc)/(1+K1*r2+K2*r2*r2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 309,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Undistorted X,Y:  7.976190476190476 7.976190476190476\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(\"Undistorted X,Y: \",X_undistorted,Y_undistorted)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true
+   },
+   "source": [
+    "# Radial Distortion Model - MDIS NAC\n",
+    "### The following code is from the ik kernel for the MDIS NAC instrument.  The NAC distortion\n",
+    "### was determined by fitting data from a simulation of the NAC's optical behavior to a 3rd order\n",
+    "### Taylor series expansion.\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 310,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "odtx=[1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0]\n",
+    "odty=[0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0]\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### [dx,dy]=distortMe(ux,uy):\n",
+    "### Takes in undistorted focal plane coordinates and returns distorted coordinates [dx,dy]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 311,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def distortMe(ux,uy,dtx,dty):\n",
+    "    \n",
+    "    f=[1,ux,uy,ux**2,ux*uy,uy**2,ux**3,uy*ux**2,ux*uy**2,uy**3]\n",
+    "    dx=0.0\n",
+    "    dy=0.0\n",
+    "    for i in range(len(f)):\n",
+    "        dx = dx+f[i]*dtx[i]\n",
+    "        dy = dy+f[i]*dty[i]    \n",
+    "    return [dx,dy]\n",
+    "        \n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### [ux,uy]=undistortMe(dx,dy):\n",
+    "### Computes undistored focal plane (ux,uy) coordinates given distorted focal plane \n",
+    "### coordinates using the Newton-Raphson Method for root finding a system of equations:\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "$$f_1(x_1,x_2,\\cdots,x_n) = f_1(\\textbf{x}) = \\textbf{0}$$\n",
+    "$$f_2(x_1,x_2,\\cdots,x_n) = f_2(\\textbf{x}) = \\textbf{0}$$\n",
+    "$$\\vdots$$\n",
+    "$$f_n(x_1,x_2,\\cdots,x_n) = f_n(\\textbf{x}) = \\textbf{0}$$\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### To solve consider Taylor series expansion of f about x to first order:\n",
+    "\n",
+    "$$f(\\textbf{x} +\\delta \\textbf{x} ) = f_i(\\textbf{x}) + \\sum_{j=0}^n\\frac{\\partial f_i}{\\partial x_j}\\delta x_j +O(\\delta x ^2),i = 1,\\cdots,n$$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Ignore the $O(\\delta x^2)$ terms and let $f(x+\\delta x) = 0 $ (ie, $x+\\delta x$ is the root we are seeking).  Then:\n",
+    "### $$-f_i(\\textbf{x}) = \\sum_{j=0}^n\\frac{\\partial f_i}{\\partial x_j}\\delta x_j, j=0,\\cdots ,n$$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Therefore:  $\\delta x_j = -f(\\textbf{x})J_f^{-1}(\\textbf(x)$ ($J$ = the Jacobian of $f$)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### And finally:\n",
+    "$$ \\textbf{x} \\Leftarrow \\textbf{x}+ \\delta(\\textbf{x}) = \\textbf{x} - J_f^{-1}(\\textbf{x})f(\\textbf{x})$$"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### In code:\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 312,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def Jacobian(x,y,odtx,odty):\n",
+    "    d_dx=[0.0,1.0,0.0,2*x,y,0.0,3*x*x,2*x*y,y*y,0.0]\n",
+    "    d_dy=[0.0,0.0,1.0,0.0,x,2*y,0.0,x**2,2*x*y,3*y**2]\n",
+    "    \n",
+    "    Jxx=0.0;\n",
+    "    Jxy = 0.0;\n",
+    "    Jyx= 0.0;\n",
+    "    Jyy = 0.0;\n",
+    "    \n",
+    "    for i in range(len(d_dx)):\n",
+    "        Jxx = Jxx+d_dx[i]*odtx[i]\n",
+    "        Jxy = Jxy+d_dy[i]*odtx[i]\n",
+    "        Jyx = Jyx + d_dx[i]*odty[i]\n",
+    "        Jyy = Jyy + d_dy[i]*odty[i] \n",
+    "    \n",
+    "    return [Jxx,Jxy,Jyx,Jyy]\n",
+    "\n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 313,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def undistortMe(dx,dy,odtx,odty):\n",
+    "    epsilon =1.4e-5\n",
+    "    maxIts = 60\n",
+    "    #initial guess\n",
+    "    x = dx\n",
+    "    y = dy\n",
+    "    [fx,fy]= distortMe(x,y,odtx,odty)\n",
+    "    for i in range(maxIts):\n",
+    "        print(i)\n",
+    "        [fx,fy]=distortMe(x,y,odtx,odty)\n",
+    "        fx=dx-fx\n",
+    "        fy = dy-fy\n",
+    "        J = Jacobian(x,y,odtx,odty)\n",
+    "        determinant = J[0]*J[3]-J[1]*J[2]\n",
+    "       \n",
+    "        if (abs(determinant) < 1e-7):\n",
+    "            print(\"Jacobian is singular.\")\n",
+    "            print(determinant)\n",
+    "            break;\n",
+    "        else:\n",
+    "            x = x+(J[3]*fx-J[1]*fy)/determinant\n",
+    "            y = y+(J[0]*fy-J[2]*fx)/determinant\n",
+    "        if (abs(fx)+abs(fy) <= epsilon):\n",
+    "            return [x,y]\n",
+    "    return [dx,dy]    \n",
+    "    \n",
+    "    \n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 314,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "0\n",
+      "1\n",
+      "2\n",
+      "3\n",
+      "4\n",
+      "5\n",
+      "6\n",
+      "7\n",
+      "8\n",
+      "9\n",
+      "10\n",
+      "11\n",
+      "12\n",
+      "13\n",
+      "14\n",
+      "15\n",
+      "16\n",
+      "[908.5, 963.75]\n",
+      "[7.499999999999999, 7.5]\n"
+     ]
+    }
+   ],
+   "source": [
+    "distortion = distortMe(7.5,7.5,odtx,odty)\n",
+    "undistorted = undistortMe(distortion[0],distortion[1],odtx,odty)\n",
+    "\n",
+    "print(distortion)\n",
+    "print (undistorted)"
+   ]
+  }
+ ],
+ "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.6.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/src/UsgsAstroFrameSensorModel.cpp b/src/UsgsAstroFrameSensorModel.cpp
index 6116a18dbb58bb9e28483c43bba7dfa2228210da..8ff40263616876531ca645665b3ce607265d1e6c 100644
--- a/src/UsgsAstroFrameSensorModel.cpp
+++ b/src/UsgsAstroFrameSensorModel.cpp
@@ -1076,7 +1076,7 @@ bool UsgsAstroFrameSensorModel::setFocalPlane(double dx,double dy,
     distortionJacobian(x, y, Jxx, Jxy, Jyx, Jyy);
 
     double determinant = Jxx * Jyy - Jxy * Jyx;
-    if (determinant < 1E-6) {
+    if (fabs(determinant) < 1E-6) {
       //
       // Near-zero determinant. Add error handling here.
       //
diff --git a/tests/FrameCameraTests.cpp b/tests/FrameCameraTests.cpp
index 0d23f2878f0c8f4121373e3de65e65a006f0e2b8..cdf235d77330c548c97c16193532c8d6d3431e1b 100644
--- a/tests/FrameCameraTests.cpp
+++ b/tests/FrameCameraTests.cpp
@@ -2,12 +2,15 @@
 #include "UsgsAstroFrameSensorModel.h"
 
 #include <json.hpp>
-
+#include <iostream>
+#include <iomanip>
 #include <sstream>
 #include <fstream>
-
+#include <map>
+#include <vector>
 #include <gtest/gtest.h>
 
+using namespace std;
 using json = nlohmann::json;
 
 class FrameIsdTest : public ::testing::Test {
@@ -15,6 +18,16 @@ class FrameIsdTest : public ::testing::Test {
 
       csm::Isd isd;
 
+      void printIsd(csm::Isd &localIsd) {
+           multimap<string,string> isdmap= localIsd.parameters();
+           for (auto it = isdmap.begin(); it != isdmap.end();++it){
+
+                      cout << it->first << " : " << it->second << endl;
+           }
+
+
+    }
+
    virtual void SetUp() {
       std::ifstream isdFile("data/simpleFramerISD.json");
       json jsonIsd = json::parse(isdFile);
@@ -36,8 +49,12 @@ class FrameIsdTest : public ::testing::Test {
 class FrameSensorModel : public ::testing::Test {
    protected:
 
+
+      protected :
       UsgsAstroFrameSensorModel *sensorModel;
-      
+
+
+
       void SetUp() override {
          sensorModel = NULL;
          std::ifstream isdFile("data/simpleFramerISD.json");
@@ -46,24 +63,25 @@ class FrameSensorModel : public ::testing::Test {
          for (json::iterator it = jsonIsd.begin(); it != jsonIsd.end(); ++it) {
             json jsonValue = it.value();
             if (jsonValue.size() > 1) {
-               for (int i = 0; i < jsonValue.size(); i++) {
-                  isd.addParam(it.key(), jsonValue[i].dump());
+              for (int i = 0; i < jsonValue.size(); i++){
+                    isd.addParam(it.key(), jsonValue[i].dump());
                }
             }
             else {
                isd.addParam(it.key(), jsonValue.dump());
             }
          }
+
          isdFile.close();
 
          UsgsAstroFramePlugin frameCameraPlugin;
-         
+
          csm::Model *model = frameCameraPlugin.constructModelFromISD(
                isd,
                "USGS_ASTRO_FRAME_SENSOR_MODEL");
-         
+
          sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-         
+
          ASSERT_NE(sensorModel, nullptr);
       }
 
@@ -72,6 +90,7 @@ class FrameSensorModel : public ::testing::Test {
             delete sensorModel;
             sensorModel = NULL;
          }
+
       }
 };
 
@@ -124,6 +143,187 @@ TEST_F(FrameSensorModel, OffBody4) {
 }
 
 
+
+TEST_F(FrameIsdTest, setFocalPlane1) {
+  int precision  = 20;
+  UsgsAstroFramePlugin frameCameraPlugin;
+  std:string odtx_key= "odt_x";
+  std::string odty_key="odt_y";
+
+  isd.clearParams(odty_key);
+  isd.clearParams(odtx_key);
+
+  csm::ImageCoord imagePt(7.5, 7.5);
+  double ux,uy;
+
+  vector<double> odtx{0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
+  vector<double> odty{0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
+
+
+   for (auto & val: odtx){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_x", strval.str());
+   }
+   for (auto & val: odty){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_y", strval.str());
+   }
+
+   csm::Model *model = frameCameraPlugin.constructModelFromISD(
+         isd,
+         "USGS_ASTRO_FRAME_SENSOR_MODEL");
+
+
+
+   UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
+
+   sensorModel->setFocalPlane(imagePt.samp, imagePt.line, ux, uy);
+   EXPECT_NEAR(imagePt.samp,7.5,1e-8 );
+   EXPECT_NEAR(imagePt.line,7.5,1e-8);
+
+}
+
+
+
+TEST_F(FrameIsdTest, Jacobian1) {
+
+  int precision  = 20;
+  UsgsAstroFramePlugin frameCameraPlugin;
+  std:string odtx_key= "odt_x";
+  std::string odty_key="odt_y";
+
+  isd.clearParams(odty_key);
+  isd.clearParams(odtx_key);
+
+   csm::ImageCoord imagePt(7.5, 7.5);
+
+   vector<double> odtx{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0};
+   vector<double> odty{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.0};
+
+   for (auto & val: odtx){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_x", strval.str());
+   }
+   for (auto & val: odty){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_y", strval.str());
+   }
+
+   csm::Model *model = frameCameraPlugin.constructModelFromISD(
+         isd,
+         "USGS_ASTRO_FRAME_SENSOR_MODEL");
+
+   UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
+
+
+   double Jxx,Jxy,Jyx,Jyy;
+   sensorModel->distortionJacobian(imagePt.samp, imagePt.line, Jxx, Jxy,Jyx,Jyy);
+
+
+
+   EXPECT_NEAR(Jxx,56.25,1e-8 );
+   EXPECT_NEAR(Jxy,112.5,1e-8);
+   EXPECT_NEAR(Jyx,56.25,1e-8);
+   EXPECT_NEAR(Jyy,281.25,1e-8);
+
+}
+
+
+TEST_F(FrameIsdTest, distortMe_AllCoefficientsOne) {
+
+  int precision  = 20;
+  UsgsAstroFramePlugin frameCameraPlugin;
+  std:string odtx_key= "odt_x";
+  std::string odty_key="odt_y";
+
+  isd.clearParams(odty_key);
+  isd.clearParams(odtx_key);
+
+   csm::ImageCoord imagePt(7.5, 7.5);
+
+   vector<double> odtx{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
+   vector<double> odty{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
+
+   for (auto & val: odtx){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_x", strval.str());
+   }
+   for (auto & val: odty){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_y", strval.str());
+   }
+
+   csm::Model *model = frameCameraPlugin.constructModelFromISD(
+         isd,
+         "USGS_ASTRO_FRAME_SENSOR_MODEL");
+
+   UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
+
+
+   printIsd(isd);
+   double dx,dy;
+   sensorModel->distortionFunction(imagePt.samp, imagePt.line,dx,dy );
+
+   cout << "dx:  " << dx << endl;
+   cout << "dy:  " << dy << endl;
+
+   EXPECT_NEAR(dx,1872.25,1e-8 );
+   EXPECT_NEAR(dy,1872.25,1e-8);
+
+}
+
+TEST_F(FrameIsdTest, setFocalPlane_AllCoefficientsOne) {
+
+  int precision  = 20;
+  UsgsAstroFramePlugin frameCameraPlugin;
+  std:string odtx_key= "odt_x";
+  std::string odty_key="odt_y";
+
+  isd.clearParams(odty_key);
+  isd.clearParams(odtx_key);
+
+   csm::ImageCoord imagePt(1872.25, 1872.25);
+
+   vector<double> odtx{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
+   vector<double> odty{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
+
+   for (auto & val: odtx){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_x", strval.str());
+   }
+   for (auto & val: odty){
+      ostringstream strval;
+      strval << setprecision(precision) << val;
+      isd.addParam("odt_y", strval.str());
+   }
+
+   csm::Model *model = frameCameraPlugin.constructModelFromISD(
+         isd,
+         "USGS_ASTRO_FRAME_SENSOR_MODEL");
+
+   UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
+
+
+   double ux,uy;
+   sensorModel->setFocalPlane(imagePt.samp, imagePt.line,ux,uy );
+
+
+   //The Jacobian is singular, so the setFocalPlane should break out of it's iteration and
+   //returns the same distorted coordinates that were passed in.
+   EXPECT_NEAR(ux,imagePt.samp,1e-8 );
+   EXPECT_NEAR(uy,imagePt.line,1e-8);
+
+}
+
+
+
 // Focal Length Tests:
 TEST_F(FrameIsdTest, FL500_OffBody4) {
    std::string key = "focal_length";
@@ -131,13 +331,13 @@ TEST_F(FrameIsdTest, FL500_OffBody4) {
    isd.clearParams(key);
    isd.addParam(key,newValue);
    UsgsAstroFramePlugin frameCameraPlugin;
-         
+
    csm::Model *model = frameCameraPlugin.constructModelFromISD(
          isd,
          "USGS_ASTRO_FRAME_SENSOR_MODEL");
-   
+
    UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-   
+
    ASSERT_NE(sensorModel, nullptr);
    csm::ImageCoord imagePt(15.0, 15.0);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
@@ -151,13 +351,13 @@ TEST_F(FrameIsdTest, FL500_OffBody3) {
    isd.clearParams(key);
    isd.addParam(key,newValue);
    UsgsAstroFramePlugin frameCameraPlugin;
-         
+
    csm::Model *model = frameCameraPlugin.constructModelFromISD(
          isd,
          "USGS_ASTRO_FRAME_SENSOR_MODEL");
-   
+
    UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-   
+
    ASSERT_NE(sensorModel, nullptr);
    csm::ImageCoord imagePt(0.0, 0.0);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
@@ -171,13 +371,13 @@ TEST_F(FrameIsdTest, FL500_Center) {
    isd.clearParams(key);
    isd.addParam(key,newValue);
    UsgsAstroFramePlugin frameCameraPlugin;
-         
+
    csm::Model *model = frameCameraPlugin.constructModelFromISD(
          isd,
          "USGS_ASTRO_FRAME_SENSOR_MODEL");
-   
+
    UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-   
+
    ASSERT_NE(sensorModel, nullptr);
    csm::ImageCoord imagePt(7.5, 7.5);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
@@ -191,20 +391,20 @@ TEST_F(FrameIsdTest, FL500_SlightlyOffCenter) {
    isd.clearParams(key);
    isd.addParam(key,newValue);
    UsgsAstroFramePlugin frameCameraPlugin;
-         
+
    csm::Model *model = frameCameraPlugin.constructModelFromISD(
          isd,
          "USGS_ASTRO_FRAME_SENSOR_MODEL");
-   
+
    UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-   
+
    ASSERT_NE(sensorModel, nullptr);
    csm::ImageCoord imagePt(7.5, 6.5);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
    EXPECT_NEAR(groundPt.x, 9.99803960, 1e-8);
    EXPECT_NEAR(groundPt.y, 0.0, 1e-8);
    EXPECT_NEAR(groundPt.z, 1.98000392e-01, 1e-8);
-   
+
 }
 
 //Observer x position:
@@ -214,20 +414,20 @@ TEST_F(FrameIsdTest, X10_SlightlyOffCenter) {
    isd.clearParams(key);
    isd.addParam(key,newValue);
    UsgsAstroFramePlugin frameCameraPlugin;
-         
+
    csm::Model *model = frameCameraPlugin.constructModelFromISD(
          isd,
          "USGS_ASTRO_FRAME_SENSOR_MODEL");
-   
+
    UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-   
+
    ASSERT_NE(sensorModel, nullptr);
    csm::ImageCoord imagePt(7.5, 6.5);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
    EXPECT_NEAR(groundPt.x, 10.0, 1e-8);
    EXPECT_NEAR(groundPt.y, 0.0, 1e-8);
    EXPECT_NEAR(groundPt.z, 0.0, 1e-8);
-   
+
 }
 TEST_F(FrameIsdTest, X1e9_SlightlyOffCenter) {
    std::string key = "x_sensor_origin";
@@ -235,13 +435,13 @@ TEST_F(FrameIsdTest, X1e9_SlightlyOffCenter) {
    isd.clearParams(key);
    isd.addParam(key,newValue);
    UsgsAstroFramePlugin frameCameraPlugin;
-         
+
    csm::Model *model = frameCameraPlugin.constructModelFromISD(
          isd,
          "USGS_ASTRO_FRAME_SENSOR_MODEL");
-   
+
    UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model);
-   
+
    ASSERT_NE(sensorModel, nullptr);
    csm::ImageCoord imagePt(7.5, 6.5);
    csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
diff --git a/tests/data/simpleFramerISD.json b/tests/data/simpleFramerISD.json
index e44f64797b293025dff5828e7bcc11f578d323c0..f1c3733b925fb0c0ec20b82362c3a5e3835aa3b9 100644
--- a/tests/data/simpleFramerISD.json
+++ b/tests/data/simpleFramerISD.json
@@ -47,17 +47,7 @@
     "phi": -1.5707963267948966,
     "kappa": 3.141592653589793,
     "semi_major_axis":0.01,
-    "semi_minor_axis":0.01,
-    "transx": [
-        0.0,
-        0.1,
-        0.0
-    ],
-    "transy": [
-        0.0,
-        0.0,
-        0.1
-    ],
+    "semi_minor_axis":0.01, 
     "x_sensor_origin": 1000,
     "y_sensor_origin": 0,
     "z_sensor_origin": 0,