Index: /branches/eam_branches/psModules.20211028/src/imcombine/pmStack.c
===================================================================
--- /branches/eam_branches/psModules.20211028/src/imcombine/pmStack.c	(revision 41878)
+++ /branches/eam_branches/psModules.20211028/src/imcombine/pmStack.c	(revision 41879)
@@ -113,5 +113,5 @@
 // KMM functions to do bimodality rejection of pixels
 double gaussian(float x, float m, float s) {
-  return(pow(s * sqrt(2 * M_PI),-1) * exp(-0.5 * pow( (x - m) / s, 2)));
+    return(pow(s * sqrt(2 * M_PI),-1) * exp(-0.5 * pow( (x - m) / s, 2)));
 }
 
@@ -122,91 +122,91 @@
 			 float *pi2, float *m2, float *s2,
                          int xyrdebug) {
-  assert(values);
-  assert(values->type.type == PS_TYPE_F32);
+    assert(values);
+    assert(values->type.type == PS_TYPE_F32);
   
-  double logL_bimodal = 0, logL_unimodal;
-  psVector *P1 = psVectorAlloc(values->n,PS_TYPE_F32);
-  psVector *P2 = psVectorAlloc(values->n,PS_TYPE_F32);
-  int i;
-  int discrepant_index = -1;
-  double discrepant_value = 0;
+    double logL_bimodal = 0, logL_unimodal;
+    psVector *P1 = psVectorAlloc(values->n,PS_TYPE_F32);
+    psVector *P2 = psVectorAlloc(values->n,PS_TYPE_F32);
+    int i;
+    int discrepant_index = -1;
+    double discrepant_value = 0;
 /*   int debug = 0; */
   
-  // Calculate unimodal properties
-  *mU = 0;
-  *sU = 0;
-  logL_unimodal = 0;
-  for (i = 0; i < values->n; i++) { // Calculate mean
-    *mU += values->data.F32[i];
-  }
-  *mU /= values->n;
-  for (i = 0; i < values->n; i++) { // Calculate sigma
-    *sU += pow(values->data.F32[i] - *mU,2);
-
-    // Attempt to guess better starting values
-    if (pow(values->data.F32[i] - *mU,2) > discrepant_value) {
-      discrepant_value = pow(values->data.F32[i] - *mU,2);
-      discrepant_index = i;
-    }
+    // Calculate unimodal properties
+    *mU = 0;
+    *sU = 0;
+    logL_unimodal = 0;
+    for (i = 0; i < values->n; i++) { // Calculate mean
+	*mU += values->data.F32[i];
+    }
+    *mU /= values->n;
+    for (i = 0; i < values->n; i++) { // Calculate sigma
+	*sU += pow(values->data.F32[i] - *mU,2);
+
+	// Attempt to guess better starting values
+	if (pow(values->data.F32[i] - *mU,2) > discrepant_value) {
+	    discrepant_value = pow(values->data.F32[i] - *mU,2);
+	    discrepant_index = i;
+	}
     
-  }
-  *sU = sqrt(*sU / values->n);
-  for (i = 0; i < values->n; i++) { // Calculate log likelihood
-    logL_unimodal += log(gaussian(values->data.F32[i],*mU,*sU));
-  }
-
-  if (xyrdebug == 1) { 
-      fprintf(stderr,"KMM uni: %d %f %d (%f %f)\n", 
-              xyrdebug,logL_unimodal,discrepant_index, 
-              *mU,*sU); 
-  } 
-
-  // Do EM loop
-  float dL = 0;
-  float oldL = -999;
-  *iter = 0;
-  logL_bimodal = logL_unimodal;
-
-  if (discrepant_index == -1) {
-    *m1 = *mU - 3 * *sU;
-    *m2 = *mU + 3 * *sU;
-    *s1 = *sU / 2;
-    *s2 = *sU / 2;
-  }
-  else {
-    // This is an attempt to speed up convergence. Find the largest contributor to sigma, and set one mean
-    // to that value.  Set the other mean to the mean of all other points with this one removed.  Next,
-    // set the sigmas to be equal to each other.  Take the value of sigma to be such that a point equidistant
-    // to the initial values of the two modes is equally not believed by either mode (2.5 sigma away).
+    }
+    *sU = sqrt(*sU / values->n);
+    for (i = 0; i < values->n; i++) { // Calculate log likelihood
+	logL_unimodal += log(gaussian(values->data.F32[i],*mU,*sU));
+    }
+
+    if (xyrdebug == 1) { 
+	fprintf(stderr,"KMM uni: %d %f %d (%f %f)\n", 
+		xyrdebug,logL_unimodal,discrepant_index, 
+		*mU,*sU); 
+    } 
+
+    // Do EM loop
+    float dL = 0;
+    float oldL = -999;
+    *iter = 0;
+    logL_bimodal = logL_unimodal;
+
+    if (discrepant_index == -1) {
+	*m1 = *mU - 3 * *sU;
+	*m2 = *mU + 3 * *sU;
+	*s1 = *sU / 2;
+	*s2 = *sU / 2;
+    }
+    else {
+	// This is an attempt to speed up convergence. Find the largest contributor to sigma, and set one mean
+	// to that value.  Set the other mean to the mean of all other points with this one removed.  Next,
+	// set the sigmas to be equal to each other.  Take the value of sigma to be such that a point equidistant
+	// to the initial values of the two modes is equally not believed by either mode (2.5 sigma away).
     
-    discrepant_value = values->data.F32[discrepant_index];
+	discrepant_value = values->data.F32[discrepant_index];
     
-    if (discrepant_value >  *mU) {
-      *m1 = ((*mU * values->n) - discrepant_value) / (values->n - 1);
-      *m2 = discrepant_value;
-    }
-    else {
-      *m1 = discrepant_value;
-      *m2 = ((*mU * values->n) - discrepant_value) / (values->n - 1);
-    }
-    *s1 = fabs((*m1 - *m2) / 5);
-    *s2 = *s1;
-  }
+	if (discrepant_value >  *mU) {
+	    *m1 = ((*mU * values->n) - discrepant_value) / (values->n - 1);
+	    *m2 = discrepant_value;
+	}
+	else {
+	    *m1 = discrepant_value;
+	    *m2 = ((*mU * values->n) - discrepant_value) / (values->n - 1);
+	}
+	*s1 = fabs((*m1 - *m2) / 5);
+	*s2 = *s1;
+    }
     
-  *pi1 = 0.5;
-  *pi2 = 0.5;
-
-  //MEH -- need to be double to help avoid 0 in norm
-  double g1,g2,norm;
-  float w1,w2;
-
-  // These should be options.
-  float KMM_TOLERANCE = 1e-6;
-  int KMM_MAX_ITERATIONS = 30;
-  float KMM_SMALL_NUMBER = 1e-5;
-  while (((dL > KMM_TOLERANCE)||(*iter < 3))&&(*iter < KMM_MAX_ITERATIONS)) {
-    *iter += 1;
-    dL = fabs(logL_bimodal - oldL);
-    oldL = logL_bimodal;
+    *pi1 = 0.5;
+    *pi2 = 0.5;
+
+    //MEH -- need to be double to help avoid 0 in norm
+    double g1,g2,norm;
+    float w1,w2;
+
+    // These should be options.
+    float KMM_TOLERANCE = 1e-6;
+    int KMM_MAX_ITERATIONS = 30;
+    float KMM_SMALL_NUMBER = 1e-5;
+    while (((dL > KMM_TOLERANCE)||(*iter < 3))&&(*iter < KMM_MAX_ITERATIONS)) {
+	*iter += 1;
+	dL = fabs(logL_bimodal - oldL);
+	oldL = logL_bimodal;
 /*     if (debug == 1) { */
 /*       fprintf(stderr,"KMM: %d %f %f %f %f (%f %f %f) (%f %f %f)\n", */
@@ -216,124 +216,124 @@
 /*     } */
 
+	if (xyrdebug == 1) { 
+	    fprintf(stderr,"KMM EM iter: %d %f %f %f %f (%f %f %e) (%f %f %e)\n", 
+		    *iter,logL_unimodal,logL_bimodal,oldL,dL, 
+		    *m1,*s1,*pi1, 
+		    *m2,*s2,*pi2); 
+	} 
+
+	// Expectation/P-stage
+	for (i = 0; i < values->n; i++) { // Calculate probabilities for each mode
+	    g1 = gaussian(values->data.F32[i],*m1,*s1);
+	    g2 = gaussian(values->data.F32[i],*m2,*s2);
+	    norm = (*pi1 * g1 + *pi2 * g2);
+	    //MEH -- must protect denom from norm=0
+	    if (norm > 0) {
+		P1->data.F32[i] = (*pi1 * g1) / norm;
+		P2->data.F32[i] = (*pi2 * g2) / norm;
+	    } else {
+		P1->data.F32[i] = 0.0;
+		P2->data.F32[i] = 0.0;
+	    }	 
+ 
+	    if (xyrdebug == 1) {
+		fprintf(stderr,"KMM EM-P loop: %d %d %le %le %le\n",
+			*iter,i,norm,g1,g2);
+	    }
+
+	}
+	// Maximization/M-stage
+	logL_bimodal = 0;
+	w1 = 0;
+	w2 = 0;
+	for (i = 0; i < values->n; i++) { // Calculate log likelihood
+	    if (!((*pi1 == 0)||(*pi2 == 0))) {
+		logL_bimodal += log(*pi1 * gaussian(values->data.F32[i],*m1,*s1) +
+				    *pi2 * gaussian(values->data.F32[i],*m2,*s2));
+	    }
+	}
+	*m1 = 0;
+	*m2 = 0;
+	*s1 = 0;
+	*s2 = 0;
+	for (i = 0; i < values->n; i++) { // Calculate new means and weights
+	    *m1 += values->data.F32[i] * P1->data.F32[i];
+	    *m2 += values->data.F32[i] * P2->data.F32[i];
+
+	    w1 += P1->data.F32[i];
+	    w2 += P2->data.F32[i];
+
+	    if (xyrdebug == 1) {
+		fprintf(stderr,"KMM EM-M loop: %d %d (%f %f %f %e) (%f %f %f %e)\n",
+			*iter,i,*m1,values->data.F32[i],w1,P1->data.F32[i],*m2,values->data.F32[i],w2,P2->data.F32[i]);
+	    }
+
+	}
+	*m1 /= w1;
+	*m2 /= w2;
+	for (i = 0; i < values->n; i++) { // Calculate new sigmas
+	    *s1 += pow(values->data.F32[i] - *m1,2) * P1->data.F32[i];
+	    *s2 += pow(values->data.F32[i] - *m2,2) * P2->data.F32[i];
+	}
+	*s1 = sqrt(*s1 / w1);
+	*s2 = sqrt(*s2 / w2);
+
+	*pi1 = w1 / values->n;
+	*pi2 = w2 / values->n;
+
+	if (!isfinite(*pi1)) { // finite checks
+	    *pi1 = 0.0;
+	}
+	if (!isfinite(*pi2)) { // finite checks
+	    *pi2 = 0.0;
+	}
+	if (*s1 == 0) { // sigma may not be zero -- MEH -- nor <0 and need additive offset if m~0
+	    *s1 = fabsf(KMM_SMALL_NUMBER * *m1) + KMM_SMALL_NUMBER;
+	}
+	if (*s2 == 0) { // sigma may not be zero 
+	    *s2 = fabsf(KMM_SMALL_NUMBER * *m2) + KMM_SMALL_NUMBER;
+	}
+
+	if (xyrdebug == 1) { 
+	    fprintf(stderr,"KMM EM end: %d %f %f %f %f (%f %e %e %f) (%f %e %e %f)\n", 
+		    *iter,logL_unimodal,logL_bimodal,oldL,dL, 
+		    *m1,*s1,*pi1,w1, 
+		    *m2,*s2,*pi2,w2); 
+	} 
+
+    } // End EM phase
+
+    // Calculate Punimodal
+    double lambda = -2.0 * (logL_unimodal - logL_bimodal);
+    int    df     = 2 + 2 * 1; // I can't find my reference on this. 
+    if (lambda > 0) {
+	*Punimodal = gsl_cdf_chisq_Q(lambda,df);
+    }
+    else { // If lambda <= 0, then logL_unimodal > logL_bimodal, so Punimodal must be by definition 1.0
+	*Punimodal = 1.0;
+    }
+
     if (xyrdebug == 1) { 
-        fprintf(stderr,"KMM EM iter: %d %f %f %f %f (%f %f %e) (%f %f %e)\n", 
-                *iter,logL_unimodal,logL_bimodal,oldL,dL, 
-                *m1,*s1,*pi1, 
-                *m2,*s2,*pi2); 
+	fprintf(stderr,"KMM calc Puni: %d %f %d %f\n", 
+		xyrdebug,lambda,df,*Punimodal); 
     } 
 
-    // Expectation/P-stage
-    for (i = 0; i < values->n; i++) { // Calculate probabilities for each mode
-      g1 = gaussian(values->data.F32[i],*m1,*s1);
-      g2 = gaussian(values->data.F32[i],*m2,*s2);
-      norm = (*pi1 * g1 + *pi2 * g2);
-      //MEH -- must protect denom from norm=0
-      if (norm > 0) {
-	  P1->data.F32[i] = (*pi1 * g1) / norm;
-	  P2->data.F32[i] = (*pi2 * g2) / norm;
-      } else {
-	  P1->data.F32[i] = 0.0;
-	  P2->data.F32[i] = 0.0;
-      }	 
- 
-      if (xyrdebug == 1) {
-          fprintf(stderr,"KMM EM-P loop: %d %d %le %le %le\n",
-                         *iter,i,norm,g1,g2);
-      }
-
-    }
-    // Maximization/M-stage
-    logL_bimodal = 0;
-    w1 = 0;
-    w2 = 0;
-    for (i = 0; i < values->n; i++) { // Calculate log likelihood
-      if (!((*pi1 == 0)||(*pi2 == 0))) {
-	logL_bimodal += log(*pi1 * gaussian(values->data.F32[i],*m1,*s1) +
-			    *pi2 * gaussian(values->data.F32[i],*m2,*s2));
-      }
-    }
-    *m1 = 0;
-    *m2 = 0;
-    *s1 = 0;
-    *s2 = 0;
-    for (i = 0; i < values->n; i++) { // Calculate new means and weights
-      *m1 += values->data.F32[i] * P1->data.F32[i];
-      *m2 += values->data.F32[i] * P2->data.F32[i];
-
-      w1 += P1->data.F32[i];
-      w2 += P2->data.F32[i];
-
-      if (xyrdebug == 1) {
-          fprintf(stderr,"KMM EM-M loop: %d %d (%f %f %f %e) (%f %f %f %e)\n",
-                         *iter,i,*m1,values->data.F32[i],w1,P1->data.F32[i],*m2,values->data.F32[i],w2,P2->data.F32[i]);
-      }
-
-    }
-    *m1 /= w1;
-    *m2 /= w2;
-    for (i = 0; i < values->n; i++) { // Calculate new sigmas
-      *s1 += pow(values->data.F32[i] - *m1,2) * P1->data.F32[i];
-      *s2 += pow(values->data.F32[i] - *m2,2) * P2->data.F32[i];
-    }
-    *s1 = sqrt(*s1 / w1);
-    *s2 = sqrt(*s2 / w2);
-
-    *pi1 = w1 / values->n;
-    *pi2 = w2 / values->n;
-
-    if (!isfinite(*pi1)) { // finite checks
-      *pi1 = 0.0;
-    }
-    if (!isfinite(*pi2)) { // finite checks
-      *pi2 = 0.0;
-    }
-    if (*s1 == 0) { // sigma may not be zero -- MEH -- nor <0 and need additive offset if m~0
-      *s1 = fabsf(KMM_SMALL_NUMBER * *m1) + KMM_SMALL_NUMBER;
-    }
-    if (*s2 == 0) { // sigma may not be zero 
-      *s2 = fabsf(KMM_SMALL_NUMBER * *m2) + KMM_SMALL_NUMBER;
-    }
-
-    if (xyrdebug == 1) { 
-        fprintf(stderr,"KMM EM end: %d %f %f %f %f (%f %e %e %f) (%f %e %e %f)\n", 
-                *iter,logL_unimodal,logL_bimodal,oldL,dL, 
-                *m1,*s1,*pi1,w1, 
-                *m2,*s2,*pi2,w2); 
-    } 
-
-  } // End EM phase
-
-  // Calculate Punimodal
-  double lambda = -2.0 * (logL_unimodal - logL_bimodal);
-  int    df     = 2 + 2 * 1; // I can't find my reference on this. 
-  if (lambda > 0) {
-    *Punimodal = gsl_cdf_chisq_Q(lambda,df);
-  }
-  else { // If lambda <= 0, then logL_unimodal > logL_bimodal, so Punimodal must be by definition 1.0
-    *Punimodal = 1.0;
-  }
-
-  if (xyrdebug == 1) { 
-      fprintf(stderr,"KMM calc Puni: %d %f %d %f\n", 
-              xyrdebug,lambda,df,*Punimodal); 
-  } 
-
-  psFree(P1);
-  psFree(P2);
+    psFree(P1);
+    psFree(P2);
 }
 
 static void KMMFindPopular(const psVector *values, float *Punimodal, float *mean, float *sigma, float *pi, int xyrdebug) {
-  float KMM_MINIMUM_PVALUE = 0.05; // Should be an option.
-  float mU,sU;
-  float pi1,m1,s1,pi2,m2,s2;
-  int iter;
-
-  assert(values);
-  assert(values->type.type == PS_TYPE_F32);
+    float KMM_MINIMUM_PVALUE = 0.05; // Should be an option.
+    float mU,sU;
+    float pi1,m1,s1,pi2,m2,s2;
+    int iter;
+
+    assert(values);
+    assert(values->type.type == PS_TYPE_F32);
   
-  KMMcalculate(values,Punimodal,&iter,
-	       &mU,&sU,
-	       &pi1,&m1,&s1,
-	       &pi2,&m2,&s2,xyrdebug);
+    KMMcalculate(values,Punimodal,&iter,
+		 &mU,&sU,
+		 &pi1,&m1,&s1,
+		 &pi2,&m2,&s2,xyrdebug);
 /*   fprintf(stdout,"%g %g : %g %g %g : %g %g %g : %g %d\t", */
 /* 	  mU,sU, */
@@ -347,23 +347,23 @@
 /*   } */
 /*   fprintf(stdout,"\n"); */
-  if (*Punimodal > KMM_MINIMUM_PVALUE) {
-    // Is unimodal
-    *mean = mU;
-    *sigma = sU;
-    *pi = 1.0;
-  }
-  else {
-    // Is bimodal. Select most popular mode.
-    if (pi1 >= pi2) {
-      *mean = m1;
-      *sigma = s1;
-      *pi = pi1;
+    if (*Punimodal > KMM_MINIMUM_PVALUE) {
+	// Is unimodal
+	*mean = mU;
+	*sigma = sU;
+	*pi = 1.0;
     }
     else {
-      *mean = m2;
-      *sigma = s2;
-      *pi = pi2;
-    }
-  }  
+	// Is bimodal. Select most popular mode.
+	if (pi1 >= pi2) {
+	    *mean = m1;
+	    *sigma = s1;
+	    *pi = pi1;
+	}
+	else {
+	    *mean = m2;
+	    *sigma = s2;
+	    *pi = pi2;
+	}
+    }  
 }
 
