Index: /branches/eam_branches/20091113/psModules/src/astrom/pmAstrometryObjects.c
===================================================================
--- /branches/eam_branches/20091113/psModules/src/astrom/pmAstrometryObjects.c	(revision 26196)
+++ /branches/eam_branches/20091113/psModules/src/astrom/pmAstrometryObjects.c	(revision 26197)
@@ -973,2 +973,91 @@
 */
 
+/*****************************************************************************/
+static void pmAstromMatchInfoFree (pmAstromMatchInfo *info)
+{
+    if (info == NULL) return;
+    return;
+}
+
+
+/*****************************************************************************/
+pmAstromMatchInfo *pmAstromMatchInfoAlloc()
+{
+    pmAstromMatchInfo *info = psAlloc (sizeof(pmAstromMatchInfo));
+    psMemSetDeallocator(info, (psFreeFunc) pmAstromMatchInfoFree);
+
+    info->match = NULL;
+    info->radius = NAN;
+
+    return (info);
+}
+
+// generate a unique set of matches (choose closest match)
+psArray *pmAstromRadiusMatchUniq (psArray *rawstars, psArray *refstars, psArray *matches) {
+
+    // I have the matches between the refstars and the rawstars.  
+    // For each refstar, find the single match which has the smallest radius and reject
+    // all others.  
+
+    // create an array of refstars->n arrays, each containing all of the matches for the
+    // given refstar.  
+
+    psArray *refstarMatches = psArrayAlloc (refstars->n);
+
+    for (int i = 0; i < matches->n; i++) {
+
+	pmAstromMatch *match = matches->data[i];
+	
+	// accumulate this refstar match on the array for this refstar (create if needed)
+	psArray *refSet = refstarMatches->data[match->ref];
+	if (!refSet) {
+	    refstarMatches->data[match->ref] = psArrayAllocEmpty (8);
+	    refSet = refstarMatches->data[match->ref];
+	}
+
+	pmAstromMatchInfo *matchInfo = pmAstromMatchInfoAlloc();
+
+	pmAstromObj *refStar = refstars->data[match->ref];
+	pmAstromObj *rawStar = rawstars->data[match->raw];
+	
+	matchInfo->match = match; // reference to the match of interest
+	matchInfo->radius = hypot (refStar->FP->x - rawStar->FP->x, refStar->FP->y - rawStar->FP->y);
+
+	psArrayAdd (refSet, 8, matchInfo); // matchInfo->match is just a reference
+	psFree (matchInfo);
+    }
+
+    // we now have a set of matches for each refstar and their distances; create a new set
+    // keeping only the closest entry for each match
+
+    psArray *unique = psArrayAllocEmpty (PS_MAX(16, matches->n / 2));
+    for (int i = 0; i < refstars->n; i++) {
+
+	psArray *refSet = refstarMatches->data[i];
+	if (!refSet) continue;
+	if (refSet->n == 0) continue; // not certain how this can happen...
+
+	if (refSet->n == 1) {
+	    pmAstromMatchInfo *matchInfo = refSet->data[0];
+	    psArrayAdd (unique, 32, matchInfo->match);
+	    continue;
+	}
+
+	pmAstromMatchInfo *matchInfo = refSet->data[0];
+	float minRadius = matchInfo->radius;
+	pmAstromMatch *minMatch = matchInfo->match;
+	for (int j = 1; j < refSet->n; j++) {
+	    pmAstromMatchInfo *matchInfo = refSet->data[j];
+	    if (minRadius < matchInfo->radius) continue;
+	    minMatch = matchInfo->match;
+	    minRadius = matchInfo->radius;
+	}
+	
+	psArrayAdd (unique, 32, minMatch); // minMatch is just a reference to a match on matches,
+    }
+
+    psLogMsg ("psastro", 3, "generate unique matches to reference stars: %ld matches -> %ld matches\n", matches->n, unique->n);
+    psFree (refstarMatches);
+
+    return unique;
+}
Index: /branches/eam_branches/20091113/psModules/src/astrom/pmAstrometryObjects.h
===================================================================
--- /branches/eam_branches/20091113/psModules/src/astrom/pmAstrometryObjects.h	(revision 26196)
+++ /branches/eam_branches/20091113/psModules/src/astrom/pmAstrometryObjects.h	(revision 26197)
@@ -54,8 +54,19 @@
 typedef struct
 {
-    int raw;                             ///< What is this?
-    int ref;                             ///< What is this?
+    int raw;                             ///< reference to the rawstar entry
+    int ref;                             ///< reference to the refstar entry
 }
 pmAstromMatch;
+
+
+/*
+ * The pmAstromMatchInfo structure is used to generate a unique set of matches
+ */
+typedef struct
+{
+    pmAstromMatch *match;		///< reference to the match
+    float radius;			///< distance between the object
+}
+pmAstromMatchInfo;
 
 
@@ -121,4 +132,5 @@
 );
 
