Index: /trunk/psastro/src/psastroMosaicAstrom.c
===================================================================
--- /trunk/psastro/src/psastroMosaicAstrom.c	(revision 19309)
+++ /trunk/psastro/src/psastroMosaicAstrom.c	(revision 19310)
@@ -1,4 +1,6 @@
 # include "psastroInternal.h"
 # define NONLIN_TOL 0.001 /* tolerance in pixels */
+
+bool psastroMosaicFit (pmFPA *fpa, psMetadata *recipe, int pass);
 
 // XXX require this fpa to have multiple chip extensions and a PHU?
@@ -34,92 +36,20 @@
     # endif
 
-    // given the existing per-chip astrometry, determine matches between raw and ref stars
-    // is this needed? yes, if we didn't do SingleChip astrometry first
-    if (!psastroMosaicSetMatch (fpa, recipe, 0)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.0.dat"); }
-
-    // fitted chips will follow the local plate-scale, hiding the distortion
-    // modify the chip->toFPA scaling to match knowledge about pixel scale,
-    // then recalculate raw and ref positions
-    if (!psastroMosaicCommonScale (fpa, recipe)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to set a common scale for the chips");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.1.dat"); }
-
-    // fit the distortion by fitting its gradient
-    // apply the new distortion terms up and down
-    // refit the per-chip terms with linear fits only
-    if (!psastroMosaicGradients (fpa, recipe)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure mosaic gradients");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.2.dat"); }
-
-    // measure the astrometry for the chips under the distortion term
-    if (!psastroMosaicChipAstrom (fpa, recipe, 0)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.3.dat"); }
-
-    // do a second pass on the distortion with improved chip positions and rotations
-    // first, re-perform the match with a slightly tighter circle
-    if (!psastroMosaicSetMatch (fpa, recipe, 1)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic (2nd pass)");
-	return false;
-    }
-    if (!psastroMosaicCommonScale (fpa, recipe)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to set a common scale for the chips (2nd pass)");
-	return false;
-    }
-    if (!psastroMosaicGradients (fpa, recipe)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure mosaic gradients (2nd pass)");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.4.dat"); }
-
-    if (!psastroMosaicChipAstrom (fpa, recipe, 1)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode (2nd pass)");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.5.dat"); }
-
-    // do a third pass on the distortion with improved chip positions and rotations
-    // first, re-perform the match with a slightly tighter circle
-    if (!psastroMosaicSetMatch (fpa, recipe, 2)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic (3rd pass)");
-	return false;
-    }
-    if (!psastroMosaicCommonScale (fpa, recipe)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to set a common scale for the chips (3rd pass)");
-	return false;
-    }
-    if (!psastroMosaicGradients (fpa, recipe)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure mosaic gradients (3rd pass)");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.6.dat"); }
-
-    if (!psastroMosaicChipAstrom (fpa, recipe, 2)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode (3rd pass)");
-	return false;
-    }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.7.dat"); }
+    if (!psastroMosaicFit (fpa, recipe, 0)) return false;
+    if (!psastroMosaicFit (fpa, recipe, 1)) return false;
+    if (!psastroMosaicFit (fpa, recipe, 2)) return false;
+    if (!psastroMosaicFit (fpa, recipe, 3)) return false;
 
     // now fit the chips under the common distortion with higher-order terms
     // first, re-perform the match with a slightly tighter circle
-    if (!psastroMosaicSetMatch (fpa, recipe, 3)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic (3rd pass)");
+    if (!psastroMosaicSetMatch (fpa, recipe, 4)) {
+	psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic (4th pass)");
 	return false;
     }
-    if (!psastroMosaicChipAstrom (fpa, recipe, 3)) {
-	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode (3rd pass)");
+    if (!psastroMosaicChipAstrom (fpa, recipe, 4)) {
+	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode (4th pass)");
 	return false;
     }
-    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.8.dat"); }
+    if (psTraceGetLevel("psastro.dump") > 0) { psastroDumpMatches (fpa, "match.10.dat"); }
 
     // save WCS and analysis metadata in update header.
@@ -150,2 +80,51 @@
  * sky (ra, dec)
  */
+
+// 1: match 4,5
+// 2: match 6,7
+// 3: match 8,9
+bool psastroMosaicFit (pmFPA *fpa, psMetadata *recipe, int pass) {
+
+    char filename[16];
+
+    // given the existing per-chip astrometry, determine matches between raw and ref stars
+    // is this needed? yes, if we didn't do SingleChip astrometry first
+    if (!psastroMosaicSetMatch (fpa, recipe, pass)) {
+	psError(PSASTRO_ERR_UNKNOWN, false, "failed to match raw and ref stars for mosaic (pass %d)", pass);
+	return false;
+    }
+
+    if ((pass == 0) && (psTraceGetLevel("psastro.dump.psastroMosaicAstrom") > 0)) { psastroDumpMatches (fpa, "match.0.dat"); }
+
+    // fitted chips will follow the local plate-scale, hiding the distortion
+    // modify the chip->toFPA scaling to match knowledge about pixel scale,
+    // then recalculate raw and ref positions
+    if (!psastroMosaicCommonScale (fpa, recipe)) {
+	psError(PSASTRO_ERR_UNKNOWN, false, "failed to set a common scale for the chips (pass %d)", pass);
+	return false;
+    }
+
+    if ((pass == 0) && (psTraceGetLevel("psastro.dump.psastroMosaicAstrom") > 0)) { psastroDumpMatches (fpa, "match.1.dat"); }
+
+    // fit the distortion by fitting its gradient
+    // apply the new distortion terms up and down
+    // refit the per-chip terms with linear fits only
+    if (!psastroMosaicDistortion (fpa, recipe)) {
+	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure mosaic gradients (pass %d)", pass);
+	return false;
+    }
+
+    snprintf (filename, 16, "match.%d.dat", 2*pass + 2);
+    if (psTraceGetLevel("psastro.dump.psastroMosaicAstrom") > 0) { psastroDumpMatches (fpa, filename); }
+    
+    // measure the astrometry for the chips under the distortion term
+    if (!psastroMosaicChipAstrom (fpa, recipe, pass)) {
+	psError(PSASTRO_ERR_UNKNOWN, false, "failed to measure chip astrometry in mosaic mode (pass %d)", pass);
+	return false;
+    }
+
+    snprintf (filename, 16, "match.%d.dat", 2*pass + 3);
+    if (psTraceGetLevel("psastro.dump.psastroMosaicAstrom") > 0) { psastroDumpMatches (fpa, filename); }
+
+    return true;
+}
