Index: trunk/psastro/src/psastroLoadGhosts.c
===================================================================
--- trunk/psastro/src/psastroLoadGhosts.c	(revision 40552)
+++ trunk/psastro/src/psastroLoadGhosts.c	(revision 41290)
@@ -13,4 +13,8 @@
 # include "psastroInternal.h"
 
+// These are only used locally:
+bool psastroLoadGhostsGPC (pmConfig *config, psMetadata *recipe, psMetadata *ghostModel, char *ghostFile);
+bool psastroLoadGhostsHSC (pmConfig *config, psMetadata *recipe, psMetadata *ghostModel, char *ghostFile);
+
 # define GET_2D_POLY(NAME,OUT) \
     md = psMetadataLookupMetadata (&status, ghostModel, NAME); \
@@ -41,7 +45,55 @@
  */
 
-		    
-
 bool psastroLoadGhosts (pmConfig *config) {
+
+    bool status;
+
+    psLogMsg ("psastro", PS_LOG_INFO, "determine ghost positions");
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSASTRO_RECIPE);
+    if (!recipe) {
+        psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe");
+        return false;
+    }
+
+    // do we want to mask ghosts?
+    bool REFSTAR_MASK_GHOST = psMetadataLookupBool (&status, recipe, "REFSTAR_MASK_GHOST");
+    if (!REFSTAR_MASK_GHOST) return true;
+
+    // choose ghost model file
+    char *ghostFile = psMetadataLookupStr (&status, recipe, "GHOST_MODEL");
+    if (!strcasecmp(ghostFile, "NONE")) return true;
+
+    // load ghost model metadata structure
+    psMetadata *ghostModel = NULL;
+    if (!pmConfigFileRead (&ghostModel, ghostFile, "GHOST MODEL")) {
+	psError(PSASTRO_ERR_CONFIG, true, "Trouble loading ghost model");
+        return false;
+    }
+
+    // test for items which are used by either the GPC or HSC ghost models:
+    psMetadataItem *item = NULL;
+
+    // test for required HSC ghost model elements
+    item = psMetadataLookup(ghostModel, "GHOST.MODEL.HSC");
+    if (item) {
+	status = psastroLoadGhostsHSC (config, recipe, ghostModel, ghostFile);
+	if (!status) goto escape;
+    }
+    
+    // test for required GPC ghost model elements
+    item = psMetadataLookup(ghostModel, "GHOST.CENTER.X");
+    if (item) {
+	status = psastroLoadGhostsGPC (config, recipe, ghostModel, ghostFile);
+	if (!status) goto escape;
+    }
+    
+escape:
+    psFree (ghostModel);
+    return status;
+}
+ 
+bool psastroLoadGhostsGPC (pmConfig *config, psMetadata *recipe, psMetadata *ghostModel, char *ghostFile) {
 
     bool status;
@@ -57,44 +109,6 @@
     psPolynomial1D *innerMajor = NULL;
     psPolynomial1D *innerMinor = NULL;
-    psMetadata *ghostModel = NULL;
-
-    psLogMsg ("psastro", PS_LOG_INFO, "determine ghost positions");
-
-    // XXX this needs to be camera-dependent
-    if (0) {
-      psWarning("Doing the hard coded switch to HSC ghosts still.");
-      return (psastroLoadGhostsHSC(config));
-    } 
-
-    psWarning("hard coded switch to GPC ghosts.");
-
-    // select the current recipe
-    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSASTRO_RECIPE);
-    if (!recipe) {
-        psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe");
-        return false;
-    }
-
-    bool REFSTAR_MASK_GHOST = psMetadataLookupBool (&status, recipe, "REFSTAR_MASK_GHOST");
-    if (!REFSTAR_MASK_GHOST) return true;
-
-    
-    char *ghostFile = psMetadataLookupStr (&status, recipe, "GHOST_MODEL");
-    if (!strcasecmp(ghostFile, "NONE")) return true;
-
-    if (!pmConfigFileRead (&ghostModel, ghostFile, "GHOST MODEL")) {
-	psError(PSASTRO_ERR_CONFIG, true, "Trouble loading ghost model");
-        return false;
-    }
 
     pmFPAview *view = pmFPAviewAlloc (0);
