Index: trunk/ippScripts/scripts/staticsky.pl
===================================================================
--- trunk/ippScripts/scripts/staticsky.pl	(revision 33689)
+++ trunk/ippScripts/scripts/staticsky.pl	(revision 33690)
@@ -89,5 +89,5 @@
 
 my $logDest = $ipprc->filename("LOG.EXP", $outroot);
-$ipprc->redirect_output($logDest) or my_die( "Unable to redirect output", $sky_id, $PS_EXIT_SYS_ERROR ) if $redirect;
+$ipprc->redirect_to_logfile($logDest) or my_die( "Unable to redirect output", $sky_id, $PS_EXIT_SYS_ERROR ) if $redirect;
 
 my $traceDest      = $ipprc->filename("TRACE.EXP", $outroot);
@@ -148,8 +148,10 @@
             my $maskCnv   = $ipprc->filename("PPSTACK.OUTPUT.MASK",     $path_base ); # Mask name
             my $weightCnv = $ipprc->filename("PPSTACK.OUTPUT.VARIANCE", $path_base ); # Weight name
+            my $expnumCnv = $ipprc->filename("PPSTACK.OUTPUT.EXPNUM",   $path_base ); # Expnum name
 
             my $imageRaw  = $ipprc->filename("PPSTACK.UNCONV",          $path_base ); # Image name
             my $maskRaw   = $ipprc->filename("PPSTACK.UNCONV.MASK",     $path_base ); # Mask name
             my $weightRaw = $ipprc->filename("PPSTACK.UNCONV.VARIANCE", $path_base ); # Weight name
+            my $expnumRaw = $ipprc->filename("PPSTACK.UNCONV.EXPNUM",   $path_base ); # Expnum name
 
             my $sources   = $ipprc->filename("PSPHOT.OUT.CMF.MEF",      $path_base ); # Sources name
