Index: trunk/psastro/src/psastroConvert.c
===================================================================
--- trunk/psastro/src/psastroConvert.c	(revision 41433)
+++ trunk/psastro/src/psastroConvert.c	(revision 41434)
@@ -14,4 +14,10 @@
 // leak free 2006.04.27
 
+// To select good stars, I want them to have a PSFmodel fit (PM_SOURCE_MODE_PSFMODEL & PM_SOURCE_MODE_FITTED) and exlcude things that are CR, EXT, FAIL, POOR 
+// Stars are allowed to be saturated, as long as the PSF model fits
+# define PHOT_SOURCE_MASK (PM_SOURCE_MODE_FAIL | PM_SOURCE_MODE_BLEND | PM_SOURCE_MODE_BADPSF | \
+                           PM_SOURCE_MODE_DEFECT | PM_SOURCE_MODE_CR_LIMIT | PM_SOURCE_MODE_EXT_LIMIT | \
+                           PM_SOURCE_MODE_POOR) // Mask to apply to sources for rejection
+
 static psArray *chooseStars(psArray *inStars, char *listName, psArray *sources, psVector *index, int nMax, float iMagMin, float iMagMax, pmSourceMode skip);
 
@@ -142,4 +148,28 @@
         }
     }
+
+    //also select a sample of stars which are allowed to be saturated and bright, as long as they are well fit by a PSF model
+    int j = 0;
+    psArray *calStars = psArrayAlloc(inStars->n);
+
+    for (int i = 0; (i < inStars->n) && (j < rawStars->n); i++) {
+        int n = index->data.S32[i];
+        pmSource *source = sources->data[n];
+
+        // we only want to use stars which are not bad. Use the source->mode to check for the rejection mask while keeping fitted PSFmodel
+        if (source->mode & PHOT_SOURCE_MASK || !isfinite(source->psfMag)) {
+            continue;
+        }
+
+        //Ensure the source has a fitted PSF model
+        if (!(source->mode & PM_SOURCE_MODE_PSFMODEL) || !(source->mode & PM_SOURCE_MODE_FITTED) ) {
+            continue;
+        }
+
+        calStars->data[j] = psMemIncrRefCounter (inStars->data[n]);
+        j++;
+    }
+    calStars->n = j;
+    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.CALSTARS", PS_DATA_ARRAY, "astrometry objects for masking", calStars);
 
     psFree (index);
Index: trunk/psastro/src/psastroLoadCrosstalk.c
===================================================================
--- trunk/psastro/src/psastroLoadCrosstalk.c	(revision 41433)
+++ trunk/psastro/src/psastroLoadCrosstalk.c	(revision 41434)
@@ -53,5 +53,5 @@
   pmFPAview *viewMask = pmFPAviewAlloc (0);
 
-  float zeropt, exptime, MAX_MAG, SPIKE_MAX_MAG;
+  float zeropt, exptime, MAX_MAG, INSTR_MAX_MAG, SPIKE_MAX_MAG;
 
   psLogMsg ("psastro", PS_LOG_INFO, "determine crosstalk positions");
@@ -99,9 +99,9 @@
   }
 
-  MAX_MAG = psMetadataLookupF32 (&status, recipe, "REFSTAR_MASK_CROSSTALK_MAG_MAX");
+  INSTR_MAX_MAG = psMetadataLookupF32 (&status, recipe, "REFSTAR_MASK_CROSSTALK_MAG_MAX");
   // recipe values are given in instrumental magnitudes
   // use the zero point and exposure time to convert to apparent mags: M_ap = M_inst + C_0 + 2.5*log(exptime)
   float MagOffset = zeropt + 2.5*log10(exptime);
-  MAX_MAG += MagOffset;
+  MAX_MAG = INSTR_MAX_MAG + MagOffset;
 
   // Get the spike maximum, as well
@@ -141,14 +141,13 @@
           }
 