@@ -381,5 +381,5 @@
                                     const psVector *exps,      // Exposure times to combine
                                     const psVector *weights // Weights to apply
-                                    )
+    )
 {
     assert(mean);
@@ -411,6 +411,6 @@
         sumWeight += weights->data.F32[i];
         if (variances) {
-	  //            sumVarianceWeight += variances->data.F32[i] * PS_SQR(weights->data.F32[i]);
-	  sumVarianceWeight += 1 / variances->data.F32[i];
+	    //            sumVarianceWeight += variances->data.F32[i] * PS_SQR(weights->data.F32[i]);
+	    sumVarianceWeight += 1 / variances->data.F32[i];
         }
         if (exps) {
@@ -427,6 +427,6 @@
     *mean = sumValueWeight / sumWeight;
     if (var) {
-      //*var = sumVarianceWeight / PS_SQR(sumWeight);
-      *var = 1 / sumVarianceWeight;
+	//*var = sumVarianceWeight / PS_SQR(sumWeight);
+	*var = 1 / sumVarianceWeight;
     }
     if (exp) {
@@ -445,5 +445,5 @@
                                    const psVector *values, // Values to combine
                                    psVector *sortBuffer // Buffer for sorting
-                                   )
+    )
 {
     assert(values);
@@ -496,5 +496,5 @@
                                         float frac, // Fraction to discard
                                         psVector *sortBuffer // Buffer for sorting
-                                        )
+    )
 {
     int numGood = values->n;            // Number of good values
@@ -527,5 +527,5 @@
                                       int x, int y, // Pixel
                                       int source // Source image index
-                                      )
+    )
 {
     CHECKPIX(x, y, "Marking image %d, pixel %d,%d for inspection\n", source, x, y);
@@ -545,5 +545,5 @@
                                      int x, int y, // Pixel
                                      int source // Source image index
-                                     )
+    )
 {
     CHECKPIX(x, y, "Marking pixel image %d, pixel %d,%d for rejection\n", source, x, y);
@@ -561,60 +561,60 @@
 // least popular mode.
 static void KMMRejectUnpopular(const psArray *inputs, int x, int y) {
-  float KMM_MINIMUM_PVALUE = 0.05;
-  float mU,sU;
-  float Punimodal,pi1,m1,s1,pi2,m2,s2;
-  int iter;
-  int j,k;
-
-  psVector *values = psVectorAlloc(inputs->n, PS_TYPE_F32);
-  k = 0;
-  for (j = 0; j < inputs->n; j++) {
-    pmStackData *data = inputs->data[j]; // Stack data of interest
-    if (!data) {
-      k++;
-      continue;
-    }
-    psImage *image = data->readout->image; // Image of interest
-    int xIn = x - data->readout->col0, yIn = y - data->readout->row0; // Coordinates on input readout
-    values->data.F32[j - k] = image->data.F32[yIn][xIn];
-  }
+    float KMM_MINIMUM_PVALUE = 0.05;
+    float mU,sU;
+    float Punimodal,pi1,m1,s1,pi2,m2,s2;
+    int iter;
+    int j,k;
+
+    psVector *values = psVectorAlloc(inputs->n, PS_TYPE_F32);
+    k = 0;
+    for (j = 0; j < inputs->n; j++) {
+	pmStackData *data = inputs->data[j]; // Stack data of interest
+	if (!data) {
+	    k++;
+	    continue;
+	}
+	psImage *image = data->readout->image; // Image of interest
+	int xIn = x - data->readout->col0, yIn = y - data->readout->row0; // Coordinates on input readout
+	values->data.F32[j - k] = image->data.F32[yIn][xIn];
+    }
   
-  KMMcalculate(values,&Punimodal,&iter,
-	       &mU,&sU,
-	       &pi1,&m1,&s1,
-	       &pi2,&m2,&s2);
-
-   CHECKPIX(x, y, 
-	  "KMM Unpopular Test: %d,%d: Puni: %g in %d",x,y,Punimodal,iter);  
-  if (Punimodal < KMM_MINIMUM_PVALUE) {
-    int i;
-    float g1,g2,norm;
-    float P1,P2;
-
-    for (i = 0; i < values->n; i++) { // Calculate probabilities for each mode
-      g1 = gaussian(values->data.F32[i],m1,s1);
-      g2 = gaussian(values->data.F32[i],m2,s2);
-      norm = (pi1 * g1 + pi2 * g2);
-      P1 = (pi1 * g1) / norm;
-      P2 = (pi2 * g2) / norm;
-
-      CHECKPIX(x, y, "KMM Unpopular Rejection: %d,%d: %f(%d): %d %f %f:(%f %f %f ) %f:(%f %f %f) rejection? %d %d\n",
-	       x, y,
-	       Punimodal,iter,
-	       i, values->data.F32[i],
-	       P1,m1,s1,pi1,
-	       P2,m2,s2,pi2,
-	       (pi1 > pi2)&&(P1 < P2),
-	       (pi1 < pi2)&&(P1 > P2));
-      if ((pi1 > pi2)&&(P1 < P2)) { // mode 1 is more popular, but this element belongs to mode 2
-	combineMarkReject(inputs,x,y,i);
-      }
-      if ((pi1 < pi2)&&(P1 > P2)) { // mode 2 is more popular, but this element belongs to mode 1
-	combineMarkReject(inputs,x,y,i);
-      }
-    }
-  }
-  psFree(values);
-  // else do nothing.
+    KMMcalculate(values,&Punimodal,&iter,
+		 &mU,&sU,
+		 &pi1,&m1,&s1,
+		 &pi2,&m2,&s2);
+
+    CHECKPIX(x, y, 
+	     "KMM Unpopular Test: %d,%d: Puni: %g in %d",x,y,Punimodal,iter);  
+    if (Punimodal < KMM_MINIMUM_PVALUE) {
+	int i;
+	float g1,g2,norm;
+	float P1,P2;
+
+	for (i = 0; i < values->n; i++) { // Calculate probabilities for each mode
+	    g1 = gaussian(values->data.F32[i],m1,s1);
+	    g2 = gaussian(values->data.F32[i],m2,s2);
+	    norm = (pi1 * g1 + pi2 * g2);
+	    P1 = (pi1 * g1) / norm;
+	    P2 = (pi2 * g2) / norm;
+
+	    CHECKPIX(x, y, "KMM Unpopular Rejection: %d,%d: %f(%d): %d %f %f:(%f %f %f ) %f:(%f %f %f) rejection? %d %d\n",
+		     x, y,
+		     Punimodal,iter,
+		     i, values->data.F32[i],
+		     P1,m1,s1,pi1,
+		     P2,m2,s2,pi2,
+		     (pi1 > pi2)&&(P1 < P2),
+		     (pi1 < pi2)&&(P1 > P2));
+	    if ((pi1 > pi2)&&(P1 < P2)) { // mode 1 is more popular, but this element belongs to mode 2
+		combineMarkReject(inputs,x,y,i);
+	    }
+	    if ((pi1 < pi2)&&(P1 > P2)) { // mode 2 is more popular, but this element belongs to mode 1
+		combineMarkReject(inputs,x,y,i);
+	    }
+	}
+    }
+    psFree(values);
+    // else do nothing.
 }
 
@@ -622,44 +622,44 @@
 // faintest mode as determined by the KMM test, and rejecting all inputs that belong to the brighest.
 static void KMMRejectBright(const psArray *inputs, int x, int y) {
-  float KMM_MINIMUM_PVALUE = 0.05;
-  float mU,sU;
-  float Punimodal,pi1,m1,s1,pi2,m2,s2;
-  int iter;
-  int j;
-
-  psVector *values = psVectorAlloc(inputs->n, PS_TYPE_F32);
-  for (j = 0; j < inputs->n; j++) {
-    pmStackData *data = inputs->data[j]; // Stack data of interest
-    psImage *image = data->readout->image; // Image of interest
-    int xIn = x - data->readout->col0, yIn = y - data->readout->row0; // Coordinates on input readout
-    values->data.F32[j] = image->data.F32[yIn][xIn];
-  }
+    float KMM_MINIMUM_PVALUE = 0.05;
+    float mU,sU;
+    float Punimodal,pi1,m1,s1,pi2,m2,s2;
+    int iter;
+    int j;
+
+    psVector *values = psVectorAlloc(inputs->n, PS_TYPE_F32);
+    for (j = 0; j < inputs->n; j++) {
+	pmStackData *data = inputs->data[j]; // Stack data of interest
+	psImage *image = data->readout->image; // Image of interest
+	int xIn = x - data->readout->col0, yIn = y - data->readout->row0; // Coordinates on input readout
+	values->data.F32[j] = image->data.F32[yIn][xIn];
+    }
   
-  KMMcalculate(values,&Punimodal,&iter,
-	       &mU,&sU,
-	       &pi1,&m1,&s1,
-	       &pi2,&m2,&s2);
-  if (Punimodal < KMM_MINIMUM_PVALUE) {
-    int i;
-    float g1,g2,norm;
-    float P1,P2;
-
-    for (i = 0; i < values->n; i++) { // Calculate probabilities for each mode
-      g1 = gaussian(values->data.F32[i],m1,s1);
-      g2 = gaussian(values->data.F32[i],m2,s2);
-      norm = (pi1 * g1 + pi2 * g2);
-      P1 = (pi1 * g1) / norm;
-      P2 = (pi2 * g2) / norm;
-
-      if ((m1 > m2)&&(P1 > P2)) { // m1 is larger, and this element belongs to mode 1
-	combineMarkReject(inputs,x,y,i);
-      }
-      if ((m1 < m2)&&(P1 < P2)) { // m2 is larger, and this element belongs to mode 2
-	combineMarkReject(inputs,x,y,i);
-      }
-    }
-  }
-  psFree(values);
-  // else do nothing.
+    KMMcalculate(values,&Punimodal,&iter,
+		 &mU,&sU,
+		 &pi1,&m1,&s1,
+		 &pi2,&m2,&s2);
+    if (Punimodal < KMM_MINIMUM_PVALUE) {
+	int i;
+	float g1,g2,norm;
+	float P1,P2;
+
+	for (i = 0; i < values->n; i++) { // Calculate probabilities for each mode
+	    g1 = gaussian(values->data.F32[i],m1,s1);
+	    g2 = gaussian(values->data.F32[i],m2,s2);
+	    norm = (pi1 * g1 + pi2 * g2);
+	    P1 = (pi1 * g1) / norm;
+	    P2 = (pi2 * g2) / norm;
+
+	    if ((m1 > m2)&&(P1 > P2)) { // m1 is larger, and this element belongs to mode 1
+		combineMarkReject(inputs,x,y,i);
+	    }
+	    if ((m1 < m2)&&(P1 < P2)) { // m2 is larger, and this element belongs to mode 2
+		combineMarkReject(inputs,x,y,i);
+	    }
+	}
+    }
+    psFree(values);
+    // else do nothing.
 }
 #endif // End if(0) to prevent KMMReject{Unpopular|Bright} from being defined.
@@ -682,5 +682,5 @@
                            psImageMaskType badMaskBits, // Value to mask as 'bad'
                            psImageMaskType suspectMaskBits // Value to mask as 'suspect'
-                           )
+    )
 {
     // Rudimentary error checking
@@ -795,5 +795,5 @@
     // set the mask bits if nGoodBits[i] > f*numGood
     {
-	# define SUSPECT_FRACTION 0.65
+# define SUSPECT_FRACTION 0.65
 	*goodMask = 0x0000;
 	psImageMaskType value = 0x0001;
@@ -840,5 +840,5 @@
 			  int nminpix,         // Minimum number of input per pixel
                           float invTotalWeight    // Inverse of total weight for all inputs
-                          )
+    )
 {
     psVector *pixelData = buffer->pixels; // Values for the pixel of interest
@@ -944,5 +944,5 @@
                         bool useVariance, // Use variance for rejection when combining?
                         bool safe    // Combine safely?
-                        )
+    )
 {
     if (iter <= 0) {
@@ -968,5 +968,5 @@
     bool useKMM = false;
     if (num >= KMM_MINIMUM_INPUTS) {
-      useKMM = true;
+	useKMM = true;
     }
     
@@ -986,7 +986,7 @@
             }
 # endif
-	  KMMFindPopular(pixelData,&Punimodal,&KMMmean,&KMMsigma,&KMMpi,xyrdebug);
-	  CHECKPIX(x,y,"KMM Popularity Contest: (%d,%d) Puni: %g Mean: %f Sigma %f Pi: %f\n",
-		   x,y,Punimodal,KMMmean,KMMsigma,KMMpi);
+	    KMMFindPopular(pixelData,&Punimodal,&KMMmean,&KMMsigma,&KMMpi,xyrdebug);
+	    CHECKPIX(x,y,"KMM Popularity Contest: (%d,%d) Puni: %g Mean: %f Sigma %f Pi: %f\n",
+		     x,y,Punimodal,KMMmean,KMMsigma,KMMpi);
 	}
         for (int i = 0; i < num; i++) {
@@ -994,12 +994,12 @@
         }
         for (int i = 0; i < num; i++) {
-	  // Systematic error contributes to the rejection level
-	  float sysVar;
-	  if (useKMM) { // If we can trust KMM results, set the systematic variance
-	    sysVar = PS_SQR(KMMsigma);
-	  }
-	  else { // Otherwise, use the 10% systematic variance we've done in the past.
-	    sysVar = PS_SQR(sys * pixelData->data.F32[i]);
-	  }
+	    // Systematic error contributes to the rejection level
+	    float sysVar;
+	    if (useKMM) { // If we can trust KMM results, set the systematic variance
+		sysVar = PS_SQR(KMMsigma);
+	    }
+	    else { // Otherwise, use the 10% systematic variance we've done in the past.
+		sysVar = PS_SQR(sys * pixelData->data.F32[i]);
+	    }
 
 	    CHECKPIX(x, y, "Variance %d (%d), pixel %d,%d: %f %f %f\n", 
@@ -1151,12 +1151,12 @@
           default: {
               if (useVariance) {
-		float median;
-		if ((useKMM)&&(Punimodal < 0.05)) {
-		  median = KMMmean;
-		}
-		else {
-                  median = combinationWeightedOlympic(pixelData, pixelWeights,
-						      olympic, buffer->sort); // Median for stack
-		}
+		  float median;
+		  if ((useKMM)&&(Punimodal < 0.05)) {
+		      median = KMMmean;
+		  }
+		  else {
+		      median = combinationWeightedOlympic(pixelData, pixelWeights,
+							  olympic, buffer->sort); // Median for stack
+		  }
 		
 		  CHECKPIX(x, y, "Flag with variance pixel %d,%d: median = %f\n", x, y, median);
@@ -1170,7 +1170,7 @@
                       float diff2 = PS_SQR(diff); // Square difference
 		      CHECKPIX(x,y, "Input %d, pixel %d,%d (%" PRIu16 "): %f %f (%f) %f %f :: %f %f %f %f\n",
-			      i, x, y, pixelSources->data.U16[j], pixelData->data.F32[j], pixelVariances->data.F32[j],
-			      1.0, pixelWeights->data.F32[j], 1.0,
-			      pixelLimits->data.F32[j], diff2, diff2 / pixelLimits->data.F32[j],worst);
+			       i, x, y, pixelSources->data.U16[j], pixelData->data.F32[j], pixelVariances->data.F32[j],
+			       1.0, pixelWeights->data.F32[j], 1.0,
+			       pixelLimits->data.F32[j], diff2, diff2 / pixelLimits->data.F32[j],worst);
 
                       if (diff2 > pixelLimits->data.F32[j]) {
@@ -1435,80 +1435,80 @@
 
 bool pmStackSimpleMedianCombine(
-				pmReadout *combined,
-				psArray *input) {
-  int num = input->n;
-  //  int numCols, numRows;
-  int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine
-  int xSize, ySize;                   // Size of the output image
-
-  psArray *stack = psArrayAlloc(num); // Stack of readouts  
-  for (int i = 0; i < num; i++) {
-    //    pmStackData *data = input->data[i]; // Stack data for this input
-    pmReadout *ro = input->data[i]; // data->readout;  // Readout of interest
-    if (!ro) {
-      continue;
-    }
-    stack->data[i] = psMemIncrRefCounter(ro);
-  }    
-
-  if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize,
-			      stack)) {
-    psError(psErrorCodeLast(), false, "Input stack is not valid.");
+    pmReadout *combined,
+    psArray *input) {
+    int num = input->n;
+    //  int numCols, numRows;
+    int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine
+    int xSize, ySize;                   // Size of the output image
+
+    psArray *stack = psArrayAlloc(num); // Stack of readouts  
+    for (int i = 0; i < num; i++) {
+	//    pmStackData *data = input->data[i]; // Stack data for this input
+	pmReadout *ro = input->data[i]; // data->readout;  // Readout of interest
+	if (!ro) {
+	    continue;
+	}
+	stack->data[i] = psMemIncrRefCounter(ro);
+    }    
+
+    if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize,
+				stack)) {
+	psError(psErrorCodeLast(), false, "Input stack is not valid.");
+	psFree(stack);
+	return false;
+    }
+
+    psVector *pixelData = psVectorAlloc(input->n,PS_TYPE_F32);
+    psVector *pixelMask = psVectorAlloc(input->n,PS_TYPE_VECTOR_MASK);
+    psStats  *stats     = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
+
+    for (int y = minInputRows; y < maxInputRows; y++) {
+	for (int x = minInputCols; x < maxInputCols; x++) {
+	    for (int i = 0; i < input->n; i++) {
+		pmReadout *ro  = stack->data[i];
+		psImage *image = ro->image;
+		pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0;
+		pixelData->data.F32[i] = image->data.F32[y][x];
+		if (isfinite(image->data.F32[y][x])&&
+		    (fabs(image->data.F32[y][x]) < 1e5)) {
+		    pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0;
+		}
+		else {
+		    pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 1;
+		}
+#if (0)
+		if ((x == 59)&&(y > 40)&&(y < 50)) {
+		    fprintf(stderr,"%d %d %d %d %g\n",
+			    x,y,i,pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i],pixelData->data.F32[i]);
+		}
+#endif
+	    }
+	    if (!psVectorStats(stats,pixelData,NULL,pixelMask,1)) {
+		psError(PS_ERR_UNKNOWN, false, "Unable to calculate median");
+		psFree(stats);
+		psFree(pixelData);
+		psFree(pixelMask);
+		psFree(stack);
+		return(false);
+	    }
+	    combined->image->data.F32[y][x] = stats->robustMedian;
+	    if (combined->mask) {
+		combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0;
+	    }
+#if (0)
+	    if ((x == 59)&&(y > 40)&&(y < 50)) {
+		fprintf(stderr,"%d %d %d %d %g\n",
+			x,y,-1,combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x],
+			combined->image->data.F32[y][x]);
+	    }
+#endif
+	}
+    }
+  
+    psFree(stats);
+    psFree(pixelData);
+    psFree(pixelMask);
     psFree(stack);
