Index: /trunk/Ohana/Makefile.in
===================================================================
--- /trunk/Ohana/Makefile.in	(revision 15742)
+++ /trunk/Ohana/Makefile.in	(revision 15743)
@@ -30,4 +30,5 @@
 addstar     \
 delstar     \
+dvosplit    \
 elixir      \
 gastro      \
Index: /trunk/Ohana/src/addstar/src/SEDfit.c
===================================================================
--- /trunk/Ohana/src/addstar/src/SEDfit.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/SEDfit.c	(revision 15743)
@@ -210,6 +210,7 @@
     }
   }
-  outcat[0].Naverage = Nave;
-  outcat[0].Nmeasure = Nmeas;
+  outcat[0].Naverage  = Nave;
+  outcat[0].Nmeasure  = Nmeas;
+  outcat[0].Nsecf_mem = Nave*Nsec;
   
   free (sourceValue.mags);
Index: /trunk/Ohana/src/addstar/src/UpdateDatabase_Image.c
===================================================================
--- /trunk/Ohana/src/addstar/src/UpdateDatabase_Image.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/UpdateDatabase_Image.c	(revision 15743)
@@ -13,5 +13,5 @@
 
   catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
-  if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MEAS_META | LOAD_MISS | LOAD_SECF;
+  if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
   
   // XXX this is probably not needed anymore
@@ -49,5 +49,5 @@
     catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
     catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
-    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MEAS_META | LOAD_MISS | LOAD_SECF;
+    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
 
     // an error exit status here is a significant error
@@ -57,7 +57,7 @@
     }
 
-    // Nave_disk == 0 implies an empty catalog file
+    // Naves_disk == 0 implies an empty catalog file
     // for only_match, skip empty catalogs 
