Index: /trunk/magic/remove/src/Makefile.simple
===================================================================
--- /trunk/magic/remove/src/Makefile.simple	(revision 20339)
+++ /trunk/magic/remove/src/Makefile.simple	(revision 20340)
@@ -7,5 +7,5 @@
     Line.o
 
-CFLAGS=`psmodules-config --cflags`
+CFLAGS=`psmodules-config --cflags` -g
 LDFLAGS=`psmodules-config --libs`
 
Index: /trunk/magic/remove/src/streaks.h
===================================================================
--- /trunk/magic/remove/src/streaks.h	(revision 20339)
+++ /trunk/magic/remove/src/streaks.h	(revision 20340)
@@ -9,4 +9,5 @@
 #include "pslib.h"
 #include "psmodules.h"
+#include "nebclient.h"
 
 typedef struct {
@@ -15,8 +16,4 @@
 
 #include "streaksastrom.h"
-
-// WES file names are ipp uris usually neb:// 
-// we need to resolve these to unix file names
-// sFile is a wrapper containing the information for our files
 
 typedef struct {
@@ -71,4 +68,5 @@
     float   recoveryMaskValue;
     float   recoveryWeightValue;
+    nebServer   *nebServer;
 } streakFiles;
 
@@ -80,4 +78,6 @@
 
 #define SFILE_IS_IMAGE(_sfile) (_sfile->image || _sfile->imagecube)
+#define IN_NEBULOUS(_filename) (!strncasecmp(_filename, "neb://", strlen("neb://")))
+
 
 #endif // STREAKS_H
Index: /trunk/magic/remove/src/streaksremove.c
===================================================================
--- /trunk/magic/remove/src/streaksremove.c	(revision 20339)
+++ /trunk/magic/remove/src/streaksremove.c	(revision 20340)
@@ -6,5 +6,7 @@
 extern bool  sFileReplace(sFile *dest, sFile *src);
 
-static void bail_out(psString str, int exitCode) {
+// for clarity in this program we don't propagate errors up the stack
+// we just bail out
+void streaksremoveExit(psString str, int exitCode) {
     psErrorStackPrint(stderr, str);
     exit(exitCode);
@@ -20,10 +22,9 @@
 
 psString
-resolveName(pmConfig *config, sFile *sfile)
-{
-    // TODO: do the nebulous lookup
-    sfile->inNebulous = false;
-
-    return psStringCopy(sfile->name);
+resolveFilename(pmConfig *config, sFile *sfile, bool create)
+{
+    sfile->inNebulous = IN_NEBULOUS(sfile->name);
+
+    return pmConfigConvertFilename(sfile->name, config, create, create);
 }
 
@@ -35,35 +36,57 @@
     memset(sfile, 0, sizeof(sFile));
 
-    // if stage is raw or chip use psFits for input, if warp or diff start with FPA
-    // so we have it for astrometry
-    if ((CHIP_LEVEL_INPUT(stage)) || strcmp(fileSelect, "INPUT")) {
-        sfile->name = psMetadataLookupStr(&status, config->arguments, fileSelect);
-        if (!status || !sfile->name) {
-            if (required) {
-                psError(PS_ERR_IO, false, "Failed to lookup name for %s", fileSelect);
-                sFileFree(sfile);
-                bail_out("", 1);
-            }
-            return NULL;
-        }
-    } else {
+    // We use directly use psFits to read the image file unless the stage is warp
+    // or diff. In that case we use the pmFPAfile functions to read the image file
+    // so that it handles managing the astrometry.
+
+    if (!CHIP_LEVEL_INPUT(stage) && !strcmp(fileSelect, "INPUT")) {
         // stage is warp or diff AND fileSelect eq "INPUT"
-        // get data from pmFPAfile
+        // get data from pmFPAfile. We read the mask and weight files using psFits
+
+        // we need to know what the nebulous and real filenames are so we steal
+        // some code from pmFPAfileDefineFromArgs
+        // XXX: create a pmFPAfile function that does this and use it there
+        psArray *infiles = psMetadataLookupPtr(&status, config->arguments, "INPUT");
+        if (!status) {
+            psError(PS_ERR_PROGRAMMING, false, "INPUT not found in config->arguments");
+            streaksremoveExit("", PS_EXIT_PROG_ERROR);
+        }
+        if (infiles->n < 1) {
+            psError(PS_ERR_IO, false, "Found n == %ld files in %s in arguments\n", infiles->n, "INPUT");
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
+        }
+        sfile->name = psStringCopy(infiles->data[0]);
+        // end of file name lookup code adapted from pmFPAfileDefineFromArgs
+
+        sfile->inNebulous = IN_NEBULOUS(sfile->name);
+
         sfile->pmfile = pmFPAfileDefineFromArgs(&status, config, "PPSUB.INPUT", "INPUT");
         if (!sfile->pmfile) {
             psError(PS_ERR_IO, false, "Failed to defile file for name for %s", fileSelect);
-            bail_out("", PS_EXIT_DATA_ERROR);
-        }
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
+        }
+
+        sfile->resolved_name = psStringCopy(sfile->pmfile->filename);
         pmFPAview *view = pmFPAviewAlloc(0);
         if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
             psError(PS_ERR_UNKNOWN, false, "Failed to load input.");
-            bail_out("", PS_EXIT_DATA_ERROR);
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
         }
         psFree(view);
-        sfile->name = sfile->pmfile->filename;
-        sfile->resolved_name = psStringCopy(sfile->name);
+        
         // copy header from fpu
         sfile->header = (psMetadata*) psMemIncrRefCounter(sfile->pmfile->fpa->hdu->header);
+
         return sfile;
+    }
+
+    sfile->name = psMetadataLookupStr(&status, config->arguments, fileSelect);
+    if (!status || !sfile->name) {
+        if (required) {
+            psError(PS_ERR_IO, false, "Failed to lookup name for %s", fileSelect);
+            sFileFree(sfile);
+            streaksremoveExit("", 1);
+        }
+        return NULL;
     }
 
@@ -72,13 +95,18 @@
     if (outputExt) {
         psStringAppend(&sfile->name, outputExt);
-        sfile->resolved_name = psStringCopy(sfile->name);
+        sfile->resolved_name = resolveFilename(config, sfile, true);
+        if (!sfile->resolved_name) {
+            psError(PS_ERR_IO, false, "Failed to create file %s", sfile->name);
+            sFileFree(sfile);
+            streaksremoveExit("", 1);
+        }
         sfile->fits = psFitsOpen(sfile->resolved_name, "w");
         sfile->fits->options = psFitsOptionsAlloc();
     } else {
-        sfile->resolved_name = resolveName(config, sfile);
+        sfile->resolved_name = resolveFilename(config, sfile, false);
         if (!sfile->resolved_name) {
             psError(PS_ERR_IO, false, "Failed to resolve name for %s", sfile->name);
             sFileFree(sfile);
-            bail_out("", 1);
+            streaksremoveExit("", 1);
         }
         sfile->fits = psFitsOpen(sfile->resolved_name, "r");
@@ -92,19 +120,9 @@
                     sfile->resolved_name, outputExt ? "writing" : "reading");
         sFileFree(sfile);
-        bail_out("", 1);
+        streaksremoveExit("", 1);
     }
 
     return sfile;
 }
-
-#ifdef notyet
-        sfile->file = pmFPAfileDefineFromArgs(&status, config, name, fileSelect);
-        if (!status || !sfile->file) {
-            if (required) {
-                psError(PS_ERR_IO, false, "Failed to build FPA for %s", name);
-            }
-            return NULL;
-        }
-#endif
 
 
@@ -121,11 +139,9 @@
 
     if (sf->bilevelAstrometry) {
-#ifdef notyet
         // Do we get here for GPC1 ? I don't necessarily have an fpa for the input image
-        if (!pmAstromReadBilevelMosaic(sf->inImage->file->fpa, phu->header)) {
+        if (!pmAstromReadBilevelMosaic(sf->inAstrom->fpa, phu->header)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for input FPA.");
             return false;
         }
-#endif
     } else {
         pmHDU *hdu = pmFPAviewThisHDU(sf->view, sf->inAstrom->fpa);
@@ -150,5 +166,5 @@
     if (!pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_BEFORE)) {
         psError(PS_ERR_UNKNOWN, false, "Failed to load input.");
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
 
@@ -166,9 +182,9 @@
     if (!sf->chip) {
         psError(PS_ERR_UNKNOWN, true, "Failed to find chip with data.");
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
     if (!pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_BEFORE)) {
         psError(PS_ERR_UNKNOWN, false, "failed to load chip");
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
 
@@ -185,6 +201,5 @@
     sf->config = config;
 
-    // error checking is done by sFileOpen. If a file can't be open we
-    // exit
+    // error checking is done by sFileOpen. If a file can't be opened we just exit
     ippStage stage = psMetadataLookupS32(&status, config->arguments, "STAGE");
 
@@ -216,5 +231,5 @@
         sf->inAstrom = sf->inImage->pmfile;
         if (!sf->inImage->pmfile) {
-            bail_out("unexpected null pmFPAfile", PS_EXIT_CONFIG_ERROR);
+            streaksremoveExit("unexpected null pmFPAfile", PS_EXIT_CONFIG_ERROR);
         }
     }
@@ -269,5 +284,5 @@
         psError(PS_ERR_IO, false, 
             "failed to move to extension %d for %s", extnum, sfile->resolved_name);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
     return true;
@@ -315,5 +330,5 @@
     } else {
         psError(PS_ERR_UNKNOWN, true, "unknown stage string: %s\n", stageStr);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
         // notreached
         return IPP_STAGE_NONE;
@@ -326,5 +341,5 @@
     pmConfig *config = pmConfigRead(&argc, argv, NULL);
     if (!config) {
-        bail_out("failed to parse arguments", PS_EXIT_CONFIG_ERROR);
+        streaksremoveExit("failed to parse arguments", PS_EXIT_CONFIG_ERROR);
     }
 
@@ -384,5 +399,5 @@
     
     if (!pmConfigFileSetsMD(config->arguments, &argc, argv, "ASTROM", "-astrom", NULL)) { ;
-        if ((stage == IPP_STAGE_RAW) || (stage == IPP_STAGE_CHIP)) {
+        if (CHIP_LEVEL_INPUT(stage)) {
             psError(PS_ERR_UNKNOWN, true, "-astrom is required for raw and chip stages\n");
             return NULL;
@@ -418,4 +433,14 @@
         psError(PS_ERR_UNKNOWN, true, "-recovery is required for -stage raw\n");
         return NULL;
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-replace"))) {
+        psArgumentRemove(argnum, &argc, argv);
+        psMetadataAddBool(config->arguments, PS_LIST_TAIL, "REPLACE", 0, "replace input files",
+            true);
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-remove"))) {
+        psArgumentRemove(argnum, &argc, argv);
+        psMetadataAddBool(config->arguments, PS_LIST_TAIL, "REMOVE", 0, "remove input files",
+            true);
     }
 
@@ -432,5 +457,5 @@
         psError(PS_ERR_IO, false, "failed to read primary header from %s\n",
             sfiles->inImage->resolved_name);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
     
@@ -439,5 +464,5 @@
         psError(PS_ERR_IO, false, "failed to write primary header to %s",
             sfiles->outImage->resolved_name);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
     // TODO: add keyword indicating that this is the recovery image
@@ -445,5 +470,5 @@
         psError(PS_ERR_IO, false, "failed to write primary header to %s",
             sfiles->recImage->resolved_name);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
     psFree(imageHeader);
@@ -455,5 +480,5 @@
             psError(PS_ERR_IO, false, "failed to read primary header from %s\n",
                 sfiles->inMask->resolved_name);
-            bail_out("", 1);
+            streaksremoveExit("", 1);
         }
         // TODO: add keyword indicating that streaks have been removed
@@ -461,5 +486,5 @@
             psError(PS_ERR_IO, false, "failed to write primary header to %s",
                 sfiles->outMask->resolved_name);
-            bail_out("", PS_EXIT_DATA_ERROR);
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
         }
         // TODO: add keyword indicating that this is the recovery image
@@ -467,5 +492,5 @@
             psError(PS_ERR_IO, false, "failed to write primary header to %s",
                 sfiles->recMask->resolved_name);
-            bail_out("", PS_EXIT_DATA_ERROR);
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
         }
         psFree(maskHeader);
@@ -477,5 +502,5 @@
             psError(PS_ERR_IO, false, "failed to read primary header from %s\n",
                 sfiles->inWeight->resolved_name);
-            bail_out("", 1);
+            streaksremoveExit("", 1);
         }
         // TODO: add keyword indicating that streaks have been removed
@@ -483,5 +508,5 @@
             psError(PS_ERR_IO, false, "failed to write primary header to %s",
                 sfiles->outWeight->resolved_name);
-            bail_out("", PS_EXIT_DATA_ERROR);
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
         }
         // TODO: add keyword indicating that this is a recovery image
