Index: branches/czw_branch/20160809/Ohana/src/relastro/include/relastro.h
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/include/relastro.h	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/include/relastro.h	(revision 39731)
@@ -33,5 +33,5 @@
 typedef enum {OP_NONE, OP_IMAGES, OP_HIGH_SPEED, OP_MERGE_SOURCE, OP_UPDATE_OBJECTS, OP_UPDATE_OFFSETS, OP_LOAD_OBJECTS, OP_HPM, OP_PARALLEL_REGIONS, OP_PARALLEL_IMAGES, OP_REPAIR_STACKS, OP_REPAIR_WARPS, OP_REPAIR_OBJECT_ID} RelastroOp;
 
-typedef enum {TARGET_NONE, TARGET_SIMPLE, TARGET_CHIPS, TARGET_MOSAICS} FitTarget;
+typedef enum {TARGET_NONE, TARGET_SIMPLE, TARGET_CHIPS, SET_CHIPS, TARGET_MOSAICS} FitTarget;
 
 typedef enum {
@@ -144,4 +144,6 @@
   int Nfit;
   int converged;
+  int useWeight;
+
 } FitAstromResult;
 
@@ -364,4 +366,15 @@
 int    USE_ALL_IMAGES;
 int    CHECK_MEASURE_TO_IMAGE;
+
+int    SKIP_PS1_CHIP;
+int    SKIP_PS1_STACK;
+int    SKIP_HSC;
+int    SKIP_CFH;
+
+int    UPDATE_PS1_CHIP_MEASURE;
+int    UPDATE_HSC_MEASURE;
+int    UPDATE_CFH_MEASURE;
+
+int    APPLY_PROPER_MOTION;
 
 int    RESET;
@@ -744,4 +757,6 @@
 int isGPC1stack (int photcode);
 int isGPC1warp (int photcode);
+int isHSCchip (int photcode);
+int isCFHchip (int photcode);
 
 int save_astrom_table ();
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/BrightCatalog.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/BrightCatalog.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/BrightCatalog.c	(revision 39731)
@@ -353,8 +353,8 @@
   /*** MeasureTiny ***/
   {
-    ohana_memcheck (1);
+    // ohana_memcheck (1);
     gfits_create_table_header (&theader, "BINTABLE", "MEASURE_TINY");
 
-    ohana_memcheck (1);
+    // ohana_memcheck (1);
 
     gfits_define_bintable_column (&theader, "D", "RA",       "ra",                         "degrees", 1.0, 0.0);
@@ -429,6 +429,6 @@
     gfits_set_bintable_column (&theader, &ftable, "RA",   	R,         catalog->Nmeasure);
 
-    fprintf (stderr, "--------------- after set_bintable RA --------------");
-    ohana_memdump_file (stderr, TRUE);
+    // fprintf (stderr, "--------------- after set_bintable RA --------------");
+    // ohana_memdump_file (stderr, TRUE);
     
     gfits_set_bintable_column (&theader, &ftable, "DEC",  	D,         catalog->Nmeasure);
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/FitAstromOps.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/FitAstromOps.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/FitAstromOps.c	(revision 39731)
@@ -257,4 +257,8 @@
   fit->converged = FALSE;
   
+  // this is an input value
+  // if true, use the IRLS modified weight
+  fit->useWeight = FALSE;
+
   return;
 }
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/FitChip.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/FitChip.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/FitChip.c	(revision 39731)
@@ -206,9 +206,26 @@
   if (VERBOSE2) fprintf (stderr, "fit sigma: %f (%f, %f) : full: %f (%f, %f), scatter limit: %f (%d full, %d bright, %d fit, %d all) (%d %d %d %d %d)\n", dRsig, dLsig, dMsig, dRsigFull, dLsigFull, dMsigFull, dRmax, NstatFull, Nstat, fit[0].Npts, Nmatch, nMask1, nMask2, nMask3, nMask4, nMask5);
 
-  image[0].dXpixSys = dLsig;
-  image[0].dYpixSys = dMsig;
+  // need to convert dLsig, dMsig back to pixel scale (or up to arcsec)
+
+  float plateScale;
+  if (image[0].coords.mosaic) {
+    // NOTE: for the full pixel to sky plate scale, use this:
+    // float plateScaleX = 3600.0*image[0].coords.mosaic->cdelt1*image[0].coords.cdelt1;
+    // float plateScaleY = 3600.0*image[0].coords.mosaic->cdelt2*image[0].coords.cdelt2;
+
+    // since we are compare L,M values, just need to compensate for focal plate to sky:
+    float plateScaleX = 3600.0*fabs(image[0].coords.mosaic->cdelt1);
+    float plateScaleY = 3600.0*fabs(image[0].coords.mosaic->cdelt2);
+    plateScale = 0.5*(plateScaleX + plateScaleY);
+  } else {
+    // since we are compare L,M values, just need to compensate for arcsec vs degrees:
+    plateScale = 3600.0;
+  }
+
+  image[0].dXpixSys = plateScale*dLsig;
+  image[0].dYpixSys = plateScale*dMsig;
   image[0].nFitAstrom = fit[0].Npts;
 
-  // fprintf (stderr, "%s %6.3f %4d %4d\n", image[0].name, image[0].refColor, Ncolor, image[0].nFitAstrom);
+  fprintf (stderr, "%s | %6.3f %6.3f | %4d %4d | %6.3f %6.3f\n", image[0].name, image[0].refColorRed, image[0].refColorBlue, Ncolor, image[0].nFitAstrom, image[0].dXpixSys, image[0].dYpixSys);
 
   if (fit) fit_free (fit);
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/FitPM.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/FitPM.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/FitPM.c	(revision 39731)
@@ -25,4 +25,5 @@
   }
 
+  fit->useWeight = FALSE; // Ordinary Least Squares
   if (!FitPM_MinChisq (fit, data, points, Npoints)) return FALSE;
   if (!FitPM_SetChisq (fit, data, points, Npoints)) return FALSE;
@@ -47,4 +48,5 @@
   
   // Solve OLS equation  
