Index: /trunk/psastro/src/psastro.h
===================================================================
--- /trunk/psastro/src/psastro.h	(revision 41289)
+++ /trunk/psastro/src/psastro.h	(revision 41290)
@@ -60,5 +60,4 @@
 psastroGhost     *psastroGhostAlloc (void);
 bool              psastroLoadGhosts (pmConfig *config);
-bool              psastroLoadGhostsHSC (pmConfig *config);
 
 bool              psastroDataSave (pmConfig *config, psMetadata *stats);
Index: /trunk/psastro/src/psastroLoadGhosts.c
===================================================================
--- /trunk/psastro/src/psastroLoadGhosts.c	(revision 41289)
+++ /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;
Index: /trunk/psastro/src/psastroLoadGlints.c
===================================================================
--- /trunk/psastro/src/psastroLoadGlints.c	(revision 41289)
+++ /trunk/psastro/src/psastroLoadGlints.c	(revision 41290)
@@ -364,15 +364,12 @@
 	      if (star_radius_deg < 0.8831) {
 		outer_edge_angle = 0.0;
-	      }
-	      else if (star_radius_deg < 0.9368) {
+	      } else if (star_radius_deg < 0.9368) {
 		outer_edge_angle = 46.2985 * sqrt(star_radius_deg - 0.8831);
-	      }
-	      else {
+	      } else {
 		outer_edge_angle = -2.67 + 14.3 * star_radius_deg;
 	      }
 	      if (star_radius_deg < 0.964) {
 		inner_edge_angle = -243.866 * pow(star_radius_deg - 0.932,2) + 2.4636;
-	      }
-	      else {
+	      } else {
 		inner_edge_angle = 66.2061 * sqrt(star_radius_deg - 0.9635);
 	      }
@@ -383,7 +380,7 @@
 	      // These define the ends of a single arc in arc-centric coordinates
 	      double x1 = C - R * cos(inner_edge_angle);
-	      double y1 = R * sin(inner_edge_angle);
+	      double y1 =     R * sin(inner_edge_angle);
 	      double x2 = C - R * cos(outer_edge_angle);
-	      double y2 = R * sin(outer_edge_angle);
+	      double y2 =     R * sin(outer_edge_angle);
 
 	      // Create the endpoints for the pair of arcs in device coordinates (in millimeters)
@@ -414,5 +411,9 @@
 		      x2s,y2s,x2e,y2e);
 		      
-	      
+	      // NOTE: the calculations below appear to expect (x1s, y1s) in millimeters, as mentioned above.
+	      // They are then scaled to camera pixel units using 0.015 millimeters / pixel, and then to
+	      // TPA units using 13.5 pixels / pixel.  I do not know where the (12.78, 57.75) mm offsets
+	      // come from (displacement of reference chip?)
+		
 	      tp->x = 13.5 * (y1s / 0.015 + 12.78);
 	      tp->y = 13.5 * (x1s / -0.015 + 57.74);
@@ -420,6 +421,4 @@
 	      x_start->data.F32[0] = fp->x;
 	      y_start->data.F32[0] = fp->y;
-	      //	      x_start->data.F32[0] = tp->x;
-	      //	      y_start->data.F32[0] = tp->y;
 
 	      tp->x = 13.5 * (y1e / 0.015 + 12.78);
@@ -428,6 +427,4 @@
 	      x_end->data.F32[0]   = fp->x;
 	      y_end->data.F32[0]   = fp->y;
-	      //	      x_end->data.F32[0]   = tp->x;
-	      //	      y_end->data.F32[0]   = tp->y;
 
 	      x_start->data.F32[1] = x_end->data.F32[0];  
@@ -441,6 +438,4 @@
 	      x_start->data.F32[2] = fp->x;
 	      y_start->data.F32[2] = fp->y;
-	      //	      x_start->data.F32[2] = tp->x;
-	      //	      y_start->data.F32[2] = tp->y;
 
 	      tp->x = 13.5 * (y2e / 0.015 + 12.78);
@@ -449,6 +444,4 @@
 	      x_end->data.F32[2]   = fp->x;
 	      y_end->data.F32[2]   = fp->y;
-	      //	      x_end->data.F32[2]   = tp->x;
-	      //	      y_end->data.F32[2]   = tp->y;
 	      
 	      x_start->data.F32[3] = x_end->data.F32[2];  
