Index: /branches/pap/psModules/src/objects/pmDetEff.c
===================================================================
--- /branches/pap/psModules/src/objects/pmDetEff.c	(revision 25330)
+++ /branches/pap/psModules/src/objects/pmDetEff.c	(revision 25331)
@@ -78,4 +78,18 @@
 }
 
+bool pmReadoutWriteDetEff(psFits *fits, const pmReadout *readout,
+                          const psMetadata *header, const char *extname)
+{
+    PM_ASSERT_READOUT_NON_NULL(readout, false);
+
+    bool mdok;                          // Status of MD lookup
+    pmDetEff *de = psMetadataLookupPtr(&mdok, readout->analysis, PM_DETEFF_ANALYSIS); // Detection efficiency
+    if (!mdok || !de) {
+        // Wrote everything there was to write
+        return true;
+    }
+    return pmDetEffWrite(fits, de, header, extname);
+}
+
 
 pmDetEff *pmDetEffRead(psFits *fits, const char *extname)
@@ -138,2 +152,17 @@
 }
 
+bool pmReadoutReadDetEff(psFits *fits, const pmReadout *readout, const char *extname)
+{
+    PM_ASSERT_READOUT_NON_NULL(readout, false);
+
+    pmDetEff *de = pmDetEffRead(fits, extname);
+    if (!de) {
+        if (psErrorCodeLast() != PS_ERR_NONE) {
+            return false;
+        }
+        return true;
+    }
+
+    return psMetadataAddPtr(readout->analysis, PS_LIST_TAIL, PM_DETEFF_ANALYSIS,
+                            PS_META_REPLACE | PS_DATA_UNKNOWN, "Detection efficiency", de);
+}
Index: /branches/pap/psModules/src/objects/pmDetEff.h
===================================================================
--- /branches/pap/psModules/src/objects/pmDetEff.h	(revision 25330)
+++ /branches/pap/psModules/src/objects/pmDetEff.h	(revision 25331)
@@ -4,4 +4,6 @@
 #include <pslib.h>
 #include <string.h>
+
+#include "pmFPA.h"
 
 #define PM_DETEFF_ANALYSIS "DETEFF"     // Location of detection efficiency on pmReadout.analysis
@@ -26,4 +28,5 @@
                         );
 
+/// Write detection efficiency to FITS file
 bool pmDetEffWrite(psFits *fits,        // FITS file to which to write
                    pmDetEff *deteff,    // Detection efficiency to write
@@ -32,7 +35,21 @@
                    );
 
+/// Write detection efficiency from a readout to a FITS file
+bool pmReadoutWriteDetEff(psFits *fits,// FITS file to which to write
+                          const pmReadout *readout, // Readout with detection efficiency
+                          const psMetadata *header, // Header to write
+                          const char *extname // Extension name
+    );
+
+/// Read detection efficiency
 pmDetEff *pmDetEffRead(psFits *fits,    // FITS file from which to read
                        const char *extname // Extension name
                        );
+
+/// Read detection efficiency into a readout
+bool pmReadoutReadDetEff(psFits *fits,// FITS file to which to write
+                         const pmReadout *readout, // Readout with detection efficiency
+                         const char *extname // Extension name
+    );
 
 #define PM_ASSERT_DETEFF_NON_NULL(DE, RETURN) { \
Index: /branches/pap/psModules/src/objects/pmSourceIO.c
===================================================================
--- /branches/pap/psModules/src/objects/pmSourceIO.c	(revision 25330)
+++ /branches/pap/psModules/src/objects/pmSourceIO.c	(revision 25331)
@@ -42,8 +42,82 @@
 #include "pmSource.h"
 #include "pmModelClass.h"
+#include "pmDetEff.h"
 #include "pmSourceIO.h"
 
 #define BLANK_HEADERS "BLANK.HEADERS"   // Name of metadata in camera configuration containing header names
                                         // for putting values into a blank PHU