+  fit->useWeight = FALSE; // Ordinary Least Squares
   if (!FitPM_MinChisq(fit, data, points, Npoints)) {
     return(FALSE);
@@ -90,4 +92,5 @@
 
     // Solve with the new weights
+    fit->useWeight = TRUE; // Reweighted Least Squares
     if (!FitPM_MinChisq(fit, data, points, Npoints)) {
 
@@ -159,38 +162,15 @@
   // NOTE EAM: in tests (fitpm.c), they seem to be too large by a factor of ~5.37
   if (data->getError) {
-    double ax = 0.0, ay = 0.0;
-    double bx = 0.0, by = 0.0;
-
-    for (i = 0; i < Npoints; i++) {
-      ax += dpsi_cauchy(points[i].rx / points[i].dX);
-      ay += dpsi_cauchy(points[i].ry / points[i].dY);
-
-      bx += SQ(points[i].Wx);
-      by += SQ(points[i].Wy);
-    }
-    ax /= 1.0 * Npoints;  // mean(psi_dot(r))
-    ay /= 1.0 * Npoints; 
-    bx /= 1.0 * (Npoints - data->Nterms); // mean(psi^2(r)) * (N / (N-p))
-    by /= 1.0 * (Npoints - data->Nterms);
-  
-    double lambda_x = 1.0 + (data->Nterms / Npoints) * (1 - ax) / ax;
-    double lambda_y = 1.0 + (data->Nterms / Npoints) * (1 - ay) / ay;
-  
-    double sigma_robust_x = lambda_x * sqrt(bx) * sigma_hat * 2.385 / ax;
-    double sigma_robust_y = lambda_y * sqrt(by) * sigma_hat * 2.385 / ay;
-
-    // This is actually sigma^2, as that's the factor in the covariance (dumouchel 4.1)
-    double sigma_final_x  = MAX(SQ(sigma_robust_x), (2 * Npoints * SQ(sigma_robust_x) + SQ(data->Nterms * sigma_ols)) / (2 * Npoints + SQ(data->Nterms)));
-    double sigma_final_y  = MAX(SQ(sigma_robust_y), (2 * Npoints * SQ(sigma_robust_y) + SQ(data->Nterms * sigma_ols)) / (2 * Npoints + SQ(data->Nterms)));
-
-    fit[0].dRo = sqrt(data->Cov[0][0]);
-    fit[0].duR = sqrt(data->Cov[1][1]);
-    fit[0].dDo = sqrt(data->Cov[2][2]);
-    fit[0].duD = sqrt(data->Cov[3][3]);
-
-    fit[0].dRo *= sigma_final_x;
-    fit[0].duR *= sigma_final_x;
-    fit[0].dDo *= sigma_final_y;
-    fit[0].duD *= sigma_final_y;
+    FitAstromResult fitErrors;
+    FitAstromResultInit (&fitErrors);
+    fitErrors.useWeight = FALSE; 
+
+    FitPM_MinChisq(&fitErrors, data, points, Npoints);
+
+    // we use the errors from a simple OLS, ignoring masked points
+    fit[0].dRo = fitErrors.dRo;
+    fit[0].duR = fitErrors.duR;
+    fit[0].dDo = fitErrors.dDo;
+    fit[0].duD = fitErrors.duD;
   }
 
@@ -212,6 +192,11 @@
     Nfit ++;
 
-    wx = points[i].qx;
-    wy = points[i].qy;
+    if (fit->useWeight) {
+      wx = points[i].qx;
+      wy = points[i].qy;
+    } else {
+      wx = points[i].Qx;
+      wy = points[i].Qy;
+    }
 
     Wx += wx;
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/FitPMandPar.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/FitPMandPar.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/FitPMandPar.c	(revision 39731)
@@ -25,4 +25,5 @@
   }
 
+  fit->useWeight = FALSE; // Ordinary Least Squares
   if (!FitPMandPar_MinChisq (fit, data, points, Npoints)) return FALSE;
   if (!FitPMandPar_SetChisq (fit, data, points, Npoints)) return FALSE;
@@ -47,4 +48,5 @@
   
   // Solve OLS equation: failure here means the chisq matrix is degenerate, give up entirely
+  fit->useWeight = FALSE; // Ordinary Least Squares
   if (!FitPMandPar_MinChisq(fit, data, points, Npoints)) {
     return(FALSE);
@@ -90,4 +92,5 @@
 
     // Solve with the new weights
+    fit->useWeight = TRUE; // Reweighted Least Squares
     if (!FitPMandPar_MinChisq(fit, data, points, Npoints)) {
 
@@ -157,43 +160,19 @@
   }
 
-  // this section calculates the formal error on the weighted fit using the covariance values
-  // NOTE EAM: in tests (fitpm.c), they seem to be too large by a factor of ~5.37
+  // this section calculates the formal error on the regular (unweighted) fit using the covariance values
+  // NOTE 20160929 : use only the unmasked points to calculate the error
   if (data->getError) {
-    double ax = 0.0, ay = 0.0;
-    double bx = 0.0, by = 0.0;
-
-    for (i = 0; i < Npoints; i++) {
-      ax += dpsi_cauchy(points[i].rx / points[i].dX);
-      ay += dpsi_cauchy(points[i].ry / points[i].dY);
-
-      bx += SQ(points[i].Wx);
-      by += SQ(points[i].Wy);
-    }
-    ax /= 1.0 * Npoints;  // mean(psi_dot(r))
-    ay /= 1.0 * Npoints; 
-    bx /= 1.0 * (Npoints - data->Nterms); // mean(psi^2(r)) * (N / (N-p))
-    by /= 1.0 * (Npoints - data->Nterms);
-  
-    double lambda_x = 1.0 + (data->Nterms / Npoints) * (1 - ax) / ax;
-    double lambda_y = 1.0 + (data->Nterms / Npoints) * (1 - ay) / ay;
-  
-    double sigma_robust_x = lambda_x * sqrt(bx) * sigma_hat * 2.385 / ax;
-    double sigma_robust_y = lambda_y * sqrt(by) * sigma_hat * 2.385 / ay;
-
-    // This is actually sigma^2, as that's the factor in the covariance (dumouchel 4.1)
-    double sigma_final_x  = MAX(SQ(sigma_robust_x), (2 * Npoints * SQ(sigma_robust_x) + SQ(data->Nterms * sigma_ols)) / (2 * Npoints + SQ(data->Nterms)));
-    double sigma_final_y  = MAX(SQ(sigma_robust_y), (2 * Npoints * SQ(sigma_robust_y) + SQ(data->Nterms * sigma_ols)) / (2 * Npoints + SQ(data->Nterms)));
-
-    fit[0].dRo = sqrt(data->Cov[0][0]);
-    fit[0].duR = sqrt(data->Cov[1][1]);
-    fit[0].dDo = sqrt(data->Cov[2][2]);
-    fit[0].duD = sqrt(data->Cov[3][3]);
-    fit[0].dp  = sqrt(data->Cov[4][4]);
-
-    fit[0].dRo *= sigma_final_x;
-    fit[0].duR *= sigma_final_x;
-    fit[0].dDo *= sigma_final_y;
-    fit[0].duD *= sigma_final_y;
-    fit[0].dp  *= sqrt(sigma_final_x * sigma_final_y);
+    FitAstromResult fitErrors;
+    FitAstromResultInit (&fitErrors);
+    fitErrors.useWeight = FALSE; 
+
+    FitPMandPar_MinChisq(&fitErrors, data, points, Npoints);
+
+    // we use the errors from a simple OLS, ignoring masked points
+    fit[0].dRo = fitErrors.dRo;
+    fit[0].duR = fitErrors.duR;
+    fit[0].dDo = fitErrors.dDo;
+    fit[0].duD = fitErrors.duD;
+    fit[0].dp  = fitErrors.dp;
   }
 
@@ -219,6 +198,11 @@
     Nfit ++;
 
-    wx = points[i].qx;
-    wy = points[i].qy;
+    if (fit->useWeight) {
+      wx = points[i].qx;
+      wy = points[i].qy;
+    } else {
+      wx = points[i].Qx;
+      wy = points[i].Qy;
+    }
 
     Wx += wx;
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/FitPosPMfixed.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/FitPosPMfixed.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/FitPosPMfixed.c	(revision 39731)
@@ -54,4 +54,5 @@
   }
 
+  fit->useWeight = FALSE; // Ordinary Least Squares
   if (!FitPosPMfixed_MinChisq (fit, data, points, Npoints)) {
     if (!FitPosPMfixed_Single (fit, points, Npoints)) return FALSE;
@@ -83,4 +84,5 @@
   
   // Solve OLS equation  
+  fit->useWeight = FALSE; // Ordinary Least Squares
   if (!FitPosPMfixed_MinChisq(fit, data, points, Npoints)) {
     return(FALSE);
@@ -126,4 +128,5 @@
 
     // Solve with the new weights
+    fit->useWeight = TRUE; // Reweighted Least Squares
     if (!FitPosPMfixed_MinChisq(fit, data, points, Npoints)) {
 
@@ -193,34 +196,16 @@
   // NOTE EAM: in tests (fitpm.c), they seem to be too large by a factor of ~5.37
   if (data->getError) {
-    double ax = 0.0, ay = 0.0;
-    double bx = 0.0, by = 0.0;
-
-    for (i = 0; i < Npoints; i++) {
-      ax += dpsi_cauchy(points[i].rx / points[i].dX);
-      ay += dpsi_cauchy(points[i].ry / points[i].dY);
-
-      bx += SQ(points[i].Wx);
-      by += SQ(points[i].Wy);
-    }
-    ax /= 1.0 * Npoints;  // mean(psi_dot(r))
-    ay /= 1.0 * Npoints; 
-    bx /= 1.0 * (Npoints - data->Nterms); // mean(psi^2(r)) * (N / (N-p))
-    by /= 1.0 * (Npoints - data->Nterms);
-  
-    double lambda_x = 1.0 + (data->Nterms / Npoints) * (1 - ax) / ax;
-    double lambda_y = 1.0 + (data->Nterms / Npoints) * (1 - ay) / ay;
-  
-    double sigma_robust_x = lambda_x * sqrt(bx) * sigma_hat * 2.385 / ax;
-    double sigma_robust_y = lambda_y * sqrt(by) * sigma_hat * 2.385 / ay;
-
-    // This is actually sigma^2, as that's the factor in the covariance (dumouchel 4.1)
-    double sigma_final_x  = MAX(SQ(sigma_robust_x), (2 * Npoints * SQ(sigma_robust_x) + SQ(data->Nterms * sigma_ols)) / (2 * Npoints + SQ(data->Nterms)));
-    double sigma_final_y  = MAX(SQ(sigma_robust_y), (2 * Npoints * SQ(sigma_robust_y) + SQ(data->Nterms * sigma_ols)) / (2 * Npoints + SQ(data->Nterms)));
-
-    fit[0].dRo = sqrt(data->Cov[0][0]);
-    fit[0].dDo = sqrt(data->Cov[1][1]);
-
-    fit[0].dRo *= sigma_final_x;
-    fit[0].dDo *= sigma_final_y;
+    FitAstromResult fitErrors;
+    FitAstromResultInit (&fitErrors);
+    fitErrors.useWeight = FALSE; 
+
+    FitPosPMfixed_MinChisq(&fitErrors, data, points, Npoints);
+
+    // we use the errors from a simple OLS, ignoring masked points
+    fit[0].dRo = fitErrors.dRo;
+    fit[0].duR = fitErrors.duR;
+    fit[0].dDo = fitErrors.dDo;
+    fit[0].duD = fitErrors.duD;
+    fit[0].dp  = fitErrors.dp;
   }
 
@@ -242,6 +227,11 @@
     Nfit ++;
 
-    wx = points[i].qx;
-    wy = points[i].qy;
+    if (fit->useWeight) {
+      wx = points[i].qx;
+      wy = points[i].qy;
+    } else {
+      wx = points[i].Qx;
+      wy = points[i].Qy;
+    }
 
     Wx += wx;
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/ImageOps.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/ImageOps.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/ImageOps.c	(revision 39731)
@@ -794,5 +794,5 @@
     
     // if we are applying the galaxy model, move the reference position...
-    if (USE_GALAXY_MODEL) {
+    if (APPLY_PROPER_MOTION) {
       // apply proper-motion from average position to measure epoch:
       float dTime = (measure[0].t - catalog[c].average[n].Tmean) / (86400*365.25) ; // time relative to Tmean in years
@@ -934,371 +934,2 @@
 }
 
-# if (0) 
-/** lifted from relphot/StarOps.clean_measures */
-void FlagOutliers2D(Catalog *catalog);
-
-// operates on Full values (not tiny)
-void FlagOutliers (Catalog *catalog) {
-
-  // XXX FlagOutliers is now just using FlagOutliers2D
-  FlagOutliers2D(catalog);
-  return;
-
-  int Ndel, Nave;
-  off_t i, j, k, m, N, Nmax, TOOFEW, Nsecfilt;
-  double Ns, theta, x, y;
-  double *R, *D, *dR, *dD;
-  StatType statsR, statsD;
-
-  Nsecfilt = GetPhotcodeNsecfilt();
-  assert(catalog[0].Nsecfilt == Nsecfilt);
-
-  if (VERBOSE2) fprintf (stderr, "marking poor measures\n");
-  Nmax = 0;
-  for (i = 0; i < catalog[0].Naverage; i++) {
-    Nmax = MAX (Nmax, catalog[0].average[i].Nmeasure);
-  }
-
-  ALLOCATE (R, double, Nmax);
-  ALLOCATE (D, double, Nmax);
-  ALLOCATE (dR, double, Nmax);
-  ALLOCATE (dD, double, Nmax);
-
-  /* it makes no sense to mark 3-sigma outliers with <5 measurements */
-  TOOFEW = MAX (5, SRC_MEAS_TOOFEW);
-
-  Ns = CLIP_THRESH;
-  Ndel = Nave = 0;
-      
-  /* loop over each object in the catalog */
-  for (j = 0; j < catalog[0].Naverage; j++) {
-    
-    // pointer to this set of measurements
-    m = catalog[0].average[j].measureOffset;
-    Measure *measure = &catalog[0].measure[m];
-
-    /* accumulate list of valid measurements */
-    N = 0;
-    for (k = 0; k < catalog[0].average[j].Nmeasure; k++) {
-      // skip measurements based on user selected criteria
-      if (!MeasFilterTest(&measure[k], FALSE)) continue;
-      R[N] = measure[k].R;
-      D[N] = measure[k].D;
-      dR[N] = GetAstromError (&measure[k], ERROR_MODE_RA);
-      dD[N] = GetAstromError (&measure[k], ERROR_MODE_DEC);
-      if (isnan(R[N]) || isnan(D[N])) continue;
-      N++;
-    }
-    if (N <= TOOFEW) continue;
-    
-    /* 3-sigma clip based on stats of inner 50% */
-    initstats ("MEAN");
-    liststats (R, dR, N, &statsR);
-    liststats (D, dD, N, &statsD);
-    
-    statsR.sigma = MAX (MIN_ERROR, statsR.sigma);
-    statsD.sigma = MAX (MIN_ERROR, statsD.sigma);
-    
-    /* compare per-object distance to this standard deviation, and flag outliers*/
-    N = 0;
-    for (k = 0; k < catalog[0].average[j].Nmeasure; k++) {
-      // reset flag on each invocation
-      measure[k].dbFlags &= ~ID_MEAS_POOR_ASTROM;
-
-      // skip measurements based on user selected criteria
-      if (!MeasFilterTest(&measure[k], FALSE)) continue;
-      
-      x = measure[k].R - statsR.median;
-      y = measure[k].D - statsD.median;
-      theta = atan2(y,x);
-      if ((x*x + y*y) > (SQR(statsR.sigma * Ns * cos(theta)) + 
-			 SQR(statsD.sigma * Ns * sin(theta)))) {   
-	measure[k].dbFlags |= ID_MEAS_POOR_ASTROM;
-	Ndel++;
-      }
-      N++;
-      Nave ++;
-    }
-
-    // examine results
-    // relastroVisualPlotOutliers(catalog, catalog[0].average[j].measureOffset, catalog[0].average[j].Nmeasure, statsR, statsD, Ns);
-  }
-  
-  if (VERBOSE) fprintf (stderr, "%d measures marked poor, %d total\n", Ndel, Nave);
-  free (R);
-  free (dR);
-  free (D);
-  free (dD); 
-}
-
-
-/** an alternative outlier rejection scheme */
-void FlagOutliers2D (Catalog *catalog) {
-
-  int Ndel, Nave;
-  off_t i, j, k, m, N, Nmax, TOOFEW, Nsecfilt;
-  double *index;
-  double Ns, theta, x, y;
-  double *R, *D, *dR, *dD, *d2;
-  StatType statsR, statsD;
-
-  // XXX we are not going to use this for now
-  return;
-
-  Nsecfilt = GetPhotcodeNsecfilt();
-  assert(catalog[0].Nsecfilt == Nsecfilt);
-
-  if (VERBOSE2) fprintf (stderr, "marking poor measures\n");
-  Nmax = 0;
-  for (i = 0; i < catalog[0].Naverage; i++) {
-    Nmax = MAX (Nmax, catalog[0].average[i].Nmeasure);
-  }
-
-  ALLOCATE (R, double, Nmax);
-  ALLOCATE (D, double, Nmax);
-  ALLOCATE (dR, double, Nmax);
-  ALLOCATE (dD, double, Nmax);
-  ALLOCATE (d2, double, Nmax);
-  ALLOCATE (index, double, Nmax);
-
-  /* it makes no sense to mark 3-sigma outliers with <5 measurements */
-  TOOFEW = MAX (5, SRC_MEAS_TOOFEW);
-
-  Ns = CLIP_THRESH;
-  Ndel = Nave = 0;
-      
-  /* loop over each object in the catalog */
-  for (j = 0; j < catalog[0].Naverage; j++) {
-    
-    // pointer to this set of measurements
-    m = catalog[0].average[j].measureOffset;
-    Measure *measure = &catalog[0].measure[m];
-
-    /* accumulate list of valid measurements */
-    N = 0;
-    for (k = 0; k < catalog[0].average[j].Nmeasure; k++) {
-
-      // reset flag on each invocation
-      measure[k].dbFlags &= ~ID_MEAS_POOR_ASTROM;
-      
-      // skip measurements based on user selected criteria
-      if (!MeasFilterTest(&measure[k], FALSE)) continue;
-      R[N] = measure[k].R;
-      D[N] = measure[k].D;
-      dR[N] = GetAstromError(&measure[k], ERROR_MODE_RA);
-      dD[N] = GetAstromError(&measure[k], ERROR_MODE_DEC);
-      if (isnan(R[N]) || isnan(D[N])) continue;
-      N++;
-    }
-    if (N <= TOOFEW) continue;
-    
-    /* calculate mean of all points*/
-    initstats ("MEAN");
-    liststats (R, dR, N, &statsR);
-    liststats (D, dD, N, &statsD);
-    statsR.sigma = MAX (MIN_ERROR, statsR.sigma);
-    statsD.sigma = MAX (MIN_ERROR, statsD.sigma);
-    
-    /* calculate deviations of all points*/
-    N = 0;
-    for (k = 0; k < catalog[0].average[j].Nmeasure; k++) {
-      // skip bad measurements
-      if (!MeasFilterTest(&measure[k], FALSE)) continue;  
-      x = measure[k].R - statsR.median;
-      y = measure[k].D - statsD.median;
-      theta = atan2(y,x);
-      d2[N] = (x*x + y*y) / (SQR(statsR.sigma * Ns * cos(theta)) + 
-			     SQR(statsD.sigma * Ns * sin(theta)));      
-      index[N] = k;
-      N++;
-    }
-    
-    // sort d2
-    dsortpair(d2, index, N);
-    N = (N/2 > (N-1)) ? N/2 : N-1;
-
-    // recalculate image center, sigma based on closest 50% of points
-    for (k = 0;  k < N; k++) {
-      off_t ind = (off_t) index[k];
-      R[k] = measure[ind].R;
-      D[k] = measure[ind].D;
-      dR[k] = GetAstromError(&measure[ind], ERROR_MODE_RA);
-      dD[k] = GetAstromError(&measure[ind], ERROR_MODE_DEC);
-    }
-    liststats (R, dR, N, &statsR);
-    liststats (D, dD, N, &statsD);
-    statsR.sigma = MAX (MIN_ERROR, statsR.sigma);
-    statsD.sigma = MAX (MIN_ERROR, statsD.sigma);
-    
-    // use these new statistics to flag outliers 
-    N = 0;
-    for (k = 0; k < catalog[0].average[j].Nmeasure; k++) {
-      //skip bad measurements
-      if (!MeasFilterTest(&measure[k], FALSE)) continue;  
-      x = measure[k].R - statsR.median;
-      y = measure[k].D - statsD.median;
-      theta = atan2(y,x);
-      d2[N] = (x*x + y*y) / (SQR(statsR.sigma * Ns * cos(theta)) + 
-			     SQR(statsD.sigma * Ns * sin(theta)));      
-      if ((d2[N]) > 1) {
-	measure[k].dbFlags |= ID_MEAS_POOR_ASTROM;
-	Ndel ++;
-      }
-      N++;
-      Nave++;
-    }  // done rejecting outliers
-
-    // examine results
-    // relastroVisualPlotOutliers(catalog, catalog[0].average[j].measureOffset, catalog[0].average[j].Nmeasure, statsR, statsD, Ns);
-    
-  } // done looping over objects
-  
-  if (VERBOSE) fprintf (stderr, "%d measures marked poor, %d total\n", Ndel, Nave);
-  free (R);
-  free (dR);
-  free (D);
-  free (dD); 
-  free (d2);
-  free (index);
-}
-
-/** Determine whether a measurement should be included in the analysis, based on supplied filter criteria */ 
-// we only optionally apply the sigma limit: for object averages, this should not be used
-int MeasFilterTestTiny(MeasureTiny *measure, int applySigmaLim) {
-  int found, k;
-  long mask;
-  PhotCode *code;
-  float mag;
-
-  if (!finite(measure[0].R) || !finite(measure[0].D)) return FALSE;
-  if (!finite(measure[0].M)) return FALSE; //XXX is this necessary for all relastro tasks?
-  if (!finite(measure[0].dM)) return FALSE; //XXX is this necessary for all relastro tasks?
-  
-  if ((MinBadQF > 0.0) && (isGPC1chip(measure[0].photcode) || isGPC1stack(measure[0].photcode))) {
-    if (!isfinite(measure[0].psfQF)) { return FALSE; };
-    if (measure[0].psfQF < MinBadQF) { return FALSE; };
-  }
-
-  /* select measurements by photcode, or equiv photcode, if specified */
-  if (NphotcodesKeep > 0) {
-    found = FALSE;
-    for (k = 0; (k < NphotcodesKeep) && !found; k++) {
-      if (photcodesKeep[k][0].code == measure[0].photcode) found = TRUE;
-      if (photcodesKeep[k][0].code == GetPhotcodeEquivCodebyCode(measure[0].photcode)) found = TRUE;
-    }
-    if (!found) return FALSE;
-  }
-  
-  if (NphotcodesSkip > 0) {
-    found = FALSE;
-    for (k = 0; (k < NphotcodesSkip) && !found; k++) {
-      if (photcodesSkip[k][0].code == measure[0].photcode) found = TRUE;
-      if (photcodesSkip[k][0].code == GetPhotcodeEquivCodebyCode(measure[0].photcode)) found = TRUE;
-    }
-    if (found) return FALSE;
-  }  
-  
-  /* select measurements by time */
-  if (TimeSelect) {
-    if (measure[0].t < TSTART) return FALSE;
-    if (measure[0].t > TSTOP) return FALSE;
-  }
-  
-  /* select measurements by quality */
-  if (PhotFlagSelect) {
-    if (PhotFlagBad) {
-      mask = PhotFlagBad;
-    } else {
-      code = GetPhotcodebyCode (measure[0].photcode);
-      if (!code) return FALSE;
-      mask = code[0].astromBadMask;
-    }
-    if (mask & measure[0].photFlags) return FALSE;
-  }
-
-  /* select measurements by measurement error */
-  // this is a bit convoluted: applySigmaLim is only TRUE when this function is
-  // called by bcatalog.  for UpdateObjects, it is FALSE
-  if (applySigmaLim && (SIGMA_LIM > 0) && (measure[0].dM > SIGMA_LIM)) {
-    return FALSE;
-  }
-  
-  /* select measurements by mag limit */
-  if (ImagSelect) {
-    mag = PhotInstTiny (measure, MAG_CLASS_PSF);
-    if (mag < ImagMin || mag > ImagMax) return FALSE;
-  }
-  
-  return TRUE;
-}
-
-# define SUPER_VERBOSE 0
-
-/** Determine whether a measurement should be included in the analysis, based on supplied filter criteria */ 
-// we only optionally apply the sigma limit: for object averages, this should not be used (should it?)
-int MeasFilterTest(Measure *measure, int applySigmaLim) {
-  int found, k;
-  long mask;
-  PhotCode *code;
-  float mag;
-
-  if (!finite(measure[0].R) || !finite(measure[0].D)) { if (SUPER_VERBOSE) fprintf (stderr, "filter 1\n"); return FALSE; };
-  if (!finite(measure[0].M)) { if (SUPER_VERBOSE) fprintf (stderr, "filter 2\n"); return FALSE; }; //XXX is this necessary for all relastro tasks?
-  if (!finite(measure[0].dM)) { if (SUPER_VERBOSE) fprintf (stderr, "filter 3\n"); return FALSE; }; //XXX is this necessary for all relastro tasks?
-  
-  /* select measurements by photcode, or equiv photcode, if specified */
-  if (NphotcodesKeep > 0) {
-    found = FALSE;
-    for (k = 0; (k < NphotcodesKeep) && !found; k++) {
-      if (photcodesKeep[k][0].code == measure[0].photcode) found = TRUE;
-      if (photcodesKeep[k][0].code == GetPhotcodeEquivCodebyCode(measure[0].photcode)) found = TRUE;
-    }
-    if (!found) { if (SUPER_VERBOSE) fprintf (stderr, "filter 4\n"); return FALSE; };
-  }
-  
-  if (NphotcodesSkip > 0) {
-    found = FALSE;
-    for (k = 0; (k < NphotcodesSkip) && !found; k++) {
-      if (photcodesSkip[k][0].code == measure[0].photcode) found = TRUE;
-      if (photcodesSkip[k][0].code == GetPhotcodeEquivCodebyCode(measure[0].photcode)) found = TRUE;
-    }
-    if (found) { if (SUPER_VERBOSE) fprintf (stderr, "filter 5\n"); return FALSE; };
-  }  
-  
-  if ((MinBadQF > 0.0) && isGPC1chip(measure[0].photcode)) {
-    if (!isfinite(measure[0].psfQF)) { if (SUPER_VERBOSE) fprintf (stderr, "filter 6\n"); return FALSE; };
-    if (measure[0].psfQF < MinBadQF) { if (SUPER_VERBOSE) fprintf (stderr, "filter 7\n"); return FALSE; };
-  }
-
-  /* select measurements by time */
-  if (TimeSelect) {
-    if (measure[0].t < TSTART) { if (SUPER_VERBOSE) fprintf (stderr, "filter 8\n"); return FALSE; };
-    if (measure[0].t > TSTOP) { if (SUPER_VERBOSE) fprintf (stderr, "filter 9\n"); return FALSE; };
-  }
-  
-  /* select measurements by quality */
-  if (PhotFlagSelect) {
-    if (PhotFlagBad) {
-      mask = PhotFlagBad;
-    } else {
-      code = GetPhotcodebyCode (measure[0].photcode);
-      if (!code) { if (SUPER_VERBOSE) fprintf (stderr, "filter 10\n"); return FALSE; };
-      mask = code[0].astromBadMask;
-    }
-    if (mask & measure[0].photFlags) { if (SUPER_VERBOSE) fprintf (stderr, "filter 11\n"); return FALSE; };
-  }
-
-  /* select measurements by measurement error */
-  if (applySigmaLim && (SIGMA_LIM > 0) && (measure[0].dM > SIGMA_LIM)) {
-    { if (SUPER_VERBOSE) fprintf (stderr, "filter 12\n"); return FALSE; };
-  }
-  
-  /* select measurements by mag limit */
-  if (ImagSelect) {
-    mag = PhotInst (measure, MAG_CLASS_PSF);
-    if (mag < ImagMin || mag > ImagMax) { if (SUPER_VERBOSE) fprintf (stderr, "filter 13\n"); return FALSE; };
-  }
-  
-  return TRUE;
-}
-# endif
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/StarMaps.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/StarMaps.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/StarMaps.c	(revision 39731)
@@ -166,4 +166,19 @@
   dLmax = dMmax = 0.0;
 
+  float plateScale;
+  if (images[N].coords.mosaic) {
+    // NOTE: for the full pixel to sky plate scale, use this:
+    // float plateScaleX = 3600.0*images[N].coords.mosaic->cdelt1*images[N].coords.cdelt1;
+    // float plateScaleY = 3600.0*images[N].coords.mosaic->cdelt2*images[N].coords.cdelt2;
+
+    // since we are compare L,M values, just need to compensate for focal plate to sky:
+    float plateScaleX = 3600.0*fabs(images[N].coords.mosaic->cdelt1);
+    float plateScaleY = 3600.0*fabs(images[N].coords.mosaic->cdelt2);
+    plateScale = 0.5*(plateScaleX + plateScaleY);
+  } else {
+    // since we are compare L,M values, just need to compensate for arcsec vs degrees:
+    plateScale = 3600.0;
+  }
+
   for (i = 0; i < starmap[N].Npoints; i++) {
 
@@ -171,6 +186,6 @@
     XY_to_LM (&L, &M, starmap[N].points[i].X, starmap[N].points[i].Y, &images[N].coords);
 
-    starmap[N].points[i].dL = starmap[N].points[i].L - L;
-    starmap[N].points[i].dM = starmap[N].points[i].M - M;
+    starmap[N].points[i].dL = plateScale*(starmap[N].points[i].L - L);
+    starmap[N].points[i].dM = plateScale*(starmap[N].points[i].M - M);
 
     dLmax = MAX(fabs(starmap[N].points[i].dL), dLmax);
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateChips.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateChips.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateChips.c	(revision 39731)
@@ -65,4 +65,10 @@
     // helper functions that grab the next available chip....
 
+    // allow certain cameras to stay static
+    if (SKIP_PS1_CHIP  && isGPC1chip (image[i].photcode)) { Nskip ++;  mode[i] = 0; continue; }
+    if (SKIP_PS1_STACK && isGPC1stack(image[i].photcode)) { Nskip ++;  mode[i] = 0; continue; }
+    if (SKIP_HSC       && isHSCchip  (image[i].photcode)) { Nskip ++;  mode[i] = 0; continue; }
+    if (SKIP_CFH       && isCFHchip  (image[i].photcode)) { Nskip ++;  mode[i] = 0; continue; }
+    
     /* skip all except WRP images */
     if (strcmp(&image[i].coords.ctype[4], "-WRP")) {
@@ -160,5 +166,5 @@
     setImageRaw (catalog, Ncatalog, i, raw, Nraw, MODE_MOSAIC);
     if (USE_GALAXY_MODEL) {
-      // XXX DEPRECATE?
+      // the image calibration was calculated using a galaxy motion model
       image[i].flags |= ID_IMAGE_ASTROM_GMM;
     }
@@ -281,4 +287,10 @@
     }
 
+    // allow certain cameras to stay static
+    if (SKIP_PS1_CHIP  && isGPC1chip (image[i].photcode)) { threadinfo->Nskip ++;  threadinfo->mode[i] = 0; continue; }
+    if (SKIP_PS1_STACK && isGPC1stack(image[i].photcode)) { threadinfo->Nskip ++;  threadinfo->mode[i] = 0; continue; }
+    if (SKIP_HSC       && isHSCchip  (image[i].photcode)) { threadinfo->Nskip ++;  threadinfo->mode[i] = 0; continue; }
+    if (SKIP_CFH       && isCFHchip  (image[i].photcode)) { threadinfo->Nskip ++;  threadinfo->mode[i] = 0; continue; }
+    
     /* skip all except WRP images */
     if (strcmp(&image[i].coords.ctype[4], "-WRP")) {
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateMeasures.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateMeasures.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateMeasures.c	(revision 39731)
@@ -115,5 +115,23 @@
 
       // only modify the chip coordinates
-      if (isGPC1chip (measureT->photcode)) {
+      if (UPDATE_PS1_CHIP_MEASURE && isGPC1chip (measureT->photcode)) {
+	measureT->R = R;
+	measureT->D = D;
+	if (measureB) {
+	  measureB->R = R;
+	  measureB->D = D;
+	}
+      }
+      // only modify the chip coordinates
+      if (UPDATE_HSC_MEASURE && isGPC1chip (measureT->photcode)) {
+	measureT->R = R;
+	measureT->D = D;
+	if (measureB) {
+	  measureB->R = R;
+	  measureB->D = D;
+	}
+      }
+      // only modify the chip coordinates
+      if (UPDATE_CFH_MEASURE && isGPC1chip (measureT->photcode)) {
 	measureT->R = R;
 	measureT->D = D;
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateObjectOffsets.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateObjectOffsets.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateObjectOffsets.c	(revision 39731)
@@ -197,4 +197,8 @@
     if (CHECK_MEASURE_TO_IMAGE) strextend (&command, "-check-measures");
 
+    if (UPDATE_PS1_CHIP_MEASURE) strextend (&command, "-update-ps1-chip");
+    if (UPDATE_HSC_MEASURE)    	 strextend (&command, "-update-hsc");
+    if (UPDATE_CFH_MEASURE)    	 strextend (&command, "-update-cfh");
+
     if (PHOTCODE_KEEP_LIST) strextend (&command, "+photcode %s", PHOTCODE_KEEP_LIST);
     if (PHOTCODE_SKIP_LIST) strextend (&command, "-photcode %s", PHOTCODE_SKIP_LIST);
@@ -330,4 +334,8 @@
     if (CHECK_MEASURE_TO_IMAGE) strextend (&command, "-check-measures");
 
+    if (UPDATE_PS1_CHIP_MEASURE) strextend (&command, "-update-ps1-chip");
+    if (UPDATE_HSC_MEASURE)    	 strextend (&command, "-update-hsc");
+    if (UPDATE_CFH_MEASURE)    	 strextend (&command, "-update-cfh");
+
     if (PHOTCODE_KEEP_LIST) strextend (&command, "+photcode %s", PHOTCODE_KEEP_LIST);
     if (PHOTCODE_SKIP_LIST) strextend (&command, "-photcode %s", PHOTCODE_SKIP_LIST);
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateObjects.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateObjects.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateObjects.c	(revision 39731)
@@ -852,8 +852,13 @@
   int i;
 
-  if (USE_GALAXY_MODEL) {
+  if (APPLY_PROPER_MOTION) {
     for (i = 0; i < Nfit; i++) {
-      fit[i].uR = average->uRgal;
-      fit[i].uD = average->uDgal;
+      if (USE_GALAXY_MODEL) {
+	fit[i].uR = average->uRgal;
+	fit[i].uD = average->uDgal;
+      } else {
+	fit[i].uR = average->uR;
+	fit[i].uD = average->uD;
+      }
     }
   } else {
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateStacks.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateStacks.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/UpdateStacks.c	(revision 39731)
@@ -3,4 +3,6 @@
 // NOTE: we only measure the systematic floor of the astrometric scatter per stack, no change to the calibration
 int UpdateStacks (Catalog *catalog, int Ncatalog) {
+
+  if (SKIP_PS1_STACK) return TRUE;
 
   off_t Nimage;
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/args.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/args.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/args.c	(revision 39731)
@@ -116,4 +116,66 @@
   }
 
+  // used to decide if changes to the image parameters get applied to the measures
+  APPLY_OFFSETS = FALSE;
+  if ((N = get_argument (argc, argv, "-apply-offsets"))) {
+    remove_argument (N, &argc, argv);
+    APPLY_OFFSETS = TRUE;
+  }
+
+  APPLY_PROPER_MOTION = FALSE;
+  if ((N = get_argument (argc, argv, "-apply-proper-motion"))) {
+    remove_argument (N, &argc, argv);
+    APPLY_PROPER_MOTION = TRUE;
+  }
+
+  SKIP_PS1_CHIP = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-ps1-chip"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_PS1_CHIP = TRUE;
+  }
+  SKIP_PS1_STACK = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-ps1-stack"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_PS1_STACK = TRUE;
+  }
+  SKIP_HSC = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-hsc"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_HSC = TRUE;
+  }
+  SKIP_CFH = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-cfh"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_CFH = TRUE;
+  }
+
+  UPDATE_PS1_CHIP_MEASURE = FALSE;
+  if ((N = get_argument (argc, argv, "-update-ps1-chip"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE_PS1_CHIP_MEASURE = TRUE;
+  }
+  UPDATE_HSC_MEASURE = FALSE;
+  if ((N = get_argument (argc, argv, "-update-hsc"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE_HSC_MEASURE = TRUE;
+  }
+  UPDATE_CFH_MEASURE = FALSE;
+  if ((N = get_argument (argc, argv, "-update-cfh"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE_CFH_MEASURE = TRUE;
+  }
+  if (RELASTRO_OP == OP_UPDATE_OFFSETS) {
+    if (!UPDATE_PS1_CHIP_MEASURE && !UPDATE_HSC_MEASURE && !UPDATE_CFH_MEASURE) {
+      fprintf (stderr, "for -update-offsets, need to select at least one of -update-ps1-chip, -update-hsc, -update-cfh\n");
+      exit (2);
+    }
+  }
+  if ((RELASTRO_OP == OP_PARALLEL_IMAGES) || (RELASTRO_OP == OP_IMAGES)) {
+    if (APPLY_OFFSETS && !UPDATE_PS1_CHIP_MEASURE && !UPDATE_HSC_MEASURE && !UPDATE_CFH_MEASURE) {
+      fprintf (stderr, "for [-images or -parallel-images] with -apply-offsets, need to select at least one of -update-ps1-chip, -update-hsc, -update-cfh\n");
+      exit (2);
+    }
+  }
+
   PARALLEL_REGIONS_MANUAL = FALSE;
   if ((N = get_argument (argc, argv, "-parallel-regions"))) {
@@ -211,4 +273,8 @@
     remove_argument (N, &argc, argv);
     FIT_TARGET = TARGET_MOSAICS;
+  }
+  if ((N = get_argument (argc, argv, "-set-chips"))) {
+    remove_argument (N, &argc, argv);
+    FIT_TARGET = SET_CHIPS;
   }
 
@@ -315,10 +381,4 @@
     remove_argument (N, &argc, argv);
     MaxDensityUse = TRUE;
-  }
-
-  APPLY_OFFSETS = FALSE;
-  if ((N = get_argument (argc, argv, "-apply-offsets"))) {
-    remove_argument (N, &argc, argv);
-    APPLY_OFFSETS = TRUE;
   }
 
@@ -724,4 +784,47 @@
     remove_argument (N, &argc, argv);
     CHECK_MEASURE_TO_IMAGE = TRUE;
+  }
+
+  SKIP_PS1_CHIP = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-ps1-chip"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_PS1_CHIP = TRUE;
+  }
+  SKIP_PS1_STACK = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-ps1-stack"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_PS1_STACK = TRUE;
+  }
+  SKIP_HSC = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-hsc"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_HSC = TRUE;
+  }
+  SKIP_CFH = FALSE;
+  if ((N = get_argument (argc, argv, "-skip-cfh"))) {
+    remove_argument (N, &argc, argv);
+    SKIP_CFH = TRUE;
+  }
+
+  UPDATE_PS1_CHIP_MEASURE = FALSE;
+  if ((N = get_argument (argc, argv, "-update-ps1-chip"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE_PS1_CHIP_MEASURE = TRUE;
+  }
+  UPDATE_HSC_MEASURE = FALSE;
+  if ((N = get_argument (argc, argv, "-update-hsc"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE_HSC_MEASURE = TRUE;
+  }
+  UPDATE_CFH_MEASURE = FALSE;
+  if ((N = get_argument (argc, argv, "-update-cfh"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE_CFH_MEASURE = TRUE;
+  }
+  if (RELASTRO_OP == OP_UPDATE_OFFSETS) {
+    if (!UPDATE_PS1_CHIP_MEASURE && !UPDATE_HSC_MEASURE && !UPDATE_CFH_MEASURE) {
+      fprintf (stderr, "for -update-offsets, need to select at least one of -update-ps1-chip, -update-hsc, -update-cfh\n");
+      exit (2);
+    }
   }
 
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/assign_images.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/assign_images.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/assign_images.c	(revision 39731)
@@ -72,4 +72,10 @@
 
   for (j = 0; j < Nimage; j++) {
+    
+    // allow certain cameras to stay static
+    if (SKIP_PS1_CHIP  && isGPC1chip (image[j].photcode)) continue;
+    if (SKIP_PS1_STACK && isGPC1stack(image[j].photcode)) continue;
+    if (SKIP_HSC       && isHSCchip  (image[j].photcode)) continue;
+    if (SKIP_CFH       && isCFHchip  (image[j].photcode)) continue;
     
     /* select images by photcode, or equiv photcode, if specified */
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/bcatalog.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/bcatalog.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/bcatalog.c	(revision 39731)
@@ -187,4 +187,10 @@
       if (isGPC1warp(catalog[0].measure[offset].photcode)) continue;
 
+      // allow certain cameras to stay static
+      if (SKIP_PS1_CHIP  && isGPC1chip(catalog[0].measure[offset].photcode)) continue;
+      if (SKIP_PS1_STACK && isGPC1stack(catalog[0].measure[offset].photcode)) continue;
+      if (SKIP_HSC       && isHSCchip(catalog[0].measure[offset].photcode)) continue;
+      if (SKIP_CFH       && isCFHchip(catalog[0].measure[offset].photcode)) continue;
+
       // filter objects based on user supplied criteria, including SIGMA_LIM
       if (!MeasFilterTest(&catalog[0].measure[offset], TRUE)) {
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/extra.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/extra.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/extra.c	(revision 39731)
@@ -39,2 +39,26 @@
   return FALSE;
 }
+
+// for now (20160925) I need to identify HSC chips explicitly.  generalize in the future
+int isHSCchip (int photcode) {
+
+  if ((photcode >= 20000) && (photcode <= 20111)) return TRUE; // g-band
+  if ((photcode >= 21000) && (photcode <= 21111)) return TRUE; // r-band
+  if ((photcode >= 22000) && (photcode <= 22111)) return TRUE; // i-band
+  if ((photcode >= 23000) && (photcode <= 23111)) return TRUE; // z-band
+  if ((photcode >= 24000) && (photcode <= 24111)) return TRUE; // y-band
+
+  return FALSE;
+}
+
+// for now (20160925) I need to identify CFH chips explicitly.  generalize in the future
+int isCFHchip (int photcode) {
+
+  if ((photcode >= 100) && (photcode <= 152)) return TRUE; // g-band
+  if ((photcode >= 200) && (photcode <= 252)) return TRUE; // r-band
+  if ((photcode >= 300) && (photcode <= 352)) return TRUE; // i-band
+  if ((photcode >= 400) && (photcode <= 452)) return TRUE; // z-band
+  if ((photcode >= 500) && (photcode <= 552)) return TRUE; // y-band
+
+  return FALSE;
+}
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/launch_region_hosts.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/launch_region_hosts.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/launch_region_hosts.c	(revision 39731)
@@ -98,4 +98,7 @@
 	strextend (&command, "-update-mosaics");
 	break;
+      case SET_CHIPS:
+	strextend (&command, "-set-chips");
+	break;
       case TARGET_NONE:
 	abort();
@@ -136,4 +139,5 @@
     if (LoopWeight2MASS) {  strextend (&command, "-loop-weights-2mass %s", LoopWeight2MASSstr); }
     if (LoopWeightTycho) {  strextend (&command, "-loop-weights-tycho %s", LoopWeightTychostr); }
+    if (APPLY_PROPER_MOTION) strextend (&command, "-apply-proper-motion");
 
     strextend (&command, "-D RELASTRO_SRC_MEAS_TOOFEW %d", SRC_MEAS_TOOFEW);
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/load_catalogs.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/load_catalogs.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/load_catalogs.c	(revision 39731)
@@ -217,4 +217,10 @@
     if (PhotFlagBad)         strextend (&command, "+photflagbad %d", PhotFlagBad); 
     if (PhotFlagPoor)        strextend (&command, "+photflagpoor %d", PhotFlagPoor);
+
+    if (SKIP_PS1_CHIP)       strextend (&command, "-skip-ps1-chip");
+    if (SKIP_PS1_STACK)      strextend (&command, "-skip-ps1-stack");
+    if (SKIP_HSC)            strextend (&command, "-skip-hsc");
+    if (SKIP_CFH)            strextend (&command, "-skip-cfh");
+
     // XXX note that the above pass in the flag as decimal -- also note that args.c cannot handle 0xHEX values
 
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/relastro_images.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/relastro_images.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/relastro_images.c	(revision 39731)
@@ -90,4 +90,11 @@
       break;
 
+    case SET_CHIPS:
+      // we just want to fit the selected chips to the mean positions
+      UpdateChips (catalog, Ncatalog, i);   // measure.X,Y -> R,D, fit image.coords
+      MARKTIME("update chips: %f sec\n", dtime);
+
+      break;
+
     case TARGET_MOSAICS:
       for (i = 0; i < NLOOP; i++) {
Index: branches/czw_branch/20160809/Ohana/src/relastro/src/select_images.c
===================================================================
--- branches/czw_branch/20160809/Ohana/src/relastro/src/select_images.c	(revision 39730)
+++ branches/czw_branch/20160809/Ohana/src/relastro/src/select_images.c	(revision 39731)
@@ -121,4 +121,10 @@
     }
 
+    // allow certain cameras to stay static
+    if (SKIP_PS1_CHIP  && isGPC1chip (timage[i].photcode)) continue;
+    if (SKIP_PS1_STACK && isGPC1stack(timage[i].photcode)) continue;
+    if (SKIP_HSC       && isHSCchip  (timage[i].photcode)) continue;
+    if (SKIP_CFH       && isCFHchip  (timage[i].photcode)) continue;
+    
     /* select images by photcode, or equiv photcode, if specified */
     if (NphotcodesKeep > 0) {
