Index: /branches/eam_branch_20071130/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /branches/eam_branch_20071130/Ohana/src/libdvo/include/dvo.h	(revision 15724)
+++ /branches/eam_branch_20071130/Ohana/src/libdvo/include/dvo.h	(revision 15725)
@@ -22,4 +22,6 @@
 typedef enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE} ElixirDetrendTypes;
 typedef enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE} ElixirDetrendModes;
+
+typedef enum {DVO_CAT_OPEN_FAIL, DVO_CAT_OPEN_OK, DVO_CAT_OPEN_EMPTY};
 
 typedef enum {
Index: /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog.c
===================================================================
--- /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog.c	(revision 15724)
+++ /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog.c	(revision 15725)
@@ -110,7 +110,7 @@
 
 /* possible exit status for lock_catalog: 
-   0 - failure (including lock failure)
-   1 - success
-   2 - empty file (file may be open or closed!) 
+   DVO_CAT_OPEN_FAIL - failure (including lock failure)
+   DVO_CAT_OPEN_OK - success
+   DVO_CAT_OPEN_EMPTY - empty file (file may be open or closed!) 
 */
 int dvo_catalog_lock (Catalog *catalog, int lockmode) {
@@ -125,10 +125,10 @@
   catalog[0].f = fsetlockfile (catalog[0].filename, 3600.0, catalog[0].lockmode, &dbstate);
 
-  if (dbstate == LCK_MISSING) return (2);
-  if (dbstate == LCK_EMPTY)   return (2);
-  if (catalog[0].f == NULL)   return (0);
+  if (dbstate == LCK_MISSING) return (DVO_CAT_OPEN_EMPTY);
+  if (dbstate == LCK_EMPTY)   return (DVO_CAT_OPEN_EMPTY);
+  if (catalog[0].f == NULL)   return (DVO_CAT_OPEN_FAIL);
 
   fseek (catalog[0].f, 0, SEEK_SET);
-  return (1);
+  return (DVO_CAT_OPEN_OK);
 }
 
@@ -192,8 +192,8 @@
   
   switch (dvo_catalog_lock (catalog, catalog[0].lockmode)) {
-  case 0:
+  case DVO_CAT_OPEN_FAIL:
     if (VERBOSE) fprintf (stderr, "can't lock file %s\n", catalog[0].filename);
     return (FALSE);
-  case 1:
+  case DVO_CAT_OPEN_OK:
     if (!dvo_catalog_load (catalog, VERBOSE)) {
       if (VERBOSE) fprintf (stderr, "failure loading catalog\n");
@@ -206,5 +206,5 @@
     if (VERBOSE) fprintf (stderr, "loaded existing file %s\n", catalog[0].filename);
     break;
-  case 2:
+  case DVO_CAT_OPEN_EMPTY:
     if ((mode == DVO_OPEN_READ) || (mode == DVO_OPEN_UPDATE)) return (TRUE);
     catalog[0].Nsecfilt = Nsecfilt;
Index: /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_create.c
===================================================================
--- /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 15724)
+++ /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 15725)
@@ -73,13 +73,13 @@
     // lock the additional split files
     // XXX clear residual locks if we fail
-    if (dvo_catalog_lock (catalog[0].measure_catalog, catalog[0].lockmode) != 2) {
+    if (dvo_catalog_lock (catalog[0].measure_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
       fprintf (stderr, "error with file lock\n");
       exit (2);
     }
-    if (dvo_catalog_lock (catalog[0].missing_catalog, catalog[0].lockmode) != 2) {
+    if (dvo_catalog_lock (catalog[0].missing_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
       fprintf (stderr, "error with file lock\n");
       exit (2);
     }
-    if (dvo_catalog_lock (catalog[0].secfilt_catalog, catalog[0].lockmode) != 2) {
+    if (dvo_catalog_lock (catalog[0].secfilt_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
       fprintf (stderr, "error with file lock\n");
       exit (2);
Index: /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_split.c
===================================================================
--- /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 15724)
+++ /branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 15725)
@@ -1,3 +1,59 @@
 # include <dvo.h>
+
+// return options: 
+// * error (cannot lock, open, read, etc)
+// * empty (file is not found)
+// * ok
+
+int dvo_catalog_open_subcat (Catalog *catalog, Catalog **Subcat, char *name, int VERBOSE) {
+
+  char *path;
+  Catalog *subcat;
+
+  /* in split mode, we need to init & open the corresponding measure file (even if we do not read
+   * any data in at this stage) */
+  ALLOCATE (subcat, Catalog, 1);
+  dvo_catalog_init (subcat, TRUE);
+
+  /* needed to find the split files below */
+  path = pathname (catalog[0].filename);
+
+  /* get split filename from main header (paths relative to cpt file) */
+  if (!gfits_scan (&catalog[0].header, name,  "%s", 1, string)) return (DVO_CAT_OPEN_FAIL);
+  ALLOCATE (subcat[0].filename, char, strlen(path) + strlen(string) + 2);
+  sprintf (subcat[0].filename, "%s/%s", path, string);
+
+  /* lock & open catalog file */
+  status = dvo_catalog_lock (subcat, catalog[0].lockmode);
+  if (status != DVO_CAT_OPEN_OK) {
+    if (VERBOSE) {
+      if (status == DVO_CAT_OPEN_EMPTY) {
+	fprintf (stderr, "%s (%s) is empty\n", name, subcat[0].filename);
+      } else {
+	fprintf (stderr, "failure to lock %s (%s)\n", name, subcat[0].filename);
+      }
+    }
+    return (status);
+  }
+
+  /* read PHU */
+  if (!gfits_load_header (subcat[0].f, &subcat[0].header)) {
+    if (VERBOSE) fprintf (stderr, "error reading %s header: %s\n", name, subcat[0].filename);
+    return (DVO_CAT_OPEN_FAIL);
+  }
+  /* matrix should be empty : XXX skip the matrix data? */
+  if (!gfits_fread_matrix (subcat[0].f, &matrix, &subcat[0].header)) {
+    if (VERBOSE) fprintf (stderr, "can't read primary matrix for %s\n", name);
+    return (DVO_CAT_OPEN_FAIL);
+  }
+  /* read Measure table header */
+  if (!gfits_fread_header (subcat[0].f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read %s PHU header\n", name);
+    return (DVO_CAT_OPEN_FAIL);
+  }
+
+  *Subcat = subcat;
+  return (DVO_CAT_OPEN_OK);
+}
 
 int dvo_catalog_load_split (Catalog *catalog, int VERBOSE) {
@@ -9,5 +65,4 @@
   FTable ftable;
   SecFilt *primary;
-  Catalog *measure, *missing, *secfilt;
 
   /* ftable header storage for below */
@@ -29,16 +84,4 @@
   catalog[0].Nsecf_disk = Naverage * Nsecfilt;
 
-  /* these values are the number of elements loaded into memory */
-  catalog[0].Naverage = 0;
-  catalog[0].Nmeasure = 0;
-  catalog[0].Nmissing = 0;
-  catalog[0].Nsecfilt = 0;
-
-  /* by default, an unloaded catalog is ready to accept more entries after the end of the table */
-  catalog[0].Naves_off = catalog[0].Naves_disk;
-  catalog[0].Nmeas_off = catalog[0].Nmeas_disk;
-  catalog[0].Nmiss_off = catalog[0].Nmiss_disk;
-  catalog[0].Nsecf_off = catalog[0].Nsecf_disk;
-
   /**  Nsecfilt is unusual: it does not list the number of data items in the table
        instead, the number of items is Nsecfilt * Naverage.  **/
@@ -51,12 +94,9 @@
   catalog[0].secfilt = NULL;
 
-  /* XXX EAM : validate table mode */
-
   /*** Average Table ***/
-
   if (catalog[0].catflags & LOAD_AVES) {
     /* move pointer past header -- must be already read (load_catalog) */
     fseek (catalog[0].f, catalog[0].header.size, SEEK_SET);
-    /* matrix should be empty */
+    /* matrix should be empty : XXX should we drop this step and skip the data? */
     if (!gfits_fread_matrix (catalog[0].f, &matrix, &catalog[0].header)) {
       if (VERBOSE) fprintf (stderr, "can't read primary matrix");
@@ -68,160 +108,97 @@
       return (FALSE);
     }
-    /* read Average table data */
+    /* read Average table data : format is irrelevant here */
     if (!gfits_fread_ftable_data (catalog[0].f, &ftable)) {
       if (VERBOSE) fprintf (stderr, "can't read table average data");
       return (FALSE);
     }
-    /* old versions of DVO stored one of the average magnitudes in Average. we save this if needed */
+    /* convert the saved version of the table to the internal version.  Old versions of DVO stored
+     * one of the average magnitudes in Average.  We save this in case it is needed below.  NOTE:
+     * primary is only used if we read in the secfilt table, otherwise it should be freed */
     catalog[0].average = FtableToAverage (&ftable, &Naverage, &catalog[0].catformat, &primary);
-    if (Naverage != catalog[0].Naverage) {
-      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naverage);
-    }
-    gfits_free_header (&header);
+    if (Naverage != catalog[0].Naves_disk) {
+      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naves_disk);
+    }
+    gfits_free_header (&header);
+    catalog[0].Naverage = Naverage;
+    catalog[0].Naves_off = 0;
   } else {
     ALLOCATE (catalog[0].average, Average, 1);
+    catalog[0].Naverage = 0;
+    catalog[0].Naves_off = Naverage;
   }
 
   /*** Measure Table ***/
-
-  measure = NULL;
-
-  /* (Full Load) */
-  if (catalog[0].catflags & LOAD_MEAS) {
-    /* in split mode, we need to init & open the corresponding measure file */
-    ALLOCATE (measure, Catalog, 1);
-    dvo_catalog_init (measure, TRUE);
-    catalog[0].measure_catalog = measure;
-
-    /* get split filename from main header (paths relative to cpt file) */
-    if (!gfits_scan (&catalog[0].header, "MEASURE",  "%s", 1, string)) return (FALSE);
-    ALLOCATE (measure[0].filename, char, strlen(path) + strlen(string) + 2);
-    sprintf (measure[0].filename, "%s/%s", path, string);
-
-    /* lock & open catalog file */
-    if (dvo_catalog_lock (measure, catalog[0].lockmode) != 1) {
-      fprintf (stderr, "cannot access measure file %s\n", measure[0].filename);
-      exit (2);
-    }
-
-    /* read PHU */
-    if (!gfits_load_header (measure[0].f, &measure[0].header)) {
-      if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", measure[0].filename);
-      return (FALSE);
-    }
-    /* matrix should be empty */
-    if (!gfits_fread_matrix (measure[0].f, &matrix, &measure[0].header)) {
-      if (VERBOSE) fprintf (stderr, "can't read primary matrix\n");
-      return (FALSE);
-    }
-    /* read Measure table header */
-    if (!gfits_fread_header (measure[0].f, &header)) {
-      if (VERBOSE) fprintf (stderr, "can't read measure PHU header\n");
-      return (FALSE);
-    }
+  status = dvo_catalog_open_subcat (catalog, &catalog[0].measure_catalog, "MEASURE");
+  if (status == DVO_CAT_OPEN_FAIL) {
+    return (FALSE);
+  }
+  if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nmeas_disk > 0)) {
+    return (FALSE);
+  }
+  if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_MEAS)) {
+    // XXX this allows an empty Measure catalog with non-empty Average catalog : is that OK?
     /* read Measure table data */
-    if (!gfits_fread_ftable_data (measure[0].f, &ftable)) {
+    if (!gfits_fread_ftable_data (catalog[0].measure_catalog[0].f, &ftable)) {
       if (VERBOSE) fprintf (stderr, "can't read table measure data\n");
       return (FALSE);
     }
-    /* convert data format to internal */
+    /* convert data format to internal : returns number of row read in Nmeasure */
     catalog[0].measure = FtableToMeasure (&ftable, &Nmeasure, &catalog[0].catformat);
-    if (Nmeasure != catalog[0].Nmeasure) {
-      fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, catalog[0].Nmeasure);
+    if (Nmeasure != catalog[0].Nmeas_disk) {
+      fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, catalog[0].Nmeas_disk);
     }
     gfits_free_header (&header);
     gfits_free_matrix (&matrix);
+    catalog[0].Nmeasure = catalog[0].Nmeas_disk;
+    catalog[0].Nmeas_off = 0;
   } else {
+    // XXX is it necessary to generate a template header here?
+    gfits_create_header (&catalog[0].measure_catalog[0].header);
     ALLOCATE (catalog[0].measure, Measure, 1);
+    catalog[0].Nmeasure = 0;
+    catalog[0].Nmeas_off = catalog[0].Nmeas_disk;
   }
 
   /*** Missing Table ***/
-
-  missing = NULL;
-  if (catalog[0].catflags & LOAD_MISS) {
-    ALLOCATE (missing, Catalog, 1);
-    dvo_catalog_init (missing, TRUE);
-
-    /* get split filename from main header (paths relative to cpt file) */
-    if (!gfits_scan (&catalog[0].header, "MISSING",  "%s", 1, string)) return (FALSE);
-    ALLOCATE (missing[0].filename, char, strlen(path) + strlen(string) + 2);
-    sprintf (missing[0].filename, "%s/%s", path, string);
-
-    /* lock & open catalog file */
-    status = dvo_catalog_lock (missing, catalog[0].lockmode);
-    if (!status) {
-      fprintf (stderr, "ERROR: cannot access missing file %s\n", missing[0].filename);
-      exit (2);
-    }
-    if (status == 2) {
-	/* MISSING table is empty (this is not an error) */
-	gfits_create_header (&missing[0].header);
-	goto missing_empty;
-    }
-
-    /* read PHU */
-    if (!gfits_load_header (missing[0].f, &missing[0].header)) {
-      if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", missing[0].filename);
-      return (FALSE);
-    }
-    /* matrix should be empty */
-    if (!gfits_fread_matrix (missing[0].f, &matrix, &missing[0].header)) {
-      if (VERBOSE) fprintf (stderr, "can't read primary matrix\n");
-      return (FALSE);
-    }
-    /* read Missing table header */
-    if (!gfits_fread_header (missing[0].f, &header)) {
-      if (VERBOSE) fprintf (stderr, "can't read table missing header\n");
-      return (FALSE);
-    }
+  status = dvo_catalog_open_subcat (catalog, &catalog[0].missing_catalog, "MISSING");
+  if (status == DVO_CAT_OPEN_FAIL) {
+    return (FALSE);
+  }
+  if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nmeas_disk > 0)) {
+    return (FALSE);
+  }
+  if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_MISS)) {
     /* read Missing table data */
-    if (!gfits_fread_ftable_data (missing[0].f, &ftable)) {
+    if (!gfits_fread_ftable_data (catalog[0].missing_catalog[0].f, &ftable)) {
       if (VERBOSE) fprintf (stderr, "can't read table missing data\n");
       return (FALSE);
     }
-    /* no conversions currently defined */
-    catalog[0].missing = gfits_table_get_Missing (&ftable, &catalog[0].Nmissing, NULL);
-    if (Nmissing != catalog[0].Nmissing) {
-      fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, catalog[0].Nmissing);
+    /* no conversions currently defined : this just does the byte swap */
+    catalog[0].missing = gfits_table_get_Missing (&ftable, &Nmissing, NULL);
+    if (Nmissing != catalog[0].Nmiss_disk) {
+      fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, catalog[0].Nmiss_disk);
     }
     gfits_free_header (&header);
     gfits_free_matrix (&matrix);
-  } 
-missing_empty:
-  catalog[0].missing_catalog = missing;
+    catalog[0].Nmissing = catalog[0].Nmiss_disk;
+    catalog[0].Nmiss_off = 0;
+  } else {
+    // XXX is it necessary to generate a template header here?
+    gfits_create_header (&catalog[0].missing_catalog[0].header);
+    ALLOCATE (catalog[0].missing, Missing, 1);
+    catalog[0].Nmissing = 0;
+    catalog[0].Nmiss_off = catalog[0].Nmiss_disk;
+  }
 
   /*** Secfilt Table ***/