-    if ((catalog.Nave_disk == 0) && options[0].only_match) {
+    if ((catalog.Naves_disk == 0) && options[0].only_match) {
       dvo_catalog_unlock (&catalog);
       dvo_catalog_free (&catalog);
@@ -73,5 +73,10 @@
     if (!options[0].only_images) {
       SetProtect (TRUE);
-      dvo_catalog_save (&catalog, VERBOSE);
+      if (options[0].update) {
+	catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
       SetProtect (FALSE);
     }
Index: /trunk/Ohana/src/addstar/src/UpdateDatabase_Refcat.c
===================================================================
--- /trunk/Ohana/src/addstar/src/UpdateDatabase_Refcat.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/UpdateDatabase_Refcat.c	(revision 15743)
@@ -37,5 +37,5 @@
     catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
     catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
-    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MEAS_META | LOAD_MISS | LOAD_SECF;
+    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
   
     // an error exit status here is a significant error
@@ -45,7 +45,7 @@
     }
 
-    // Nave_disk == 0 implies an empty catalog file
+    // Naves_disk == 0 implies an empty catalog file
     // for only_match, skip empty catalogs
-    if ((catalog.Nave_disk == 0) && options[0].only_match) {
+    if ((catalog.Naves_disk == 0) && options[0].only_match) {
       dvo_catalog_unlock (&catalog);
       dvo_catalog_free (&catalog);
@@ -62,5 +62,10 @@
     if (!options[0].only_images) {
       SetProtect (TRUE);
-      dvo_catalog_save (&catalog, VERBOSE);
+      if (options[0].update) {
+	catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
       SetProtect (FALSE);
     }
Index: /trunk/Ohana/src/addstar/src/UpdateDatabase_Reflist.c
===================================================================
--- /trunk/Ohana/src/addstar/src/UpdateDatabase_Reflist.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/UpdateDatabase_Reflist.c	(revision 15743)
@@ -37,5 +37,5 @@
     catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
     catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
-    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MEAS_META | LOAD_MISS | LOAD_SECF;
+    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
 
     // an error exit status here is a significant error
@@ -46,5 +46,5 @@
 
     /* for only_match, skip empty catalogs XXX EAM : this leaves behind empty files */
-    if ((catalog.Nave_disk == 0) && options[0].only_match) {
+    if ((catalog.Naves_disk == 0) && options[0].only_match) {
       dvo_catalog_unlock (&catalog);
       dvo_catalog_free (&catalog);
@@ -58,5 +58,10 @@
     if (!options[0].only_images) {
       SetProtect (TRUE);
-      dvo_catalog_save (&catalog, VERBOSE);
+      if (options[0].update) {
+	catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
       SetProtect (FALSE);
     }
Index: /trunk/Ohana/src/addstar/src/addstar.c
===================================================================
--- /trunk/Ohana/src/addstar/src/addstar.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/addstar.c	(revision 15743)
@@ -90,5 +90,5 @@
     catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
     catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
-    if (options.update) catalog.catflags = LOAD_AVES | LOAD_MEAS_META | LOAD_MISS | LOAD_SECF;
+    if (options.update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
 
     // open as read or write, depending on desire
@@ -105,7 +105,7 @@
     }
 
-    // Nave_disk == 0 implies an empty catalog file
+    // Naves_disk == 0 implies an empty catalog file
     // for only_match, skip empty catalogs
-    if ((catalog.Nave_disk == 0) && options.only_match) {
+    if ((catalog.Naves_disk == 0) && options.only_match) {
       dvo_catalog_unlock (&catalog);
       dvo_catalog_free (&catalog);
@@ -142,5 +142,10 @@
     if (Nsubset && !options.only_images) {
       SetProtect (TRUE);
-      dvo_catalog_save (&catalog, VERBOSE);
+      if (options.update) {
+	catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
       SetProtect (FALSE);
     }
Index: /trunk/Ohana/src/addstar/src/find_matches.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/find_matches.c	(revision 15743)
@@ -361,4 +361,5 @@
   catalog[0].Naverage = Nave;
   catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
   if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas: %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmatch);
 
Index: /trunk/Ohana/src/addstar/src/find_matches_closest.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_closest.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/find_matches_closest.c	(revision 15743)
@@ -362,4 +362,5 @@
   catalog[0].Naverage = Nave;
   catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
   if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas: %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmatch);
 
Index: /trunk/Ohana/src/addstar/src/find_matches_refstars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_refstars.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/find_matches_refstars.c	(revision 15743)
@@ -372,4 +372,5 @@
   catalog[0].Nmeasure = Nmeas;
   catalog[0].Nmissing = Nmiss;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
   if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas, Nmiss: %d %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmiss, Nmatch);
   return (Nmatch);
Index: /trunk/Ohana/src/addstar/src/load2mass_catalog.c
===================================================================
--- /trunk/Ohana/src/addstar/src/load2mass_catalog.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/load2mass_catalog.c	(revision 15743)
@@ -79,4 +79,5 @@
   catalog[0].Naverage = Nave;
   catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nsecf_mem = Nave*Nsec;
   return (TRUE);
 }
Index: /trunk/Ohana/src/addstar/src/sedstar.c
===================================================================
--- /trunk/Ohana/src/addstar/src/sedstar.c	(revision 15742)
+++ /trunk/Ohana/src/addstar/src/sedstar.c	(revision 15743)
@@ -34,6 +34,6 @@
     }
 
-    // Nave_disk == 0 implies an empty catalog file
-    if ((incatalog.Nave_disk == 0) && options.only_match) {
+    // Naves_disk == 0 implies an empty catalog file
+    if ((incatalog.Naves_disk == 0) && options.only_match) {
       if (VERBOSE) fprintf (stderr, "skipping empty region\n");
       dvo_catalog_unlock (&incatalog);
Index: /trunk/Ohana/src/delstar/src/delete_imagefile.c
===================================================================
--- /trunk/Ohana/src/delstar/src/delete_imagefile.c	(revision 15742)
+++ /trunk/Ohana/src/delstar/src/delete_imagefile.c	(revision 15743)
@@ -33,5 +33,5 @@
       exit (2);
     }
-    if (!catalog.Nave_disk) {
+    if (!catalog.Naves_disk) {
       dvo_catalog_unlock (&catalog);
       dvo_catalog_free (&catalog);
Index: /trunk/Ohana/src/delstar/src/delete_imagename.c
===================================================================
--- /trunk/Ohana/src/delstar/src/delete_imagename.c	(revision 15742)
+++ /trunk/Ohana/src/delstar/src/delete_imagename.c	(revision 15743)
@@ -44,5 +44,5 @@
 	exit (2);
       }
-      if (!catalog.Nave_disk) {
+      if (!catalog.Naves_disk) {
 	dvo_catalog_unlock (&catalog);
 	dvo_catalog_free (&catalog);
Index: /trunk/Ohana/src/delstar/src/delete_orphans.c
===================================================================
--- /trunk/Ohana/src/delstar/src/delete_orphans.c	(revision 15742)
+++ /trunk/Ohana/src/delstar/src/delete_orphans.c	(revision 15743)
@@ -252,4 +252,6 @@
   catalog.Nmeasure = Nmeas;
   catalog.Nmissing = Nmiss;
+  catalog.Nsecf_mem = Nave*Nsecfilt;
+
   if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
 
Index: /trunk/Ohana/src/delstar/src/delete_times.c
===================================================================
--- /trunk/Ohana/src/delstar/src/delete_times.c	(revision 15742)
+++ /trunk/Ohana/src/delstar/src/delete_times.c	(revision 15743)
@@ -64,5 +64,5 @@
       exit (2);
     }
-    if (!catalog.Nave_disk) {
+    if (!catalog.Naves_disk) {
       dvo_catalog_unlock (&catalog);
       dvo_catalog_free (&catalog);
Index: /trunk/Ohana/src/delstar/src/find_matches.c
===================================================================
--- /trunk/Ohana/src/delstar/src/find_matches.c	(revision 15742)
+++ /trunk/Ohana/src/delstar/src/find_matches.c	(revision 15743)
@@ -234,4 +234,6 @@
   catalog[0].Nmeasure = Nmeas;
   catalog[0].Nmissing = Nmiss;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
+
   if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
 
Index: /trunk/Ohana/src/dvosplit/Makefile
===================================================================
--- /trunk/Ohana/src/dvosplit/Makefile	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/Makefile	(revision 15743)
@@ -0,0 +1,48 @@
+default: dvosplit
+help:
+	@echo "make options: dvosplit (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/dvosplit
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+dvosplit     : $(BIN)/dvosplit.$(ARCH)
+all: dvosplit
+
+DVOSPLIT = \
+$(SRC)/dvosplit.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/args.$(ARCH).o \
+$(SRC)/split_averages.$(ARCH).o \
+$(SRC)/split_measures.$(ARCH).o \
+$(SRC)/open_output_catalogs.$(ARCH).o
+
+$(DVOSPLIT)  : $(INC)/dvosplit.h
+
+$(BIN)/dvosplit.$(ARCH) : $(DVOSPLIT)
+
+INSTALL = dvosplit
+
+# dependancy rules for binary code #########################
+$(INSTALL): % : $(BIN)/%.$(ARCH)
+
+%.clean :
+	rm -f $(BIN)/$*.$(ARCH)
+
+%.install:
+	make $(DESTBIN)/$*
+
+install:
+	for i in $(INSTALL); do make $$i.install || exit; done
Index: /trunk/Ohana/src/dvosplit/include/dvosplit.h
===================================================================
--- /trunk/Ohana/src/dvosplit/include/dvosplit.h	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/include/dvosplit.h	(revision 15743)
@@ -0,0 +1,41 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+# include <sys/time.h>
+# include <time.h>
+# include <zlib.h>
+
+/* solaris requires both of these instead of ip.h:
+   # include <sys/socket.h>
+   # include <netinet/in.h>
+*/
+
+/* linux is happy with this, not solaris */
+# include <netinet/ip.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+# include <glob.h>
+
+typedef struct {
+  int *outref;
+  int *outcat;
+} AveLinks;
+
+int    VERBOSE;
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+
+SkyRegion UserPatch;  // used by MODE CAT
+
+int        main                   PROTO((int argc, char **argv));
+
+int        ConfigInit             PROTO((int *argc, char **argv));
+int        SetSignals             PROTO(());
+void       SetProtect             PROTO((int mode));
+void       TrapSignal             PROTO((int sig));
+int        args                   PROTO((int argc, char **argv));
+
+Catalog   *open_output_catalogs   PROTO((SkyList *outlist));
+AveLinks  *split_averages         PROTO((Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs));
+int        split_measures         PROTO((Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs, AveLinks *avelinks));
Index: /trunk/Ohana/src/dvosplit/src/ConfigInit.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/ConfigInit.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/ConfigInit.c	(revision 15743)
@@ -0,0 +1,57 @@
+# include "dvosplit.h"
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+
+int ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  GetConfig (config, "CATDIR",                 	"%s",  0, CATDIR);
+  GetConfig (config, "PHOTCODE_FILE",          	"%s",  0, MasterPhotcodeFile);
+
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+
+  /* default mode, format, if not specified */
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+  return (TRUE);
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /trunk/Ohana/src/dvosplit/src/SetSignals.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/SetSignals.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/SetSignals.c	(revision 15743)
@@ -0,0 +1,122 @@
+# include "dvosplit.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect these signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored (POSIX.1-1990) */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored (POSIX.1-1990) */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore (POSIX.1-1990) */
+    case SIGCONT:    /* continue - maintain this action (POSIX.1-1990) */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? (POSIX.1-1990) */
+    case SIGURG:     /* socket signal, ignore this (POSIX.1-2001) */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /trunk/Ohana/src/dvosplit/src/Shutdown.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/Shutdown.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/Shutdown.c	(revision 15743)
@@ -0,0 +1,20 @@
+# include "dvosplit.h"
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format) + 2);
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
Index: /trunk/Ohana/src/dvosplit/src/args.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/args.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/args.c	(revision 15743)
@@ -0,0 +1,87 @@
+# include "dvosplit.h"
+static void help (void);
+
+int args (int argc, char **argv) {
+  
+  int i, N, CONFIRM;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /*** check for command line options ***/
+
+  /*** provide additional data ***/ 
+  /* restrict to a portion of the sky? (REFCAT only) */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  CONFIRM = TRUE;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    CONFIRM = FALSE;
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc == 2) {
+    if (CONFIRM) {
+      fprintf (stderr, "you are splitting the entire sky in one pass\n");
+      fprintf (stderr, "this could be a time consuming operation.  type Ctrl-C within 5 seconds to cancel\n");
+      for (i = 5; i > 0; i--) {
+	fprintf (stderr, "%d.. ", i);
+	usleep (1000000);
+      }
+      fprintf (stderr, "\n");
+    }    
+    return (TRUE);
+  }
+
+  fprintf (stderr, "USAGE: dvosplit (newlevel) [-region (Rmin) (Rmax) (Dmin) (Dmax)]\n");
+  exit (2);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  dvosplit (newlevel)\n\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -region ra ra dec dec 	  : migrate catalogs in specified region\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
+
+/** addstar modes:
+ 
+    addstar (image.smp)  - add cmp/smp image data to db
+    addstar -ref (file.dat) (photcode) 
+    addstar -cat (USNO/2MASS/GSC) -region (ra dec - ra dec)
+
+    -replace : ref/cat - replace existing match (photcode/time)
+    -match   : ref/cat - only add measures to existing averages
+
+    ref types: 
+    ASCII - RA,DEC,M,dM in a table
+
+    addstar 
+
+**/
+
Index: /trunk/Ohana/src/dvosplit/src/dvosplit.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/dvosplit.c	(revision 15742)
+++ /trunk/Ohana/src/dvosplit/src/dvosplit.c	(revision 15743)
@@ -1,11 +1,19 @@
 # include "dvosplit.h"
-# define NROWS 100000 /* ~10MB per row for measures */
 
+// dvosplit (outlevel) [-region Rmin Rmax Dmin Dmax]
 int main (int argc, char **argv) {
 
-  // USAGE: dvosplit (outlevel) [-region RA RA DEC DEC]
+  int i, j, OUT_DEPTH;
+  SkyTable *sky;
+  SkyList *skylist, *outlist;
+  Catalog incatalog, *outcatalogs;
+  AveLinks *avelinks;
+  char filename[256];
 
-  // the output catalog needs to inherit the SKY_DEPTH of the input catalog. 
-  // if the CATDIR/SkyTable.fits is not found, assume the HST layout (old default)
+  SetSignals ();
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  OUT_DEPTH = atoi (argv[1]);
 
   // load the sky table for the existing database
@@ -13,11 +21,6 @@
   SkyTableSetFilenames (sky, CATDIR, "cpt");
 
-  // XXX I should just be copying the input sky and setting the output names on that
-  // load the sky table for the existing database, generate output names
-  outsky = SkyTableLoadOptimal (CATDIR, NULL, NULL, SKY_DEPTH_HST, VERBOSE);
-  SkyTableSetFilenames (outsky, OUTDIR, "cpt");
-
   // get the list of populated regions
-  skylist  = SkyListByPatch (sky, -1, &REGION);
+  skylist  = SkyListByPatch (sky, -1, &UserPatch);
   
   for (i = 0; i < skylist[0].Nregions; i++) {
@@ -27,6 +30,4 @@
     // if (current level == out level) skip: no action is needed
     if (skylist[0].regions[i][0].depth >= OUT_DEPTH) continue;
-
-    outlist = SkyListByPatch (outsky, OUT_DEPTH, skylist[0].regions[i]);
 
     // set the parameters which guide catalog open/load/create
@@ -42,5 +43,5 @@
 
     // skip empty input catalogs
-    if (!incatalog.Nave_disk) {
+    if (!incatalog.Naves_disk) {
       dvo_catalog_unlock (&incatalog);
       dvo_catalog_free (&incatalog);
@@ -48,93 +49,38 @@
     }
 
-    outcatalog = SkyTableSubdivide (&incatalog, &Noutcatalog);
+    // change sky.regions[i].depth for these regions
+    outlist = SkyListByPatch (sky, OUT_DEPTH, skylist[0].regions[i]);
 
-    // split out the average entries:
-    incatalog.catflags = LOAD_AVES;
-    Nblocks = incatalog.Nave_disk / NROWS;
-    for (j = 0; j < Nblocks; j++) {
+    outcatalogs = open_output_catalogs (outlist);
 
-      // read up to NROWS at a time
-      dvo_catalog_load_segment (&incatalog, VERBOSE, j*NROWS, NROWS);
+    avelinks = split_averages (&incatalog, outlist, outcatalogs); 
 
-      for (k = 0; k < incatalog.Naverage; k++) {
-	averef = j*NROWS + k;
-	
-	inR  = incatalog.average[k].R;
-	inD = incatalog.average[k].D;
+    split_measures (&incatalog, outlist, outcatalogs, avelinks); 
 
-	// which of the outcatalogs contains this coordinate?
+    // XXX missing entries have to be reconstructed if they are desired
+    // split_missings (&incatalog, outlist, outcatalogs, avelinks); 
 
-	N = -1;
-	for (n = 0; n < Noutcatalog; n++) {
-	  if (inR < outregions[n].Rmin) continue;
-	  if (inR > outregions[n].Rmax) continue;
-	  if (inD < outregions[n].Dmin) continue;
-	  if (inD > outregions[n].Dmax) continue;
-	  Ncat = n;
-	  break;
-	}
-	if (Ncat == -1) continue;
+    dvo_catalog_unlock (&incatalog);
 
-	// XXX this probably needs to be Nave_disk so we can have partial saves
-	Nout = outcatalog[Ncat].Naverage;
-	outref[averef] = Nout;
-	outcat[averef] = Ncat;
-
-	outcatalog[Ncat].average[Nout] = incatalog.average[k];
-	outcatalog[Ncat].Naverage++;
-      }
-
-      for (n = 0; n < Noutcatalog; n++) {
-	dvo_catalog_save_segment (&outcatalog[Ncat], VERBOSE, outcatalog[Ncat].Nave_disk, outcatalog[Ncat].Naverage);
-      }
+    for (j = 0; j < outlist[0].Nregions; j++) {
+      dvo_catalog_unlock (&outcatalogs[j]);
     }
 
-    // split out the measure entries:
-    incatalog.catflags = LOAD_MEAS;
-    Nblocks = incatalog.Nmeas_disk / NROWS;
-    for (j = 0; j < Nblocks; j++) {
-
-      // read up to NROWS at a time
-      dvo_catalog_load_segment (&incatalog, VERBOSE, j*NROWS, NROWS);
-
-      for (k = 0; k < incatalog.Nmeasure; k++) {
-
-	averef = incatalog.measure[k].averef;
-	Ncat = outcat[averef];
-
-	Nout = outcatalog[Ncat].Nmeasure;
-	outcatalog[Ncat].measure[Nout] = incatalog.measure[k];
-	outcatalog[Ncat].measure[Nout].averef = outref[averef];
-	outcatalog[Ncat].Nmeasure++;
-      }
-
-      for (n = 0; n < Noutcatalog; n++) {
-	dvo_catalog_save_segment (&outcatalog[N], VERBOSE, outcatalog[N].Nmeas_disk, outcatalog[N].Nmeasure);
-      }
+    // adjust depth
+    skylist[0].regions[i][0].table = FALSE;
+    for (j = 0; j < outlist[0].Nregions; j++) {
+      outlist[0].regions[j][0].table = TRUE;
     }
 
-    // split out the secfilt entries:
-    incatalog.catflags = LOAD_SECF;
-    Nblocks = incatalog.Nsecfilt_disk / NROWS;
-    for (j = 0; j < Nblocks; j++) {
+  }
 
-      // read up to NROWS at a time
-      dvo_catalog_load_segment (&incatalog, VERBOSE, j*NROWS, NROWS);
+  // save sky table copy
+  sprintf (filename, "%s/SkyTable.fits", CATDIR);
+  check_file_access (filename, FALSE, VERBOSE);
+  if (!SkyTableSave (sky, filename)) {
+    fprintf (stderr, "ERROR: failed to save sky table for %s\n", CATDIR);
+    exit (1);
+  }
 
-      for (k = 0; k < incatalog.Naverage; k++) {
-
-	averef = j*NROWS + k;
-	Ncat = outcat[averef];
-	Nout = outref[averef] * Nsecfilt;
-
-	for (n = 0; n < Nsecfilt; n++) {
-	  outcatalog[Ncat].secfilt[Nout + n] = incatalog.measure[k*Nsecfilt + n];
-	}
-      }
-
-      for (n = 0; n < Noutcatalog; n++) {
-	dvo_catalog_save_segment (&outcatalog[N], VERBOSE, outcatalog[N].Nmeas_disk, outcatalog[N].Nmeasure);
-      }
-    }
-
+  exit (0);
+}
Index: /trunk/Ohana/src/dvosplit/src/open_output_catalogs.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/open_output_catalogs.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/open_output_catalogs.c	(revision 15743)
@@ -0,0 +1,27 @@
+# include "dvosplit.h"
+
+Catalog *open_output_catalogs (SkyList *outlist) {
+
+  int i;
+  Catalog *outcatalogs;
+
+  ALLOCATE (outcatalogs, Catalog, outlist[0].Nregions);
+
+  // an error exit status here is a significant error
+  for (i = 0; i < outlist[0].Nregions; i++) {
+    
+    // set the parameters which guide catalog open/load/create
+    outcatalogs[i].filename  = outlist[0].filename[i];
+    outcatalogs[i].Nsecfilt  = GetPhotcodeNsecfilt ();
+    outcatalogs[i].catflags  = LOAD_NONE;
+    outcatalogs[i].catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    outcatalogs[i].catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+
+    if (!dvo_catalog_open (&outcatalogs[i], outlist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", outcatalogs[i].filename);
+      exit (2);
+    }
+  }
+  
+  return (outcatalogs);
+}
Index: /trunk/Ohana/src/dvosplit/src/split_averages.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/split_averages.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/split_averages.c	(revision 15743)
@@ -0,0 +1,99 @@
+# include "dvosplit.h"
+# define NROWS 100000 /* ~10MB per block for measures */
+
+AveLinks *split_averages (Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs) {
+
+  double inR, inD;
+  int n, block, ave, cat, averef, Nblocks, Ncat, Nout, Nsecfilt;
+  int *outref, *outcat;
+  AveLinks *avelinks;
+
+  ALLOCATE (outref, int, incatalog[0].Naves_disk);
+  ALLOCATE (outcat, int, incatalog[0].Naves_disk);
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  // allocate enough space for these output buffers: use Nsecfilt + 1 incase the file
+  // contains primary photcodes, which will increase Nsecfilt by one.
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    REALLOCATE (outcatalogs[cat].average, Average, NROWS);
+    REALLOCATE (outcatalogs[cat].secfilt, SecFilt, NROWS*(Nsecfilt + 1));
+  }
+
+  // split out the average & secfilt entries:
+  incatalog[0].catflags = LOAD_AVES | LOAD_SECF;
+  Nblocks = incatalog[0].Naves_disk / NROWS;
+  if (incatalog[0].Naves_disk % NROWS) Nblocks ++;
+  for (block = 0; block < Nblocks; block++) {
+
+    // read up to NROWS at a time
+    dvo_catalog_load_segment (incatalog, VERBOSE, block*NROWS, NROWS);
+    assert (block*NROWS == incatalog[0].Naves_off);
+
+    for (ave = 0; ave < incatalog[0].Naverage; ave++) {
+      averef = ave + incatalog[0].Naves_off;
+	
+      inR = incatalog[0].average[ave].R;
+      inD = incatalog[0].average[ave].D;
+
+      // which of the outcatalogs contains this coordinate?
+
+      Ncat = -1;
+      for (cat = 0; cat < outlist[0].Nregions; cat++) {
+	if (inR < outlist[0].regions[cat][0].Rmin) continue;
+	if (inR > outlist[0].regions[cat][0].Rmax) continue;
+	if (inD < outlist[0].regions[cat][0].Dmin) continue;
+	if (inD > outlist[0].regions[cat][0].Dmax) continue;
+	Ncat = cat;
+	break;
+      }
+
+      if (Ncat == -1) {
+	fprintf (stderr, "WARNING: missed %d (%f, %f)\n", averef, inR, inD);
+	continue;
+      }
+
+      Nout = outcatalogs[Ncat].Naverage;
+      outref[averef] = Nout + outcatalogs[Ncat].Naves_off;
+      outcat[averef] = Ncat;
+
+      // assign the value to the next element of the output catalog
+      outcatalogs[Ncat].average[Nout] = incatalog[0].average[ave];
+      outcatalogs[Ncat].Naverage ++;
+
+      // update secfilt at the same time
+      for (n = 0; n < Nsecfilt; n++) {
+	outcatalogs[Ncat].secfilt[Nout*Nsecfilt + n] = incatalog[0].secfilt[ave*Nsecfilt + n];
+	outcatalogs[Ncat].Nsecf_mem++;
+      }
+    }
+
+    // double check the values of Naverage, Nsecf_mem?
+
+    // write out the new values
+    for (cat = 0; cat < outlist[0].Nregions; cat++) {
+      outcatalogs[cat].catflags = LOAD_AVES | LOAD_SECF;
+
+      fprintf (stderr, "secfilt: %d %d %d %d\n", outcatalogs[cat].Nsecf_mem, outcatalogs[cat].Nsecf_disk, outcatalogs[cat].Nsecf_off, outcatalogs[cat].Naverage, outcatalogs[cat].Nsecfilt);
+      dvo_catalog_save (&outcatalogs[cat], VERBOSE);
+      fprintf (stderr, "secfilt: %d %d %d %d\n", outcatalogs[cat].Nsecf_mem, outcatalogs[cat].Nsecf_disk, outcatalogs[cat].Nsecf_off, outcatalogs[cat].Naverage, outcatalogs[cat].Nsecfilt);
+
+      // XXX I need to advance the pointers and free the current data
+      // XXX these should be done within save segment:
+      outcatalogs[cat].Naves_disk += outcatalogs[cat].Naverage;
+      outcatalogs[cat].Naves_off  += outcatalogs[cat].Naverage;
+      outcatalogs[cat].Nsecf_disk += outcatalogs[cat].Nsecfilt * outcatalogs[cat].Naverage;
+      outcatalogs[cat].Nsecf_off  += outcatalogs[cat].Nsecfilt * outcatalogs[cat].Naverage;
+      outcatalogs[cat].Nsecfilt    = Nsecfilt;
+
+      outcatalogs[cat].Naverage    = 0;
+      outcatalogs[cat].Nsecf_mem   = 0;
+    }
+  }
+
+  ALLOCATE (avelinks, AveLinks, 1);
+  avelinks[0].outref = outref;
+  avelinks[0].outcat = outcat;
+
+  return (avelinks);
+}
Index: /trunk/Ohana/src/dvosplit/src/split_measures.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/split_measures.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/split_measures.c	(revision 15743)
@@ -0,0 +1,48 @@
+# include "dvosplit.h"
+# define NROWS 100000 /* ~10MB per row for measures */
+
+int split_measures (Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs, AveLinks *avelinks) {
+
+  int block, meas, cat, Nblocks, Ncat, Nout, averef;
+  int *outref, *outcat;
+
+  outref = avelinks->outref;
+  outcat = avelinks->outcat;
+
+  // allocate enough space for the output buffer
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    REALLOCATE (outcatalogs[cat].measure, Measure, NROWS);
+  }
+
+  // split out the measure entries:
+  incatalog[0].catflags = LOAD_MEAS;
+  Nblocks = incatalog[0].Nmeas_disk / NROWS;
+  if (incatalog[0].Nmeas_disk % NROWS) Nblocks ++;
+  for (block = 0; block < Nblocks; block++) {
+
+    // read up to NROWS at a time
+    dvo_catalog_load_segment (incatalog, VERBOSE, block*NROWS, NROWS);
+
+    for (meas = 0; meas < incatalog[0].Nmeasure; meas++) {
+
+      averef = incatalog[0].measure[meas].averef;
+      Ncat = outcat[averef];
+
+      Nout = outcatalogs[Ncat].Nmeasure;
+      outcatalogs[Ncat].measure[Nout] = incatalog[0].measure[meas];
+      outcatalogs[Ncat].measure[Nout].averef = outref[averef];
+      outcatalogs[Ncat].Nmeasure++;
+    }
+
+    for (cat = 0; cat < outlist[0].Nregions; cat++) {
+      outcatalogs[cat].catflags = LOAD_MEAS;
+      dvo_catalog_save (&outcatalogs[cat], VERBOSE);
+
+      outcatalogs[cat].Nmeas_disk += outcatalogs[cat].Nmeasure;
+      outcatalogs[cat].Nmeas_off  += outcatalogs[cat].Nmeasure;
+      outcatalogs[cat].Nmeasure    = 0;
+
+    }
+  }
+  return (TRUE);
+}
Index: /trunk/Ohana/src/dvosplit/src/split_missings.c
===================================================================
--- /trunk/Ohana/src/dvosplit/src/split_missings.c	(revision 15743)
+++ /trunk/Ohana/src/dvosplit/src/split_missings.c	(revision 15743)
@@ -0,0 +1,47 @@
+# include "dvosplit.h"
+# define NROWS 100000 /* ~10MB per row for missings */
+
+int split_missings (Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs, AveLinks *avelinks) {
+
+  int *outref, *outcat;
+
+  outref = avelinks->outref;
+  outcat = avelinks->outcat;
+
+  // allocate enough space for the output buffer
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    REALLOCATE (outcatalog[cat].missing, Missing, NROWS);
+  }
+
+  // split out the missing entries:
+  incatalog[0].catflags = LOAD_MISS;
+  Nblocks = incatalog[0].Nmiss_disk / NROWS;
+  if (incatalog[0].Nmiss_disk % NROWS) Nblocks ++;
+  for (block = 0; block < Nblocks; block++) {
+
+    // read up to NROWS at a time
+    dvo_catalog_load_segment (incatalog, VERBOSE, block*NROWS, NROWS);
+
+    for (miss = 0; miss < incatalog[0].Nmissing; miss++) {
+
+      averef = incatalog[0].missing[miss].averef;
+      Ncat = outcat[averef];
+
+      Nout = outcatalog[Ncat].Nmissing;
+      outcatalog[Ncat].missing[Nout] = incatalog[0].missing[miss];
+      outcatalog[Ncat].missing[Nout].averef = outref[averef];
+      outcatalog[Ncat].Nmissing++;
+    }
+
+    for (cat = 0; cat < outlist[0].Nregions; cat++) {
+      outcatalogs[cat].catflags = LOAD_MISS;
+      dvo_catalog_save_segment (&outcatalog[cat], VERBOSE);
+
+      outcatalog[cat].Nmiss_disk += outcatalog[cat].Nmissing;
+      outcatalog[cat].Nmiss_off  += outcatalog[cat].Nmissing;
+      outcatalog[cat].Nmissing    = 0;
+
+    }
+  }
+  return (TRUE);
+}
Index: /trunk/Ohana/src/gastro/src/getptolemy.c
===================================================================
--- /trunk/Ohana/src/gastro/src/getptolemy.c	(revision 15742)
+++ /trunk/Ohana/src/gastro/src/getptolemy.c	(revision 15743)
@@ -36,7 +36,7 @@
     dvo_catalog_unlock (&catalog);
 
-    // Nave_disk == 0 implies an empty catalog file
+    // Naves_disk == 0 implies an empty catalog file
     // for only_match, skip empty catalogs
-    if (!catalog.Nave_disk) {
+    if (!catalog.Naves_disk) {
       dvo_catalog_free (&catalog);
       continue;
Index: /trunk/Ohana/src/gastro2/src/getptolemy.c
===================================================================
--- /trunk/Ohana/src/gastro2/src/getptolemy.c	(revision 15742)
+++ /trunk/Ohana/src/gastro2/src/getptolemy.c	(revision 15743)
@@ -38,7 +38,7 @@
     dvo_catalog_unlock (&catalog);
 
-    // Nave_disk == 0 implies an empty catalog file
+    // Naves_disk == 0 implies an empty catalog file
     // for only_match, skip empty catalogs
-    if (!catalog.Nave_disk) {
+    if (!catalog.Naves_disk) {
       dvo_catalog_free (&catalog);
       continue;
Index: /trunk/Ohana/src/getstar/src/getstar.c
===================================================================
--- /trunk/Ohana/src/getstar/src/getstar.c	(revision 15742)
+++ /trunk/Ohana/src/getstar/src/getstar.c	(revision 15743)
@@ -21,4 +21,5 @@
   output.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
   output.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+  output.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
   output.Nsecfilt  = GetPhotcodeNsecfilt ();
 
@@ -47,5 +48,5 @@
 	  exit (2);
 	}
-	if (!catalog.Nave_disk) {
+	if (!catalog.Naves_disk) {
 	  dvo_catalog_unlock (&catalog);
 	  dvo_catalog_free (&catalog);
@@ -78,5 +79,5 @@
 	}
 	/* skip empty catalogs */
-	if (!catalog.Nave_disk) continue;
+	if (!catalog.Naves_disk) continue;
 	stars = select_by_image (&catalog, &image, 0, 0, stars, &Nstars);
       }
Index: /trunk/Ohana/src/getstar/src/select_by_region.c
===================================================================
--- /trunk/Ohana/src/getstar/src/select_by_region.c	(revision 15742)
+++ /trunk/Ohana/src/getstar/src/select_by_region.c	(revision 15743)
@@ -91,4 +91,6 @@
   output[0].Naverage = Nave;
   output[0].Nmeasure = Nmeas;
+  output[0].Nsecf_mem = Nave*Nsecfilt;
+
   fprintf (stderr, "output catalog has %d stars (%d measures, %d secfilt)\n",
 	   output[0].Naverage, output[0].Nmeasure, output[0].Nsecfilt);
Index: /trunk/Ohana/src/libdvo/doc/dvo-catalogs.txt
===================================================================
--- /trunk/Ohana/src/libdvo/doc/dvo-catalogs.txt	(revision 15742)
+++ /trunk/Ohana/src/libdvo/doc/dvo-catalogs.txt	(revision 15743)
@@ -2,12 +2,5 @@
 // APIs related to the DVO catalogs:
 
-// XXX change name
-// XXX add SORTED test to load
-// XXX add Nsecfilt test? or add an API?
 load_catalog (Catalog *catalog, int VERBOSE);
-// returns
-//   0: failure to lock catalog
-//   1: success: file is locked and opened
-//   2: success: file is locked but empty
 
 dvo_catalog_lock (Catalog *catalog, int lockmode);
@@ -20,4 +13,16 @@
 // layout: RAW, MEF, SPLIT
 // mode:   READ, WRITE
+
+// returns
+//   DVO_CAT_OPEN_FAIL:  failure to lock catalog
+//   DVO_CAT_OPEN_OK:    success: file is locked and opened
+//   DVO_CAT_OPEN_EMPTY: success: file is locked but empty
+
+ the catalog is opened and the data for each of the elements (average,
+ measure, etc) is loaded if requested.  Whether or not the data is
+ loaded, the values of catalog.Naves_disk,Naves_off,Naverage are set
+ to match the segment of data loaded.  this API always loads either
+ the entire data set, or none.  If none, the offset value is set to
+ point at the end of the table.
 
 dvo_catalog_save (Catalog *catalog, int VERBOSE);
@@ -43,4 +48,23 @@
 - open and read an existing catalog / error if missing (can be ignored)
 
+dvo_catalog_open (Catalog *catalog, int mode); 
 
-dvo_catalog_open (Catalog *catalog, int mode); 
+dvo_catalog_load_segment_average (Catalog *catalog, int start, int Nrows)
+
+ this function reads in the requested number of rows from the catalog
+ for the Average and SecFilt tables only.  It is possible within the
+ DVO framework to examine the average values in slices.  
+
+dvo_catalog_load_segment_measure (Catalog *catalog, int start, int Nrows)
+
+ this function reads in the requested number of rows from the catalog
+ for the Measure table only.  It is not guaranteed to be possible to
+ examine the measure values in slices if reference is needed to their
+ average values.
+
+dvo_catalog_load_segment_missing (Catalog *catalog, int start, int Nrows)
+
+ this function reads in the requested number of rows from the catalog
+ for the Missing table only.  It is not guaranteed to be possible to
+ examine the missing values in slices if reference is needed to their
+ average values.
Index: /trunk/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /trunk/Ohana/src/libdvo/include/dvo.h	(revision 15742)
+++ /trunk/Ohana/src/libdvo/include/dvo.h	(revision 15743)
@@ -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} DVOCatalogOpenModes;
 
 typedef enum {
@@ -195,8 +197,16 @@
   Missing *missing; 
   SecFilt *secfilt;
-  int Naverage, Nmeasure, Nmissing, Nsecfilt;   /* current number of each component */
-  int Nave_disk, Nmeas_disk, Nmiss_disk;        /* number of component on disk */
-  int Nmeas_off;			        /* dist seq of first loaded data value */
-  /* note the different counting for Nsecfilt */
+
+  int Nsecfilt;  /* number of secfilt entries for each average entry */
+  int Naverage,   Nmeasure,   Nmissing,   Nsecf_mem;  /* current number of each component in memory */
+  int Naves_disk, Nmeas_disk, Nmiss_disk, Nsecf_disk; /* current number of each component on disk */
+  int Naves_off,  Nmeas_off,  Nmiss_off,  Nsecf_off;  /* index of first loaded data value */
+
+  /* note the different counting for Nsecfilt:
+     number of secfilt rows on disk is: Nave_disk * Nsecfilt
+     number of secfilt rows in mem  is: Naverage * Nsecfilt
+     *** that is just silly, and bad: convert to using Nsec_mem, Nsec_disk, Nsec_off.
+     *** unless we always require the secfilt and average entries to be loaded sychronously.
+   */
 
   /* pointers to split data files */
Index: /trunk/Ohana/src/libdvo/src/dvo_catalog.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_catalog.c	(revision 15742)
+++ /trunk/Ohana/src/libdvo/src/dvo_catalog.c	(revision 15743)
@@ -90,9 +90,15 @@
   catalog[0].Nmeasure = 0;
   catalog[0].Nmissing = 0;
-
-  catalog[0].Nave_disk  = 0;
+  catalog[0].Nsecf_mem = 0;
+
+  catalog[0].Naves_disk = 0;
   catalog[0].Nmeas_disk = 0;
   catalog[0].Nmiss_disk = 0;
+  catalog[0].Nsecf_disk = 0;
+
+  catalog[0].Naves_off  = 0;
   catalog[0].Nmeas_off  = 0;
+  catalog[0].Nmiss_off  = 0;
+  catalog[0].Nsecf_off  = 0;
 
   /* pointers to SPLIT data files */
@@ -110,7 +116,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 +131,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 +198,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 +212,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;
@@ -235,10 +241,4 @@
   if (!status) catalog[0].sorted = TRUE;
 
-  // even if the data is sorted on disk, if we only load the MEAS_META, we are
-  // treating it as unsorted (eg, append only)
-  if (catalog[0].catflags & LOAD_MEAS_META) {
-      catalog[0].sorted = FALSE;
-  }
-
   // determine catmode
   if (!gfits_scan (&catalog[0].header, "NAXIS", "%d", 1, &Naxis)) {
@@ -275,5 +275,7 @@
 }
 
-// write out the data, unlink if empty?
+// write out the data, unlink if empty?  'save' means: write out all data currently in
+// memory.  NOTE: this is currently not always possible: for non-SPLIT moe files, this
+// operation may require expanding the file size, which does not automatically happen
 int dvo_catalog_save (Catalog *catalog, char VERBOSE) {
 
@@ -281,11 +283,5 @@
   gfits_modify (&catalog[0].header, "SORTED",  "%t", 1, catalog[0].sorted);
 
-  if (catalog[0].Nmeas_off != 0) {
-    if (!dvo_catalog_update (catalog, VERBOSE)) {
-      return (FALSE);
-    } 
-    return (TRUE);
-  }
-
+  // XXX handle return status
   switch (catalog[0].catmode) {
     case DVO_MODE_RAW:
@@ -305,21 +301,22 @@
 }
 
+// write out the in-memory data which extends beyond the data on disk.  NOTE: this is
+// currently only possible for the SPLIT mode.
 int dvo_catalog_update (Catalog *catalog, char VERBOSE) {
+
+  // set the 'sorted' header keyword
+  catalog[0].sorted = FALSE;
+  gfits_modify (&catalog[0].header, "SORTED",  "%t", 1, catalog[0].sorted);
 
   /* update is only valid for catmode SPLIT */
   switch (catalog[0].catmode) {
     case DVO_MODE_RAW:
-      dvo_catalog_save_raw (catalog, VERBOSE);
+      fprintf (stderr, "not allowed for RAW mode\n");
       break;
     case DVO_MODE_MEF:
-      dvo_catalog_save_mef (catalog, VERBOSE);
+      fprintf (stderr, "not allowed for MEF mode\n");
       break;
     case DVO_MODE_SPLIT:
-      /* new file needs to use save_catalog_split */
-      if (catalog[0].Nave_disk == 0) {
-	dvo_catalog_save_split (catalog, VERBOSE);
-      } else {
-	dvo_catalog_update_split (catalog, VERBOSE);
-      }
+      dvo_catalog_update_split (catalog, VERBOSE);
       break;
     default:
@@ -360,4 +357,5 @@
     catalog[0].secfilt = outsec;
     catalog[0].Nsecfilt = Nsecfilt;
+    catalog[0].Nsecf_mem = Nsecfilt * catalog[0].Naverage;
   }
   return (TRUE);
@@ -396,2 +394,33 @@
   style  : raw, mef, split, mysql
 */
+
+int dvo_catalog_load_segment (Catalog *catalog, int VERBOSE, int start, int Nrows) {
+  
+  int Naxis, split, status;
+  char measure[80];
+
+  // catformat determined in dvo_catalog_load_XXX function
+  catalog[0].catformat = DVO_FORMAT_UNDEF;
+
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_RAW)\n");
+      fprintf (stderr, "cannot do this in raw mode\n");
+      // dvo_catalog_load_segment_raw (catalog, VERBOSE, start, Nrows);
+      break;
+    case DVO_MODE_MEF:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_MEF)\n");
+      fprintf (stderr, "cannot do this in mef mode\n");
+      // dvo_catalog_load_segment_mef (catalog, VERBOSE, start, Nrows);
+      break;
+    case DVO_MODE_SPLIT:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_SPLIT)\n");
+      dvo_catalog_load_segment_split (catalog, VERBOSE, start, Nrows);
+      break;
+    default:
+      fprintf (stderr, "error getting catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/libdvo/src/dvo_catalog_create.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 15742)
+++ /trunk/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 15743)
@@ -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: /trunk/Ohana/src/libdvo/src/dvo_catalog_mef.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_catalog_mef.c	(revision 15742)
+++ /trunk/Ohana/src/libdvo/src/dvo_catalog_mef.c	(revision 15743)
@@ -28,7 +28,19 @@
   if (!gfits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;
 
+  /* save the current number so we can do partial updates */
+  catalog[0].Naves_disk = Naverage;
+  catalog[0].Nmeas_disk = Nmeasure;
+  catalog[0].Nmiss_disk = Nmissing;
+  catalog[0].Nsecf_disk = Naverage * Nsecfilt;
+
   /**  Nsecfilt is unusual: it does not list the number of data items in the table
        instead, the number of items is Nsecfilt * Naverage.  **/
   catalog[0].Nsecfilt = Nsecfilt;
+
+  /* default values, but we will assign these a valid value before we exit (even if empty) */
+  catalog[0].average = NULL;
+  catalog[0].measure = NULL;
+  catalog[0].missing = NULL;
+  catalog[0].secfilt = NULL;
 
   /* validate table mode */
@@ -46,11 +58,16 @@
     }
     /* old versions of DVO stored one of the average magnitudes in Average. we save this if needed */
-    catalog[0].average = FtableToAverage (&ftable, &catalog[0].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);
-    }
+    catalog[0].average = FtableToAverage (&ftable, &Naverage, &catalog[0].catformat, &primary);
+    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);
+    }
+    catalog[0].Naverage = catalog[0].Naves_disk;
+    catalog[0].Naves_off = 0;
   } else {
     Nbytes = gfits_data_size (&header);
     fseek (f, Nbytes, SEEK_CUR);
+    ALLOCATE (catalog[0].average, Average, 1);
+    catalog[0].Naverage = 0;
+    catalog[0].Naves_off = catalog[0].Naves_disk;
   }
   gfits_free_header (&header);
@@ -69,10 +86,15 @@
     }
     catalog[0].measure = FtableToMeasure (&ftable, &catalog[0].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);
+    }
+    catalog[0].Nmeasure = catalog[0].Nmeas_disk;
+    catalog[0].Nmeas_off = 0;
   } else {
     Nbytes = gfits_data_size (&header);
     fseek (f, Nbytes, SEEK_CUR);
+    ALLOCATE (catalog[0].measure, Measure, 1);
+    catalog[0].Nmeasure = 0;
+    catalog[0].Nmeas_off = catalog[0].Nmeas_disk;
   }
 
@@ -90,10 +112,15 @@
     /* 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);
-    }
+    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);
+    }
+    catalog[0].Nmissing = catalog[0].Nmiss_disk;
+    catalog[0].Nmiss_off = 0;
   } else {
     Nbytes = gfits_data_size (&header);
     fseek (f, Nbytes, SEEK_CUR);
+    ALLOCATE (catalog[0].missing, Missing, 1);
+    catalog[0].Nmissing = 0;
+    catalog[0].Nmiss_off = catalog[0].Nmiss_disk;
   }
 
@@ -125,7 +152,7 @@
       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++) {
+      for (i = 0; i < catalog[0].Naves_disk; i++) {
 	catalog[0].secfilt[i*Nsecfilt + 0] = primary[i];
 	for (j = 0; j < Ntmpfilt; j++) {
@@ -134,18 +161,22 @@
       }		
       catalog[0].Nsecfilt = Nsecfilt;
+      catalog[0].Nsecf_disk = Ntotal;
       free (primary);
     } 
-
+    catalog[0].Nsecf_mem = catalog[0].Nsecf_disk;
+    catalog[0].Nsecf_off = 0;
   } else {
     /* no real need to skip the data array here... */
     Nbytes = gfits_data_size (&header);
     fseek (f, Nbytes, SEEK_CUR);
-    if (primary != NULL) free (primary);
-  }
-
-  /* save the current number so we can do partial updates */
-  catalog[0].Nave_disk  = catalog[0].Naverage;
-  catalog[0].Nmeas_disk = catalog[0].Nmeasure;
-  catalog[0].Nmiss_disk = catalog[0].Nmissing;
+    if (primary != NULL) {
+      free (primary);
+      catalog[0].Nsecfilt ++;
+      catalog[0].Nsecf_disk =  catalog[0].Nsecfilt * catalog[0].Naves_disk;
+    }
+    ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+    catalog[0].Nsecf_mem = 0;
+    catalog[0].Nsecf_off = catalog[0].Nsecf_disk;
+  }
 
   return (TRUE);
Index: /trunk/Ohana/src/libdvo/src/dvo_catalog_raw.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_catalog_raw.c	(revision 15742)
+++ /trunk/Ohana/src/libdvo/src/dvo_catalog_raw.c	(revision 15743)
@@ -171,4 +171,5 @@
       }		
       catalog[0].Nsecfilt = Nsecfilt;
+      catalog[0].Nsecf_mem = Ntotal;
       free (primary);
     } 
@@ -201,5 +202,5 @@
 
   /* save the current number so we can do partial updates */
-  catalog[0].Nave_disk  = catalog[0].Naverage;
+  catalog[0].Naves_disk = catalog[0].Naverage;
   catalog[0].Nmeas_disk = catalog[0].Nmeasure;
   catalog[0].Nmiss_disk = catalog[0].Nmissing;
Index: /trunk/Ohana/src/libdvo/src/dvo_catalog_split.c
===================================================================
--- /trunk/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 15742)
+++ /trunk/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 15743)
@@ -1,3 +1,155 @@
 # include <dvo.h>
