Index: /branches/eam_branches/ipp-dev-20210817/ippconfig/gpc1/psastro.config
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/ippconfig/gpc1/psastro.config	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/ippconfig/gpc1/psastro.config	(revision 41877)
@@ -82,10 +82,17 @@
 PSASTRO.MOSAIC.UNIQ.ITER      S32      3  # for iterations >= N, require a single match per reference
 
-PSASTRO.MOSAIC.MAX.ERROR.N0 F32    0.00 # max allow error for valid solution (arcsec)
-PSASTRO.MOSAIC.MAX.ERROR.N1 F32    0.00 # max allow error for valid solution (arcsec)
-PSASTRO.MOSAIC.MAX.ERROR.N2 F32    0.00 # max allow error for valid solution (arcsec)
-PSASTRO.MOSAIC.MAX.ERROR.N3 F32    0.00 # max allow error for valid solution (arcsec)
-PSASTRO.MOSAIC.MAX.ERROR.N4 F32    0.00 # max allow error for valid solution (arcsec)
-PSASTRO.MOSAIC.MAX.ERROR.N5 F32    0.30 # max allow error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N0 F32    0.00 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N1 F32    0.00 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N2 F32    0.00 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N3 F32    0.00 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N4 F32    0.00 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N5 F32    0.30 # max allowed error for valid solution (arcsec)
+
+PSASTRO.MOSAIC.MAX.STDEV.N0 F32    0.00 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N1 F32    0.00 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N2 F32    0.00 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N3 F32    0.00 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N4 F32    0.00 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N5 F32    0.00 # max allowed stdev for valid solution (arcsec)
 
 # mosaic radius match in pixels (do these make sense?)
Index: /branches/eam_branches/ipp-dev-20210817/ippconfig/recipes/psastro.config
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/ippconfig/recipes/psastro.config	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/ippconfig/recipes/psastro.config	(revision 41877)
@@ -91,5 +91,6 @@
 PSASTRO.CHIP.NSIGMA    F32      3  # fit clipping sigmas
 
-PSASTRO.MAX.ERROR      F32      1.5 # max allow error for valid solution (UNITS?)
+PSASTRO.MAX.ERROR      F32      1.5 # max allowed error for valid solution (arcsec)
+PSASTRO.MAX.STDEV      F32      1.0 # max allowed stdev for valid solution (arcsec)
 PSASTRO.MIN.NSTAR      S32      3   # min fitted stars in solution
 PSASTRO.MAX.NSTAR      S32      300   # max fitted stars in solution
@@ -135,10 +136,17 @@
 PSASTRO.MOSAIC.CHIP.NSIGMA    F32      3  # fit clipping sigmas
 
-PSASTRO.MOSAIC.MAX.ERROR.N0   F32      1.5 # max allow error for valid solution (UNITS?)
-PSASTRO.MOSAIC.MAX.ERROR.N1   F32      1.5 # max allow error for valid solution (UNITS?)
-PSASTRO.MOSAIC.MAX.ERROR.N2   F32      1.5 # max allow error for valid solution (UNITS?)
-PSASTRO.MOSAIC.MAX.ERROR.N3   F32      1.5 # max allow error for valid solution (UNITS?)
-PSASTRO.MOSAIC.MAX.ERROR.N4   F32      1.5 # max allow error for valid solution (UNITS?)
-PSASTRO.MOSAIC.MAX.ERROR.N5   F32      1.5 # max allow error for valid solution (UNITS?)
+PSASTRO.MOSAIC.MAX.ERROR.N0   F32      1.5 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N1   F32      1.5 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N2   F32      1.5 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N3   F32      1.5 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N4   F32      1.5 # max allowed error for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.ERROR.N5   F32      1.5 # max allowed error for valid solution (arcsec)
+
+PSASTRO.MOSAIC.MAX.STDEV.N0   F32      1.5 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N1   F32      1.5 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N2   F32      1.5 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N3   F32      1.5 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N4   F32      1.5 # max allowed stdev for valid solution (arcsec)
+PSASTRO.MOSAIC.MAX.STDEV.N5   F32      1.5 # max allowed stdev for valid solution (arcsec)
 
 # need at least this fraction of chips to pass for exposure to be considered acceptable
Index: /branches/eam_branches/ipp-dev-20210817/ippconfig/recipes/pswarp.config
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/ippconfig/recipes/pswarp.config	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/ippconfig/recipes/pswarp.config	(revision 41877)
@@ -14,5 +14,6 @@
 APPLY.PIXELNAN		BOOL	FALSE		# Apply NAN'ing of pixels underneath masks
 
-MAX.CERROR		F32	0.1		# Maximum allowed CERROR value (astrometric error in arcsec)
+MAX.CERROR		F32	0.30	        # Maximum allowed CERROR value (astrometric error in arcsec)
+MAX.CERSTD		F32	0.15		# Maximum allowed CERSTD value (astrometric error in arcsec)
 
 NO.COMPRESS             BOOL    FALSE           # turn off image compression (if enabled)