@@ -162,7 +164,9 @@
             &my_die("Couldn't find input: $maskRaw",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$maskRaw");
             &my_die("Couldn't find input: $weightRaw", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$weightRaw");
+            &my_die("Couldn't find input: $expnumRaw", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$expnumRaw");
             &my_die("Couldn't find input: $imageCnv",  $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$imageCnv");
             &my_die("Couldn't find input: $maskCnv",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$maskCnv");
             &my_die("Couldn't find input: $weightCnv", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$weightCnv");
+            &my_die("Couldn't find input: $expnumCnv", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$expnumCnv");
             &my_die("Couldn't find input: $psfCnv",    $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$psfCnv");
             &my_die("Couldn't find input: $sources",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$sources");
@@ -171,8 +175,10 @@
             print $listFile "  RAW:MASK      STR  " . $maskRaw   . "\n";
             print $listFile "  RAW:VARIANCE  STR  " . $weightRaw . "\n";
+            print $listFile "  RAW:EXPNUM    STR  " . $expnumRaw . "\n";
 
             print $listFile "  CNV:IMAGE     STR  " . $imageCnv  . "\n";
             print $listFile "  CNV:MASK      STR  " . $maskCnv   . "\n";
             print $listFile "  CNV:VARIANCE  STR  " . $weightCnv . "\n";
+            print $listFile "  CNV:EXPNUM    STR  " . $expnumCnv . "\n";
             print $listFile "  CNV:PSF       STR  " . $psfCnv    . "\n";
 
@@ -288,5 +294,5 @@
         my $use_raw = metadataLookupBool($recipeData, 'PSPHOT.STACK.USE.RAW');
 
-        my ($image, $mask, $variance);
+        my ($image, $mask, $variance, $expnum);
         if ($use_raw) {
             $image  = $ipprc->filename("PPSTACK.UNCONV",          $path_base ); # Image name
@@ -297,4 +303,5 @@
             $mask   = $ipprc->filename("PPSTACK.OUTPUT.MASK",     $path_base ); # Mask name
             $variance = $ipprc->filename("PPSTACK.OUTPUT.VARIANCE", $path_base ); # Weight name
+            $expnum = $ipprc->filename("PPSTACK.OUTPUT.EXPNUM", $path_base ); # Weight name
         }
 
@@ -306,4 +313,5 @@
         &my_die("Couldn't find input: $mask",   $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$mask");
         &my_die("Couldn't find input: $variance", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$variance");
+        &my_die("Couldn't find input: $expnum", $sky_id, $PS_EXIT_SYS_ERROR) unless $ipprc->file_exists("$expnum");
 
         # Perform stack photometry analysis
@@ -313,4 +321,5 @@
             $command .= " -mask $mask";
             $command .= " -variance $variance";
+            $command .= " -expnum $expnum";
             $command .= " -threads $threads" if defined $threads;
             $command .= " -recipe PSPHOT  $recipe_psphot";
Index: trunk/ippconfig/recipes/filerules-split.mdc
===================================================================
--- trunk/ippconfig/recipes/filerules-split.mdc	(revision 33689)
+++ trunk/ippconfig/recipes/filerules-split.mdc	(revision 33690)
@@ -74,5 +74,5 @@
 PSPHOT.INPUT.CMF          INPUT    @FILES        CHIP       CMF       
 PSPHOT.INPUT.TEXT         INPUT    @FILES        CHIP       SRCTEXT       
-PSPHOT.EXPNUM             INPUT    @FILES        CHIP       MASK
+PSPHOT.EXPNUM             INPUT    @FILES        CHIP       EXPNUM
 
 ## files used by psphotStack
@@ -80,8 +80,10 @@
 PSPHOT.STACK.MASK.RAW     INPUT    @FILES        CHIP       MASK     
 PSPHOT.STACK.VARIANCE.RAW INPUT    @FILES        CHIP       VARIANCE     
+PSPHOT.STACK.EXPNUM.RAW   INPUT    @FILES        CHIP       EXPNUM     
 PSPHOT.STACK.PSF.RAW      INPUT    @FILES        CHIP       PSF       
 PSPHOT.STACK.INPUT.CNV    INPUT    @FILES        CHIP       IMAGE
 PSPHOT.STACK.MASK.CNV     INPUT    @FILES        CHIP       MASK     
 PSPHOT.STACK.VARIANCE.CNV INPUT    @FILES        CHIP       VARIANCE     
+PSPHOT.STACK.EXPNUM.CNV   INPUT    @FILES        CHIP       EXPNUM     
 PSPHOT.STACK.PSF.CNV      INPUT    @FILES        CHIP       PSF       
 PSPHOT.STACK.SOURCES      INPUT    @FILES        FPA        CMF
Index: trunk/psModules/src/camera/Makefile.am
===================================================================
--- trunk/psModules/src/camera/Makefile.am	(revision 33689)
+++ trunk/psModules/src/camera/Makefile.am	(revision 33690)
@@ -30,5 +30,6 @@
 	pmReadoutStack.c \
 	pmReadoutFake.c \
-	pmFPABin.c
+	pmFPABin.c \
+	pmFPAExpNumIO.c
 
 pkginclude_HEADERS = \
@@ -59,5 +60,6 @@
 	pmReadoutStack.h \
 	pmReadoutFake.h \
-	pmFPABin.h
+	pmFPABin.h \
+	pmFPAExpNumIO.h
 
 CLEANFILES = *~
Index: trunk/psModules/src/camera/pmFPAExpNumIO.c
===================================================================
--- trunk/psModules/src/camera/pmFPAExpNumIO.c	(revision 33690)
+++ trunk/psModules/src/camera/pmFPAExpNumIO.c	(revision 33690)
@@ -0,0 +1,450 @@
+#include <stdio.h>
+#include <pslib.h>
+#include <string.h>
+
+#include "pmHDU.h"
+#include "pmHDUUtils.h"
+#include "pmFPA.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+#include "pmFPAfileFitsIO.h"
+#include "pmFPAHeader.h"
+#include "pmConceptsRead.h"
+#include "pmConceptsWrite.h"
+
+#include "pmFPAExpNumIO.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+static bool pmReadoutReadExpNum(pmReadout *ro, psFits *fits)
+{
+    PM_ASSERT_READOUT_NON_NULL(ro, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    pmCell *cell = ro->parent;          // Cell of interest
+    if (!cell) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "No cell associated with readout.");
+        return false;
+    }
+    pmChip *chip = cell->parent;    // Chip of interest
+    pmFPA *fpa = chip->parent;      // FPA of interest
+    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // HDU for readout
+    if (!hdu) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "No HDU associated with readout.");
+        return false;
+    }
+
+#ifdef notdef
+    if (!psFitsMoveExtName(fits, hdu->extname)) {
+        psError(PS_ERR_IO, false, "Unable to move to EXPNUM image.");
+        return false;
+    }
+#endif
+    psMetadata *header = psFitsReadHeader(NULL, fits); // Header
+    if (!header) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to read header for EXPNUM image.");
+        return false;
+    }
+
+    bool data = false;                  // Did we find any data?
+
+    int naxis = psMetadataLookupS32(NULL, header, "NAXIS"); // Number of axes
+    if (naxis > 0) {
+        psImage *expnum = psFitsReadImage(fits, psRegionSet(0, 0, 0, 0), 0);
+        psMetadataAddImage(ro->analysis, PS_LIST_TAIL, "EXPNUM", PS_META_REPLACE,
+                           "EXPNUM", expnum);
+        psFree(expnum);
+        data = true;
+    }
+
+    if (data) {
+        ro->data_exists = true;
+        ro->parent->data_exists = true;
+        ro->parent->parent->data_exists = true;
+    }
+
+    psFree(header);
+
+    return true;
+}
+
+static bool pmCellReadExpNum(pmCell *cell, const pmFPAview *view,
+                              pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc(view->nRows); // Copy of input view
+    *thisView = *view;
+
+    // Create a readout if none exists
+    if (!cell->readouts || cell->readouts->n == 0) {
+        pmReadout *readout = pmReadoutAlloc(cell); // New readout
+        psFree(readout);                // Drop reference
+    }
+
+    cell->data_exists = false;
+    for (int i = 0; i < cell->readouts->n; i++) {
+        pmReadout *readout = cell->readouts->data[i];
+        thisView->readout = i;
+        if (!pmReadoutReadExpNum(readout, file->fits)) {
+            psError(PS_ERR_IO, false, "Unable to read pattern correction.");
+            return false;
+        }
+    }
+    psFree(thisView);
+
+    if (!pmCellReadHeader(cell, file->fits, config)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell.");
+        return false;
+    }
+    // load in the concept information for this cell
+    if (!pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, true, NULL)) {
+        psErrorClear();
+        psWarning("Difficulty reading concepts for cell; attempting to proceed.");
+    }
+
+    return true;
+}
+
+static bool pmChipReadExpNum(pmChip *chip, const pmFPAview *view,
+                              pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc(view->nRows); // Copy of input view
+    *thisView = *view;
+
+    chip->data_exists = false;
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        thisView->cell = i;
+        pmCellReadExpNum(cell, thisView, file, config);
+        if (!cell->data_exists) {
+            continue;
+        }
+        chip->data_exists = true;
+    }
+    psFree(thisView);
+
+    if (!pmChipReadHeader(chip, file->fits, config)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell.");
+        return false;
+    }
+    if (!pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_HEADER, true, true, NULL)) {
+        psError(PS_ERR_IO, false, "Failed to read concepts for chip.\n");
+        return false;
+    }
+
+    return true;
+}
+
+static bool pmFPAReadExpNum(pmFPA *fpa, const pmFPAview *view,
+                             pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa->chips, false);
+
+    pmFPAview *thisView = pmFPAviewAlloc(view->nRows); // Copy of input view
+    *thisView = *view;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        thisView->chip = i;
+        pmChipReadExpNum(chip, thisView, file, config);
+    }
+    psFree(thisView);
+
+    if (!pmFPAReadHeader(fpa, file->fits, config)) {
+        psError(PS_ERR_IO, false, "Unable to read header for cell.");
+        return false;
+    }
+    if (!pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER, true, NULL)) {
+        psError(PS_ERR_IO, false, "Failed to read concepts for fpa.\n");
+        return false;
+    }
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool pmExpNumRead(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmFPA *fpa = file->fpa;
+
+    if (view->chip == -1) {
+        pmFPAReadExpNum(fpa, view, file, config);
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        pmChipReadExpNum(chip, view, file, config);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        pmCellReadExpNum(cell, view, file, config);
+        return true;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    return pmReadoutReadExpNum(readout, file->fits);
+}
+#ifdef notyet
+// Currently only ppStack writes an EXPNUM image and it uses file type MASK
+bool pmReadoutWriteExpNum(pmReadout *ro, psFits *fits)
+{
+    PM_ASSERT_READOUT_NON_NULL(ro, false);
+    PS_ASSERT_FITS_NON_NULL(fits, false);
+
+    bool gotRow, gotCell;
+    psImage *rowCorr = psMetadataLookupPtr(&gotRow, ro->analysis, PM_PATTERN_ROW_CORRECTION); // Row correction
+    float cellCorr = psMetadataLookupF32(&gotCell, ro->analysis, PM_PATTERN_CELL_CORRECTION); // Cell corr.
+
+    pmCell *cell = ro->parent;          // Cell of interest
+    if (!cell) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "No cell associated with readout.");
+        return false;
+    }
+    pmChip *chip = cell->parent;    // Chip of interest
+    pmFPA *fpa = chip->parent;      // FPA of interest
+    pmHDU *hdu = pmHDUGetLowest(fpa, chip, cell); // HDU for readout
+    if (!hdu) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "No HDU associated with readout.");
+        return false;
+    }
+
+    psMetadata *header = psMetadataCopy(NULL, hdu->header); // Header for output
+
+    if (gotCell) {
+        psMetadataAddF32(header, PS_LIST_TAIL, PM_PATTERN_CELL_CORRECTION, PS_META_REPLACE,
+                         "ExpNum cell correction value", cellCorr);
+    }
+
+    if (gotRow) {
+        if (!psFitsWriteImage(fits, header, rowCorr, 0, hdu->extname)) {
+            psError(PS_ERR_IO, false, "Unable to write pattern row correction.");
+            psFree(header);
+            return false;
+        }
+    } else {
+        if (!psFitsWriteBlank(fits, header, hdu->extname)) {
+            psError(PS_ERR_IO, false, "Unable to write pattern cell correction.");
+            psFree(header);
+            return false;
+        }
+    }
+
+    psFree(header);
+    return true;
+}
+
+static bool pmCellWriteExpNum(pmCell *cell, const pmFPAview *view,
+                               pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    PS_ASSERT_PTR_NON_NULL(cell->readouts, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    if (!pmConceptsWriteCell(cell, true, config)) {
+        psError(PS_ERR_IO, false, "Unable to write concepts for cell.");
+        return false;
+    }
+
+    // Only do the FIRST readout --- don't want to write lots of headers
+    pmReadout *readout = cell->readouts->data[0];
+    if (!pmReadoutWriteExpNum(readout, file->fits)) {
+        psError(PS_ERR_IO, false, "Failed to write readout");
+        return false;
+    }
+    return true;
+}
+
+static bool pmChipWriteExpNum(pmChip *chip, const pmFPAview *view,
+                               pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    PS_ASSERT_PTR_NON_NULL(chip->cells, false);
+    PS_ASSERT_PTR_NON_NULL(view, false);
+
+    if (!pmConceptsWriteChip(chip, true, true, config)) {
+        psError(PS_ERR_IO, false, "Unable to write concepts for chip.\n");
+        return false;
+    }
+
+    pmFPAview *thisView = pmFPAviewAlloc(view->nRows); // Copy of input view
+    *thisView = *view;
+
+    for (int i = 0; i < chip->cells->n; i++) {
+        pmCell *cell = chip->cells->data[i];
+        thisView->cell = i;
+        if (!pmCellWriteExpNum(cell, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth cell", i);
+            psFree(thisView);
+            return false;
+        }
+    }
+    psFree(thisView);
+    return true;
+}
+
+static bool pmFPAWriteExpNum(pmFPA *fpa, const pmFPAview *view,
+                              pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    PS_ASSERT_PTR_NON_NULL(fpa->chips, false);
+
+    if (!pmConceptsWriteFPA(fpa, true, config)) {
+        psError(PS_ERR_IO, false, "Unable to write concepts for FPA.\n");
+        return false;
+    }
+
+    pmFPAview *thisView = pmFPAviewAlloc(view->nRows); // Copy of input view
+    *thisView = *view;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+        pmChip *chip = fpa->chips->data[i];
+        thisView->chip = i;
+        if (!pmChipWriteExpNum(chip, thisView, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write %dth chip", i);
+            psFree(thisView);
+            return false;
+        }
+    }
+    psFree(thisView);
+    return true;
+}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Currently only ppStack writes an EXPNUM image and it uses file type MASK
+bool pmExpNumWrite(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+    PS_ASSERT_PTR_NON_NULL(file->fpa, false);
+
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+
+    if (view->chip == -1) {
+        if (!pmFPAWriteExpNum(fpa, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write pattern correction from fpa");
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing chip == %d (>= chips->n == %ld)", view->chip, fpa->chips->n);
+        psFree(fpa);
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        if (!pmChipWriteExpNum(chip, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write pattern correction from chip");
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing cell == %d (>= cells->n == %ld)",
+                view->cell, chip->cells->n);
+        psFree(fpa);
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        if (!pmCellWriteExpNum(cell, view, file, config)) {
+            psError(PS_ERR_IO, false, "Failed to write pattern correction from cell");
+            psFree(fpa);
+            return false;
+        }
+        psFree(fpa);
+        return true;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        psError(PS_ERR_UNKNOWN, false, "Writing readout == %d (>= readouts->n == %ld)",
+                view->readout, cell->readouts->n);
+        psFree(fpa);
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    if (!pmReadoutWriteExpNum(readout, file->fits)) {
+        psError(PS_ERR_IO, false, "Failed to write pattern correction from readout %d", view->readout);
+        psFree(fpa);
+        return false;
+    }
+
+    psFree(fpa);
+    return true;
+}
+
+bool pmExpNumWritePHU(const pmFPAview *view, pmFPAfile *file, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(view, false);
+    PS_ASSERT_PTR_NON_NULL(file, false);
+
+    if (file->wrote_phu) {
+        return true;
+    }
+
+    // find the FPA phu
+    pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config, false); // Suitable FPA for writing
+    pmHDU *phu = psMemIncrRefCounter(pmFPAviewThisPHU(view, fpa));
+    psFree(fpa);
+
+    // if there is no PHU, this is a single header+image (extension-less) file. This could be the case for an
+    // input SPLIT set of files being written out as a MEF.  if there is a PHU, write it out as a 'blank'
+    psMetadata *outhead = psMetadataAlloc();
+    if (phu) {
+        psMetadataCopy (outhead, phu->header);
+    }
+    psFree(phu);
+
+    pmConfigConformHeader(outhead, file->format);
+
+    psFitsWriteBlank(file->fits, outhead, "");
+    file->wrote_phu = true;
+
+    psTrace("pmFPAfile", 5, "wrote phu %s (type: %d)\n", file->filename, file->type);
+    psFree(outhead);
+
+    return true;
+}
+#endif // notyet
+
Index: trunk/psModules/src/camera/pmFPAExpNumIO.h
===================================================================
--- trunk/psModules/src/camera/pmFPAExpNumIO.h	(revision 33690)
+++ trunk/psModules/src/camera/pmFPAExpNumIO.h	(revision 33690)
@@ -0,0 +1,36 @@
+#ifndef PM_EXPNUM_IO_H
+#define PM_EXPNUM_IO_H
+
+#include <pslib.h>
+
+#include <pmHDU.h>
+#include <pmFPA.h>
+
+
+bool pmExpNumRead(const pmFPAview *view, ///< View into which to read
+                   pmFPAfile *file, ///< File from which to read
+                   pmConfig *config ///< Configuration
+    );
+
+#ifdef notyet
+// Currently we don't need write functions for the EXPNUM images. 
+// Only ppStack creates them and it uses a MASK file type
+
+/// Write pattern correction within a readout to a FITS file
+bool pmReadoutWritePattern(
+    pmReadout *readout,                 ///< Readout for which to write pattern correction (in analysis MD)
+    psFits *fits                        ///< FITS file to which to write
+    );
+bool pmPatternWrite(const pmFPAview *view, ///< View from which to write
+                    pmFPAfile *file, ///< File to which to write
+                    pmConfig *config ///< Configuration
+    );
+
+bool pmPatternWritePHU(const pmFPAview *view, // View to PHU
+                       pmFPAfile *file, ///< File to which to write
+                       pmConfig *config ///< Configuration
+    );
+
+#endif // notyet
+
+#endif
Index: trunk/psModules/src/camera/pmFPAfile.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfile.c	(revision 33689)
+++ trunk/psModules/src/camera/pmFPAfile.c	(revision 33690)
@@ -543,4 +543,7 @@
     if (!strcasecmp(type, "PATTERN")) {
         return PM_FPA_FILE_PATTERN;
+    }
+    if (!strcasecmp(type, "EXPNUM")) {
+        return PM_FPA_FILE_EXPNUM;
     }
 
@@ -589,4 +592,6 @@
       case PM_FPA_FILE_PATTERN:
         return "PATTERN";
+      case PM_FPA_FILE_EXPNUM:
+        return "EXPNUM";
       default:
         return ("NONE");
Index: trunk/psModules/src/camera/pmFPAfile.h
===================================================================
--- trunk/psModules/src/camera/pmFPAfile.h	(revision 33689)
+++ trunk/psModules/src/camera/pmFPAfile.h	(revision 33690)
@@ -51,4 +51,5 @@
     PM_FPA_FILE_PATTERN,
     PM_FPA_FILE_LINEARITY,
+    PM_FPA_FILE_EXPNUM,
 } pmFPAfileType;
 
Index: trunk/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileIO.c	(revision 33689)
+++ trunk/psModules/src/camera/pmFPAfileIO.c	(revision 33690)
@@ -53,4 +53,5 @@
 #include "pmSubtractionIO.h"
 #include "pmPatternIO.h"
+#include "pmFPAExpNumIO.h"
 #include "pmConcepts.h"
 #include "pmConfigRun.h"
@@ -231,4 +232,7 @@
         status = pmAstromModelReadForView (view, file, config);
         break;
+      case PM_FPA_FILE_EXPNUM:
+        status = pmExpNumRead(view, file, config);
+        break;
       case PM_FPA_FILE_ASTROM_REFSTARS:
       case PM_FPA_FILE_JPEG:
@@ -291,4 +295,5 @@
       case PM_FPA_FILE_DARK:
       case PM_FPA_FILE_PATTERN:
+      case PM_FPA_FILE_EXPNUM:
         {
             // create FPA structure component based on view
@@ -500,4 +505,9 @@
         status = pmFPAviewWriteSourcePlot (view, file, config);
         break;
+
+      case PM_FPA_FILE_EXPNUM:
+        // when ppStack output's EXPNUM file it uses a file rule where the file type is MASK
+        psError(PS_ERR_IO, true, "cannot write type EXPNUM (%s)", file->name);
+        return false;
 
       case PM_FPA_FILE_WCS:
@@ -562,4 +572,5 @@
       case PM_FPA_FILE_ASTROM_REFSTARS:
       case PM_FPA_FILE_LINEARITY:
+      case PM_FPA_FILE_EXPNUM:
         psTrace ("psModules.camera", 5, "closing %s (%s) (%d:%d:%d)\n", file->filename, file->name, view->chip, view->cell, view->readout);
         status = psFitsClose (file->fits);
@@ -636,4 +647,5 @@
       case PM_FPA_FILE_ASTROM_MODEL:
       case PM_FPA_FILE_ASTROM_REFSTARS:
+      case PM_FPA_FILE_EXPNUM:
         psTrace ("psModules.camera", 6, "NOT freeing %s (%s) : save for further analysis\n", file->filename, file->name);
         return true;
@@ -797,4 +809,5 @@
       case PM_FPA_FILE_ASTROM_REFSTARS:
       case PM_FPA_FILE_LINEARITY:
+      case PM_FPA_FILE_EXPNUM:
         psTrace ("psModules.camera", 5, "opening %s (%s) (%d:%d:%d)\n",
                  file->filename, file->name, view->chip, view->cell, view->readout);
@@ -996,4 +1009,5 @@
         status = pmAstromRefstarsWritePHU (view, file, config);
         break;
+      case PM_FPA_FILE_EXPNUM:
       case PM_FPA_FILE_ASTROM_MODEL:
       case PM_FPA_FILE_SX:
Index: trunk/psModules/src/objects/pmSource.c
===================================================================
--- trunk/psModules/src/objects/pmSource.c	(revision 33689)
+++ trunk/psModules/src/objects/pmSource.c	(revision 33690)
@@ -160,4 +160,5 @@
     source->parent = NULL;
     source->imageID = -1;
+    source->nFrames = 0;
 
     psMemSetDeallocator(source, (psFreeFunc) sourceFree);
Index: trunk/psModules/src/objects/pmSource.h
===================================================================
--- trunk/psModules/src/objects/pmSource.h	(revision 33689)
+++ trunk/psModules/src/objects/pmSource.h	(revision 33690)
@@ -118,4 +118,5 @@
     pmSource *parent;			///< reference to the master source from which this is derived
     int imageID;
+    psU16 nFrames;
 };
 
Index: trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c
===================================================================
--- trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c	(revision 33689)
+++ trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c	(revision 33690)
@@ -81,10 +81,9 @@
     }
 
-    short nImageOverlap; 
     float magOffset; 
     float zeroptErr; 
     float fwhmMajor; 
     float fwhmMinor;
-    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
+    pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
 
     table = psArrayAllocEmpty (sources->n);
@@ -161,6 +160,5 @@
         psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
 
-        // XXX not sure how to get this : need to load Nimages with weight?
-        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", nImageOverlap);
+        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", source->nFrames);
         psMetadataAdd (row, PS_LIST_TAIL, "PADDING",          PS_DATA_S16, "padding", 0);
 
Index: trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV2.c
===================================================================
--- trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV2.c	(revision 33689)
+++ trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV2.c	(revision 33690)
@@ -82,10 +82,9 @@
     table = psArrayAllocEmpty (sources->n);
 
-    short nImageOverlap; 
     float magOffset; 
     float zeroptErr; 
     float fwhmMajor; 
     float fwhmMinor;
-    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
+    pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
 
     // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
@@ -180,5 +179,5 @@
 
         // XXX not sure how to get this : need to load Nimages with weight?
-        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", nImageOverlap);
+        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", source->nFrames);
         psMetadataAdd (row, PS_LIST_TAIL, "PADDING",          PS_DATA_S16, "padding", 0);
 
Index: trunk/psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c
===================================================================
--- trunk/psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c	(revision 33689)
+++ trunk/psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c	(revision 33690)
@@ -84,10 +84,9 @@
     table = psArrayAllocEmpty (sources->n);
 
-    short nImageOverlap; 
     float magOffset; 
     float zeroptErr; 
     float fwhmMajor; 
     float fwhmMinor;
-    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
+    pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
 
     // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
@@ -170,6 +169,5 @@
         psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2",           PS_DATA_U32, "psphot analysis flags",                     source->mode2);
 
-        // XXX not sure how to get this : need to load Nimages with weight?
-        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", nImageOverlap);
+        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", source->nFrames);
         psMetadataAdd (row, PS_LIST_TAIL, "PADDING",          PS_DATA_S16, "padding", 0);
 
Index: trunk/psModules/src/objects/pmSourceOutputs.c
===================================================================
--- trunk/psModules/src/objects/pmSourceOutputs.c	(revision 33689)
+++ trunk/psModules/src/objects/pmSourceOutputs.c	(revision 33690)
@@ -40,5 +40,5 @@
 #include "pmSourceOutputs.h"
 
-bool pmSourceOutputsCommonValues (short *nImageOverlap, float *magOffset, float *zeroptErr, float *fwhmMajor, float *fwhmMinor, pmReadout *readout, psMetadata *header) {
+bool pmSourceOutputsCommonValues (float *magOffset, float *zeroptErr, float *fwhmMajor, float *fwhmMinor, pmReadout *readout, psMetadata *header) {
 
     pmFPA  *fpa  = readout->parent->parent->parent;
@@ -72,5 +72,4 @@
     }
 
-    *nImageOverlap = psMetadataLookupS32 (&status2, header, "NINPUTS");
     return true;
 
Index: trunk/psModules/src/objects/pmSourceOutputs.h
===================================================================
--- trunk/psModules/src/objects/pmSourceOutputs.h	(revision 33689)
+++ trunk/psModules/src/objects/pmSourceOutputs.h	(revision 33690)
@@ -56,5 +56,5 @@
 } pmSourceOutputsMoments;
 
-bool pmSourceOutputsCommonValues (short *nImageOverlap, float *magOffset, float *zeroptErr, float *fwhmMajor, float *fwhmMinor, pmReadout *readout, psMetadata *header);
+bool pmSourceOutputsCommonValues (float *magOffset, float *zeroptErr, float *fwhmMajor, float *fwhmMinor, pmReadout *readout, psMetadata *header);
 
 bool pmSourceOutputsSetValues (pmSourceOutputs *outputs, pmSource *source, pmChip *chip, float fwhmMajor, float fwhmMinor, float magOffset);
Index: trunk/psphot/src/Makefile.am
===================================================================
--- trunk/psphot/src/Makefile.am	(revision 33689)
+++ trunk/psphot/src/Makefile.am	(revision 33690)
@@ -206,5 +206,6 @@
         psphotPetrosianStats.c         \
         psphotPetrosianVisual.c        \
-	psphotEfficiency.c
+	psphotEfficiency.c	       \
+	psphotSetNFrames.c
 
 # re-instate these
Index: trunk/psphot/src/psphot.h
===================================================================
--- trunk/psphot/src/psphot.h	(revision 33689)
+++ trunk/psphot/src/psphot.h	(revision 33690)
@@ -481,3 +481,6 @@
 bool psphotStackObjectsSelectForAnalysis (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objects);
 
+bool psphotSetNFrames (pmConfig *config, const pmFPAview *view, const char *filerule);
+bool psphotSetNFramesReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index);
+
 #endif
Index: trunk/psphot/src/psphotArguments.c
===================================================================
--- trunk/psphot/src/psphotArguments.c	(revision 33689)
+++ trunk/psphot/src/psphotArguments.c	(revision 33690)
@@ -217,4 +217,5 @@
     pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf",      "-psflist");
     pmConfigFileSetsMD (config->arguments, &argc, argv, "SRC",        "-src",      "-srclist");
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "EXPNUM",     "-expnum",   "-expnumlist");
 
     if (argc == 1) {
Index: trunk/psphot/src/psphotKronIterate.c
===================================================================
--- trunk/psphot/src/psphotKronIterate.c	(revision 33689)
+++ trunk/psphot/src/psphotKronIterate.c	(revision 33690)
@@ -150,5 +150,5 @@
 	    if (!psphotKronIterate_Threaded(job)) {
 		psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
-		psFree(AnalysisRegion);
+		// psFree(AnalysisRegion);
 		return false;
 	    }
@@ -222,4 +222,8 @@
 	    float windowRadius = PS_MAX(RADIUS, maxWindow);
 
+#ifdef notdef
+            fprintf(stderr, "Redefining pixels for source: %d %4d %4d new radius: %f\n", 
+                                        i, source->peak->x, source->peak->y, windowRadius+2);
+#endif
 	    // re-allocate image, weight, mask arrays for each peak with box big enough to fit BIG_RADIUS
 	    pmSourceRedefinePixels (source, readout, source->peak->x, source->peak->y, windowRadius + 2);
Index: trunk/psphot/src/psphotParseCamera.c
===================================================================
--- trunk/psphot/src/psphotParseCamera.c	(revision 33689)
+++ trunk/psphot/src/psphotParseCamera.c	(revision 33690)
@@ -2,4 +2,6 @@
 
 // define the needed / desired I/O files
+
+
 bool psphotParseCamera (pmConfig *config) {
 
@@ -40,4 +42,11 @@
     }
 
+    pmFPAfileBindFromArgs (&status, input, config, "PSPHOT.EXPNUM", "EXPNUM");
+    if (!status) {
+        psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
+        return NULL;
+    }
+
+
     // define the additional input/output files associated with psphot
     if (!psphotDefineFiles (config, input)) {
Index: trunk/psphot/src/psphotSetNFrames.c
===================================================================
--- trunk/psphot/src/psphotSetNFrames.c	(revision 33690)
+++ trunk/psphot/src/psphotSetNFrames.c	(revision 33690)
@@ -0,0 +1,68 @@
+# include "psphotInternal.h"
+
+# define ESCAPE(MESSAGE) {				\
+	psError(PSPHOT_ERR_DATA, false, MESSAGE);	\
+	psFree (view);					\
+	return false;					\
+    }
+
+
+// Set source->nFrames based on the values in the EXPNUM image at the coordinates of each source's peak
+
+bool psphotSetNFrames (pmConfig *config, const pmFPAview *view, const char *filerule)
+{
+    psLogMsg ("psphot", PS_LOG_INFO, "--- psphot Set N Frames ---");
+
+    int num = psphotFileruleCount(config, filerule);
+
+    // loop over the inputs
+    for (int i = 0; i < num; i++) {
+        if (!psphotSetNFramesReadout (config, view, filerule, i)) {
+            psError (PSPHOT_ERR_CONFIG, false, "failed to set nFrames for %s entry %d", filerule, i);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool psphotSetNFramesReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index)
+{
+    bool status;
+    // find the currently selected readout
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
+    psAssert (file, "missing file?");
+
+    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
+    psAssert (readout, "missing readout?");
+
+    psImage *expnum = psMetadataLookupPtr(&status, readout->analysis, "EXPNUM");
+    if (!status || !expnum) { 
+        psLogMsg ("psphot", PS_LOG_INFO, "No EXPNUM image for input %d", index);
+        return true;
+    }
+
+    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
+    psAssert (detections, "missing detections?");
+    psAssert (detections->allSources, "missing sources?");
+
+    psArray *sources = detections->allSources;
+
+    int col0 = expnum->col0;
+    int row0 = expnum->row0;
+    int numCols = expnum->numCols;
+    int numRows = expnum->numRows;
+    
+    for (int i = 0; i < sources->n; i++) {
+        pmSource *source = sources->data[i];
+        int x = source->peak->x;
+        int y = source->peak->y;
+        if (x >= col0 && x < numCols && y >= row0 && y < numRows) {
+            source->nFrames = expnum->data.PS_TYPE_IMAGE_MASK_DATA[y][x];
+        } else {
+            source->nFrames = 0;
+        }
+    }
+
+    return true;
+}
Index: trunk/psphot/src/psphotStackArguments.c
===================================================================
--- trunk/psphot/src/psphotStackArguments.c	(revision 33689)
+++ trunk/psphot/src/psphotStackArguments.c	(revision 33690)
@@ -53,4 +53,8 @@
         psMetadataAddStr (options, PS_LIST_TAIL, "BREAK_POINT", PS_META_REPLACE, "", argv[N]);
         psArgumentRemove (N, &argc, argv);
+    }
+    if ((N = psArgumentGet (argc, argv, "-ds9regions"))) {
+        psArgumentRemove (N, &argc, argv);
+        pmSubtractionRegions(true);
     }
 
Index: trunk/psphot/src/psphotStackImageLoop.c
===================================================================
--- trunk/psphot/src/psphotStackImageLoop.c	(revision 33689)
+++ trunk/psphot/src/psphotStackImageLoop.c	(revision 33690)
@@ -30,7 +30,16 @@
     }
 
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
+    bool useRaw = psMetadataLookupBool (NULL, recipe, "PSPHOT.STACK.USE.RAW");
+    if (useRaw && inputRaw == NULL) {
+        psLogMsg ("psphot", 1, "PSPHOT.STACK.USE.RAW set but no raw input.");
+        useRaw = false;
+    }
+
     pmFPAview *view = pmFPAviewAlloc (0);
 
-    // XXX for now, just load the full set of images up front
+
+    // XXX for now, just load the full set of images up front except for EXPNUM which we defer
+    pmFPAfileActivate (config->files, false, "PSPHOT.STACK.EXPNUM.RAW");
     if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for fpa in psphot.");
 
@@ -86,6 +95,9 @@
 	UpdateHeadersForChip(config, view);
 
-	// save output which is saved at the chip level
-	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed output for Chip in psphot.");
+        // Defer output until we have performed psphotSetNFrames()
+        pmFPAfileActivate (config->files, false, NULL);
+
+	// Iterate up
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed pmFPAfileIOChecks for Chip in psphot.");
     }
     psMemDump("doneloop");
@@ -93,5 +105,36 @@
     UpdateHeadersForFPA(config, view);
 
-    // save output which is saved at the fpa level
+    // Iterate up output which is saved at the fpa level
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed ouput pmFPAfileIOChecks FPA in psphot.");
+
+    // Load the appropriate EXPNUM image
+    pmFPAfileActivate (config->files, true, useRaw ? "PSPHOT.STACK.EXPNUM.RAW" : "PSPHOT.STACK.EXPNUM.CNV");
+
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for fpa EXPNUM in psphot.");
+
+    // for psphot, we force data to be read at the chip level
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+        psLogMsg ("psphot", 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 ("failed input for Chip EXPNUM in psphotStack.");
+
+        // there is now only a single chip (multiple readouts?). loop over it and process
+        while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            psLogMsg ("psphot", 5, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+	    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Cell in psphotStack.");
+
+            // process each of the readouts
+            while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+                psLogMsg ("psphot", 6, "Readout %d: %x %x\n", view->readout, cell->file_exists, cell->process);
+                if (! readout->data_exists) { continue; }
+
+                if (!psphotSetNFrames (config, view, useRaw ? inputRaw->name : inputCnv->name)) ESCAPE ("failed to setNFrames.");
+            }
+        }
+        // now activate all files to trigger final output
+        pmFPAfileActivate (config->files, true, NULL);
+
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed output for Chip in psphot.");
+    }
     if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed ouput for FPA in psphot.");
 
