Index: /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/stellarParams.d
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/stellarParams.d	(revision 37389)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libautocode/def/stellarParams.d	(revision 37389)
@@ -0,0 +1,18 @@
+STRUCT       StarPars
+EXTNAME      DVO_STELLAR_PARAMS
+TYPE         BINTABLE
+SIZE         48
+DESCRIPTION  DVO Table of Stellar Properties
+
+FIELD galLat,         GAL_LAT,       double, galactic latitude
+FIELD galLon,         GAL_LON,       double, galactic longitude
+FIELD MKtype,         MK_TYPE,       float, O0 = 0.0?
+FIELD Par,            PARALLAX,      float, 1/pc
+FIELD dPar,           PARALLAX_ERR,  float, 1/pc
+FIELD uRA,            U_RA,          model guess for proper motion
+FIELD uDEC,           U_DEC,         model guess for proper motion
+FIELD averef,         AVE_REF,      unsigned int,   reference to average entry      
+FIELD objID,          OBJ_ID,       unsigned int,   unique ID for object in table
+FIELD catID,          CAT_ID,       unsigned int,   unique ID for table in which object was first realized
+
+# this is the list of stellar parameters loaded from Greg Green's tables:
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h	(revision 37388)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h	(revision 37389)
@@ -653,8 +653,10 @@
   Lensobj *lensobj;
 
+  StarPar *starpar;
+
   int Nsecfilt;  /* number of secfilt entries for each average entry */
-  off_t Naverage,   Nmeasure,   Nmissing,   Nlensing,      Nlensobj,      Nsecf_mem;  /* current number of each component in memory */
-  off_t Naves_disk, Nmeas_disk, Nmiss_disk, Nlensing_disk, Nlensobj_disk, Nsecf_disk; /* current number of each component on disk */
-  off_t Naves_off,  Nmeas_off,  Nmiss_off,  Nlensing_off,  Nlensobj_off,  Nsecf_off;  /* index of first loaded data value */
+  off_t Naverage,   Nmeasure,   Nmissing,   Nlensing,      Nlensobj,      Nstarpar,      Nsecf_mem;  /* current number of each component in memory */
+  off_t Naves_disk, Nmeas_disk, Nmiss_disk, Nlensing_disk, Nlensobj_disk, Nstarpar_disk, Nsecf_disk; /* current number of each component on disk */
+  off_t Naves_off,  Nmeas_off,  Nmiss_off,  Nlensing_off,  Nlensobj_off,  Nstarpar_off,  Nsecf_off;  /* index of first loaded data value */
 
   // note that we use these for the full-sky relphot analysis
@@ -677,4 +679,5 @@
   struct Catalog *lensing_catalog;		/* lensing catalog data (split) */
   struct Catalog *lensobj_catalog;		/* lensobj catalog data (split) */
+  struct Catalog *starpar_catalog;		/* starpar catalog data (split) */
 
   unsigned int objID;
@@ -869,4 +872,5 @@
 Lensing *FtableToLensing (FTable *ftable, off_t *Nlensing, char *format);
 Lensobj *FtableToLensobj (FTable *ftable, off_t *Nlensobj, char *format);
+StarPar *FtableToStarPar (FTable *ftable, off_t *Nstarpar, char *format);
 int      FtableToImage   (FTable *ftable, Header *theader, char *format);
 
@@ -876,4 +880,5 @@
 int LensingToFtable (FTable *ftable, Lensing *lensing, off_t Nlensing, char format);
 int LensobjToFtable (FTable *ftable, Lensobj *lensobj, off_t Nlensobj, char format);
+int StarParToFtable (FTable *ftable, StarPar *starpar, off_t Nstarpar, char format);
 int ImageToFtable (FTable *ftable, Header *theader, char format);
 int ImageToVtable (VTable *vtable, Header *theader, char format);
@@ -1003,4 +1008,6 @@
 void dvo_lensobj_init (Lensobj *lensobj, int toZero);
 