+
+// return options: 
+// * error (cannot lock, open, read, etc)
+// * empty (file is not found)
+// * ok
+
+int dvo_catalog_secfilt_to_primary (Catalog *catalog, SecFilt **myPrimary, SecFilt **mySecfilt, int *myNsecfilt) {
+
+  int i, j, Nallfilt, Nsecfilt, Ntotal;
+
+  SecFilt *primary;
+  SecFilt *secfilt;
+
+  if (catalog[0].secfilt == NULL) {       
+    fprintf (stderr, "missing secfilt, cannot build output averages (dvo_catalog_split.c)\n");
+    exit (1);
+  }
+  secfilt = catalog[0].secfilt;
+
+  // XXX this translation only works if we have loaded / created a matched average/secfilt set
+  assert (catalog[0].Nsecf_mem == catalog[0].Nsecfilt*catalog[0].Naverage);
+
+  Nallfilt = catalog[0].Nsecfilt;
+  Nsecfilt = catalog[0].Nsecfilt - 1;
+  Ntotal = Nsecfilt * catalog[0].Naverage;
+  ALLOCATE (primary, SecFilt, catalog[0].Naverage);
+  ALLOCATE (secfilt, SecFilt, Ntotal);
+
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    primary[i] = secfilt[i*Nallfilt + 0];
+    for (j = 0; j < Nsecfilt; j++) {
+      secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1];
+    }
+  }		
+  catalog[0].Nsecfilt --;
+  catalog[0].Nsecf_mem = catalog[0].Naverage*catalog[0].Nsecfilt;
+
+  *myPrimary = primary;
+  *mySecfilt = secfilt;
+  *myNsecfilt = Nsecfilt;
+}
+
+int dvo_catalog_primary_to_secfilt (Catalog *catalog, SecFilt *primary, int Naves) {
+
+  int Ntmpfilt, Nsecfilt, Ntotal, i, j;
+  SecFilt *tmpfilt;
+
+  tmpfilt  = catalog[0].secfilt;
+  Ntmpfilt = catalog[0].Nsecfilt;
+
+  // we do NOT modify Nsecf_disk; this operation only modifies in in-memory values
+
+  catalog[0].Nsecfilt ++;
+  Nsecfilt = catalog[0].Nsecfilt;
+  Ntotal = Nsecfilt * Naves;
+
+  catalog[0].Nsecf_mem = Ntotal;
+
+  ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal);
+  for (i = 0; i < Naves; i++) {
+    catalog[0].secfilt[i*Nsecfilt + 0] = primary[i];
+    for (j = 0; j < Ntmpfilt; j++) {
+      catalog[0].secfilt[i*Nsecfilt + j + 1] = tmpfilt[i*Ntmpfilt + j];
+    }
+  }		
+  free (primary);
+  return (TRUE);
+}
+
+int dvo_catalog_save_subcat (Catalog *catalog, FTable *ftable, int start, int Nrows, int Ndisk, int Ntotal) {
+
+  Matrix matrix;
+
+  /* rewind file pointers and truncate (file is still open) */
+  fseek (catalog->f, 0, SEEK_SET);
+
+  // write PHU header
+  if (!gfits_fwrite_header  (catalog->f, &catalog->header)) {
+    fprintf (stderr, "can't write primary header");
+    return (FALSE);
+  }
+
+  // write the PHU matrix; this is probably a NOP, do I have to keep it in?
+  gfits_create_matrix (&catalog->header, &matrix);
+  if (!gfits_fwrite_matrix  (catalog->f, &matrix)) {
+    fprintf (stderr, "can't write primary matrix");
+    gfits_free_matrix (&matrix);
+    return (FALSE);
+  }
+  gfits_free_matrix (&matrix);
+
+  // write the table data
+  if (!gfits_fwrite_ftable_range (catalog->f, ftable, start, Nrows, Ndisk, Ntotal)) {
+    fprintf (stderr, "can't write table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int dvo_catalog_open_subcat (Catalog *catalog, Catalog **Subcat, Header *header, char *name, int VERBOSE) {
+
+  int status;
+  char *path, string[80];
+  Catalog *subcat;
+  Matrix matrix;
+
+  /* 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);
+  }
+  gfits_free_matrix (&matrix);
+  /* 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,8 +161,10 @@
   FTable ftable;
   SecFilt *primary;
-  Catalog *measure, *missing, *secfilt;
 
   /* ftable header storage for below */
   ftable.header = &header;
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+  primary = NULL;
 
   /* needed to find the split files below */
@@ -23,9 +177,15 @@
   if (!gfits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;
 
+  /* save the current number so we can do partial updates */
+  catalog[0].Naves_disk = Naverage;
+  catalog[0].Nmeas_disk = Nmeasure;
+  catalog[0].Nmiss_disk = Nmissing;
+  catalog[0].Nsecf_disk = Naverage * Nsecfilt;
+
   /**  Nsecfilt is unusual: it does not list the number of data items in the table
        instead, the number of items is Nsecfilt * Naverage.  **/
-  catalog[0].Nsecfilt = Nsecfilt;
-
-  /* default values */
+  catalog[0].Nsecfilt  = Nsecfilt;
+
+  /* default values, but we will assign these a valid value before we exit (even if empty) */
   catalog[0].average = NULL;
   catalog[0].measure = NULL;
@@ -33,12 +193,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");
@@ -50,235 +207,287 @@
       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 */
-    catalog[0].average = FtableToAverage (&ftable, &catalog[0].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);
-  } 
+    /* 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].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 = catalog[0].Naves_disk;
+    catalog[0].Naves_off = 0;
+  } else {
+    ALLOCATE (catalog[0].average, Average, 1);
+    catalog[0].Naverage = 0;
+    catalog[0].Naves_off = catalog[0].Naves_disk;
+  }
 
   /*** Measure Table ***/
-
-  measure = NULL;
-
-  /* (Full Load) */
-  if (catalog[0].catflags & LOAD_MEAS) {
-    ALLOCATE (measure, Catalog, 1);
-    dvo_catalog_init (measure, TRUE);
-
-    /* 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, ftable.header, "MEASURE", VERBOSE);
+  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 */
-    catalog[0].measure = FtableToMeasure (&ftable, &catalog[0].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);
-    }
+    /* 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].Nmeas_disk) {
+      fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, catalog[0].Nmeas_disk);
+    }
+    catalog[0].Nmeasure = catalog[0].Nmeas_disk;
     catalog[0].Nmeas_off = 0;
-    gfits_free_header (&header);
-    gfits_free_matrix (&matrix);
-  }
-
-  /* (Meta Load) */
-  if (catalog[0].catflags & LOAD_MEAS_META) {
-    ALLOCATE (measure, Catalog, 1);
-    dvo_catalog_init (measure, TRUE);
-
-    /* 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);
-    }
-
-    /* allocate dummy data for valid realloc */
+  } 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);
-
-    /* set up the table size information */
-    catalog[0].Nmeasure  = 0;        /* no rows loaded */
-    catalog[0].Nmeas_off = Nmeasure; /* start of new entries */
-  }
-  catalog[0].measure_catalog = measure;
+    catalog[0].Nmeasure = 0;
+    catalog[0].Nmeas_off = catalog[0].Nmeas_disk;
+  }
+  gfits_free_header (ftable.header);
 
   /*** 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, ftable.header, "MISSING", VERBOSE);
+  if (status == DVO_CAT_OPEN_FAIL) {
+    return (FALSE);
+  }
+  if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nmiss_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);
-    }
-    gfits_free_header (&header);
-    gfits_free_matrix (&matrix);
-  } 
-missing_empty:
-  catalog[0].missing_catalog = missing;
+    /* 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);
+    }
+    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;
+  }
+  gfits_free_header (ftable.header);
 
   /*** 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, ftable.header, "SECFILT", VERBOSE);
+  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)) {
+    if (!gfits_fread_ftable_data (catalog[0].secfilt_catalog[0].f, &ftable)) {
       if (VERBOSE) fprintf (stderr, "can't read table secfilt data\n");
       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);
+    }
+    catalog[0].Nsecf_mem = catalog[0].Nsecf_disk;
+    catalog[0].Nsecf_off = 0;
 
     /* if primary is defined, we were supplied with one additional average magnitude from Average
        we need to interleave these magnitudes with the secfilt entries just loaded */
     if (primary != NULL) {
-      int Ntmpfilt, Ntotal, i, j;
-      SecFilt *tmpfilt;
-      tmpfilt  = catalog[0].secfilt;
-      Ntmpfilt = catalog[0].Nsecfilt;
-      Nsecfilt = catalog[0].Nsecfilt + 1;
-      Ntotal = Nsecfilt * catalog[0].Naverage;
-      ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal);
-      for (i = 0; i < catalog[0].Naverage; i++) {
-	catalog[0].secfilt[i*Nsecfilt + 0] = primary[i];
-	for (j = 0; j < Ntmpfilt; j++) {
-	  catalog[0].secfilt[i*Nsecfilt + j + 1] = tmpfilt[i*Ntmpfilt + j];
-	}
-      }		
-      catalog[0].Nsecfilt = Nsecfilt;
+      // this modifies catalog.Nsecf_mem,Nsecfilt
+      dvo_catalog_primary_to_secfilt (catalog, primary, catalog[0].Naves_disk);
+    } 
+  } else {
+    if (primary != NULL) {
       free (primary);
-    } 
-
-
-    gfits_free_header (&header);
-    gfits_free_matrix (&matrix);
-  } else {
-    if (primary != NULL) free (primary);
-  }
-
-  catalog[0].secfilt_catalog = secfilt;
-
-  /* save the current number so we can do partial updates */
-  catalog[0].Nave_disk  = Naverage;
-  catalog[0].Nmeas_disk = Nmeasure;
-  catalog[0].Nmiss_disk = Nmissing;
+      catalog[0].Nsecfilt ++;
+    }
+    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;
+  }
+  gfits_free_header (ftable.header);
 
   return (TRUE);
 }
 
