Index: trunk/psastro/src/Makefile.am
===================================================================
--- trunk/psastro/src/Makefile.am	(revision 41858)
+++ trunk/psastro/src/Makefile.am	(revision 41895)
@@ -10,5 +10,5 @@
 libpsastro_la_LDFLAGS = $(PSASTRO_LIBS) $(PPSTATS_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 
-bin_PROGRAMS = psastro psastroExtract psastroModel psastroModelFit gpcModel
+bin_PROGRAMS = psastro psastroExtract psastroModel psastroModelFit gpcModel psastroTIO
 
 psastro_CFLAGS = $(PSASTRO_CFLAGS) $(PPSTATS_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
@@ -31,4 +31,8 @@
 gpcModel_LDFLAGS = $(PSASTRO_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
 gpcModel_LDADD = libpsastro.la
+
+psastroTIO_CFLAGS = $(PSASTRO_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+psastroTIO_LDFLAGS = $(PSASTRO_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
+psastroTIO_LDADD = libpsastro.la
 
 psastro_SOURCES = \
@@ -62,4 +66,12 @@
 	psastroModelAdjust.c        \
 	psastroModelDataSave.c      \
+	psastroCleanup.c
+
+psastroTIO_SOURCES = \
+	psastroTIO.c		    \
+        psastroTIOArguments.c	    \
+	psastroTIOParseCamera.c   \
+	psastroTIODataLoad.c      \
+	psastroTIODataSave.c      \
 	psastroCleanup.c
 
Index: trunk/psastro/src/psastroAstromGuess.c
===================================================================
--- trunk/psastro/src/psastroAstromGuess.c	(revision 41858)
+++ trunk/psastro/src/psastroAstromGuess.c	(revision 41895)
@@ -342,7 +342,10 @@
         if (!updates) goto skip_chip;
 
+	// in psastroOneChipFit & psastroMosaicOneCihp, astrometry failures are marked with NASTRO = 0
+	// these should be ignored when checking the overall solution
         int nAstro = psMetadataLookupS32 (&status, updates, "NASTRO");
         if (!nAstro) goto skip_chip;
 
+	// it is not clear when astError = 0.0
         float astError = psMetadataLookupF32 (&status, updates, "CERROR");
         if (fabs(astError) < 1e-6) goto skip_chip;
@@ -397,5 +400,5 @@
     }
 
-    psPlaneTransform *map = psPlaneTransformAlloc (1, 1);
+    psPlaneTransform *map = psPlaneTransformAlloc (1, 1, PS_POLYNOMIAL_ORD);
     map->x->coeffMask[1][1] = PS_POLY_MASK_SET;
     map->y->coeffMask[1][1] = PS_POLY_MASK_SET;
Index: trunk/psastro/src/psastroConvert.c
===================================================================
--- trunk/psastro/src/psastroConvert.c	(revision 41858)
+++ trunk/psastro/src/psastroConvert.c	(revision 41895)
@@ -172,4 +172,5 @@
     calStars->n = j;
     psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.CALSTARS", PS_DATA_ARRAY, "astrometry objects for masking", calStars);
+    psFree (calStars);
 
     psFree (index);
Index: trunk/psastro/src/psastroFixChips.c
===================================================================
--- trunk/psastro/src/psastroFixChips.c	(revision 41858)
+++ trunk/psastro/src/psastroFixChips.c	(revision 41895)
@@ -170,5 +170,5 @@
     if (DEBUG) fclose (f);
 
-    psPlaneTransform *map = psPlaneTransformAlloc (1, 1);
+    psPlaneTransform *map = psPlaneTransformAlloc (1, 1, PS_POLYNOMIAL_ORD);
 
     psVector *mask = psVectorAlloc (nPts, PS_TYPE_VECTOR_MASK);
@@ -289,5 +289,5 @@
         // apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter
         // XXX this only works if toTPA is at most a linear transformation
-        psPlaneTransform *toFPA = psPlaneTransformAlloc(refChip->toFPA->x->nX, refChip->toFPA->x->nY);
+        psPlaneTransform *toFPA = psPlaneTransformAlloc(refChip->toFPA->x->nX, refChip->toFPA->x->nY, PS_POLYNOMIAL_ORD);
         for (int i = 0; i <= refChip->toFPA->x->nX; i++) {
             for (int j = 0; j <= refChip->toFPA->x->nY; j++) {
Index: trunk/psastro/src/psastroMetadataStats.c
===================================================================
--- trunk/psastro/src/psastroMetadataStats.c	(revision 41858)
+++ trunk/psastro/src/psastroMetadataStats.c	(revision 41895)
@@ -37,4 +37,5 @@
         psMetadataItemSupplement(&status, stats, header, "ZPT_ERR");
         psMetadataItemSupplement(&status, stats, header, "CERROR");
+        psMetadataItemSupplement(&status, stats, header, "CERSTD");
         psMetadataItemSupplement(&status, stats, header, "NASTRO");
         psMetadataItemSupplement(&status, stats, header, "AST_R0");
Index: trunk/psastro/src/psastroMosaicAstrom.c
===================================================================
--- trunk/psastro/src/psastroMosaicAstrom.c	(revision 41858)
+++ trunk/psastro/src/psastroMosaicAstrom.c	(revision 41895)
@@ -277,9 +277,8 @@
     }
 
-    // the original transforms are (1, 1), but we will need higher order to fit the distortions
+    // the original transforms are (1, 1), but we will need higher order to fit the distortions.
+    // forward transformations (chip->fpa->tpa->sky) use Ordinary polynomials
     psFree (fpa->toTPA);
-
-    // the original transforms are (1, 1), but we will need higher order to fit the distortions
-    fpa->toTPA = psPlaneTransformAlloc (order, order);
+    fpa->toTPA = psPlaneTransformAlloc (order, order, PS_POLYNOMIAL_ORD);
     for (int i = 0; i <= fpa->toTPA->x->nX; i++) {
         for (int j = 0; j <= fpa->toTPA->x->nY; j++) {
Index: trunk/psastro/src/psastroMosaicChipAstrom.c
===================================================================
--- trunk/psastro/src/psastroMosaicChipAstrom.c	(revision 41858)
+++ trunk/psastro/src/psastroMosaicChipAstrom.c	(revision 41895)
@@ -91,9 +91,2 @@
     return true;
 }
-
-// XXX count success and failures
-// XXX set bad quality if fraction of successes < threshold
-// XXX e.g., 5% success would mean 3 of 60 GPC1 chips are goo.
-// XXX or, 10% would be 6 of 60.
-// XXX seems like a good indicator of failure.
-// XXX also, test CERROR against a minimum value?
Index: trunk/psastro/src/psastroMosaicCorrectDistortion.c
===================================================================
--- trunk/psastro/src/psastroMosaicCorrectDistortion.c	(revision 41858)
+++ trunk/psastro/src/psastroMosaicCorrectDistortion.c	(revision 41895)
@@ -22,6 +22,7 @@
     }
 
-    // store the new coeffs in a new structure
-    psPlaneTransform *toTPAnew = psPlaneTransformAlloc(fpa->toTPA->x->nX, fpa->toTPA->x->nY);
+    // Store the new coeffs in a new structure.  Forward transformations (chip->fpa->tpa->sky)
+    // use Ordinary polynomials
+    psPlaneTransform *toTPAnew = psPlaneTransformAlloc(fpa->toTPA->x->nX, fpa->toTPA->x->nY, PS_POLYNOMIAL_ORD);
 
     // set the new coeffs, or set the mask
Index: trunk/psastro/src/psastroMosaicFPtoTP.c
===================================================================
--- trunk/psastro/src/psastroMosaicFPtoTP.c	(revision 41858)
+++ trunk/psastro/src/psastroMosaicFPtoTP.c	(revision 41895)
@@ -80,5 +80,5 @@
 
     // linear fit without xy cross term
-    psPlaneTransform *map = psPlaneTransformAlloc (1, 1);
+    psPlaneTransform *map = psPlaneTransformAlloc (1, 1, PS_POLYNOMIAL_ORD);
     map->x->coeffMask[1][1] = PS_POLY_MASK_SET;
     map->y->coeffMask[1][1] = PS_POLY_MASK_SET;
Index: trunk/psastro/src/psastroMosaicGradients.c
===================================================================
--- trunk/psastro/src/psastroMosaicGradients.c	(revision 41858)
+++ trunk/psastro/src/psastroMosaicGradients.c	(revision 41895)
@@ -84,6 +84,8 @@
         return false;
     }
+
+    // forward transformations (chip->fpa->tpa->sky) use Ordinary polynomials
     psFree (fpa->toTPA);
-    fpa->toTPA = psPlaneTransformAlloc (order, order);
+    fpa->toTPA = psPlaneTransformAlloc (order, order, PS_POLYNOMIAL_ORD);
     for (int i = 0; i <= fpa->toTPA->x->nX; i++) {
         for (int j = 0; j <= fpa->toTPA->x->nY; j++) {
Index: trunk/psastro/src/psastroMosaicOneChip.c
===================================================================
--- trunk/psastro/src/psastroMosaicOneChip.c	(revision 41858)
+++ trunk/psastro/src/psastroMosaicOneChip.c	(revision 41895)
@@ -23,4 +23,5 @@
     bool status;
     char errorWord[64];
+    char stdevWord[64];
     char orderWord[64];
 
@@ -44,7 +45,10 @@
 
     // allowed limits for valid solutions
+    // CERROR is currently tested during the iterations, but not CERSTD
     snprintf (errorWord, 64, "PSASTRO.MOSAIC.MAX.ERROR.N%d", iteration);
-    REQUIRED_RECIPE_VALUE (float maxError, errorWord, F32, "failed to find single-chip max allowed error\n");
-    REQUIRED_RECIPE_VALUE (int minNstar, "PSASTRO.MOSAIC.MIN.NSTAR", S32, "failed to find single-chip min allowed stars\n");
+    snprintf (stdevWord, 64, "PSASTRO.MOSAIC.MAX.STDEV.N%d", iteration);
+    REQUIRED_RECIPE_VALUE (float maxError,                  errorWord, F32, "failed to find single-chip max allowed error\n");
+    REQUIRED_RECIPE_VALUE (float maxStdev,                  stdevWord, F32, "failed to find single-chip max allowed stdev\n");
+    REQUIRED_RECIPE_VALUE (int   minNstar, "PSASTRO.MOSAIC.MIN.NSTAR", S32, "failed to find single-chip min allowed stars\n");
 
     // set the order of the per-chip fit (higher order only if iteration > 0)
@@ -88,6 +92,7 @@
         }
     } else {
+	// Forward transformations (chip->fpa->tpa->sky) use Ordinary polynomials
         psFree (chip->toFPA);
-        chip->toFPA = psPlaneTransformAlloc (order, order);
+        chip->toFPA = psPlaneTransformAlloc (order, order, PS_POLYNOMIAL_ORD);
         for (int i = 0; i <= chip->toFPA->x->nX; i++) {
             for (int j = 0; j <= chip->toFPA->x->nY; j++) {
@@ -134,4 +139,8 @@
     int astNstar = results->yStats->clippedNvalues;
 
+    // astStdev is the average 1D stdev of median residuals in arcsec ('results' are in FPA units = microns)
+    // the median residuals are calculated in a grid of N x N bins 
+    float astStdev = 0.5*(results->dXstdev + results->dYstdev) * plateScale;
+
     // if we clip away too many stars, the order may be invalid
     if (order == 3) { minNstar = PS_MAX (15, minNstar); }
@@ -141,10 +150,14 @@
     bool validSolution = true;
 
-    // XXX should these result in errors or be handled another way?
-    psLogMsg ("psastro", PS_LOG_INFO, "astrometry solution: error: %f arcsec, Nstars: %d", astError, astNstar);
+    // We have options to exclude chips on the basis of NASTRO, CERROR, CERSTD
+    psLogMsg ("psastro", PS_LOG_INFO, "astrometry solution: error: %f arcsec, Nstars: %d, stdev: %f arcsec", astError, astNstar, astStdev);
     if ((maxError > 0) && (astError > maxError)) {
         psLogMsg("psastro", PS_LOG_INFO, "residual error is too large, failed to find a solution: %f > %f", astError, maxError);
         validSolution = false;
     }
+    if ((maxStdev > 0) && (astStdev > maxStdev)) {
+        psLogMsg("psastro", PS_LOG_INFO, "residual stdev is too large, failed to find a solution: %f > %f", astStdev, maxStdev);
+        validSolution = false;
+    }
     if (astNstar < minNstar) {
         psLogMsg("psastro", PS_LOG_INFO, "solution uses too few stars: %d < %d", astNstar, minNstar);
@@ -152,13 +165,16 @@
     }
 
-    // DVO expects NASTRO = 0 if we fail to find a solution
+    // DVO expects NASTRO = 0 if we fail to find a solution, NASTUSED is the true number
     psMetadataAddF32 (updates, PS_LIST_TAIL, "PERROR",   PS_META_REPLACE, "astrometry error (pixels)", pixError);
     psMetadataAddF32 (updates, PS_LIST_TAIL, "CERROR",   PS_META_REPLACE, "astrometry error (arcsec)", astError);
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "CERSTD",   PS_META_REPLACE, "astrometry stdev (arcsec)", astStdev);
     if (validSolution) {
         psMetadataAddF32 (updates, PS_LIST_TAIL, "CPRECISE", PS_META_REPLACE, "astrometry precision (arcsec)", astError/sqrt(astNstar));
         psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO",   PS_META_REPLACE, "number of astrometry stars", astNstar);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     } else {
         psMetadataAddF32 (updates, PS_LIST_TAIL, "CPRECISE", PS_META_REPLACE, "astrometry precision (arcsec)", 0.0);
         psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO",   PS_META_REPLACE, "number of astrometry stars", 0);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     }
     psMetadataAddF32 (updates, PS_LIST_TAIL, "EQUINOX",  PS_META_REPLACE, "", 2000.0); // XXX this is bogus: should be defined based on equinox of refstars
Index: trunk/psastro/src/psastroOneChipFit.c
===================================================================
--- trunk/psastro/src/psastroOneChipFit.c	(revision 41858)
+++ trunk/psastro/src/psastroOneChipFit.c	(revision 41895)
@@ -40,5 +40,6 @@
     // allowed limits for valid solutions
     REQUIRED_RECIPE_VALUE (float maxError, "PSASTRO.MAX.ERROR", F32);
-    REQUIRED_RECIPE_VALUE (int minNstar, "PSASTRO.MIN.NSTAR", S32);
+    REQUIRED_RECIPE_VALUE (float maxStdev, "PSASTRO.MAX.STDEV", F32);
+    REQUIRED_RECIPE_VALUE (int   minNstar, "PSASTRO.MIN.NSTAR", S32);
 
     psArray *match = NULL;
@@ -121,7 +122,8 @@
         }
 
-        // create output toFPA; set masks appropriate to the Elixir DVO astrometry format
+        // Create output toFPA; set masks appropriate to the Elixir DVO astrometry format.
+	// Forward transformations (chip->fpa->tpa->sky) use Ordinary polynomials
         psFree (chip->toFPA);
-        chip->toFPA = psPlaneTransformAlloc (order, order);
+        chip->toFPA = psPlaneTransformAlloc (order, order, PS_POLYNOMIAL_ORD);
         for (int i = 0; i <= chip->toFPA->x->nX; i++) {
             for (int j = 0; j <= chip->toFPA->x->nY; j++) {
@@ -192,4 +194,8 @@
     float astError = 0.5*(rawXstdev + rawYstdev) * plateScale;
 
+    // astStdev is the average 1D stdev of median residuals in arcsec ('results' are in FPA units = microns)
+    // the median residuals are calculated in a grid of N x N bins 
+    float astStdev = 0.5*(results->dXstdev + results->dYstdev) * plateScale;
+
     // x and y are forced to use the same subset of values:
     int astNstar = results->yStats->clippedNvalues;
@@ -198,9 +204,13 @@
 
     // XXX should these result in errors or be handled another way?
-    psLogMsg ("psastro", PS_LOG_INFO, "astrometry solution: error: %f arcsec, Nstars: %d", astError, astNstar);
+    psLogMsg ("psastro", PS_LOG_INFO, "astrometry solution: error: %f arcsec, Nstars: %d, stdev: %f arcsec", astError, astNstar, astStdev);
     if (astError > maxError) {
         psLogMsg("psastro", PS_LOG_INFO, "residual error is too large, failed to find a solution: %f > %f", astError, maxError);
         validSolution = false;
     }
+    if (astStdev > maxStdev) {
+	psLogMsg("psastro", PS_LOG_INFO, "residual stdev is too large, failed to find a solution: %f > %f", astStdev, maxStdev);
+        validSolution = false;
+    }
     if (astNstar < minNstar) {
         psLogMsg("psastro", PS_LOG_INFO, "solution uses too few stars: %d < %d", astNstar, minNstar);
@@ -211,9 +221,12 @@
     psMetadataAddF32 (updates, PS_LIST_TAIL, "PERROR",   PS_META_REPLACE, "astrometry error (pixels)", pixError);
     psMetadataAddF32 (updates, PS_LIST_TAIL, "CERROR",   PS_META_REPLACE, "astrometry error (arcsec)", astError);
+    psMetadataAddF32 (updates, PS_LIST_TAIL, "CERSTD",   PS_META_REPLACE, "astrometry stdev (arcsec)", astStdev);
     if (validSolution) {
         psMetadataAddF32 (updates, PS_LIST_TAIL, "CPRECISE", PS_META_REPLACE, "astrometry precision (arcsec)", astError/sqrt(astNstar));
         psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTRO",   PS_META_REPLACE, "number of astrometry stars", astNstar);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     } else {
 	psastroChipFailureHeader (updates);
+        psMetadataAddS32 (updates, PS_LIST_TAIL, "NASTUSED", PS_META_REPLACE, "number of astrometry stars", astNstar);
     }
     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
Index: trunk/psastro/src/psastroTIO.c
===================================================================
--- trunk/psastro/src/psastroTIO.c	(revision 41895)
+++ trunk/psastro/src/psastroTIO.c	(revision 41895)
@@ -0,0 +1,60 @@
+/** @file psastroTIO.c
+ *
+ *  @brief
+ *
+ *  @ingroup psastroTIO
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "psastroStandAlone.h"
+
+pmConfig *psastroTIOArguments (int argc, char **argv);
+bool psastroTIOParseCamera (pmConfig *config);
+bool psastroTIODataLoad (pmConfig *config);
+bool psastroTIODataSave (pmConfig *config);
+
+int main (int argc, char **argv) {
+
+    pmConfig *config = NULL;
+
+    psTimerStart ("complete");
+
+    // model inits are needed in pmSourceIO
+    // models defined in psphot/src/models are not available in psastro
+    pmModelClassInit ();
+
+    // load configuration information
+    config = psastroTIOArguments (argc, argv);
+
+    // load identify the data sources
+    if (!psastroTIOParseCamera (config)) {
+	psErrorStackPrint(stderr, "error setting up the camera\n");
+	exit (1);
+    }
+
+    psLogMsg ("psastro", 3, "parsed camera: %f sec\n", psTimerMark ("complete"));
+
+    // load the raw pixel data (from PSPHOT.SOURCES)
+    // select subset of stars for astrometry
+    if (!psastroTIODataLoad (config)) {
+	psErrorStackPrint(stderr, "error loading input data\n");
+	exit (1);
+    }
+
+    psLogMsg ("psastro", 3, "read data: %f sec\n", psTimerMark ("complete"));
+
+    // save the model
+    if (!psastroTIODataSave (config)) {
+	psErrorStackPrint(stderr, "error saving output data\n");
+	exit (1);
+    }
+
+    psLogMsg ("psastro", 3, "save data: %f sec\n", psTimerMark ("complete"));
+
+    // psastroCleanup (config);
+    exit (EXIT_SUCCESS);
+}
Index: trunk/psastro/src/psastroTIOArguments.c
===================================================================
--- trunk/psastro/src/psastroTIOArguments.c	(revision 41895)
+++ trunk/psastro/src/psastroTIOArguments.c	(revision 41895)
@@ -0,0 +1,73 @@
+/** @file psastroTIOArguments.c
+ *
+ *  @brief
+ *
+ *  @ingroup psastroTIO
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "psastroStandAlone.h"
+
+static char *usage = "USAGE: psastroTIO -file (filename) -output (root)";
+
+pmConfig *psastroTIOArguments (int argc, char **argv) {
+
+    int N;
+
+    if (argc == 1) {
+        psError(PSASTRO_ERR_ARGUMENTS, true, "No arguments supplied");
+        psErrorStackPrint(stderr, "%s", usage);
+	exit (1);
+    }
+
+    // load config data from default locations
+    pmConfig *config = pmConfigRead(&argc, argv, PSASTRO_RECIPE);
+    if (config == NULL) {
+        psError(PSASTRO_ERR_CONFIG, false, "Can't read site configuration");
+        psErrorStackPrint(stderr, "%s", usage);
+	exit (1);
+    }
+
+    // save the following additional recipe values based on command-line options
+    // these options override the PSASTRO recipe values loaded from recipe files
+
+    // define the output filename
+    if ((N = psArgumentGet (argc, argv, "-output")) == FALSE) {
+        psError(PSASTRO_ERR_ARGUMENTS, true, "Missing -output (root)");
+        psErrorStackPrint(stderr, "%s", usage);
+	exit (1);
+    }
+    psArgumentRemove (N, &argc, argv);
+    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[N]);
+    psArgumentRemove (N, &argc, argv);
+
+    int status = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT", "-file", "-list");
+    if (!status) {
+        psError(PSASTRO_ERR_ARGUMENTS, true, "Missing -file (input) or -list (input)");
+        psErrorStackPrint(stderr, "exit");
+        return NULL;
+    }
+
+    // chip selection is used to limit chips to be processed
+    if ((N = psArgumentGet (argc, argv, "-chip"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_META_REPLACE, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+    
+    if (argc != 1) {
+	psError(PSASTRO_ERR_ARGUMENTS, true, "Incorrect arguments supplied: argc = %d", argc);
+	if (argc) {
+	    for (int i = 1; i < argc; i++){
+		fprintf (stderr, "argc %d : %s\n", i, argv[i]);
+	    }
+	}
+	psErrorStackPrint(stderr, "exit");
+	exit (1);
+    }
+    return (config);
+}
Index: trunk/psastro/src/psastroTIODataLoad.c
===================================================================
--- trunk/psastro/src/psastroTIODataLoad.c	(revision 41895)
+++ trunk/psastro/src/psastroTIODataLoad.c	(revision 41895)
@@ -0,0 +1,82 @@
+/** @file psastroTIODataLoad.c
+ *
+ *  @brief
+ *
+ *  @ingroup psastro
+ *
+ *  @author IfA
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "psastroStandAlone.h"
+
+# define ESCAPE { \
+  psError(PS_ERR_UNKNOWN, false, "Failure in psastroTIODataLoad"); \
+  psFree (view); \
+  return false; \
+}
+  
+bool psastroTIODataLoad (pmConfig *config) {
+
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+
+    psTimerStart ("psastroDataLoad");
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, PSASTRO_RECIPE);
+    if (!recipe) {
+	psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!\n");
+	return false;
+    }
+
+    // select the input data sources
+    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
+    if (!input) {
+	psError(PSASTRO_ERR_CONFIG, true, "Can't find input data!\n");
+	return false;
+    }
+
+    // de-activate all files except PSASTRO.INPUT
+    pmFPAfileActivate (config->files, false, NULL);
+    pmFPAfileActivate (config->files, true, "PSASTRO.INPUT");
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    // files associated with the science image
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+        psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+
+	while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            psTrace ("psastro", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+	    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+
+	    // process each of the readouts
+	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+		if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+		if (!readout->data_exists) { continue; }
+
+		// if (!psastroConvertReadout (config, view, readout, recipe)) ESCAPE;
+
+		if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+	    }
+	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+	}
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+    }
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+
+    psLogMsg ("psastro", 3, "load data : %f sec\n", psTimerMark ("psastroDataLoad"));
+
+    psFree (view);
+    return true;
+}
+
Index: trunk/psastro/src/psastroTIODataSave.c
===================================================================
--- trunk/psastro/src/psastroTIODataSave.c	(revision 41895)
+++ trunk/psastro/src/psastroTIODataSave.c	(revision 41895)
@@ -0,0 +1,82 @@
+/** @file psastroTIODataSave.c
+ *
+ *  @brief
+ *
+ *  @ingroup psastro
+ *
+ *  @author IfA
+ *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "psastroInternal.h"
+
+# define ESCAPE { \
+  psError(PS_ERR_UNKNOWN, false, "Failure in psastroTIODataSave"); \
+  psFree (view); \
+  return false; \
+}
+
+void pmSourceIO_ShowTiming(void);
+
+bool psastroTIODataSave (pmConfig *config) {
+
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+
+    psTimerStart ("psastroDataSave");
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, PSASTRO_RECIPE);
+    if (!recipe) {
+        psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!\n");
+        return false;
+    }
+
+    // select the output data sources
+    pmFPAfile *output = psMetadataLookupPtr (NULL, config->files, "PSASTRO.OUTPUT");
+    if (!output) {
+        psError(PSASTRO_ERR_CONFIG, true, "Can't find or interpret output file rule PSASTRO.OUTPUT!\n");
+        return false;
+    }
+
+    // de-activate all files except PSASTRO.OUTPUT, PSASTRO.OUT.ASTROM, and PSPHOT.OUTPUT.CFF
+    pmFPAfileActivate (config->files, false, NULL);
+    pmFPAfileActivate (config->files, true, "PSASTRO.OUTPUT");
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+
+    // open/load files as needed
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+
+    while ((chip = pmFPAviewNextChip (view, output->fpa, 1)) != NULL) {
+        psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+
+        while ((cell = pmFPAviewNextCell (view, output->fpa, 1)) != NULL) {
+            psTrace ("psastro", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+
+            // process each of the readouts
+            while ((readout = pmFPAviewNextReadout (view, output->fpa, 1)) != NULL) {
+                if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE;
+                if (!readout->data_exists) { continue; }
+
+                if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+            }
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+        }
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+    }
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE;
+
+    psLogMsg ("psastro", 3, "save data : %f sec\n", psTimerMark ("psastroDataSave"));
+
+    psFree (view);
+
+    return true;
+}
Index: trunk/psastro/src/psastroTIOParseCamera.c
===================================================================
--- trunk/psastro/src/psastroTIOParseCamera.c	(revision 41895)
+++ trunk/psastro/src/psastroTIOParseCamera.c	(revision 41895)
@@ -0,0 +1,51 @@
+/** @file psastroTIOParseCamera.c
+ *
+ *  @brief
+ *
+ *  @ingroup psastroTIO
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# include "psastroInternal.h"
+
+bool psastroTIOParseCamera (pmConfig *config) {
+
+    bool status = false;
+
+    // the input image(s) are required arguments; they define the camera
+    pmFPAfile *input = pmFPAfileDefineFromArgs (&status, config, "PSASTRO.INPUT", "INPUT");
+    if (!status) {
+	psError(PSASTRO_ERR_CONFIG, false, "Failed to build FPA from PSASTRO.INPUT");
+	return false;
+    }
+
+    pmFPAfile *output = pmFPAfileDefineOutput (config, input->fpa, "PSASTRO.OUTPUT");
+    if (!output) {
+	psError(PSASTRO_ERR_CONFIG, false, "Failed to build FPA from PSASTRO.INPUT");
+	return false;
+    }
+    output->save = true;
+
+
+    // Chip selection: turn on only the chips specified (option is not required)
+    char *chipLine = psMetadataLookupStr(&status, config->arguments, "CHIP_SELECTIONS"); 
+    psArray *chips = psStringSplitArray (chipLine, ",", false);
+    if (chips->n > 0) {
+	pmFPASelectChip (input->fpa, -1, true); // deselect all chips
+	for (int i = 0; i < chips->n; i++) {
+	    int chipNum = atoi(chips->data[i]);
+	    if (! pmFPASelectChip(input->fpa, chipNum, false)) {
+		psError(PSASTRO_ERR_CONFIG, true, "Chip number %d doesn't exist in camera.\n", chipNum);
+		return false;
+	    }
+        }
+    }
+    psFree (chips);
+
+    psTrace("psastro", 1, "Done with psastroTIOParseCamera...\n");
+    return true;
+}
Index: trunk/psastro/src/psastroUtils.c
===================================================================
--- trunk/psastro/src/psastroUtils.c	(revision 41858)
+++ trunk/psastro/src/psastroUtils.c	(revision 41895)
@@ -215,5 +215,5 @@
 psPlaneTransform *psPlaneTransformCopy (psPlaneTransform *input) {
 
-    psPlaneTransform *output = psPlaneTransformAlloc (input->x->nX, input->x->nY);
+    psPlaneTransform *output = psPlaneTransformAlloc (input->x->nX, input->x->nY, input->x->type);
 
     for (int i = 0; i < input->x->nX; i++) {