-
-    GET_2D_POLY ("GHOST.CENTER.X", centerX);
-    GET_2D_POLY ("GHOST.CENTER.Y", centerY);
-
-    GET_1D_POLY ("GHOST.OUTER.MAJOR", outerMajor);
-    GET_1D_POLY ("GHOST.OUTER.MINOR", outerMinor);
-    GET_1D_POLY ("GHOST.INNER.MAJOR", innerMajor);
-    GET_1D_POLY ("GHOST.INNER.MINOR", innerMinor);
 
     // select the input astrometry data (also carries the refstars)
@@ -106,7 +120,15 @@
     pmFPA *fpa = astrom->fpa;
 
-    // really error-out here?  or just skip?
+    GET_2D_POLY ("GHOST.CENTER.X", centerX);
+    GET_2D_POLY ("GHOST.CENTER.Y", centerY);
+
+    GET_1D_POLY ("GHOST.OUTER.MAJOR", outerMajor);
+    GET_1D_POLY ("GHOST.OUTER.MINOR", outerMinor);
+    GET_1D_POLY ("GHOST.INNER.MAJOR", innerMajor);
+    GET_1D_POLY ("GHOST.INNER.MINOR", innerMinor);
+
+    // raise an error if the config is broken
     if (!psastroZeroPointFromRecipe (&zeropt, &exptime, &MAX_MAG, fpa, recipe)) {
-        psLogMsg ("psastro", PS_LOG_INFO, "failed to load zeropt data from recipe");
+        psError(PSASTRO_ERR_CONFIG, true, "failed to load zeropt data from recipe");
 	goto escape;
     }
@@ -253,5 +275,4 @@
     psFree (outerMajor);
     psFree (outerMinor);
-    psFree (ghostModel);
     psFree (view);
     return true;
@@ -264,12 +285,12 @@
     psFree (outerMajor);
     psFree (outerMinor);
-    psFree (ghostModel);
     psFree (view);
     return false;
 }
-
-
  
-bool psastroLoadGhostsHSC (pmConfig *config) {
+// This function adds the ghost mask elements to the ghostReadout->analysis structures.
+// We return false and raise an error on a config problem.
+bool psastroLoadGhostsHSC (pmConfig *config, psMetadata *recipe, psMetadata *ghostModel, char *ghostFile) {
+
   bool status;
   pmChip *chip = NULL;
@@ -277,32 +298,11 @@
   pmReadout *readout = NULL;
   float zeropt, exptime, MAX_MAG;
-  psMetadata *ghostModel = NULL;
   psVector *C_terms = NULL;
   psVector *R_terms = NULL;
   float glintPixelScale = 0.0;
   
-  psLogMsg ("psastro", PS_LOG_INFO, "determine ghost positions");
-  
-  // select the current recipe
-  psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSASTRO_RECIPE);
-  if (!recipe) {
-    psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe");
-    return false;
-  }
-  
-  bool REFSTAR_MASK_GHOST = psMetadataLookupBool (&status, recipe, "REFSTAR_MASK_GHOST");
-  if (!REFSTAR_MASK_GHOST) return true;
-  
-  // Load model from file
-  char *ghostFile = psMetadataLookupStr (&status, recipe, "GHOST_MODEL");
-  if (!strcasecmp(ghostFile, "NONE")) return true;
-  psLogMsg("psastro", PS_LOG_INFO, "ghost file %s",ghostFile);
-  if (!pmConfigFileRead (&ghostModel, ghostFile, "GHOST MODEL")) {
-    psError(PSASTRO_ERR_CONFIG, true, "Trouble loading ghost model");
-    return false;
-  }
-  
   // Allocate FPA and refstars
   pmFPAview *view = pmFPAviewAlloc (0);
+
   // select the input astrometry data (also carries the refstars)
   pmFPAfile *astrom = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
@@ -314,12 +314,13 @@
   
   char *filter = psMetadataLookupStr (&status, fpa->concepts, "FPA.FILTERID");
+
   psMetadataItem *item = psMetadataLookup(ghostModel, "GHOST.MODEL.HSC");
   if (!item) {
-    psLogMsg ("psastro", PS_LOG_INFO, "GHOST.MODEL.HSC data missing");
-    return false;
+      psError(PSASTRO_ERR_CONFIG, true, "GHOST.MODEL.HSC data missing");
+      goto escape;
   }
   if (item->type != PS_DATA_METADATA_MULTI) {
-    psLogMsg ("psastro", PS_LOG_INFO, "GHOST.MODEL.HSC not multi");
-    return false;
+      psError(PSASTRO_ERR_CONFIG, true, "GHOST.MODEL.HSC not multi");
+      goto escape;
   }
   
@@ -328,10 +329,9 @@
   while ((refItem = psListGetAndIncrement(iter))) {
     if (refItem->type != PS_DATA_METADATA) {
-      psLogMsg ("psastro", PS_LOG_INFO, "GHOST.MODEL.HSC entry not metadata");
-      return false;
+	psError(PSASTRO_ERR_CONFIG, true, "GHOST.MODEL.HSC entry not metadata");
+	goto escape;
     }
     char *refFilter = psMetadataLookupStr (&status, refItem->data.md, "FILTER");
     if (!status) {
-      // psLogMsg ("psastro", PS_LOG_INFO, "a PHOTCODE.DATA recipe folder is missing FILTER");
       continue;
     }
@@ -343,14 +343,14 @@
   }
 
-  // really error-out here?  or just skip?
+  // if a ghost model is not defined for a filter, skip HSC ghost model for that filter (no error)
   if (!R_terms) {
     psLogMsg ("psastro", PS_LOG_INFO, "failed to find HSC ghost model for filter %s", filter);
-    goto escape;
-  }
-  
-  // really error-out here?  or just skip?
+    goto giveup;
+  }
+  
+  // if a filter is defined, but the recipe elements are missing, the config is broken.
   if (!psastroZeroPointFromRecipe (&zeropt, &exptime, &MAX_MAG, fpa, recipe)) {
-    psLogMsg ("psastro", PS_LOG_INFO, "failed to load zeropt data from recipe");
-    goto escape;
+	psError(PSASTRO_ERR_CONFIG, true, "failed to load zeropt data from recipe");
+	goto escape;
   }
   