-/* save_catalog_split writes complete new files from scratch */
+// I need to always read both average and secfilt at the same time to correctly manage the
+// primary secfilt values...
+int dvo_catalog_load_segment_split (Catalog *catalog, int VERBOSE, int start, int Nrows) {
+
+  int Naverage, Nsecfilt, Nexpect, Nitems, Nmeasure, Nmissing;
+  Header header;
+  Matrix matrix;
+  FTable ftable;
+  SecFilt *primary;
+
+  /* ftable header storage for below */
+  ftable.header = &header;
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+  primary = NULL;
+
+  /*** Average (& SecFilt) Table ***/
+  if (catalog[0].catflags & LOAD_AVES) {
+
+    /*** load the Average data ***/
+    /* 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_ftable_range (catalog[0].f, &ftable, 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 */
+    catalog[0].average = FtableToAverage (&ftable, &Naverage, &catalog[0].catformat, &primary);
+    if (Naverage != Nrows) {
+      // XXX this condition denotes the eof has been reached; not an error or a warning
+      // 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;
+
+    /*** load the secfilt data ***/
+    Catalog *subcat = catalog[0].secfilt_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 Secfilt table header */
+    if (!gfits_fread_header (subcat[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure header");
+      return (FALSE);
+    }
+    /* read Secfilt table data : format is irrelevant here */
+    if (!gfits_fread_ftable_range (subcat[0].f, &ftable, start*catalog[0].Nsecfilt, catalog[0].Naverage*catalog[0].Nsecfilt)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure data");
+      return (FALSE);
+    }
+
+    Nexpect = catalog[0].Naverage * catalog[0].Nsecfilt;
+    catalog[0].secfilt = FtableToSecFilt (&ftable, &Nitems, &catalog[0].catformat);
+    if (Nitems != Nexpect) {
+      fprintf (stderr, "Warning: mismatch between Nsecfilt items in PHU and Table headers (%d vs %d)\n", Nitems, Nexpect);
+    }
+    catalog[0].Nsecf_mem = catalog[0].Naverage * catalog[0].Nsecfilt;
+    catalog[0].Nsecf_off = start               * catalog[0].Nsecfilt;
+
+    /* if primary is defined, we were supplied with one additional average magnitude from Average
+       we need to interleave these magnitudes with the secfilt entries just loaded */
+    if (primary != NULL) {
+      dvo_catalog_primary_to_secfilt (catalog, primary, Nrows);
+    } 
+    gfits_free_header (&header);
+    gfits_free_matrix (&matrix);
+  }
+
+  // XXX check the open status of the catalog
+  if (catalog[0].catflags & LOAD_MEAS) {
+
+    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_ftable_range (subcat[0].f, &ftable, 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 = FtableToMeasure (&ftable, &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;
+  }
+
+  // XXX check the open status of the catalog?
+  if (catalog[0].catflags & LOAD_MISS) {
+
+    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_ftable_range (subcat[0].f, &ftable, start, Nrows)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing data");
+      return (FALSE);
+    }
+
+    /* no conversions currently defined : this just does the byte swap */
+    catalog[0].missing = gfits_table_get_Missing (&ftable, &Nmissing, NULL);
+    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);
+}
+
+/* save_catalog_split writes all data currently in memory to disk */
 int dvo_catalog_save_split (Catalog *catalog, char VERBOSE) {
 
@@ -290,86 +499,262 @@
   SecFilt *primary, *secfilt;
   int i, j, Nsecfilt, Nallfilt, Ntotal;
+  int Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new;
+  int first, start, Nrows;
 
   ftable.header = &header;
-
-  if (catalog[0].Naverage == 0) {
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+  primary = NULL;
+  
+  // skip empty catalogs: it is illegal to have Measures without corresponding Averages
+  Naves_disk_new = MAX (catalog[0].Naves_disk, catalog[0].Naverage + catalog[0].Naves_off);
+  if (Naves_disk_new == 0) {
     if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
     return (TRUE);
   }
 
-  /* for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary */
-  if ((catalog[0].catformat == DVO_FORMAT_ELIXIR) || // special case for ELIXIR
-      (catalog[0].catformat == DVO_FORMAT_LONEOS)) { // special case for LONEOS
-    if (catalog[0].secfilt == NULL) {       
-      fprintf (stderr, "missing secfilt, cannot build output averages (dvo_catalog_split.c:544)\n");
-      exit (1);
-    }
-    secfilt = catalog[0].secfilt;
-
-    Nallfilt = catalog[0].Nsecfilt;
-    Nsecfilt = catalog[0].Nsecfilt - 1;
-    Ntotal = Nsecfilt * catalog[0].Naverage;
-    ALLOCATE (primary, SecFilt, catalog[0].Naverage);
-    ALLOCATE (secfilt, SecFilt, Ntotal);
-
-    for (i = 0; i < catalog[0].Naverage; i++) {
-      primary[i] = secfilt[i*Nallfilt + 0];
-      for (j = 0; j < Nsecfilt; j++) {
-	secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1];
-      }
-    }		
-  } else {
-    primary = NULL;
-    secfilt = catalog[0].secfilt;
-    Nsecfilt = catalog[0].Nsecfilt;
-  }
+  // for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary
+  switch (catalog[0].catformat) {
+    case DVO_FORMAT_ELIXIR: // special case for ELIXIR
+    case DVO_FORMAT_LONEOS: // special case for LONEOS
+      dvo_catalog_secfilt_to_primary (catalog, &primary, &secfilt, &Nsecfilt);
+      break;
+    default:
+      primary = NULL;
+      secfilt = catalog[0].secfilt;
+      Nsecfilt = catalog[0].Nsecfilt;
+      break;
+  }
+
+  Nmeas_disk_new = MAX (catalog[0].Nmeas_disk, catalog[0].Nmeasure + catalog[0].Nmeas_off);
+  Nmiss_disk_new = MAX (catalog[0].Nmiss_disk, catalog[0].Nmissing + catalog[0].Nmiss_off);
+  Nsecf_disk_new = MAX (catalog[0].Nsecf_disk, catalog[0].Naverage*Nsecfilt + catalog[0].Nsecf_off);
 
   /* make sure header is consistent with data */
-  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
-  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
-  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, Naves_disk_new);
+  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, Nmeas_disk_new);
+  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, Nmiss_disk_new);
   gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt);
   gfits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
 
-  /* rewind file pointers and truncate (file is still open) */
-  fseek (catalog[0].f, 0, SEEK_SET);
-
-  /* write table PHU header - always write this out */
-  /* XXX EAM : check if disk file size has changed */
-  if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
-    fprintf (stderr, "can't write primary header");
-    goto failure;
-  }
-
   /* in split mode, we can save only part of the data */ 
 
   /*** Average Table ***/
