Index: branches/tap_branches/psastro/src/psastroOneChipFit.c
===================================================================
--- branches/tap_branches/psastro/src/psastroOneChipFit.c	(revision 25900)
+++ branches/tap_branches/psastro/src/psastroOneChipFit.c	(revision 27838)
@@ -18,5 +18,5 @@
    psAbort ("Failed to find %s in recipe", NAME); }
 
-bool psastroOneChipFit (pmFPA *fpa, pmChip *chip, psArray *refstars, psArray *rawstars, psMetadata *recipe, psMetadata *updates) {
+bool psastroOneChipFit (pmFPA *fpa, pmChip *chip, pmReadout *readout, psArray *refstars, psArray *rawstars, psMetadata *recipe, psMetadata *updates) {
 
     bool status;
@@ -27,4 +27,7 @@
     // run the match/fit sequence NITER times
     REQUIRED_RECIPE_VALUE (int nIter, "PSASTRO.MATCH.FIT.NITER", S32);
+
+    // for iterations >= uniqIter, require a single match per reference
+    REQUIRED_RECIPE_VALUE (int uniqIter, "PSASTRO.MATCH.UNIQ.ITER", S32);
 
     // correct radius to FP units (physical pixel scale in microns per pixel)
@@ -61,4 +64,14 @@
             return false;
         }
+
+	if (iter >= uniqIter) {
+	    psArray *unique = pmAstromRadiusMatchUniq (rawstars, refstars, match);
+	    if (!unique) {
+		psLogMsg ("psastro", 3, "failed to generate a uniq set of matched sources\n");
+		return false;
+	    }
+	    psFree (match);
+	    match = unique;
+	}
 
         // modify the order to correspond to the actual number of matched stars:
@@ -101,5 +114,5 @@
         }
 
-        // XXX allow statitic to be set by the user
+        // XXX allow statistic to be set by the user
         // fitStats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
         fitStats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
@@ -117,10 +130,14 @@
 
         // determine fromFPA transformation and apply new transformation to raw & ref stars
-        psastroUpdateChipToFPA (fpa, chip, rawstars, refstars);
+	// this applies the transformation to all stars (including subset)
+        psastroUpdateChipToFPA (fpa, chip); // updates PSASTRO.RAWSTARS and PSASTRO.REFSTARS
 
         // toSky converts from FPA & TPA units (microns) to sky units (radians)
         float plateScale = 0.5*(fpa->toSky->Xs + fpa->toSky->Ys)*3600.0*PM_DEG_RAD;
-        // float astError = 0.5*(results->xStats->clippedStdev + results->yStats->clippedStdev) * plateScale;
-        float astError = 0.5*(results->xStats->robustStdev + results->yStats->robustStdev) * plateScale;
+
+	float rawXstdev = psStatsGetValue (results->xStats, psStatsStdevOption(results->xStats->options));
+	float rawYstdev = psStatsGetValue (results->yStats, psStatsStdevOption(results->yStats->options));
+
+        float astError = 0.5*(rawXstdev + rawYstdev) * plateScale;
         int astNstar = results->yStats->clippedNvalues;
         psLogMsg ("psastro", PS_LOG_INFO, "pass %d, error: %f arcsec, Nstars: %d", iter, astError, astNstar);
@@ -136,11 +153,14 @@
     float plateScale = 0.5*(fpa->toSky->Xs + fpa->toSky->Ys)*3600.0*PM_DEG_RAD;
 
+    float rawXstdev = psStatsGetValue (results->xStats, psStatsStdevOption(results->xStats->options));
+    float rawYstdev = psStatsGetValue (results->yStats, psStatsStdevOption(results->yStats->options));
+
     // pixError is the average 1D scatter in pixels ('results' are in FPA units = microns)
-    // float pixError = 0.5*(results->xStats->clippedStdev + results->yStats->clippedStdev) / pixelScale;
-    float pixError = 0.5*(results->xStats->robustStdev + results->yStats->robustStdev) / pixelScale;
+    float pixError = 0.5*(rawXstdev + rawYstdev) / pixelScale;
 
     // astError is the average 1D scatter in arcsec ('results' are in FPA units = microns)
-    // float astError = 0.5*(results->xStats->clippedStdev + results->yStats->clippedStdev) * plateScale;
-    float astError = 0.5*(results->xStats->robustStdev + results->yStats->robustStdev) * plateScale;
+    float astError = 0.5*(rawXstdev + rawYstdev) * plateScale;
+
+    // x and y are forced to use the same subset of values:
     int astNstar = results->yStats->clippedNvalues;
 
@@ -170,6 +190,12 @@
     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
 
-    // XXX drop from here : determine fromFPA transformation and apply new transformation to raw & ref stars
-    // psastroUpdateChipToFPA (fpa, chip, rawstars, refstars);
+    // additional error measurements:
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_CDX",   PS_META_REPLACE, "chip astrometry X stdev (arcsec)", rawXstdev * plateScale);
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_CSX",   PS_META_REPLACE, "chip astrometry X systematic err (arcsec)", results->dXsys * plateScale);
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_CRX",   PS_META_REPLACE, "chip astrometry X 10-90 percentile (arcsec)", results->dXrange * plateScale);
+
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_CDY",   PS_META_REPLACE, "chip astrometry Y stdev (arcsec)", rawYstdev * plateScale);
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_CSY",   PS_META_REPLACE, "chip astrometry Y systematic err (arcsec)", results->dYsys * plateScale);
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "AST_CRY",   PS_META_REPLACE, "chip astrometry Y 10-90 percentile (arcsec)", results->dYrange * plateScale);
 
     // XXX check if we correctly applied the new transformation:
@@ -186,7 +212,11 @@
     }
 
+    // save the match table for zero points and other tests
+    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.MATCH", PS_DATA_ARRAY | PS_META_REPLACE, "astrometry matches", match);
+
     psFree (match);
     psFree (results);
     psFree (fitStats);
+
     return validSolution;
 }