@@ -489,5 +514,5 @@
             psError(PS_ERR_IO, false, "failed to write primary header to %s",
                 sfiles->recWeight->resolved_name);
-            bail_out("", PS_EXIT_DATA_ERROR);
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
         }
         psFree(weightHeader);
@@ -528,5 +553,5 @@
 {
     // XXX: Currently this function assumes that it is only used for a single
-    // chip single cell FPA (i.e. a skyfile)
+    // chip single cell FPA (i.e. a skycell)
     pmFPAview *view = sf->view;
     assert(view->chip == 0);
@@ -535,14 +560,14 @@
 
     if (!sf->cell) {
-        bail_out("no cells found in chip", PS_EXIT_PROG_ERROR);
+        streaksremoveExit("no cells found in chip", PS_EXIT_PROG_ERROR);
     }
     if (sf->cell->readouts->n != 1) {
         psError(PS_ERR_PROGRAMMING, true, "unexpected number of readouts found: %ld", sf->cell->readouts->n);
-        bail_out("", PS_EXIT_PROG_ERROR);
+        streaksremoveExit("", PS_EXIT_PROG_ERROR);
     }
     view->readout = 0;
     pmReadout *readout = pmFPAviewThisReadout(view, sf->inImage->pmfile->fpa);
     if (!readout) {
-        bail_out("readout 0 not found", PS_EXIT_PROG_ERROR);
+        streaksremoveExit("readout 0 not found", PS_EXIT_PROG_ERROR);
     }
 
@@ -569,7 +594,6 @@
         psError(PS_ERR_IO, false, "failed to read header from %s extnum: %d", 
             in->resolved_name, extnum);
-        bail_out("", PS_EXIT_DATA_ERROR);
-    }
-
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
+    }
 
     if (!isImage(in)) {
@@ -584,5 +608,5 @@
             psError(PS_ERR_IO, false, "failed to read image from %s extnum: %d", 
                 in->resolved_name, extnum);
-            bail_out("", PS_EXIT_DATA_ERROR);
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
         }
         in->numCols = in->image->numCols;