-    return false;
-  }
-
-  psVector *pixelData = psVectorAlloc(input->n,PS_TYPE_F32);
-  psVector *pixelMask = psVectorAlloc(input->n,PS_TYPE_VECTOR_MASK);
-  psStats  *stats     = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
-
-  for (int y = minInputRows; y < maxInputRows; y++) {
-    for (int x = minInputCols; x < maxInputCols; x++) {
-      for (int i = 0; i < input->n; i++) {
-	pmReadout *ro  = stack->data[i];
-	psImage *image = ro->image;
-	pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0;
-	pixelData->data.F32[i] = image->data.F32[y][x];
-	if (isfinite(image->data.F32[y][x])&&
-	    (fabs(image->data.F32[y][x]) < 1e5)) {
-	  pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0;
-	}
-	else {
-	  pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 1;
-	}
-#if (0)
-      if ((x == 59)&&(y > 40)&&(y < 50)) {
-	  fprintf(stderr,"%d %d %d %d %g\n",
-		  x,y,i,pixelMask->data.PS_TYPE_VECTOR_MASK_DATA[i],pixelData->data.F32[i]);
-	}
-#endif
-      }
-      if (!psVectorStats(stats,pixelData,NULL,pixelMask,1)) {
-	psError(PS_ERR_UNKNOWN, false, "Unable to calculate median");
-	psFree(stats);
-	psFree(pixelData);
-	psFree(pixelMask);
-	psFree(stack);
-	return(false);
-      }
-      combined->image->data.F32[y][x] = stats->robustMedian;
-      if (combined->mask) {
-	combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0;
-      }
-#if (0)
-      if ((x == 59)&&(y > 40)&&(y < 50)) {
-	fprintf(stderr,"%d %d %d %d %g\n",
-		x,y,-1,combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x],
-		combined->image->data.F32[y][x]);
-      }
-#endif
-    }
-  }
-  
-  psFree(stats);
-  psFree(pixelData);
-  psFree(pixelMask);
-  psFree(stack);
-  return (true);
+    return (true);
 }
 