+
+// lookup the EXTNAME values used for table data and image header segments
+static bool sourceExtensions(psString *headname, // Extension name for header
+                             psString *dataname, // Extension name for data
+                             psString *deteffname, // Extension name for detection efficiency
+                             psString *xsrcname, // Extension name for extended sources
+                             psString *xfitname, // Extension name for extended fits
+                             const pmFPAfile *file, // File of interest
+                             const pmFPAview *view // View to level of interest
+                             )
+{
+    bool status;                        // Status of MD lookup
+
+    // Menu of EXTNAME rules
+    psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
+    if (!menu) {
+        psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
+        return false;
+    }
+
+    // EXTNAME for image header
+    if (headname) {
+        const char *rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
+            return false;
+        }
+        *headname = pmFPAfileNameFromRule(rule, file, view);
+    }
+
+    // EXTNAME for table data
+    if (dataname) {
+        const char *rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
+            return false;
+        }
+        *dataname = pmFPAfileNameFromRule(rule, file, view);
+    }
+
+    // EXTNAME for detection efficiency
+    if (deteffname) {
+        const char *rule = psMetadataLookupStr(&status, menu, "CMF.DETEFF");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DETEFF in EXTNAME.RULES in camera.config");
+            return false;
+        }
+        *deteffname = pmFPAfileNameFromRule(rule, file, view);
+    }
+
+    // EXTNAME for extended source data table
+    if (xsrcname) {
+        const char *rule = psMetadataLookupStr(&status, menu, "CMF.XSRC");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XSRC in EXTNAME.RULES in camera.config");
+            return false;
+        }
+        *xsrcname = pmFPAfileNameFromRule (rule, file, view);
+    }
+
+    if (xfitname) {
+        // EXTNAME for extended source data table
+        const char *rule = psMetadataLookupStr(&status, menu, "CMF.XFIT");
+        if (!rule) {
+            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XFIT in EXTNAME.RULES in camera.config");
+            return false;
+        }
+        *xfitname = pmFPAfileNameFromRule (rule, file, view);
+    }
+
+    return true;
+}
+
 
 // translations between psphot object types and dophot object types
@@ -271,8 +345,4 @@
 
     char *exttype  = NULL;
-    char *dataname = NULL;
-    char *xsrcname = NULL;
-    char *xfitname = NULL;
-    char *headname = NULL;
 
     // if sources is NULL, write out an empty table
@@ -354,49 +424,12 @@
 
         // define the EXTNAME values for the different data segments:
-        {
-            // lookup the EXTNAME values used for table data and image header segments
-            char *rule = NULL;
-
-            // Menu of EXTNAME rules
-            psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
-            if (!menu) {
-                psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
-                return false;
-            }
-
-            // EXTNAME for image header
-            rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
-            if (!rule) {
-                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
-                return false;
-            }
-            headname = pmFPAfileNameFromRule (rule, file, view);
-
-            // EXTNAME for table data
-            rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
-            if (!rule) {
-                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
-                return false;
-            }
-            dataname = pmFPAfileNameFromRule (rule, file, view);
-
-            if (XSRC_OUTPUT) {
-              // EXTNAME for extended source data table
-              rule = psMetadataLookupStr(&status, menu, "CMF.XSRC");
-              if (!rule) {
-                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XSRC in EXTNAME.RULES in camera.config");
-                return false;
-              }
-              xsrcname = pmFPAfileNameFromRule (rule, file, view);
-            }
-            if (XFIT_OUTPUT) {
-              // EXTNAME for extended source data table
-              rule = psMetadataLookupStr(&status, menu, "CMF.XFIT");
-              if (!rule) {
-                psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XFIT in EXTNAME.RULES in camera.config");
-                return false;
-              }
-              xfitname = pmFPAfileNameFromRule (rule, file, view);
-            }
+        psString headname = NULL;
+        psString dataname = NULL;
+        psString deteffname = NULL;
+        psString xsrcname = NULL;
+        psString xfitname = NULL;
+        if (!sourceExtensions(&headname, &dataname, &deteffname, XSRC_OUTPUT ? &xsrcname : NULL,
+                              XFIT_OUTPUT ? &xfitname : NULL, file, view)) {
+            return false;
         }
 
@@ -480,49 +513,54 @@
 
             // XXX these are case-sensitive since the EXTYPE is case-sensitive
-            status = false;
+            status = true;
             if (!strcmp (exttype, "SMPDATA")) {
-                status = pmSourcesWrite_SMPDATA (file->fits, sources, file->header, outhead, dataname);
+                status &= pmSourcesWrite_SMPDATA (file->fits, sources, file->header, outhead, dataname);
             }
             if (!strcmp (exttype, "PS1_DEV_0")) {
-                status = pmSourcesWrite_PS1_DEV_0 (file->fits, sources, file->header, outhead, dataname);
+                status &= pmSourcesWrite_PS1_DEV_0 (file->fits, sources, file->header, outhead, dataname);
             }
             if (!strcmp (exttype, "PS1_DEV_1")) {
-                status = pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname);
+                status &= pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname);
             }
             if (!strcmp (exttype, "PS1_CAL_0")) {
-                status = pmSourcesWrite_PS1_CAL_0 (file->fits, readout, sources, file->header, outhead, dataname);
+                status &= pmSourcesWrite_PS1_CAL_0 (file->fits, readout, sources, file->header, outhead, dataname);
             }
             if (!strcmp (exttype, "PS1_V1")) {
-                status = pmSourcesWrite_CMF_PS1_V1 (file->fits, readout, sources, file->header, outhead, dataname);
+                status &= pmSourcesWrite_CMF_PS1_V1 (file->fits, readout, sources, file->header, outhead, dataname);
             }
             if (!strcmp (exttype, "PS1_V2")) {
-                status = pmSourcesWrite_CMF_PS1_V2 (file->fits, readout, sources, file->header, outhead, dataname);
-            }
+                status &= pmSourcesWrite_CMF_PS1_V2 (file->fits, readout, sources, file->header, outhead, dataname);
+            }
+
+            if (deteffname) {
+                status &= pmReadoutWriteDetEff(file->fits, readout, outhead, deteffname);
+            }
+
             if (xsrcname) {
               if (!strcmp (exttype, "PS1_DEV_1")) {
-                  status = pmSourcesWrite_PS1_DEV_1_XSRC (file->fits, sources, xsrcname, recipe);
+                  status &= pmSourcesWrite_PS1_DEV_1_XSRC (file->fits, sources, xsrcname, recipe);
               }
               if (!strcmp (exttype, "PS1_CAL_0")) {
-                  status = pmSourcesWrite_PS1_CAL_0_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
+                  status &= pmSourcesWrite_PS1_CAL_0_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
               }
               if (!strcmp (exttype, "PS1_V1")) {
-                  status = pmSourcesWrite_CMF_PS1_V1_XSRC (file->fits, sources, xsrcname, recipe);
+                  status &= pmSourcesWrite_CMF_PS1_V1_XSRC (file->fits, sources, xsrcname, recipe);
               }
               if (!strcmp (exttype, "PS1_V2")) {
-                  status = pmSourcesWrite_CMF_PS1_V2_XSRC (file->fits, sources, xsrcname, recipe);
+                  status &= pmSourcesWrite_CMF_PS1_V2_XSRC (file->fits, sources, xsrcname, recipe);
               }
             }
             if (xfitname) {
               if (!strcmp (exttype, "PS1_DEV_1")) {
-                  status = pmSourcesWrite_PS1_DEV_1_XFIT (file->fits, sources, xfitname);
+                  status &= pmSourcesWrite_PS1_DEV_1_XFIT (file->fits, sources, xfitname);
               }
               if (!strcmp (exttype, "PS1_CAL_0")) {
-                  status = pmSourcesWrite_PS1_CAL_0_XFIT (file->fits, readout, sources, file->header, xfitname);
+                  status &= pmSourcesWrite_PS1_CAL_0_XFIT (file->fits, readout, sources, file->header, xfitname);
               }
               if (!strcmp (exttype, "PS1_V1")) {
-                  status = pmSourcesWrite_CMF_PS1_V1_XFIT (file->fits, sources, xfitname);
+                  status &= pmSourcesWrite_CMF_PS1_V1_XFIT (file->fits, sources, xfitname);
               }
               if (!strcmp (exttype, "PS1_V2")) {
-                  status = pmSourcesWrite_CMF_PS1_V2_XFIT (file->fits, sources, xfitname);
+                  status &= pmSourcesWrite_CMF_PS1_V2_XFIT (file->fits, sources, xfitname);
               }
             }