+psArray *pmAstromRadiusMatchUniq (psArray *refstars, psArray *rawstars, psArray *matches);
 
 pmAstromStats *pmAstromStatsAlloc(void);
Index: /branches/eam_branches/20091113/psastro/doc/outline.txt
===================================================================
--- /branches/eam_branches/20091113/psastro/doc/outline.txt	(revision 26197)
+++ /branches/eam_branches/20091113/psastro/doc/outline.txt	(revision 26197)
@@ -0,0 +1,45 @@
+
+psastro outline:
+
+  psastroParseCamera
+  psastroDataLoad
+    psastroConvertReadout (save PSASTRO.RAWSTARS & PSASTRO.RAWSTARS.SUBSET on readout->analysis)
+  psastroAnalysis
+    psastroUseModel
+    psastroAstromGuess (plots PSASTRO.RAWSTARS)
+    psastroLoadRefstars (loads full reference star set)
+    psastroChooseRefstars (save PSASTRO.REFSTARS & PSASTRO.REFSTARS.SUBSET on readout->analysis)
+      psastroRefstarSubset (adjust PSASTRO.REFSTARS.SUBSET on readout->analysis)
+    psastroChooseGlintStars (uses full reference star set)
+    psastroChipAstrom (uses PSASTRO.REFSTARS.SUBSET & PSASTRO.RAWSTARS.SUBSET)
+      psastroOneChipGrid
+      psastroOneChipFit
+    psastroMosaicAstrom
+      psastroFixChips
+      psastroFixChipsTest
+      psastroMosaicFit
+        psastroMosaicSetMatch (uses PSASTRO.REFSTARS.SUBSET & PSASTRO.RAWSTARS.SUBSET)
+        psastroMosaicCommonScale
+        psastroMosaicDistortion
+        psastroMosaicChipAstrom
+    psastroZeroPoint
+    psastroAstromGuessCheck
+    psastroMaskUpdates
+  psastroDataSave
+
+psastroExtract outline:
+  psastroExtractParseCamera
+  psastroExtractDataLoad
+  psastroExtractAnalysis
+    psastroLoadRefstars (loads full reference star set)
+    psastroChooseRefstars (save PSASTRO.REFSTARS & PSASTRO.REFSTARS.SUBSET on readout->analysis)
+      psastroRefstarSubset (adjust PSASTRO.REFSTARS.SUBSET on readout->analysis)
+    psastroExtractGhosts
+    psastroExtractStars
+  psastroDataSave
+
+
+psastroModel outline:
+
+psastroModelFit outline:
+
Index: /branches/eam_branches/20091113/psastro/src/psastroMosaicSetMatch.c
===================================================================
--- /branches/eam_branches/20091113/psastro/src/psastroMosaicSetMatch.c	(revision 26196)
+++ /branches/eam_branches/20091113/psastro/src/psastroMosaicSetMatch.c	(revision 26197)
@@ -26,7 +26,10 @@
     double RADIUS = psMetadataLookupF32 (&status, recipe, radiusWord);
     if (!status) {
-        psError(PS_ERR_IO, false, "Failed to lookup matching radius: %s", radiusWord);
-        psFree (view);
-        return false;
+        psAbort("Failed to lookup matching radius: %s", radiusWord);
+    }
+
+    int uniqIter = psMetadataLookupS32 (&status, recipe, "PSASTRO.MOSAIC.UNIQ.ITER");
+    if (!status) {
+        psAbort("Failed to lookup matching PSASTRO.MOSAIC.UNIQ.ITER");
     }
 
@@ -69,4 +72,14 @@
                 psTrace ("psastro", 4, "Matched %ld refstars\n", matches->n);
 
+		if (iteration >= uniqIter) {
+		    psArray *unique = pmAstromRadiusMatchUniq (rawstars, refstars, matches);
+		    if (!unique) {
+			psLogMsg ("psastro", 3, "failed to generate a uniq set of matched sources\n");
+			return false;
+		    }
+		    psFree (matches);
+		    matches = unique;
+		}
+
                 pmAstromVisualPlotMosaicMatches(rawstars, refstars, matches, iteration, recipe);
 
Index: /branches/eam_branches/20091113/psastro/src/psastroOneChipFit.c
===================================================================
--- /branches/eam_branches/20091113/psastro/src/psastroOneChipFit.c	(revision 26196)
+++ /branches/eam_branches/20091113/psastro/src/psastroOneChipFit.c	(revision 26197)
@@ -66,8 +66,11 @@
 
 	if (iter >= uniqIter) {
-	  if (!pmAstromRadiusMatchUniq (rawstars, refstars, match)) {
-            psLogMsg ("psastro", 3, "failed to generate a uniq find radius-matched sources\n");
-            return false;
-	  }
+	    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;
 	}
 