Index: trunk/psphot/src/psphotStackParseCamera.c
===================================================================
--- trunk/psphot/src/psphotStackParseCamera.c	(revision 33689)
+++ trunk/psphot/src/psphotStackParseCamera.c	(revision 33690)
@@ -59,4 +59,11 @@
 		}
 	    }
+	    psString expnum = psMetadataLookupStr(&status, input, "RAW:EXPNUM"); // Name of expnum image
+	    if (expnum && strlen(expnum) > 0) {
+		if (!defineFile(config, rawInputFile, "PSPHOT.STACK.EXPNUM.RAW", expnum, PM_FPA_FILE_EXPNUM)) {
+		    psError(PS_ERR_UNKNOWN, false, "Unable to define file from expnum %d (%s)", i, expnum);
+		    return false;
+		}
+	    }
 	    nRaw ++;
 	}
@@ -81,4 +88,11 @@
 		if (!defineFile(config, cnvInputFile, "PSPHOT.STACK.VARIANCE.CNV", variance, PM_FPA_FILE_VARIANCE)) {
 		    psError(PS_ERR_UNKNOWN, false, "Unable to define file from variance %d (%s)", i, variance);
+		    return false;
+		}
+	    }
+	    psString expnum = psMetadataLookupStr(&status, input, "CNV:EXPNUM"); // Name of EXPNUM image
+	    if (expnum && strlen(expnum) > 0) {
+		if (!defineFile(config, cnvInputFile, "PSPHOT.STACK.EXPNUM.CNV", expnum, PM_FPA_FILE_EXPNUM)) {
+		    psError(PS_ERR_UNKNOWN, false, "Unable to define file from expnum %d (%s)", i, expnum);
 		    return false;
 		}
