Index: trunk/psModules/src/detrend/pmBias.c
===================================================================
--- trunk/psModules/src/detrend/pmBias.c	(revision 13776)
+++ trunk/psModules/src/detrend/pmBias.c	(revision 13810)
@@ -11,4 +11,8 @@
 #include "pmFPA.h"
 #include "pmHDUUtils.h"
+#include "pmFPALevel.h"
+#include "pmFPAview.h"
+#include "pmFPACalibration.h"
+
 #include "pmBias.h"
 
@@ -206,25 +210,25 @@
 }
 
-
-bool pmBiasSubtract(pmReadout *in, pmOverscanOptions *overscanOpts,
-                    const pmReadout *bias, const pmReadout *dark)
+bool pmBiasSubtract(pmReadout *inRO, pmOverscanOptions *overscanOpts,
+                    const pmReadout *biasRO, const pmReadout *darkRO, const pmFPAview *view)
 {
     psTrace("psModules.detrend", 4,
             "---- pmBiasSubtract() begin ----\n");
-    PS_ASSERT_PTR_NON_NULL(in, NULL);
-    PS_ASSERT_IMAGE_NON_NULL(in->image, NULL);
-    PS_ASSERT_IMAGE_TYPE(in->image, PS_TYPE_F32, NULL);
-    if (bias) {
-        PS_ASSERT_IMAGE_NON_NULL(bias->image, NULL);
-        PS_ASSERT_IMAGE_TYPE(bias->image, PS_TYPE_F32, NULL);
-    }
-    if (dark) {
-        PS_ASSERT_IMAGE_NON_NULL(dark->image, NULL);
-        PS_ASSERT_IMAGE_TYPE(dark->image, PS_TYPE_F32, NULL);
-    }
-
-    pmHDU *hdu = pmHDUFromReadout(in);  // HDU of interest
-
-    psImage *image = in->image;         // The input image
+
+    PS_ASSERT_PTR_NON_NULL(inRO, false);
+    PS_ASSERT_IMAGE_NON_NULL(inRO->image, false);
+    PS_ASSERT_IMAGE_TYPE(inRO->image, PS_TYPE_F32, false);
+    if (biasRO) {
+        PS_ASSERT_IMAGE_NON_NULL(biasRO->image, false);
+        PS_ASSERT_IMAGE_TYPE(biasRO->image, PS_TYPE_F32, false);
+    }
+    if (darkRO) {
+        PS_ASSERT_PTR_NON_NULL(view, false);
+        PS_ASSERT_IMAGE_NON_NULL(darkRO->image, false);
+        PS_ASSERT_IMAGE_TYPE(darkRO->image, PS_TYPE_F32, false);
+    }
+
+    pmHDU *hdu = pmHDUFromReadout(inRO);  // HDU of interest
+    psImage *image = inRO->image;         // The input image
 
     // Overscan processing
@@ -238,5 +242,5 @@
         }
 
-        psList *overscans = in->bias; // List of the overscan images
+        psList *overscans = inRO->bias; // List of the overscan images
 
         psStatsOptions statistic = psStatsSingleOption(overscanOpts->stat->options); // Statistic to use
@@ -281,6 +285,7 @@
             psFree(comment);
 
-	    // write metadata header value
-            psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE, "Overscan value", reduced);
+            // write metadata header value
+            psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE, "Overscan value",
+                             reduced);
             psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE, "Overscan stdev", NAN);
 
@@ -288,5 +293,6 @@
         } else {
             // We do the regular overscan subtraction
-            bool readRows = psMetadataLookupBool(NULL, in->parent->concepts, "CELL.READDIR");// Read direction
+            bool readRows = psMetadataLookupBool(NULL, inRO->parent->concepts,
+                                                 "CELL.READDIR"); // Read direction
             float chi2 = NAN;           // chi^2 from fit
 
@@ -302,11 +308,11 @@
                 psImage *overscan = NULL; // Overscan image from iterator
                 while ((overscan = psListGetAndIncrement(iter))) {
-		    // the overscan and image might not be aligned.  pixels->data represents
-		    // the image row pixels.
+                    // the overscan and image might not be aligned.  pixels->data represents
+                    // the image row pixels.
                     int diff = overscan->row0 - image->row0; // Offset between the two regions
                     for (int i = PS_MAX(0,diff); i < PS_MIN(image->numRows, overscan->numRows + diff); i++) {
-			int j = i - diff;
+                        int j = i - diff;
                         // i is row on image
-			// j is row on overscan
+                        // j is row on overscan
                         psVector *values = pixels->data[i];
                         int index = values->n; // Index in the vector
@@ -349,16 +355,16 @@
                 psImage *overscan = NULL; // Overscan image from iterator
                 while ((overscan = psListGetAndIncrement(iter))) {
-		    // the overscan and image might not be aligned.  pixels->data represents
-		    // the image row pixels.
+                    // the overscan and image might not be aligned.  pixels->data represents
+                    // the image row pixels.
                     int diff = overscan->col0 - image->col0; // Offset between the two regions
                     for (int i = PS_MAX(0,diff); i < PS_MIN(image->numCols, overscan->numCols + diff); i++) {
-			int I = i - diff;
+                        int iFixed = i - diff;
                         // i is column on image
-                        // I is column on overscan
+                        // iFixed is column on overscan
                         psVector *values = pixels->data[i];
                         int index = values->n; // Index in the vector
                         values = psVectorRealloc(values, values->n + overscan->numRows);
-                        for (int J = 0; J < overscan->numRows; J++) {
-                            values->data.F32[index++] = overscan->data.F32[J][I];
+                        for (int j = 0; j < overscan->numRows; j++) {
+                            values->data.F32[index++] = overscan->data.F32[j][iFixed];
                         }
                         values->n += overscan->numRows;
@@ -397,7 +403,9 @@
                     psFree(comment);
 
-		    // write metadata header value
-		    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE, "Overscan value", poly->coeff[0]);
-		    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE, "Overscan stdev", poly->coeffErr[0]);
+                    // write metadata header value
+                    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE,
+                                     "Overscan value", poly->coeff[0]);
+                    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE,
+                                     "Overscan stdev", poly->coeffErr[0]);
                     break;
                 }
@@ -414,7 +422,9 @@
                         psFree(comment);
                     }