@@ -1519,16 +1519,21 @@
 #define SORT_VV_COMPARE(A,B) (pixelData->data.F32[A] < pixelData->data.F32[B])
 #define SORT_VV_SWAP(TYPE,A,B) {					\
-    if (A != B) {							\
-      psF32 tempVal = pixelData->data.F32[A];				\
-      pixelData->data.F32[A] = pixelData->data.F32[B];			\
-      pixelData->data.F32[B] = tempVal;					\
-      psF32 tempVar = pixelVariances->data.F32[A];			\
-      pixelVariances->data.F32[A] = pixelVariances->data.F32[B];		\
-      pixelVariances->data.F32[B] = tempVar;				\
-    }									\
-}
-
-#define SORT_VALUE_AND_VAR(A,B) { PSSORT(A->n, SORT_VV_COMPARE, SORT_VV_SWAP, F32); }
-  
+	if (A != B) {							\
+	    psF32 tempVal = pixelData->data.F32[A];			\
+	    pixelData->data.F32[A] = pixelData->data.F32[B];		\
+	    pixelData->data.F32[B] = tempVal;				\
+	    psF32 tempVar = pixelVariances->data.F32[A];		\
+	    pixelVariances->data.F32[A] = pixelVariances->data.F32[B];	\
+	    pixelVariances->data.F32[B] = tempVar;			\
+	    if (expTime) {						\
+		psF32 tempExp = expTime->data.F32[A];			\
+		expTime->data.F32[A] = expTime->data.F32[B];		\
+		expTime->data.F32[B] = tempExp;				\
+	    }								\
+	}								\
+    }
+
+// this macro uses the macros above which assume pixelData, pixelVariances, expTime
+#define SORT_VALUES(NVALUES) { PSSORT(NVALUES, SORT_VV_COMPARE, SORT_VV_SWAP, F32); }
 
 bool pmStackCombineByPercentile(
@@ -1537,9 +1542,8 @@
     psArray *stackData,			// input exposures
     psF64 rejectFraction,               // outlier fraction of pixels to reject
-    psF64 maxRange,
     psImageMaskType badMaskBits, 	// treat these bits as 'bad'
     psImageMaskType suspectMaskBits,	// treat these bits as 'suspect'
     psImageMaskType blankMaskBits       // use this mask value for pixels missing input data (distinguish between Ninput = 0 and Ngood = 0?)
-) {
+    ) {
     int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine
     int xSize, ySize;                   // Size of the output image
@@ -1562,18 +1566,14 @@
     // make sure the output readout matches the inputs, and set to blank by default
     pmReadoutUpdateSize(combined, minInputCols, minInputRows, xSize, ySize, true, true, blankMaskBits);
-
-    psImage *exp = NULL, *expnum = NULL, *expweight = NULL; // Exposure map and exposure number
     if (expmaps) {
-        if (!expmaps->image) { exp = expmaps->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); }
-        if (!expmaps->mask) { expnum = expmaps->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK); }
-        if (!expmaps->variance) { expweight = expmaps->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32); }
+	// if we are generating the expmaps, update to match the images, set blank mask areas to 0
+	pmReadoutUpdateSize(expmaps, minInputCols, minInputRows, xSize, ySize, expmaps->mask != NULL, expmaps->variance != NULL, 0);
     }
    
     psVector *pixelData      = psVectorAlloc(stackData->n, PS_TYPE_F32);
     psVector *pixelVariances = psVectorAlloc(stackData->n, PS_TYPE_F32);
