Index: trunk/psastro/src/psastro.h
===================================================================
--- trunk/psastro/src/psastro.h	(revision 41498)
+++ trunk/psastro/src/psastro.h	(revision 41499)
@@ -108,5 +108,5 @@
 bool              psastroMosaicCorrectDistortion (pmFPA *fpa, psPlaneTransform *TPtoFP);
 bool              psastroMosaicCommonScale (pmFPA *fpa, psMetadata *recipe);
-bool              psastroMosaicAstrom (pmConfig *config);
+bool              psastroMosaicAstrom (pmConfig *config, psMetadata *stats);
 bool              psastroMosaicChipAstrom (pmFPA *fpa, psMetadata *recipe, int iteration);
 bool              psastroMosaicSetMatch (pmFPA *fpa, psMetadata *recipe, int iteration);
Index: trunk/psastro/src/psastroAnalysis.c
===================================================================
--- trunk/psastro/src/psastroAnalysis.c	(revision 41498)
+++ trunk/psastro/src/psastroAnalysis.c	(revision 41499)
@@ -139,5 +139,5 @@
 
     if (mosastro) {
-        if (!psastroMosaicAstrom (config)) {
+	if (!psastroMosaicAstrom (config, stats)) {
             // This is likely a data quality issue
             psWarning("Failed mosaic astrometry --- suspect bad data quality");
Index: trunk/psastro/src/psastroMosaicAstrom.c
===================================================================
--- trunk/psastro/src/psastroMosaicAstrom.c	(revision 41498)
+++ trunk/psastro/src/psastroMosaicAstrom.c	(revision 41499)
@@ -14,9 +14,10 @@
 # define NONLIN_TOL 0.001 /* tolerance in pixels */
 
-bool psastroMosaicFit (pmFPA *fpa, psMetadata *recipe, const char *rootname, int pass);
+bool psastroMosaicFit (pmFPA *fpa, psMetadata *stats, psMetadata *recipe, const char *rootname, int pass);
 bool psastroProjectionRefit (pmFPA *fpa, psMetadata *recipe);
 
 // XXX require this fpa to have multiple chip extensions and a PHU?
-bool psastroMosaicAstrom (pmConfig *config) {
+// EAM 2021.02.18 : addings 'stats' to set bad quality as appropriate 
+bool psastroMosaicAstrom (pmConfig *config, psMetadata *stats) {
 
     bool status;
@@ -25,4 +26,5 @@
     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSASTRO_RECIPE);
     if (!recipe) {
+	// recipe or programming error
         psError(PSASTRO_ERR_CONFIG, false, "Can't find PSASTRO recipe!\n");
         return false;
@@ -32,4 +34,5 @@
     pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
     if (!input) {
+	// recipe or programming error
         psError(PSASTRO_ERR_CONFIG, false, "Can't find input data!\n");
         return false;
@@ -53,5 +56,6 @@
     // this should be in a loop with nIter =
     for (int iter = 0; fitMosaicDistortion && (iter < nIter); iter++) {
-        if (!psastroMosaicFit (fpa, recipe, outroot, iter)) return false;
+	// NOTE: data quality (psastroMosaicDistortion) or recipe / config error
+        if (!psastroMosaicFit (fpa, stats, recipe, outroot, iter)) return false;
     }
 
@@ -59,8 +63,10 @@
     // first, re-perform the match with a slightly tighter circle
     if (!psastroMosaicSetMatch (fpa, recipe, nIter)) {
+      // recipe or alloc error
       psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic (pass %d)", nIter);
       return false;
     }
-    if (!psastroMosaicChipAstrom (fpa, recipe, nIter)) {
+    if (!psastroMosaicChipAstrom (fpa, stats, recipe, nIter)) {
+      // this cannot actually return false
       psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode (pass %d)", nIter);
       return false;
@@ -83,6 +89,10 @@
     }
     if (!pmAstromWriteBilevelMosaic (updates, fpa, NONLIN_TOL)) {
-        psError(psErrorCodeLast(), false, "Failed to save header terms");
-        return false;
+	// error here is a data quality problem (and too bad to write smf)
+	psWarning ("Failed to save header terms");
+	if (stats && psMetadataLookupS32(NULL, stats, "QUALITY") == 0) {
+	    psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE, "Mosaic astrometry failed", PSASTRO_ERR_DATA);
+	}
+	return false;
     }
 
@@ -109,5 +119,5 @@
 // 2: match 6,7
 // 3: match 8,9
-bool psastroMosaicFit (pmFPA *fpa, psMetadata *recipe, const char *rootname, int pass) {
+bool psastroMosaicFit (pmFPA *fpa, psMetadata *stats, psMetadata *recipe, const char *rootname, int pass) {
 
     char filename[256];
@@ -117,4 +127,5 @@
     if (!psastroMosaicSetMatch (fpa, recipe, pass)) {
         psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic (pass %d)", pass);
+	// this can only fail on alloc failure in pmAstromRadiusMatchUniq
         return false;
     }
@@ -129,4 +140,5 @@
     // then recalculate raw and ref positions
     if (!psastroMosaicCommonScale (fpa, recipe)) {
+	// this can only return false if the recipe value is not set
         psError(PSASTRO_ERR_UNKNOWN, false, "failed to set a common scale for the chips (pass %d)", pass);
         return false;
@@ -141,6 +153,10 @@
     // apply the new distortion terms up and down
     // refit the per-chip terms with linear fits only
+    // NOTE: failure here is a data quality problem
     if (!psastroMosaicDistortion (fpa, recipe, pass)) {
-        psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure mosaic gradients (pass %d)", pass);
+	psWarning ("failed to measure mosaic gradients (pass %d)", pass);
+	if (stats && psMetadataLookupS32(NULL, stats, "QUALITY") == 0) {
+	    psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE, "Mosaic astrometry failed", PSASTRO_ERR_DATA);
+	}
         return false;
     }
@@ -150,5 +166,6 @@
 
     // measure the astrometry for the chips under the distortion term
-    if (!psastroMosaicChipAstrom (fpa, recipe, pass)) {
+    if (!psastroMosaicChipAstrom (fpa, stats, recipe, pass)) {
+	// this cannot actually return false
         psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode (pass %d)", pass);
         return false;
Index: trunk/psastro/src/psastroMosaicChipAstrom.c
===================================================================
--- trunk/psastro/src/psastroMosaicChipAstrom.c	(revision 41498)
+++ trunk/psastro/src/psastroMosaicChipAstrom.c	(revision 41499)
@@ -14,5 +14,5 @@
 # define NONLIN_TOL 0.001 ///< tolerance in pixels
 
-bool psastroMosaicChipAstrom (pmFPA *fpa, psMetadata *recipe, int iteration) {
+bool psastroMosaicChipAstrom (pmFPA *fpa, psMetadata *stats, psMetadata *recipe, int iteration) {
 
     bool status;
@@ -83,5 +83,8 @@
     if (fGood < minGoodChipFraction) {
       psWarning ("Too few good chips (%d of %d = %.2f), setting bad quality for this exposure\n", nChipGood, (nChipGood + nChipFail), fGood);
-      // return false;
+      // NOTE: set bad data quality here
+      if (stats && psMetadataLookupS32(NULL, stats, "QUALITY") == 0) {
+	  psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE, "Mosaic astrometry failed", PSASTRO_ERR_DATA);
+      }
     }
 
Index: trunk/psastro/src/psastroMosaicSetMatch.c
===================================================================
--- trunk/psastro/src/psastroMosaicSetMatch.c	(revision 41498)
+++ trunk/psastro/src/psastroMosaicSetMatch.c	(revision 41499)
@@ -76,5 +76,5 @@
 		    if (!unique) {
 			psLogMsg ("psastro", 3, "failed to generate a uniq set of matched sources\n");
-			return false;
+			return false; // this can only happen if alloc fails, not a data quality problem
 		    }
 		    psFree (matches);
