Index: trunk/Ohana/src/addstar/src/ReadStarsFITS.c
===================================================================
--- trunk/Ohana/src/addstar/src/ReadStarsFITS.c	(revision 34422)
+++ trunk/Ohana/src/addstar/src/ReadStarsFITS.c	(revision 34429)
@@ -606,4 +606,5 @@
     stars[i].measure.psfChisq   = ps1data[i].psfChisq;
     stars[i].measure.psfQF      = ps1data[i].psfQF;
+    stars[i].measure.psfQFperf  = ps1data[i].psfQFpef;
     stars[i].measure.psfNdof    = ps1data[i].psfNdof;
     stars[i].measure.psfNpix    = ps1data[i].psfNpix;
@@ -675,4 +676,170 @@
     stars[i].measure.dMkron     = (ps1data[i].kronFlux > 0.0) ? ps1data[i].kronFluxErr / ps1data[i].kronFlux : NAN;
                         
+    // these fluxes are converted from counts to counts/sec in FilterStars.c
+    stars[i].measure.FluxPSF    = ps1data[i].Flux;
+    stars[i].measure.dFluxPSF   = ps1data[i].dFlux;
+    stars[i].measure.FluxKron   = ps1data[i].kronFlux;
+    stars[i].measure.dFluxKron  = ps1data[i].kronFluxErr;
+
+    stars[i].measure.Sky        = ps1data[i].sky;
+    stars[i].measure.dSky       = ps1data[i].dSky;
+                        
+    stars[i].measure.psfChisq   = ps1data[i].psfChisq;
+    stars[i].measure.psfQF      = ps1data[i].psfQF;
+    stars[i].measure.psfQFperf  = ps1data[i].psfQFpef;
+    stars[i].measure.psfNdof    = ps1data[i].psfNdof;
+    stars[i].measure.psfNpix    = ps1data[i].psfNpix;
+    stars[i].measure.crNsigma   = ps1data[i].crNsigma;
+    stars[i].measure.extNsigma  = ps1data[i].extNsigma;
+
+    stars[i].measure.FWx        = ToShortPixels(ps1data[i].fx);
+    stars[i].measure.FWy        = ToShortPixels(ps1data[i].fy);
+    stars[i].measure.theta      = ToShortDegrees(ps1data[i].df);
+
+    stars[i].measure.Mxx        = ToShortPixels(ps1data[i].Mxx);
+    stars[i].measure.Mxy        = ToShortPixels(ps1data[i].Mxy);
+    stars[i].measure.Myy        = ToShortPixels(ps1data[i].Myy);
+                        
+    stars[i].measure.photFlags  = ps1data[i].flags;
+
+    // this is may optionally be replaced by the internal sequence (see FilterStars.c)
+    stars[i].measure.detID      = ps1data[i].detID; 
+
+    // the Average fields and the following Measure fields are set in FilterStars after
+    // the image metadata is in hand:  dR, dD, Mcal, dt, airmass, az, t, imageID, extID.
+
+    // averef is set in find_matches
+
+    // dbFlags is zero on ingest.
+
+    // the following fields are currently not being set anywhere: t_msec
+  }    
+  *nstars = Nstars;
+  return (stars);
+}
+
+Stars *Convert_PS1_SV1 (FTable *table, unsigned int *nstars) {
+
+  off_t Nstars; 
+  unsigned int i;
+  double ZeroPt;
+  Stars *stars;
+  CMF_PS1_SV1 *ps1data;
+
+  if (table[0].header[0].Naxis[0] == 196) {
+    stars = Convert_PS1_SV1_Alt (table, nstars);
+    return (stars);
+  }
+
+  ps1data = gfits_table_get_CMF_PS1_SV1 (table, &Nstars, NULL);
+  if (!ps1data) {
+    fprintf (stderr, "skipping inconsistent entry\n");
+    return (NULL);
+  }
+  ZeroPt = GetZeroPoint();
+
+  ALLOCATE (stars, Stars, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    InitStar (&stars[i]);
+    stars[i].measure.Xccd       = ps1data[i].X;
+    stars[i].measure.Yccd       = ps1data[i].Y;
+    stars[i].measure.dXccd      = ToShortPixels(ps1data[i].dX);
+    stars[i].measure.dYccd      = ToShortPixels(ps1data[i].dY);
+
+    stars[i].measure.posangle   = ToShortDegrees(ps1data[i].posangle);
+    stars[i].measure.pltscale   = ps1data[i].pltscale;
+
+    if ((ps1data[i].M >= 0.0) || isnan(ps1data[i].M)) {
+      stars[i].measure.M      = NAN;
+    } else {
+      stars[i].measure.M      = ps1data[i].M + ZeroPt;
+    }
+    stars[i].measure.dM         = ps1data[i].dM;
+    stars[i].measure.dMcal      = ps1data[i].dMcal;
+    stars[i].measure.Map        = ps1data[i].Map + ZeroPt;
+                        
+    stars[i].measure.Mkron      = (ps1data[i].kronFlux > 0.0) ? -2.5*log10(ps1data[i].kronFlux) + ZeroPt : NAN;
+    stars[i].measure.dMkron     = (ps1data[i].kronFlux > 0.0) ? ps1data[i].kronFluxErr / ps1data[i].kronFlux : NAN;
+
+    // these fluxes are converted from counts to counts/sec in FilterStars.c
+    stars[i].measure.FluxPSF    = ps1data[i].Flux;
+    stars[i].measure.dFluxPSF   = ps1data[i].dFlux;
+    stars[i].measure.FluxKron   = ps1data[i].kronFlux;
+    stars[i].measure.dFluxKron  = ps1data[i].kronFluxErr;
+
+    stars[i].measure.Sky        = ps1data[i].sky;
+    stars[i].measure.dSky       = ps1data[i].dSky;
+                        
+    stars[i].measure.psfChisq   = ps1data[i].psfChisq;
+    stars[i].measure.psfQF      = ps1data[i].psfQF;
+    stars[i].measure.psfQFperf  = ps1data[i].psfQFpef;
+    stars[i].measure.psfNdof    = ps1data[i].psfNdof;
+    stars[i].measure.psfNpix    = ps1data[i].psfNpix;
+    stars[i].measure.crNsigma   = ps1data[i].crNsigma;
+    stars[i].measure.extNsigma  = ps1data[i].extNsigma;
+
+    stars[i].measure.FWx        = ToShortPixels(ps1data[i].fx);
+    stars[i].measure.FWy        = ToShortPixels(ps1data[i].fy);
+    stars[i].measure.theta      = ToShortDegrees(ps1data[i].df);
+
+    stars[i].measure.Mxx        = ToShortPixels(ps1data[i].Mxx);
+    stars[i].measure.Mxy        = ToShortPixels(ps1data[i].Mxy);
+    stars[i].measure.Myy        = ToShortPixels(ps1data[i].Myy);
+                        
+    stars[i].measure.photFlags  = ps1data[i].flags;
+
+    // this is may optionally be replaced by the internal sequence (see FilterStars.c)
+    stars[i].measure.detID      = ps1data[i].detID; 
+
+    // the Average fields and the following Measure fields are set in FilterStars after
+    // the image metadata is in hand:  dR, dD, Mcal, dt, airmass, az, t, imageID, extID, 
+    // averef is set in find_matches, dbFlags is zero on ingest.
+
+    // the following fields are currently not being set anywhere: t_msec
+  }    
+  *nstars = Nstars;
+  return (stars);
+}
+
+Stars *Convert_PS1_SV1_Alt (FTable *table, unsigned int *nstars) {
+
+  off_t Nstars; 
+  unsigned int i;
+  double ZeroPt;
+  Stars *stars;
+  CMF_PS1_SV1 *ps1data;
+
+  // some test output files were produced called CMF_PS1_SV1 but with mismatch byte boundaries
+
+  ps1data = gfits_table_get_CMF_PS1_SV1_Alt (table, &Nstars, NULL);
+  if (!ps1data) {
+    fprintf (stderr, "skipping inconsistent entry\n");
+    return (NULL);
+  }
+  ZeroPt = GetZeroPoint();
+
+  ALLOCATE (stars, Stars, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    InitStar (&stars[i]);
+    stars[i].measure.Xccd       = ps1data[i].X;
+    stars[i].measure.Yccd       = ps1data[i].Y;
+    stars[i].measure.dXccd      = ToShortPixels(ps1data[i].dX);
+    stars[i].measure.dYccd      = ToShortPixels(ps1data[i].dY);
+
+    stars[i].measure.posangle   = ToShortDegrees(ps1data[i].posangle);
+    stars[i].measure.pltscale   = ps1data[i].pltscale;
+
+    if ((ps1data[i].M >= 0.0) || isnan(ps1data[i].M)) {
+      stars[i].measure.M      = NAN;
+    } else {
+      stars[i].measure.M      = ps1data[i].M + ZeroPt;
+    }
+    stars[i].measure.dM         = ps1data[i].dM;
+    stars[i].measure.dMcal      = ps1data[i].dMcal;
+    stars[i].measure.Map        = ps1data[i].Map + ZeroPt;
+                        
+    stars[i].measure.Mkron      = (ps1data[i].kronFlux > 0.0) ? -2.5*log10(ps1data[i].kronFlux) + ZeroPt : NAN;
+    stars[i].measure.dMkron     = (ps1data[i].kronFlux > 0.0) ? ps1data[i].kronFluxErr / ps1data[i].kronFlux : NAN;
+
     // these fluxes are converted from counts to counts/sec in FilterStars.c
     stars[i].measure.FluxPSF    = ps1data[i].Flux;
@@ -705,9 +872,6 @@
 
     // the Average fields and the following Measure fields are set in FilterStars after
-    // the image metadata is in hand:  dR, dD, Mcal, dt, airmass, az, t, imageID, extID.
-
-    // averef is set in find_matches
-
-    // dbFlags is zero on ingest.
+    // the image metadata is in hand:  dR, dD, Mcal, dt, airmass, az, t, imageID, extID, 
+    // averef is set in find_matches, dbFlags is zero on ingest.
 
     // the following fields are currently not being set anywhere: t_msec
@@ -717,5 +881,5 @@
 }
 
-Stars *Convert_PS1_SV1 (FTable *table, unsigned int *nstars) {
+Stars *Convert_PS1_SV2 (FTable *table, unsigned int *nstars) {
 
   off_t Nstars; 
@@ -723,12 +887,7 @@
   double ZeroPt;
   Stars *stars;
-  CMF_PS1_SV1 *ps1data;
-
-  if (table[0].header[0].Naxis[0] == 196) {
-    stars = Convert_PS1_SV1_Alt (table, nstars);
-    return (stars);
-  }
-
-  ps1data = gfits_table_get_CMF_PS1_SV1 (table, &Nstars, NULL);
+  CMF_PS1_SV2 *ps1data;
+
+  ps1data = gfits_table_get_CMF_PS1_SV2 (table, &Nstars, NULL);
   if (!ps1data) {
     fprintf (stderr, "skipping inconsistent entry\n");
@@ -771,4 +930,5 @@
     stars[i].measure.psfChisq   = ps1data[i].psfChisq;
     stars[i].measure.psfQF      = ps1data[i].psfQF;
+    stars[i].measure.psfQFperf  = ps1data[i].psfQFpef;
     stars[i].measure.psfNdof    = ps1data[i].psfNdof;
     stars[i].measure.psfNpix    = ps1data[i].psfNpix;
@@ -799,159 +959,3 @@
 }
 
-Stars *Convert_PS1_SV1_Alt (FTable *table, unsigned int *nstars) {
-
-  off_t Nstars; 
-  unsigned int i;
-  double ZeroPt;
-  Stars *stars;
-  CMF_PS1_SV1 *ps1data;
-
-  // some test output files were produced called CMF_PS1_SV1 but with mismatch byte boundaries
-
-  ps1data = gfits_table_get_CMF_PS1_SV1_Alt (table, &Nstars, NULL);
-  if (!ps1data) {
-    fprintf (stderr, "skipping inconsistent entry\n");
-    return (NULL);
-  }
-  ZeroPt = GetZeroPoint();
-
-  ALLOCATE (stars, Stars, Nstars);
-  for (i = 0; i < Nstars; i++) {
-    InitStar (&stars[i]);
-    stars[i].measure.Xccd       = ps1data[i].X;
-    stars[i].measure.Yccd       = ps1data[i].Y;
-    stars[i].measure.dXccd      = ToShortPixels(ps1data[i].dX);
-    stars[i].measure.dYccd      = ToShortPixels(ps1data[i].dY);
-
-    stars[i].measure.posangle   = ToShortDegrees(ps1data[i].posangle);
-    stars[i].measure.pltscale   = ps1data[i].pltscale;
-
-    if ((ps1data[i].M >= 0.0) || isnan(ps1data[i].M)) {
-      stars[i].measure.M      = NAN;
-    } else {
-      stars[i].measure.M      = ps1data[i].M + ZeroPt;
-    }
-    stars[i].measure.dM         = ps1data[i].dM;
-    stars[i].measure.dMcal      = ps1data[i].dMcal;
-    stars[i].measure.Map        = ps1data[i].Map + ZeroPt;
-                        
-    stars[i].measure.Mkron      = (ps1data[i].kronFlux > 0.0) ? -2.5*log10(ps1data[i].kronFlux) + ZeroPt : NAN;
-    stars[i].measure.dMkron     = (ps1data[i].kronFlux > 0.0) ? ps1data[i].kronFluxErr / ps1data[i].kronFlux : NAN;
-
-    // these fluxes are converted from counts to counts/sec in FilterStars.c
-    stars[i].measure.FluxPSF    = ps1data[i].Flux;
-    stars[i].measure.dFluxPSF   = ps1data[i].dFlux;
-    stars[i].measure.FluxKron   = ps1data[i].kronFlux;
-    stars[i].measure.dFluxKron  = ps1data[i].kronFluxErr;
-
-    stars[i].measure.Sky        = ps1data[i].sky;
-    stars[i].measure.dSky       = ps1data[i].dSky;
-                        
-    stars[i].measure.psfChisq   = ps1data[i].psfChisq;
-    stars[i].measure.psfQF      = ps1data[i].psfQF;
-    stars[i].measure.psfNdof    = ps1data[i].psfNdof;
-    stars[i].measure.psfNpix    = ps1data[i].psfNpix;
-    stars[i].measure.crNsigma   = ps1data[i].crNsigma;
-    stars[i].measure.extNsigma  = ps1data[i].extNsigma;
-
-    stars[i].measure.FWx        = ToShortPixels(ps1data[i].fx);
-    stars[i].measure.FWy        = ToShortPixels(ps1data[i].fy);
-    stars[i].measure.theta      = ToShortDegrees(ps1data[i].df);
-
-    stars[i].measure.Mxx        = ToShortPixels(ps1data[i].Mxx);
-    stars[i].measure.Mxy        = ToShortPixels(ps1data[i].Mxy);
-    stars[i].measure.Myy        = ToShortPixels(ps1data[i].Myy);
-                        
-    stars[i].measure.photFlags  = ps1data[i].flags;
-
-    // this is may optionally be replaced by the internal sequence (see FilterStars.c)
-    stars[i].measure.detID      = ps1data[i].detID; 
-
-    // the Average fields and the following Measure fields are set in FilterStars after
-    // the image metadata is in hand:  dR, dD, Mcal, dt, airmass, az, t, imageID, extID, 
-    // averef is set in find_matches, dbFlags is zero on ingest.
-
-    // the following fields are currently not being set anywhere: t_msec
-  }    
-  *nstars = Nstars;
-  return (stars);
-}
-
-Stars *Convert_PS1_SV2 (FTable *table, unsigned int *nstars) {
-
-  off_t Nstars; 
-  unsigned int i;
-  double ZeroPt;
-  Stars *stars;
-  CMF_PS1_SV2 *ps1data;
-
-  ps1data = gfits_table_get_CMF_PS1_SV2 (table, &Nstars, NULL);
-  if (!ps1data) {
-    fprintf (stderr, "skipping inconsistent entry\n");
-    return (NULL);
-  }
-  ZeroPt = GetZeroPoint();
-
-  ALLOCATE (stars, Stars, Nstars);
-  for (i = 0; i < Nstars; i++) {
-    InitStar (&stars[i]);
-    stars[i].measure.Xccd       = ps1data[i].X;
-    stars[i].measure.Yccd       = ps1data[i].Y;
-    stars[i].measure.dXccd      = ToShortPixels(ps1data[i].dX);
-    stars[i].measure.dYccd      = ToShortPixels(ps1data[i].dY);
-
-    stars[i].measure.posangle   = ToShortDegrees(ps1data[i].posangle);
-    stars[i].measure.pltscale   = ps1data[i].pltscale;
-
-    if ((ps1data[i].M >= 0.0) || isnan(ps1data[i].M)) {
-      stars[i].measure.M      = NAN;
-    } else {
-      stars[i].measure.M      = ps1data[i].M + ZeroPt;
-    }
-    stars[i].measure.dM         = ps1data[i].dM;
-    stars[i].measure.dMcal      = ps1data[i].dMcal;
-    stars[i].measure.Map        = ps1data[i].Map + ZeroPt;
-                        
-    stars[i].measure.Mkron      = (ps1data[i].kronFlux > 0.0) ? -2.5*log10(ps1data[i].kronFlux) + ZeroPt : NAN;
-    stars[i].measure.dMkron     = (ps1data[i].kronFlux > 0.0) ? ps1data[i].kronFluxErr / ps1data[i].kronFlux : NAN;
-
-    // these fluxes are converted from counts to counts/sec in FilterStars.c
-    stars[i].measure.FluxPSF    = ps1data[i].Flux;
-    stars[i].measure.dFluxPSF   = ps1data[i].dFlux;
-    stars[i].measure.FluxKron   = ps1data[i].kronFlux;
-    stars[i].measure.dFluxKron  = ps1data[i].kronFluxErr;
-
-    stars[i].measure.Sky        = ps1data[i].sky;
-    stars[i].measure.dSky       = ps1data[i].dSky;
-                        
-    stars[i].measure.psfChisq   = ps1data[i].psfChisq;
-    stars[i].measure.psfQF      = ps1data[i].psfQF;
-    stars[i].measure.psfNdof    = ps1data[i].psfNdof;
-    stars[i].measure.psfNpix    = ps1data[i].psfNpix;
-    stars[i].measure.crNsigma   = ps1data[i].crNsigma;
-    stars[i].measure.extNsigma  = ps1data[i].extNsigma;
-
-    stars[i].measure.FWx        = ToShortPixels(ps1data[i].fx);
-    stars[i].measure.FWy        = ToShortPixels(ps1data[i].fy);
-    stars[i].measure.theta      = ToShortDegrees(ps1data[i].df);
-
-    stars[i].measure.Mxx        = ToShortPixels(ps1data[i].Mxx);
-    stars[i].measure.Mxy        = ToShortPixels(ps1data[i].Mxy);
-    stars[i].measure.Myy        = ToShortPixels(ps1data[i].Myy);
-                        
-    stars[i].measure.photFlags  = ps1data[i].flags;
-
-    // this is may optionally be replaced by the internal sequence (see FilterStars.c)
-    stars[i].measure.detID      = ps1data[i].detID; 
-
-    // the Average fields and the following Measure fields are set in FilterStars after
-    // the image metadata is in hand:  dR, dD, Mcal, dt, airmass, az, t, imageID, extID, 
-    // averef is set in find_matches, dbFlags is zero on ingest.
-
-    // the following fields are currently not being set anywhere: t_msec
-  }    
-  *nstars = Nstars;
-  return (stars);
-}
-
-
+
Index: trunk/Ohana/src/libdvo/include/dvo.h
===================================================================
--- trunk/Ohana/src/libdvo/include/dvo.h	(revision 34422)
+++ trunk/Ohana/src/libdvo/include/dvo.h	(revision 34429)
@@ -149,27 +149,28 @@
 /* Average.flags values -- these values are 32 bit (as of PS1_V1) */
 typedef enum {
-  ID_STAR_FEW     = 0x00000001, // used within relphot: skip star
-  ID_STAR_POOR    = 0x00000002, // used within relphot: skip star
-  ID_PROPER       = 0x00000400, // star with large proper motion
-  ID_TRANSIENT    = 0x00001000, // is this mutually exclusive with USNO?
-  ID_VARIABLE     = 0x00002000, // not currently set?
-  ID_ASTEROID     = 0x00002000, // identified with an asteroid
-  ID_BAD_OBJECT   = 0x00004000, // if all measurements are bad, set this bit
-  ID_MOVING       = 0x00008000, // is a moving object
-  ID_ROCK         = 0x0000a000, // 0x8000 + 0x2000
-  ID_GHOST        = 0x0000c001, // 0x8000 + 0x4000 + 0x0001
-  ID_TRAIL        = 0x0000c002, // 0x8000 + 0x4000 + 0x0002
-  ID_BLEED        = 0x0000c003, // 0x8000 + 0x4000 + 0x0003
-  ID_COSMIC       = 0x0000c004, // 0x8000 + 0x4000 + 0x0004
-  ID_STAR_FIT_AVE = 0x00010000, // average position fitted
-  ID_STAR_FIT_PM  = 0x00020000, // proper motion fitted
-  ID_STAR_FIT_PAR = 0x00040000, // parallax fitted
-  ID_STAR_USE_AVE = 0x00080000, // average position used (not PM or PAR)
-  ID_STAR_USE_PM  = 0x00100000, // proper motion used (not AVE or PAR)
-  ID_STAR_USE_PAR = 0x00200000, // parallax used (not AVE or PM)
-  ID_OBJ_EXT      = 0x01000000, // extended in our data (eg, PS)
-  ID_OBJ_EXT_ALT  = 0x02000000, // extended in external data (eg, 2MASS)
-  ID_OBJ_GOOD     = 0x04000000, // good-quality measurement in our data (eg,PS)
-  ID_OBJ_GOOD_ALT = 0x08000000, // good-quality measurement in  external data (eg, 2MASS)
+  ID_STAR_FEW       = 0x00000001, // used within relphot: skip star
+  ID_STAR_POOR      = 0x00000002, // used within relphot: skip star
+  ID_PROPER         = 0x00000400, // star with large proper motion
+  ID_TRANSIENT      = 0x00001000, // is this mutually exclusive with USNO?
+  ID_VARIABLE       = 0x00002000, // not currently set?
+  ID_ASTEROID       = 0x00002000, // identified with an asteroid
+  ID_BAD_OBJECT     = 0x00004000, // if all measurements are bad, set this bit
+  ID_MOVING         = 0x00008000, // is a moving object
+  ID_ROCK           = 0x0000a000, // 0x8000 + 0x2000
+  ID_GHOST          = 0x0000c001, // 0x8000 + 0x4000 + 0x0001
+  ID_TRAIL          = 0x0000c002, // 0x8000 + 0x4000 + 0x0002
+  ID_BLEED          = 0x0000c003, // 0x8000 + 0x4000 + 0x0003
+  ID_COSMIC         = 0x0000c004, // 0x8000 + 0x4000 + 0x0004
+  ID_STAR_FIT_AVE   = 0x00010000, // average position fitted
+  ID_STAR_FIT_PM    = 0x00020000, // proper motion fitted
+  ID_STAR_FIT_PAR   = 0x00040000, // parallax fitted
+  ID_STAR_USE_AVE   = 0x00080000, // average position used (not PM or PAR)
+  ID_STAR_USE_PM    = 0x00100000, // proper motion used (not AVE or PAR)
+  ID_STAR_USE_PAR   = 0x00200000, // parallax used (not AVE or PM)
+  ID_STAR_NO_ASTROM = 0x00400000, // mean astrometry could not be measured
+  ID_OBJ_EXT        = 0x01000000, // extended in our data (eg, PS)
+  ID_OBJ_EXT_ALT    = 0x02000000, // extended in external data (eg, 2MASS)
+  ID_OBJ_GOOD       = 0x04000000, // good-quality measurement in our data (eg,PS)
+  ID_OBJ_GOOD_ALT   = 0x08000000, // good-quality measurement in  external data (eg, 2MASS)
 } DVOAverageFlags;
 
@@ -180,4 +181,6 @@
   ID_SECF_USE_SYNTH   = 0x00000004, // synthetic photometry used in average measurement
   ID_SECF_USE_UBERCAL = 0x00000008, // synthetic photometry used in average measurement
+  ID_SECF_HAS_PS1     = 0x00000010, // PS1 photometry used in average measurement
+  ID_SECF_HAS_STACK   = 0x00000020, // PS1 stack photometry exists
   ID_PHOTOM_PASS_0    = 0x00000100, // average magnitude calculated in 0th pass
   ID_PHOTOM_PASS_1    = 0x00000200, // average magnitude calculated in 1th pass
Index: trunk/Ohana/src/libdvo/src/dvo_catalog.c
===================================================================
--- trunk/Ohana/src/libdvo/src/dvo_catalog.c	(revision 34422)
+++ trunk/Ohana/src/libdvo/src/dvo_catalog.c	(revision 34429)
@@ -89,4 +89,7 @@
   average->Trange   	   = 0;
 
+  average->psfQF   	   = 0.0;
+  average->psfQFperf   	   = 0.0;
+
   average->stargal    	   = 0.0;
   average->Npos    	   = 0;
Index: trunk/Ohana/src/relastro/src/UpdateObjects.c
===================================================================
--- trunk/Ohana/src/relastro/src/UpdateObjects.c	(revision 34422)
+++ trunk/Ohana/src/relastro/src/UpdateObjects.c	(revision 34429)
@@ -168,9 +168,9 @@
       }
 
-      // if we have too few good detections for the desired fit, or too limited a baseline, use a
-      // fit with fewer parameters.  XXX if we have too few parameters for even the average
-      // position, consider including the lower-quality detections
-
-      catalog[i].average[j].flags &= ~ID_STAR_FEW;
+      // if we have too few good detections for the desired fit, or too limited a
+      // baseline, use a fit with fewer parameters.  XXX if we have too few measurements
+      // for even the average position, consider including the lower-quality detections?
+
+      catalog[i].average[j].flags &= ~ID_STAR_NO_ASTROM;
 
       // find Tmin & Tmax from the list of accepted measurements
@@ -197,5 +197,5 @@
 	// XXX need to define PHOTOM and ASTROM object flags
 	// XXX reset the average value fields?
-	catalog[i].average[j].flags |= ID_STAR_FEW;
+	catalog[i].average[j].flags |= ID_STAR_NO_ASTROM;
 	catalog[i].average[j].ChiSqAve  = NAN;
 	catalog[i].average[j].ChiSqPM   = NAN;
Index: trunk/Ohana/src/relastro/src/bcatalog.c
===================================================================
--- trunk/Ohana/src/relastro/src/bcatalog.c	(revision 34422)
+++ trunk/Ohana/src/relastro/src/bcatalog.c	(revision 34429)
@@ -26,12 +26,11 @@
 
   DVOAverageFlags averageBits = 
-    ID_STAR_FEW     |
-    ID_STAR_POOR    |
-    ID_STAR_FIT_AVE |
-    ID_STAR_FIT_PM  |
-    ID_STAR_FIT_PAR |
-    ID_STAR_USE_AVE |
-    ID_STAR_USE_PM  |
-    ID_STAR_USE_PAR; 
+    ID_STAR_FIT_AVE   |
+    ID_STAR_FIT_PM    |
+    ID_STAR_FIT_PAR   |
+    ID_STAR_USE_AVE   |
+    ID_STAR_USE_PM    |
+    ID_STAR_USE_PAR   |
+    ID_STAR_NO_ASTROM ; 
 
   /* exclude stars not in range or with too few measurements */
Index: trunk/Ohana/src/relastro/src/initialize.c
===================================================================
--- trunk/Ohana/src/relastro/src/initialize.c	(revision 34422)
+++ trunk/Ohana/src/relastro/src/initialize.c	(revision 34429)
@@ -19,8 +19,4 @@
 
   initstats (STATMODE);
-
-  // IMAGE_BAD = ID_IMAGE_ASTROM_POOR | ID_IMAGE_ASTROM_FEW | ID_IMAGE_ASTROM_SKIP;
-  // STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
-  // MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR_ASTROM | ID_MEAS_SKIP_ASTROM | ID_MEAS_AREA;
 
   /* XXX drop irrelevant entries */
@@ -57,8 +53,4 @@
 
   initstats (STATMODE);
-
-  // IMAGE_BAD = ID_IMAGE_ASTROM_POOR | ID_IMAGE_ASTROM_FEW | ID_IMAGE_ASTROM_SKIP;
-  // STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
-  // MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR_ASTROM | ID_MEAS_SKIP_ASTROM | ID_MEAS_AREA;
 }
 
Index: trunk/Ohana/src/relastro/src/liststats.c
===================================================================
--- trunk/Ohana/src/relastro/src/liststats.c	(revision 34422)
+++ trunk/Ohana/src/relastro/src/liststats.c	(revision 34429)
@@ -136,5 +136,5 @@
     dS += M;
   }