-    psVector *pixelMask      = psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK);
-
-    psVector *expTime        = expmask ? psVectorAlloc(stackData->n, PS_TYPE_F32) : NULL;
-    psVector *expNum         = expmask ? psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK): NULL;
+
+    // if we are asking for the exptime maps, generate a storage vector expTime
+    psVector *expTime        = expmaps && expmaps->image ? psVectorAlloc(stackData->n, PS_TYPE_F32) : NULL;
 
     int nGoodBits[16]; // accumulate the good pixel bits here for fuzzy logic
@@ -1589,4 +1589,7 @@
 		pmStackData *data = stackData->data[i]; // Stack data for this input
 		pmReadout *ro = data->readout;  // Readout of interest
+
+		psAssert (ro->mask,     "must must exist, but does not");
+		psAssert (ro->variance, "variance must exist, but does not");
 
 		psImage *image    = ro->image;
@@ -1607,17 +1610,16 @@
 		psImageMaskType value = 0x0001;
 		for (int nbit = 0; nbit < 16; nbit ++) {
-		  if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) {
-		    nGoodBits[nbit] ++;
-		  }
-		  value <<= 1;
+		    if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) {
+			nGoodBits[nbit] ++;
+		    }
+		    value <<= 1;
 		}
 
-		// pixelWeights->data.F32[nGood] = data->weight;
-		// pixelExps->data.F32[nGood] = data->exp;
-		// pixelSources->data.U16[nGood] = i;
-
+		// accumulate pixel data and variance values:
 		pixelData->data.F32[nGood] = image->data.F32[yIn][xIn];
