Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/include/WISE.h
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/include/WISE.h	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/include/WISE.h	(revision 42166)
@@ -21,8 +21,8 @@
 short WISE_W1, WISE_W2, WISE_W3, WISE_W4;
 
-enum {MODE_NONE, MODE_ALLWISE, MODE_ALLSKY, MODE_PRELIM};
+enum {MODE_NONE, MODE_CATWISE, MODE_ALLWISE, MODE_ALLSKY, MODE_PRELIM};
 int MODE;
 
-AddstarClientOptions args_loadwise (int argc, char **argv, AddstarClientOptions options);
+AddstarClientOptions args_loadwise (int *argc, char **argv, AddstarClientOptions options);
 
 int loadwise_rawdata (SkyList *skytable, char *filename, AddstarClientOptions options);
@@ -38,5 +38,5 @@
 int loadwise_star_allsky  (Measure *measure, char *line, int Nmax);
 int loadwise_star_allwise (Measure *measure, char *line, int Nmax);
-
+int loadwise_star_catwise (Measure *measure, char *line, int Nmax, double Rs, double Ds);
 
 char *nextWISEfield (char *line);
@@ -49,4 +49,12 @@
 int setWISE_dup_flag (Measure *measure, char qual);
 int setWISE_use_flag (Measure *measure, char qual);
+int setWISE_sat_flag (Measure *measure, char *ptr);
+
+int setCatWISE_sat_flag (Measure *measure, char *ptr, int start, int end);
+int setCatWISE_blend_flag (Measure *measure, char *line);
 
 char *skipNbounds (char *line, char bound, int Nbound, int Nbyte);
+
+char *getLineSegment (char *line, int start, int end);
+double getDoubleRAW (char *line, int start, int end);
+double getDoubleNAN (char *line, int start, int end);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/include/ukirt_uhs.h
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/include/ukirt_uhs.h	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/include/ukirt_uhs.h	(revision 42166)
@@ -3,4 +3,5 @@
 
 # define NSTARS_MAX 10000000
+//# define NSTARS_MAX 5000
 // # define NSTARS_MAX 10
 
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/args_loadwise.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/args_loadwise.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/args_loadwise.c	(revision 42166)
@@ -3,11 +3,11 @@
 static void help (void);
 