-  X2 = X2 / Nm;
+  X2 = X2 / (Nm - 1);
   dS = sqrt (dS / Nm);
 
Index: trunk/Ohana/src/relastro/src/relastro_objects.c
===================================================================
--- trunk/Ohana/src/relastro/src/relastro_objects.c	(revision 34422)
+++ trunk/Ohana/src/relastro/src/relastro_objects.c	(revision 34429)
@@ -16,12 +16,11 @@
 
   DVOAverageFlags averageBits = 
-    ID_STAR_FEW     |
-    ID_STAR_POOR    |
-    ID_STAR_FIT_AVE |
-    ID_STAR_FIT_PM  |
-    ID_STAR_FIT_PAR |
-    ID_STAR_USE_AVE |
-    ID_STAR_USE_PM  |
-    ID_STAR_USE_PAR; 
+    ID_STAR_FIT_AVE   |
+    ID_STAR_FIT_PM    |
+    ID_STAR_FIT_PAR   |
+    ID_STAR_USE_AVE   |
+    ID_STAR_USE_PM    |
+    ID_STAR_USE_PAR   |
+    ID_STAR_NO_ASTROM ; 
 
   // XXX need to decide how to determine PARALLEL mode...
Index: trunk/Ohana/src/relphot/src/StarOps.c
===================================================================
--- trunk/Ohana/src/relphot/src/StarOps.c	(revision 34422)
+++ trunk/Ohana/src/relphot/src/StarOps.c	(revision 34429)
@@ -11,10 +11,19 @@
   int Nmos;
   int Ngrid;