-		if (variance) { pixelVariances->data.F32[nGood] = variance->data.F32[yIn][xIn]; }
-		if (expmask) { pixelVariances->data.F32[nGood] = variance->data.F32[yIn][xIn]; }
+		pixelVariances->data.F32[nGood] = variance->data.F32[yIn][xIn];
+
+		// accumulate exposure times if required
+		if (expTime)  { expTime->data.F32[nGood] = data->exp; }
 
 		nGood ++;
@@ -1647,5 +1649,5 @@
 		combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = blankMaskBits; // probably not needed since it was set above.
 		if (expmaps) {
-		    expmaps->image->F32[y][x] = NAN;
+		    expmaps->image->F32[y][x] = NAN; // XXX should this value be NAN or 0?
 		    expmaps->variance->F32[y][x] = NAN;
 		    expmaps->mask->PS_TYPE_IMAGE_MASK_DATA[y][x] = 0;
@@ -1654,6 +1656,6 @@
 	    }
 
-	    // sort both pixelData and pixelVariance
-	    SORT_VALUE_AND_VAR (pixelData, pixelVariances);
+	    // sort pixelData, pixelVariance, expTime (if it exists)
+	    SORT_VALUES (pixelData->n);
 
 	    // set the given (suspect) mask bit if nGoodBits[i] > f*nGood