-
-  secfilt = NULL;
-  if (catalog[0].catflags & LOAD_SECF) {
-    ALLOCATE (secfilt, Catalog, 1);
-    dvo_catalog_init (secfilt, TRUE);
-
-    /* get split filename from main header (paths relative to cpt file) */
-    if (!gfits_scan (&catalog[0].header, "SECFILT",  "%s", 1, string)) return (FALSE);
-    ALLOCATE (secfilt[0].filename, char, strlen(path) + strlen(string) + 2);
-    sprintf (secfilt[0].filename, "%s/%s", path, string);
-
-    /* lock & open catalog file */
-    if (dvo_catalog_lock (secfilt, catalog[0].lockmode) != 1) {
-      fprintf (stderr, "cannot access secfilt file %s\n", secfilt[0].filename);
-      exit (2);
-    }
-
-    /* read PHU */
-    if (!gfits_load_header (secfilt[0].f, &secfilt[0].header)) {
-      if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", secfilt[0].filename);
-      return (FALSE);
-    }
-    /* matrix should be empty */
-    if (!gfits_fread_matrix (secfilt[0].f, &matrix, &secfilt[0].header)) {
-      if (VERBOSE) fprintf (stderr, "can't read primary matrix\n");
-      return (FALSE);
-    }
-    /* read secfilt table header */
-    if (!gfits_fread_header (secfilt[0].f, &header)) {
-      if (VERBOSE) fprintf (stderr, "can't read table secfilt header\n");
-      return (FALSE);
-    }
+  status = dvo_catalog_open_subcat (catalog, &catalog[0].secfilt_catalog, "SECFILT");
+  if (status == DVO_CAT_OPEN_FAIL) {
+    return (FALSE);
+  }
+  if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nsecf_disk > 0)) {
+    return (FALSE);
+  }
+  if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_SECF)) {
     /* read secfilt table data */
     if (!gfits_fread_ftable_data (secfilt[0].f, &ftable)) {
@@ -229,8 +206,7 @@
       return (FALSE);
     }
-    Nexpect = catalog[0].Nsecfilt * catalog[0].Naverage;
     catalog[0].secfilt = FtableToSecFilt (&ftable, &Nitems, &catalog[0].catformat);
-    if (Nexpect != Nitems) {
-      fprintf (stderr, "Warning: mismatch between Nsecfilt items in PHU and Table headers (%d vs %d)\n", Nexpect, Nitems);
+    if (Nitems != catalog[0].Nsecf_disk) {
+      fprintf (stderr, "Warning: mismatch between Nsecfilt items in PHU and Table headers (%d vs %d)\n", Nitems, catalog[0].Nsecf_disk);
     }
 
@@ -243,5 +219,5 @@
       Ntmpfilt = catalog[0].Nsecfilt;
       Nsecfilt = catalog[0].Nsecfilt + 1;
-      Ntotal = Nsecfilt * catalog[0].Naverage;
+      Ntotal = Nsecfilt * catalog[0].Naves_disk;
       ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal);
       for (i = 0; i < catalog[0].Naverage; i++) {
@@ -252,16 +228,138 @@
       }		
       catalog[0].Nsecfilt = Nsecfilt;
+      catalog[0].Nsecf_disk = Ntotal;
       free (primary);
     } 