+void dvo_starpar_init (StarPar *starpar);
+
 void InitRegionHosts (RegionHostInfo *hosts, int Nhosts, int NHOSTS);
 void FreeRegionHosts (RegionHostInfo *hosts, int Nhosts);
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/AstromOffsetMapIO.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/AstromOffsetMapIO.c	(revision 37388)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/AstromOffsetMapIO.c	(revision 37389)
@@ -107,8 +107,8 @@
   ALLOCATE (table->map, AstromOffsetMap, Nmap);
 
-  // find the max value of ID
+  // find the max value of imageID
   int MaxID = 0;
   for (i = 0; i < Nmap; i++) {
-    MaxID = MAX(map_disk[i].ID, MaxID);
+    MaxID = MAX(map_disk[i].imageID, MaxID);
   }
   MaxID ++; // we want the outer bound, not the last value
@@ -119,10 +119,10 @@
     table->IDtoSeq[i] = -1;
   }
-  table->MaxID = MaxID;
+  table->MaxID = MaxID - 1;
 
   // assign the ID values
   for (i = 0; i < Nmap; i++) {
-    int ID = map_disk[i].ID;
-    myAssert (table->IDtoSeq[ID] == -1, "oops, duplicate map IDs");
+    int ID = map_disk[i].imageID;
+    myAssert (table->IDtoSeq[ID] == -1, "oops, duplicate image IDs");
     table->IDtoSeq[ID] = i;
   }
@@ -162,5 +162,5 @@
 
   AstromOffsetMap_Disk_6x6 *map_disk = NULL;
-  ALLOCATE (map_disk, AstromOffsetMap_Disk_6x6, Nmap);
+  ALLOCATE (map_disk, AstromOffsetMap_Disk_6x6, table->Nmap);
 
   // assign the map values (this allocates just the area needed for each image, not the
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/AstromOffsetMapOps.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/AstromOffsetMapOps.c	(revision 37388)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/AstromOffsetMapOps.c	(revision 37389)
@@ -65,5 +65,5 @@
 int AstromOffsetMapFit (AstromOffsetMap *map, float *x, float *y, float *f, int Npts, int xdir) {
 
-  int i, ix, iy, jx, jy;
+  int i, j, ix, iy, jx, jy;
 
   // choose to map direction:
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/astrom_maps.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/astrom_maps.c	(revision 37389)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/astrom_maps.c	(revision 37389)
@@ -0,0 +1,25 @@
+# include <dvo.h>
+
+int MatchChipsToAstromMaps (Image *images, off_t Nimages, AstromOffsetTable *table) {
+
+  // we have a table of astrometry offset maps.  we want to find the chips that match to
+  // each of the maps so we can assign the map to the image.coords.offsetMap entry
+
+  // we have the lookup table of table->IDtoSeq to find the match by imageID
+  
+  // we are just going to assume that table->IDtoSeq is correct and complete
+  for (i = 0; i < Nimages; i++) {
+    int imageID = images[i].imageID;
+    if (imageID < 0) continue;
+    if (imageID > table->maxID) continue;
+    
+    int seq = table->IDtoSeq[imageID];
+    if (seq < 0) continue;
+    if (seq >= table->Nmap) continue; // this one is probably not valid, right?
+
+    images[i].coords.offsetMap = &table->map[seq];    
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog.c	(revision 37388)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog.c	(revision 37389)
@@ -437,4 +437,18 @@
 
 // init all data, or just catalog data
+void dvo_starpars_init (StarPars *starpars) {
+  starpars->galLat = NAN;
+  starpars->galLon = NAN;
+  starpars->MKtype = NAN;
+  starpars->Par    = NAN;
+  starpars->dPar   = NAN;
+  starpars->uRA    = NAN;
+  starpars->uDEC   = NAN;
+  starpars->averef = -1;
+  starpars->objID  = -1;
+  starpars->catID  = -1;
+}
+
+// init all data, or just catalog data
 void dvo_catalog_init (Catalog *catalog, int complete) {
 
@@ -462,4 +476,6 @@
   catalog[0].lensobj = NULL; 
 
+  catalog[0].starpar = NULL; 
+
   catalog[0].averageT = NULL;
   catalog[0].measureT = NULL; 
@@ -477,4 +493,6 @@
   catalog[0].Nlensobj = 0;
 
+  catalog[0].Nstarpar = 0;
+
   catalog[0].Naves_disk = 0;
   catalog[0].Nmeas_disk = 0;
@@ -485,4 +503,6 @@
   catalog[0].Nlensobj_disk = 0;
 
+  catalog[0].Nstarpar_disk = 0;
+
   catalog[0].Naves_off  = 0;
   catalog[0].Nmeas_off  = 0;
@@ -492,4 +512,6 @@
   catalog[0].Nlensing_off  = 0;
   catalog[0].Nlensobj_off  = 0;
+
+  catalog[0].Nstarpar_off  = 0;
 
   /* pointers to SPLIT data files */
@@ -499,4 +521,5 @@
   catalog[0].lensing_catalog = NULL;
   catalog[0].lensobj_catalog = NULL;
+  catalog[0].starpar_catalog = NULL;
 
   /* pointers for data manipulation */
@@ -560,4 +583,5 @@
     if (catalog[0].lensing_catalog) dvo_catalog_unlock (catalog[0].lensing_catalog);
     if (catalog[0].lensobj_catalog) dvo_catalog_unlock (catalog[0].lensobj_catalog);
+    if (catalog[0].starpar_catalog) dvo_catalog_unlock (catalog[0].starpar_catalog);
   }
   return (1);
@@ -835,4 +859,9 @@
       free (catalog[0].lensobj_catalog);
     }
+    if (catalog[0].starpar_catalog) {
+      free (catalog[0].starpar_catalog[0].filename);
+      dvo_catalog_free (catalog[0].starpar_catalog);
+      free (catalog[0].starpar_catalog);
+    }
   }
   dvo_catalog_free_data (catalog);
@@ -873,4 +902,9 @@
     catalog[0].Nlensobj = 0;
     catalog[0].lensobj = NULL;
+  }
+  if (catalog[0].starpar) {
+    free (catalog[0].starpar); 
+    catalog[0].Nstarpar = 0;
+    catalog[0].starpar = NULL;
   }
   if (catalog[0].nOwn_t)      { free (catalog[0].nOwn_t); catalog[0].nOwn_t = NULL; }
