Index: trunk/Ohana/src/dvomerge/Makefile
===================================================================
--- trunk/Ohana/src/dvomerge/Makefile	(revision 28857)
+++ trunk/Ohana/src/dvomerge/Makefile	(revision 29001)
@@ -20,5 +20,5 @@
 dvomerge     : $(BIN)/dvoconvert.$(ARCH)
 
-all: dvomerge dvoconvert
+all: dvomerge dvoconvert dvosecfilt
 
 DVOMERGE = \
@@ -58,5 +58,17 @@
 $(BIN)/dvoconvert.$(ARCH) : $(DVOCONVERT)
 
-INSTALL = dvomerge dvoconvert
+DVOSECFILT = \
+$(SRC)/dvosecfilt.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/help.$(ARCH).o \
+$(SRC)/args.$(ARCH).o
+
+$(DVOSECFILT)  : $(INC)/dvomerge.h
+
+$(BIN)/dvosecfilt.$(ARCH) : $(DVOSECFILT)
+
+INSTALL = dvomerge dvoconvert dvosecfilt
 
 # dependancy rules for binary code #########################
Index: trunk/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 28857)
+++ trunk/Ohana/src/dvomerge/include/dvomerge.h	(revision 29001)
@@ -55,5 +55,10 @@
 int  	   dvoconvert_args	  PROTO((int *argc, char **argv));
 
+void       dvosecfilt_usage       PROTO((void));
+void 	   dvosecfilt_help 	  PROTO((int argc, char **argv));
+int  	   dvosecfilt_args	  PROTO((int *argc, char **argv));
+
 int        SkyTablePopulatedRange PROTO((off_t *ns, off_t *ne, SkyTable *sky, off_t Nstart));
+int        SkyListPopulatedRange  PROTO((off_t *ns, off_t *ne, SkyList *sky, off_t Nstart));
 
 SkyList   *SkyTablePopulatedList  PROTO((SkyTable *sky));
Index: trunk/Ohana/src/dvomerge/src/SkyTablePopulatedRange.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/SkyTablePopulatedRange.c	(revision 28857)
+++ trunk/Ohana/src/dvomerge/src/SkyTablePopulatedRange.c	(revision 29001)
@@ -12,4 +12,27 @@
     Ns = sky[0].regions[Nstart].childS;
     Ne = sky[0].regions[Nstart].childE;
+    if (Ns == 0) {
+      fprintf (stderr, "no populated tables at an appropriate depth\n");
+      exit (1);
+    }
+    Nstart = Ns;
+  }
+
+  *ns = Ns;
+  *ne = Ne;
+  return (TRUE);
+}
+
+int SkyListPopulatedRange (off_t *ns, off_t *ne, SkyList *sky, off_t Nstart) {
+
+  off_t Ns, Ne;
+
+  // given the starting sky region, find the populated range at or below this region
+
+  Ns = Nstart;
+  Ne = Nstart + 1;
+  while (!sky[0].regions[Nstart][0].table) {
+    Ns = sky[0].regions[Nstart][0].childS;
+    Ne = sky[0].regions[Nstart][0].childE;
     if (Ns == 0) {
       fprintf (stderr, "no populated tables at an appropriate depth\n");
Index: trunk/Ohana/src/dvomerge/src/args.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/args.c	(revision 28857)
+++ trunk/Ohana/src/dvomerge/src/args.c	(revision 29001)
@@ -15,4 +15,22 @@
     remove_argument (N, argc, argv);
     ALTERNATE_PHOTCODE_FILE = strdup(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /*** provide additional data ***/ 
+  /* restrict to a portion of the sky? */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax= 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (*argc, argv, "-region"))) {
+    remove_argument (N, argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
     remove_argument (N, argc, argv);
   }
@@ -37,2 +55,18 @@
   return TRUE;
 }
+
+/*** check for command line options ***/
+int dvosecfilt_args (int *argc, char **argv) {
+  
+  int N;
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != 3) dvosecfilt_usage();
+  return TRUE;
+}
Index: trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 28857)
+++ trunk/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 29001)
@@ -13,4 +13,9 @@
  
   images = gfits_table_get_Image (&in[0].ftable, &Nimages, &in[0].swapped);