-
-
     gfits_free_header (&header);
     gfits_free_matrix (&matrix);
+    catalog[0].Nsecf_mem = catalog[0].Nsecf_disk;
+    catalog[0].Nsecf_off = 0;
   } else {
-    if (primary != NULL) free (primary);
-  }
-
-  catalog[0].secfilt_catalog = secfilt;
-
+    if (primary != NULL) {
+      free (primary);
+      catalog[0].Nsecfilt ++;
+      catalog[0].Nsecf_disk =  catalog[0].Nsecfilt * catalog[0].Naves_disk;
+    }
+    gfits_create_header (&catalog[0].secfilt_catalog[0].header);
+    ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+    catalog[0].Nsecf_mem = 0;
+    catalog[0].Nsecf_off = catalog[0].Nsecf_disk;
+  }
+
+  return (TRUE);
+}
+
+// XXX I either need to always read both average and secfilt at the same time, or 
+// do something sloppy to carry around the primary secfilt values...
+
+int dvo_catalog_load_segment_split_average (Catalog *catalog, int start, int Nrows) {
+
+  // XXX check the open status of the FILE *f?
+
+    /* move pointer past header -- must be already read (load_catalog) */
+    fseek (catalog[0].f, catalog[0].header.size, SEEK_SET);
+    /* matrix should be empty : XXX should we drop this step and skip the data? */
+    if (!gfits_fread_matrix (catalog[0].f, &matrix, &catalog[0].header)) {
+      if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+      return (FALSE);
+    }
+    /* read Average table header */
+    if (!gfits_fread_header (catalog[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average header");
+      return (FALSE);
+    }
+    /* read Average table data : format is irrelevant here */
+    if (!gfits_fread_vtable_range (catalog[0].f, &vtable, start, Nrows)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average data");
+      return (FALSE);
+    }
+
+    /* convert the saved version of the table to the internal version.  Old versions of DVO stored
+     * one of the average magnitudes in Average.  We save this in case it is needed below.  NOTE:
+     * primary is only used if we read in the secfilt table, otherwise it should be freed */
+
+    // XXX Vtable version is needed (merge Ftable and Vtable versions?)
+    catalog[0].average = VtableToAverage (&ftable, &Naverage, &catalog[0].catformat, &primary);
+
+    // XXX validate the sizes?  start + Nrows < Naves_disk (no other constraints)
+    if (Naverage != Nrows) {
+      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, Nrows);
+    }
+    gfits_free_header (&header);
+    catalog[0].Naverage = Naverage;
+    catalog[0].Naves_off = start;
+
+    return (TRUE);
+}
+
+int dvo_catalog_load_segment_split_measure (Catalog *catalog, int start, int Nrows) {
+
+  // XXX check the open status of the FILE *f?
+
+  Catalog *subcat = catalog[0].measure_catalog;
+
+  /* move pointer past header -- must be already read (load_catalog) */
+  fseek (subcat[0].f, subcat[0].header.size, SEEK_SET);
+  /* matrix should be empty : XXX should we drop this step and skip the data? */
+  if (!gfits_fread_matrix (subcat[0].f, &matrix, &subcat[0].header)) {
+    if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+    return (FALSE);
+  }
+  /* read Measure table header */
+  if (!gfits_fread_header (subcat[0].f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table measure header");
+    return (FALSE);
+  }
+  /* read Measure table data : format is irrelevant here */
+  if (!gfits_fread_vtable_range (subcat[0].f, &vtable, start, Nrows)) {
+    if (VERBOSE) fprintf (stderr, "can't read table measure data");
+    return (FALSE);
+  }
+
+  /* convert data format to internal : returns number of row read in Nmeasure */
+  catalog[0].measure = VtableToMeasure (&vtable, &Nmeasure, &catalog[0].catformat);
+  if (Nmeasure != Nrows) {
+    fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, Nrows);
+  }
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  catalog[0].Nmeasure = Nmeasure;
+  catalog[0].Nmeas_off = start;
+  return (TRUE);
+}
+
+int dvo_catalog_load_segment_split_missing (Catalog *catalog, int start, int Nrows) {
+
+  // XXX check the open status of the FILE *f?
+
+  Catalog *subcat = catalog[0].missing_catalog;
+
+  /* move pointer past header -- must be already read (load_catalog) */
+  fseek (subcat[0].f, subcat[0].header.size, SEEK_SET);
+  /* matrix should be empty : XXX should we drop this step and skip the data? */
+  if (!gfits_fread_matrix (subcat[0].f, &matrix, &subcat[0].header)) {
+    if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+    return (FALSE);
+  }
+  /* read Missing table header */
+  if (!gfits_fread_header (subcat[0].f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table missing header");
+    return (FALSE);
+  }
+  /* read Missing table data : format is irrelevant here */
+  if (!gfits_fread_vtable_range (subcat[0].f, &vtable, start, Nrows)) {
+    if (VERBOSE) fprintf (stderr, "can't read table missing data");
+    return (FALSE);
+  }
+
+  /* convert data format to internal : returns number of row read in Nmissing */
+  catalog[0].missing = VtableToMissing (&vtable, &Nmissing, &catalog[0].catformat);
+  if (Nmissing != Nrows) {
+    fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, Nrows);
+  }
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  catalog[0].Nmissing = Nmissing;
+  catalog[0].Nmiss_off = start;
   return (TRUE);
 }
@@ -346,6 +444,6 @@
     /* write out Average table (convert to FITS table format) */
     if (!AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat, primary)) {
-	fprintf (stderr, "trouble converting format\n");
-	goto failure;
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
     }
     if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
