Index: /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/spline.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/spline.c	(revision 34528)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/spline.c	(revision 34529)
@@ -4,4 +4,6 @@
 int spline_create (int argc, char **argv);
 int spline_apply (int argc, char **argv);
+int spline_load (int argc, char **argv);
+int spline_save (int argc, char **argv);
 int spline_delete (int argc, char **argv);
 int spline_getspline (int argc, char **argv);
@@ -11,4 +13,6 @@
   {1, "create",     spline_create,     "create a spline"},
   {1, "apply",      spline_apply,      "apply a spline"},
+  {1, "load",       spline_load,       "write a spline to a FITS file"},
+  {1, "save",       spline_save,       "read a spline from a FITS file"},
   {1, "delete",     spline_delete,     "delete a spline"},
 };
Index: /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/spline_commands.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/spline_commands.c	(revision 34528)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/spline_commands.c	(revision 34529)
@@ -69,4 +69,40 @@
 }
 
+int spline_save (int argc, char **argv) {
+
+  int N;
+
+  int APPEND = FALSE;
+  if ((N = get_argument (argc, argv, "-append"))) {
+    APPEND = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: spline save (name) (filename) [-append]\n");
+    return FALSE;
+  }
+
+  if (!SaveSpline(argv[2], argv[1], APPEND)) {
+    gprint (GP_ERR, "failed to save spline %s\n", argv[1]);
+    return (FALSE);
+  }
+  return TRUE;
+}
+
+int spline_load (int argc, char **argv) {
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: spline load (name) (filename)\n");
+    return FALSE;
+  }
+
+  if (!LoadSpline(argv[2], argv[1])) {
+    gprint (GP_ERR, "failed to load spline %s\n", argv[1]);
+    return (FALSE);
+  }
+  return TRUE;
+}
+
 int spline_delete (int argc, char **argv) {
 
Index: /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/write_vectors.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 34528)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 34529)
@@ -99,5 +99,5 @@
   }
 
-  /* open file for outuput */
+  /* open file for output */
   if (append) {
     f = fopen (argv[1], "a");
Index: /branches/eam_branches/ipp-20120905/Ohana/src/opihi/include/data.h
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/opihi/include/data.h	(revision 34528)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/opihi/include/data.h	(revision 34529)
@@ -190,4 +190,6 @@
 int DeleteSpline (Spline *spline);
 void ListSplines ();
+int SaveSpline (char *filename, char *name, int append);
+int LoadSpline (char *filename, char *name);
 
 /* hermitian functions */
Index: /branches/eam_branches/ipp-20120905/Ohana/src/opihi/lib.data/SplineOps.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/opihi/lib.data/SplineOps.c	(revision 34528)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/opihi/lib.data/SplineOps.c	(revision 34529)
@@ -27,13 +27,21 @@
 void InitSpline (Spline *spline, char *name, int Nknots) {
 
+  if (!spline[0].name) {
     spline[0].name = strcreate (name);
-
-    spline[0].Nknots = Nknots;
+  }
+  spline[0].Nknots = Nknots;
+  
+  if (spline[0].xk) {
+    REALLOCATE (spline[0].xk, opihi_flt, spline[0].Nknots);
+    REALLOCATE (spline[0].yk, opihi_flt, spline[0].Nknots);
+    REALLOCATE (spline[0].y2, opihi_flt, spline[0].Nknots);
+  } else {
     ALLOCATE (spline[0].xk, opihi_flt, spline[0].Nknots);
     ALLOCATE (spline[0].yk, opihi_flt, spline[0].Nknots);
     ALLOCATE (spline[0].y2, opihi_flt, spline[0].Nknots);
-    memset (spline[0].xk, 0, spline[0].Nknots * sizeof(opihi_flt));
-    memset (spline[0].yk, 0, spline[0].Nknots * sizeof(opihi_flt));
-    memset (spline[0].y2, 0, spline[0].Nknots * sizeof(opihi_flt));
+  }
+  memset (spline[0].xk, 0, spline[0].Nknots * sizeof(opihi_flt));
+  memset (spline[0].yk, 0, spline[0].Nknots * sizeof(opihi_flt));
+  memset (spline[0].y2, 0, spline[0].Nknots * sizeof(opihi_flt));
 }
 
@@ -76,5 +84,8 @@
 
   spline = FindSpline (name);
-  if (spline != NULL) return (spline);
+  if (spline != NULL) {
+    InitSpline (spline, name, Nknots);
+    return (spline);
+  }
 
   N = Nsplines;
@@ -82,4 +93,8 @@
   CHECK_REALLOCATE (splines, Spline *, NSPLINES, Nsplines, 16);
   ALLOCATE (spline, Spline, 1);
+  spline->name = NULL;
+  spline->xk = NULL;
+  spline->yk = NULL;
+  spline->y2 = NULL;
   InitSpline (spline, name, Nknots);
   splines[N] = spline;
@@ -126,2 +141,123 @@
   return;
 }