Index: /branches/eam_branches/ipp-dev-20210817/ppViz/src/ppCoord/ppCoordLoop.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/ppViz/src/ppCoord/ppCoordLoop.c	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/ppViz/src/ppCoord/ppCoordLoop.c	(revision 41877)
@@ -228,4 +228,6 @@
             psWarning("More than one cell present for chip %d", view->chip);
         }
+
+	fprintf (stderr, "chip: %s\n", chipName);
 
         // read WCS data from the corresponding header
@@ -368,4 +370,5 @@
 		src.sky.d = dec->data.F64[i];
                 coordSky2Chip(&src, data->radians, astromFile->fpa, chip);
+		fprintf (stderr, "x,y: %.2f %.2f\n", src.pix.x, src.pix.y);
                 if ((src.pix.x < 0 || src.pix.x > numCols || src.pix.y < 0 || src.pix.y > numRows)) {
                     // Not on this chip
Index: /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroAstromGuess.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroAstromGuess.c	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroAstromGuess.c	(revision 41877)
@@ -342,7 +342,10 @@
         if (!updates) goto skip_chip;
 
+	// in psastroOneChipFit & psastroMosaicOneCihp, astrometry failures are marked with NASTRO = 0
+	// these should be ignored when checking the overall solution
         int nAstro = psMetadataLookupS32 (&status, updates, "NASTRO");
         if (!nAstro) goto skip_chip;
 
+	// it is not clear when astError = 0.0
         float astError = psMetadataLookupF32 (&status, updates, "CERROR");
         if (fabs(astError) < 1e-6) goto skip_chip;
Index: /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroMetadataStats.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroMetadataStats.c	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroMetadataStats.c	(revision 41877)
@@ -37,4 +37,5 @@
         psMetadataItemSupplement(&status, stats, header, "ZPT_ERR");
         psMetadataItemSupplement(&status, stats, header, "CERROR");
+        psMetadataItemSupplement(&status, stats, header, "CERSTD");
         psMetadataItemSupplement(&status, stats, header, "NASTRO");
         psMetadataItemSupplement(&status, stats, header, "AST_R0");
Index: /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroMosaicOneChip.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroMosaicOneChip.c	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroMosaicOneChip.c	(revision 41877)
@@ -44,7 +44,10 @@
 
     // allowed limits for valid solutions
+    // CERROR is currently tested during the iterations, but not CERSTD
     snprintf (errorWord, 64, "PSASTRO.MOSAIC.MAX.ERROR.N%d", iteration);
-    REQUIRED_RECIPE_VALUE (float maxError, errorWord, F32, "failed to find single-chip max allowed error\n");
-    REQUIRED_RECIPE_VALUE (int minNstar, "PSASTRO.MOSAIC.MIN.NSTAR", S32, "failed to find single-chip min allowed stars\n");
+    snprintf (stdevWord, 64, "PSASTRO.MOSAIC.MAX.STDEV.N%d", iteration);
+    REQUIRED_RECIPE_VALUE (float maxError,                  errorWord, F32, "failed to find single-chip max allowed error\n");
+    REQUIRED_RECIPE_VALUE (float maxStdev,                  stdevWord, F32, "failed to find single-chip max allowed stdev\n");
+    REQUIRED_RECIPE_VALUE (int   minNstar, "PSASTRO.MOSAIC.MIN.NSTAR", S32, "failed to find single-chip min allowed stars\n");
 
     // set the order of the per-chip fit (higher order only if iteration > 0)
@@ -146,9 +149,12 @@
     bool validSolution = true;
 
-    // XXX should these result in errors or be handled another way?
-    // psLogMsg ("psastro", PS_LOG_INFO, "astrometry solution: error: %f arcsec, Nstars: %d", astError, astNstar);
+    // We have options to exclude chips on the basis of NASTRO, CERROR, CERSTD
     psLogMsg ("psastro", PS_LOG_INFO, "astrometry solution: error: %f arcsec, Nstars: %d, stdev: %f arcsec", astError, astNstar, astStdev);
     if ((maxError > 0) && (astError > maxError)) {
         psLogMsg("psastro", PS_LOG_INFO, "residual error is too large, failed to find a solution: %f > %f", astError, maxError);
+        validSolution = false;
+    }
+    if ((maxStdev > 0) && (astStdev > maxStdev)) {
+        psLogMsg("psastro", PS_LOG_INFO, "residual stdev is too large, failed to find a solution: %f > %f", astStdev, maxStdev);
         validSolution = false;
     }
@@ -158,5 +164,5 @@
     }
 
-    // DVO expects NASTRO = 0 if we fail to find a solution
+    // DVO expects NASTRO = 0 if we fail to find a solution, NASTUSED is the true number
     psMetadataAddF32 (updates, PS_LIST_TAIL, "PERROR",   PS_META_REPLACE, "astrometry error (pixels)", pixError);
     psMetadataAddF32 (updates, PS_LIST_TAIL, "CERROR",   PS_META_REPLACE, "astrometry error (arcsec)", astError);