@@ -572,6 +610,6 @@
     // not needed if only one chip
     if (file->fpa->chips->n == 1) {
-	pmSourceIO_WriteMatchedRefs (file->fits, file->fpa, config);
-	return true;
+        pmSourceIO_WriteMatchedRefs (file->fits, file->fpa, config);
+        return true;
     }
 
@@ -885,26 +923,11 @@
         hdu = pmFPAviewThisHDU (view, file->fpa);
 
-        // lookup the EXTNAME values used for table data and image header segments
-        char *rule = NULL;
-        // Menu of EXTNAME rules
-        psMetadata *menu = psMetadataLookupMetadata(&status, file->camera, "EXTNAME.RULES");
-        if (!menu) {
-            psError(PS_ERR_UNKNOWN, true, "missing EXTNAME.RULES in camera.config");
-            return false;
-        }
-        // EXTNAME for image header
-        rule = psMetadataLookupStr(&status, menu, "CMF.HEAD");
-        if (!rule) {
-            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.HEAD in EXTNAME.RULES in camera.config");
-            return false;
-        }
-        char *headname = pmFPAfileNameFromRule (rule, file, view);
-        // EXTNAME for table data
-        rule = psMetadataLookupStr(&status, menu, "CMF.DATA");
-        if (!rule) {
-            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.DATA in EXTNAME.RULES in camera.config");
-            return false;
-        }
-        char *dataname = pmFPAfileNameFromRule (rule, file, view);
+        // define the EXTNAME values for the different data segments:
+        psString headname = NULL;
+        psString dataname = NULL;
+        psString deteffname = NULL;
+        if (!sourceExtensions(&headname, &dataname, &deteffname, NULL, NULL, file, view)) {
+            return false;
+        }
 
         // advance to the IMAGE HEADER extension
@@ -958,4 +981,9 @@
                 sources = pmSourcesRead_CMF_PS1_V2 (file->fits, hdu->header);
             }
+
+            if (!pmReadoutReadDetEff(file->fits, readout, deteffname)) {
+                psError(PS_ERR_IO, false, "Unable to read detection efficiency");
+                return false;
+            }
         }
 
@@ -1070,3 +1098,3 @@
 }
 
-    
+