-
+  if ((catalog[0].catflags & LOAD_AVES) && (catalog[0].average != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Naves_off; // first disk row to write
+    Nrows  = catalog[0].Naverage - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first < catalog[0].Naverage);
+    assert (catalog[0].Naves_disk >= catalog[0].Naves_off);
+
+    /* convert internal to external format */
+    if (!AverageToFtable (&ftable, &catalog[0].average[first], Nrows, catalog[0].catformat, primary)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    if (!dvo_catalog_save_subcat (catalog, &ftable, start, Nrows, catalog[0].Naves_disk, Naves_disk_new)) {
+      fprintf (stderr, "failure writing Average table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  } else {
+    // even if we do not save the average table, we need to keep the header in sync
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (catalog[0].f, 0, SEEK_SET);
+
+    /* write table PHU header - always write this out */
+    /* XXX EAM : check if disk file size has changed */
+    if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      goto failure;
+    }
+  }
+
+  /*** Measure Table ***/
+  if ((catalog[0].catflags & LOAD_MEAS) && (catalog[0].measure != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Nmeas_off; // first disk row to write
+    Nrows  = catalog[0].Nmeasure - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first < catalog[0].Nmeasure);
+    assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off);
+
+    // convert to external table format
+    if (!MeasureToFtable (&ftable, &catalog[0].measure[first], Nrows, catalog[0].catformat)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Measure table
+    if (!dvo_catalog_save_subcat (catalog[0].measure_catalog, &ftable, start, Nrows, catalog[0].Nmeas_disk, Nmeas_disk_new)) {
+      fprintf (stderr, "trouble writing Measure table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Missing Table ***/
+  if ((catalog[0].catflags & LOAD_MISS) && (catalog[0].missing != NULL)) {
+
+    if (catalog[0].Nmiss_off != 0) {
+      fprintf (stderr, "inconsistency: Missing table cannot be written in segments\n");
+      goto failure;
+    }
+
+    // convert to external table format
+    if (!gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Missing table (must write out entire table)
+    if (!dvo_catalog_save_subcat (catalog[0].missing_catalog, &ftable, 0, catalog[0].Nmissing, catalog[0].Nmissing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble writing Missing Table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Secfilt Table ***/
+  if ((catalog[0].catflags & LOAD_SECF) && (catalog[0].secfilt != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Nsecf_off; // first disk row to write
+    Nitems = catalog[0].Nsecf_mem;
+    Nrows  = Nitems - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first < Nitems);
+    assert (catalog[0].Nsecf_disk >= catalog[0].Nsecf_off);
+    // XXX check these for consistency...
+
+    // convert to external table format
+    SecFiltToFtable (&ftable, &secfilt[first], Nrows, catalog[0].catformat);
+
+    // write out SecFilt table
+    if (!dvo_catalog_save_subcat (catalog[0].secfilt_catalog, &ftable, start, Nrows, catalog[0].Nsecf_disk, Nsecf_disk_new)) {
+      fprintf (stderr, "failure writing SecFilt table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (TRUE);
+
+failure:
+  /* free temp storage */
+  gfits_free_header (&header);
+  gfits_free_table (&ftable);
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (FALSE);
+}
+
+/* update_catalog_split only writes new lines to file. */
+int dvo_catalog_update_split (Catalog *catalog, char VERBOSE) {
+
+  int i, Nx, Ny, Nlines;
+  int Nitems, Nskip, Nout, Ndisk, Nstart;
+  Matrix matrix;
+  Header header;
+  FTable ftable;
+  Catalog *catfile;
+  SecFilt *primary, *secfilt;
+  int j, Nsecfilt, Nallfilt, Ntotal;
+  int Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new;
+  int first, start, Nrows;
+
+  ftable.header = &header;
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+
+  // skip empty catalogs: it is illegal to have Measures without corresponding Averages
+  Naves_disk_new = MAX (catalog[0].Naves_disk, catalog[0].Naverage + catalog[0].Naves_off);
+  if (Naves_disk_new == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  // for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary 
+  switch (catalog[0].catformat) {
+    case DVO_FORMAT_ELIXIR: // special case for ELIXIR
+    case DVO_FORMAT_LONEOS: // special case for LONEOS
+      dvo_catalog_secfilt_to_primary (catalog, &primary, &secfilt, &Nsecfilt);
+      break;
+    default:
+      primary = NULL;
+      secfilt = catalog[0].secfilt;
+      Nsecfilt = catalog[0].Nsecfilt;
+      break;
+  }
+
+  Nmeas_disk_new = MAX (catalog[0].Nmeas_disk, catalog[0].Nmeasure + catalog[0].Nmeas_off);
+  Nmiss_disk_new = MAX (catalog[0].Nmiss_disk, catalog[0].Nmissing + catalog[0].Nmiss_off);
+  Nsecf_disk_new = MAX (catalog[0].Nsecf_disk, catalog[0].Naverage*Nsecfilt + catalog[0].Nsecf_off);
+
+  /* make sure header is consistent with data */
+  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, Naves_disk_new);
+  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, Nmeas_disk_new);
+  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, Nmiss_disk_new);
+  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt);
+  gfits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
+
+  /* in split mode, we can save only part of the data */ 
+
+  /*** Average Table ***/
   if (catalog[0].average != NULL) {
-    ftruncate (fileno (catalog[0].f), catalog[0].header.size);
-
-    /* this is probably a NOP, do I have to keep it in? */
-    gfits_create_matrix (&catalog[0].header, &matrix);
-    if (!gfits_fwrite_matrix  (catalog[0].f, &matrix)) {
-      fprintf (stderr, "can't write primary matrix");
-      goto failure;
-    }
-    gfits_free_matrix (&matrix);
-
-    /* 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;
-    }
-    if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
+
+    first  = catalog[0].Naves_disk - catalog[0].Naves_off; // first row to write (memory)
+    start  = catalog[0].Naves_disk;                        // first row to write (disk)
+    Nrows  = catalog[0].Naverage - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first < catalog[0].Naverage);
+    assert (catalog[0].Naves_disk >= catalog[0].Naves_off);
+
+    /* convert internal to external format */
+    if (!AverageToFtable (&ftable, &catalog[0].average[first], Nrows, catalog[0].catformat, primary)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    if (!dvo_catalog_save_subcat (catalog, &ftable, start, Nrows, catalog[0].Naves_disk, Naves_disk_new)) {
+      fprintf (stderr, "failure writing Average table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
     gfits_free_table (&ftable);
-    gfits_free_header (&header);
+  } else {
+    // even if we do not save the average table, we need to keep the header in sync
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (catalog[0].f, 0, SEEK_SET);
+
+    /* write table PHU header - always write this out */
+    /* XXX EAM : check if disk file size has changed */
+    if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      goto failure;
+    }
   }
 
@@ -377,81 +762,53 @@
   if (catalog[0].measure != NULL) {
 
-    /* catalog file data is stored in separate structure */
-    catfile = catalog[0].measure_catalog;
-
-    /* XXX EAM : warn about this condition; add code to handle? */
-    if (catalog[0].Nmeas_off != 0) {
-      fprintf (stderr, "WARNING: LOAD_MEAS_META mixed with save??\n");
-      fprintf (stderr, "WARNING: this should not be allowed to happen!\n");
-    }
-
-    /* rewind file pointers and truncate (file is still open) */
-    fseek (catfile[0].f, 0, SEEK_SET);
-    ftruncate (fileno (catfile[0].f), 0);
-
-    /* write table PHU header */
-    if (!gfits_fwrite_header  (catfile[0].f, &catfile[0].header)) {
-      fprintf (stderr, "can't write primary header");
-      goto failure;
-    }
-
-    /* this is probably a NOP, do I have to keep it in? */
-    gfits_create_matrix (&catfile[0].header, &matrix);
-    if (!gfits_fwrite_matrix  (catfile[0].f, &matrix)) {
-      fprintf (stderr, "can't write primary matrix");
-      goto failure;
-    }
-    gfits_free_matrix (&matrix);
-
-    /* write out Measure table (convert to FITS table format) */
-    MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
-    if (!gfits_fwrite_Theader (catfile[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_table (catfile[0].f, &ftable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
+    first  = catalog[0].Nmeas_disk - catalog[0].Nmeas_off;  // first row in memory to write
+    start  = catalog[0].Nmeas_off; // first disk row to write
+    Nrows  = catalog[0].Nmeasure - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first < catalog[0].Nmeasure);
+    assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off);
+
+    // convert to external table format
+    if (!MeasureToFtable (&ftable, &catalog[0].measure[first], Nrows, catalog[0].catformat)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Measure table
+    if (!dvo_catalog_save_subcat (catalog[0].measure_catalog, &ftable, start, Nrows, catalog[0].Nmeas_disk, Nmeas_disk_new)) {
+      fprintf (stderr, "trouble writing Measure table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
     gfits_free_table (&ftable);
-    gfits_free_header (&header);
-  }
+  }
+
+  /* missing table CANNOT be written unsorted, thus it is always written 
+     out in full */
 
   /*** Missing Table ***/
+
   if (catalog[0].missing != NULL) {
 
-    /* catalog data is stored in separate catalog */
-    catfile = catalog[0].missing_catalog;
-
-    /* rewind file pointers and truncate (file is still open) */
-    fseek (catfile[0].f, 0, SEEK_SET);
-    ftruncate (fileno (catfile[0].f), 0);
-
-    /* write table PHU header */
-    if (!gfits_fwrite_header  (catfile[0].f, &catfile[0].header)) {
-      fprintf (stderr, "can't write primary header");
-      goto failure;
-    }
-
-    /* this is probably a NOP, do I have to keep it in? */
-    gfits_create_matrix (&catfile[0].header, &matrix);
-    if (!gfits_fwrite_matrix  (catfile[0].f, &matrix)) {
-      fprintf (stderr, "can't write primary matrix");
-      goto failure;
-    }
-    gfits_free_matrix (&matrix);
-
-    /* write out Missing table (convert to FITS table format) */
-    gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
-    if (!gfits_fwrite_Theader (catfile[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_table (catfile[0].f, &ftable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
+    if (catalog[0].Nmiss_off != 0) {
+      fprintf (stderr, "inconsistency: Missing table cannot be written in segments\n");
+      goto failure;
+    }
+
+    // convert to external table format
+    if (!gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Missing table (must write out entire table)
+    if (!dvo_catalog_save_subcat (catalog[0].missing_catalog, &ftable, 0, catalog[0].Nmissing, catalog[0].Nmissing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble writing Missing Table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
     gfits_free_table (&ftable);
-    gfits_free_header (&header);
   }
 
@@ -459,38 +816,24 @@
   if (catalog[0].secfilt != NULL) {
 
-    /* catalog file data is stored in a separate catalog structure */
-    catfile = catalog[0].secfilt_catalog;
-
-    /* rewind file pointers and truncate (file is still open) */
-    fseek (catfile[0].f, 0, SEEK_SET);
-    ftruncate (fileno (catfile[0].f), 0);
-
-    /* write table PHU header */
-    if (!gfits_fwrite_header  (catfile[0].f, &catfile[0].header)) {
-      fprintf (stderr, "can't write primary header");
-      goto failure;
-    }
-
-    /* this is probably a NOP, do I have to keep it in? */
-    gfits_create_matrix (&catfile[0].header, &matrix);
-    if (!gfits_fwrite_matrix  (catfile[0].f, &matrix)) {
-      fprintf (stderr, "can't write primary matrix");
-      goto failure;
-    }
-    gfits_free_matrix (&matrix);
-
-    /* write out SecFilt table (convert to FITS table format) */
-    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
-    SecFiltToFtable (&ftable, secfilt, Nitems, catalog[0].catformat);
-    if (!gfits_fwrite_Theader (catfile[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_table (catfile[0].f, &ftable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
+    first  = catalog[0].Nsecf_disk - catalog[0].Nsecf_off;  // first row in memory to write
+    start  = catalog[0].Nsecf_off; // first disk row to write
+    Nitems = catalog[0].Nsecf_mem;
+    Nrows  = Nitems - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first < Nitems);
+    assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off);
+
+    // convert to external table format
+    SecFiltToFtable (&ftable, &secfilt[first], Nrows, catalog[0].catformat);
+
+    // write out SecFilt table
+    if (!dvo_catalog_save_subcat (catalog[0].secfilt_catalog, &ftable, start, Nrows, catalog[0].Nsecf_disk, Nsecf_disk_new)) {
+      fprintf (stderr, "failure writing SecFilt table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
     gfits_free_table (&ftable);
-    gfits_free_header (&header);
   }
 
@@ -512,240 +855,4 @@
 }
 
-/* update_catalog_split only writes new lines to file.  
- * if file is empty, call save_catalog_split instead.
- * XXX EAM : save_catalog SHOULD do this
- */
-
-int dvo_catalog_update_split (Catalog *catalog, char VERBOSE) {
-
-  int i, Nx, Ny, Nlines;
-  int Nitems, Nskip, Nout, Ndisk, Nstart;
-  Matrix matrix;
-  Header header;
-  FTable ftable;
-  VTable vtable;
-  Catalog *catfile;
-  SecFilt *primary, *secfilt;
-  int j, Nsecfilt, Nallfilt, Ntotal;
-
-  ftable.header = &header;
-  vtable.header = &header;
-
-  if (catalog[0].Naverage == 0) {
-    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
-    return (TRUE);
-  }
-
-  /** for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary **/
-  if ((catalog[0].catformat == DVO_FORMAT_ELIXIR) || // special case for ELIXIR
-      (catalog[0].catformat == DVO_FORMAT_LONEOS)) { // special case for LONEOS
-    if (catalog[0].secfilt == NULL) { 
-      fprintf (stderr, "missing secfilt, cannot build output averages (dvo_catalog_split.c:544)\n");
-      exit (1);
-    }
-    secfilt = catalog[0].secfilt;
-
-    Nallfilt = catalog[0].Nsecfilt;
-    Nsecfilt = catalog[0].Nsecfilt - 1;
-    Ntotal = Nsecfilt * catalog[0].Naverage;
-    ALLOCATE (primary, SecFilt, catalog[0].Naverage);
-    ALLOCATE (secfilt, SecFilt, Ntotal);
-
-    for (i = 0; i < catalog[0].Naverage; i++) {
-      primary[i] = secfilt[i*Nallfilt + 0];
-      for (j = 0; j < Nsecfilt; j++) {
-	secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1];
-      }
-    }		
-  } else {
-    primary = NULL;
-    secfilt = catalog[0].secfilt;
-    Nsecfilt = catalog[0].Nsecfilt;
-  }
-
-  /* make sure header is consistent with data */
-  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
-  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure + catalog[0].Nmeas_off);
-  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
-  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt);
-  gfits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
-
-  /* rewind file pointers and truncate (file is still open) */
-  fseek (catalog[0].f, 0, SEEK_SET);
-
-  /* write table PHU header - always write this out */
-  /* XXX EAM : check if disk file size has changed */
-  if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
-    fprintf (stderr, "can't write primary header");
-    goto failure;
-  }
-
-  /*** Average Table ***/
-  if (catalog[0].average != NULL) {
-
-    /* skip past matrix (already at end of header) */
-    Nskip = gfits_data_size (&catalog[0].header);
-    fseek (catalog[0].f, Nskip, SEEK_CUR);
-
-    /* how many lines to write out? */
-    Nout = catalog[0].Naverage - catalog[0].Nave_disk;
-
-    /* write out Average table (convert to FITS table format) */
-    AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat, primary);
-    /* convert only output rows to vtable */
-    gfits_table_to_vtable (&ftable, &vtable, catalog[0].Nave_disk, Nout);
-
-    if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_vtable (catalog[0].f, &vtable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
-    gfits_free_vtable (&vtable);
-    gfits_free_table (&ftable);
-    gfits_free_header (&header);
-  }
-
-  /*** Measure Table ***/
-  if (catalog[0].measure != NULL) {
-
-    catfile = catalog[0].measure_catalog;
-
-    /* skip past PHU header and matrix */
-    Nskip = catfile[0].header.size + gfits_data_size (&catfile[0].header);
-    fseek (catfile[0].f, Nskip, SEEK_SET);
-
-    Ndisk  = catalog[0].Nmeas_disk;
-    Nstart = catalog[0].Nmeas_disk - catalog[0].Nmeas_off; /* where is first new line? */
-    Nout   = catalog[0].Nmeasure - Nstart;                   /* how many lines to write out? */
-    Nlines = catalog[0].Nmeasure + catalog[0].Nmeas_off;   /* how many lines total in file */
-
-    /* convert to output format FITS table (only rows for output : 0 - Nout) */
-    MeasureToFtable (&ftable, &catalog[0].measure[Nstart], Nout, catalog[0].catformat);
-
-    gfits_scan (&header, "NAXIS1", "%d", 1, &Nx);
-    gfits_scan (&header, "NAXIS2", "%d", 1, &Ny);
-
-    /* convert all output rows to vtable */
-    ALLOCATE (vtable.row, int, MAX (1, Nout));
-    ALLOCATE (vtable.buffer, char *, MAX (1, Nout));
-    for (i = 0; i < Nout; i++) {
-      ALLOCATE (vtable.buffer[i], char, MAX (1, Nx));
-      memcpy (vtable.buffer[i], &ftable.buffer[i*Nx], Nx);
-      vtable.row[i] = i + Ndisk;
-    }
-
-    /* modify vtable to represent full disk table */
-    gfits_modify (&header, "NAXIS2", "%d", 1, Nlines);
-    header.Naxis[1] = Nlines;
-
-    vtable.size = gfits_data_size (&header);
-    vtable.Nrow = Nout;
-    vtable.pad = vtable.size - Nx*Ny;
-
-    if (!gfits_fwrite_Theader (catfile[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_vtable (catfile[0].f, &vtable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
-    gfits_free_vtable (&vtable);
-    gfits_free_table (&ftable);
-    gfits_free_header (&header);
-  }
-
-  /*** Missing Table ***/
-  /* missing table CANNOT be written unsorted, thus it is always written 
-     out in full */
-
-  if (catalog[0].missing != NULL) {
-
-    catfile = catalog[0].missing_catalog;
-
-    /* rewind file pointers and truncate (file is still open) */
-    fseek (catfile[0].f, 0, SEEK_SET);
-    ftruncate (fileno (catfile[0].f), 0);
-
-    /* write table PHU header */
-    if (!gfits_fwrite_header  (catfile[0].f, &catfile[0].header)) {
-      fprintf (stderr, "can't write primary header");
-      goto failure;
-    }
-
-    /* this is probably a NOP, do I have to keep it in? */
-    gfits_create_matrix (&catfile[0].header, &matrix);
-    if (!gfits_fwrite_matrix  (catfile[0].f, &matrix)) {
-      fprintf (stderr, "can't write primary matrix");
-      goto failure;
-    }
-    gfits_free_matrix (&matrix);
-
-    /* write out Missing table (convert to FITS table format) */
-    gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
-    if (!gfits_fwrite_Theader (catfile[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_table (catfile[0].f, &ftable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
-    gfits_free_table (&ftable);
-    gfits_free_header (&header);
-  }
-
-  /*** Secfilt Table ***/
-  if (catalog[0].secfilt != NULL) {
-
-    catfile = catalog[0].secfilt_catalog;
-
-    /* skip past PHU header and matrix */
-    Nskip = catfile[0].header.size + gfits_data_size (&catfile[0].header);
-    fseek (catfile[0].f, Nskip, SEEK_SET);
-
-    /* how many lines to write out? */
-    Nout  = catalog[0].Nsecfilt * (catalog[0].Naverage - catalog[0].Nave_disk);
-    Ndisk = catalog[0].Nsecfilt * catalog[0].Nave_disk;
-
-    /* convert to output format FITS table */
-    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
-    SecFiltToFtable (&ftable, secfilt, Nitems, catalog[0].catformat);
-    /* convert only output rows to vtable */
-    gfits_table_to_vtable (&ftable, &vtable, Ndisk, Nout);
-
-    if (!gfits_fwrite_Theader (catfile[0].f, &header)) {
-      fprintf (stderr, "can't write table header");
-      goto failure;
-    }
-    if (!gfits_fwrite_vtable (catfile[0].f, &vtable)) {
-      fprintf (stderr, "can't write table data");
-      goto failure;
-    }
-    gfits_free_vtable (&vtable);
-    gfits_free_table (&ftable);
-    gfits_free_header (&header);
-  }
-
-  /* free temp storage */
-  if (primary != NULL) {
-    free (primary);
-    free (secfilt);
-  }
-
-  return (TRUE);
-
-failure:
-  /* free temp storage */
-  if (primary != NULL) {
-    free (primary);
-    free (secfilt);
-  }
-  return (FALSE);
-}
-
 /* in split mode, extra files are linked to catalog->measure_catalog, etc.  Each
    has a valid filename, f, header.  The primary catalog data pointers are set
@@ -758,5 +865,16 @@
 /* XXX EAM : update is not efficient.  MeasureToFtable should only 
    convert the new rows (Nmeas_disk to Nmeasure). the resulting
-   table represents the end rows of the vtable.  we need to define
+   table represents the end rows of the ftable.  we need to define
    the vtable based on the ftable, but with Ny = Nmeasure */  
   
+
+
+    // * convert to an ftable
+    // * optionally write the PHU header/matrix
+    // * advance to the start of the output data block:
+    // ** Nx * catalog[0].Nmeas_off
+    // * write out the ftable data block
+    // * if Nmeas_off + Nmeasure >= Nmeas_disk, update padding
+    // ** start = Nmeas_off
+    // ** Nrows = Nmeasure
+
Index: /trunk/Ohana/src/libfits/header/F_read_H.c
===================================================================
--- /trunk/Ohana/src/libfits/header/F_read_H.c	(revision 15742)
+++ /trunk/Ohana/src/libfits/header/F_read_H.c	(revision 15743)
@@ -34,4 +34,8 @@
     Nbytes = fread (&header[0].buffer[i*FT_RECORD_SIZE], 
 		    sizeof(char), FT_RECORD_SIZE, f);
+    if (Nbytes != FT_RECORD_SIZE) {
+      perror ("fits read error");
+    }
+    
     header[0].size += Nbytes;
     if (Nbytes != FT_RECORD_SIZE) {
Index: /trunk/Ohana/src/libfits/include/gfitsio.h
===================================================================
--- /trunk/Ohana/src/libfits/include/gfitsio.h	(revision 15742)
+++ /trunk/Ohana/src/libfits/include/gfitsio.h	(revision 15743)
@@ -2,4 +2,5 @@
 
 # include <assert.h>
+# include <errno.h>
 
 # ifndef GFITSIO
@@ -172,4 +173,5 @@
 int   	gfits_fread_ftable             PROTO((FILE *f, FTable *ftable, char *extname)); 
 int   	gfits_fread_ftable_data        PROTO((FILE *f, FTable *ftable));
+int   	gfits_fread_ftable_range       PROTO((FILE *f, FTable *ftable, int start, int Nrows));
 int   	gfits_fread_vtable             PROTO((FILE *f, VTable *vtable, char *extname, int Nrow, int *row));
 int   	gfits_fread_vtable_range       PROTO((FILE *f, VTable *vtable, int start, int Nrows));
@@ -178,4 +180,5 @@
 int     gfits_fwrite_table             PROTO((FILE *f, FTable *table));
 int     gfits_fwrite_vtable            PROTO((FILE *f, VTable *table));
+int     gfits_fwrite_ftable_range      PROTO((FILE *f, FTable *table, int start, int Nrows, int Ndisk, int Ntotal));
 int     gfits_get_bintable_column      PROTO((Header *header, FTable *table, char *label, void **data));
 int     gfits_get_bintable_column_type PROTO((Header *header, char *label, char *type, int *Nval));
Index: /trunk/Ohana/src/libfits/matrix/F_load_M.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_load_M.c	(revision 15742)
+++ /trunk/Ohana/src/libfits/matrix/F_load_M.c	(revision 15743)
@@ -30,4 +30,7 @@
 
   nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    perror ("fits matrix read error");
+  }
 
 # ifdef BYTE_SWAP  
Index: /trunk/Ohana/src/libfits/matrix/F_read_portion.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_read_portion.c	(revision 15742)
+++ /trunk/Ohana/src/libfits/matrix/F_read_portion.c	(revision 15743)
@@ -47,4 +47,8 @@
   fseek (f, header.size + Nskip, SEEK_SET);
   nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    perror ("fits matrix read error");
+  }
+
   fclose (f);
 
Index: /trunk/Ohana/src/libfits/matrix/F_read_segment.c
===================================================================
--- /trunk/Ohana/src/libfits/matrix/F_read_segment.c	(revision 15742)
+++ /trunk/Ohana/src/libfits/matrix/F_read_segment.c	(revision 15743)
@@ -90,4 +90,8 @@
   fseek (f, Nskip, SEEK_CUR);
   nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    perror ("fits matrix read error");
+  }
+
   matrix[0].size = Nbytes;
 
Index: /trunk/Ohana/src/libfits/table/F_read_T.c
===================================================================
--- /trunk/Ohana/src/libfits/table/F_read_T.c	(revision 15742)
+++ /trunk/Ohana/src/libfits/table/F_read_T.c	(revision 15743)
@@ -59,8 +59,50 @@
   Nread = fread (table[0].buffer, sizeof (char), Nbytes, f);
   if (Nread != Nbytes) {
+    perror ("fits read error");
     gfits_free_table  (table);
     return (FALSE);
   }
   table[0].size = Nbytes;
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fread_ftable_range (FILE *f, FTable *table, int start, int Nrows) {
+
+  int Nbytes, Nread, Nskip, Nx, Ny;
+
+  /* find disk table size */
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[1];
+
+  // it is an error to ask for data starting out-of-bounds
+  if (start < 0) return (FALSE);
+  if (start >= Ny) return (FALSE);
+  
+  // if we request more data than is available, we will stop at the table end.
+  Nrows = MIN (Nrows, Ny - start);
+
+  Nskip = start * Nx;
+  Nbytes = Nrows * Nx;
+  ALLOCATE (table[0].buffer, char, MAX (Nbytes, 1));
+
+  fseek (f, Nskip, SEEK_CUR);
+
+  Nread = fread (table[0].buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    if (ferror (f)) {
+      perror ("fits read error");
+    } else {
+      fprintf (stderr, "unexpected eof\n");
+    }      
+    free (table[0].buffer);
+    return (FALSE);
+  }
+
+  /* modify structure and header to match actual read rows Ny */
+  table[0].header[0].Naxis[1] = Nrows;
+  gfits_modify (table[0].header, "NAXIS2",  "%d", 1, Nrows);
+  table[0].size = gfits_data_size (table[0].header);
+
   return (TRUE);
 }	
@@ -88,4 +130,5 @@
   Nread = fread (buffer, sizeof (char), Nbytes, f);
   if (Nread != Nbytes) {
+    perror ("fits read error");
     free (buffer);
     return (FALSE);
@@ -146,5 +189,8 @@
       fseek (f, offset, SEEK_SET);
       Nread = fread (table[0].buffer[i], sizeof (char), Nx, f);
-      if (Nread != Nx) { return (FALSE); }
+      if (Nread != Nx) { 
+	perror ("fits read error");
+	return (FALSE); 
+      }
     }
 
Index: /trunk/Ohana/src/libfits/table/F_read_TH.c
===================================================================
--- /trunk/Ohana/src/libfits/table/F_read_TH.c	(revision 15742)
+++ /trunk/Ohana/src/libfits/table/F_read_TH.c	(revision 15743)
@@ -46,4 +46,8 @@
     Nbytes = fread (&Theader[0].buffer[i*FT_RECORD_SIZE], 
 		    sizeof(char), FT_RECORD_SIZE, f);
+    if (Nbytes != FT_RECORD_SIZE) {
+      perror ("fits matrix read error");
+    }
+
     Theader[0].size += Nbytes;
     if (Nbytes != FT_RECORD_SIZE) 
Index: /trunk/Ohana/src/libfits/table/F_write_T.c
===================================================================
--- /trunk/Ohana/src/libfits/table/F_write_T.c	(revision 15742)
+++ /trunk/Ohana/src/libfits/table/F_write_T.c	(revision 15743)
@@ -69,2 +69,47 @@
 /* this will add data beyond the end of the table in the file if needed,
    filling intervening gap with 0 */
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fwrite_ftable_range (FILE *f, FTable *ftable, int start, int Nrows, int Ndisk, int Ntotal) {
+
+  int Nbytes, Nwrite, Nskip, Nx, Npad;
+  char *pad;
+
+  if (start < 0) return (FALSE);
+  
+  /* modify vtable to represent full disk table */
+  gfits_modify (ftable[0].header, "NAXIS2", "%d", 1, Ntotal);
+  ftable[0].header[0].Naxis[1] = Ntotal;
+
+  Nx = ftable[0].header[0].Naxis[0]; // final output table size on disk 
+  ftable[0].size = gfits_data_size (ftable[0].header);
+
+  Nskip = start * Nx;
+  Nbytes = Nrows * Nx;
+
+  // cursor must be at start of the table header
+  if (!gfits_fwrite_Theader (f, ftable[0].header)) {
+    fprintf (stderr, "can't write table header");
+    return (FALSE);
+  }
+
+  // cursor must be at start of the table (after table header)
+  fseek (f, Nskip, SEEK_CUR);
+  Nwrite = fwrite (ftable[0].buffer, sizeof (char), Nbytes, f);
+  if (Nwrite != Nbytes) {
+    return (FALSE);
+  }
+
+  if (Ntotal >= Ndisk) {
+    Npad = ftable[0].size - Nx*Ntotal;
+    ALLOCATE (pad, char, Npad);
+    bzero (pad, Npad);
+    Nbytes = fwrite (pad, sizeof (char), Npad, f);
+    free (pad);
+
+    if (Nbytes != Npad) return (FALSE); 
+  }
+
+  return (TRUE);
+}	
+
Index: /trunk/Ohana/src/markrock/src/markrock.c
===================================================================
--- /trunk/Ohana/src/markrock/src/markrock.c	(revision 15742)
+++ /trunk/Ohana/src/markrock/src/markrock.c	(revision 15743)
@@ -45,5 +45,5 @@
     exit (2);
   }
-  if (catalog.Nave_disk) {
+  if (catalog.Naves_disk) {
     dvo_catalog_unlock (&catalog);
     dvo_catalog_free (&catalog);
Index: /trunk/Ohana/src/markstar/src/markstar.c
===================================================================
--- /trunk/Ohana/src/markstar/src/markstar.c	(revision 15742)
+++ /trunk/Ohana/src/markstar/src/markstar.c	(revision 15743)
@@ -48,5 +48,5 @@
     exit (2);
   }
-  if (!catalog.Nave_disk) {
+  if (!catalog.Naves_disk) {
     dvo_catalog_unlock (&catalog);
     dvo_catalog_free (&catalog);
Index: /trunk/Ohana/src/mosastro/src/getptolemy.c
===================================================================
--- /trunk/Ohana/src/mosastro/src/getptolemy.c	(revision 15742)
+++ /trunk/Ohana/src/mosastro/src/getptolemy.c	(revision 15743)
@@ -36,7 +36,7 @@
     dvo_catalog_unlock (&catalog);
 
-    // Nave_disk == 0 implies an empty catalog file
+    // Naves_disk == 0 implies an empty catalog file
     // for only_match, skip empty catalogs
-    if (!catalog.Nave_disk) {
+    if (!catalog.Naves_disk) {
       dvo_catalog_free (&catalog);
       continue;
Index: /trunk/Ohana/src/photdbc/src/join_stars.c
===================================================================
--- /trunk/Ohana/src/photdbc/src/join_stars.c	(revision 15742)
+++ /trunk/Ohana/src/photdbc/src/join_stars.c	(revision 15743)
@@ -172,4 +172,5 @@
   
   catalog[0].Naverage = Naves;
+  catalog[0].Nsecf_mem = Naves*catalog[0].Nsecfilt;
 }
 
@@ -181,4 +182,6 @@
    generates a new SecFilt table with empty values 
    does NOT update magnitudes 
+   output measure table is the same size as the input measure table
+   (measures are just moved around).  thus, catalog[0].Nmeasure does not change.
 */   
    
Index: /trunk/Ohana/src/photdbc/src/make_subcatalog.c
===================================================================
--- /trunk/Ohana/src/photdbc/src/make_subcatalog.c	(revision 15742)
+++ /trunk/Ohana/src/photdbc/src/make_subcatalog.c	(revision 15743)
@@ -10,4 +10,5 @@
 
   Nsecfilt = GetPhotcodeNsecfilt ();
+  assert (catalog[0].Nsecfilt == Nsecfilt);
 
   /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
@@ -96,5 +97,6 @@
   subcatalog[0].Naverage = Naverage;
   subcatalog[0].Nmeasure = Nmeasure;
-  subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
+  subcatalog[0].Nsecfilt = Nsecfilt;
+  subcatalog[0].Nsecf_mem = Naverage * Nsecfilt;
 
   // XXX for now, don't copy the missing entries (these should be re-computed)
Index: /trunk/Ohana/src/photdbc/src/photdbc.c
===================================================================
--- /trunk/Ohana/src/photdbc/src/photdbc.c	(revision 15742)
+++ /trunk/Ohana/src/photdbc/src/photdbc.c	(revision 15743)
@@ -34,5 +34,5 @@
     }
     // skip empty input catalogs
-    if (!incatalog.Nave_disk) {
+    if (!incatalog.Naves_disk) {
       dvo_catalog_unlock (&incatalog);
       dvo_catalog_free (&incatalog);
Index: /trunk/Ohana/src/relastro/src/bcatalog.c
===================================================================
--- /trunk/Ohana/src/relastro/src/bcatalog.c	(revision 15742)
+++ /trunk/Ohana/src/relastro/src/bcatalog.c	(revision 15743)
@@ -6,4 +6,9 @@
   int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm;
   float mag;
+
+  // XXX PhotNsec as a global is a bad idea; either get it from catalog
+  // or get it from:
+  // Nsecfilt = GetPhotcodeNsecfilt ();
+  // assert (catalog[0].Nsecfilt == Nsecfilt);
 
   /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
@@ -104,4 +109,6 @@
   subcatalog[0].Nmeasure = Nmeasure;
   subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
+  subcatalog[0].Nsecf_mem = Naverage * PhotNsec;
+  assert (PhotNsec == catalog[0].Nsecfilt);
 
   if (VERBOSE) {
Index: /trunk/Ohana/src/relastro/src/load_catalogs.c
===================================================================
--- /trunk/Ohana/src/relastro/src/load_catalogs.c	(revision 15742)
+++ /trunk/Ohana/src/relastro/src/load_catalogs.c	(revision 15743)
@@ -13,4 +13,6 @@
   for (i = 0; i < skylist[0].Nregions; i++) {
 
+    // we only allow output if we do not use a subset.  in this case,
+    // the output parameters are correctly set for catalog[i] via pcatalog
     pcatalog = subselect ? &tcatalog : &catalog[i];
 
@@ -26,5 +28,5 @@
       exit (1);
     }
-    if (VERBOSE && !pcatalog[0].Nave_disk) fprintf (stderr, "no data in %s, skipping\n", pcatalog[0].filename);
+    if (VERBOSE && !pcatalog[0].Naves_disk) fprintf (stderr, "no data in %s, skipping\n", pcatalog[0].filename);
 
     // select only the brighter stars
Index: /trunk/Ohana/src/relastro/src/reload_catalogs.c
===================================================================
--- /trunk/Ohana/src/relastro/src/reload_catalogs.c	(revision 15742)
+++ /trunk/Ohana/src/relastro/src/reload_catalogs.c	(revision 15743)
@@ -29,5 +29,5 @@
       exit (1);
     }
-    if (VERBOSE && (catalog.Nave_disk == 0)) {
+    if (VERBOSE && (catalog.Naves_disk == 0)) {
 	fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
 	dvo_catalog_unlock (&catalog);
Index: /trunk/Ohana/src/relphot/src/bcatalog.c
===================================================================
--- /trunk/Ohana/src/relphot/src/bcatalog.c	(revision 15742)
+++ /trunk/Ohana/src/relphot/src/bcatalog.c	(revision 15743)
@@ -6,4 +6,9 @@
   int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm;
   float mag;
+
+  // XXX PhotNsec as a global is a bad idea; either get it from catalog
+  // or get it from:
+  // Nsecfilt = GetPhotcodeNsecfilt ();
+  // assert (catalog[0].Nsecfilt == Nsecfilt);
 
   /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
@@ -105,4 +110,6 @@
   subcatalog[0].Nmeasure = Nmeasure;
   subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
+  subcatalog[0].Nsecf_mem = Naverage * catalog[0].Nsecfilt;
+  assert (PhotNsec == catalog[0].Nsecfilt);
 
   if (VERBOSE) {
Index: /trunk/Ohana/src/relphot/src/load_catalogs.c
===================================================================
--- /trunk/Ohana/src/relphot/src/load_catalogs.c	(revision 15742)
+++ /trunk/Ohana/src/relphot/src/load_catalogs.c	(revision 15743)
@@ -24,5 +24,5 @@
       exit (1);
     }
-    if (VERBOSE && !tcatalog.Nave_disk) fprintf (stderr, "no data in %s, skipping\n", tcatalog.filename);
+    if (VERBOSE && !tcatalog.Naves_disk) fprintf (stderr, "no data in %s, skipping\n", tcatalog.filename);
 
     // select only the brighter stars
Index: /trunk/Ohana/src/relphot/src/reload_catalogs.c
===================================================================
--- /trunk/Ohana/src/relphot/src/reload_catalogs.c	(revision 15742)
+++ /trunk/Ohana/src/relphot/src/reload_catalogs.c	(revision 15743)
@@ -30,5 +30,5 @@
       exit (1);
     }
-    if (VERBOSE && (catalog.Nave_disk == 0)) {
+    if (VERBOSE && (catalog.Naves_disk == 0)) {
 	fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
 	dvo_catalog_unlock (&catalog);
Index: /trunk/Ohana/src/uniphot/src/update.c
===================================================================
--- /trunk/Ohana/src/uniphot/src/update.c	(revision 15742)
+++ /trunk/Ohana/src/uniphot/src/update.c	(revision 15743)
@@ -52,5 +52,5 @@
       exit (2);
     }
-    if (!catalog.Nave_disk) {
+    if (!catalog.Naves_disk) {
       dvo_catalog_unlock (&catalog);
       dvo_catalog_free (&catalog);