+
+// write the spline data to a FITS file.
+int SaveSpline (char *filename, char *name, int append) {
+  
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+
+  Spline *myspline = FindSpline (name);
+  if (!myspline) {
+    gprint (GP_ERR, "can't find spline for write : %s\n", name);
+    return (FALSE);
+  }
+
+  FILE *f = NULL;
+
+  /* open file for output */
+  if (append) {
+    f = fopen (filename, "a");
+  } else {
+    f = fopen (filename, "w");
+  }
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't open file for write : %s\n", filename);
+    return (FALSE);
+  }
+
+  gfits_create_table_header (&theader, "BINTABLE", name);
+
+  gfits_define_bintable_column (&theader, "D", "X_KNOT", NULL, NULL, 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "D", "Y_KNOT", NULL, NULL, 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "D", "DY2_DX", NULL, NULL, 1.0, 0.0);
+
+  // generate the output array that carries the data
+  gfits_create_table (&theader, &ftable);
+
+  gfits_set_bintable_column_reformat (&theader, &ftable, "X_KNOT", "double", myspline->xk, myspline->Nknots);
+  gfits_set_bintable_column_reformat (&theader, &ftable, "Y_KNOT", "double", myspline->yk, myspline->Nknots);
+  gfits_set_bintable_column_reformat (&theader, &ftable, "DY2_DX", "double", myspline->y2, myspline->Nknots);
+
+  if (!append) {
+    gfits_init_header (&header);
+    header.extend = TRUE;
+
+    gfits_create_header (&header);
+    gfits_create_matrix (&header, &matrix);
+
+    gfits_fwrite_header  (f, &header);
+    gfits_fwrite_matrix  (f, &matrix);
+
+    gfits_free_header (&header);
+    gfits_free_matrix (&matrix);
+  }
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table  (f, &ftable);
+
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
+
+  fclose (f);
+  fflush (f);
+  return (TRUE);
+}
+
+// read the spline data from a FITS file.
+// these functions (LoadSpline, SaveSpline) should probably take spline pointers not names
+int LoadSpline (char *filename, char *name) {
+  
+  int i, Ncol;
+  off_t Nrow;
+  char type[16];
+
+  Header theader;
+  FTable ftable;
+
+  FILE *f = NULL;
+
+  /* open file for input */
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't open file for read : %s\n", filename);
+    return FALSE;
+  }
+
+  ftable.header = &theader;
+
+  // read the full table data into a buffer
+  if (!gfits_fread_ftable (f, &ftable, name)) {
+    fclose (f);
+    gprint (GP_ERR, "can't read FITS file : %s\n", filename);
+    return FALSE;
+  }
+
+  // XXX: need to handle case of spline data not existing...
+
+  // need to create and assign to flat-field correction
+  double *xk = gfits_get_bintable_column_data (&theader, &ftable, "X_KNOT", type, &Nrow, &Ncol);
+  assert (!strcmp(type, "double"));
+  
+  // need to create and assign to flat-field correction
+  double *yk = gfits_get_bintable_column_data (&theader, &ftable, "Y_KNOT", type, &Nrow, &Ncol);
+  assert (!strcmp(type, "double"));
+
+  // need to create and assign to flat-field correction
+  double *y2 = gfits_get_bintable_column_data (&theader, &ftable, "DY2_DX", type, &Nrow, &Ncol);
+  assert (!strcmp(type, "double"));
+
+  Spline *myspline = CreateSpline (name, Nrow);
+  for (i = 0; i < Nrow; i++) {
+    myspline->xk[i] = xk[i];
+    myspline->yk[i] = yk[i];
+    myspline->y2[i] = y2[i];
+  }
+  free (xk);
+  free (yk);
+  free (y2);
+
+  fclose (f);
+  return (TRUE);
+}
Index: /branches/eam_branches/ipp-20120905/Ohana/src/opihi/lib.shell/VectorIO.c
===================================================================
--- /branches/eam_branches/ipp-20120905/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 34528)
+++ /branches/eam_branches/ipp-20120905/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 34529)
@@ -2,34 +2,11 @@
   
 // write a set of vectors to a FITS file (vectors names become fits column names)
