Index: /trunk/psastro/Makefile
===================================================================
--- /trunk/psastro/Makefile	(revision 7153)
+++ /trunk/psastro/Makefile	(revision 7154)
@@ -21,16 +21,22 @@
 
 PSASTRO = \
-$(SRC)/psastro.$(ARCH).o           \
-$(SRC)/psastroArguments.$(ARCH).o  \
-$(SRC)/psastroParseCamera.$(ARCH).o\
-$(SRC)/psastroDataLoad.$(ARCH).o   \
-$(SRC)/psastroDataSave.$(ARCH).o   \
-$(SRC)/psastroAstromGuess.$(ARCH).o\
-$(SRC)/psastroLoadReferences.$(ARCH).o\
-$(SRC)/psastroConvert.$(ARCH).o	   \
-$(SRC)/psastroChipAstrom.$(ARCH).o\
-$(SRC)/psastroOneChip.$(ARCH).o\
-$(SRC)/psastroUtils.$(ARCH).o\
-$(SRC)/psastroTestFuncs.$(ARCH).o\
+$(SRC)/psastro.$(ARCH).o               	    \
+$(SRC)/psastroArguments.$(ARCH).o      	    \
+$(SRC)/psastroParseCamera.$(ARCH).o    	    \
+$(SRC)/psastroDataLoad.$(ARCH).o       	    \
+$(SRC)/psastroDataSave.$(ARCH).o       	    \
+$(SRC)/psastroAstromGuess.$(ARCH).o    	    \
+$(SRC)/psastroLoadReferences.$(ARCH).o 	    \
+$(SRC)/psastroConvert.$(ARCH).o	       	    \
+$(SRC)/psastroChipAstrom.$(ARCH).o     	    \
+$(SRC)/psastroOneChip.$(ARCH).o	       	    \
+$(SRC)/psastroUtils.$(ARCH).o	       	    \
+$(SRC)/psastroTestFuncs.$(ARCH).o      	    \
+$(SRC)/psastroMosaicAstrom.$(ARCH).o        \
+$(SRC)/psastroMosaicGetGrads.$(ARCH).o      \
+$(SRC)/psastroMosaicGetRefstars.$(ARCH).o   \
+$(SRC)/psastroMosaicChipAstrom.$(ARCH).o    \
+$(SRC)/psastroMosaicSetAstrom.$(ARCH).o	    \
+$(SRC)/psastroMosaicSetMatch.$(ARCH).o	    \
 $(SRC)/psastroWCS.$(ARCH).o	   
 