@@ -593,5 +617,5 @@
             psError(PS_ERR_IO, false, "failed to read image cube from %s extnum: %d", 
                 in->resolved_name, extnum);
-            bail_out("", PS_EXIT_DATA_ERROR);
+            streaksremoveExit("", PS_EXIT_DATA_ERROR);
         }
         psImage *image = (psImage *) (in->imagecube->data[0]);
@@ -603,5 +627,5 @@
 
 static void
-setOptions(sFile *sfile, psString extname, int bitpix, float bscale, float bzero)
+setFitsOptions(sFile *sfile, psString extname, int bitpix, float bscale, float bzero)
 {
     if (sfile->fits->options) {
@@ -646,6 +670,6 @@
 
     psString extname = psMetadataLookupStr(&mdok, in->header, "EXTNAME");
-    setOptions(out, extname, bitpix, bscale, bzero);
-    setOptions(rec, extname, bitpix, bscale, bzero);
+    setFitsOptions(out, extname, bitpix, bscale, bzero);
+    setFitsOptions(rec, extname, bitpix, bscale, bzero);
 }
 
@@ -673,10 +697,10 @@
     if (!table) {
         psError(PS_ERR_UNKNOWN, false, "failed to read table in extension %d from in->resolved name", extnum);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
 
     if (!psFitsWriteTable(out->fits, out->header, table, extname)) {
         psError(PS_ERR_UNKNOWN, false, "failed to copy table in extension %d", extnum);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
 }
@@ -689,5 +713,5 @@
     if (!rec->image) {
         psError(PS_ERR_UNKNOWN, false, "failed to allocate recoveyr image for extnsion %d", extnum);
-        bail_out("", PS_EXIT_UNKNOWN_ERROR);
+        streaksremoveExit("", PS_EXIT_UNKNOWN_ERROR);
     }
     psImageInit(rec->image, 0);
@@ -707,6 +731,6 @@
         readImage(sf->inImage, sf->extnum);
         if (SFILE_IS_IMAGE(sf->inImage)) {
-            sf->astrom = streakSetAstrometry(sf->astrom, sf->inAstrom->fpa, sf->chip, false, sf->inImage->header,
-                sf->inImage->numCols, sf->inImage->numRows);
+            sf->astrom = streakSetAstrometry(sf->astrom, sf->inAstrom->fpa, sf->chip, false,
+                sf->inImage->header, sf->inImage->numCols, sf->inImage->numRows);
         }
     }
@@ -734,5 +758,6 @@
     // psFitsCompressionGet(sf->inImage->image) gives compression none
     // perhaps we should just use the definition of COMP_IMG in the configuration 
-    psFitsSetCompression(sf->outImage->fits, PS_FITS_COMPRESS_RICE, sf->tiles, 8, 0, 0);
+// XXX: turn off compression as a test
+//    psFitsSetCompression(sf->outImage->fits, PS_FITS_COMPRESS_RICE, sf->tiles, 8, 0, 0);
     psFitsSetCompression(sf->recImage->fits, PS_FITS_COMPRESS_RICE, sf->tiles, 8, 0, 0);
 
@@ -778,5 +803,5 @@
         psError(PS_ERR_IO, false, "failed to write image to %s extnum: %d", 
             sfile->resolved_name, extnum);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
     psFree(sfile->image);
@@ -791,5 +816,5 @@
         psError(PS_ERR_IO, false, "failed to write image to %s extnum: %d", 
             sfile->resolved_name, extnum);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
     psFree(sfile->header);
@@ -832,5 +857,5 @@
         psError(PS_ERR_IO, false, "failed to close image to %s", 
             sfile->resolved_name);
-        bail_out("", PS_EXIT_DATA_ERROR);
+        streaksremoveExit("", PS_EXIT_DATA_ERROR);
     }
 }