@@ -985,4 +1019,14 @@
       }
     }
+    if (catalog[0].starpar_catalog != NULL) {
+      if (catalog[0].Nstarpar_disk == 0) {
+	// need to relock (and re-open) file for close elsewhere
+	status = dvo_catalog_lock (catalog[0].starpar_catalog, lockmode);
+      } else {
+	if (!dvo_catalog_backup (catalog[0].starpar_catalog, FALSE)) {
+	  return FALSE;
+	}
+      }
+    }
   }
   return TRUE;
@@ -1036,4 +1080,9 @@
       }
     }
+    if ((catalog[0].starpar_catalog != NULL) && (catalog[0].Nstarpar_disk > 0)) {
+      if (!dvo_catalog_unlink_backup (catalog[0].starpar_catalog, FALSE)) {
+	return FALSE;
+      }
+    }
   }
   return TRUE;
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog_create.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 37388)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 37389)
@@ -95,4 +95,16 @@
     free (file);
 
+    /* define starpar catalog file */
+    ALLOCATE (catalog[0].starpar_catalog, Catalog, 1);
+    dvo_catalog_init (catalog[0].starpar_catalog, TRUE);
+
+    /* create basic data for starpar catalog file */
+    gfits_create_header (&catalog[0].starpar_catalog[0].header);
+    ALLOCATE (catalog[0].starpar_catalog[0].filename, char, length);
+    sprintf (catalog[0].starpar_catalog[0].filename, "%s/%s.cpy", path, root);
+    file = filebasename (catalog[0].starpar_catalog[0].filename);
+    gfits_modify (&catalog[0].header, "STARPAR", "%s", 1, file);
+    free (file);
+
     free (path);
     free (root);
