Index: trunk/psModules/src/detrend/Makefile.am
===================================================================
--- trunk/psModules/src/detrend/Makefile.am	(revision 7567)
+++ trunk/psModules/src/detrend/Makefile.am	(revision 7589)
@@ -9,5 +9,6 @@
 	pmMaskBadPixels.c \
 	pmNonLinear.c \
-	pmSubtractBias.c
+	pmSubtractBias.c \
+	pmDetrendDB.c
 
 #	pmSubtractSky.c
@@ -22,5 +23,6 @@
 	pmMaskBadPixels.h \
 	pmNonLinear.h \
-	pmSubtractBias.h
+	pmSubtractBias.h \
+	pmDetrendDB.h
 
 #	pmSubtractSky.c
Index: trunk/psModules/src/detrend/pmDetrendDB.c
===================================================================
--- trunk/psModules/src/detrend/pmDetrendDB.c	(revision 7589)
+++ trunk/psModules/src/detrend/pmDetrendDB.c	(revision 7589)
@@ -0,0 +1,159 @@
+# include <pslib.h>
+# include "pmFPA.h"
+# include "pmDetrendDB.h"
+
+// ************* detrend select functions **************
+
+//
+static void pmDetrendSelectOptionsFree (pmDetrendSelectOptions *options)
+{
+
+    if (!options)
+        return;
+
+    psFree (options->camera);
+    psFree (options->filter);
+
+    return;
+}
+
+// define basic options for a new detrend database query
+pmDetrendSelectOptions *pmDetrendSelectOptionsAlloc(char *camera, psTime time, pmDetrendType type)
+{
+
+    pmDetrendSelectOptions *options = psAlloc(sizeof(pmDetrendSelectOptions));
+    psMemSetDeallocator(options, (psFreeFunc) pmDetrendSelectOptionsFree);
+
+    // basic options required by every query
+    options->camera = psMemIncrRefCounter(camera);
+    options->time   = time;
+    options->type   = type;
+
+    // these other options depend on the type of detrend data
+    options->filter = NULL;
+    options->exptime = 0.0;
+    options->airmass = 0.0;
+
+    return options;
+}
+
+static void pmDetrendSelectResultsFree (pmDetrendSelectResults *results)
+{
+
+    if (!results)
+        return;
+
+    psFree (results->detID);
+
+    return;
+}
+
+pmDetrendSelectResults *pmDetrendSelectResultsAlloc ()
+{
+
+    pmDetrendSelectResults *results = psAlloc(sizeof(pmDetrendSelectResults));
+    psMemSetDeallocator(results, (psFreeFunc) pmDetrendSelectResultsFree);
+
+    results->detID = NULL;
+    results->level = PM_FPA_LEVEL_NONE;
+
+    return results;
+}
+
+psString pmDetrendTypeToString (pmDetrendType type)
+{
+
+    # define DETREND_STRING_CASE(TTT) \
+case PM_DETREND_TYPE_##TTT: \
+    return psStringCopy (#TTT);
+
+    switch (type) {
+        DETREND_STRING_CASE (MASK);
+        DETREND_STRING_CASE (BIAS);
+        DETREND_STRING_CASE (DARK);
+        DETREND_STRING_CASE (FLAT);
+        DETREND_STRING_CASE (FLAT_CORRECTION);
+        DETREND_STRING_CASE (FRINGE_IMAGE);
+        DETREND_STRING_CASE (FRINGE_TABLE);
+    default:
+        return NULL;
+    }
+    return NULL;
+}
+
+// detselect -camera (camera) -time (time) -type (type) [others]
+pmDetrendSelectResults *pmDetrendSelect (pmDetrendSelectOptions *options)
+{
+
+    char answer[128];
+    char line[1024];
+
+    char *time = psTimeToISO (&options->time);
+    char *type = pmDetrendTypeToString (options->type);
+
+    sprintf (line, "detselect -camera %s -time %s -type %s",
+             options->camera, time, type);
+    psFree (time);
+    psFree (type);
+
+    // XXX put this in a fork/exec to catch the timeout
+    FILE *p = popen (line, "r");
+    fgets (answer, 127, p);
+    pclose (p);
+
+    psList *list = psStringSplit (answer, " ", false);
+    psArray *array = psListToArray (list);
+
+    if (!array)
+        return NULL;
+    if (!array->n)
+        return NULL;
+    if (!strcasecmp(array->data[0], "ERROR"))
+        return NULL;
+
+    pmFPALevel level = pmFPALevelFromName (array->data[1]);
+    if (level == PM_FPA_LEVEL_NONE)
+        return NULL;
+
+    pmDetrendSelectResults *results = pmDetrendSelectResultsAlloc();
+    results->level = level;
+    results->detID = psStringCopy (array->data[2]);
+
+    psFree (array);
+    psFree (list);
+
+    return results;
+}
+
+// ************* detrend file functions **************
+
+char *pmDetrendFile (char *detID, char *classID)
+{
+
+    char answer[128];
+    char line[1024];
+
+    sprintf (line, "detselect -select -detID %s -classID %s", detID, classID);
+
+    // XXX put this in a fork/exec to catch the timeout
+    FILE *p = popen (line, "r");
+    fgets (answer, 127, p);
+    pclose (p);
+
+    psList *list = psStringSplit (answer, " ", false);
+    psArray *array = psListToArray (list);
+
+    if (!array)
+        return NULL;
+    if (!array->n)
+        return NULL;
+    if (!strcasecmp(array->data[0], "ERROR"))
+        return NULL;
+
+    char *result = psStringCopy (array->data[2]);
+
+    psFree (array);
+    psFree (list);
+
+    return result;
+}
Index: trunk/psModules/src/detrend/pmDetrendDB.h
===================================================================
--- trunk/psModules/src/detrend/pmDetrendDB.h	(revision 7589)
+++ trunk/psModules/src/detrend/pmDetrendDB.h	(revision 7589)
@@ -0,0 +1,68 @@
+/** @file  pmDetrendDB.h
+*
+*  @brief Tools to query the detrend database system
+*
+*  the functions in here do not perform the detrend database queries directly.  all interfaces
+*  to the detrend database go through the external dettools functions.  this allows the modules
+*  and directly dependent program to be sufficiently independent of the database schema that it
+*  can be used with any properly defined detrend database tables.  
+*
+*  XXX place the specific name of the detrend database query command in the configuration data
+*
+*  @ingroup Detrend
+*
+*  @author EAM, IfA
+*
+*  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-06-17 01:50:43 $
+*
+*  Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+*/
+
+#ifndef PM_DETREND_DB_H
+#define PM_DETREND_DB_H
+
+typedef enum {
+    PM_DETREND_TYPE_MASK,
+    PM_DETREND_TYPE_BIAS,
+    PM_DETREND_TYPE_DARK,
+    PM_DETREND_TYPE_FLAT,
+    PM_DETREND_TYPE_FLAT_CORRECTION,
+    PM_DETREND_TYPE_FRINGE_IMAGE,
+    PM_DETREND_TYPE_FRINGE_TABLE,
+    PM_DETREND_TYPE_BACKGROUND,
+} pmDetrendType;
+
+typedef struct
+{
+    char *camera;   // name of camera
+    psTime time;   // time of input data
+    pmDetrendType type;   // type of detrend data
+    char *filter;   // name of filter
+    float exptime;   // exposure time (for dark, maybe flat & fringe)
+    float airmass;   // for fringe
+}
+pmDetrendSelectOptions;
+
+typedef struct
+{
+    char *detID;   // identifier of detrend image
+    pmFPALevel level;   // level in FPA hierarchy of individual file
+}
+pmDetrendSelectResults;
+
+typedef struct
+{
+    char *detID;   // identifier of detrend image
+    char *classID;   // level in FPA hierarchy of individual file
+}
+pmDetrendFileOptions;
+
+psString pmDetrendTypeToString (pmDetrendType type);
+
+pmDetrendSelectOptions *pmDetrendSelectOptionsAlloc(char *camera, psTime time, pmDetrendType type);
+pmDetrendSelectResults *pmDetrendSelectResultsAlloc();
+pmDetrendSelectResults *pmDetrendSelect (pmDetrendSelectOptions *options);
+char *pmDetrendFile (char *detID, char *classID);
+
+# endif
Index: trunk/psModules/src/detrend/pmSubtractBias.c
===================================================================
--- trunk/psModules/src/detrend/pmSubtractBias.c	(revision 7567)
+++ trunk/psModules/src/detrend/pmSubtractBias.c	(revision 7589)
@@ -11,6 +11,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-06-08 22:14:28 $
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-17 01:50:43 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -106,4 +106,22 @@
     psImage *subImage = sub->image;     // The image to be subtracted
     psImage *subMask  = sub->mask;      // The mask for the subtraction image
+
+    int xIpar = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.XPARITY");
+    int xSpar = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.XPARITY");
+    if (xIpar != xSpar) {
+        psError(PS_ERR_UNKNOWN, true, "images for subtraction do not have the same "
+                "CELL.XPARITY (%d vs %d).\n    pmSubtractBias must be upgraded to handle this situation\n",
+                xIpar, xSpar);
+        return false;
+    }
+
+    int yIpar = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.YPARITY");
+    int ySpar = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.YPARITY");
+    if (yIpar != ySpar) {
+        psError(PS_ERR_UNKNOWN, true, "images for subtraction do not have the same "
+                "CELL.YPARITY (%d vs %d).\n    pmSubtractBias must be upgraded to handle this situation\n",
+                xIpar, xSpar);
+        return false;
+    }
 
     // Offsets of the cells
@@ -293,6 +311,6 @@
 XXX: The SDRS does not specify type support.  F32 is implemented here.
  *****************************************************************************/
-pmReadout *pmSubtractBias(pmReadout *in, pmOverscanOptions *overscanOpts,
-                          const pmReadout *bias, const pmReadout *dark)
+bool pmSubtractBias(pmReadout *in, pmOverscanOptions *overscanOpts,
+                    const pmReadout *bias, const pmReadout *dark)
 {
     psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4,
@@ -319,5 +337,5 @@
                 overscanOpts->fitType != PM_FIT_POLY_CHEBY && overscanOpts->fitType != PM_FIT_SPLINE) {
             psError(PS_ERR_UNKNOWN, true, "Invalid fit type (%d).  Returning original image.\n", overscanOpts->fitType);
-            return(in);
+            return false;
         }
 
@@ -349,5 +367,5 @@
             if (! p_psGetStatValue(myStats, &reduced)) {
                 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning input image.\n");
-                return(in);
+                return false;
             }
             (void)psBinaryOp(image, image, "-", psScalarAlloc((float)reduced, PS_TYPE_F32));
@@ -391,5 +409,5 @@
                 psFree(pixels);
                 if (! reduced) {
-                    return in;
+                    return false;
                 }
 
@@ -435,5 +453,5 @@
                 psFree(pixels);
                 if (! reduced) {
-                    return in;
+                    return false;
                 }
 
@@ -452,5 +470,6 @@
     // Bias frame subtraction
     if (bias) {
-        SubtractFrame(in, bias, 1.0);
+        if (!SubtractFrame(in, bias, 1.0))
+            return false;
     }
 
@@ -459,9 +478,10 @@
         float inTime = psMetadataLookupF32(NULL, in->parent->concepts, "CELL.DARKTIME");
         float darkTime = psMetadataLookupF32(NULL, dark->parent->concepts, "CELL.DARKTIME");
-        SubtractFrame(in, dark, inTime/darkTime);
-    }
-
-    return in;
-}
-
-
+        if (!SubtractFrame(in, dark, inTime/darkTime))
+            return false;
+    }
+
+    return true;
+}
+
+
Index: trunk/psModules/src/detrend/pmSubtractBias.h
===================================================================
--- trunk/psModules/src/detrend/pmSubtractBias.h	(revision 7567)
+++ trunk/psModules/src/detrend/pmSubtractBias.h	(revision 7589)
@@ -11,6 +11,6 @@
  *  @author GLG, MHPCC
  *
- *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-05-01 01:56:29 $
+ *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-06-17 01:50:43 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -61,6 +61,6 @@
 pmOverscanOptions *pmOverscanOptionsAlloc(bool single, pmFit fitType, unsigned int order, psStats *stat);
 
-pmReadout *pmSubtractBias(pmReadout *in, pmOverscanOptions *overscanOpts,
-                          const pmReadout *bias, const pmReadout *dark);
+bool pmSubtractBias(pmReadout *in, pmOverscanOptions *overscanOpts,
+                    const pmReadout *bias, const pmReadout *dark);
 
 #if 0