@@ -854,19 +879,141 @@
 }
 
-void
-dumpAstro(streakFiles *sf)
-{
-    strkPt pt;
-    if (!sf->inImage->image) {
-        return;
-    }
-
-    cellToSky(&pt, sf->astrom, 0, 0);
-
-    psString extname = psMetadataLookupStr(NULL, sf->inImage->header, "EXTNAME");
-
-    printf("%2d %s %f %f\n", sf->extnum, extname, pt.x, pt.y);
-}
-
+static bool
+replicate(nebServer *server, sFile *sfile, void *xattr)
+{
+    if (!sfile->inNebulous) {
+        return true;
+    }
+    // for now just set "user.copies" to 2
+    if (!nebSetXattr(server, sfile->name, "user.copies", "2",  NEB_REPLACE)) {
+        psError(PM_ERR_UNKNOWN, true, "nebSetXattr failed for %s\n%s", sfile->name, nebErr(server));
+        return false;
+    }
+    if (!nebReplicate(server, sfile->name, NULL, NULL)) {
+        psError(PM_ERR_UNKNOWN, true, "nebSetXattr failed for %s\n%s", sfile->name, nebErr(server));
+        return false;
+    }
+    return true;
+}
+
+// for any of the outputs that are stored in Nebulous set their extended attributes
+// and replicate the files
+
+static bool
+replicateOutputs(streakFiles *sfiles)
+{
+    bool status = false;
+    psString neb_server = getenv("NEB_SERVER");
+
+    // XXX: Note: all of the flags to psError should be true, but I don't think nebclient
+    // uses psError
+    if (!neb_server) {
+        neb_server = psMetadataLookupStr(&status, sfiles->config->site, "NEB_SERVER");
+        if (!status) {
+            psError(PM_ERR_CONFIG, true, "failed to lookup config value for NEB_SERVER.");
+            return false;
+        }
+    }
+
+    if (!neb_server) {
+        psError(PM_ERR_CONFIG, true, "Could not determine nebulous server URI.");
+        return false;
+    }
+
+    sfiles->nebServer = nebServerAlloc(neb_server);
+    if (!sfiles->nebServer) {
+        psError(PM_ERR_SYS, true, "failed to create a nebServer object.");
+        return false;
+    }
+
+    // XXX: TODO: need a nebGetXatrr function, but there isn't one
+    void *xattr = NULL;
+
+    if (!replicate(sfiles->nebServer, sfiles->outImage, xattr)) {
+        psError(PM_ERR_SYS, false, "failed to replicate outImage.");
+        return false;
+    }
+
+#ifdef notyet
+    // don't replicate mask and weight images until we can look up
+    // the input's xattr. There may be a perl program that can getXattr
+    if (sfiles->outMask) {
+        // get xattr from input to see if we need to replicate
+        if (!replicate(sfiles->nebServer, sfiles->outMask, xattr)) {
+            psError(PM_ERR_SYS, false, "failed to replicate outImage.");
+            return false;
+        }
+    }
+    if (sfiles->outWeight) {
+        // get xattr from input to see if we need to replicate
+        if (!replicate(sfiles->nebServer, sfiles->outWeight, xattr)) {
+            psError(PM_ERR_SYS, false, "failed to replicate outImage.");
+            return false;
+        }
+    }
+#endif
+
+//      replicate the recovery images (if in nebulous)
+//      perhaps whether we do that or not should be configurable.
+//      Sounds like we need a recipe
+
+    return true;
+}
+static bool
+swapOutputsToInputs(streakFiles *sfiles)
+{
+    bool status = false;
+
+    if (!sfiles->nebServer) {
+        // no output files are in nebulous
+        return true;
+    }
+
+    // XXX: we should check for consistency before here
+    // We need to insure that the database is consistent
+    // If input is in nebulous, output must be
+    // if input is not in nebulous output must not be Catch in parseArguments
+    // if not in nebulous create a backup of input before overwriting
+
+    if (sfiles->inImage->inNebulous && sfiles->outImage->inNebulous) {
+        if (!nebSwap(sfiles->nebServer, sfiles->outImage->name, sfiles->inImage->name)) {
+            psError(PM_ERR_SYS, false, "failed to swap instances for Image\n%s.",
+                nebErr(sfiles->nebServer));
+            return false;
+        }
+    }
+
+    // TODO: handle weight and mask images
+
+    return true;
+}
+static bool
+deleteTemps(streakFiles *sfiles)
+{
+    bool status = false;
+
+    if (!sfiles->nebServer) {
+        // no output files are in nebulous
+        return true;
+    }
+
+    // XXX: we should check for consistency before here
+    // We need to insure that the database is consistent
+    // If input is in nebulous, output must be
+    // if input is not in nebulous output must not be Catch in parseArguments
+    // if not in nebulous create a backup of input before overwriting
+
+    if (sfiles->outImage->inNebulous) {
+        if (!nebDelete(sfiles->nebServer, sfiles->outImage->name)) {
+            psError(PM_ERR_SYS, false, "failed to delete %s\n%s.", sfiles->outImage->name,
+                nebErr(sfiles->nebServer));
+            return false;
+        }
+    }
+
+    // TODO: weight and mask images
+
+    return true;
+}
 
 int
