Index: trunk/psastro/src/psastroLoadCrosstalk.c
===================================================================
--- trunk/psastro/src/psastroLoadCrosstalk.c	(revision 41430)
+++ 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;
 