-          // Get the array of reference stars we're concerned with.
-          psArray *refstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.REFSTARS");
-          if (refstars == NULL) { return(true); }
-
-          // Check each reference star
-          for (int i = 0; i < refstars->n; i++) {
-	    // This is the source of the ct.
-            pmAstromObj *ref = refstars->data[i];
-
-            if (ref->Mag > MAX_MAG) {
+          // To check for the presence of crosstalk we first make use the actual detections on this image.
+          // That way we can include things like movers creating crosstalk features.
+          psArray *calstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.CALSTARS");
+          if (calstars == NULL) { continue; }
+
+          for (int i = 0; i < calstars->n; i++) {
+            pmAstromObj *cal = calstars->data[i];
+
+            if (cal->Mag > INSTR_MAX_MAG) {
               continue;
             }
@@ -156,5 +155,5 @@
             // Identify which cell holds the star
             pmChip *CTsourceChip = refChip;
-            pmCell *CTsourceCell = pmCellInChip(refChip,ref->chip->x,ref->chip->y);
+            pmCell *CTsourceCell = pmCellInChip(refChip,cal->chip->x,cal->chip->y);
 
             if (!CTsourceCell) {
@@ -162,7 +161,6 @@
             }
 
-            psTrace ("psastro.crosstalk",2,"REF: %d %f (%f %f) %f %f :: %f %f\n",
-                     i,ref->Mag, ref->sky->r,ref->sky->d, ref->FP->x,ref->FP->y, ref->chip->x,ref->chip->y);
-
+            psTrace ("psastro.crosstalk",2,"DETEC: %d %f :: %f %f\n",
+                     i,cal->Mag, cal->chip->x,cal->chip->y);
 
             const char *cellName = psMetadataLookupStr(NULL,CTsourceCell->concepts, "CELL.NAME");
@@ -176,5 +174,5 @@
             float x_t_chip,y_t_chip;
 	    // int faint_ct = 0; NOTE: not currently used
-            pmCellCoordsForChip(&x_cell,&y_cell,CTsourceCell,ref->chip->x,ref->chip->y);
+            pmCellCoordsForChip(&x_cell,&y_cell,CTsourceCell,cal->chip->x,cal->chip->y);
 
             x_t_cell = x_cell;
@@ -245,8 +243,9 @@
             psStringAppend(&targetCellName,"xy%d%d",Ut,Vt);
 
-            psTrace ("psastro.crosstalk",2,"CTsource @ OTA%d%dxy%d%d@%f,%f CTtarget OTA%d%dxy%d%d@%f,%f [%s %s]",
+            psTrace ("psastro.crosstalk",2,"CTsource from DETEC @ OTA%d%dxy%d%d@%f,%f CTtarget OTA%d%dxy%d%d@%f,%f [%s %s]",
                      X,Y,U,V,x_cell,y_cell,Xt,Yt,Ut,Vt,x_t_cell,y_t_cell,
                      targetChipName,targetCellName);
 
+
             pmCell *CTtargetCell = getCellByName (CTsourceChip,targetCellName);
             if (!CTtargetCell) continue;
@@ -254,5 +253,5 @@
             pmChipCoordsForCell(&x_t_chip,&y_t_chip,CTtargetCell,x_t_cell,y_t_cell);
 
-            psTrace ("psastro.crosstalk",2,"CTsource @ OTA%d%dxy%d%d@%f,%f CTtarget OTA%d%dxy%d%d@%f,%f ChipLoc: (%f,%f)",
+            psTrace ("psastro.crosstalk",2,"CTsource from DETEC @ OTA%d%dxy%d%d@%f,%f CTtarget OTA%d%dxy%d%d@%f,%f ChipLoc: (%f,%f)",
                      X,Y,U,V,x_cell,y_cell,Xt,Yt,Ut,Vt,x_t_cell,y_t_cell,x_t_chip,y_t_chip);
 
@@ -272,6 +271,160 @@
             pmAstromObj *crosstalk = pmAstromObjAlloc();
 	    
+            crosstalk->Mag = cal->Mag;
+            crosstalk->chip->x = x_t_chip;
+            crosstalk->chip->y = y_t_chip;
+
+            psArray *crosstalks = psMetadataLookupPtr (&status, targetReadout->analysis, "PSASTRO.CROSSTALKS");
+            if (crosstalks == NULL) {
+              crosstalks = psArrayAllocEmpty(100);
+              if (!psMetadataAdd(targetReadout->analysis,PS_LIST_TAIL,"PSASTRO.CROSSTALKS", PS_DATA_ARRAY, "crosstalk locations", crosstalks)) {
+                psError(PSASTRO_ERR_CONFIG, false, "failure to add crosstalks to readout");
+                goto escape;
+              }
+              psFree(crosstalks);
+            }
+            psArrayAdd(crosstalks,100,crosstalk);
+	    
+            psFree(targetChipName);
+            psFree(targetCellName);
+            psFree(crosstalk);
+          }
+
+
+          // We also want to use the refstars to check for crosstalk. In particular, the detections 
+          // do not do well for bright stars, and saturated detections will underestimate the size of the crostalk
+          // Get the array of reference stars we're concerned with.
+          psArray *refstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.REFSTARS");
+          if (refstars == NULL) { return(true); }
+
+          // Check each reference star
+          for (int i = 0; i < refstars->n; i++) {
+	    // This is the source of the ct.
+            pmAstromObj *ref = refstars->data[i];
+
+            if (ref->Mag > MAX_MAG) {
+              continue;
+            }
+
+            // Identify which cell holds the star
+            pmChip *CTsourceChip = refChip;
+            pmCell *CTsourceCell = pmCellInChip(refChip,ref->chip->x,ref->chip->y);
+
+            if (!CTsourceCell) {
+              continue;
+            }
+
+            psTrace ("psastro.crosstalk",2,"REF: %d %f (%f %f) %f %f :: %f %f\n",
+                     i,ref->Mag, ref->sky->r,ref->sky->d, ref->FP->x,ref->FP->y, ref->chip->x,ref->chip->y);
+
+            const char *cellName = psMetadataLookupStr(NULL,CTsourceCell->concepts, "CELL.NAME");
+            int U = cellName[2] - '0';
+            int V = cellName[3] - '0';
+
+            int Xt = X,Yt = Y,Ut = U,Vt = V;
+            float x_cell,y_cell;
+            float x_t_cell,y_t_cell;
+
+            float x_t_chip,y_t_chip;
+	    // int faint_ct = 0; NOTE: not currently used
+            pmCellCoordsForChip(&x_cell,&y_cell,CTsourceCell,ref->chip->x,ref->chip->y);
+
+            x_t_cell = x_cell;
+            y_t_cell = y_cell;
+
+	    // 2020-10-21 TdB: Here is the list of known cross talks from the bright star analysis:
+            // The relationships work using OTA"XY"XY"UV"
+	    // Inter-chip
+	    // OTA2yXY3v => OTA3yXY3v
+	    // OTA4yXY3v <= OTA5yXY3v
+	    // Intra-chip
+	    // OTA2yXY5v <=> OTA2yXY6v
+	    // OTA5yXY5v <=> OTA5yXY6v
+	    // One way fainter
+	    // OTA2yXY7v => OTA3yXY2v
+	    // OTA5yXY7v => OTA4yXY2v
+            // Determine if this combination of chip and cell produces a crosstalk artifact
+            if ((X == 2)&&(! ((U == 3)||(U == 5)||(U == 6)||(U == 7)))) {
+              psTrace ("psastro.crosstalk",2,"Cell (%d%d) on chip (%d%d) not a known crosstalk source.",U,V,X,Y);
+	      psTrace ("psastro.crosstalk",2,"t1: %d t2: %d",
+		       (X == 2),
+		       (! ((U == 3)||(U == 5)||(U == 6)||(U == 7))));
+              continue;
+            }
+            if ((X == 5)&&(! ((U == 3)||(U == 5)||(U == 6)||(U == 7)))) {
+              psTrace ("psastro.crosstalk",2,"Cell (%d%d) on chip (%d%d) not a known crosstalk source.",U,V,X,Y);
+              continue;
+            }
+
+            // Calculate destination positions
+            if (X == 2) {
+              if (U == 3) {
+                Xt = 3;
+              }
+              if (U == 5) {
+                Ut = 6;
+              }
+              if (U == 6) {
+                Ut = 5;
+              }
+	      if (U == 7) {
+		Xt = 3;
+		Ut = 2;
+		// faint_ct = 1; NOTE: not currently used
+	      }
+            }
+            if (X == 5) {
+              if (U == 3) {
+                Xt = 4;
+              }
+              if (U == 5) {
+                Ut = 6;
+              }
+              if (U == 6) {
+                Ut = 5;
+              }
+	      if (U == 7) {
+		Xt = 4;
+		Ut = 2;
+		// faint_ct = 1; NOTE: not currently used
+	      }
+            }
+
+            // Convert target cell coordinates to target chip coordinates
+            psString targetChipName = NULL;
+            psStringAppend(&targetChipName,"XY%d%d",Xt,Yt);
+            psString targetCellName = NULL;
+            psStringAppend(&targetCellName,"xy%d%d",Ut,Vt);
+
+            psTrace ("psastro.crosstalk",2,"CTsource @ OTA%d%dxy%d%d@%f,%f CTtarget OTA%d%dxy%d%d@%f,%f [%s %s]",
+                     X,Y,U,V,x_cell,y_cell,Xt,Yt,Ut,Vt,x_t_cell,y_t_cell,
+                     targetChipName,targetCellName);
+
+            pmCell *CTtargetCell = getCellByName (CTsourceChip,targetCellName);
+            if (!CTtargetCell) continue;
+
+            pmChipCoordsForCell(&x_t_chip,&y_t_chip,CTtargetCell,x_t_cell,y_t_cell);
+
+            psTrace ("psastro.crosstalk",2,"CTsource @ OTA%d%dxy%d%d@%f,%f CTtarget OTA%d%dxy%d%d@%f,%f ChipLoc: (%f,%f)",
+                     X,Y,U,V,x_cell,y_cell,Xt,Yt,Ut,Vt,x_t_cell,y_t_cell,x_t_chip,y_t_chip);
+
+            // Hunt down the readout for the target, and save the chip position and magnitude of source star.
+            pmChip *targetChip = getChipByName(fpa,targetChipName);
+            if (!targetChip) continue;
+            if (!targetChip->cells) continue;
+            if (!targetChip->cells->n) continue;
+
+            pmCell *targetCell = targetChip->cells->data[0];
+            if (!targetCell) continue;
+            if (!targetCell->readouts) continue;
+            if (!targetCell->readouts->n) continue;
+            pmReadout *targetReadout = targetCell->readouts->data[0];
+            if (!targetReadout) continue;
+
+            pmAstromObj *crosstalk = pmAstromObjAlloc();
+	    
             crosstalk->Mag = ref->Mag - MagOffset;
             crosstalk->chip->x = x_t_chip;
+            crosstalk->chip->y = y_t_chip;
             crosstalk->chip->y = y_t_chip;
 
Index: trunk/psastro/src/psastroLoadGhosts.c
===================================================================
--- trunk/psastro/src/psastroLoadGhosts.c	(revision 41433)
+++ trunk/psastro/src/psastroLoadGhosts.c	(revision 41434)
@@ -41,4 +41,10 @@
     }
 
+// To select good stars, I want them to have a PSFmodel fit (PM_SOURCE_MODE_PSFMODEL & PM_SOURCE_MODE_FITTED) and exlcude things that are CR, EXT, FAIL, POOR 
+// Stars are allowed to be saturated, as long as the PSF model fits
+# define PHOT_SOURCE_MASK (PM_SOURCE_MODE_FAIL | PM_SOURCE_MODE_BLEND | PM_SOURCE_MODE_BADPSF | \
+                           PM_SOURCE_MODE_DEFECT | PM_SOURCE_MODE_CR_LIMIT | PM_SOURCE_MODE_EXT_LIMIT | \
+                           PM_SOURCE_MODE_POOR) // Mask to apply to sources for rejection
+
 /**
  * calculate ghost FPA and Chip positions for the stars loaded on the FPA
@@ -101,5 +107,5 @@
     pmCell *cell = NULL;
     pmReadout *readout = NULL;
-    float zeropt, exptime, MAX_MAG;
+    float zeropt, exptime,MAX_MAG, INSTR_MAX_MAG;
     psMetadata *md = NULL;
     psPolynomial2D *centerX = NULL;
@@ -139,5 +145,5 @@
 
     // raise an error if the config is broken
-    if (!psastroZeroPointFromRecipe (&zeropt, &exptime, &MAX_MAG, NULL, fpa, recipe)) {
+    if (!psastroZeroPointFromRecipe (&zeropt, &exptime, &INSTR_MAX_MAG, NULL, fpa, recipe)) {
         psError(PSASTRO_ERR_CONFIG, true, "failed to load zeropt data from recipe");
 	goto escape;
@@ -147,5 +153,5 @@
     // use the zero point and exposure time to convert to apparent mags: M_ap = M_inst + C_0 + 2.5*log(exptime)
     float MagOffset = zeropt + 2.5*log10(exptime);
-    MAX_MAG += MagOffset;
+    MAX_MAG = INSTR_MAX_MAG + MagOffset;
 
     // this loop selects the matched stars for all chips
@@ -163,4 +169,119 @@
                 if (! readout->data_exists) { continue; }
 
+                //First, select bright sources for ghosts from the detections. Later on, do the same using the refcat
+                // That way we can include things like movers creating crosstalk features.
+                psArray *calstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.CALSTARS");
+                if (calstars == NULL) { continue; }
+
+                // identify the bright stars of interest
+                for (int i = 0; i < calstars->n; i++) {
+                    pmAstromObj *cal = calstars->data[i];
+		    psTrace("psastro.ghost",5,"Begin ghost %d/%ld: MAX_MAG: %g; ref_mag: %g @ (%.10g,%.10g)",i,calstars->n,INSTR_MAX_MAG,cal->Mag,cal->sky->r * 180 / M_PI,cal->sky->d * 180.0 / M_PI);
+
+                    if (cal->Mag > INSTR_MAX_MAG) {
+                        continue;
+                    }
+
+		    psastroGhost *ghost = psastroGhostAlloc ();
+		    ghost->srcFP->x = cal->FP->x; 
+		    ghost->srcFP->y = cal->FP->y;
+
+		    double rSrc = hypot (cal->FP->x, cal->FP->y);
+     	            double theta0 = atan2(cal->FP->x,cal->FP->y);
+
+                    if(mirCheck) {
+                         //TdB: first mirror the reference star positions (around the 0,0 pixel) using the radial offset coefficients and the ghost/star angle
+		        double ghost_offset_rad = psPolynomial1DEval (mirrorRad, rSrc);
+		        double ghost_x_fpa_mirror = cal->FP->x + ((cal->FP->x*-1.)/abs(cal->FP->x)*abs(cos(theta0)*ghost_offset_rad));
+		        double ghost_y_fpa_mirror = cal->FP->y + ((cal->FP->y*-1.)/abs(cal->FP->y)*abs(sin(theta0)*ghost_offset_rad));
+
+		        // Now use the mirrored position together with the 2D ghost center fitting to get the actual ghost position in FPA coords 
+		        ghost->FP->x = ghost_x_fpa_mirror + psPolynomial2DEval(centerX, ghost_x_fpa_mirror, ghost_y_fpa_mirror);
+		        ghost->FP->y = ghost_y_fpa_mirror + psPolynomial2DEval(centerY, ghost_x_fpa_mirror, ghost_y_fpa_mirror);
+                    }  
+                    if(!mirCheck) {
+                        //Use the old-style ghost position determination
+                        ghost->FP->x = -cal->FP->x + psPolynomial2DEval(centerX, -cal->FP->x, -cal->FP->y);
+                        ghost->FP->y = -cal->FP->y + psPolynomial2DEval(centerY, -cal->FP->x, -cal->FP->y);
+                    }
+
+		    ghost->inner.major = psPolynomial1DEval (innerMajor, rSrc);
+		    ghost->inner.minor = psPolynomial1DEval (innerMinor, rSrc);
+		    ghost->inner.theta = atan2(cal->FP->y, cal->FP->x);
+
+		    ghost->outer.major = psPolynomial1DEval (outerMajor, rSrc);
+		    ghost->outer.minor = psPolynomial1DEval (outerMinor, rSrc);
+		    ghost->outer.theta = atan2(cal->FP->y, cal->FP->x);
+
+		    // report instrumental ghost star mags
+		    ghost->Mag = cal->Mag;
+		    
+		    // XXX this code yields a single chip: we need to provide results for any chips
+		    // which encompass the full size of the ghost
+		    pmChip *ghostChip = psastroFindChip (&ghost->chip->x, &ghost->chip->y, fpa, -ghost->srcFP->x, -ghost->srcFP->y);
+/* 		    float star_chip_x = ghost->chip->x; */
+/* 		    float star_chip_y = ghost->chip->y; */
+		    ghostChip = psastroFindChip (&ghost->chip->x, &ghost->chip->y, fpa, ghost->FP->x, ghost->FP->y);
+                    //psLogMsg ("psastro", PS_LOG_INFO, "-> DETEC model chip position: %f, %f %f, %f %g\n", ghost->chip->x, ghost->chip->y,ghost->srcFP->x, ghost->srcFP->y,cal->Mag+MagOffset);
+
+		    if (ghostChip) {
+		      psTrace("psastro.ghost",5,"   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,calstars->n,
+			      cal->FP->x,cal->FP->y,
+			      psMetadataLookupStr(NULL,chip->concepts,"CHIP.NAME"),
+			      ghost->FP->x,ghost->FP->y,
+			      ghost->chip->x,ghost->chip->y,psMetadataLookupStr(NULL,ghostChip->concepts,"CHIP.NAME"),
+			      rSrc,
+			      ghost->inner.major,ghost->inner.minor,ghost->inner.theta,
+			      ghost->outer.major,ghost->outer.minor,ghost->outer.theta);
+/* 		      psWarning("   GHOST_DATA: %d/%ld: ref: (%f,%f) or (%f,%f,%s) ghost: (%f,%f) or (%f,%f,%s) %f inner: (%f,%f,%f) outer: (%f,%f,%f)", */
+/* 			      i,calstars->n, */
+/* 			      cal->FP->x,cal->FP->y, */
+/* 			      ref_chip_x,ref_chip_y,psMetadataLookupStr(NULL,chip->concepts,"CHIP.NAME"), */
+/* 			      ghost->FP->x,ghost->FP->y, */
+/* 			      ghost->chip->x,ghost->chip->y,psMetadataLookupStr(NULL,ghostChip->concepts,"CHIP.NAME"), */
+/* 			      rSrc, */
+/* 			      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)",
+			      i,calstars->n,
+			      cal->FP->x,cal->FP->y,
+			      ghost->FP->x,ghost->FP->y,
+			      ghost->chip->x,ghost->chip->y,"NONE",
+			      ghost->inner.major,ghost->inner.minor,ghost->inner.theta,
+			      ghost->outer.major,ghost->outer.minor,ghost->outer.theta);
+		    }		      
+		      			    
+		    if (!ghostChip) goto skip;
+		    if (!ghostChip->cells) goto skip;
+		    if (!ghostChip->cells->n) goto skip;
+
+		    
+		    pmCell *ghostCell = ghostChip->cells->data[0];
+		    if (!ghostCell) goto skip;
+		    if (!ghostCell->readouts) goto skip;
+		    if (!ghostCell->readouts->n) goto skip;
+		    pmReadout *ghostReadout = ghostCell->readouts->data[0];
+		    if (!ghostReadout) goto skip;
+
+		    psArray *ghosts = psMetadataLookupPtr (&status, ghostReadout->analysis, "PSASTRO.GHOSTS");
+		    if (ghosts == NULL) { 
+			ghosts = psArrayAllocEmpty (100);
+			if (!psMetadataAdd (ghostReadout->analysis, PS_LIST_TAIL, "PSASTRO.GHOSTS", PS_DATA_ARRAY, "astrometry matches", ghosts)) {
+			  psError(PSASTRO_ERR_CONFIG, false, "failure to add ghosts to readout");
+			  goto escape;
+			}
+			psFree (ghosts);
+		    }
+
+		    psArrayAdd (ghosts, 100, ghost);
+
+		skip:
+		    
+		    psFree (ghost);
+                }
+
                 // select the raw objects for this readout (loaded in psastroChooseRefstars.c)
 		// XXX : note that we place limits on the refstar sample in psastroChooseRefstars.c:
@@ -173,4 +294,5 @@
                     pmAstromObj *ref = refstars->data[i];
 		    psTrace("psastro.ghost",5,"Begin ghost %d/%ld: MAX_MAG: %g; ref_mag: %g @ (%.10g,%.10g)",i,refstars->n,MAX_MAG,ref->Mag,ref->sky->r * 180 / M_PI,ref->sky->d * 180.0 / M_PI);
+
                     if (ref->Mag > MAX_MAG) continue;
 
@@ -224,6 +346,5 @@
 /* 		    float ref_chip_y = ghost->chip->y; */
 		    ghostChip = psastroFindChip (&ghost->chip->x, &ghost->chip->y, fpa, ghost->FP->x, ghost->FP->y);
-		    // fprintf (stderr, "-> model chip position: %f, %f\n", ghost->chip->x, ghost->chip->y);
-
+                    //psLogMsg ("psastro", PS_LOG_INFO, "-> model chip position: %f, %f %f, %f %g\n", ghost->chip->x, ghost->chip->y,ghost->srcFP->x, ghost->srcFP->y,ref->Mag);
 
 		    if (ghostChip) {
@@ -257,15 +378,15 @@
 		    }		      
 		      			    
-		    if (!ghostChip) goto skip;
-		    if (!ghostChip->cells) goto skip;
-		    if (!ghostChip->cells->n) goto skip;
+		    if (!ghostChip) goto skipref;
+		    if (!ghostChip->cells) goto skipref;
+		    if (!ghostChip->cells->n) goto skipref;
 
 		    
 		    pmCell *ghostCell = ghostChip->cells->data[0];
-		    if (!ghostCell) goto skip;
-		    if (!ghostCell->readouts) goto skip;
-		    if (!ghostCell->readouts->n) goto skip;
+		    if (!ghostCell) goto skipref;
+		    if (!ghostCell->readouts) goto skipref;
+		    if (!ghostCell->readouts->n) goto skipref;
 		    pmReadout *ghostReadout = ghostCell->readouts->data[0];
-		    if (!ghostReadout) goto skip;
+		    if (!ghostReadout) goto skipref;
 
 		    psArray *ghosts = psMetadataLookupPtr (&status, ghostReadout->analysis, "PSASTRO.GHOSTS");
@@ -281,8 +402,9 @@
 		    psArrayAdd (ghosts, 100, ghost);
 
-		skip:
+		skipref:
 		    
 		    psFree (ghost);
                 }
+
             }
         }
Index: trunk/psastro/src/psastroLoadGlints.c
===================================================================
--- trunk/psastro/src/psastroLoadGlints.c	(revision 41433)
+++ trunk/psastro/src/psastroLoadGlints.c	(revision 41434)
@@ -307,5 +307,5 @@
 		   	  psFree (glints);
 		   	}
-		   			   	psVector *glint = psVectorAlloc(5,PS_TYPE_F32);
+                        psVector *glint = psVectorAlloc(5,PS_TYPE_F32);
 		   	glint->data.F32[0] = xChip0;
 		   	glint->data.F32[1] = yChip0;
Index: trunk/psastro/src/psastroUtils.c
===================================================================
--- trunk/psastro/src/psastroUtils.c	(revision 41433)
+++ trunk/psastro/src/psastroUtils.c	(revision 41434)
@@ -132,4 +132,14 @@
 		    psPlaneTransformApply (raw->TP, fpa->toTPA, raw->FP);
 		    psDeproject (raw->sky, raw->TP, fpa->toSky);
+		}
+	    }
+
+	    psArray *calstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.CALSTARS");
+	    if (calstars) { 
+		for (int i = 0; i < calstars->n; i++) {
+		    pmAstromObj *cal = calstars->data[i];
+		    psPlaneTransformApply (cal->FP, chip->toFPA, cal->chip);
+		    psPlaneTransformApply (cal->TP, fpa->toTPA, cal->FP);
+		    psDeproject (cal->sky, cal->TP, fpa->toSky);
 		}
 	    }