@@ -942,35 +1089,65 @@
             pixelPos = psArrayGet (pixels, i);
             imageValue  = psImageGet (sfiles->inImage->image,  pixelPos->x, pixelPos->y);
-            weightValue = psImageGet (sfiles->inWeight->image, pixelPos->x, pixelPos->y);
-            maskValue   = psImageGet (sfiles->inMask->image,   pixelPos->x, pixelPos->y);
-
             psImageSet (sfiles->recImage->image,  pixelPos->x, pixelPos->y, imageValue);
-            psImageSet (sfiles->recWeight->image, pixelPos->x, pixelPos->y, weightValue);
-            psImageSet (sfiles->recMask->image,   pixelPos->x, pixelPos->y, maskValue);
-
             psImageSet (sfiles->outImage->image,  pixelPos->x, pixelPos->y, NAN);
-            psImageSet (sfiles->outWeight->image, pixelPos->x, pixelPos->y, NAN);
-            // TODO:
-            // Need to get mask weight for PM_MASK_DETECTOR.  Is this stored
-            // in a config somewhere?  Not sure how to properly set the maskValue.
-            psImageSet (sfiles->outMask->image,   pixelPos->x, pixelPos->y, maskValue);
+            if (sfiles->inWeight) {
+                weightValue = psImageGet (sfiles->inWeight->image, pixelPos->x, pixelPos->y);
+                psImageSet (sfiles->recWeight->image, pixelPos->x, pixelPos->y, weightValue);
+                psImageSet (sfiles->outWeight->image, pixelPos->x, pixelPos->y, NAN);
+            }
+            if (sfiles->inMask) {
+                maskValue   = psImageGet (sfiles->inMask->image,   pixelPos->x, pixelPos->y);
+                psImageSet (sfiles->recMask->image,   pixelPos->x, pixelPos->y, maskValue);
+                // TODO:
+                // Need to get mask weight for PM_MASK_DETECTOR.  Is this stored
+                // in a config somewhere?  Not sure how to properly set the maskValue.
+                psImageSet (sfiles->outMask->image,   pixelPos->x, pixelPos->y, maskValue);
+            }
         }
         psArrayElementsFree (pixels);
 