@@ -117,4 +129,8 @@
     }
     if (dvo_catalog_lock (catalog[0].lensobj_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
+      fprintf (stderr, "error with file lock\n");
+      exit (2);
+    }
+    if (dvo_catalog_lock (catalog[0].starpar_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
       fprintf (stderr, "error with file lock\n");
       exit (2);
@@ -146,4 +162,5 @@
   ALLOCATE (catalog[0].lensing, Lensing, 1);
   ALLOCATE (catalog[0].lensobj, Lensobj, 1);
+  ALLOCATE (catalog[0].starpar, StarPar, 1);
 
   /* setup secondary filters to match photcodes:
Index: /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog_split.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 37388)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 37389)
@@ -134,8 +134,9 @@
   if (!gfits_scan (&catalog[0].header, name,  "%s", 1, string)) {
     free (path);
-    // databases created prior to ~2014.07.01 did not have the LENSING or LENSOBJ paths in their headers.
+    // databases created prior to ~2014.07.01 did not have the LENSING, LENSOBJ, STARPAR paths in their headers.
     // in these cases, we do not try to lock or open the relevant file
     if (!strcmp (name, "LENSING")) return (DVO_CAT_OPEN_EMPTY);
     if (!strcmp (name, "LENSOBJ")) return (DVO_CAT_OPEN_EMPTY);
+    if (!strcmp (name, "STARPAR")) return (DVO_CAT_OPEN_EMPTY);
     return (DVO_CAT_OPEN_FAIL);
   }
@@ -182,4 +183,5 @@
   off_t Nlensing;
   off_t Nlensobj;
+  off_t Nstarpar;
   off_t Nitems;
   int status, Nsecfilt;
@@ -196,5 +198,5 @@
 
   /* get the components from the header - these duplicate information in the split files (NAXIS2) */
-  // NSTARS, NMEAS, NMISS are required; NLENSING, NLENSOBJ are not (0 if not found)
+  // NSTARS, NMEAS, NMISS are required; NLENSING, NLENSOBJ, NSTARPAR are not (0 if not found)
   if (!gfits_scan (&catalog[0].header, "NSTARS",   OFF_T_FMT, 1,  &Naverage)) return (FALSE);
   if (!gfits_scan (&catalog[0].header, "NMEAS",    OFF_T_FMT, 1,  &Nmeasure)) return (FALSE);
@@ -203,4 +205,5 @@
   if (!gfits_scan (&catalog[0].header, "NLENSING", OFF_T_FMT, 1,  &Nlensing)) Nlensing = 0;
   if (!gfits_scan (&catalog[0].header, "NLENSOBJ", OFF_T_FMT, 1,  &Nlensobj)) Nlensobj = 0;
+  if (!gfits_scan (&catalog[0].header, "NSTARPAR", OFF_T_FMT, 1,  &Nstarpar)) Nstarpar = 0;
 
   /* the OBJID is a counter that uniquely defines an average entry and never changes.  if
@@ -223,4 +226,5 @@
   catalog[0].Nlensing_disk = Nlensing;
   catalog[0].Nlensobj_disk = Nlensobj;
+  catalog[0].Nstarpar_disk = Nstarpar;
 
   /**  Nsecfilt is unusual: it does not list the number of data items in the table
@@ -235,4 +239,5 @@
   catalog[0].lensing = NULL;
   catalog[0].lensobj = NULL;
+  catalog[0].starpar = NULL;
 
   /*** Average Table ***/
@@ -465,4 +470,44 @@
   gfits_free_header (&header);
 
+  /*** Starpar Table ***/
+  if (!(catalog[0].catflags & SKIP_STARPAR)) {
+    // unless we specify 'skip', we still need to load the 
+    status = dvo_catalog_open_subcat (catalog, &catalog[0].starpar_catalog, ftable.header, "STARPAR", VERBOSE);
+    if (status == DVO_CAT_OPEN_FAIL) {
+      return (FALSE);
+    }
+    // the Starpar file need not exist, unless we expect data to exist
+    if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nstarpar_disk > 0)) {
+      return (FALSE);
+    }
+  }
+  if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_STARPAR)) {
+    // only read the Starpar table if the file actually exists
+    /* read Starpar table data */
+    if (!gfits_fread_ftable_data (catalog[0].starpar_catalog[0].f, &ftable, FALSE)) {
+      if (VERBOSE) fprintf (stderr, "can't read table starpar data\n");
+      return (FALSE);
+    }
+    /* convert data format to internal : returns number of row read in Nstarpar */
+    catalog[0].starpar = FtableToStarpar (&ftable, &Nstarpar, &catalog[0].catformat);
+    if (Nstarpar != catalog[0].Nstarpar_disk) {
+      fprintf (stderr, "Warning: mismatch between Nstarpar in PHU and Table headers ("OFF_T_FMT" vs "OFF_T_FMT")\n",  Nstarpar,  catalog[0].Nstarpar_disk);
+    }
+    catalog[0].Nstarpar = catalog[0].Nstarpar_disk;
+    catalog[0].Nstarpar_off = 0;
+  } else {
+    if (catalog[0].starpar_catalog) {
+      gfits_free_header (&catalog[0].starpar_catalog[0].header);
+    } else {
+      ALLOCATE (catalog[0].starpar_catalog, Catalog, 1);
+      dvo_catalog_init (catalog[0].starpar_catalog, TRUE);
+    }
+    gfits_create_header (&catalog[0].starpar_catalog[0].header);
+    ALLOCATE (catalog[0].starpar, Starpar, 1);
+    catalog[0].Nstarpar = 0;
+    catalog[0].Nstarpar_off = catalog[0].Nstarpar_disk;
+  }
+  gfits_free_header (&header);
+
   return (TRUE);
 }