@@ -430,6 +430,5 @@
 	  
 	  if (ghostChip) {
-	    psLogMsg("psastro",PS_LOG_INFO,
-		     //	    psTrace("psastro.ghost",5,
+	    psLogMsg("psastro", PS_LOG_INFO,
 		    "   in ghost: %d/%ld: ref: (%f,%f) or (%s) ghost: (%f,%f) or (%f,%f,%s) %f inner: (%f,%f,%f) outer: (%f,%f,%f)",
 		    i,refstars->n,
@@ -441,7 +440,7 @@
 		    ghost->inner.major,ghost->inner.minor,ghost->inner.theta,
 		    ghost->outer.major,ghost->outer.minor,ghost->outer.theta);
-	  }
-	  else {
-	    psTrace("psastro.ghost",5,"   in ghost: %d/%ld: ref: (%f,%f) ghost: (%f,%f) or (%f,%f,%s) inner: (%f,%f,%f) outer: (%f,%f,%f)",
+	  } else {
+	    psTrace("psastro.ghost", 5,
+		    "   in ghost: %d/%ld: ref: (%f,%f) ghost: (%f,%f) or (%f,%f,%s) inner: (%f,%f,%f) outer: (%f,%f,%f)",
 		    i,refstars->n,
 		    ref->FP->x,ref->FP->y,
@@ -451,6 +450,4 @@
 		    ghost->outer.major,ghost->outer.minor,ghost->outer.theta);
 	  }		      
-	  
-	  
 	  
 	  if (!ghostChip) goto skip;
@@ -475,9 +472,7 @@
 	    psFree (ghosts);
 	  }
-	  
 	  psArrayAdd (ghosts, 100, ghost);
 	  
 	skip:
-	  
 	  psFree (ghost);
 	}
@@ -488,7 +483,7 @@
   psastroExtractFreeChipBounds();
   
+giveup:
   psFree (C_terms);
   psFree (R_terms);
-  //    psFree (ghostModel);
   psFree (view);
   return true;
@@ -497,5 +492,4 @@
   psFree (C_terms);
   psFree (R_terms);
-  //    psFree (ghostModel);
   psFree (view);
   return false;