-  double *list;
-  double *dlist;
-  double *wlist;
-  double *aplist;
-  double *kronlist;
-  double *dkronlist;
+
+  // NOTE: the following arrays are (possibly) pre-allocated and carried down to each
+  // thread.  The first 3 (list, dlist, wlist) are used in all relphot analyses; the
+  // others are only used on the final output steps.
+
+  double *list;		      // list of measure.mag values for a given star
+  double *dlist;	      // mag errors for a star
+  double *wlist;	      // weights to use for mean mags
+  double *aplist;	      // ap mags for a star
+  double *kronlist;	      // kron mags for a star
+  double *dkronlist;	      // kron mag errors 
+
+  double *psfqf_list;	      // psfqf for all filters
+  double *psfqfperf_list;     // psfqfperf for all filters
+  double *stargal_list;	      // stargal for all filters
 } SetMrelInfo;
 
@@ -168,4 +177,8 @@
   ALLOCATE (results.dkronlist, double, Nmax);
 
+  ALLOCATE (results.psfqf_list, double, Nmax);
+  ALLOCATE (results.psfqfperf_list, double, Nmax);
+  ALLOCATE (results.stargal_list, double, Nmax);
+
   for (i = 0; i < Ncatalog; i++) {
     setMrel_catalog  (catalog, i, pass, flatcorr, &results, Nsecfilt); // XXX add arguments as needed for options
@@ -178,4 +191,8 @@
   free (results.kronlist);
   free (results.dkronlist);
+
+  free (results.psfqf_list);
+  free (results.psfqfperf_list);
+  free (results.stargal_list);
   return (TRUE);
 }