@@ -165,7 +171,9 @@
         psMetadataAddF32 (updates, PS_LIST_TAIL, "CPRECISE", PS_META_REPLACE, "astrometry precision (arcsec)", astError/sqrt(astNstar));
         psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO",   PS_META_REPLACE, "number of astrometry stars", astNstar);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     } else {
         psMetadataAddF32 (updates, PS_LIST_TAIL, "CPRECISE", PS_META_REPLACE, "astrometry precision (arcsec)", 0.0);
         psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO",   PS_META_REPLACE, "number of astrometry stars", 0);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     }
     psMetadataAddF32 (updates, PS_LIST_TAIL, "EQUINOX",  PS_META_REPLACE, "", 2000.0); // XXX this is bogus: should be defined based on equinox of refstars
Index: /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroOneChipFit.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroOneChipFit.c	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/psastro/src/psastroOneChipFit.c	(revision 41877)
@@ -40,5 +40,6 @@
     // allowed limits for valid solutions
     REQUIRED_RECIPE_VALUE (float maxError, "PSASTRO.MAX.ERROR", F32);
-    REQUIRED_RECIPE_VALUE (int minNstar, "PSASTRO.MIN.NSTAR", S32);
+    REQUIRED_RECIPE_VALUE (float maxStdev, "PSASTRO.MAX.STDEV", F32);
+    REQUIRED_RECIPE_VALUE (int   minNstar, "PSASTRO.MIN.NSTAR", S32);
 
     psArray *match = NULL;
@@ -208,4 +209,8 @@
         validSolution = false;
     }
+    if (astStdev > maxStdev) {
+	psLogMsg("psastro", PS_LOG_INFO, "residual stdev is too large, failed to find a solution: %f > %f", astStdev, maxStdev);
+        validSolution = false;
+    }
     if (astNstar < minNstar) {
         psLogMsg("psastro", PS_LOG_INFO, "solution uses too few stars: %d < %d", astNstar, minNstar);
@@ -220,6 +225,8 @@
         psMetadataAddF32 (updates, PS_LIST_TAIL, "CPRECISE", PS_META_REPLACE, "astrometry precision (arcsec)", astError/sqrt(astNstar));
         psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO",   PS_META_REPLACE, "number of astrometry stars", astNstar);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     } else {
 	psastroChipFailureHeader (updates);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     }
     psMetadataAddF32 (updates, PS_LIST_TAIL, "EQUINOX",  PS_META_REPLACE, "equinox of ref catalog", 2000.0); // XXX this is bogus: should be defined based on equinox of refstars
Index: /branches/eam_branches/ipp-dev-20210817/pswarp/src/pswarpLoadAstrometry.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/pswarp/src/pswarpLoadAstrometry.c	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/pswarp/src/pswarpLoadAstrometry.c	(revision 41877)
@@ -94,16 +94,7 @@
         }
     }
+
     // apply the bilevel astrometry elements to the target
     if (bilevelAstrometry) {
-      int additional_orders = 4;
-      bool status = false;
-      int config_additional_orders = psMetadataLookupS32(&status,config->arguments,"ADDITIONAL_WCS_ORDERS");
-      if (status) {
-	additional_orders = config_additional_orders;
-      }
-      psMetadataAddS32(astrom->fpa->analysis,PS_LIST_TAIL, "ADDITIONAL_WCS_ORDERS", PS_META_REPLACE,
-		       "Additional orders for bilevel fit.", additional_orders);
-      
-	
 	if (!pmAstromReadBilevelMosaic(astrom->fpa, phu->header)) {
 	    psError(psErrorCodeLast(), false, "Unable to read bilevel mosaic astrometry for skycell.");
Index: /branches/eam_branches/ipp-dev-20210817/pswarp/src/pswarpOptions.c
===================================================================
--- /branches/eam_branches/ipp-dev-20210817/pswarp/src/pswarpOptions.c	(revision 41876)
+++ /branches/eam_branches/ipp-dev-20210817/pswarp/src/pswarpOptions.c	(revision 41877)
@@ -104,6 +104,6 @@
       config_additional_orders = 0;
     }
-    
-
+    pmAstrometryGetExtraOrders(config_additional_orders);
+    // This is the number of orders that should be added to all non-linear inverse transformations
     
     // Set recipe values in the recipe (since we've possibly altered some)
Index: /branches/eam_branches/psModules.20211028/src/astrom/pmAstrometryWCS.c
===================================================================
--- /branches/eam_branches/psModules.20211028/src/astrom/pmAstrometryWCS.c	(revision 41876)
+++ /branches/eam_branches/psModules.20211028/src/astrom/pmAstrometryWCS.c	(revision 41877)
@@ -705,9 +705,4 @@
     psFree (fpa->fromTPA);
     int additional_orders = pmAstrometryGetExtraOrders();  // This is the number of orders that should be added.
-    bool status = false;
-    int config_additional_orders = psMetadataLookupS32(&status,fpa->analysis, "ADDITIONAL_WCS_ORDERS");
-    if (status) { // If this keyword is found, then use that number of orders instead
-      additional_orders = config_additional_orders; 
-    }
     fpa->fromTPA = psPlaneTransformInvert(NULL, fpa->toTPA, region, 50, additional_orders);
     return true;