+  if (!images) {
+    fprintf (stderr, "ERROR: failed to read images\n");
+    exit (2);
+  }
+
   ALLOCATE (IDmap->old, off_t, Nimages);
   ALLOCATE (IDmap->new, off_t, Nimages);
@@ -59,4 +64,6 @@
 
   off_t Nlo, Nhi, N;
+
+  if (!IDmap->Nmap) return 0;
 
   // find the a close entry below desired ID
Index: trunk/Ohana/src/dvomerge/src/dvoconvert.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvoconvert.c	(revision 28857)
+++ trunk/Ohana/src/dvomerge/src/dvoconvert.c	(revision 29001)
@@ -148,4 +148,8 @@
   // convert the raw image table to Image type (byteswap if needed)
   images = gfits_table_get_Image (&inDB.ftable, &Nimages, &inDB.swapped);
+  if (!images) {
+    fprintf (stderr, "ERROR: failed to read images\n");
+    exit (2);
+  }
 
   // update additional metadata
Index: trunk/Ohana/src/dvomerge/src/dvomergeUpdate.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 28857)
+++ trunk/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 29001)
@@ -6,5 +6,5 @@
   off_t i, j, Ns, Ne;
   SkyTable *outsky, *insky;
-  SkyList *inlist;
+  SkyList *outlist, *inlist;
   Catalog incatalog, outcatalog;
   char filename[256], *input, *output;
@@ -70,4 +70,7 @@
   SkyTableSetFilenames (insky, input, "cpt");
 