@@ -473,5 +518,5 @@
 
   off_t Nbytes;
-  off_t Naverage, Nexpect, Nitems, Nmeasure, Nmissing, Nlensing, Nlensobj;
+  off_t Naverage, Nexpect, Nitems, Nmeasure, Nmissing, Nlensing, Nlensobj, Nstarpar;
   Header header;
   FTable ftable;
@@ -675,4 +720,35 @@
   }
 
+  // XXX check the open status of the catalog
+  if (catalog[0].catflags & LOAD_STARPAR) {
+
+    Catalog *subcat = catalog[0].starpar_catalog;
+
+    /* move pointer past header -- must be already read (load_catalog) */
+    Nbytes = subcat[0].header.datasize + gfits_data_size (&subcat[0].header);
+    fseeko (subcat[0].f, Nbytes, SEEK_SET);
+
+    /* read Starpar table header */
+    if (!gfits_fread_header (subcat[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table starpar header");
+      return (FALSE);
+    }
+    /* read Starpar table data : format is irrelevant here */
+    if (!gfits_fread_ftable_range (subcat[0].f, &ftable, start, Nrows)) {
+      if (VERBOSE) fprintf (stderr, "can't read table starpar data");
+      return (FALSE);
+    }
+
+    /* convert data format to internal : returns number of row read in Nstarpar */
+    catalog[0].starpar = FtableToStarpar (&ftable, &Nstarpar, &catalog[0].catformat);
+    if (Nstarpar != Nrows) {
+      // XXX this condition denotes the eof has been reached; not an error or a warning
+      // fprintf (stderr, "Warning: mismatch between Nstarpar in PHU and Table headers ("OFF_T_FMT" vs "OFF_T_FMT")\n",  Nstarpar,  Nrows);
+    }
+    gfits_free_header (&header);
+    catalog[0].Nstarpar = Nstarpar;
+    catalog[0].Nstarpar_off = start;
+  }
+
   return (TRUE);
 }
@@ -686,5 +762,5 @@
   SecFilt *primary, *secfilt;
   int Nsecfilt;
-  off_t Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new, Nlensing_disk_new, Nlensobj_disk_new;
+  off_t Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new, Nlensing_disk_new, Nlensobj_disk_new, Nstarpar_disk_new;
   off_t first, start, Nrows;
 
@@ -719,4 +795,5 @@
   Nlensing_disk_new = MAX (catalog[0].Nlensing_disk, catalog[0].Nlensing + catalog[0].Nlensing_off);
   Nlensobj_disk_new = MAX (catalog[0].Nlensobj_disk, catalog[0].Nlensobj + catalog[0].Nlensobj_off);
+  Nstarpar_disk_new = MAX (catalog[0].Nstarpar_disk, catalog[0].Nstarpar + catalog[0].Nstarpar_off);
 
   /* make sure header is consistent with data */
@@ -727,4 +804,5 @@
   gfits_modify (&catalog[0].header, "NLENSING", OFF_T_FMT, 1,  Nlensing_disk_new);
   gfits_modify (&catalog[0].header, "NLENSOBJ", OFF_T_FMT, 1,  Nlensobj_disk_new);
+  gfits_modify (&catalog[0].header, "NSTARPAR", OFF_T_FMT, 1,  Nstarpar_disk_new);
   gfits_modify_alt (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
   gfits_modify (&catalog[0].header, "OBJID",    "%d", 1, catalog[0].objID);
@@ -893,4 +971,31 @@
     if (!dvo_catalog_save_subcat (catalog[0].lensobj_catalog, &ftable, start, Nrows, catalog[0].Nlensobj_disk, Nlensobj_disk_new)) {
       fprintf (stderr, "trouble writing Lensobj table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Lensobj Table ***/
+  if ((catalog[0].catflags & LOAD_STARPAR) && (catalog[0].starpar != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Nstarpar_off; // first disk row to write
+    Nrows  = catalog[0].Nstarpar - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= catalog[0].Nstarpar);
+    assert (catalog[0].Nstarpar_disk >= catalog[0].Nstarpar_off);
+
+    // convert to external table format (note that the block above does not damage or free catalog.average) 
+    if (!StarparToFtable (&ftable, &catalog[0].starpar[first], Nrows, catalog[0].catformat)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Starpar table
+    if (!dvo_catalog_save_subcat (catalog[0].starpar_catalog, &ftable, start, Nrows, catalog[0].Nstarpar_disk, Nstarpar_disk_new)) {
+      fprintf (stderr, "trouble writing Starpar table\n");
       goto failure;
     }
@@ -925,5 +1030,5 @@
   SecFilt *primary, *secfilt;
   int Nsecfilt;
-  off_t Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new, Nlensing_disk_new, Nlensobj_disk_new;
+  off_t Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new, Nlensing_disk_new, Nlensobj_disk_new, Nstarpar_disk_new;
   off_t first, start, Nrows;
 
@@ -956,4 +1061,8 @@
   if (catalog[0].Nlensobj_off > 0) {
     fprintf (stderr, "ERROR: only partial catalog (Lensobj) was loaded\n");
+    goto failure;
+  }
+  if (catalog[0].Nstarpar_off > 0) {
+    fprintf (stderr, "ERROR: only partial catalog (Starpar) was loaded\n");
     goto failure;
   }
@@ -984,4 +1093,5 @@
   Nlensing_disk_new = catalog[0].Nlensing;
   Nlensobj_disk_new = catalog[0].Nlensobj;
+  Nstarpar_disk_new = catalog[0].Nstarpar;
 
   /* make sure header is consistent with data */
@@ -992,4 +1102,5 @@
   gfits_modify (&catalog[0].header, "NLENSING", OFF_T_FMT, 1,  Nlensing_disk_new);
   gfits_modify (&catalog[0].header, "NLENSOBJ", OFF_T_FMT, 1,  Nlensobj_disk_new);
+  gfits_modify (&catalog[0].header, "NSTARPAR", OFF_T_FMT, 1,  Nstarpar_disk_new);
   gfits_modify_alt (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
   gfits_modify (&catalog[0].header, "OBJID",    "%d", 1, catalog[0].objID);
@@ -1139,4 +1250,31 @@
   /*** Lensobj Table ***/
   if ((catalog[0].catflags & LOAD_LENSOBJ) && (catalog[0].lensobj != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Nlensobj_off; // first disk row to write
+    Nrows  = catalog[0].Nlensobj - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= catalog[0].Nlensobj);
+    assert (catalog[0].Nlensobj_disk >= catalog[0].Nlensobj_off);
+
+    // convert to external table format
+    if (!LensobjToFtable (&ftable, &catalog[0].lensobj[first], Nrows, catalog[0].catformat)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Lensobj table
+    if (!dvo_catalog_save_subcat (catalog[0].lensobj_catalog, &ftable, start, Nrows, catalog[0].Nlensobj_disk, Nlensobj_disk_new)) {
+      fprintf (stderr, "trouble writing Lensobj table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Starpar Table ***/
+  if ((catalog[0].catflags & LOAD_STARPAR) && (catalog[0].lensobj != NULL)) {
 
     first  = 0;                    // first row in memory to write
@@ -1189,5 +1327,5 @@
   SecFilt *primary, *secfilt;
   int Nsecfilt;
-  off_t Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new, Nlensing_disk_new, Nlensobj_disk_new;
+  off_t Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new, Nlensing_disk_new, Nlensobj_disk_new, Nlensobj_disk_new;
   off_t first, start, Nrows;
 
@@ -1221,4 +1359,5 @@
   Nlensing_disk_new = MAX (catalog[0].Nlensing_disk, catalog[0].Nlensing + catalog[0].Nlensing_off);
   Nlensobj_disk_new = MAX (catalog[0].Nlensobj_disk, catalog[0].Nlensobj + catalog[0].Nlensobj_off);
+  Nlensobj_disk_new = MAX (catalog[0].Nlensobj_disk, catalog[0].Nlensobj + catalog[0].Nlensobj_off);
 
   /* make sure header is consistent with data */
@@ -1229,4 +1368,5 @@
   gfits_modify (&catalog[0].header, "NLENSING", OFF_T_FMT, 1,  Nlensing_disk_new);
   gfits_modify (&catalog[0].header, "NLENSOBJ", OFF_T_FMT, 1,  Nlensobj_disk_new);
+  gfits_modify (&catalog[0].header, "NLENSOBJ", OFF_T_FMT, 1,  Nlensobj_disk_new);
   gfits_modify_alt (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
   gfits_modify (&catalog[0].header, "OBJID",    "%d", 1, catalog[0].objID);
@@ -1371,4 +1511,32 @@
     if (!dvo_catalog_save_subcat (catalog[0].lensing_catalog, &ftable, start, Nrows, catalog[0].Nlensing_disk, Nlensing_disk_new)) {
       fprintf (stderr, "trouble writing Lensing table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Lensobj Table ***/
+  if (catalog[0].lensobj != NULL) {
+
+    first  = catalog[0].Nlensobj_disk - catalog[0].Nlensobj_off;  // first row in memory to write
+    start  = catalog[0].Nlensobj_disk; // first disk row to write
+    Nrows  = catalog[0].Nlensobj - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= catalog[0].Nlensobj);
+    assert (catalog[0].Nlensobj_disk >= catalog[0].Nlensobj_off);
+
+    // convert to external table format
+    // XXX does catalog.lensobj have averef correctly set up?
+    if (!LensobjToFtable (&ftable, &catalog[0].lensobj[first], Nrows, catalog[0].catformat)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Lensobj table
+    if (!dvo_catalog_save_subcat (catalog[0].lensobj_catalog, &ftable, start, Nrows, catalog[0].Nlensobj_disk, Nlensobj_disk_new)) {
+      fprintf (stderr, "trouble writing Lensobj table\n");
       goto failure;
     }