Index: unk/psastro/src/psModUtils.c
===================================================================
--- /trunk/psastro/src/psModUtils.c	(revision 7153)
+++ 	(revision )
@@ -1,146 +1,0 @@
-# include "psastro.h"
-
-psPlane *psCoordReadoutToCell (psPlane *cellpix, psPlane *readpix, pmReadout *readout) {
-
-    if (cellpix == NULL) {
-	cellpix = psPlaneAlloc ();
-    }
-
-    cellpix->x = readpix->x*readout->colBins + readout->col0;
-    cellpix->y = readpix->y*readout->rowBins + readout->row0;
-
-    return (cellpix);
-}
-
-psPlane *psCoordCellToReadout (psPlane *readpix, psPlane *cellpix, pmReadout *readout) {
-
-    if (readpix == NULL) {
-	readpix = psPlaneAlloc ();
-    }
-
-    readpix->x = (cellpix->x - readout->col0) / readout->colBins;
-    readpix->y = (cellpix->y - readout->row0) / readout->rowBins;
-
-    return (readpix);
-}
-
-psPlane* psCoordChipToCell_EAM(psPlane* cellCoord,
-			       const psPlane* chipCoord,
-			       const pmCell* cell)
-{
-    PS_ASSERT_PTR_NON_NULL(chipCoord, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell, NULL);
-    PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
-
-    // XXX EAM : why was this being done?
-    // pmCell *tmpCell = pmCellInChip(chipCoord, cell->parent);
-    PS_ASSERT_PTR_NON_NULL(cell->toChip, NULL);
-    psPlaneTransform *tmpChipToCell = p_psPlaneTransformLinearInvert(cell->toChip);
-    PS_ASSERT_PTR_NON_NULL(tmpChipToCell, NULL);
-    cellCoord = psPlaneTransformApply(cellCoord, tmpChipToCell, chipCoord);
-    psFree(tmpChipToCell);
-    return(cellCoord);
-}
-
-bool psastroProjectFPA (pmFPA *fpa, char *starlist, bool toSky) {
-
-    bool status;
-
-    for (int i = 0; i < fpa->chips->n; i++) {
-	pmChip *chip = fpa->chips->data[i];
-	for (int j = 0; j < chip->cells->n; j++) {
-	    pmCell *cell = chip->cells->data[j];
-	    for (int k = 0; k < cell->readouts->n; k++) {
-		pmReadout *readout = cell->readouts->data[k];
-		psArray *stars = psMetadataLookupPtr (&status, readout->analysis, starlist);
-		if (toSky) {
-		    psastroProjectRawstars (stars, readout);
-		} else {
-		    psastroProjectRefstars (stars, readout);
-		}
-	    }
-	}
-    }
-    return true;
-}
- 
-bool psastroProjectRawstars (psArray *stars, pmReadout *readout) {
-
-    pmCell *cell = readout->parent;
-    pmChip *chip = cell->parent;
-    pmFPA  *fpa  = chip->parent;
-
-    for (int i = 0; i < stars->n; i++) {
-	pmAstromObj *star = stars->data[i];
-	psCoordReadoutToCell (&star->cell, &star->pix, readout);
-	psCoordCellToChip (&star->chip, &star->cell, cell);
-	psCoordChipToFPA (&star->FP, &star->chip, chip);
-	psCoordFPAToTP (&star->TP, &star->FP, 0.0, 0.0, fpa);
-	psCoordTPToSky (&star->sky, &star->TP, fpa->projection);
-    }
-    return true;
-}
- 
-bool psastroProjectRefstars (psArray *stars, pmReadout *readout) {
-
-    pmCell *cell = readout->parent;
-    pmChip *chip = cell->parent;
-    pmFPA  *fpa  = chip->parent;
-
-    for (int i = 0; i < stars->n; i++) {
-	pmAstromObj *star = stars->data[i];
-	psCoordSkyToTP (&star->TP, &star->sky, fpa->projection);
-	psCoordTPToFPA (&star->FP, &star->TP, 0.0, 0.0, fpa);
-	psCoordFPAToChip (&star->chip, &star->FP, chip);
-	psCoordChipToCell_EAM (&star->cell, &star->chip, cell);
-	psCoordCellToReadout (&star->pix, &star->cell, readout);
-    }
-    return true;
-}
- 
-pmFPA *pmFPACopyAstrom (pmFPA *inFPA) {
-
-    pmFPA *fpa = pmFPAAlloc (NULL, NULL);
-
-    // copy FPA astrometry data
-    fpa->toSky   = psProjectionCopy (inFPA->toSky);
-    fpa->toTPA   = psPlaneDistortCopy (inFPA->toTPA);
-    fpa->fromTPA = psPlaneDistortCopy (inFPA->fromTPA);
-
-    psArrayRealloc (fpa->chips, inFPA->chips->n);
-    for (int i = 0; i < inFPA->chips->n; i++) {
-	pmChip *inChip = inFPA->chips->data[i];
-	pmChip *chip = pmChipAlloc (fpa);
-
-	// copy Chip astrometry data
-	chip->toFPA = psPlaneTransformCopy (inChip->toFPA);
-	chip->fromFPA = psPlaneTransformCopy (inChip->fromFPA);
-
-	psArrayRealloc (chip->cells, inChip->cells->n);
-	for (int j = 0; j < inChip->cells->n; j++) {
-	    pmCell *inCell = inChip->cells->data[j];
-	    pmCell *cell = pmCellAlloc (chip);
-
-	    // cell.header is a view on inCell.header
-	    cell->header = psMemCopy (inCell->header);
-
-	    // copy Cell astrometry data 
-	    cell->toChip = psPlaneTransformCopy (inCell->toChip);
-
-	    psArrayRealloc (cell->readouts, inCell->readouts->n);
-	    for (int k = 0; k < inCell->readouts->n; k++) {
-		pmReadout *inReadout = inCell->readouts->data[k];
-		pmReadout *readout = pmReadoutAlloc (cell);
-
-		// copy Readout data
-		*readout = *inReadout;
-
-		cell->readouts->data[k] = readout;
-	    }
-	    chip->cells->data[j] = cell;
-	}
-	fpa->chips->data[i] = chip;
-    }
-    return (fpa);
-}
-
Index: /trunk/psastro/src/psastro.c
===================================================================
--- /trunk/psastro/src/psastro.c	(revision 7153)
+++ /trunk/psastro/src/psastro.c	(revision 7154)
@@ -27,4 +27,5 @@
 
     psastroChipAstrom (config, refs);