-int WriteVectorTableFITS (char *filename, char *extname, Vector **vec, int Nvec, int append, char *format) {
-  
+int WriteVectorTable (Header *theader, FTable *ftable, char *extname, Vector **vec, int Nvec, char *format) {
+  
+  int j;
+
   char *tformat = NULL;
-  Header header;
-  Matrix matrix;
-  Header theader;
-  FTable ftable;
-
-  int j;
-  FILE *f = NULL;
-
-  /* open file for outuput */
-  if (append) {
-    f = fopen (filename, "a");
-  } else {
-    f = fopen (filename, "w");
-  }
-  if (f == (FILE *) NULL) {
-    gprint (GP_ERR, "can't open file for write : %s\n", filename);
-    return (FALSE);
-  }
-
-  if (!append) {
-    gfits_init_header (&header);
-    header.extend = TRUE;
-    gfits_create_header (&header);
-    gfits_create_matrix (&header, &matrix);
-  }
-
-  gfits_create_table_header (&theader, "BINTABLE", extname);
+
+  gfits_create_table_header (theader, "BINTABLE", extname);
 
   ALLOCATE (tformat, char, 2*Nvec);
@@ -71,21 +48,54 @@
   // this somehow
   for (j = 0; j < Nvec; j++) {
-    gfits_define_bintable_column (&theader, &tformat[2*j], vec[j][0].name, NULL, NULL, 1.0, 0.0);
+    gfits_define_bintable_column (theader, &tformat[2*j], vec[j][0].name, NULL, NULL, 1.0, 0.0);
   }
   free (tformat);
 
   // generate the output array that carries the data
-  gfits_create_table (&theader, &ftable);
+  gfits_create_table (theader, ftable);
 
   // add the vectors to the output array
   for (j = 0; j < Nvec; j++) {
     if (vec[j][0].type == OPIHI_FLT) {
-      gfits_set_bintable_column_reformat (&theader, &ftable, vec[j][0].name, "double", vec[j][0].elements.Flt, vec[j][0].Nelements);
+      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "double", vec[j][0].elements.Flt, vec[j][0].Nelements);
     } else {
-      gfits_set_bintable_column_reformat (&theader, &ftable, vec[j][0].name, "int", vec[j][0].elements.Int, vec[j][0].Nelements);
-    }
-  }
+      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int", vec[j][0].elements.Int, vec[j][0].Nelements);
+    }
+  }
+  return (TRUE);
+
+ escape:
+  if (tformat) free (tformat);
+  return (FALSE);
+}
+  
+// write a set of vectors to a FITS file (vectors names become fits column names)
+int WriteVectorTableFITS (char *filename, char *extname, Vector **vec, int Nvec, int append, char *format) {
+  
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+
+  FILE *f = NULL;
+
+  /* open file for outuput */
+  if (append) {
+    f = fopen (filename, "a");
+  } else {
+    f = fopen (filename, "w");
+  }
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't open file for write : %s\n", filename);
+    return (FALSE);
+  }
+
+  if (!WriteVectorTable (&theader, &ftable, extname, vec, Nvec, format)) goto escape;
 
   if (!append) {
+    gfits_init_header (&header);
+    header.extend = TRUE;
+    gfits_create_header (&header);
+    gfits_create_matrix (&header, &matrix);
     gfits_fwrite_header  (f, &header);
     gfits_fwrite_matrix  (f, &matrix);
@@ -111,5 +121,4 @@
   gfits_free_table (&ftable);
 
-  if (tformat) free (tformat);
   fclose (f);
   fflush (f);
