Index: /trunk/Ohana/src/libohana/Makefile
===================================================================
--- /trunk/Ohana/src/libohana/Makefile	(revision 5227)
+++ /trunk/Ohana/src/libohana/Makefile	(revision 5228)
@@ -47,9 +47,10 @@
 $(SRC)/fits_db.$(ARCH).o	 \
 $(SRC)/photfits.$(ARCH).o        \
-$(SRC)/dvo_image.$(ARCH).o           \
-$(SRC)/dvo_image_raw.$(ARCH).o           \
-$(SRC)/phot_catalog.$(ARCH).o    \
-$(SRC)/phot_catalog_mef.$(ARCH).o      \
-$(SRC)/phot_catalog_raw.$(ARCH).o      \
+$(SRC)/dvo_image.$(ARCH).o       \
+$(SRC)/dvo_image_raw.$(ARCH).o   \
+$(SRC)/dvo_catalog.$(ARCH).o     \
+$(SRC)/dvo_catalog_raw.$(ARCH).o       \
+$(SRC)/dvo_catalog_mef.$(ARCH).o       \
+$(SRC)/dvo_catalog_split.$(ARCH).o     \
 $(SRC)/dvo_convert.$(ARCH).o           \
 $(SRC)/dvo_convert_elixir.$(ARCH).o    \
Index: /trunk/Ohana/src/libohana/include/dvo.h
===================================================================
--- /trunk/Ohana/src/libohana/include/dvo.h	(revision 5227)
+++ /trunk/Ohana/src/libohana/include/dvo.h	(revision 5228)
@@ -118,23 +118,10 @@
 
 /* a catalog contains this data */
