Index: trunk/psphot/src/psphotDefineFiles.c
===================================================================
--- trunk/psphot/src/psphotDefineFiles.c	(revision 36375)
+++ trunk/psphot/src/psphotDefineFiles.c	(revision 42842)
@@ -1,3 +1,4 @@
 # include "psphotInternal.h"
+pmConfig *pmConfigMakeTemp (pmConfig *config);
 
 bool psphotINpsphotStack = false;
@@ -143,6 +144,15 @@
     }
 
+    // Use a temporary config for the source files, keeping the main user, site,
+    // system, files, arguments entries.  This allows the sources to be from a
+    // different camera than the input image.  NOTE: there is no check that these two
+    // images match in terms of size, pixel scale, etc. That is up to the user.
+    // The temporary config structure has PSCAMERA entries removed from the SKYCELL rules
+    // to allow forced photometry between cameras.
+    
+    pmConfig *srcconfig = pmConfigMakeTemp(config);
+
     if (psMetadataLookupPtr(NULL, config->arguments, "SRC")) {
-        if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.CMF", "SRC")) {
+        if (!pmFPAfileDefineFromArgs (&status, srcconfig, "PSPHOT.INPUT.CMF", "SRC")) {
             psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.CMF");
             return status;
@@ -151,5 +161,5 @@
 
     if (psMetadataLookupPtr(NULL, config->arguments, "FORCE")) {
-        if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.CFF", "FORCE")) {
+        if (!pmFPAfileDefineFromArgs (&status, srcconfig, "PSPHOT.INPUT.CFF", "FORCE")) {
             psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.CFF");
             return status;
@@ -160,5 +170,5 @@
 	// XXX cannot use pmFPAfileDefineFromArgs: this is explicitly a FITS-based I/O function
 	// supply the attach the 
-	if (!psphotLoadSRCTEXT(input->fpa, config)) {
+	if (!psphotLoadSRCTEXT(input->fpa, srcconfig)) {
             psError(PSPHOT_ERR_CONFIG, false, "Failed to load PSPHOT.INPUT.TEXT");
             return status;
@@ -167,5 +177,5 @@
 
     if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.PSF")) {
-        pmFPAfileBindFromArgs(&status, input, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
+        pmFPAfileBindFromArgs(&status, input, srcconfig, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
         if (!status) {
             psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.PSF.LOAD");
@@ -173,4 +183,6 @@
         }
     }
+
+    psFree (srcconfig);
 
     // XXX add in example PSF image thumbnails
@@ -214,2 +226,67 @@
     return rule;
 }
+
+pmConfig *pmConfigMakeTemp (pmConfig *config) {
+    pmConfig *altconfig = pmConfigAlloc();
+
+    // these are NULL on pmConfigAlloc
+    altconfig->user   = psMemIncrRefCounter(config->user);   // inherit from primary camera
+    altconfig->site   = psMemIncrRefCounter(config->site);   // inherit from primary camera
+
+    psFree (altconfig->system);
+    altconfig->system = psMetadataCopy(NULL, config->system); // container for camera-specific recipe values (to be dropped)
+
+    psFree (altconfig->files);
+    altconfig->files  = psMemIncrRefCounter(config->files); // inherit from primary camera
+
+    psFree (altconfig->arguments);
+    altconfig->arguments = psMemIncrRefCounter(config->arguments); // inherit from primary camera
+
+    psFree (altconfig->recipes);
+    altconfig->recipes = psMetadataCopy(NULL, config->recipes); // container for camera-specific recipe values (to be dropped)
+
+    // remove PSCAMERA entries from *-SKYCELL cameras.  This allows skycell images from
+    // one camera to match those of another camera.  XXX Make this optional to force
+    // matching cameras if desired?
+    bool mdok = false;
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, altconfig->system, "CAMERAS");
+    psAssert(cameras, "missing cameras in system config info");
+    
+    // iterate over the cameras and find ones with names like _*-SKYCELLS
+    // psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, "^_.+-SKYCELL$");
+    psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL);
+    psAssert(camerasIter, "unable to generate iterator?");
+
+    psMetadataItem *camerasItem = NULL; // Item from the metadata
+    while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
+      psAssert(camerasItem->type == PS_DATA_METADATA, "camerasItem has invalid type");
+      
+      char *name = camerasItem->name;
+      psAssert (name, "NULL name for item");
+
+      int nameLen = strlen(name);
+      if (name[0] != '_') continue;
+      if (nameLen <= 9) continue;
+      char *p = &name[nameLen - 8];
+      if (strcmp(p, "-SKYCELL")) continue;
+
+      // remove PSCAMERA entries from *-SKYCELL cameras
+      psMetadata *formats = psMetadataLookupMetadata(&mdok, camerasItem->data.md, "FORMATS"); // List of formats
+      psAssert (formats, "missing FORMATS in camera.config ");
+
+      psMetadata *format = psMetadataLookupMetadata(&mdok, formats, "SKYCELL"); // one true format for skycells
+      psAssert (format, "missing SKYCELL metaformat for -SKYCELL entry ");
+
+      psMetadata *rule = psMetadataLookupMetadata(&mdok, format, "RULE"); // one true format for skycells
+      psAssert (rule, "missing RULE in SKYCELL metaformat for -SKYCELL entry ");
+
+      psString pscamera = psMetadataLookupStr(&mdok, rule, "PSCAMERA"); // one true format for skycells
+      if (!pscamera) continue; // already removed, or never supplied
+
+      psMetadataRemoveKey (rule, "PSCAMERA"); // allow any camera skycell to match
+    }
+    psFree (camerasIter);
+
+    return (altconfig);
+}
+