@@ -315,4 +332,7 @@
   liststats_setmode (&kronstats, STATMODE);
 
+  // StatType psfstats;
+  // liststats_setmode (&psfstats, "MEAN");
+
   double *list      = results->list;
   double *dlist     = results->dlist;
@@ -322,4 +342,8 @@
   double *dkronlist = results->dkronlist;
 
+  double *psfqf_list     = results->psfqf_list;
+  double *psfqfperf_list = results->psfqfperf_list;
+  double *stargal_list   = results->stargal_list;
+
   SetMrelInfoInit (results, FALSE); // do not allocate list,dlist,wlist arrays
 
@@ -327,5 +351,7 @@
 
   char *primaryCell = NULL;
-  ALLOCATE (primaryCell, char, DVO_MAX_PATH);
+  if (isSetMrelFinal) {
+    ALLOCATE (primaryCell, char, DVO_MAX_PATH);
+  }
 
   for (j = 0; j < catalog[Nc].Naverage; j++) {
@@ -338,5 +364,7 @@
     }
 
-    BoundaryTreePrimaryCell(primaryCell, catalog[Nc].average[j].R, catalog[Nc].average[j].D);
+    if (isSetMrelFinal) {
+      BoundaryTreePrimaryCell(primaryCell, catalog[Nc].average[j].R, catalog[Nc].average[j].D);
+    }
 
     int GoodPS1 = FALSE;