+  // XXX apply this...generate the subset matching the user-selected region
+  inlist = SkyListByPatch (insky, -1, &UserPatch);
+
   // generate an output table populated at the desired depth
   outsky = SkyTableLoadOptimal (output, NULL, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
@@ -79,15 +82,21 @@
   // loop over the populatable output tables; check for data in input in the corresponding regions
 
-  SkyTablePopulatedRange (&Ns, &Ne, insky, 0);
-  depth = insky[0].regions[Ns].depth;
+  SkyListPopulatedRange (&Ns, &Ne, inlist, 0);
+  depth = inlist[0].regions[Ns][0].depth;
   
-  // loop over the populatable output regions
-  for (i = 0; i < outsky[0].Nregions; i++) {
-    if (!outsky[0].regions[i].table) continue;
-    if (VERBOSE) fprintf (stderr, "output: %s\n", outsky[0].regions[i].name);
+  // loop over the populated input regions
+  for (i = 0; i < inlist[0].Nregions; i++) {
+    if (!inlist[0].regions[i][0].table) continue;
+    if (VERBOSE) fprintf (stderr, "input: %s\n", inlist[0].regions[i][0].name);
 
-    SetPhotcodeTable(outputPhotcodes);
+    SetPhotcodeTable(inputPhotcodes);
     // load / create output catalog (if catalog does not exist, it will be created)
-    LoadCatalog (&outcatalog, &outsky[0].regions[i], outsky[0].filename[i], "w");
+    LoadCatalog (&incatalog, &inlist[0].regions[i][0], inlist[0].filename[i], "r");
+    // skip empty input catalogs
+    if (!incatalog.Naves_disk) {
+	dvo_catalog_unlock (&incatalog);
+	dvo_catalog_free (&incatalog);
+	continue;
+    }
 
     // combine only tables at equal or larger depth
@@ -97,31 +106,31 @@
     // compare to a slightly reduced footprint
     float dPos = 2.0/3600.0;
-    inlist = SkyListByBounds (insky, depth, outsky[0].regions[i].Rmin + dPos, outsky[0].regions[i].Rmax - dPos, outsky[0].regions[i].Dmin + dPos, outsky[0].regions[i].Dmax - dPos);
-    for (j = 0; j < inlist[0].Nregions; j++) {
-      if (VERBOSE) fprintf (stderr, "input : %s\n", inlist[0].regions[j][0].name);
+    outlist = SkyListByBounds (outsky, depth, inlist[0].regions[i][0].Rmin + dPos, inlist[0].regions[i][0].Rmax - dPos, inlist[0].regions[i][0].Dmin + dPos, inlist[0].regions[i][0].Dmax - dPos);
+    for (j = 0; j < outlist[0].Nregions; j++) {
+      if (VERBOSE) fprintf (stderr, "output : %s\n", outlist[0].regions[j][0].name);
 
       // load input catalog
-      SetPhotcodeTable(inputPhotcodes);
-      LoadCatalog (&incatalog, inlist[0].regions[j], inlist[0].filename[j], "r");
+      SetPhotcodeTable(outputPhotcodes);
+      LoadCatalog (&outcatalog, outlist[0].regions[j], outlist[0].filename[j], "w");
 
-      // skip empty input catalogs
-      if (!incatalog.Naves_disk) {
-	dvo_catalog_unlock (&incatalog);
-	dvo_catalog_free (&incatalog);
-	continue;
-      }
       dvo_update_image_IDs (&IDmap, &incatalog);
-      merge_catalogs_old (&outsky[0].regions[i], &outcatalog, &incatalog, RADIUS, secfiltMap);
-      dvo_catalog_unlock (&incatalog);
-      dvo_catalog_free (&incatalog);
+      merge_catalogs_old (&outsky[0].regions[j], &outcatalog, &incatalog, RADIUS, secfiltMap);
 
-      fprintf (stderr, "merged %s into %s\n", outsky[0].regions[i].name, inlist[0].regions[j][0].name);
+      outcatalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+      // if we receive a signal which would cause us to exit, wait until the full catalog is written
+      SetProtect (TRUE);
+      dvo_catalog_save (&outcatalog, VERBOSE);
+      SetProtect (FALSE);
+
+      dvo_catalog_unlock (&outcatalog);
+      dvo_catalog_free (&outcatalog);
+
+      fprintf (stderr, "merged %s into %s\n", inlist[0].regions[i][0].name, outlist[0].regions[j][0].name);
     }
-    SkyListFree (inlist);
+    SkyListFree (outlist);
 
-    outcatalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
-    dvo_catalog_save (&outcatalog, VERBOSE);
-    dvo_catalog_unlock (&outcatalog);
-    dvo_catalog_free (&outcatalog);
+    dvo_catalog_unlock (&incatalog);
+    dvo_catalog_free (&incatalog);
   }
 
@@ -153,5 +162,7 @@
   // load the image table 
   if (inDB.dbstate == LCK_EMPTY) {
-    Shutdown ("can't find input image catalog %s", inDB.filename);
+    // Shutdown ("can't find input image catalog %s", inDB.filename);
+    IDmap->Nmap = 0;
+    return TRUE;
   }
   if (!dvo_image_load (&inDB, VERBOSE, TRUE)) {
Index: trunk/Ohana/src/dvomerge/src/dvosecfilt.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvosecfilt.c	(revision 29001)
+++ trunk/Ohana/src/dvomerge/src/dvosecfilt.c	(revision 29001)
@@ -0,0 +1,90 @@
+# include "dvomerge.h"
+
+// modify the number of average photcodes : change only secfilt tables in place
+int main (int argc, char **argv) {
+
+  char filename[256], *input;
+  off_t i, j, k, Nsecfilt, NsecInput, Nstart;
+  SkyTable *insky;
+  Catalog catalog;
+  SecFilt *insec, *outsec;
+
+  SetSignals ();
+  dvosecfilt_help (argc, argv);
+  ConfigInit (&argc, argv);
+  dvosecfilt_args (&argc, argv);
+
+  input = argv[1];
+  Nsecfilt = atoi(argv[2]);
+
+  // load the sky table for the existing database
+  insky = SkyTableLoadOptimal (input, NULL, NULL, FALSE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (insky, input, "cpt");
+
+  // loop over all input catalogs
+  for (i = 0; i < insky[0].Nregions; i++) {
+    if (!insky[0].regions[i].table) continue;
+    if (VERBOSE) fprintf (stderr, "table: %s\n", insky[0].regions[i].name);
+
+    // set the parameters which guide catalog open/load/create
+    catalog.filename  = insky[0].filename[i];
+    catalog.Nsecfilt  = 0;
+
+    // always load all of the data (if any exists)
+    catalog.catflags  = LOAD_SECF;
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+
+    if (!dvo_catalog_open (&catalog, &insky[0].regions[i], VERBOSE, "w")) {
+	fprintf (stderr, "ERROR: failure to open catalog file %s\n", filename);
+	exit (2);
+    }
+
+    if (catalog.Naves_disk == 0) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    if (Nsecfilt == catalog.Nsecfilt) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    NsecInput = catalog.Nsecfilt;
+    Nstart = MIN(Nsecfilt, NsecInput);
+
+    insec = catalog.secfilt;
+    ALLOCATE (outsec, SecFilt, catalog.Naves_disk * Nsecfilt);
+
+    for (k = 0; k < catalog.Naves_disk; k++) {
+      for (j = 0; (j < catalog.Nsecfilt) && (j < Nsecfilt); j++) {
+	outsec[k*Nsecfilt + j].M  = insec[k*NsecInput + j].M;
+	outsec[k*Nsecfilt + j].dM = insec[k*NsecInput + j].dM;
+	outsec[k*Nsecfilt + j].Xm = insec[k*NsecInput + j].Xm;
+	outsec[k*Nsecfilt + j].flags  = insec[k*NsecInput + j].flags;
+	outsec[k*Nsecfilt + j].Ncode  = insec[k*NsecInput + j].Ncode;
+	outsec[k*Nsecfilt + j].Nused  = insec[k*NsecInput + j].Nused;
+	outsec[k*Nsecfilt + j].M_20   = insec[k*NsecInput + j].M_20;
+	outsec[k*Nsecfilt + j].M_80   = insec[k*NsecInput + j].M_80;
+      }
+      for (j = Nstart; j < Nsecfilt; j++) {
+	outsec[k*Nsecfilt + j].M  = NAN;
+	outsec[k*Nsecfilt + j].dM = NAN;
+	outsec[k*Nsecfilt + j].Xm = NAN_S_SHORT;
+      }
+    }
+    free (catalog.secfilt);
+    catalog.secfilt = outsec;
+    catalog.Nsecfilt = Nsecfilt;
+    catalog.Nsecf_mem = Nsecfilt * catalog.Naves_disk;
+    catalog.Nsecf_disk = Nsecfilt * catalog.Naves_disk;
+
+    dvo_catalog_save (&catalog, VERBOSE);
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+
+  exit (0);
+}
Index: trunk/Ohana/src/dvomerge/src/dvoverify.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/dvoverify.c	(revision 28857)
+++ trunk/Ohana/src/dvomerge/src/dvoverify.c	(revision 29001)
@@ -154,4 +154,8 @@
   // convert the raw image table to Image type (byteswap if needed)
   images = gfits_table_get_Image (&inDB.ftable, &Nimages, &inDB.swapped);
+  if (!images) {
+    fprintf (stderr, "ERROR: failed to read images\n");
+    exit (2);
+  }
 
   // update additional metadata
Index: trunk/Ohana/src/dvomerge/src/help.c
===================================================================
--- trunk/Ohana/src/dvomerge/src/help.c	(revision 28857)
+++ trunk/Ohana/src/dvomerge/src/help.c	(revision 29001)
@@ -4,4 +4,5 @@
   fprintf (stderr, "USAGE: dvomerge (input1) and (input2) to (output)\n");
   fprintf (stderr, "   OR: dvomerge (input) into (output)\n");
+  fprintf (stderr, "   [-region Rmin Rmax Dmin Dmax]\n");
   exit (2);
 }
@@ -10,4 +11,11 @@
 
   fprintf (stderr, "USAGE: dvoconvert (input) to (output)\n");
+
+  exit (2);
+}
+
+void dvosecfilt_usage(void) {
+
+  fprintf (stderr, "USAGE: dvosecfilt (input) -photcodes (photcodes.txt)\n");
 
   exit (2);
@@ -57,2 +65,23 @@
 }
 
+void dvosecfilt_help (int argc, char **argv) {
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help")) goto show_help;
+  if (get_argument (argc, argv, "-h"))    goto show_help;
+  return;
+
+show_help:
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  dvosecfilt (input) (Nsecfilt)\n\n");
+
+  fprintf (stderr, "  change number of secfilt entries in photcode table (updates secfilt tables only)\n");
+ 
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
+
