Index: trunk/psModules/src/detrend/pmBias.c
===================================================================
--- trunk/psModules/src/detrend/pmBias.c	(revision 10302)
+++ trunk/psModules/src/detrend/pmBias.c	(revision 10326)
@@ -8,6 +8,6 @@
 
 #include "pmFPA.h"
+#include "pmHDUUtils.h"
 #include "pmBias.h"
-
 
 static void overscanOptionsFree(pmOverscanOptions *options)
@@ -212,5 +212,5 @@
     }
 
-    //    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now, used for reporting
+    pmHDU *hdu = pmHDUFromReadout(in);  // HDU of interest
 
     psImage *image = in->image;         // The input image
@@ -235,4 +235,11 @@
         }
         psStats *stats = psStatsAlloc(statistic); // A new psStats, to avoid clobbering original
+
+        psString comment = NULL;    // Comment to add
+        psStringAppend(&comment, "Subtracting overscan (stat %x; type %x; order %d)",
+                       statistic, overscanOpts->fitType, overscanOpts->order);
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                         comment, "");
+        psFree(comment);
 
         // Reduce all overscan pixels to a single value
@@ -245,11 +252,9 @@
                 pixels = psVectorRealloc(pixels, pixels->n + overscan->numRows * overscan->numCols);
                 pixels->n += overscan->numRows * overscan->numCols;
-                // XXX Reimplement with memcpy
                 for (int i = 0; i < overscan->numRows; i++) {
-                    for (int j = 0; j < overscan->numCols; j++) {
-                        pixels->data.F32[index++] = overscan->data.F32[i][j];
-                    }
-                }
-
+                    memcpy(&pixels->data.F32[index], overscan->data.F32[i],
+                           overscan->numCols * sizeof(psF32));
+                    index += overscan->numCols;
+                }
             }
             psFree(iter);
@@ -260,7 +265,5 @@
             (void)psBinaryOp(image, image, "-", psScalarAlloc((float)reduced, PS_TYPE_F32));
         } else {
-
             // We do the regular overscan subtraction
-
             bool readRows = psMetadataLookupBool(NULL, in->parent->concepts, "CELL.READDIR");// Read direction
 
@@ -357,6 +360,15 @@
     // Bias frame subtraction
     if (bias) {
-        if (!subtractFrame(in, bias, 1.0))
+        psVector *md5 = psImageMD5(bias->image); // md5 hash
+        psString md5string = psMD5toString(md5); // String
+        psFree(md5);
+        psStringPrepend(&md5string, "BIAS image MD5: ");
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                         md5string, "");
+        psFree(md5string);
+
+        if (!subtractFrame(in, bias, 1.0)) {
             return false;
+        }
     }
 
@@ -365,7 +377,26 @@
         float inTime = psMetadataLookupF32(NULL, in->parent->concepts, "CELL.DARKTIME");
         float darkTime = psMetadataLookupF32(NULL, dark->parent->concepts, "CELL.DARKTIME");
-        if (!subtractFrame(in, dark, inTime/darkTime))
+
+        psVector *md5 = psImageMD5(dark->image); // md5 hash
+        psString md5string = psMD5toString(md5); // String
+        psFree(md5);
+        psStringPrepend(&md5string, "DARK image (scale %.3f) MD5: ", inTime/darkTime);
+        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                         md5string, "");
+        psFree(md5string);
+
+        if (!subtractFrame(in, dark, inTime/darkTime)) {
             return false;
-    }
+        }
+    }
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now, used for reporting
+    psString timeString = psTimeToISO(time); // String with time
+    psFree(time);
+    psStringPrepend(&timeString, "Bias processing completed at ");
+    psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK,
+                     timeString, "");
+    psFree(timeString);
+
 
     return true;