@@ -1663,8 +1665,8 @@
 	    psImageMaskType outputMask = 0x0000;
 	    for (int nbit = 0; nbit < 16; nbit ++) {
-	      if (nGoodBits[nbit] > SUSPECT_FRACTION*nGood) {
-		outputMask |= value;
-	      }
-	      value <<= 1;
+		if (nGoodBits[nbit] > SUSPECT_FRACTION*nGood) {
+		    outputMask |= value;
+		}
+		value <<= 1;
 	    }
 
@@ -1688,10 +1690,18 @@
 	    combined->variance->data.F32[y][x] = varValue;
 	    combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = outputMask;
-	}
-    }
-  
+
+	    if (expTime) { 
+		float sum = 0.0;
+		for (int n = Ns; n < Ne; n++) {
+		    sum += expTime->data.F32[n];
+		}
+		expmaps->image->data.F32[y][x] = sum;
+	    }
+	    if (expNum) { expmaps->mask->data.F32[y][x] = Ne - Ns; }
+	}
+    }
     psFree(pixelData);
-    psFree(pixelMask);
-
+    psFree(pixelVariance);
+    psFree(expTime);
     return (true);
 }
Index: /branches/eam_branches/psModules.20211028/src/imcombine/pmStack.h
===================================================================
--- /branches/eam_branches/psModules.20211028/src/imcombine/pmStack.h	(revision 41878)
+++ /branches/eam_branches/psModules.20211028/src/imcombine/pmStack.h	(revision 41879)
@@ -49,7 +49,7 @@
 bool pmStackCombineByPercentile(
     pmReadout *combined,
+    pmReadout *expmaps,
     psArray *input,
-    psF64 minRange,
-    psF64 maxRange,
+    psF64 rejectFraction,
     psImageMaskType badMaskBits, 	// treat these bits as 'bad'
     psImageMaskType suspectMaskBits,	// treat these bits as 'suspect'