+    psastroMosaicAstrom (config, refs);
 
     # if 0
Index: /trunk/psastro/src/psastro.h
===================================================================
--- /trunk/psastro/src/psastro.h	(revision 7153)
+++ /trunk/psastro/src/psastro.h	(revision 7154)
@@ -38,2 +38,9 @@
 bool              psastroWriteTransform (psPlaneTransform *map);
 
+// mosaic fitting functions
+psArray *psastroMosaicGetGrads (pmFPA *fpa, psMetadata *recipe);
+bool psastroMosaicAstrom (pmConfig *config, psArray *refs);
+bool psastroMosaicGetRefstars (pmFPA *fpa, psArray *refs, psMetadata *recipe);
+bool psastroMosaicChipAstrom (pmFPA *fpa, psMetadata *recipe);
+bool psastroMosaicSetMatch (pmFPA *fpa, psMetadata *recipe);
+bool psastroMosaicSetAstrom (pmFPA *fpa);
Index: /trunk/psastro/src/psastroMosaicAstrom.c
===================================================================
--- /trunk/psastro/src/psastroMosaicAstrom.c	(revision 7154)
+++ /trunk/psastro/src/psastroMosaicAstrom.c	(revision 7154)
@@ -0,0 +1,64 @@
+# include "psastro.h"
+
+bool psastroMosaicAstrom (pmConfig *config, psArray *refs) {
+
+    bool status;
+    psArray *grads = NULL;
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, "PSASTRO");
+    if (!recipe) {
+	psErrorStackPrint(stderr, "Can't find PSASTRO recipe!\n");
+	exit(EXIT_FAILURE);
+    }
+
+    // select the input data sources
+    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
+    if (!input) {
+	psErrorStackPrint(stderr, "Can't find input data!\n");
+	exit(EXIT_FAILURE);
+    }
+
+    double plateScale = psMetadataLookupF32 (&status, recipe, "PSASTRO.PLATE.SCALE");
+    if (!status) plateScale = 1.0;
+
+    pmFPA *fpa = input->fpa;
+
+    psastroMosaicGetRefstars (fpa, refs, recipe);
+    psastroMosaicSetMatch (fpa, recipe);
+
+    grads = psastroMosaicGetGrads (fpa, recipe);
+
+    // fit the measured gradients with the telescope distortion model (3rd order polynomial)
+    pmAstromFitDistortion (fpa, grads, recipe);
+
+    // apply the new distortion terms up and down
+    // re-perform the match with a slightly tighter circle
+    psastroMosaicSetAstrom (fpa);
+    psastroMosaicSetMatch (fpa, recipe);
+
+    // fit the chips with linear fits
+    // re-match
+    psastroMosaicChipAstrom (fpa, recipe);
+    psastroMosaicSetMatch (fpa, recipe);
+
+    // re-fit the chips with higher-order fits
+    // re-match
+    psastroMosaicChipAstrom (fpa, recipe);
+    psastroMosaicSetMatch (fpa, recipe);
+
+    // re-fit the chips with higher-order fits
+    psastroMosaicChipAstrom (fpa, recipe);
+    // psastroMosaicHeaders (fpa);
+
+    return true;
+}
+
+/* coordinate frame hierachy
+   pixels (on a given readout)
+   cell
+   chip
+   FP (focal plane)
+   TP (tangent plane)
+   sky (ra, dec)
+*/
Index: /trunk/psastro/src/psastroMosaicChipAstrom.c
===================================================================
--- /trunk/psastro/src/psastroMosaicChipAstrom.c	(revision 7154)
+++ /trunk/psastro/src/psastroMosaicChipAstrom.c	(revision 7154)
@@ -0,0 +1,39 @@
+# include "psastro.h"
+
+bool psastroMosaicChipAstrom (pmFPA *fpa, psMetadata *recipe) {
+
+    pmChip *chip = NULL;
+    pmCell *cell = NULL;
+    pmReadout *readout = NULL;
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    // this loop selects the matched stars for all chips
+    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
+        psTrace (__func__, 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	
+	while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
+            psTrace (__func__, 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+
+	    // process each of the readouts
+	    // XXX there can only be one readout per chip, right?
+	    while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
+		if (! readout->data_exists) { continue; }
+
+		// select the raw objects for this readout
+		psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.OBJECTS");
+		if (rawstars == NULL) { continue; }
+
+		psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
+		if (refstars == NULL) { continue; }
+
+		psArray *match = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.MATCH");
+		if (match == NULL) { continue; }
+
+		pmAstromMatchFit (chip->toFPA, rawstars, refstars, match, recipe);
+	    }
+	}
+    }
+    return true;
+}
Index: /trunk/psastro/src/psastroMosaicGetGrads.c
===================================================================
--- /trunk/psastro/src/psastroMosaicGetGrads.c	(revision 7154)
+++ /trunk/psastro/src/psastroMosaicGetGrads.c	(revision 7154)
@@ -0,0 +1,44 @@
+# include "psastro.h"
+
+psArray *psastroMosaicGetGrads (pmFPA *fpa, psMetadata *recipe) {
+
+    pmChip *chip = NULL;
+    pmCell *cell = NULL;
+    pmReadout *readout = NULL;
+    psArray *grads = NULL;
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    // this loop selects the matched stars for all chips
+    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
+        psTrace (__func__, 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	
+	while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
+            psTrace (__func__, 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+
+	    // process each of the readouts
+	    // XXX there can only be one readout per chip, right?
+	    while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
+		if (! readout->data_exists) { continue; }
+
+		// select the raw objects for this readout
+		psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.OBJECTS");
+		if (rawstars == NULL) { continue; }
+
+		// select the raw objects for this readout
+		psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
+		if (refstars == NULL) { continue; }
+
+		psArray *match = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.MATCH");
+		if (match == NULL) { continue; }
+
+		// measure the local gradients for this set of stars
+		// XXX update the function prototype to accept an incoming gradient structure to which the new elements are added
+		grads = pmAstromMeasureGradients (grads, rawstars, refstars, match, recipe);
+	    }
+	}
+    }
+    return (grads);
+}
Index: /trunk/psastro/src/psastroMosaicGetRefstars.c
===================================================================
--- /trunk/psastro/src/psastroMosaicGetRefstars.c	(revision 7154)
+++ /trunk/psastro/src/psastroMosaicGetRefstars.c	(revision 7154)
@@ -0,0 +1,54 @@
+# include "psastro.h"
+
+bool psastroMosaicGetRefstars (pmFPA *fpa, psArray *refs, psMetadata *recipe) {
+
+    pmChip *chip = NULL;
+    pmCell *cell = NULL;
+    pmReadout *readout = NULL;
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    // this loop selects the matched stars for all chips
+    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
+        psTrace (__func__, 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	
+	while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
+            psTrace (__func__, 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+
+	    // process each of the readouts
+	    // XXX there can only be one readout per chip, right?
+	    while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
+		if (! readout->data_exists) { continue; }
+
+		// select the raw objects for this readout
+		psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.OBJECTS");
+		if (rawstars == NULL) { continue; }
+
+		// the refstars is a subset within range of this chip
+		psArray *refstars = psArrayAlloc (100);
+
+		// select the reference objects within range of this readout
+		// project the reference objects to this chip
+		for (int i = 0; i < refs->n; i++) {
+		    pmAstromObj *ref = refs->data[i];
+	
+		    p_psProject (ref->TP, ref->sky, fpa->projection);
+		    psPlaneDistortApply (ref->FP, fpa->fromTangentPlane, ref->TP, 0.0, 0.0);
+		    psPlaneTransformApply (ref->chip, chip->fromFPA, ref->FP);
+
+		    // XXX what is the X,Y range of the selected chip?
+		    // XXX for the moment, force these to be good for Megacam
+		    if (ref->chip->x <  -10) continue;
+		    if (ref->chip->x > 2060) continue;
+		    if (ref->chip->y <  -10) continue;
+		    if (ref->chip->y > 4610) continue;
+		    
+		    psArrayAdd (refstars, 100, ref);
+		}
+		psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.REFSTARS", PS_DATA_ARRAY, "astrometry matches", refstars);
+	    }
+	}
+    }
+    return true;
+}
Index: /trunk/psastro/src/psastroMosaicSetAstrom.c
===================================================================
--- /trunk/psastro/src/psastroMosaicSetAstrom.c	(revision 7154)
+++ /trunk/psastro/src/psastroMosaicSetAstrom.c	(revision 7154)
@@ -0,0 +1,50 @@
+# include "psastro.h"
+
+bool psastroMosaicSetAstrom (pmFPA *fpa) {
+
+    pmChip *chip = NULL;
+    pmCell *cell = NULL;
+    pmReadout *readout = NULL;
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    // this loop selects the matched stars for all chips
+    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
+        psTrace (__func__, 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	
+	while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
+            psTrace (__func__, 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+
+	    // process each of the readouts
+	    // XXX there can only be one readout per chip, right?
+	    while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
+		if (! readout->data_exists) { continue; }
+
+		// select the raw objects for this readout
+		psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.OBJECTS");
+		if (rawstars == NULL) { continue; }
+
+		for (int i = 0; i < rawstars->n; i++) {
+		    pmAstromObj *raw = rawstars->data[i];
+	
+		    psPlaneTransformApply (raw->FP, chip->toFPA, raw->chip);
+		    psPlaneDistortApply (raw->TP, fpa->toTangentPlane, raw->FP, 0.0, 0.0);
+		    p_psDeproject (raw->sky, raw->TP, fpa->projection);
+		}
+
+		psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
+		if (refstars == NULL) { continue; }
+
+		for (int i = 0; i < refstars->n; i++) {
+		    pmAstromObj *ref = refstars->data[i];
+	
+		    p_psProject (ref->TP, ref->sky, fpa->projection);
+		    psPlaneDistortApply (ref->FP, fpa->fromTangentPlane, ref->TP, 0.0, 0.0);
+		    psPlaneTransformApply (ref->chip, chip->fromFPA, ref->FP);
+		}
+	    }
+	}
+    }
+    return true;
+}
Index: /trunk/psastro/src/psastroMosaicSetMatch.c
===================================================================
--- /trunk/psastro/src/psastroMosaicSetMatch.c	(revision 7154)
+++ /trunk/psastro/src/psastroMosaicSetMatch.c	(revision 7154)
@@ -0,0 +1,42 @@
+# include "psastro.h"
+
+bool psastroMosaicSetMatch (pmFPA *fpa, psMetadata *recipe) {
+
+    pmChip *chip = NULL;
+    pmCell *cell = NULL;
+    pmReadout *readout = NULL;
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    // this loop selects the matched stars for all chips
+    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
+        psTrace (__func__, 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	
+	while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
+            psTrace (__func__, 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+
+	    // process each of the readouts
+	    // XXX there can only be one readout per chip, right?
+	    while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
+		if (! readout->data_exists) { continue; }
+
+		// select the raw objects for this readout
+		psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.OBJECTS");
+		if (rawstars == NULL) { continue; }
+
+		// select the raw objects for this readout
+		psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
+		if (refstars == NULL) { continue; }
+
+		// use small radius to match stars (assume starting astrometry is good)
+		// XXX should this take a (double radius)?
+		psArray *matches = pmAstromRadiusMatch (rawstars, refstars, recipe);
+
+		// XXX drop the old one
+		psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.MATCH", PS_DATA_ARRAY, "astrometry matches", matches);
+	    }
+	}
+    }
+    return true;
+}