-        // dumpAstro(sfiles);
-        // write out the destreaked temporary images
+        // write out the destreaked temporary images and the recovery images
         writeImages(sfiles);
     } while (streakFilesNextExtension(sfiles));
 
-    // close the destreaked temporary images
+    // close all files
     closeImages(sfiles);
 
-    // TODO:
-    // Now copy the destreaked images files that we made above 
-    // over each nebulous instances of input files
-
     // NOTE: from here on we can't just quit if something goes wrong.
-    // especially if we're working on a rawImage
-
+    // especially if we're working at the raw stage
+
+    if (!replicateOutputs(sfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to replicate output files");
+        psErrorStackPrint(stderr, "");
+        exit(PS_EXIT_UNKNOWN_ERROR);
+    }
+
+    bool status;
+    if (psMetadataLookupBool(&status, config->arguments, "REPLACE")) {
+        //     swap the instances for the input and output
+        //     Note this is a database operation. No file I/O is performed
+        if (!swapOutputsToInputs(sfiles)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to replicate output files");
+            // XXX: Now what? I guess swapOutputsToInputs will need to undo anything that
+            // it has done and give a detailed report of what happened
+            psErrorStackPrint(stderr, "");
+            exit(PS_EXIT_UNKNOWN_ERROR);
+        }
+    }
+
+    if (psMetadataLookupBool(&status, config->arguments, "REMOVE")) {
+        //      delete the temporary storage objects (which now points to the original image(s)
+        if (!deleteTemps(sfiles)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to delete temporary files");
+            // XXX: Now what? At this point the output files have been swapped, so we can't
+            // repeat the operation.
+            // Returning error status is problematic. Maybe just print an error message and
+            // let other system tools clean up
+            psErrorStackPrint(stderr, "");
+            exit(PS_EXIT_UNKNOWN_ERROR);
+        }
+    }
+
+    //  PAU
 
     return 0;