@@ -346,4 +374,6 @@
     int NextPS1 = 0;
     int NpsfPS1 = 0;
+
+    int Nmeas = 0; // number of meas used for psfqf, psfqfperf, and stargal
 
     int Ns;
@@ -365,4 +395,5 @@
       int haveSynth = FALSE;
       int haveStack = FALSE;
+      int havePS1   = FALSE;
 
       // need to find the measurement closest to the center of its skycell, as well as the
@@ -420,4 +451,5 @@
 
 	if (isSetMrelFinal) {
+	  // Map (aplist) and Mkron (kronlist,dkronlist) are used to calculate mean mags per filter
 	  float Map = PhotAper (&catalog[Nc].measure[m]);
 	  aplist[N] = Map - Mcal - Mmos - Mgrid;
@@ -426,4 +458,9 @@
 	  kronlist[N] = Mkron - Mcal - Mmos - Mgrid;
 	  dkronlist[N] = catalog[Nc].measure[m].dMkron;
+
+	  // mean psfQF, psfQFperf, and stargal values are calculated per object (all filters)
+	  psfqf_list[Nmeas]     = catalog[Nc].measure[m].psfQF;
+	  psfqfperf_list[Nmeas] = catalog[Nc].measure[m].psfQF;
+	  stargal_list[Nmeas]   = catalog[Nc].measure[m].extNsigma;
 
 	  // special options for PS1 data
@@ -431,5 +468,10 @@
 	    // count the extended detections
 	    if (!isnan(catalog[Nc].measure[m].Map)) {
-	      if (catalog[Nc].measure[m].M - catalog[Nc].measure[m].Map > 0.5) {
+	      float dMagAp = catalog[Nc].measure[m].M - catalog[Nc].measure[m].Map;
+	      float SigmaAp = hypot(0.1, 2.5*catalog[Nc].measure[m].dM);
+	      // XXX this is still quite ad hoc, but at least it:
+	      // (a) converges to 0.1 mag offset at the bright end
+	      // (b) converges to 0.5 mag offset at the faint end (dM = 0.2)
+	      if (dMagAp > SigmaAp) {
 		Next ++;
 		NextPS1 ++;
@@ -438,4 +480,5 @@
 	      }
 	    }
+	    havePS1 = TRUE;
 	  }
 	  // gpc1 stack data
@@ -543,4 +586,5 @@
 	}
 	N++;
