Repository: SETI/rms-cspyce (language: python)

Issue:
frmchg is returning transposed result
frmchg is calling the Fortran routine frmchg_ with a 6x6 array, and directly returning the result.  This means the result is transposed and not the correct result.

We need to check all calls directly to Fortran to see if they involve 2-dimensional arrays.


Discussion / hints:

Fix patch:
diff --git a/swig/cspyce0.i b/swig/cspyce0.i
index d4f62382..f15fe180 100644
--- a/swig/cspyce0.i
+++ b/swig/cspyce0.i
@@ -3290,6 +3290,8 @@ extern void frinfo_c(
         SpiceDouble xform[6][6])
     {
         frmchg_(&frame1, &frame2, &et, (SpiceDouble *)xform);
+        // We are calling Fortran, so the resulting matrix needs to be transposed.
+        xpose6_c(xform, xform);
     }
 %}
 
@@ -7236,6 +7238,8 @@ VECTORIZE_dX__3d(recsph, recsph_c)
         SpiceDouble rotate[3][3])
     {
         refchg_(&frame1, &frame2, &et, (SpiceDouble *)rotate);
+        // We are calling Fortran, so the resulting matrix needs to be transposed.
+        xpose_c(rotate, rotate);
     }
 %}
 


Test patch:
diff --git a/unittests/test_kernels.py b/unittests/test_kernels.py
index 518d074a..50a12e18 100644
--- a/unittests/test_kernels.py
+++ b/unittests/test_kernels.py
@@ -429,28 +429,28 @@ def runTest(self):
     self.assertRaises(KeyError, frinfo, INTMAX)
 
     # frmchg, sxform, pxform, xf2rav, pxfrm2, refchg
-    sat0a = frmchg(1, 10016, 0.)
-    sat1a = frmchg(1, 10016, 86400.)
+    sat0a = frmchg(10016, 1, 0.)
+    sat1a = frmchg(10016, 1, 86400.)
     sat0b = sxform('IAU_SATURN', 'J2000', 0.)
     sat1b = sxform('IAU_SATURN', 'J2000', 86400.)
     sat0c = pxform('IAU_SATURN', 'J2000', 0.)
     sat1c = pxform('IAU_SATURN', 'J2000', 86400.)
     sat0d = pxfrm2('IAU_SATURN', 'J2000', 0., 0.)
     sat1d = pxfrm2('IAU_SATURN', 'J2000', 86400., 86400.)
-    sat0e = refchg(1, 10016, 0.)
-    sat1e = refchg(1, 10016, 86400.)
+    sat0e = refchg(10016, 1, 0.)
+    sat1e = refchg(10016, 1, 86400.)
 
     self.assertAllEqual(sat0a[:3,:3], sat0b[:3,:3], 0)
     self.assertAllEqual(sat0a[:3,:3], sat0c, 0)
     self.assertAllEqual(sat0a[:3,:3], sat0d, 0)
     self.assertAllEqual(sat0a[:3,:3], sat0e, 0)
-    self.assertAllEqual(sat0a[:3,:3], sat0a[3:,3:], 0)  # frmchg not rotating
+    self.assertAllEqual(sat0a[:3,:3], sat0a[3:,3:], 0) # true even for rotating frames
 
     self.assertAllEqual(sat1a[:3,:3], sat1b[:3,:3], 0)
     self.assertAllEqual(sat1a[:3,:3], sat1c, 0)
     self.assertAllEqual(sat1a[:3,:3], sat1d, 0)
     self.assertAllEqual(sat1a[:3,:3], sat1e, 0)
-    self.assertAllEqual(sat1a[:3,:3], sat1a[3:,3:], 0)
+    self.assertAllEqual(sat1a[:3,:3], sat1a[3:,3:], 0)  # true even for rotating frames
 
     (mat0a, vec0a) = xf2rav(sat0a)
     (mat1a, vec1a) = xf2rav(sat1a)
@@ -462,16 +462,22 @@ def runTest(self):
     self.assertAllEqual(sat0b[:3,:3], mat0b, 0)
     self.assertAllEqual(sat1b[:3,:3], mat1b, 0)
 
-    self.assertAllEqual(vec0a, 3*[0.], 0.)
-    self.assertAllEqual(vec1a, 3*[0.], 0.)
+    # Make sure that non-rotating frames have the form we're expecting
+    non_rotate = frmchg(1, 2, 0.)   # J2000 and B1950 are both fixed
+    self.assertAllEqual(non_rotate[:3,:3], non_rotate[3:,3:])
+    self.assertFalse(np.any(non_rotate[:3, 3:]))  # top left and bottom right are zero
+    self.assertFalse(np.any(non_rotate[3:, :3]))
+    non_rotate_matrix, non_rotate_vec = xf2rav(non_rotate)
+    self.assertAllEqual(non_rotate[:3, :3], non_rotate_matrix)
+    self.assertAllEqual(non_rotate_vec, [0., 0., 0.])
 
     self.assertAllEqual(vec0b, vec1b, 1.e-13)
 
-    sat01a = frmchg_vector(1, 10016, [0.,86400.])
+    sat01a = frmchg_vector(10016, 1, [0.,86400.])
     sat01b = sxform_vector('IAU_SATURN', 'J2000', [0.,86400.])
     sat01c = pxform_vector('IAU_SATURN', 'J2000', [0.,86400.])
     sat01d = pxfrm2_vector('IAU_SATURN', 'J2000', [0.,86400.], [0.,86400.])
-    sat01e = refchg_vector(1, 10016, [0.,86400.])
+    sat01e = refchg_vector(10016, 1, [0.,86400.])
 
     self.assertAllEqual(sat01a, [sat0a,sat1a], 0)
     self.assertAllEqual(sat01b, [sat0b,sat1b], 0)
diff --git a/unittests/test_p_r.py b/unittests/test_p_r.py
index 560abb87..9c6f475d 100644
--- a/unittests/test_p_r.py
+++ b/unittests/test_p_r.py
@@ -605,13 +605,11 @@ def test_recazl():
     
     
 def test_refchg():
-    frame1 = 1
-    frame2 = 2
-    et = 123456789.0
+    et = 31415926.0
+    frame1 = cs.namfrm("J2000")
+    frame2 = cs.namfrm("B1950")
+    expected = cs.pxform("J2000", "B1950", et)
     calculated = cs.refchg(frame1, frame2, et)
-    expected = [[ 9.99925708e-01, -1.11789381e-02, -4.85900382e-03],
-                [ 1.11789381e-02,  9.99937513e-01, -2.71625947e-05],
-                [ 4.85900384e-03, -2.71579263e-05,  9.99988195e-01]]
     npt.assert_almost_equal(expected, calculated)