-typedef struct {
-  /* description of the catalog file: */
-  char *filename;
-  int lockmode;
-  FILE *f;
-
-  /* extra table data if needed (move these to enums?) */
-  # if (0)
-  char catmode[10];         /* storage mode: raw, mef, split, mysql */
-  char average_format[80];  /* table format: internal, loneos, elixir, panstarrs */
-  char measure_format[80];  /* table format: must match average_format */
-  char secfilt_format[80];  /* table format: must match average_format */
-  # endif
-
-  int catmode;
-  int catformat;
-  
-  /* data in the catalog */
+typedef struct Catalog {
+  char *filename;			/* catalog file */
+  FILE *f;  				/* file descriptor */
   Header  header;
+
+  /* data in the catalog file */
   Average *average;
   Measure *measure; 
@@ -143,4 +130,15 @@
   int Naverage, Nmeasure, Nmissing, Nsecfilt;
 
+  /* pointers to split data files */
+  struct Catalog *measure_catalog;		/* measure catalog data (split) */
+  struct Catalog *missing_catalog;		/* missing catalog data (split) */
+  struct Catalog *secfilt_catalog;		/* secfilt catalog data (split) */
+
+  /* extra catalog information */
+  int lockmode;
+  int catmode;				/* storage mode (raw, mef, split, mysql) */
+  int catformat;			/* storage format (elixir, panstarrs, etc) */
+  int ordered;				/* is measure table average-ordered? */
+  
   /* pointers for data manipulation */
   int *found;
@@ -149,4 +147,5 @@
   float *X;
   float *Y;
+
 } Catalog;
 
@@ -290,4 +289,6 @@
 int load_catalog_mef (Catalog *catalog, char mode, int VERBOSE);
 int save_catalog_mef (Catalog *catalog, char VERBOSE);
+int load_catalog_split (Catalog *catalog, char mode, int VERBOSE);
+int save_catalog_split (Catalog *catalog, char VERBOSE);
 
 /*** DVO image db I/O Functions ***/
Index: /trunk/Ohana/src/libohana/src/dvo_catalog.c
===================================================================
--- /trunk/Ohana/src/libohana/src/dvo_catalog.c	(revision 5228)
+++ /trunk/Ohana/src/libohana/src/dvo_catalog.c	(revision 5228)
@@ -0,0 +1,125 @@
+# include <ohana.h>
+# include <dvo.h>
+
+/* possible exit status for lock_catalog: 
+   0 - failure (including lock failure)
+   1 - success
+   2 - empty file (file may be open or closed!) 
+*/
+
+int lock_catalog (Catalog *catalog, int lockmode) {
+
+  int dbstate;
+
+  /* record lockmode choice */
+  catalog[0].lockmode = lockmode;
+
+  /* set lock on database, create stream f */
+  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);
+
+  fseek (catalog[0].f, 0, SEEK_SET);
+  return (1);
+}
+
+int unlock_catalog (Catalog *catalog) {
+
+  int dbstate;
+
+  if (catalog[0].f == (FILE *) NULL) return (2);
+  fclearlockfile (catalog[0].filename, catalog[0].f, catalog[0].lockmode, &dbstate);
+  return (1);
+}
+
+int load_catalog (Catalog *catalog, char mode, int VERBOSE) {
+  
+  int Naxis, split;
+  char measure[80];
+
+  /** we will have to check catmode for MYSQL before reading from the file **/
+
+  fits_fread_header (catalog[0].f, &catalog[0].header);
+  if (!fits_scan (&catalog[0].header, "NAXIS", "%d", 1, &Naxis)) {
+    if (VERBOSE) fprintf (stderr, "can't determine catalog db mode\n");
+    return (FALSE);
+  }
+  split = fits_scan (&catalog[0].header, "MEASURE", "%s", 1, measure);
+
+  /* currenly, the catmode information is carried per table.
+     the user-set value of catmode will set the output mode for new tables
+     an old table will keep its mode
+  */
+
+  catalog[0].catmode = DVO_MODE_MEF;
+  catalog[0].catformat = DVO_FORMAT_UNDEF;
+  if (split) catalog[0].catmode = DVO_MODE_SPLIT;
+  if (Naxis == 2) catalog[0].catmode = DVO_MODE_RAW;
+  /* don't use Naxis == 2 and split mode! */
+
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_RAW)\n");
+      load_catalog_raw (catalog, mode, VERBOSE);
+      break;
+    case DVO_MODE_MEF:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_MEF)\n");
+      load_catalog_mef (catalog, mode, VERBOSE);
+      break;
+    case DVO_MODE_SPLIT:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_SPLIT)\n");
+      load_catalog_split (catalog, mode, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "error getting catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+int save_catalog (Catalog *catalog, char VERBOSE) {
+
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      save_catalog_raw (catalog, VERBOSE);
+      break;
+    case DVO_MODE_MEF:
+      save_catalog_mef (catalog, VERBOSE);
+      break;
+    case DVO_MODE_SPLIT:
+      save_catalog_split (catalog, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "invalid catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+int update_catalog (Catalog *catalog, char VERBOSE) {
+
+  /* update is only valid for catmode SPLIT */
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      save_catalog_raw (catalog, VERBOSE);
+      break;
+    case DVO_MODE_MEF:
+      save_catalog_mef (catalog, VERBOSE);
+      break;
+    case DVO_MODE_SPLIT:
+      update_catalog_split (catalog, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "invalid catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+/*
+  mode   : items to read (LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF)
+  format : what structure on disk (INTERNAL, ELIXIR, LONEOS, PANSTARRS)
+  style  : raw, mef, split, mysql
+*/
Index: /trunk/Ohana/src/libohana/src/dvo_catalog_mef.c
===================================================================
--- /trunk/Ohana/src/libohana/src/dvo_catalog_mef.c	(revision 5228)
+++ /trunk/Ohana/src/libohana/src/dvo_catalog_mef.c	(revision 5228)
@@ -0,0 +1,237 @@
+# include <ohana.h>
+# include <dvo.h>
+
+int load_catalog_mef (Catalog *catalog, char mode, int VERBOSE) {
+  
+  int Nitems, Nbytes, Nexpect, Naverage, Nmeasure, Nmissing, Nsecfilt;
+  FILE *f;
+
+  Header header;
+  Matrix matrix;
+  FTable ftable;
+
+  f = catalog[0].f;
+  ftable.header = &header;
+
+  /* move pointer past header -- must be already read (load_catalog) */
+  fseek (f, catalog[0].header.size, SEEK_SET);
+
+  /* matrix should be empty */
+  if (!fits_fread_matrix (f, &matrix, &catalog[0].header)) {
+    if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+    return (FALSE);
+  }
+  /* get the components from the header */
+  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &Naverage)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &Nmeasure)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &Nmissing)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;
+
+  /**  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;
+
+  /* validate table mode */
+
+  /* read Average table header */
+  if (!fits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table average header");
+    return (FALSE);
+  }
+  /* read Average table data (or skip) */
+  if (mode & LOAD_AVES) {
+    if (!fits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average data");
+      return (FALSE);
+    }
+    catalog[0].average = FtableToAverage (&ftable, &catalog[0].Naverage, &catalog[0].catformat);
+    if (Naverage != catalog[0].Naverage) {
+      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naverage);
+    }
+  } else {
+    Nbytes = fits_matrix_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+  fits_free_header (&header);
+  /** free the ftable or not? data is being used still..? **/
+
+  /* read Measure table header */
+  if (!fits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table measure header");
+    return (FALSE);
+  }
+  /* read Measure table data */
+  if (mode & LOAD_MEAS) {
+    if (!fits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure data");
+      return (FALSE);
+    }
+    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);
+    }
+  } else {
+    Nbytes = fits_matrix_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+
+  /* read Missing table header */
+  if (!fits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table missing header");
+    return (FALSE);
+  }
+  /* read Missing table data */
+  if (mode & LOAD_MISS) {
+    if (!fits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing data");
+      return (FALSE);
+    }
+    /* no conversions currently defined */
+    catalog[0].missing = fits_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);
+    }
+  } else {
+    Nbytes = fits_matrix_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+
+  // catalog[0].secfilt = fits_table_get_SecFilt (&ftable, &Nitems, NULL);
+  // catalog[0].Nsecfilt = Nitems / catalog[0].Naverage;
+
+  /* read secfilt table header */
+  if (!fits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table secfilt header");
+    return (FALSE);
+  }
+  /* read secfilt table data */
+  if (mode & LOAD_SECF) {
+    if (!fits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table secfilt data");
+      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);
+    }
+  } else {
+    /* no real need to skip the data array here... */
+    Nbytes = fits_matrix_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+  return (TRUE);
+}
+
+/* save_catalog_mef writes a complete new file from scratch */
+
+int save_catalog_mef (Catalog *catalog, char VERBOSE) {
+
+  int Nitems;
+  FILE *f;
+  Matrix matrix;
+  Header header;
+  FTable ftable;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  /* make sure header is consistent with data */
+  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
+  fits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
+
+  f = catalog[0].f;
+  /* rewind file pointers and truncate */
+  fseek (f, 0, SEEK_SET);
+  ftruncate (fileno (catalog[0].f), 0);
+  ftable.header = &header;
+
+  /* write table PHU header */
+  if (!fits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+    fprintf (stderr, "can't write primary header");
+    return (FALSE);
+  }
+
+  /* this is probably a NOP, do I have to keep it in? */
+  fits_create_matrix (&catalog[0].header, &matrix);
+  if (!fits_fwrite_matrix  (catalog[0].f, &matrix)) {
+    fprintf (stderr, "can't write primary matrix");
+    return (FALSE);
+  }
+  fits_free_matrix (&matrix);
+
+  /* write out Average table (convert to FITS table format) */
+  AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat);
+  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    return (FALSE);
+  }
+  fits_free_table (&ftable);
+  fits_free_header (&header);
+
+  /* write out Measure table (convert to FITS table format) */
+  MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
+  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    return (FALSE);
+  }
+  fits_free_table (&ftable);
+  fits_free_header (&header);
+
+  /* write out Missing table (convert to FITS table format) */
+  fits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
+  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    return (FALSE);
+  }
+  fits_free_table (&ftable);
+  fits_free_header (&header);
+
+  /* write out SecFilt table (convert to FITS table format) */
+  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+  SecFiltToFtable (&ftable, catalog[0].secfilt, Nitems, catalog[0].catformat);
+  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    return (FALSE);
+  }
+  fits_free_table (&ftable);
+  fits_free_header (&header);
+
+  return (TRUE);
+}
+
+/*
+   catalog data is:
+   header (bitpix == 8)
+   matrix (empty)
+   average header
+   average table
+   measure header
+   measure table
+   missing header
+   missing table
+   secfilt header
+   secfilt table
+*/
+   
Index: /trunk/Ohana/src/libohana/src/dvo_catalog_raw.c
===================================================================
--- /trunk/Ohana/src/libohana/src/dvo_catalog_raw.c	(revision 5228)
+++ /trunk/Ohana/src/libohana/src/dvo_catalog_raw.c	(revision 5228)
@@ -0,0 +1,581 @@
+# include <ohana.h>
+# include <dvo.h>
+
+/* read data from raw-style catalog file; set data format values based on file */
+
+int load_catalog_raw (Catalog *catalog, char mode, int VERBOSE) {
+  
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, size;
+  int NewMeasure, Nskip;
+  int AverageSize, MeasureSize, MissingSize, SecFiltSize;
+  FILE *f;
+  struct stat filestatus;
+  char format[80], telescope[80];
+
+  f = catalog[0].f;
+
+  /* move pointer past header -- must be already read (load_catalog) */
+  fseek (f, catalog[0].header.size, SEEK_SET);
+
+  /* get the components from the header */
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
+  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;
+
+  /* determine catalog format */
+  catalog[0].catformat = DVO_FORMAT_UNDEF;
+  if (fits_scan (&catalog[0].header, "FORMAT",  "%s", 1, format)) {
+    if (!strcmp (format, "INTERNAL")) catalog[0].catformat = DVO_FORMAT_INTERNAL;
+    if (!strcmp (format, "LONEOS")) catalog[0].catformat = DVO_FORMAT_LONEOS;
+    if (!strcmp (format, "ELIXIR")) catalog[0].catformat = DVO_FORMAT_ELIXIR;
+    if (!strcmp (format, "PANSTARRS")) catalog[0].catformat = DVO_FORMAT_PANSTARRS;
+    if (catalog[0].catformat != DVO_FORMAT_UNDEF) goto got_format;
+  }
+  if (fits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) {
+    catalog[0].catformat = DVO_FORMAT_ELIXIR;
+    goto got_format;
+  }
+  if (fits_scan (&catalog[0].header, "TELESCOP",  "%s", 1, telescope)) {
+    if (!strncmp (telescope, "LONEOS", strlen("LONEOS"))) {
+      catalog[0].catformat = DVO_FORMAT_LONEOS;
+      goto got_format;
+    }
+    if (!strncmp (telescope, "1.3m McGraw-Hill", strlen("1.3m McGraw-Hill"))) {
+      catalog[0].catformat = DVO_FORMAT_ELIXIR;
+      goto got_format;
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "cannot determine catalog format\n");
+  return (FALSE);
+
+got_format:
+  /* determine datatype sizes */
+  switch (catalog[0].catformat) {
+    case DVO_FORMAT_INTERNAL:
+      AverageSize = sizeof(Average);
+      MeasureSize = sizeof(Measure);
+      SecFiltSize = sizeof (SecFilt);
+      break;
+    case DVO_FORMAT_LONEOS:
+      AverageSize = sizeof(AverageLoneos);
+      MeasureSize = sizeof(MeasureLoneos);
+      SecFiltSize = sizeof (SecFiltLoneos);
+      break;
+    case DVO_FORMAT_ELIXIR:
+      AverageSize = sizeof(AverageElixir);
+      MeasureSize = sizeof(MeasureElixir);
+      SecFiltSize = sizeof (SecFiltElixir);
+      break;
+    case DVO_FORMAT_PANSTARRS:
+      AverageSize = sizeof(AveragePanstarrs);
+      MeasureSize = sizeof(MeasurePanstarrs);
+      SecFiltSize = sizeof (SecFiltPanstarrs);
+      break;
+    default:
+      fprintf (stderr, "programming error in phot_catalog_raw\n");
+      exit (2);
+  }
+  MissingSize = sizeof (Missing);
+
+  /* predicted file size - for double checking data validity */
+  size = catalog[0].header.size;
+  size += AverageSize * catalog[0].Naverage;
+  size += MeasureSize * catalog[0].Nmeasure;
+  size += MissingSize * catalog[0].Nmissing;
+  size += SecFiltSize * catalog[0].Nsecfilt * catalog[0].Naverage;
+
+  /* check that file size makes sense */
+  if (stat (catalog[0].filename, &filestatus) == -1) {
+    if (VERBOSE) fprintf (stderr, "failed to get status of catalog\n");
+    return (FALSE);
+  }
+  if (size > filestatus.st_size) {
+    if (VERBOSE) {
+      fprintf (stderr, "star catalog has inconsistent size\n");
+      fprintf (stderr, "average: %d = %d bytes\n", catalog[0].Naverage, catalog[0].Naverage*AverageSize);
+      fprintf (stderr, "measure: %d = %d bytes\n", catalog[0].Nmeasure, catalog[0].Nmeasure*MeasureSize);
+      fprintf (stderr, "missing: %d = %d bytes\n", catalog[0].Nmissing, catalog[0].Nmissing*MissingSize);
+      fprintf (stderr, "secfilt: %d = %d bytes\n", catalog[0].Nsecfilt, catalog[0].Nsecfilt*SecFiltSize*catalog[0].Naverage);
+      fprintf (stderr, "expect: %d, found: %d\n", size, (int)filestatus.st_size);
+    }
+    return (FALSE);
+  } 
+  if (size < filestatus.st_size) {
+    if (VERBOSE) fprintf (stderr, "warning: file larger than expected\n");
+  } 
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", catalog[0].filename);
+    return (TRUE);
+  }
+
+  /* read and convert the averages (use a macro to clean this up?) */
+  if (mode & LOAD_AVES) {
+    catalog[0].average = ReadRawAverage (catalog[0].f, catalog[0].Naverage, catalog[0].catformat);
+  } else {
+    /* skip over averages */
+    Nskip = catalog[0].Naverage * AverageSize;
+    fseek (f, Nskip, SEEK_CUR); 
+  }    
+  
+  /* read and convert the measures (use a macro to clean this up?) */
+  if (mode & LOAD_MEAS) {
+    catalog[0].measure = ReadRawMeasure (catalog[0].f, catalog[0].Nmeasure, catalog[0].catformat);
+  } else {
+    /* skip over measures */
+    Nskip = catalog[0].Nmeasure * MeasureSize;
+    fseek (f, Nskip, SEEK_CUR); 
+  }    
+
+  /* read and convert missing */
+  if (mode & LOAD_MISS) {
+    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+    Nitems = catalog[0].Nmissing;
+    nitems = fread (catalog[0].missing, MissingSize, Nitems, f);
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read missing from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+    fits_convert_Missing (catalog[0].missing, MissingSize, Nitems);
+  } else {
+    /* skip over missings */
+    Nskip = catalog[0].Nmissing * MissingSize;
+    fseek (f, Nskip, SEEK_CUR); 
+  }
+  
+  /* read and convert secfilt */
+  if (mode & LOAD_SECF) {
+    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+    catalog[0].secfilt = ReadRawSecFilt (catalog[0].f, Nitems, catalog[0].catformat);
+  } else {
+    /* skip over secfilts */
+    Nskip = catalog[0].Nsecfilt * catalog[0].Naverage * SecFiltSize;
+    fseek (f, Nskip, SEEK_CUR); 
+  }
+
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
+	   catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);
+
+  /* check data integrity */
+  if (mode & LOAD_AVES) {
+    for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+      Nmeas += catalog[0].average[i].Nm; 
+      Nmiss += catalog[0].average[i].Nn; 
+    }
+    if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+      if (VERBOSE) {
+	fprintf (stderr, "****** data in catalog %s is corrupt, sums don't check\n", catalog[0].filename);
+	fprintf (stderr, "****** Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+	fprintf (stderr, "****** Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+      }
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
+
+int save_catalog_raw (Catalog *catalog, char VERBOSE) {
+
+  int Nitems, nitems;
+  FILE *f;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  /* make sure header is consistent with data */
+  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
+
+  /* specify the appropriate data format */
+  if (catalog[0].catformat == DVO_FORMAT_INTERNAL)  fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "INTERNAL");
+  if (catalog[0].catformat == DVO_FORMAT_LONEOS)    fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "LONEOS");
+  if (catalog[0].catformat == DVO_FORMAT_ELIXIR)    fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "ELIXIR");
+  if (catalog[0].catformat == DVO_FORMAT_PANSTARRS) fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PANSTARRS");
+
+  /* rewind file pointers and truncate file */
+  f = catalog[0].f;
+  fseek (f, 0, SEEK_SET);
+  ftruncate (fileno (catalog[0].f), 0);
+
+  /* write header data (use fits_write_header?) */
+  nitems = fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f);
+  if (nitems != catalog[0].header.size) {
+    if (VERBOSE) fprintf (stderr, "failed to write header\n");
+    return (FALSE);
+  }
+
+  /* write averages and measures */
+  WriteRawAverage (f, catalog[0].average, catalog[0].Naverage, catalog[0].catformat);
+  WriteRawMeasure (f, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
+
+  /* write missing data */
+  Nitems = catalog[0].Nmissing;
+  fits_convert_Missing (catalog[0].missing, sizeof(Missing), Nitems);
+  nitems = fwrite (catalog[0].missing, sizeof(Missing), Nitems, f);
+  if (nitems != Nitems) {
+    if (VERBOSE) fprintf (stderr, "failed to write catalog file missing %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+
+  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+  WriteRawSecFilt (f, catalog[0].secfilt, Nitems, catalog[0].catformat);
+  return (TRUE);
+}
+
+/*** 
+     some warnings:
+     - need to be wary of exit condition errors
+***/
+
+/** Average / Raw Table conversions **/
+
+Average *ReadRawAverage (FILE *f, int Naverage, int format) {
+
+  int nitems;
+  Average *average;
+  AverageElixir *tmpAverageElixir;
+  AverageLoneos *tmpAverageLoneos;
+  AveragePanstarrs *tmpAveragePanstarrs;
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL:
+      ALLOCATE (average, Average, MAX (Naverage, 1));
+      nitems = fread (average, sizeof(Average), Naverage, f);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
+	return (NULL);
+      }
+      fits_convert_Average (average, sizeof(Average), Naverage);
+      break;
+    case DVO_FORMAT_ELIXIR:
+      ALLOCATE (tmpAverageElixir, AverageElixir, MAX (Naverage, 1));
+      nitems = fread (tmpAverageElixir, sizeof(AverageElixir), Naverage, f);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
+	return (NULL);
+      }
+      fits_convert_AverageElixir (tmpAverageElixir, sizeof(AverageElixir), Naverage);
+      average = AverageElixirToInternal (tmpAverageElixir, Naverage);
+      free (tmpAverageElixir);
+      break;
+    case DVO_FORMAT_LONEOS:
+      ALLOCATE (tmpAverageLoneos, AverageLoneos, MAX (Naverage, 1));
+      nitems = fread (tmpAverageLoneos, sizeof(AverageLoneos), Naverage, f);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
+	return (NULL);
+      }
+      fits_convert_AverageLoneos (tmpAverageLoneos, sizeof(AverageLoneos), Naverage);
+      average = AverageLoneosToInternal (tmpAverageLoneos, Naverage);
+      free (tmpAverageLoneos);
+      break;
+    case DVO_FORMAT_PANSTARRS:
+      ALLOCATE (tmpAveragePanstarrs, AveragePanstarrs, MAX (Naverage, 1));
+      nitems = fread (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage, f);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
+	return (NULL);
+      }
+      fits_convert_AveragePanstarrs (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage);
+      average = AveragePanstarrsToInternal (tmpAveragePanstarrs, Naverage);
+      free (tmpAveragePanstarrs);
+      break;
+    default:
+      fprintf (stderr, "error reading measures\n");
+      return (NULL);
+  }
+  return (average);
+}
+
+/* accepts and converts internal average formats and outputs 
+   raw data in the specified format */
+int WriteRawAverage (FILE *f, Average *average, int Naverage, int format) {
+
+  int nitems;
+  AverageElixir *tmpAverageElixir;
+  AverageLoneos *tmpAverageLoneos;
+  AveragePanstarrs *tmpAveragePanstarrs;
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL:
+      fits_convert_Average (average, sizeof(Average), Naverage);
+      nitems = fwrite (average, sizeof(Average), Naverage, f);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_ELIXIR:
+      tmpAverageElixir = AverageInternalToElixir (average, Naverage);
+      fits_convert_AverageElixir (tmpAverageElixir, sizeof(AverageElixir), Naverage);
+      nitems = fwrite (tmpAverageElixir, sizeof(AverageElixir), Naverage, f);
+      free (tmpAverageElixir);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_LONEOS:
+      tmpAverageLoneos = AverageInternalToLoneos (average, Naverage);
+      fits_convert_AverageLoneos (tmpAverageLoneos, sizeof(AverageLoneos), Naverage);
+      nitems = fwrite (tmpAverageLoneos, sizeof(AverageLoneos), Naverage, f);
+      free (tmpAverageLoneos);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_PANSTARRS:
+      tmpAveragePanstarrs = AverageInternalToPanstarrs (average, Naverage);
+      fits_convert_AveragePanstarrs (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage);
+      nitems = fwrite (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage, f);
+      free (tmpAveragePanstarrs);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
+	return (FALSE);
+      }
+      break;
+    default:
+      fprintf (stderr, "error writing averages\n");
+      return (FALSE);
+  }
+  return (TRUE);
+}
+
+/** Average / Raw Table conversions **/
+
+Measure *ReadRawMeasure (FILE *f, int Nmeasure, int format) {
+
+  int nitems;
+  Measure *measure;
+  MeasureElixir *tmpMeasureElixir;
+  MeasureLoneos *tmpMeasureLoneos;
+  MeasurePanstarrs *tmpMeasurePanstarrs;
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL:
+      ALLOCATE (measure, Measure, MAX (Nmeasure, 1));
+      nitems = fread (measure, sizeof(Measure), Nmeasure, f);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
+	return (NULL);
+      }
+      fits_convert_Measure (measure, sizeof(Measure), Nmeasure);
+      break;
+    case DVO_FORMAT_ELIXIR:
+      ALLOCATE (tmpMeasureElixir, MeasureElixir, MAX (Nmeasure, 1));
+      nitems = fread (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure, f);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
+	return (NULL);
+      }
+      fits_convert_MeasureElixir (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure);
+      measure = MeasureElixirToInternal (tmpMeasureElixir, Nmeasure);
+      free (tmpMeasureElixir);
+      break;
+    case DVO_FORMAT_LONEOS:
+      ALLOCATE (tmpMeasureLoneos, MeasureLoneos, MAX (Nmeasure, 1));
+      nitems = fread (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure, f);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
+	return (NULL);
+      }
+      fits_convert_MeasureLoneos (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure);
+      measure = MeasureLoneosToInternal (tmpMeasureLoneos, Nmeasure);
+      free (tmpMeasureLoneos);
+      break;
+    case DVO_FORMAT_PANSTARRS:
+      ALLOCATE (tmpMeasurePanstarrs, MeasurePanstarrs, MAX (Nmeasure, 1));
+      nitems = fread (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure, f);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
+	return (NULL);
+      }
+      fits_convert_MeasurePanstarrs (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure);
+      measure = MeasurePanstarrsToInternal (tmpMeasurePanstarrs, Nmeasure);
+      free (tmpMeasurePanstarrs);
+      break;
+    default:
+      fprintf (stderr, "error reading measures\n");
+      return (NULL);
+  }
+  return (measure);
+}
+
+/* accepts and converts internal measure formats and outputs 
+   raw data in the specified format */
+int WriteRawMeasure (FILE *f, Measure *measure, int Nmeasure, int format) {
+
+  int nitems;
+  MeasureElixir *tmpMeasureElixir;
+  MeasureLoneos *tmpMeasureLoneos;
+  MeasurePanstarrs *tmpMeasurePanstarrs;
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL:
+      fits_convert_Measure (measure, sizeof(Measure), Nmeasure);
+      nitems = fwrite (measure, sizeof(Measure), Nmeasure, f);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_ELIXIR:
+      tmpMeasureElixir = MeasureInternalToElixir (measure, Nmeasure);
+      fits_convert_MeasureElixir (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure);
+      nitems = fwrite (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure, f);
+      free (tmpMeasureElixir);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_LONEOS:
+      tmpMeasureLoneos = MeasureInternalToLoneos (measure, Nmeasure);
+      fits_convert_MeasureLoneos (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure);
+      nitems = fwrite (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure, f);
+      free (tmpMeasureLoneos);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_PANSTARRS:
+      tmpMeasurePanstarrs = MeasureInternalToPanstarrs (measure, Nmeasure);
+      fits_convert_MeasurePanstarrs (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure);
+      nitems = fwrite (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure, f);
+      free (tmpMeasurePanstarrs);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
+	return (FALSE);
+      }
+      break;
+    default:
+      fprintf (stderr, "error writing measures\n");
+      return (FALSE);
+  }
+  return (TRUE);
+}
+
+/** SecFilt / Raw Table conversions **/
+
+SecFilt *ReadRawSecFilt (FILE *f, int Nsecfilt, int format) {
+
+  int nitems;
+  SecFilt *secfilt;
+  SecFiltElixir *tmpSecFiltElixir;
+  SecFiltLoneos *tmpSecFiltLoneos;
+  SecFiltPanstarrs *tmpSecFiltPanstarrs;
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL:
+      ALLOCATE (secfilt, SecFilt, MAX (Nsecfilt, 1));
+      nitems = fread (secfilt, sizeof(SecFilt), Nsecfilt, f);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (NULL);
+      }
+      fits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
+      break;
+    case DVO_FORMAT_ELIXIR:
+      ALLOCATE (tmpSecFiltElixir, SecFiltElixir, MAX (Nsecfilt, 1));
+      nitems = fread (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt, f);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (NULL);
+      }
+      fits_convert_SecFiltElixir (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt);
+      secfilt = SecFiltElixirToInternal (tmpSecFiltElixir, Nsecfilt);
+      free (tmpSecFiltElixir);
+      break;
+    case DVO_FORMAT_LONEOS:
+      ALLOCATE (tmpSecFiltLoneos, SecFiltLoneos, MAX (Nsecfilt, 1));
+      nitems = fread (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt, f);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (NULL);
+      }
+      fits_convert_SecFiltLoneos (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt);
+      secfilt = SecFiltLoneosToInternal (tmpSecFiltLoneos, Nsecfilt);
+      free (tmpSecFiltLoneos);
+      break;
+    case DVO_FORMAT_PANSTARRS:
+      ALLOCATE (tmpSecFiltPanstarrs, SecFiltPanstarrs, MAX (Nsecfilt, 1));
+      nitems = fread (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt, f);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (NULL);
+      }
+      fits_convert_SecFiltPanstarrs (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt);
+      secfilt = SecFiltPanstarrsToInternal (tmpSecFiltPanstarrs, Nsecfilt);
+      free (tmpSecFiltPanstarrs);
+      break;
+    default:
+      fprintf (stderr, "error reading measures\n");
+      return (NULL);
+  }
+  return (secfilt);
+}
+
+/* accepts and converts internal secfilt formats and outputs 
+   raw data in the specified format */
+int WriteRawSecFilt (FILE *f, SecFilt *secfilt, int Nsecfilt, int format) {
+
+  int nitems;
+  SecFiltElixir *tmpSecFiltElixir;
+  SecFiltLoneos *tmpSecFiltLoneos;
+  SecFiltPanstarrs *tmpSecFiltPanstarrs;
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL:
+      fits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
+      nitems = fwrite (secfilt, sizeof(SecFilt), Nsecfilt, f);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_ELIXIR:
+      tmpSecFiltElixir = SecFiltInternalToElixir (secfilt, Nsecfilt);
+      fits_convert_SecFiltElixir (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt);
+      nitems = fwrite (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt, f);
+      free (tmpSecFiltElixir);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_LONEOS:
+      tmpSecFiltLoneos = SecFiltInternalToLoneos (secfilt, Nsecfilt);
+      fits_convert_SecFiltLoneos (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt);
+      nitems = fwrite (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt, f);
+      free (tmpSecFiltLoneos);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (FALSE);
+      }
+      break;
+    case DVO_FORMAT_PANSTARRS:
+      tmpSecFiltPanstarrs = SecFiltInternalToPanstarrs (secfilt, Nsecfilt);
+      fits_convert_SecFiltPanstarrs (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt);
+      nitems = fwrite (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt, f);
+      free (tmpSecFiltPanstarrs);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (FALSE);
+      }
+      break;
+    default:
+      fprintf (stderr, "error writing secfilts\n");
+      return (FALSE);
+  }
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/libohana/src/dvo_catalog_split.c
===================================================================
--- /trunk/Ohana/src/libohana/src/dvo_catalog_split.c	(revision 5228)
+++ /trunk/Ohana/src/libohana/src/dvo_catalog_split.c	(revision 5228)
@@ -0,0 +1,579 @@
+# include <ohana.h>
+# include <dvo.h>
+
+int load_catalog_split (Catalog *catalog, char mode, int VERBOSE) {
+
+  int Nitems, Nexpect, Naverage, Nmeasure, Nmissing, Nsecfilt;
+  char *path, string[80];
+  Header header;
+  Matrix matrix;
+  FTable ftable;
+  Catalog *measure, *missing, *secfilt;
+
+  /* ftable header storage for below */
+  ftable.header = &header;
+
+  /* needed to find the split files below */
+  path = pathname (catalog[0].filename);
+
+  /* get the components from the header - these duplicate information in the split files (NAXIS2) */
+  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &Naverage)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &Nmeasure)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &Nmissing)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;
+
+  /**  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].average = NULL;
+  catalog[0].measure = NULL;
+  catalog[0].missing = NULL;
+  catalog[0].secfilt = NULL;
+
+  /* XXX EAM : validate table mode */
+
+  /*** Average Table ***/
+
+  if (mode & 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 */
+    if (!fits_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 (!fits_fread_header (catalog[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average header");
+      return (FALSE);
+    }
+    /* read Average table data */
+    if (!fits_fread_ftable_data (catalog[0].f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average data");
+      return (FALSE);
+    }
+    catalog[0].average = FtableToAverage (&ftable, &catalog[0].Naverage, &catalog[0].catformat);
+    if (Naverage != catalog[0].Naverage) {
+      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naverage);
+    }
+    fits_free_header (&header);
+  } 
+
+  /*** Measure Table ***/
+
+  measure = NULL;
+  if (mode & LOAD_MEAS) {
+    ALLOCATE (measure, Catalog, 1);
+
+    /* get split filename from main header (paths relative to cpt file) */
+    if (!fits_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 (lock_catalog (measure, catalog[0].lockmode) != 1) {
+      fprintf (stderr, "cannot access measure file %s\n", measure[0].filename);
+      exit (2);
+    }
+
+    /* read PHU */
+    if (!fits_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 (!fits_fread_matrix (measure[0].f, &matrix, &measure[0].header)) {
+      if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+      return (FALSE);
+    }
+    /* read Measure table header */
+    if (!fits_fread_header (measure[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read measure PHU header");
+      return (FALSE);
+    }
+    /* read Measure table data */
+    if (!fits_fread_ftable_data (measure[0].f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure data");
+      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);
+    }
+    fits_free_header (&header);
+    fits_free_matrix (&matrix);
+  }
+  catalog[0].measure_catalog = measure;
+
+  /*** Missing Table ***/
+
+  missing = NULL;
+  if (mode & LOAD_MISS) {
+    ALLOCATE (missing, Catalog, 1);
+
+    /* get split filename from main header (paths relative to cpt file) */
+    if (!fits_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 */
+    if (lock_catalog (missing, catalog[0].lockmode) != 1) {
+      fprintf (stderr, "cannot access missing file %s\n", missing[0].filename);
+      exit (2);
+    }
+
+    /* read PHU */
+    if (!fits_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 (!fits_fread_matrix (missing[0].f, &matrix, &missing[0].header)) {
+      if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+      return (FALSE);
+    }
+    /* read Missing table header */
+    if (!fits_fread_header (missing[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing header");
+      return (FALSE);
+    }
+    /* read Missing table data */
+    if (!fits_fread_ftable_data (missing[0].f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing data");
+      return (FALSE);
+    }
+    /* no conversions currently defined */
+    catalog[0].missing = fits_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);
+    }
+    fits_free_header (&header);
+    fits_free_matrix (&matrix);
+  } 
+  catalog[0].missing_catalog = missing;
+
+  /*** Secfilt Table ***/
+
+  secfilt = NULL;
+  if (mode & LOAD_SECF) {
+    ALLOCATE (secfilt, Catalog, 1);
+  
+    /* get split filename from main header (paths relative to cpt file) */
+    if (!fits_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 (lock_catalog (secfilt, catalog[0].lockmode) != 1) {
+      fprintf (stderr, "cannot access secfilt file %s\n", secfilt[0].filename);
+      exit (2);
+    }
+
+    /* read PHU */
+    if (!fits_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 (!fits_fread_matrix (secfilt[0].f, &matrix, &secfilt[0].header)) {
+      if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+      return (FALSE);
+    }
+    /* read secfilt table header */
+    if (!fits_fread_header (secfilt[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table secfilt header");
+      return (FALSE);
+    }
+    /* read secfilt table data */
+    if (!fits_fread_ftable_data (secfilt[0].f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table secfilt data");
+      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);
+    }
+    fits_free_header (&header);
+    fits_free_matrix (&matrix);
+  } 
+  catalog[0].secfilt_catalog = secfilt;
+
+  return (TRUE);
+}
+
+/* save_catalog_split writes complete new files from scratch */
+
+int save_catalog_split (Catalog *catalog, char VERBOSE) {
+
+  int Nitems;
+  Matrix matrix;
+  Header header;
+  FTable ftable;
+  Catalog *measure, *missing, *secfilt;
+
+  ftable.header = &header;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  /* make sure header is consistent with data */
+  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
+  fits_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 (!fits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+    fprintf (stderr, "can't write primary header");
+    return (FALSE);
+  }
+
+  /* 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? */
+    fits_create_matrix (&catalog[0].header, &matrix);
+    if (!fits_fwrite_matrix  (catalog[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out Average table (convert to FITS table format) */
+    AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat);
+    if (!fits_fwrite_Theader (catalog[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (catalog[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  /*** Measure Table ***/
+
+  if (catalog[0].measure != NULL) {
+
+    measure = catalog[0].measure_catalog;
+
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (measure[0].f, 0, SEEK_SET);
+    ftruncate (fileno (measure[0].f), 0);
+
+    /* write table PHU header */
+    if (!fits_fwrite_header  (measure[0].f, &measure[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      return (FALSE);
+    }
+
+    /* this is probably a NOP, do I have to keep it in? */
+    fits_create_matrix (&measure[0].header, &matrix);
+    if (!fits_fwrite_matrix  (measure[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out Measure table (convert to FITS table format) */
+    MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
+    if (!fits_fwrite_Theader (measure[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (measure[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  /*** Missing Table ***/
+
+  if (catalog[0].missing != NULL) {
+
+    missing = catalog[0].missing_catalog;
+
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (missing[0].f, 0, SEEK_SET);
+    ftruncate (fileno (missing[0].f), 0);
+
+    /* write table PHU header */
+    if (!fits_fwrite_header  (missing[0].f, &missing[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      return (FALSE);
+    }
+
+    /* this is probably a NOP, do I have to keep it in? */
+    fits_create_matrix (&missing[0].header, &matrix);
+    if (!fits_fwrite_matrix  (missing[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out Missing table (convert to FITS table format) */
+    fits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
+    if (!fits_fwrite_Theader (missing[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (missing[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  /*** Secfilt Table ***/
+
+  if (catalog[0].secfilt != NULL) {
+
+    secfilt = catalog[0].secfilt_catalog;
+
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (secfilt[0].f, 0, SEEK_SET);
+    ftruncate (fileno (secfilt[0].f), 0);
+
+    /* write table PHU header */
+    if (!fits_fwrite_header  (secfilt[0].f, &secfilt[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      return (FALSE);
+    }
+
+    /* this is probably a NOP, do I have to keep it in? */
+    fits_create_matrix (&secfilt[0].header, &matrix);
+    if (!fits_fwrite_matrix  (secfilt[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out SecFilt table (convert to FITS table format) */
+    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+    SecFiltToFtable (&ftable, catalog[0].secfilt, Nitems, catalog[0].catformat);
+    if (!fits_fwrite_Theader (secfilt[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (secfilt[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  return (TRUE);
+}
+
+/* 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 update_catalog_split (Catalog *catalog, char VERBOSE) {
+
+  int Nitems;
+  Matrix matrix;
+  Header header;
+  FTable ftable;
+  Catalog *measure, *missing, *secfilt;
+
+  ftable.header = &header;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  /* make sure header is consistent with data */
+  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
+  fits_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 (!fits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+    fprintf (stderr, "can't write primary header");
+    return (FALSE);
+  }
+
+  /* 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? */
+    fits_create_matrix (&catalog[0].header, &matrix);
+    if (!fits_fwrite_matrix  (catalog[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out Average table (convert to FITS table format) */
+    AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat);
+    if (!fits_fwrite_Theader (catalog[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (catalog[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  /*** Measure Table ***/
+
+  if (catalog[0].measure != NULL) {
+
+    measure = catalog[0].measure_catalog;
+
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (measure[0].f, 0, SEEK_SET);
+    ftruncate (fileno (measure[0].f), 0);
+
+    /* write table PHU header */
+    if (!fits_fwrite_header  (measure[0].f, &measure[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      return (FALSE);
+    }
+
+    /* this is probably a NOP, do I have to keep it in? */
+    fits_create_matrix (&measure[0].header, &matrix);
+    if (!fits_fwrite_matrix  (measure[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out Measure table (convert to FITS table format) */
+    MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
+    if (!fits_fwrite_Theader (measure[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (measure[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  /*** Missing Table ***/
+
+  if (catalog[0].missing != NULL) {
+
+    missing = catalog[0].missing_catalog;
+
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (missing[0].f, 0, SEEK_SET);
+    ftruncate (fileno (missing[0].f), 0);
+
+    /* write table PHU header */
+    if (!fits_fwrite_header  (missing[0].f, &missing[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      return (FALSE);
+    }
+
+    /* this is probably a NOP, do I have to keep it in? */
+    fits_create_matrix (&missing[0].header, &matrix);
+    if (!fits_fwrite_matrix  (missing[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out Missing table (convert to FITS table format) */
+    fits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
+    if (!fits_fwrite_Theader (missing[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (missing[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  /*** Secfilt Table ***/
+
+  if (catalog[0].secfilt != NULL) {
+
+    secfilt = catalog[0].secfilt_catalog;
+
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (secfilt[0].f, 0, SEEK_SET);
+    ftruncate (fileno (secfilt[0].f), 0);
+
+    /* write table PHU header */
+    if (!fits_fwrite_header  (secfilt[0].f, &secfilt[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      return (FALSE);
+    }
+
+    /* this is probably a NOP, do I have to keep it in? */
+    fits_create_matrix (&secfilt[0].header, &matrix);
+    if (!fits_fwrite_matrix  (secfilt[0].f, &matrix)) {
+      fprintf (stderr, "can't write primary matrix");
+      return (FALSE);
+    }
+    fits_free_matrix (&matrix);
+
+    /* write out SecFilt table (convert to FITS table format) */
+    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+    SecFiltToFtable (&ftable, catalog[0].secfilt, Nitems, catalog[0].catformat);
+    if (!fits_fwrite_Theader (secfilt[0].f, &header)) {
+      fprintf (stderr, "can't write table header");
+      return (FALSE);
+    }
+    if (!fits_fwrite_table (secfilt[0].f, &ftable)) {
+      fprintf (stderr, "can't write table data");
+      return (FALSE);
+    }
+    fits_free_table (&ftable);
+    fits_free_header (&header);
+  }
+
+  return (TRUE);
+}
+
+/* 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
+   to point at the corresponding entries from the elements on the chain. An
+   unloaded entry has a null pointer here.
+*/
+
+/* XXX EAM : this file needs work on the error exit conditions and memory leaks, esp under errors */
Index: unk/Ohana/src/libohana/src/phot_catalog.c
===================================================================
--- /trunk/Ohana/src/libohana/src/phot_catalog.c	(revision 5227)
+++ 	(revision )
@@ -1,105 +1,0 @@
-# include <ohana.h>
-# include <dvo.h>
-
-/* possible exit status for lock_catalog: 
-   0 - failure (including lock failure)
-   1 - success
-   2 - empty file (file may be open or closed!) 
-*/
-
-int lock_catalog (Catalog *catalog, int lockmode) {
-
-  int dbstate;
-
-  /* set lock on database, create stream f */
-  catalog[0].f = NULL;
-  catalog[0].f = fsetlockfile (catalog[0].filename, 3600.0, lockmode, &dbstate);
-  if (dbstate == LCK_MISSING) return (2);
-  if (dbstate == LCK_EMPTY)   return (2);
-  if (catalog[0].f == NULL)   return (0);
-
-  fseek (catalog[0].f, 0, SEEK_SET);
-  catalog[0].lockmode = lockmode;
-
-  return (1);
-}
-
-int unlock_catalog (Catalog *catalog) {
-
-  int dbstate;
-
-  if (catalog[0].f == (FILE *) NULL) return (2);
-  fclearlockfile (catalog[0].filename, catalog[0].f, catalog[0].lockmode, &dbstate);
-  return (1);
-}
-
-int load_catalog (Catalog *catalog, char mode, int VERBOSE) {
-  
-  int Naxis, Nread;
-  char buffer[241];
-
-  /** we will have to check catmode for MYSQL before reading from the file **/
-
-  /* check for mode RAW (NAXIS == 2 in FITS header 3) */
-  bzero (buffer, 241);
-  fseek (catalog[0].f, 0, SEEK_SET);
-  Nread = fread (buffer, 1, 240, catalog[0].f);
-  if (Nread != 240) {
-    if (VERBOSE) fprintf (stderr, "can't determine image db mode\n");
-    return (FALSE);
-  }
-  Nread = sscanf (&buffer[160], "NAXIS   = %d", &Naxis);
-  if (Nread != 1) {
-    if (VERBOSE) fprintf (stderr, "can't determine catalog db mode\n");
-    return (FALSE);
-  }
-  fseek (catalog[0].f, 0, SEEK_SET);
-
-  /* the test for MEF vs SPLIT should be EXTEND = T */
-
-  /* currenly, the mode information is carried per table.
-     the user-set value of catmode will set the output mode for new tables
-     an old table will keep its mode
-  */
-
-  catalog[0].catmode = DVO_MODE_MEF;
-  catalog[0].catformat = DVO_FORMAT_UNDEF;
-  if (Naxis == 2) catalog[0].catmode = DVO_MODE_RAW;
-
-  switch (catalog[0].catmode) {
-    case DVO_MODE_RAW:
-      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_RAW)\n");
-      load_catalog_raw (catalog, mode, VERBOSE);
-      break;
-    case DVO_MODE_MEF:
-      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_MEF)\n");
-      load_catalog_mef (catalog, mode, VERBOSE);
-      break;
-    default:
-      fprintf (stderr, "error getting catalog mode\n");
-      exit (2);
-  }
-  return (TRUE);
-}
-
-int save_catalog (Catalog *catalog, char VERBOSE) {
-
-  switch (catalog[0].catmode) {
-    case DVO_MODE_RAW:
-      save_catalog_raw (catalog, VERBOSE);
-      break;
-    case DVO_MODE_MEF:
-      save_catalog_mef (catalog, VERBOSE);
-      break;
-    default:
-      fprintf (stderr, "invalid catalog mode\n");
-      exit (2);
-  }
-  return (TRUE);
-}
-
-/*
-  mode   : items to read (LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF)
-  format : what structure on disk (INTERNAL, ELIXIR, LONEOS, PANSTARRS)
-  style  : raw, mef, split, mysql
-*/
Index: unk/Ohana/src/libohana/src/phot_catalog_mef.c
===================================================================
--- /trunk/Ohana/src/libohana/src/phot_catalog_mef.c	(revision 5227)
+++ 	(revision )
@@ -1,240 +1,0 @@
-# include <ohana.h>
-# include <dvo.h>
-
-int load_catalog_mef (Catalog *catalog, char mode, int VERBOSE) {
-  
-  int Nitems, Nbytes, Nexpect, Naverage, Nmeasure, Nmissing, Nsecfilt;
-  FILE *f;
-
-  Header header;
-  Matrix matrix;
-  FTable ftable;
-
-  f = catalog[0].f;
-  fseek (f, 0, SEEK_SET);
-  ftable.header = &header;
-
-  /* read PHU */
-  if (!fits_load_header (f, &catalog[0].header)) {
-    if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", catalog[0].filename);
-    return (FALSE);
-  }
-  /* matrix should be empty */
-  if (!fits_fread_matrix (f, &matrix, &catalog[0].header)) {
-    if (VERBOSE) fprintf (stderr, "can't read primary matrix");
-    return (FALSE);
-  }
-  /* get the components from the header */
-  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &Naverage)) return (FALSE);
-  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &Nmeasure)) return (FALSE);
-  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &Nmissing)) return (FALSE);
-  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;
-
-  /**  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;
-
-  /* validate table mode */
-
-  /* read Average table header */
-  if (!fits_fread_header (f, &header)) {
-    if (VERBOSE) fprintf (stderr, "can't read table average header");
-    return (FALSE);
-  }
-  /* read Average table data (or skip) */
-  if (mode & LOAD_AVES) {
-    if (!fits_fread_ftable_data (f, &ftable)) {
-      if (VERBOSE) fprintf (stderr, "can't read table average data");
-      return (FALSE);
-    }
-    catalog[0].average = FtableToAverage (&ftable, &catalog[0].Naverage, &catalog[0].catformat);
-    if (Naverage != catalog[0].Naverage) {
-      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naverage);
-    }
-  } else {
-    Nbytes = fits_matrix_size (&header);
-    fseek (f, Nbytes, SEEK_CUR);
-  }
-  fits_free_header (&header);
-  /** free the ftable or not? data is being used still..? **/
-
-  /* read Measure table header */
-  if (!fits_fread_header (f, &header)) {
-    if (VERBOSE) fprintf (stderr, "can't read table measure header");
-    return (FALSE);
-  }
-  /* read Measure table data */
-  if (mode & LOAD_MEAS) {
-    if (!fits_fread_ftable_data (f, &ftable)) {
-      if (VERBOSE) fprintf (stderr, "can't read table measure data");
-      return (FALSE);
-    }
-    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);
-    }
-  } else {
-    Nbytes = fits_matrix_size (&header);
-    fseek (f, Nbytes, SEEK_CUR);
-  }
-
-  /* read Missing table header */
-  if (!fits_fread_header (f, &header)) {
-    if (VERBOSE) fprintf (stderr, "can't read table missing header");
-    return (FALSE);
-  }
-  /* read Missing table data */
-  if (mode & LOAD_MISS) {
-    if (!fits_fread_ftable_data (f, &ftable)) {
-      if (VERBOSE) fprintf (stderr, "can't read table missing data");
-      return (FALSE);
-    }
-    /* no conversions currently defined */
-    catalog[0].missing = fits_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);
-    }
-  } else {
-    Nbytes = fits_matrix_size (&header);
-    fseek (f, Nbytes, SEEK_CUR);
-  }
-
-  // catalog[0].secfilt = fits_table_get_SecFilt (&ftable, &Nitems, NULL);
-  // catalog[0].Nsecfilt = Nitems / catalog[0].Naverage;
-
-  /* read secfilt table header */
-  if (!fits_fread_header (f, &header)) {
-    if (VERBOSE) fprintf (stderr, "can't read table secfilt header");
-    return (FALSE);
-  }
-  /* read secfilt table data */
-  if (mode & LOAD_SECF) {
-    if (!fits_fread_ftable_data (f, &ftable)) {
-      if (VERBOSE) fprintf (stderr, "can't read table secfilt data");
-      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);
-    }
-  } else {
-    /* no real need to skip the data array here... */
-    Nbytes = fits_matrix_size (&header);
-    fseek (f, Nbytes, SEEK_CUR);
-  }
-  return (TRUE);
-}
-
-/* save_catalog_mef writes a complete new file from scratch */
-
-int save_catalog_mef (Catalog *catalog, char VERBOSE) {
-
-  int Nitems;
-  FILE *f;
-  Matrix matrix;
-  Header header;
-  FTable ftable;
-
-  if (catalog[0].Naverage == 0) {
-    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
-    return (TRUE);
-  }
-
-  /* make sure header is consistent with data */
-  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
-  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
-  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
-  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
-  fits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
-
-  f = catalog[0].f;
-  /* rewind file pointers and truncate */
-  fseek (f, 0, SEEK_SET);
-  ftruncate (fileno (catalog[0].f), 0);
-  ftable.header = &header;
-
-  /* write table PHU header */
-  if (!fits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
-    fprintf (stderr, "can't write primary header");
-    return (FALSE);
-  }
-
-  /* this is probably a NOP, do I have to keep it in? */
-  fits_create_matrix (&catalog[0].header, &matrix);
-  if (!fits_fwrite_matrix  (catalog[0].f, &matrix)) {
-    fprintf (stderr, "can't write primary matrix");
-    return (FALSE);
-  }
-  fits_free_matrix (&matrix);
-
-  /* write out Average table (convert to FITS table format) */
-  AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat);
-  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
-    fprintf (stderr, "can't write table header");
-    return (FALSE);
-  }
-  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
-    fprintf (stderr, "can't write table data");
-    return (FALSE);
-  }
-  fits_free_table (&ftable);
-  fits_free_header (&header);
-
-  /* write out Measure table (convert to FITS table format) */
-  MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
-  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
-    fprintf (stderr, "can't write table header");
-    return (FALSE);
-  }
-  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
-    fprintf (stderr, "can't write table data");
-    return (FALSE);
-  }
-  fits_free_table (&ftable);
-  fits_free_header (&header);
-
-  /* write out Missing table (convert to FITS table format) */
-  fits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
-  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
-    fprintf (stderr, "can't write table header");
-    return (FALSE);
-  }
-  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
-    fprintf (stderr, "can't write table data");
-    return (FALSE);
-  }
-  fits_free_table (&ftable);
-  fits_free_header (&header);
-
-  /* write out SecFilt table (convert to FITS table format) */
-  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
-  SecFiltToFtable (&ftable, catalog[0].secfilt, Nitems, catalog[0].catformat);
-  if (!fits_fwrite_Theader (catalog[0].f, &header)) {
-    fprintf (stderr, "can't write table header");
-    return (FALSE);
-  }
-  if (!fits_fwrite_table (catalog[0].f, &ftable)) {
-    fprintf (stderr, "can't write table data");
-    return (FALSE);
-  }
-  fits_free_table (&ftable);
-  fits_free_header (&header);
-
-  return (TRUE);
-}
-
-/*
-   catalog data is:
-   header (bitpix == 8)
-   matrix (empty)
-   average header
-   average table
-   measure header
-   measure table
-   missing header
-   missing table
-   secfilt header
-   secfilt table
-*/
-   
Index: unk/Ohana/src/libohana/src/phot_catalog_raw.c
===================================================================
--- /trunk/Ohana/src/libohana/src/phot_catalog_raw.c	(revision 5227)
+++ 	(revision )
@@ -1,588 +1,0 @@
-# include <ohana.h>
-# include <dvo.h>
-
-/* read data from raw-style catalog file; set data format values based on file */
-
-int load_catalog_raw (Catalog *catalog, char mode, int VERBOSE) {
-  
-  int Nitems, nitems;
-  int i, Nmeas, Nmiss, size;
-  int NewMeasure, Nskip;
-  int AverageSize, MeasureSize, MissingSize, SecFiltSize;
-  FILE *f;
-  struct stat filestatus;
-  char format[80], telescope[80];
-
-  f = catalog[0].f;
-  fseek (f, 0, SEEK_SET);
-
-  /* read catalog header */
-  if (!fits_load_header (f, &catalog[0].header)) {
-    if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", catalog[0].filename);
-    return (FALSE);
-  }
-
-  /* this is done by the load anyway... */
-  fseek (f, catalog[0].header.size, SEEK_SET); 
-
-  /* get the components from the header */
-  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
-  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
-  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
-  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
-  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;
-
-  /* determine catalog format */
-  catalog[0].catformat = DVO_FORMAT_UNDEF;
-  if (fits_scan (&catalog[0].header, "FORMAT",  "%s", 1, format)) {
-    if (!strcmp (format, "INTERNAL")) catalog[0].catformat = DVO_FORMAT_INTERNAL;
-    if (!strcmp (format, "LONEOS")) catalog[0].catformat = DVO_FORMAT_LONEOS;
-    if (!strcmp (format, "ELIXIR")) catalog[0].catformat = DVO_FORMAT_ELIXIR;
-    if (!strcmp (format, "PANSTARRS")) catalog[0].catformat = DVO_FORMAT_PANSTARRS;
-    if (catalog[0].catformat != DVO_FORMAT_UNDEF) goto got_format;
-  }
-  if (fits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) {
-    catalog[0].catformat = DVO_FORMAT_ELIXIR;
-    goto got_format;
-  }
-  if (fits_scan (&catalog[0].header, "TELESCOP",  "%s", 1, telescope)) {
-    if (!strncmp (telescope, "LONEOS", strlen("LONEOS"))) {
-      catalog[0].catformat = DVO_FORMAT_LONEOS;
-      goto got_format;
-    }
-    if (!strncmp (telescope, "1.3m McGraw-Hill", strlen("1.3m McGraw-Hill"))) {
-      catalog[0].catformat = DVO_FORMAT_ELIXIR;
-      goto got_format;
-    }
-  }
-  if (VERBOSE) fprintf (stderr, "cannot determine catalog format\n");
-  return (FALSE);
-
-got_format:
-  /* determine datatype sizes */
-  switch (catalog[0].catformat) {
-    case DVO_FORMAT_INTERNAL:
-      AverageSize = sizeof(Average);
-      MeasureSize = sizeof(Measure);
-      SecFiltSize = sizeof (SecFilt);
-      break;
-    case DVO_FORMAT_LONEOS:
-      AverageSize = sizeof(AverageLoneos);
-      MeasureSize = sizeof(MeasureLoneos);
-      SecFiltSize = sizeof (SecFiltLoneos);
-      break;
-    case DVO_FORMAT_ELIXIR:
-      AverageSize = sizeof(AverageElixir);
-      MeasureSize = sizeof(MeasureElixir);
-      SecFiltSize = sizeof (SecFiltElixir);
-      break;
-    case DVO_FORMAT_PANSTARRS:
-      AverageSize = sizeof(AveragePanstarrs);
-      MeasureSize = sizeof(MeasurePanstarrs);
-      SecFiltSize = sizeof (SecFiltPanstarrs);
-      break;
-    default:
-      fprintf (stderr, "programming error in phot_catalog_raw\n");
-      exit (2);
-  }
-  MissingSize = sizeof (Missing);
-
-  /* predicted file size - for double checking data validity */
-  size = catalog[0].header.size;
-  size += AverageSize * catalog[0].Naverage;
-  size += MeasureSize * catalog[0].Nmeasure;
-  size += MissingSize * catalog[0].Nmissing;
-  size += SecFiltSize * catalog[0].Nsecfilt * catalog[0].Naverage;
-
-  /* check that file size makes sense */
-  if (stat (catalog[0].filename, &filestatus) == -1) {
-    if (VERBOSE) fprintf (stderr, "failed to get status of catalog\n");
-    return (FALSE);
-  }
-  if (size > filestatus.st_size) {
-    if (VERBOSE) {
-      fprintf (stderr, "star catalog has inconsistent size\n");
-      fprintf (stderr, "average: %d = %d bytes\n", catalog[0].Naverage, catalog[0].Naverage*AverageSize);
-      fprintf (stderr, "measure: %d = %d bytes\n", catalog[0].Nmeasure, catalog[0].Nmeasure*MeasureSize);
-      fprintf (stderr, "missing: %d = %d bytes\n", catalog[0].Nmissing, catalog[0].Nmissing*MissingSize);
-      fprintf (stderr, "secfilt: %d = %d bytes\n", catalog[0].Nsecfilt, catalog[0].Nsecfilt*SecFiltSize*catalog[0].Naverage);
-      fprintf (stderr, "expect: %d, found: %d\n", size, (int)filestatus.st_size);
-    }
-    return (FALSE);
-  } 
-  if (size < filestatus.st_size) {
-    if (VERBOSE) fprintf (stderr, "warning: file larger than expected\n");
-  } 
-
-  if (catalog[0].Naverage == 0) {
-    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", catalog[0].filename);
-    return (TRUE);
-  }
-
-  /* read and convert the averages (use a macro to clean this up?) */
-  if (mode & LOAD_AVES) {
-    catalog[0].average = ReadRawAverage (catalog[0].f, catalog[0].Naverage, catalog[0].catformat);
-  } else {
-    /* skip over averages */
-    Nskip = catalog[0].Naverage * AverageSize;
-    fseek (f, Nskip, SEEK_CUR); 
-  }    
-  
-  /* read and convert the measures (use a macro to clean this up?) */
-  if (mode & LOAD_MEAS) {
-    catalog[0].measure = ReadRawMeasure (catalog[0].f, catalog[0].Nmeasure, catalog[0].catformat);
-  } else {
-    /* skip over measures */
-    Nskip = catalog[0].Nmeasure * MeasureSize;
-    fseek (f, Nskip, SEEK_CUR); 
-  }    
-
-  /* read and convert missing */
-  if (mode & LOAD_MISS) {
-    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
-    Nitems = catalog[0].Nmissing;
-    nitems = fread (catalog[0].missing, MissingSize, Nitems, f);
-    if (nitems != Nitems) {
-      if (VERBOSE) fprintf (stderr, "failed to read missing from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
-      return (FALSE);
-    }
-    fits_convert_Missing (catalog[0].missing, MissingSize, Nitems);
-  } else {
-    /* skip over missings */
-    Nskip = catalog[0].Nmissing * MissingSize;
-    fseek (f, Nskip, SEEK_CUR); 
-  }
-  
-  /* read and convert secfilt */
-  if (mode & LOAD_SECF) {
-    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
-    catalog[0].secfilt = ReadRawSecFilt (catalog[0].f, Nitems, catalog[0].catformat);
-  } else {
-    /* skip over secfilts */
-    Nskip = catalog[0].Nsecfilt * catalog[0].Naverage * SecFiltSize;
-    fseek (f, Nskip, SEEK_CUR); 
-  }
-
-  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
-	   catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);
-
-  /* check data integrity */
-  if (mode & LOAD_AVES) {
-    for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
-      Nmeas += catalog[0].average[i].Nm; 
-      Nmiss += catalog[0].average[i].Nn; 
-    }
-    if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
-      if (VERBOSE) {
-	fprintf (stderr, "****** data in catalog %s is corrupt, sums don't check\n", catalog[0].filename);
-	fprintf (stderr, "****** Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
-	fprintf (stderr, "****** Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
-      }
-      return (FALSE);
-    }
-  }
-  return (TRUE);
-}
-
-int save_catalog_raw (Catalog *catalog, char VERBOSE) {
-
-  int Nitems, nitems;
-  FILE *f;
-
-  if (catalog[0].Naverage == 0) {
-    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
-    return (TRUE);
-  }
-
-  /* make sure header is consistent with data */
-  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
-  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
-  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
-  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
-
-  /* specify the appropriate data format */
-  if (catalog[0].catformat == DVO_FORMAT_INTERNAL)  fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "INTERNAL");
-  if (catalog[0].catformat == DVO_FORMAT_LONEOS)    fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "LONEOS");
-  if (catalog[0].catformat == DVO_FORMAT_ELIXIR)    fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "ELIXIR");
-  if (catalog[0].catformat == DVO_FORMAT_PANSTARRS) fits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PANSTARRS");
-
-  /* rewind file pointers and truncate file */
-  f = catalog[0].f;
-  fseek (f, 0, SEEK_SET);
-  ftruncate (fileno (catalog[0].f), 0);
-
-  /* write header data (use fits_write_header?) */
-  nitems = fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f);
-  if (nitems != catalog[0].header.size) {
-    if (VERBOSE) fprintf (stderr, "failed to write header\n");
-    return (FALSE);
-  }
-
-  /* write averages and measures */
-  WriteRawAverage (f, catalog[0].average, catalog[0].Naverage, catalog[0].catformat);
-  WriteRawMeasure (f, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
-
-  /* write missing data */
-  Nitems = catalog[0].Nmissing;
-  fits_convert_Missing (catalog[0].missing, sizeof(Missing), Nitems);
-  nitems = fwrite (catalog[0].missing, sizeof(Missing), Nitems, f);
-  if (nitems != Nitems) {
-    if (VERBOSE) fprintf (stderr, "failed to write catalog file missing %s\n", catalog[0].filename);
-    return (FALSE);
-  }
-
-  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
-  WriteRawSecFilt (f, catalog[0].secfilt, Nitems, catalog[0].catformat);
-  return (TRUE);
-}
-
-/*** 
-     some warnings:
-     - need to be wary of exit condition errors
-***/
-
-/** Average / Raw Table conversions **/
-
-Average *ReadRawAverage (FILE *f, int Naverage, int format) {
-
-  int nitems;
-  Average *average;
-  AverageElixir *tmpAverageElixir;
-  AverageLoneos *tmpAverageLoneos;
-  AveragePanstarrs *tmpAveragePanstarrs;
-
-  switch (format) {
-    case DVO_FORMAT_INTERNAL:
-      ALLOCATE (average, Average, MAX (Naverage, 1));
-      nitems = fread (average, sizeof(Average), Naverage, f);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
-	return (NULL);
-      }
-      fits_convert_Average (average, sizeof(Average), Naverage);
-      break;
-    case DVO_FORMAT_ELIXIR:
-      ALLOCATE (tmpAverageElixir, AverageElixir, MAX (Naverage, 1));
-      nitems = fread (tmpAverageElixir, sizeof(AverageElixir), Naverage, f);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
-	return (NULL);
-      }
-      fits_convert_AverageElixir (tmpAverageElixir, sizeof(AverageElixir), Naverage);
-      average = AverageElixirToInternal (tmpAverageElixir, Naverage);
-      free (tmpAverageElixir);
-      break;
-    case DVO_FORMAT_LONEOS:
-      ALLOCATE (tmpAverageLoneos, AverageLoneos, MAX (Naverage, 1));
-      nitems = fread (tmpAverageLoneos, sizeof(AverageLoneos), Naverage, f);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
-	return (NULL);
-      }
-      fits_convert_AverageLoneos (tmpAverageLoneos, sizeof(AverageLoneos), Naverage);
-      average = AverageLoneosToInternal (tmpAverageLoneos, Naverage);
-      free (tmpAverageLoneos);
-      break;
-    case DVO_FORMAT_PANSTARRS:
-      ALLOCATE (tmpAveragePanstarrs, AveragePanstarrs, MAX (Naverage, 1));
-      nitems = fread (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage, f);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
-	return (NULL);
-      }
-      fits_convert_AveragePanstarrs (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage);
-      average = AveragePanstarrsToInternal (tmpAveragePanstarrs, Naverage);
-      free (tmpAveragePanstarrs);
-      break;
-    default:
-      fprintf (stderr, "error reading measures\n");
-      return (NULL);
-  }
-  return (average);
-}
-
-/* accepts and converts internal average formats and outputs 
-   raw data in the specified format */
-int WriteRawAverage (FILE *f, Average *average, int Naverage, int format) {
-
-  int nitems;
-  AverageElixir *tmpAverageElixir;
-  AverageLoneos *tmpAverageLoneos;
-  AveragePanstarrs *tmpAveragePanstarrs;
-
-  switch (format) {
-    case DVO_FORMAT_INTERNAL:
-      fits_convert_Average (average, sizeof(Average), Naverage);
-      nitems = fwrite (average, sizeof(Average), Naverage, f);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_ELIXIR:
-      tmpAverageElixir = AverageInternalToElixir (average, Naverage);
-      fits_convert_AverageElixir (tmpAverageElixir, sizeof(AverageElixir), Naverage);
-      nitems = fwrite (tmpAverageElixir, sizeof(AverageElixir), Naverage, f);
-      free (tmpAverageElixir);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_LONEOS:
-      tmpAverageLoneos = AverageInternalToLoneos (average, Naverage);
-      fits_convert_AverageLoneos (tmpAverageLoneos, sizeof(AverageLoneos), Naverage);
-      nitems = fwrite (tmpAverageLoneos, sizeof(AverageLoneos), Naverage, f);
-      free (tmpAverageLoneos);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_PANSTARRS:
-      tmpAveragePanstarrs = AverageInternalToPanstarrs (average, Naverage);
-      fits_convert_AveragePanstarrs (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage);
-      nitems = fwrite (tmpAveragePanstarrs, sizeof(AveragePanstarrs), Naverage, f);
-      free (tmpAveragePanstarrs);
-      if (nitems != Naverage) {
-	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
-	return (FALSE);
-      }
-      break;
-    default:
-      fprintf (stderr, "error writing averages\n");
-      return (FALSE);
-  }
-  return (TRUE);
-}
-
-/** Average / Raw Table conversions **/
-
-Measure *ReadRawMeasure (FILE *f, int Nmeasure, int format) {
-
-  int nitems;
-  Measure *measure;
-  MeasureElixir *tmpMeasureElixir;
-  MeasureLoneos *tmpMeasureLoneos;
-  MeasurePanstarrs *tmpMeasurePanstarrs;
-
-  switch (format) {
-    case DVO_FORMAT_INTERNAL:
-      ALLOCATE (measure, Measure, MAX (Nmeasure, 1));
-      nitems = fread (measure, sizeof(Measure), Nmeasure, f);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
-	return (NULL);
-      }
-      fits_convert_Measure (measure, sizeof(Measure), Nmeasure);
-      break;
-    case DVO_FORMAT_ELIXIR:
-      ALLOCATE (tmpMeasureElixir, MeasureElixir, MAX (Nmeasure, 1));
-      nitems = fread (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure, f);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
-	return (NULL);
-      }
-      fits_convert_MeasureElixir (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure);
-      measure = MeasureElixirToInternal (tmpMeasureElixir, Nmeasure);
-      free (tmpMeasureElixir);
-      break;
-    case DVO_FORMAT_LONEOS:
-      ALLOCATE (tmpMeasureLoneos, MeasureLoneos, MAX (Nmeasure, 1));
-      nitems = fread (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure, f);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
-	return (NULL);
-      }
-      fits_convert_MeasureLoneos (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure);
-      measure = MeasureLoneosToInternal (tmpMeasureLoneos, Nmeasure);
-      free (tmpMeasureLoneos);
-      break;
-    case DVO_FORMAT_PANSTARRS:
-      ALLOCATE (tmpMeasurePanstarrs, MeasurePanstarrs, MAX (Nmeasure, 1));
-      nitems = fread (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure, f);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
-	return (NULL);
-      }
-      fits_convert_MeasurePanstarrs (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure);
-      measure = MeasurePanstarrsToInternal (tmpMeasurePanstarrs, Nmeasure);
-      free (tmpMeasurePanstarrs);
-      break;
-    default:
-      fprintf (stderr, "error reading measures\n");
-      return (NULL);
-  }
-  return (measure);
-}
-
-/* accepts and converts internal measure formats and outputs 
-   raw data in the specified format */
-int WriteRawMeasure (FILE *f, Measure *measure, int Nmeasure, int format) {
-
-  int nitems;
-  MeasureElixir *tmpMeasureElixir;
-  MeasureLoneos *tmpMeasureLoneos;
-  MeasurePanstarrs *tmpMeasurePanstarrs;
-
-  switch (format) {
-    case DVO_FORMAT_INTERNAL:
-      fits_convert_Measure (measure, sizeof(Measure), Nmeasure);
-      nitems = fwrite (measure, sizeof(Measure), Nmeasure, f);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_ELIXIR:
-      tmpMeasureElixir = MeasureInternalToElixir (measure, Nmeasure);
-      fits_convert_MeasureElixir (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure);
-      nitems = fwrite (tmpMeasureElixir, sizeof(MeasureElixir), Nmeasure, f);
-      free (tmpMeasureElixir);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_LONEOS:
-      tmpMeasureLoneos = MeasureInternalToLoneos (measure, Nmeasure);
-      fits_convert_MeasureLoneos (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure);
-      nitems = fwrite (tmpMeasureLoneos, sizeof(MeasureLoneos), Nmeasure, f);
-      free (tmpMeasureLoneos);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_PANSTARRS:
-      tmpMeasurePanstarrs = MeasureInternalToPanstarrs (measure, Nmeasure);
-      fits_convert_MeasurePanstarrs (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure);
-      nitems = fwrite (tmpMeasurePanstarrs, sizeof(MeasurePanstarrs), Nmeasure, f);
-      free (tmpMeasurePanstarrs);
-      if (nitems != Nmeasure) {
-	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
-	return (FALSE);
-      }
-      break;
-    default:
-      fprintf (stderr, "error writing measures\n");
-      return (FALSE);
-  }
-  return (TRUE);
-}
-
-/** SecFilt / Raw Table conversions **/
-
-SecFilt *ReadRawSecFilt (FILE *f, int Nsecfilt, int format) {
-
-  int nitems;
-  SecFilt *secfilt;
-  SecFiltElixir *tmpSecFiltElixir;
-  SecFiltLoneos *tmpSecFiltLoneos;
-  SecFiltPanstarrs *tmpSecFiltPanstarrs;
-
-  switch (format) {
-    case DVO_FORMAT_INTERNAL:
-      ALLOCATE (secfilt, SecFilt, MAX (Nsecfilt, 1));
-      nitems = fread (secfilt, sizeof(SecFilt), Nsecfilt, f);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (NULL);
-      }
-      fits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
-      break;
-    case DVO_FORMAT_ELIXIR:
-      ALLOCATE (tmpSecFiltElixir, SecFiltElixir, MAX (Nsecfilt, 1));
-      nitems = fread (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt, f);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (NULL);
-      }
-      fits_convert_SecFiltElixir (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt);
-      secfilt = SecFiltElixirToInternal (tmpSecFiltElixir, Nsecfilt);
-      free (tmpSecFiltElixir);
-      break;
-    case DVO_FORMAT_LONEOS:
-      ALLOCATE (tmpSecFiltLoneos, SecFiltLoneos, MAX (Nsecfilt, 1));
-      nitems = fread (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt, f);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (NULL);
-      }
-      fits_convert_SecFiltLoneos (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt);
-      secfilt = SecFiltLoneosToInternal (tmpSecFiltLoneos, Nsecfilt);
-      free (tmpSecFiltLoneos);
-      break;
-    case DVO_FORMAT_PANSTARRS:
-      ALLOCATE (tmpSecFiltPanstarrs, SecFiltPanstarrs, MAX (Nsecfilt, 1));
-      nitems = fread (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt, f);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (NULL);
-      }
-      fits_convert_SecFiltPanstarrs (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt);
-      secfilt = SecFiltPanstarrsToInternal (tmpSecFiltPanstarrs, Nsecfilt);
-      free (tmpSecFiltPanstarrs);
-      break;
-    default:
-      fprintf (stderr, "error reading measures\n");
-      return (NULL);
-  }
-  return (secfilt);
-}
-
-/* accepts and converts internal secfilt formats and outputs 
-   raw data in the specified format */
-int WriteRawSecFilt (FILE *f, SecFilt *secfilt, int Nsecfilt, int format) {
-
-  int nitems;
-  SecFiltElixir *tmpSecFiltElixir;
-  SecFiltLoneos *tmpSecFiltLoneos;
-  SecFiltPanstarrs *tmpSecFiltPanstarrs;
-
-  switch (format) {
-    case DVO_FORMAT_INTERNAL:
-      fits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
-      nitems = fwrite (secfilt, sizeof(SecFilt), Nsecfilt, f);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_ELIXIR:
-      tmpSecFiltElixir = SecFiltInternalToElixir (secfilt, Nsecfilt);
-      fits_convert_SecFiltElixir (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt);
-      nitems = fwrite (tmpSecFiltElixir, sizeof(SecFiltElixir), Nsecfilt, f);
-      free (tmpSecFiltElixir);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_LONEOS:
-      tmpSecFiltLoneos = SecFiltInternalToLoneos (secfilt, Nsecfilt);
-      fits_convert_SecFiltLoneos (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt);
-      nitems = fwrite (tmpSecFiltLoneos, sizeof(SecFiltLoneos), Nsecfilt, f);
-      free (tmpSecFiltLoneos);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (FALSE);
-      }
-      break;
-    case DVO_FORMAT_PANSTARRS:
-      tmpSecFiltPanstarrs = SecFiltInternalToPanstarrs (secfilt, Nsecfilt);
-      fits_convert_SecFiltPanstarrs (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt);
-      nitems = fwrite (tmpSecFiltPanstarrs, sizeof(SecFiltPanstarrs), Nsecfilt, f);
-      free (tmpSecFiltPanstarrs);
-      if (nitems != Nsecfilt) {
-	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
-	return (FALSE);
-      }
-      break;
-    default:
-      fprintf (stderr, "error writing secfilts\n");
-      return (FALSE);
-  }
-  return (TRUE);
-}
-