-		    // write metadata header value
-		    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE, "Overscan value", NAN);
-		    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE, "Overscan stdev", NAN);
+                    // write metadata header value
+                    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE,
+                                     "Overscan value", NAN);
+                    psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE,
+                                     "Overscan stdev", NAN);
                     break;
                 }
@@ -431,6 +441,6 @@
 
     // Bias frame subtraction
-    if (bias) {
-        psVector *md5 = psImageMD5(bias->image); // md5 hash
+    if (biasRO) {
+        psVector *md5 = psImageMD5(biasRO->image); // md5 hash
         psString md5string = psMD5toString(md5); // String
         psFree(md5);
@@ -440,23 +450,36 @@
         psFree(md5string);
 
-        if (!subtractFrame(in, bias, 1.0)) {
+        if (!subtractFrame(inRO, biasRO, 1.0)) {
             return false;
         }
     }
 
-    if (dark) {
+    if (darkRO) {
         // Get the scaling
-        float inTime = psMetadataLookupF32(NULL, in->parent->concepts, "CELL.DARKTIME");
-        float darkTime = psMetadataLookupF32(NULL, dark->parent->concepts, "CELL.DARKTIME");
-
-        psVector *md5 = psImageMD5(dark->image); // md5 hash
+        float inTime = psMetadataLookupF32(NULL, inRO->parent->concepts, "CELL.DARKTIME");
+        float darkTime = psMetadataLookupF32(NULL, darkRO->parent->concepts, "CELL.DARKTIME");
+        if (isnan(inTime) || isnan(darkTime)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine dark scaling.");
+            return false;
+        }
+
+        float inNorm = pmFPADarkNorm(inRO->parent->parent->parent, view, inTime);
+        float darkNorm = pmFPADarkNorm(darkRO->parent->parent->parent, view, darkTime);
+        if (isnan(inNorm) || isnan(darkNorm)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to determine dark normalisations.");
+            return false;
+        }
+
+        float scale = inNorm / darkNorm;// Scaling to apply to dark exposure
+
+        psVector *md5 = psImageMD5(darkRO->image); // md5 hash
         psString md5string = psMD5toString(md5); // String
         psFree(md5);
-        psStringPrepend(&md5string, "DARK image (scale %.3f) MD5: ", inTime/darkTime);
+        psStringPrepend(&md5string, "DARK image (scale %.3f) MD5: ", scale);
         psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
                          md5string, "");
         psFree(md5string);
 
-        if (!subtractFrame(in, dark, inTime/darkTime)) {
+        if (!subtractFrame(inRO, darkRO, scale)) {
             return false;
         }
Index: trunk/psModules/src/detrend/pmBias.h
===================================================================
--- trunk/psModules/src/detrend/pmBias.h	(revision 13776)
+++ trunk/psModules/src/detrend/pmBias.h	(revision 13810)
@@ -5,6 +5,6 @@
  * @author Paul Price, IfA
  *
- * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-03-30 21:12:56 $
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-06-14 02:03:29 $
  * Copyright 2004--2006 Institute for Astronomy, University of Hawaii
  */
@@ -57,6 +57,7 @@
 bool pmBiasSubtract(pmReadout *in,      ///< Input readout, to be overscan/bias/dark corrected
                     pmOverscanOptions *overscanOpts, ///< Options for overscan subtraction, or NULL
-                    const pmReadout *bias, ///< Bias image to subtract, or NULL
-                    const pmReadout *dark ///< Dark image to scale and subtract, or NULL
+                    const pmReadout *bias, ///< Bias to subtract, or NULL
+                    const pmReadout *dark, ///< Dark to scale and subtract, or NULL
+                    const pmFPAview *view ///< View for readout of interest
                    );
 