+	Nmeas++;
       }
 
@@ -658,13 +702,13 @@
 	  case 0:
 	    catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_0;
-	    GoodPS1 = TRUE;
+	    if (havePS1) GoodPS1 = TRUE;
 	    break;
 	  case 1:
 	    catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_1;
-	    GoodPS1 = TRUE;
+	    if (havePS1) GoodPS1 = TRUE;
 	    break;
 	  case 2:
 	    catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_2;
-	    GoodPS1 = TRUE;
+	    if (havePS1) GoodPS1 = TRUE;
 	    break;
 	  case 3:
@@ -678,4 +722,10 @@
 	  catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_SECF_USE_SYNTH;
 	}	
+	if (haveStack) {
+	  catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_SECF_HAS_STACK;
+	}	
+	if (havePS1) {
+	  catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_SECF_HAS_PS1;
+	}	
 	if (haveUbercal) {
 	  catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_SECF_USE_UBERCAL;
@@ -685,8 +735,9 @@
 
     if (isSetMrelFinal) {
-      DVOAverageFlags flagBits = ID_OBJ_EXT | ID_OBJ_EXT_ALT | ID_OBJ_GOOD | ID_OBJ_GOOD_ALT;
-
-      // we attempt to set a few flags here; reset those bits before trying:
-      catalog[Nc].average[j].flags &= ~flagBits;
+      if (pass == 0) {
+	DVOAverageFlags flagBits = ID_OBJ_EXT | ID_OBJ_EXT_ALT | ID_OBJ_GOOD | ID_OBJ_GOOD_ALT;
+	// we attempt to set a few flags here; reset those bits before trying:
+	catalog[Nc].average[j].flags &= ~flagBits;
+      }
 
       if (NextPS1 && (NextPS1 > NpsfPS1)) {
@@ -701,4 +752,28 @@
       if (Good2MASS) {
 	catalog[Nc].average[j].flags |= ID_OBJ_GOOD_ALT;
+      }
+
+      // use NAN values for catalog[Nc].average[j].psfQF as signal
+      if (!isfinite(catalog[Nc].average[j].psfQF)) {
+	// do something here
+	float psfQFmax     = 0.0;
+	float psfQFperfmax = 0.0;
+	float stargalmax   = 0.0;
+	int seq;
+	for (seq = 0; seq < Nmeas; seq++) {
+	  if (isfinite(psfqf_list[seq])) {
+	    psfQFmax     = MAX (psfqf_list[seq], psfQFmax);
+	  }
+	  if (isfinite(psfqfperf_list[seq])) {
+	    psfQFperfmax = MAX (psfqfperf_list[seq], psfQFperfmax);
+	  }
+	  if (isfinite(stargal_list[seq])) {
+	    stargalmax   = MAX (stargal_list[seq], stargalmax);
+	  }
+	}
+
+	catalog[Nc].average[j].psfQF     = psfQFmax;
+	catalog[Nc].average[j].psfQFperf = psfQFperfmax;
+	catalog[Nc].average[j].stargal   = stargalmax;
       }
     }
Index: trunk/Ohana/src/relphot/src/initialize.c
===================================================================
--- trunk/Ohana/src/relphot/src/initialize.c	(revision 34422)
+++ trunk/Ohana/src/relphot/src/initialize.c	(revision 34429)
@@ -77,5 +77,21 @@
   args_client (argc, argv);
 
-  if (MODE == MODE_UPDATE_OBJECTS) return;
+  if (MODE == MODE_UPDATE_OBJECTS) {
+    char tmpline1[256];
+    int Ns;
+    Nphotcodes = GetPhotcodeNsecfilt ();
+    ALLOCATE (photcodes, PhotCode *, Nphotcodes);
+    ALLOCATE (PhotcodeList, char, 256);
+    for (Ns = 0; Ns < Nphotcodes; Ns++) {
+      photcodes[Ns] = GetPhotcodebyNsec (Ns);
+      if (Ns > 0) {
+	snprintf (tmpline1, 256, "%s,%s", PhotcodeList, photcodes[Ns][0].name);
+      } else {
+	snprintf (tmpline1, 256, "%s", photcodes[Ns][0].name);
+      }
+      strcpy (PhotcodeList, tmpline1);
+    }
+    return;
+  }
 
   // load the list of photcodes into the globals (photcodes, Nphotcodes)
Index: trunk/Ohana/src/relphot/src/liststats.c
===================================================================
--- trunk/Ohana/src/relphot/src/liststats.c	(revision 34422)
+++ trunk/Ohana/src/relphot/src/liststats.c	(revision 34429)
@@ -38,5 +38,9 @@
     dsortthree (value, dvalue, weight, N);
   } else {
-    dsortpair (value, dvalue, N);
+    if (dvalue) {
+      dsortpair (value, dvalue, N);
+    } else {
+      dsort (value, N);
+    }
   }
 
Index: trunk/Ohana/src/relphot/src/relphot_objects.c
===================================================================
--- trunk/Ohana/src/relphot/src/relphot_objects.c	(revision 34422)
+++ trunk/Ohana/src/relphot/src/relphot_objects.c	(revision 34429)
@@ -61,29 +61,34 @@
       Nsecfilt = catalog.Nsecfilt;
       DVOSecfiltFlags secfiltBits = 
-	ID_SECF_STAR_FEW | 
-	ID_SECF_STAR_POOR | 
-	ID_PHOTOM_PASS_0 | 
-	ID_PHOTOM_PASS_1 | 
-	ID_PHOTOM_PASS_2 | 
-	ID_PHOTOM_PASS_3 | 
-	ID_PHOTOM_PASS_4 |
-	ID_SECF_USE_SYNTH |
+	ID_SECF_STAR_FEW    | 
+	ID_SECF_STAR_POOR   | 
+	ID_PHOTOM_PASS_0    | 
+	ID_PHOTOM_PASS_1    | 
+	ID_PHOTOM_PASS_2    | 
+	ID_PHOTOM_PASS_3    | 
+	ID_PHOTOM_PASS_4    |
+	ID_SECF_USE_SYNTH   |
 	ID_SECF_USE_UBERCAL |
-	ID_SECF_OBJ_EXT;
+	ID_SECF_HAS_STACK   |
+	ID_SECF_HAS_PS1     |
+	ID_SECF_OBJ_EXT     ;
+      
+      DVOAverageFlags astromBits = 
+	ID_STAR_FIT_AVE   | 
+	ID_STAR_FIT_PM    | 
+	ID_STAR_FIT_PAR   | 
+	ID_STAR_USE_AVE   | 
+	ID_STAR_USE_PM    | 
+	ID_STAR_USE_PAR   |
+	ID_STAR_NO_ASTROM ; 
       
       for (j = 0; j < catalog.Naverage; j++) {
-	catalog.average[j].flags = 0;
+	catalog.average[j].flags &= astromBits; // reset all except astrometry bits
+	catalog.average[j].psfQF     = NAN;     // reset (will be re-calculated here)
+	catalog.average[j].psfQFperf = NAN;	// reset (will be re-calculated here)
+	catalog.average[j].stargal   = NAN;	// reset (will be re-calculated here)
 	for (k = 0; k < Nsecfilt; k++) {
-	  catalog.secfilt[j*Nsecfilt + k].M    	 = NAN;
-	  catalog.secfilt[j*Nsecfilt + k].Map    = NAN;
-	  catalog.secfilt[j*Nsecfilt + k].dM   	 = NAN;
-	  catalog.secfilt[j*Nsecfilt + k].Mstdev = NAN_S_SHORT;
-	  catalog.secfilt[j*Nsecfilt + k].Xm     = NAN;
-	  catalog.secfilt[j*Nsecfilt + k].M_20 	 = NAN_S_SHORT;
-	  catalog.secfilt[j*Nsecfilt + k].M_80 	 = NAN_S_SHORT;
-	  catalog.secfilt[j*Nsecfilt + k].Ncode  = 0;
-	  catalog.secfilt[j*Nsecfilt + k].Nused  = 0;
-	  catalog.secfilt[j*Nsecfilt + k].flags &= ~secfiltBits;
-	  catalog.secfilt[j*Nsecfilt + k].ubercalDist = 1000;
+	  dvo_secfilt_init (&catalog.secfilt[j*Nsecfilt + k]);
+	  catalog.secfilt[j*Nsecfilt + k].flags &= ~secfiltBits; // XXX: only reset photom bits: 
 	}
       }
Index: trunk/Ohana/src/relphot/src/setMrelFinal.c
===================================================================
--- trunk/Ohana/src/relphot/src/setMrelFinal.c	(revision 34422)
+++ trunk/Ohana/src/relphot/src/setMrelFinal.c	(revision 34429)
@@ -94,4 +94,10 @@
   }
 
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    catalog[0].average[i].psfQF     = NAN;	// force recalculation below
+    catalog[0].average[i].psfQFperf = NAN;	// force recalculation below
+    catalog[0].average[i].stargal   = NAN;	// force recalculation below
+  }
+
   // XXX make this optional? (do not clean for -averages?)
   if (!simpleAverage) clean_measures (catalog, 1, TRUE, flatcorr);    /* mark outliers ID_MEAS_POOR_PHOTOM */