-AddstarClientOptions args_loadwise (int argc, char **argv, AddstarClientOptions options) {
+AddstarClientOptions args_loadwise (int *argc, char **argv, AddstarClientOptions options) {
   
   int N;
 
   /* check for help request */
-  if (get_argument (argc, argv, "-help") ||
-      get_argument (argc, argv, "-h")) {
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
     help ();
   }
@@ -29,33 +29,33 @@
   /* only add to existing regions */
   options.existing_regions = FALSE;
-  if ((N = get_argument (argc, argv, "-existing-regions"))) {
+  if ((N = get_argument (*argc, argv, "-existing-regions"))) {
     options.existing_regions = TRUE;
-    remove_argument (N, &argc, argv);
+    remove_argument (N, argc, argv);
   }
   /* only add to existing objects */
   options.only_match = FALSE;
-  if ((N = get_argument (argc, argv, "-only-match"))) {
+  if ((N = get_argument (*argc, argv, "-only-match"))) {
     options.only_match = TRUE;
-    remove_argument (N, &argc, argv);
+    remove_argument (N, argc, argv);
   }
   /* replace measurement, don't duplicate (ref/cat only) */
   options.replace = FALSE;
-  if ((N = get_argument (argc, argv, "-replace"))) {
+  if ((N = get_argument (*argc, argv, "-replace"))) {
     options.replace = TRUE;
-    remove_argument (N, &argc, argv);
+    remove_argument (N, argc, argv);
   }
 
   /* extra error messages */
   VERBOSE = FALSE;
-  if ((N = get_argument (argc, argv, "-v"))) {
+  if ((N = get_argument (*argc, argv, "-v"))) {
     VERBOSE = TRUE;
-    remove_argument (N, &argc, argv);
+    remove_argument (N, argc, argv);
   }
 
   /* load the prelim data dump */
-  MODE = MODE_ALLWISE;
-  if ((N = get_argument (argc, argv, "-mode"))) {
-    MODE = MODE_NONE;
-    remove_argument (N, &argc, argv);
+  MODE = MODE_NONE;
+  if ((N = get_argument (*argc, argv, "-mode"))) {
+    remove_argument (N, argc, argv);
+    if (!strcasecmp(argv[N], "catwise")) MODE = MODE_CATWISE;
     if (!strcasecmp(argv[N], "allwise")) MODE = MODE_ALLWISE;
     if (!strcasecmp(argv[N], "allsky"))  MODE = MODE_ALLSKY;
@@ -65,5 +65,5 @@
       exit (2);
     }
-    remove_argument (N, &argc, argv);
+    remove_argument (N, argc, argv);
   }
 
@@ -85,5 +85,5 @@
   DUMP = NULL;
 
-  if (argc < 2) {
+  if (*argc < 2) {
     fprintf (stderr, "USAGE: loadwise [options] (wisefile) [..more files]\n");
     exit (2);
@@ -94,6 +94,8 @@
 static void help () {
 
-  fprintf (stderr, "USAGE: loadwise [options] (wisefile) [..more files]\n");
+  fprintf (stderr, "USAGE: loadwise [-mode MODE] [options] (wisefile) [..more files]\n");
   fprintf (stderr, "  add data from WISE catalog to DVO\n\n");
+
+  fprintf (stderr, "  MODE may be : catwise, allwise, allsky, prelim\n");
 
   fprintf (stderr, "  optional flags:\n");
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ugcs.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ugcs.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ugcs.c	(revision 42166)
@@ -467,12 +467,14 @@
 	NELEM += 1000;
 
-	REALLOCATE (sourceID,     uint64_t, NELEM);
+	REALLOCATE (sourceID,     uint64_t, NELEM);  
 	REALLOCATE (frameSetID,   uint64_t, NELEM);
 	REALLOCATE (ra,           double,   NELEM);
 	REALLOCATE (dec,          double,   NELEM);
+	REALLOCATE (epoch,        double,   NELEM);
 	REALLOCATE (priOrSec,     uint64_t, NELEM);
 	REALLOCATE (mergedClass,  int,      NELEM);
 	REALLOCATE (pStar,        double,   NELEM);
 	REALLOCATE (pGalaxy,      double,   NELEM);
+
 	REALLOCATE (zHallMag,     double,   NELEM);
 	REALLOCATE (zHallMagErr,  double,   NELEM);
@@ -485,4 +487,5 @@
 	REALLOCATE (zppErrBits,   int,      NELEM);
 	REALLOCATE (zSeqNum,      int,      NELEM);
+
 	REALLOCATE (yHallMag,     double,   NELEM);
 	REALLOCATE (yHallMagErr,  double,   NELEM);
@@ -495,4 +498,5 @@
 	REALLOCATE (yppErrBits,   int,      NELEM);
 	REALLOCATE (ySeqNum,      int,      NELEM);
+
 	REALLOCATE (jHallMag,     double,   NELEM);
 	REALLOCATE (jHallMagErr,  double,   NELEM);
@@ -505,4 +509,5 @@
 	REALLOCATE (jppErrBits,   int,      NELEM);
 	REALLOCATE (jSeqNum,      int,      NELEM);
+
 	REALLOCATE (hHallMag,     double,   NELEM);
 	REALLOCATE (hHallMagErr,  double,   NELEM);
@@ -515,4 +520,5 @@
 	REALLOCATE (hppErrBits,   int,      NELEM);
 	REALLOCATE (hSeqNum,      int,      NELEM);
+
 	REALLOCATE (k1HallMag,     double,   NELEM);
 	REALLOCATE (k1HallMagErr,  double,   NELEM);
@@ -525,4 +531,5 @@
 	REALLOCATE (k1ppErrBits,   int,      NELEM);
 	REALLOCATE (k1SeqNum,      int,      NELEM);
+
 	REALLOCATE (k2HallMag,     double,   NELEM);
 	REALLOCATE (k2HallMagErr,  double,   NELEM);
@@ -541,4 +548,5 @@
     }
   }
+  fprintf (stderr, " DONE: Nelem: %d, *nstars: %d\n", Nelem, *nstars);
 
   // Nelem is now the number of items (objects,stars) read from the Gaia CSV file
@@ -715,5 +723,5 @@
     Nstars ++;
 
-    if (NSTARS >= Nstars) {
+    if (Nstars >= NSTARS) {
       NSTARS += 10000;
       REALLOCATE (stars, UKIRT_Stars, NSTARS);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ugps.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ugps.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ugps.c	(revision 42166)
@@ -388,12 +388,14 @@
 	NELEM += 1000;
 
-	REALLOCATE (sourceID,     uint64_t, NELEM);
+	REALLOCATE (sourceID,     uint64_t, NELEM);    
 	REALLOCATE (frameSetID,   uint64_t, NELEM);
 	REALLOCATE (ra,           double,   NELEM);
 	REALLOCATE (dec,          double,   NELEM);
+	REALLOCATE (epoch,        double,   NELEM);
 	REALLOCATE (priOrSec,     uint64_t, NELEM);
 	REALLOCATE (mergedClass,  int,      NELEM);
 	REALLOCATE (pStar,        double,   NELEM);
 	REALLOCATE (pGalaxy,      double,   NELEM);
+
 	REALLOCATE (jAperMag1,     double,   NELEM);
 	REALLOCATE (jAperMag1Err,  double,   NELEM);
@@ -406,4 +408,5 @@
 	REALLOCATE (jppErrBits,   int,      NELEM);
 	REALLOCATE (jSeqNum,      int,      NELEM);
+
 	REALLOCATE (hAperMag1,     double,   NELEM);
 	REALLOCATE (hAperMag1Err,  double,   NELEM);
@@ -416,4 +419,5 @@
 	REALLOCATE (hppErrBits,   int,      NELEM);
 	REALLOCATE (hSeqNum,      int,      NELEM);
+
 	REALLOCATE (k1AperMag1,     double,   NELEM);
 	REALLOCATE (k1AperMag1Err,  double,   NELEM);
@@ -426,4 +430,5 @@
 	REALLOCATE (k1ppErrBits,   int,      NELEM);
 	REALLOCATE (k1SeqNum,      int,      NELEM);
+
 	REALLOCATE (k2AperMag1,     double,   NELEM);
 	REALLOCATE (k2AperMag1Err,  double,   NELEM);
@@ -436,4 +441,5 @@
 	REALLOCATE (k2ppErrBits,   int,      NELEM);
 	REALLOCATE (k2SeqNum,      int,      NELEM);
+
 	REALLOCATE (h2AperMag1,     double,   NELEM);
 	REALLOCATE (h2AperMag1Err,  double,   NELEM);
@@ -452,4 +458,5 @@
     }
   }
+  fprintf (stderr, " DONE: Nelem: %d, *nstars: %d\n", Nelem, *nstars);
 
   // Nelem is now the number of items (objects,stars) read from the Gaia CSV file
@@ -606,5 +613,5 @@
     Nstars ++;
 
-    if (NSTARS >= Nstars) {
+    if (Nstars >= NSTARS) {
       NSTARS += 10000;
       REALLOCATE (stars, UKIRT_Stars, NSTARS);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_uhs.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_uhs.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_uhs.c	(revision 42166)
@@ -234,4 +234,5 @@
     }
   }
+  fprintf (stderr, " DONE: Nelem: %d, *nstars: %d\n", Nelem, *nstars);
 
   // Nelem is now the number of items (objects,stars) read from the Gaia CSV file
@@ -307,5 +308,5 @@
     Nstars ++;
 
-    if (NSTARS >= Nstars) {
+    if (Nstars >= NSTARS) {
       NSTARS += 10000;
       REALLOCATE (stars, UKIRT_Stars, NSTARS);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ulas.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ulas.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadukirt_uhs_readstars_ulas.c	(revision 42166)
@@ -415,12 +415,14 @@
 	NELEM += 1000;
 
-	REALLOCATE (sourceID,     uint64_t, NELEM);
+	REALLOCATE (sourceID,     uint64_t, NELEM);    
 	REALLOCATE (frameSetID,   uint64_t, NELEM);
 	REALLOCATE (ra,           double,   NELEM);
 	REALLOCATE (dec,          double,   NELEM);
+	REALLOCATE (epoch,        double,   NELEM);
 	REALLOCATE (priOrSec,     uint64_t, NELEM);
 	REALLOCATE (mergedClass,  int,      NELEM);
 	REALLOCATE (pStar,        double,   NELEM);
 	REALLOCATE (pGalaxy,      double,   NELEM);
+
 	REALLOCATE (yHallMag,     double,   NELEM);
 	REALLOCATE (yHallMagErr,  double,   NELEM);
@@ -433,4 +435,5 @@
 	REALLOCATE (yppErrBits,   int,      NELEM);
 	REALLOCATE (ySeqNum,      int,      NELEM);
+
 	REALLOCATE (j1HallMag,     double,   NELEM);
 	REALLOCATE (j1HallMagErr,  double,   NELEM);
@@ -443,4 +446,5 @@
 	REALLOCATE (j1ppErrBits,   int,      NELEM);
 	REALLOCATE (j1SeqNum,      int,      NELEM);
+
 	REALLOCATE (j2HallMag,     double,   NELEM);
 	REALLOCATE (j2HallMagErr,  double,   NELEM);
@@ -453,4 +457,5 @@
 	REALLOCATE (j2ppErrBits,   int,      NELEM);
 	REALLOCATE (j2SeqNum,      int,      NELEM);
+
 	REALLOCATE (hHallMag,     double,   NELEM);
 	REALLOCATE (hHallMagErr,  double,   NELEM);
@@ -463,4 +468,5 @@
 	REALLOCATE (hppErrBits,   int,      NELEM);
 	REALLOCATE (hSeqNum,      int,      NELEM);
+
 	REALLOCATE (kHallMag,     double,   NELEM);
 	REALLOCATE (kHallMagErr,  double,   NELEM);
@@ -479,4 +485,5 @@
     }
   }
+  fprintf (stderr, " DONE: Nelem: %d, *nstars: %d\n", Nelem, *nstars);
 
   // Nelem is now the number of items (objects,stars) read from the Gaia CSV file
@@ -633,5 +640,5 @@
     Nstars ++;
 
-    if (NSTARS >= Nstars) {
+    if (Nstars >= NSTARS) {
       NSTARS += 10000;
       REALLOCATE (stars, UKIRT_Stars, NSTARS);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise.c	(revision 42166)
@@ -22,5 +22,5 @@
   SetSignals ();
   options = ConfigInit (&argc, argv);
-  options = args_loadwise (argc, argv, options);
+  options = args_loadwise (&argc, argv, options);
 
   // load the full sky description table:
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_ops.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_ops.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_ops.c	(revision 42166)
@@ -17,8 +17,14 @@
   char *ptr = line;
 
-  ptr = skipNbounds (ptr, '|', 1, Nmax);
-  *R = strtod (ptr, NULL);
-  ptr = skipNbounds (ptr, '|', 1, Nmax);
-  *D = strtod (ptr, NULL);
+  if (MODE == MODE_CATWISE) {
+      // copy the string ranges and then use strtod (not necessary?)
+      *R = strtod (&ptr[47], NULL); // safe to use the strtod on the line because it is white-space separated
+      *D = strtod (&ptr[59], NULL);
+  } else {
+      ptr = skipNbounds (ptr, '|', 1, Nmax);
+      *R = strtod (ptr, NULL);
+      ptr = skipNbounds (ptr, '|', 1, Nmax);
+      *D = strtod (ptr, NULL);
+  }
   if (*D > 90) Shutdown ("weird DEC value: something is wrong");
 
@@ -91,4 +97,27 @@
 }
   
+/* return a pointer to the first char after Nbound of value bound */
+char *getLineSegment (char *line, int start, int end) {
+
+  // do NOT damage the buffer by seting the end byte to NULL
+  if (0) { line[end] = 0; }
+  char *ptr = &line[start];
+  return (ptr);
+}
+  
+double getDoubleRAW (char *line, int start, int end) {
+    char *ptr = getLineSegment(line, start, end);
+    double value = strtod (ptr, NULL);
+    return value;
+}
+
+double getDoubleNAN (char *line, int start, int end) {
+    char *endpoint = NULL;
+    char *ptr = getLineSegment(line, start, end);
+    double value = strtod (ptr, &endpoint);
+    if (endpoint == ptr) { value = NAN; }
+    return value;
+}
+
 /* watch for patches which cross 0,360 boundary */
 SkyTable *loadWISE_acc (char *path, char *accel) {
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_rawdata.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_rawdata.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_rawdata.c	(revision 42166)
@@ -28,4 +28,6 @@
   getWISE_setup ();
 
+  int NMeasPerStar = (MODE == MODE_CATWISE) ? 2 : 4;
+
   ALLOCATE (buffer, char, NBYTE);
 
@@ -34,4 +36,6 @@
   if (f == NULL) Shutdown ("can't read WISE data file: %s", filename);
   // test if this is a raw datafile or gzipped...
+
+  int skipHeader = TRUE;
 
   Nextra = 0;  // number excess bytes from lsat partial row
@@ -59,6 +63,18 @@
     Dmax = -90.0;
 
+    // XXX buffer is being reread instead of continuing.
+
     // scan through entire buffer for star coords
     while (1) {
+
+      if (skipHeader && (MODE == MODE_CATWISE)) {
+	if (*p == '\\') goto skip_header;
+	if (*p == '|') goto skip_header;
+      }
+      if (skipHeader && (MODE == MODE_CATWISE)) {
+	// once we get past the header, do not skip any more
+	skipHeader = FALSE;
+      }
+
       getWISE_coords (p, &tstars[Ntstars].R, &tstars[Ntstars].D, Nbyte - offset);
       tstars[Ntstars].offset = offset; // offset within scan
@@ -74,4 +90,6 @@
       Ntstars ++;
       CHECK_REALLOCATE (tstars, WISE_Stars, NTSTARS, Ntstars, 10000);
+
+    skip_header:
 
       /* start of the next line */
@@ -143,8 +161,9 @@
 	if (tstars[j].D > UserPatch.Dmax) continue;
 	  
+	// offset is bytes to start of line from start of buffer
 	offset = tstars[j].offset;
 
 	dvo_average_init (&newcat->average[Nave]);
-	for (k = 0; k < 4; k++) {
+	for (k = 0; k < NMeasPerStar; k++) {
 	  dvo_measure_init (&newcat->measure[Nmeas+k]);
 	}
@@ -163,4 +182,7 @@
 	    loadwise_star_allwise (&newcat->measure[Nmeas], &buffer[offset], Nbyte - offset);
 	    break;
+	  case MODE_CATWISE:
+	    loadwise_star_catwise (&newcat->measure[Nmeas], &buffer[offset], Nbyte - offset, tstars[j].R, tstars[j].D);
+	    break;
 	  default:
 	    break;
@@ -169,9 +191,9 @@
 	tstars[j].flag = TRUE;
 
-	newcat->average[Nave].Nmeasure = 4;
+	newcat->average[Nave].Nmeasure = NMeasPerStar;
 	newcat->average[Nave].measureOffset = Nmeas;
 
 	Nave ++;
-	Nmeas += 4;
+	Nmeas += NMeasPerStar;
 
 	CHECK_REALLOCATE (newcat->average, Average, NAVE,  Nave,  1000);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_star_full.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_star_full.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/addstar/src/loadwise_star_full.c	(revision 42166)
@@ -2,12 +2,95 @@
 # include "WISE.h"
 
-int setWISE_ph_qual (Measure *measure, char qual);
 int setWISE_var_flag_allsky (Measure *measure, char qual);
 int setWISE_ext_flag_allsky (Measure *measure, char ptr);
 int setWISE_var_flag_prelim (Measure *measure, char qual);
 int setWISE_ext_flag_prelim (Measure *measure, char ptr);
-int setWISE_cc_flag (Measure *measure, char qual);
-int setWISE_sat_flag (Measure *measure, char *ptr);
 int setWISE_blend_flag (Measure *measure, char *ptr);
+
+// fill in the data for a CatWISE double star.  takes a pointer to the start of the line the
+// RA and DEC have already been set
+int loadwise_star_catwise (Measure *measure, char *line, int Nmax, double Rs, double Ds) {
+
+  if (line == NULL) Shutdown ("format error in WISE");
+
+  /*** CATWISE has fixed width data, not pipe-separated, etc ***/
+
+  // https://irsa.ipac.caltech.edu/data/WISE/CatWISE/gator_docs/catwise_colDescriptions.html
+
+  // We are supplied a pointer (line) to the start of a full line of data.  The CatWISE
+  // format uses fixed-width fields with white-space separators.  The ra & dec values have
+  // already been extracted.
+
+  measure[0].R    = Rs;
+  measure[0].D    = Ds;
+  measure[1].R    = Rs;
+  measure[1].D    = Ds;
+
+  // I can assign dRA and dDEC to dX and dY if I can consistently set posangle and pltscale
+  measure[0].dXccd = ToShortPixels(getDoubleRAW (line, 71, 79) + 0.005); // sig_ra -- add 5/1000 to avoid truncation
+  measure[0].dYccd = ToShortPixels(getDoubleRAW (line, 80, 88) + 0.005); // sig_dec
+  measure[0].posangle = 0.0;
+  measure[0].pltscale = 1.0;
+
+  // we only know a single set of values for both bands 
+  measure[1].dXccd    = measure[0].dXccd;
+  measure[1].dYccd    = measure[0].dYccd;
+  measure[1].posangle = measure[0].posangle;
+  measure[1].pltscale = measure[0].pltscale;
+
+  measure[0].Xccd = getDoubleRAW (line,  98, 106); // wx
+  measure[0].Yccd = getDoubleRAW (line, 107, 115); // wy
+  measure[1].Xccd = measure[0].Xccd;
+  measure[1].Yccd = measure[0].Yccd;
+
+  // W1
+  measure[0].M         = getDoubleNAN (line, 248, 254); // w1mpro
+  measure[0].dM        = getDoubleNAN (line, 255, 264); // w1sigmpro
+  measure[0].psfChisq  = getDoubleRAW (line, 265, 275); // w1rchi2
+  measure[0].psfQF     = measure[0].psfChisq;
+  measure[0].photFlags = 0;
+
+  // W2
+  measure[1].M         = getDoubleNAN (line, 276, 282); // w2mpro
+  measure[1].dM        = getDoubleNAN (line, 283, 292); // w2sigmpro
+  measure[1].psfChisq  = getDoubleRAW (line, 293, 303); // w2rchi2
+  measure[1].psfQF     = measure[1].psfChisq;
+  measure[1].photFlags = 0;
+
+  setCatWISE_blend_flag (measure, line); // w1sat
+
+  setCatWISE_sat_flag (&measure[0], line, 323, 330); // w1sat
+  setCatWISE_sat_flag (&measure[1], line, 331, 338); // w2sat
+
+  // cc_flags? 1642 - 1657
+  // setWISE_cc_flag (&measure[0], ptr[i]); // cc_flags
+
+  // set ext flags for all 4 measures
+  // setCatWISE_ext_flag_allsky (measure, ptr[0]); // ext_flg
+
+  // setWISE_var_flag_allsky (&measure[0], ptr[i]); // var_flg
+
+  // setWISE_ph_qual (&measure[i], ptr[i]); // ph_qual
+
+  double mjdmean = getDoubleRAW (line, 1126, 1138); // MeanObsMJD
+  
+  // the release is based on data taken in the period 14 January 2010 to 29 April 2010
+  if (mjdmean == 0.0) {
+    measure[0].t = 0;
+  } else {
+    measure[0].t = ohana_mjd_to_sec (mjdmean);
+  }
+  measure[1].t = measure[0].t;
+
+  measure[0].photcode  = WISE_W1;
+  measure[0].detID   = 0;
+  measure[0].imageID = 0;
+
+  measure[1].photcode  = WISE_W2;
+  measure[1].detID   = 0;
+  measure[1].imageID = 0;
+
+  return TRUE;
+}
 
 // fill in the data for a WISE quad star.  takes a pointer to the start of the line the
@@ -458,4 +541,22 @@
 }
 
+int setCatWISE_blend_flag (Measure *measure, char *line) {
+
+  // na
+  int nb = atoi(getLineSegment(line, 315, 318)); // nb
+  int na = atoi(getLineSegment(line, 319, 322)); // na
+
+  if (nb != 1) {
+    if (na == 0) {
+      measure[0].photFlags |= FLAG_BLEND_ACTIVE;
+      measure[1].photFlags |= FLAG_BLEND_ACTIVE;
+    } else {
+      measure[0].photFlags |= FLAG_BLEND_PASSIVE;
+      measure[1].photFlags |= FLAG_BLEND_PASSIVE;
+    }
+  }
+  return TRUE;
+}
+
 int setWISE_sat_flag (Measure *measure, char *ptr) {
 
@@ -465,4 +566,13 @@
     }
     return TRUE;
+}
+
+int setCatWISE_sat_flag (Measure *measure, char *ptr, int start, int end) {
+
+  float sat = getDoubleRAW (ptr, start, end);
+  if (sat > 0.0) {
+    measure[0].photFlags |= FLAG_SATURATED_PIX;
+  }
+  return TRUE;
 }
 
Index: /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/include/dvomerge.h	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/include/dvomerge.h	(revision 42166)
@@ -65,4 +65,5 @@
 int    RESET_LENSING;
 
+int    SKIP_IMAGES; 
 int    SKIP_MEASURE;
 int    SKIP_MISSING;
Index: /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/args.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/args.c	(revision 42166)
@@ -39,9 +39,18 @@
     remove_argument (N, argc, argv);
   }
-
-  /* extra error messages */
-  MATCHED_TABLES = FALSE;
+  SKIP_IMAGES = FALSE;
+  if ((N = get_argument (*argc, argv, "-skip-images"))) {
+    SKIP_IMAGES = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  /* extra error messages */
+  MATCHED_TABLES = TRUE;
   if ((N = get_argument (*argc, argv, "-matched-tables"))) {
     MATCHED_TABLES = TRUE;
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-unmatched-tables"))) {
+    MATCHED_TABLES = FALSE;
     remove_argument (N, argc, argv);
   }
@@ -77,4 +86,14 @@
     SKIP_GALPHOT = TRUE;
     remove_argument (N, argc, argv);
+  }
+
+  if (SKIP_IMAGES && !(SKIP_MEASURE || SKIP_LENSING)) {
+    fprintf (stderr, "WARNING: skipping images but merging measure and lensing tables: imageIDs will not be correct\n");
+    fprintf (stderr, "type Ctrl-C within 5 seconds to cancel\n");
+    for (int i = 5; i > 0; i--) {
+      fprintf (stderr, "%d.. ", i);
+      usleep (1000000);
+    }
+    fprintf (stderr, "\n");
   }
 
Index: /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvo_image_merge_dbs.c	(revision 42166)
@@ -404,9 +404,9 @@
   off_t i;
 
-  for (i = 0; i < IDmap->oldIDmax + 1; i++) {
+  for (i = 0; IDmap->notFoundMeasure && (i < IDmap->oldIDmax + 1); i++) {
     if (!IDmap->notFoundMeasure[i]) continue;
     fprintf (stderr, "SKIP IMAGE MEASURE: "OFF_T_FMT", %d measures\n", i, IDmap->notFoundMeasure[i]);
   }
-  for (i = 0; i < IDmap->oldIDmax + 1; i++) {
+  for (i = 0; IDmap->notFoundLensing && (i < IDmap->oldIDmax + 1); i++) {
     if (!IDmap->notFoundLensing[i]) continue;
     fprintf (stderr, "SKIP IMAGE LENSING: "OFF_T_FMT", %d lensings\n", i, IDmap->notFoundLensing[i]);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate.c	(revision 42166)
@@ -81,12 +81,15 @@
   }
 
-  if (CONTINUE) {
-    // need to determine the mapping from the input to the output images
-    dvomergeImagesGetMap (&IDmap, input, output);
-  } else {
-    dvomergeImagesUpdate (&IDmap, input, output);
-    if (IMAGES_ONLY) exit (0);
+  // do not merge the images unless requested
+  if (!SKIP_IMAGES) {
+    if (CONTINUE) {
+      // need to determine the mapping from the input to the output images
+      dvomergeImagesGetMap (&IDmap, input, output);
+    } else {
+      dvomergeImagesUpdate (&IDmap, input, output);
+      if (IMAGES_ONLY) exit (0);
+    }
   }
-
+    
   // load the sky table for the existing database
   insky = SkyTableLoadOptimal (input, NULL, NULL, FALSE, SKY_DEPTH_HST, VERBOSE);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate_catalogs.c	(revision 42166)
@@ -163,4 +163,5 @@
     }
 
+    // for SKIP_IMAGES, this is a NO-OP
     dvo_update_image_IDs (IDmap, &incatalog);
 
Index: /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate_threaded.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate_threaded.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/dvomerge/src/dvomergeUpdate_threaded.c	(revision 42166)
@@ -69,4 +69,5 @@
       LoadCatalog (&outcatalog, outlist[0].regions[j], outlist[0].filename[j], "w", threadData->NsecfiltOutput);
 
+      // for SKIP_IMAGES, this is a NO-OP
       dvo_update_image_IDs (threadData->IDmap, &incatalog);
       merge_catalogs_old (&threadData->outsky->regions[j], &outcatalog, &incatalog, RADIUS, threadData->secfiltMap);
@@ -183,10 +184,12 @@
   }
 
-  if (CONTINUE) {
-    // need to determine the mapping from the input to the output images
-    dvomergeImagesGetMap (&IDmap, input, output);
-  } else {
-    dvomergeImagesUpdate (&IDmap, input, output);
-    if (IMAGES_ONLY) exit (0);
+  if (!SKIP_IMAGES) {
+    if (CONTINUE) {
+      // need to determine the mapping from the input to the output images
+      dvomergeImagesGetMap (&IDmap, input, output);
+    } else {
+      dvomergeImagesUpdate (&IDmap, input, output);
+      if (IMAGES_ONLY) exit (0);
+    }
   }
 
Index: /branches/eam_branches/ipp-20220316/Ohana/src/libohana/src/errors.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/libohana/src/errors.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/libohana/src/errors.c	(revision 42166)
@@ -26,4 +26,12 @@
 
 int push_error (char *line) {
+
+  if (!errorlines) {
+    NLINE = 10;
+    ALLOCATE (errorlines, char *, NLINE);
+    for (int i = 0; i < NLINE; i++) {
+      errorlines[i] = NULL;
+    }
+  }
 
   errorlines[Nline] = strcreate (line);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/Makefile	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/Makefile	(revision 42166)
@@ -106,4 +106,5 @@
 $(SRC)/mget3d.$(ARCH).o		\
 $(SRC)/mslice.$(ARCH).o		\
+$(SRC)/mlayer.$(ARCH).o		\
 $(SRC)/minterpolate.$(ARCH).o	\
 $(SRC)/medimage.$(ARCH).o	\
Index: /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/create.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/create.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/create.c	(revision 42166)
@@ -3,5 +3,5 @@
 int create (int argc, char **argv) {
   
-  int i, N, INT;
+  int i, N;
   opihi_flt start, end, delta;
   Vector *vec;
@@ -34,5 +34,5 @@
   }
 
-  INT = FALSE;
+  int INT = FALSE;
   if ((N = get_argument (argc, argv, "-int"))) {
     INT = TRUE;
@@ -40,12 +40,18 @@
   }
 
-  if ((argc != 5) && (argc != 4)) {
-    gprint (GP_ERR, "USAGE: create vector start end [delta] [-int]\n");
-    gprint (GP_ERR, " -int : resulting vector is integer type (delta must be integer)\n");
-    gprint (GP_ERR, " -str : resulting vector is string type (only give number of elements)\n");
-    return (FALSE);
+  int EMPTY = FALSE;
+  if ((N = get_argument (argc, argv, "-empty"))) {
+    EMPTY = TRUE;
+    remove_argument (N, &argc, argv);
   }
 
+  if (!EMPTY && (argc != 5) && (argc != 4)) goto usage;
+  if (EMPTY && (argc != 2)) goto usage;
+
   if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if (EMPTY) {
+    ResetVector (vec, (INT ? OPIHI_INT : OPIHI_FLT), 0);
+    return TRUE;
+  }
 
   delta = 1;
@@ -91,3 +97,10 @@
 
   return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "USAGE: create vector start end [delta] [-int]\n");
+  gprint (GP_ERR, " -int : resulting vector is integer type (delta must be integer)\n");
+  gprint (GP_ERR, " -str : resulting vector is string type (only give number of elements)\n");
+  gprint (GP_ERR, "OR: create vector -empty (creates vector of length zero)\n");
+  return (FALSE);
 }
Index: /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/init.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/init.c	(revision 42166)
@@ -97,4 +97,5 @@
 int mget3d           PROTO((int, char **));
 int mslice           PROTO((int, char **));
+int mlayer           PROTO((int, char **));
 int minterp          PROTO((int, char **));
 int medimage_command PROTO((int, char **));
@@ -296,4 +297,5 @@
   {1, "mget3d",       mget3d,           "extract a vector from a 3D image"},
   {1, "mslice",       mslice,           "extract an image plane from a 3D image"},
+  {1, "mlayer",       mlayer,           "insert an image plane into a 3D image"},
   {1, "imget",        mget,             "extract a vector from an image"},
   {1, "minterp",      minterp,          "interpolate image pixels"},
Index: /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/mlayer.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/mlayer.c	(revision 42166)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/mlayer.c	(revision 42166)
@@ -0,0 +1,118 @@
+# include "data.h"
+
+int mlayer (int argc, char **argv) {
+  
+  int N;
+  Buffer *src, *tgt;
+
+  int Dir = 0;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    Dir = 1;    
+  }
+  if ((N = get_argument (argc, argv, "-y"))) {
+    remove_argument (N, &argc, argv);
+    if (Dir) {
+      gprint (GP_ERR, "ERROR: multiple -x,-y,-z options are not allowed\n");
+      return FALSE;
+    }
+    Dir = 2;    
+  }
+  if ((N = get_argument (argc, argv, "-z"))) {
+    remove_argument (N, &argc, argv);
+    if (Dir) {
+      gprint (GP_ERR, "ERROR: multiple -x,-y,-z options are not allowed\n");
+      return FALSE;
+    }
+    Dir = 3;    
+  }
+  if (!Dir) Dir = 3;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: mlayer <output> <input> plane [-x,-y,-z]\n");
+    gprint (GP_ERR, "  insert 2D image into 3D cube (opposite of mslice)\n");
+    gprint (GP_ERR, "  -z is default\n");
+    return (FALSE);
+  }
+
+  int plane = atoi(argv[3]);
+
+  if ((tgt = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if (tgt[0].matrix.Naxes < 3) {
+    gprint (GP_ERR, "buffer is not 3D\n");
+    return FALSE;
+  }
+  if ((src = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  int Nx = tgt[0].matrix.Naxis[0];
+  int Ny = tgt[0].matrix.Naxis[1];
+  int Nz = tgt[0].matrix.Naxis[2];
+
+  int NplaneMax = 0;
+  int Nsrc1 = 0;
+  int Nsrc2 = 0;
+
+  switch (Dir) {
+    case 1: NplaneMax = Nx; Nsrc1 = Ny; Nsrc2 = Nz; break;
+    case 2: NplaneMax = Ny; Nsrc1 = Nx; Nsrc2 = Nz; break;
+    case 3: NplaneMax = Nz; Nsrc1 = Nx; Nsrc2 = Ny; break;
+    default: myAbort ("impossible");
+  }
+
+  int invalid = FALSE;
+  invalid = invalid || (plane < 0);
+  invalid = invalid || (plane >= NplaneMax);
+  if (invalid) {
+    gprint (GP_ERR, "plane %d out of range (max = %d)\n", plane, NplaneMax);
+    return (FALSE);
+  }
+  if (Nsrc1 != src->matrix.Naxis[0]) {
+    gprint (GP_ERR, "source image does not match output cube dimensions (%d vs %ld)\n", Nsrc1, src->matrix.Naxis[0]);
+    return (FALSE);
+  }
+  if (Nsrc2 != src->matrix.Naxis[1]) {
+    gprint (GP_ERR, "source image does not match output cube dimensions (%d vs %ld)\n", Nsrc2, src->matrix.Naxis[1]);
+    return (FALSE);
+  }
+
+  // pixel (ix, iy, iz) : tgt[0].matrix.buffer + ix + iy*Nx + iz*Nx*Ny
+
+  switch (Dir) {
+    case 1: {
+      float *srcF = (float *) src[0].matrix.buffer;
+      
+      // pixel (ix, iy, iz) : tgt[0].matrix.buffer + ix + iy*Nx + iz*Nx*Ny
+
+      for (int iz = 0; iz < Nz; iz++) {
+	float *tgtF  = (float *) tgt[0].matrix.buffer + plane + iz*Nx*Ny;
+	for (int iy = 0; iy < Ny; iy++, tgtF += Nx, srcF++) {
+	  *tgtF = *srcF;
+	}
+      }
+      break;
+    }
+    case 2: {
+
+      float *srcF = (float *) src[0].matrix.buffer;
+
+      for (int iz = 0; iz < Nz; iz++) {
+	float *tgtF  = (float *) tgt[0].matrix.buffer + plane*Nx + iz*Nx*Ny;
+	for (int ix = 0; ix < Nx; ix++, tgtF++, srcF++) {
+	   *tgtF = *srcF;
+	}
+      }
+      break;
+    }
+    case 3: {
+      float *tgtF  = (float *) tgt[0].matrix.buffer + plane*Nx*Ny;
+      float *srcF = (float *) src[0].matrix.buffer;
+      
+      for (int i = 0; i < Nx*Ny; i++, tgtF ++, srcF++) {
+	*tgtF = *srcF;
+      }
+      break;
+    }
+    default: myAbort ("impossible");
+  }
+  return (TRUE);
+}
Index: /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/mslice.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/mslice.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/mslice.c	(revision 42166)
@@ -31,4 +31,5 @@
   if (argc != 4) {
     gprint (GP_ERR, "USAGE: mslice <input> <output> plane [-x,-y,-z]\n");
+    gprint (GP_ERR, "  extract 2D image from 3D cube (opposite of mlayer)\n");
     gprint (GP_ERR, "  -z is default\n");
     return (FALSE);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/write_vectors.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 42166)
@@ -102,5 +102,5 @@
   if (argc < 3) {
     gprint (GP_ERR, "USAGE: write [options] file vector vector ...\n");
-    gprint (GP_ERR, "OPTIONS: [-header] [-append] [-f \"format\"] [-fits NAME] [-csv] [-h,--help]\n");
+    gprint (GP_ERR, "OPTIONS: [-header [buf]] [-append] [-f \"format\"] [-fits NAME] [-csv] [-h,--help]\n");
     return (FALSE);
   }
@@ -289,8 +289,8 @@
  usage:
     gprint (GP_ERR, "USAGE: write [options] file vector vector ...\n");
-    gprint (GP_ERR, "OPTIONS: [-header] [-append] [-f \"format\"] [-fits NAME] [-csv] [-h,--help]\n\n");
+    gprint (GP_ERR, "OPTIONS: [-header [buf]] [-append] [-f \"format\"] [-fits NAME] [-csv] [-h,--help]\n\n");
 
     gprint (GP_ERR, "OPTIONS: \n");
-    gprint (GP_ERR, "  -header : add a descriptive header line to ascii or csv output\n");
+    gprint (GP_ERR, "  -header : add a descriptive header line to ascii or csv output (see below for FITS)\n");
     gprint (GP_ERR, "  -append : write to the end of the existing file\n");
     gprint (GP_ERR, "  -fits NAME : write a fits table (extention name is NAME, column names match vector names)\n");
Index: /branches/eam_branches/ipp-20220316/Ohana/src/opihi/lib.shell/VectorIO.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 42166)
@@ -267,5 +267,5 @@
 }
   
-static char *rawkeywords[] = {"SIMPLE", "BITPIX", "NAXIS", "PCOUNT", "GCOUNT", "EXTEND", "EXTNAME", "BSCALE", "BZERO", "TFIELDS", "TFORM", "TZERO", "TSCAL", "        ", NULL};
+static char *rawkeywords[] = {"SIMPLE", "BITPIX", "NAXIS", "PCOUNT", "GCOUNT", "EXTEND", "EXTNAME", "BSCALE", "BZERO", "TFIELDS", "TFORM", "TTYPE", "TZERO", "TSCAL", "        ", NULL};
 
 // write a set of vectors to a FITS file (vectors names become fits column names)
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/include/relphot.h
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/include/relphot.h	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/include/relphot.h	(revision 42166)
@@ -721,5 +721,5 @@
 int relphot_images (SkyList *skylist);
 
-void relphot_usage (void);
+void relphot_usage (int argc, char **argv);
 void relphot_help (int argc, char **argv);
 
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/ResetOps.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/ResetOps.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/ResetOps.c	(revision 42166)
@@ -123,10 +123,15 @@
 
   for (off_t i = 0; i < catalog->Naverage; i++) {
-    catalog->average[i].psfQF     = NAN;	// force recalculation in setMrelCatalog
-    catalog->average[i].psfQFperf = NAN;	// force recalculation in setMrelCatalog
-    catalog->average[i].stargal   = NAN;	// force recalculation in setMrelCatalog
-    catalog->average[i].photFlagsUpper = 0;	// reset (will be re-calculated)
-    catalog->average[i].photFlagsLower = 0;	// reset (will be re-calculated)
-    catalog->average[i].NwarpOK        = 0;	// reset (will be re-calculated)
+    if (STAGES & STAGE_CHIP) {
+      catalog->average[i].psfQF     = NAN;	// force recalculation in setMrelCatalog
+      catalog->average[i].psfQFperf = NAN;	// force recalculation in setMrelCatalog
+      catalog->average[i].stargal   = NAN;	// force recalculation in setMrelCatalog
+      catalog->average[i].photFlagsUpper = 0;	// reset (will be re-calculated)
+      catalog->average[i].photFlagsLower = 0;	// reset (will be re-calculated)
+    }
+    
+    if (STAGES & STAGE_WARP) {
+      catalog->average[i].NwarpOK        = 0;	// reset (will be re-calculated)
+    }
 
     // RESET_FLATCORR independent of RESET?
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/args.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/args.c	(revision 42166)
@@ -203,5 +203,5 @@
     remove_argument (N, &argc, argv);
     TEST_IMAGE1 = strtol(argv[N], &endptr, 0);
-    if (*endptr) relphot_usage (); 
+    if (*endptr) relphot_usage (argc, argv); 
     remove_argument (N, &argc, argv);
   }
@@ -211,5 +211,5 @@
     remove_argument (N, &argc, argv);
     TEST_IMAGE2 = strtol(argv[N], &endptr, 0);
-    if (*endptr) relphot_usage (); 
+    if (*endptr) relphot_usage (argc, argv); 
     remove_argument (N, &argc, argv);
   }
@@ -584,8 +584,8 @@
     remove_argument (N, &argc, argv);
     mode = PARALLEL_IMAGES;
-    if (N >= argc) relphot_usage();
+    if (N >= argc) relphot_usage(argc, argv);
     IMAGE_TABLE = strcreate (argv[N]);
     remove_argument (N, &argc, argv);
-    if (!REGION_FILE) relphot_usage();
+    if (!REGION_FILE) relphot_usage(argc, argv);
   }
 
@@ -594,5 +594,5 @@
     remove_argument (N, &argc, argv);
     mode = PARALLEL_REGIONS;
-    if (!REGION_FILE) relphot_usage();
+    if (!REGION_FILE) relphot_usage(argc, argv);
     if ((N = get_argument (argc, argv, "-parallel-regions-manual"))) {
       remove_argument (N, &argc, argv);
@@ -609,7 +609,9 @@
       // note: initialize sets PhotcodeList to the full set of average photcodes
       // if the mode is UPDATE_AVERAGES
-      if (argc != 1) relphot_usage();
-      break;
+      // if (argc != 1) relphot_usage(argc, argv);
+      // break;
       
+      if (argc == 1) break; // if no photcodes are given, use them all?
+
     case UPDATE_IMAGES:
     case PARALLEL_IMAGES:
@@ -623,8 +625,8 @@
     default:
       fprintf (stderr, "no valid mode selected\n");
-      relphot_usage();
+      relphot_usage(argc, argv);
       break;
   }
-  if (argc != 1) relphot_usage ();
+  if (argc != 1) relphot_usage (argc, argv);
 
   // if we supplied a file, we need to load it now
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/help.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/help.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/help.c	(revision 42166)
@@ -1,5 +1,5 @@
 # include "relphot.h"
 
-void relphot_usage (void) {
+void relphot_usage (int argc, char **argv) {
   fprintf (stderr, "ERROR: USAGE: relphot (photcodes) -images\n");
   fprintf (stderr, "       or:    relphot -averages\n");
@@ -11,4 +11,11 @@
   fprintf (stderr, "       or:    -catalog (name)\n");
   fprintf (stderr, "  use -h for more usage information\n");
+
+  fprintf (stderr, "unparsed arguments: ");
+  for (int i = 0; i < argc; i++) {
+    fprintf (stderr, "%s ", argv[i]);
+  }
+  fprintf (stderr, "\n");
+
   exit (2);
 } 
@@ -19,5 +26,5 @@
   if (get_argument (argc, argv, "-help")) goto show_help;
   if (get_argument (argc, argv, "-h"))    goto show_help;
-  if (argc == 1) relphot_usage();
+  if (argc == 1) relphot_usage(0, NULL);
   return;
 
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/initialize.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/initialize.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/initialize.c	(revision 42166)
@@ -9,6 +9,8 @@
   if (!mode) exit (2);
 
-  // UPDATE_AVERAGES always operates on all photcodes? 
-  if (mode == UPDATE_AVERAGES) {
+  // UPDATE_AVERAGES used to always operate on all photcodes
+  // now, if a list of photcodes are given that is used, otherwise
+  // all will be used
+  if (!photcodes) {
     char tmpline1[256];
     int Ns;
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/relphot_images.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/relphot_images.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/relphot_images.c	(revision 42166)
@@ -132,4 +132,7 @@
   
     // if (GRID_ZEROPT) dump_grid ();
+    setMcal  (catalog);
+    setMmos  (catalog);
+    setMgrp  (catalog);
 
     setMcal  (catalog);
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/setMrelCatalog.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/setMrelCatalog.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/setMrelCatalog.c	(revision 42166)
@@ -266,4 +266,6 @@
       // overlaps).  Msys + measure.Mcal is our best guess of the true magnitude
       Mcal = measureT[k].McalPSF; // check that this is zero for loaded REF value
+      // but external reference photometry might not have Mcal set, so set to 0.0 in that case.
+      if (isnan(Mcal)) Mcal = 0.0;
     } else {
       // getMcal returns image[].Mcal
@@ -412,5 +414,5 @@
 
     // XXX hardwired grizy = (01234) JHK = (567) w = (8)
-    if ((Nsec < 5) || (Nsec == 8)) {
+    if (Nsec < 5) {
       secfilt[Nsec].Ncode = results->NexpPS1[Nsec]; 
     } else {
Index: /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/setMrelFinal.c
===================================================================
--- /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/setMrelFinal.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/Ohana/src/relphot/src/setMrelFinal.c	(revision 42166)
@@ -11,4 +11,5 @@
   int Nsecfilt = GetPhotcodeNsecfilt ();
 
+  // this resets values only if -reset is used
   ResetAverageAndMeasure (catalog);
   
Index: /branches/eam_branches/ipp-20220316/doc/release.2015/ps1.datasystem/datasystem.tex
===================================================================
--- /branches/eam_branches/ipp-20220316/doc/release.2015/ps1.datasystem/datasystem.tex	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/doc/release.2015/ps1.datasystem/datasystem.tex	(revision 42166)
@@ -116,5 +116,8 @@
 The CCDs each consist of an $8\times8$ grid of $590 \times 598$
 pixel readout regions, yielding an effective $4846 \times 4868$
-detector.  Initial performance assessments are presented in
+detector.
+\textadd{The GPC1 CCDs have the ability to move charge in both
+  dimensions on the detector and are thus referred to as Orthogonal Transfer Arrays (OTAs).}
+Initial performance assessments are presented in
 \cite{2008SPIE.7014E..0DO}.  Routine observations are conducted remotely from the
 Advanced Technology Research Center in Kula, the main facility of the
Index: /branches/eam_branches/ipp-20220316/ippScripts/scripts/register_exp.pl
===================================================================
--- /branches/eam_branches/ipp-20220316/ippScripts/scripts/register_exp.pl	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippScripts/scripts/register_exp.pl	(revision 42166)
@@ -200,8 +200,4 @@
 	return(undef,undef,undef,"reg",undef,undef,undef);
     }
-    if ($obsmode eq 'ENGINEERING') {
-	print "Skipping because we don't queue engineering data to chip\n";
-	return(undef,undef,undef,"reg",undef,undef,undef);
-    }
     # Grab the configuration data.
     my %nightlyscience_config = ();
Index: /branches/eam_branches/ipp-20220316/ippTests/ippCheck/cammask.pro
===================================================================
--- /branches/eam_branches/ipp-20220316/ippTests/ippCheck/cammask.pro	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippTests/ippCheck/cammask.pro	(revision 42166)
@@ -78,4 +78,18 @@
  if ($table:Ny == 0)
   echo "ERROR: no reference sources found in $refsrcs"
+
+  # generate an empty output file
+  $OUT_FIELDS = 
+  foreach field $SMF_FIELDS_CAM $REF_FIELDS_CAM $XTR_FIELDS_CAM
+    $OUT_FIELDS = $OUT_FIELDS $field\_out
+    create -empty $field\_out
+  end
+  
+  sprintf output "%s/%s.%s.cam.stf" $OUTDIR $expname $OUTVERSION
+  write -fits DATA $output $OUT_FIELDS
+  
+  # save this name for warp and diff analysis, if desired
+  $CAMSOURCE = $output
+
   break
  end
@@ -271,6 +285,7 @@
    if ($COPYMASKS) exec neb-copy $camMask:$i $OUTDIR
    $j ++
- end
- $camMask:n = $chipName:n
+   if ($j >= $tmpName:n) last
+ end
+ $camMask:n = $tmpName:n
 end
 
Index: /branches/eam_branches/ipp-20220316/ippTests/ippCheck/camstats.pro
===================================================================
--- /branches/eam_branches/ipp-20220316/ippTests/ippCheck/camstats.pro	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippTests/ippCheck/camstats.pro	(revision 42166)
@@ -38,5 +38,5 @@
    # results in magFound, fracFound, numFound
    calc.camstats
-   if ($i == 0)
+   if (numTotal_sum?[] == 0)
      set numTotal_sum = numTotal
      set numFound_sum = numFound
@@ -57,9 +57,13 @@
  end
    
- set numTotal = numTotal_sum
- set numFound = numFound_sum
- set numPoss  = numPoss_sum
- set numGood  = numGood_sum
- delete numTotal_sum numFound_sum numPoss_sum numGood_sum
+ if (numTotal_sum?[] == 0)
+   calc.camstats 
+ else 
+   set numTotal = numTotal_sum
+   set numFound = numFound_sum
+   set numPoss  = numPoss_sum
+   set numGood  = numGood_sum
+   delete numTotal_sum numFound_sum numPoss_sum numGood_sum
+ end
 
  set fracFound = (numTotal > 0) ? numFound / numTotal : zero(numTotal)
@@ -79,11 +83,16 @@
   $BST2 = -tickpad 0.2 -xpad 3.5 -labelpadx 3.0 -ypad 0.5 -labelpady 0.0 +ypad 4.5 +labelpady 4.0 -labels 1001
   
-  section aM 0.00 0.66 0.65 0.33
-  section aR 0.00 0.33 0.65 0.33
-  section aD 0.00 0.00 0.65 0.33
-
-  section bM 0.65 0.66 0.35 0.33
-  section bR 0.65 0.33 0.35 0.33
-  section bD 0.65 0.00 0.35 0.33
+  section aM 0.00 0.66 0.65 0.33;  label -x mag -y "&sd&h mag"
+  section aR 0.00 0.33 0.65 0.33;  label -x mag -y "&sd&h R.A."
+  section aD 0.00 0.00 0.65 0.33;  label -x mag -y "&sd&h Dec" 
+
+  section bM 0.65 0.66 0.35 0.33;  label -x mag -y "&sd&h mag" 
+  section bR 0.65 0.33 0.35 0.33;  label -x mag -y "&sd&h R.A."
+  section bD 0.65 0.00 0.35 0.33;  label -x mag -y "&sd&h Dec" 
+
+  if (RA_PSF?[] == 0)
+    echo "no sources in datafile"
+    return
+  end
 
   set dR = 3600*(RA_PSF - Rref)*dcos(Dref)
@@ -256,4 +265,13 @@
  $Mdel = 0.25
  
+ if (Mref_out?[] == 0)
+   create magBin $Mmin $Mmax $Mdel
+   set numTotal = zero(magBin)
+   set numFound = zero(magBin)
+   set numPoss  = zero(magBin)
+   set numGood  = zero(magBin)
+   return
+ end
+
  delete -q  magBin numTotal numPoss numFound numGood
  for mag $Mmin $Mmax $Mdel
Index: /branches/eam_branches/ipp-20220316/ippTests/ippCheck/diffmask.pro
===================================================================
--- /branches/eam_branches/ipp-20220316/ippTests/ippCheck/diffmask.pro	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippTests/ippCheck/diffmask.pro	(revision 42166)
@@ -51,5 +51,22 @@
   # load the reference source table
   # how to choose the name of the filter?
-  data $refsrcs; 
+  data $refsrcs
+
+  # first check if the FITS table has any entries
+  read -fits DATA -sizes
+  if ($table:Ny == 0) 
+    echo "WARNING: empty reference table $refsrcs"
+
+    $OUT_FIELDS = 
+    foreach field $SMF_FIELDS_DIF $REF_FIELDS_DIF $XTR_FIELDS_DIF
+      $OUT_FIELDS = $OUT_FIELDS $field\_out
+      create -empty $field\_out
+    end
+    
+    sprintf output "%s/%s.%s.dif.stf" $OUTDIR $expname $OUTVERSION
+    write -fits DATA $output $OUT_FIELDS
+    return
+  end
+
   if ($USE_CAMSOURCE) 
    read -fits DATA Rref_out Dref_out Mref_out
Index: /branches/eam_branches/ipp-20220316/ippTests/ippCheck/ippCheck
===================================================================
--- /branches/eam_branches/ipp-20220316/ippTests/ippCheck/ippCheck	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippTests/ippCheck/ippCheck	(revision 42166)
@@ -59,5 +59,5 @@
   getargs -no-warp  BOOL  -var SKIP_WARP
   getargs -no-diff  BOOL  -var SKIP_DIFF
-  getargs -do-plots BOOL  -var DO_PLOTS;   
+  getargs -no-plots BOOL  -var SKIP_PLOTS;   
   getargs -use-refs BOOL  -var USE_REFSOURCE
   getargs -camera   VALUE -var CAMERA;
@@ -97,5 +97,5 @@
   end
 
-  if ($DO_PLOTS) plot.exposure.real $expname
+  if (not($SKIP_PLOTS)) plot.exposure.real $expname
 end
 
Index: /branches/eam_branches/ipp-20220316/ippTests/ippCheck/warpmask.pro
===================================================================
--- /branches/eam_branches/ipp-20220316/ippTests/ippCheck/warpmask.pro	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippTests/ippCheck/warpmask.pro	(revision 42166)
@@ -44,4 +44,23 @@
   # NOTE: Mref is chosen to match filter for this exposure
   data $refsrcs                 ;
+
+  # first check if the FITS table has any entries
+  read -fits DATA -sizes
+  if ($table:Ny == 0) 
+    echo "WARNING: empty reference table $refsrcs"
+
+    # generate empty output vectors for output file
+    $OUT_FIELDS = 
+    foreach field $REF_FIELDS_WRP $XTR_FIELDS_WRP
+      $OUT_FIELDS = $OUT_FIELDS $field\_out
+      create -empty $field\_out
+    end
+    
+    sprintf output "%s/%s.%s.wrp.stf" $OUTDIR $expname $OUTVERSION
+    write -fits DATA $output $OUT_FIELDS
+
+    return
+  end
+
   if ($USE_CAMSOURCE) 
    read -fits DATA Rref_out Dref_out Mref_out
Index: /branches/eam_branches/ipp-20220316/ippTests/ippCheck/warpstats.pro
===================================================================
--- /branches/eam_branches/ipp-20220316/ippTests/ippCheck/warpstats.pro	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippTests/ippCheck/warpstats.pro	(revision 42166)
@@ -24,5 +24,5 @@
    # results in magFound, fracFound, numFound
    calc.warpstats
-   if ($i == 0)
+   if (numTotal_sum?[] == 0)
      set numTotal_sum = numTotal
      set numPoss_sum  = numPoss
@@ -39,7 +39,12 @@
  end
    
- set numTotal = numTotal_sum
- set numPoss  = numPoss_sum
- delete numTotal_sum numPoss_sum
+ if (numTotal_sum?[] == 0)
+    # generate vectors for empty inputs
+   calc.warpstats
+ else   
+   set numTotal = numTotal_sum
+   set numPoss  = numPoss_sum
+   delete numTotal_sum numPoss_sum
+ end
 
  set fracPoss  = (numTotal > 0) ? numPoss  / numTotal : zero(numTotal)
@@ -89,4 +94,11 @@
  $Mdel = 0.25
  
+ if (Mref_out?[] == 0)
+   create magBin $Mmin $Mmax $Mdel
+   set numTotal = zero(magBin)
+   set numPoss  = zero(magBin)
+   return
+ end
+
  delete -q  magBin numTotal numPoss
  for mag $Mmin $Mmax $Mdel
Index: /branches/eam_branches/ipp-20220316/ippTools/src/pztoolConfig.c
===================================================================
--- /branches/eam_branches/ipp-20220316/ippTools/src/pztoolConfig.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippTools/src/pztoolConfig.c	(revision 42166)
@@ -171,5 +171,4 @@
     psMetadataAddStr(updatepzexpArgs, PS_LIST_TAIL, "-set_state",  0,            "define new state (required)", NULL);
     
-# if (0)
     // -updatesummitexp
     psMetadata *updatesummitexpArgs = psMetadataAlloc();
@@ -179,5 +178,4 @@
     psMetadataAddStr(updatesummitexpArgs, PS_LIST_TAIL, "-telescope",  0,            "search by telescope (required)", NULL);
     psMetadataAddS32(updatesummitexpArgs, PS_LIST_TAIL, "-set_fault",  0,            "define new fault (required)", 0);
-# endif
     
     // -updatenewexp
Index: /branches/eam_branches/ipp-20220316/ippconfig/megacam/psphot.config
===================================================================
--- /branches/eam_branches/ipp-20220316/ippconfig/megacam/psphot.config	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippconfig/megacam/psphot.config	(revision 42166)
@@ -40,3 +40,9 @@
   IMSTATS_NPIX            S32   100000
   SKY_STAT                STR   ROBUST_MEDIAN
+
+  PSF.TREND.MODE                      STR   MAP
+  PSF.TREND.NX                        S32   2
+  PSF.TREND.NY                        S32   3
+
+  APTREND.ORDER.MAX                   S32   1
 END
Index: /branches/eam_branches/ipp-20220316/ippconfig/recipes/filerules-mef.mdc
===================================================================
--- /branches/eam_branches/ipp-20220316/ippconfig/recipes/filerules-mef.mdc	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippconfig/recipes/filerules-mef.mdc	(revision 42166)
@@ -191,4 +191,6 @@
 PPBGRESTORE.INPUT       INPUT    @FILES        CHIP       IMAGE
 PPBGRESTORE.BACKMDL     INPUT    @FILES        CHIP       IMAGE
+
+PPVIZPATTERN.INPUT        INPUT    @FILES        CHIP       PATTERN
 
 PPBACKGROUND.IMAGE	  INPUT    @FILES        CHIP       IMAGE
@@ -425,6 +427,10 @@
 PPBGRESTORE.OUTPUT      OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE     COMP_IMG   CHIP       TRUE      NONE
 
-PPBACKGROUND.OUTPUT	     OUTPUT {OUTPUT}.{CHIP.NAME}.fits    IMAGE     COMP_IMG   CHIP       TRUE      NONE
-PPBACKGROUND.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.mk.fits MASK      COMP_MASK  CHIP       TRUE      NONE
+PPVIZPSF.OUTPUT              OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE           NONE       CHIP       TRUE      NONE
+PPVIZPATTERN.OUTPUT          OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE           NONE       CHIP       TRUE      NONE
+PPVIZPATTERN.CHIP            OUTPUT {OUTPUT}.{CHIP.NAME}.ch.fits      IMAGE           NONE       CHIP       TRUE      NONE
+
+PPBACKGROUND.OUTPUT	     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE           COMP_IMG   CHIP       TRUE      NONE
+PPBACKGROUND.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.mk.fits      MASK            COMP_MASK  CHIP       TRUE      NONE
 PPBACKGROUND.CONFIG          OUTPUT {OUTPUT}.{CHIP.NAME}.ppBackground.mdc TEXT        NONE       CHIP       TRUE      NONE
 PPBACKGROUND.STATS           OUTPUT {OUTPUT}.{CHIP.NAME}.stats        STATS           NONE       CHIP       TRUE      NONE
Index: /branches/eam_branches/ipp-20220316/ippconfig/recipes/filerules-simple.mdc
===================================================================
--- /branches/eam_branches/ipp-20220316/ippconfig/recipes/filerules-simple.mdc	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ippconfig/recipes/filerules-simple.mdc	(revision 42166)
@@ -407,4 +407,8 @@
 PPBGRESTORE.OUTPUT           OUTPUT {OUTPUT}.fits                 IMAGE           NONE       FPA        TRUE      NONE
 
+PPVIZPSF.OUTPUT              OUTPUT {OUTPUT}.fits                     IMAGE           NONE       CHIP       TRUE      NONE
+PPVIZPATTERN.OUTPUT          OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE           NONE       CHIP       TRUE      NONE
+PPVIZPATTERN.CHIP            OUTPUT {OUTPUT}.{CHIP.NAME}.ch.fits      IMAGE           NONE       CHIP       TRUE      NONE
+
 PPBACKGROUND.OUTPUT	     OUTPUT {OUTPUT}.{CHIP.NAME}.fits         IMAGE           NONE       FPA        TRUE      NONE
 PPBACKGROUND.OUTPUT.MASK     OUTPUT {OUTPUT}.{CHIP.NAME}.mk.fits      MASK            NONE       FPA        TRUE      NONE
Index: /branches/eam_branches/ipp-20220316/ppImage/src/ppImageDetrendPattern.c
===================================================================
--- /branches/eam_branches/ipp-20220316/ppImage/src/ppImageDetrendPattern.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ppImage/src/ppImageDetrendPattern.c	(revision 42166)
@@ -327,2 +327,26 @@
 }
 
+psVector *ppImageDetrendPatternCellFailures(pmFPAfile *input, const pmFPAview *inputView) {
+    
+    bool status = false;
+    pmCell *cell = NULL;
+    
+    pmFPAview *view = pmFPAviewAlloc(0); // View for local processing
+    *view = *inputView;
+
+    // extract the MEDIAN_CELL_BACKGROUND values to check for problems
+    psVector *cellBackground = psVectorAllocEmpty (64, PS_DATA_F32);
+    while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
+	if (!cell->process || !cell->file_exists || !cell->data_exists) {
+	    psVectorAppend (cellBackground, NAN);
+	    continue;
+	}
+	
+	// select the HDU for this cell
+	pmHDU *hdu = pmHDUFromCell(cell);  // HDU of interest
+	
+	psF32 value = psMetadataLookupF32(&status, hdu->header, "BACK_VAL");
+	psVectorAppend (cellBackground, value);
+    }
+    return cellBackground;
+}
Index: /branches/eam_branches/ipp-20220316/ppImage/src/ppImageLoop.c
===================================================================
--- /branches/eam_branches/ipp-20220316/ppImage/src/ppImageLoop.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ppImage/src/ppImageLoop.c	(revision 42166)
@@ -170,4 +170,12 @@
             ESCAPE("Unable to free detrend images");
         }
+
+        // Apply the pattern correction
+        // XX if (options->checkCellFailures) {
+        // XX   if (!ppImageDetrendPatternCellFailures(config,chip,view,options)) {
+        // XX     ESCAPE("Unable to apply pattern corrections");
+        // XX   }
+        // XX }
+
 
         // Apply the fringe correction
Index: /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoord.h
===================================================================
--- /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoord.h	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoord.h	(revision 42166)
@@ -14,4 +14,5 @@
     psString rawName;                   // Filename with raw image (or NULL)
     psString pixelsName;                // Filename with pixel coordinates
+    psString fpaName;                   // Filename with FPA coordinates
     psString chipName;                  // Name of chip of interest
     psString radecName;                 // Filename with sky coordinates
Index: /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordArguments.c
===================================================================
--- /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordArguments.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordArguments.c	(revision 42166)
@@ -49,4 +49,5 @@
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-raw", 0, "Filename with raw data", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-pixels", 0, "Filename with pixel coordinates", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-fpa", 0, "Filename with FPA coordinates", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-chip", 0, "Chip for pixel coordinates", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-radec", 0, "Filename with RA,Dec (default decimal degrees)", NULL);
@@ -66,4 +67,5 @@
     data->rawName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-raw"));
     data->pixelsName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-pixels"));
+    data->fpaName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-fpa"));
     data->chipName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-chip"));
     data->radecName = psMemIncrRefCounter(psMetadataLookupStr(NULL, arguments, "-radec"));
@@ -96,6 +98,6 @@
     }
 
-    if (!data->pixelsName && !data->radecName && !data->streaksName && !data->clustersName) {
-        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Neither -pixels nor -radec provided.");
+    if (!data->pixelsName && !data->radecName && !data->fpaName && !data->streaksName && !data->clustersName) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Neither -pixels nor -radec nor -fpa provided.");
         return false;
     }
Index: /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordData.c
===================================================================
--- /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordData.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordData.c	(revision 42166)
@@ -16,4 +16,5 @@
     psFree(data->rawName);
     psFree(data->pixelsName);
+    psFree(data->fpaName);
     psFree(data->chipName);
     psFree(data->radecName);
@@ -37,4 +38,5 @@
     data->rawName = NULL;
     data->pixelsName = NULL;
+    data->fpaName = NULL;
     data->chipName = NULL;
     data->radecName = NULL;
Index: /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordLoop.c
===================================================================
--- /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordLoop.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/ppViz/src/ppCoord/ppCoordLoop.c	(revision 42166)
@@ -79,6 +79,6 @@
         NULL; // File with raw image
 
-    psArray *pixels = NULL, *radec = NULL, *streaks = NULL, *clusters = NULL; // Array of coordinate vectors
-    psArray *radecOut = NULL, *streaksOut = NULL, *clustersOut = NULL;        // Output for sky coordinates
+    psArray *pixels = NULL, *radec = NULL, *fpas = NULL, *streaks = NULL, *clusters = NULL; // Array of coordinate vectors
+    psArray *radecOut = NULL,*fpaOut = NULL, *streaksOut = NULL, *clustersOut = NULL;        // Output for sky coordinates
     if (data->pixelsName) {
         pixels = psVectorsReadFromFile(data->pixelsName, "%f %f");
@@ -107,4 +107,25 @@
         psVectorInit(radecOut->data[1], NAN);
         psVectorInit(radecOut->data[2], NAN);
+    }
+
+    if (data->fpaName) {
+        fpas = psVectorsReadFromFile(data->fpaName, "%f %f");
+        if (!fpas || fpas->n != 2) {
+            psError(psErrorCodeLast(), false, "Unable to read FPA coordinates");
+            return false;
+        }
+        psVector *fpa_x = fpas->data[0];  // FPA x coordinates
+        long num = fpa_x->n;               // Number of coordinates
+        fpaOut = psArrayAlloc(6);
+        fpaOut->data[0] = psArrayAlloc(num);
+        fpaOut->data[1] = psVectorAlloc(num, PS_TYPE_F32);
+        fpaOut->data[2] = psVectorAlloc(num, PS_TYPE_F32);
+        fpaOut->data[3] = psArrayAlloc(num);
+        fpaOut->data[4] = psVectorAlloc(num, PS_TYPE_F32);
+        fpaOut->data[5] = psVectorAlloc(num, PS_TYPE_F32);
+        psVectorInit(fpaOut->data[1], NAN);
+        psVectorInit(fpaOut->data[2], NAN);
+        psVectorInit(fpaOut->data[4], NAN);
+        psVectorInit(fpaOut->data[5], NAN);
     }
 
@@ -394,4 +415,59 @@
 		yTP->data.F32[i] = src.tp.y;
             }
+        }
+
+        if (fpas) {
+            psVector *fpa_x = fpas->data[0], *fpa_y = fpas->data[1]; // FPA coordinates
+            long num = fpa_x->n;                                     // Number of coordinates
+
+            int numCols = psMetadataLookupS32(NULL, hdu->header, "IMNAXIS1"); // Number of columns
+            int numRows = psMetadataLookupS32(NULL, hdu->header, "IMNAXIS2"); // Number of rows
+            if (numCols <= 0 || numRows <= 0) {
+                psError(psErrorCodeLast(), false, "Unable to read size of chip.");
+                return false;
+            }
+
+            psArray *chipPix = fpaOut->data[0]; // Chip for pixels
+            psVector *xPix = fpaOut->data[1];   // x coordinate for pixels
+            psVector *yPix = fpaOut->data[2];   // y coordinate for pixels
+            psArray *cellPix = fpaOut->data[3]; // Cell for pixels
+            psVector *xCell = fpaOut->data[4];   // x coordinate for cell
+            psVector *yCell = fpaOut->data[5];   // y coordinate for cell
+
+            psPlane *pix = psPlaneAlloc();   // Pixel coordinates on chip
+            psPlane *fp = psPlaneAlloc();    // Focal plane coordinates
+
+            for (long i = 0; i < num; i++) {
+                float x, y;             // Pixel coordinates
+                fp->x = fpa_x->data.F32[i];
+                fp->y = fpa_y->data.F32[i];
+
+                psPlaneTransformApply(pix, chip->fromFPA, fp);
+                psTrace("ppCoord",2,"fpa2pix tr1: %f %f\n",pix->x,pix->y);
+
+                x = pix->x;
+                y = pix->y;
+
+                if ((x < 0 || x > numCols || y < 0 || y > numRows)) {
+                    // Not on this chip
+                    continue;
+                }
+
+                chipPix->data[i] = psStringCopy(chipName);
+                xPix->data.F32[i] = x;
+                yPix->data.F32[i] = y;
+
+                if (rawChip) {
+                    psString cellName = NULL; // Name of cell
+                    coordChip2Cell(&cellName, &x, &y, x, y, cellNames, cellBounds,
+                                   cellX0, cellY0, cellParityX, cellParityY, cellBinX, cellBinY);
+                    cellPix->data[i] = cellName;
+                    xCell->data.F32[i] = x;
+                    yCell->data.F32[i] = y;
+                }
+
+            }
+            psFree(pix);
+            psFree(fp);
         }
 
@@ -556,4 +632,39 @@
     }
 
+    if (fpaOut) {
+        psArray *chipPix = fpaOut->data[0]; // Chip for pixels
+        psVector *xPix = fpaOut->data[1];   // x coordinate for pixels
+        psVector *yPix = fpaOut->data[2];   // y coordinate for pixels
+        psArray *cellPix = fpaOut->data[3]; // Cell for pixels
+        psVector *xCell = fpaOut->data[4];   // x coordinate for pixels
+        psVector *yCell = fpaOut->data[5];   // y coordinate for pixels
+        psVector *fpa_x = fpas->data[0];        // FPA x coordinate
+        psVector *fpa_y = fpas->data[1];       // FPA y coordinate
+
+        for (long i = 0; i < chipPix->n; i++) {
+            const char *chipName = chipPix->data[i]; // Name of chip
+            const char *cellName = cellPix->data[i]; // Name of cell, or NULL
+            if (!data->all && (!isfinite(xPix->data.F32[i]) || !isfinite(yPix->data.F32[i]) ||
+                               !chipName || (rawFile && !cellName))) {
+                continue;
+            }
+            if (!rawFile && data->ds9) {
+                // Region file is only appropriate if we're not mapping all the way back to cell coordinates
+                fprintf(data->ds9, "image;circle(%f,%f,%f) # color=%s\n",
+                        xPix->data.F32[i], yPix->data.F32[i], data->ds9radius, data->ds9color);
+            } else if (rawFile) {
+                fprintf(stdout, "%.3f %.3f --> %.3f %.3f %s %.3f %.3f %s\n",
+                        fpa_x->data.F32[i], fpa_y->data.F32[i], xPix->data.F32[i], yPix->data.F32[i],
+                        chipName ? chipName : "UNKNOWN",
+                        xCell->data.F32[i], yCell->data.F32[i],
+                        cellName ? cellName : "UNKNOWN");
+            } else {
+                fprintf(stdout, "%.3f %.3f --> %.3f %.3f %s\n",
+                        fpa_x->data.F32[i], fpa_y->data.F32[i], xPix->data.F32[i], yPix->data.F32[i],
+                        chipName ? chipName : "UNKNOWN");
+            }
+        }
+    }
+
     if (streaksOut) {
         psArray *chipPix1 = streaksOut->data[0]; // Chip for point 1
Index: /branches/eam_branches/ipp-20220316/psModules/src/objects/pmPSF_IO.c
===================================================================
--- /branches/eam_branches/ipp-20220316/psModules/src/objects/pmPSF_IO.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/psModules/src/objects/pmPSF_IO.c	(revision 42166)
@@ -903,4 +903,9 @@
     // load the PSF model parameters from the FITS table
     char *modelName = psMetadataLookupStr (&status, header, "PSF_NAME");
+    if (!modelName) {
+        psError(PS_ERR_UNKNOWN, true, "missing model name in psf file %s", file->filename);
+        return false;
+    }
+
     options->type = pmModelClassGetType (modelName);
     if (options->type == -1) {
@@ -939,4 +944,9 @@
     // check the number of expected parameters
     int nPar = psMetadataLookupS32 (&status, header, "PSF_NPAR");
+    if (!status) {
+	psError(PS_ERR_UNKNOWN, true, "PSF file %s missing PSF_NPAR value", file->filename);
+	return false;
+    }
+
     if (nPar != pmModelClassParameterCount (psf->type))
         psAbort("mismatch model par count");
@@ -1051,5 +1061,13 @@
 
         int xBin  = psMetadataLookupS32 (&status, header, "XBIN");
+	if (!status) {
+            psError(psErrorCodeLast(), false, "XBIN not set in PSF residual image header.");
+            return false;
+        }
         int yBin  = psMetadataLookupS32 (&status, header, "YBIN");
+	if (!status) {
+            psError(psErrorCodeLast(), false, "YBIN not set in PSF residual image header.");
+            return false;
+        }
 
         int xSize = Nx / xBin;
Index: /branches/eam_branches/ipp-20220316/pswarp/src/pswarpMapGrid.c
===================================================================
--- /branches/eam_branches/ipp-20220316/pswarp/src/pswarpMapGrid.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/pswarp/src/pswarpMapGrid.c	(revision 42166)
@@ -38,4 +38,5 @@
     int nYpts = (int)(Ny / nYpix) + 1;
 
+    psLogMsg("pswarp", 3, "in grid sampling\n");
     // create the grid of maps
     pswarpMapGrid *grid = pswarpMapGridAlloc (nXpts, nYpts);
@@ -49,5 +50,5 @@
     }
 
-    if (0) {
+    //if (0) {
 	// test the transformation sky<->chip for chip in smf:
 	if (fout == NULL) { fout = fopen ("map.grid.txt", "w");	}
@@ -88,4 +89,8 @@
 		fprintf (fout, "%f %f < %f %f < %f %f \n", TP1->x, TP1->y, FP1->x, FP1->y, CH1->x, CH1->y);
 
+                psLogMsg("pswarp", 3, "testing grid sampling\n");
+                psLogMsg("pswarp", 3, "%f %f > %f %f > %f %f > %f %f | ", CH0->x, CH0->y, FP0->x, FP0->y, TP0->x, TP0->y, sky->r*180/M_PI, sky->d*180/M_PI);
+                psLogMsg("pswarp", 3, "%f %f < %f %f < %f %f \n", TP1->x, TP1->y, FP1->x, FP1->y, CH1->x, CH1->y);
+
 	    }
 	}
@@ -101,5 +106,5 @@
 
 	psFree (sky);
-    }
+    //}
 
     grid->nXpix = nXpix;
Index: /branches/eam_branches/ipp-20220316/pswarp/src/pswarpTransformReadout.c
===================================================================
--- /branches/eam_branches/ipp-20220316/pswarp/src/pswarpTransformReadout.c	(revision 42165)
+++ /branches/eam_branches/ipp-20220316/pswarp/src/pswarpTransformReadout.c	(revision 42166)
@@ -104,4 +104,5 @@
     // pswarpMapGridFromImage builds a set of locally-linear maps which convert the
     // output coordinates to input coordinates
+    psLogMsg("pswarp", 3, "going into MapGrid \n");
     pswarpMapGrid *grid = pswarpMapGridFromImage(input, output, nGridX, nGridY);
     
