Index: /trunk/psastro/src/Makefile.am
===================================================================
--- /trunk/psastro/src/Makefile.am	(revision 9586)
+++ /trunk/psastro/src/Makefile.am	(revision 9587)
@@ -17,5 +17,6 @@
 psastroDataSave.c           \
 psastroAstromGuess.c        \
-psastroLoadReferences.c     \
+psastroLoadRefstars.c     \
+psastroChooseRefstars.c  \
 psastroConvert.c	    \
 psastroChipAstrom.c         \
@@ -23,7 +24,8 @@
 psastroUtils.c	       	    \
 psastroTestFuncs.c          \
+psastroLuminosityFunction.c \
+psastroRefstarSubset.c      \
 psastroMosaicAstrom.c       \
 psastroMosaicGetGrads.c     \
-psastroMosaicGetRefstars.c  \
 psastroMosaicChipAstrom.c   \
 psastroMosaicSetAstrom.c    \
Index: /trunk/psastro/src/psastro.c
===================================================================
--- /trunk/psastro/src/psastro.c	(revision 9586)
+++ /trunk/psastro/src/psastro.c	(revision 9587)
@@ -39,5 +39,5 @@
 
     // load the reference stars overlapping the data stars
-    psArray *refs = psastroLoadReferences (config);
+    psArray *refs = psastroLoadRefstars (config);
     if (!refs) {
 	psErrorStackPrint(stderr, "failed to load reference data");
@@ -45,6 +45,9 @@
     }
 
-    // XXX ?? what does this do ??
-    psastroMosaicGetRefstars (config, refs);
+    // choose reference stars corresponding to the selected chips
+    if (psastroChooseRefstars (config, refs)) {
+	psErrorStackPrint(stderr, "failed to select reference data for chips");
+	exit (1);
+    }
 
     char *mosastro = psMetadataLookupStr (NULL, config->arguments, "MOSASTRO");
Index: /trunk/psastro/src/psastro.h
===================================================================
--- /trunk/psastro/src/psastro.h	(revision 9586)
+++ /trunk/psastro/src/psastro.h	(revision 9587)
@@ -20,4 +20,13 @@
 # define toTPA toTangentPlane
 # define toSky projection
+
+// this structure represents a fit to the logN / logS curve for a set of stars
+// logN = offset + slope * logS 
+typedef struct {
+  double mMin;
+  double mMax;
+  double offset;
+  double slope;
+} pmLumFunc;
 
 pmConfig         *psastroArguments (int argc, char **argv);
Index: /trunk/psastro/src/psastroChooseRefstars.c
===================================================================
--- /trunk/psastro/src/psastroChooseRefstars.c	(revision 9587)
+++ /trunk/psastro/src/psastroChooseRefstars.c	(revision 9587)
@@ -0,0 +1,91 @@
+# include "psastro.h"
+
+bool psastroChooseRefstars (pmConfig *config, psArray *refs) {
+
+    bool status;
+    pmChip *chip = NULL;
+    pmCell *cell = NULL;
+    pmReadout *readout = NULL;
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, "PSASTRO");
+    if (!recipe) {
+	psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!\n");
+	return false;
+    }
+
+    // select the input data sources
+    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
+    if (!input) {
+	psError(PSASTRO_ERR_CONFIG, true, "Can't find input data!\n");
+	return false;
+    }
+
+    float fieldExtra = psMetadataLookupS32 (&status, recipe, "PSASTRO.FIELD.EXTRA"); 
+    if (!status) fieldExtra = 0.0;
+
+    pmFPAview *view = pmFPAviewAlloc (0);
+    pmFPA *fpa = input->fpa;
+
+    // this loop selects the matched stars for all chips
+    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
+        psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	
+	while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
+            psTrace ("psastro", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+
+	    // process each of the readouts
+	    // XXX there can only be one readout per chip in astrometry, right?
+	    while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
+		if (! readout->data_exists) { continue; }
+
+		// read WCS data from the corresponding header
+		pmHDU *hdu = pmFPAviewThisHDU (view, fpa);
+
+		int Nx = psMetadataLookupS32 (&status, hdu->header, "NAXIS1"); 
+		int Ny = psMetadataLookupS32 (&status, hdu->header, "NAXIS2"); 
+
+		float minX = -fieldExtra*Nx;
+		float maxX = (1+fieldExtra)*Nx;
+		float minY = -fieldExtra*Ny;
+		float maxY = (1+fieldExtra)*Ny;
+
+		// the refstars is a subset within range of this chip
+		psArray *refstars = psArrayAlloc (100);
+
+		// select the reference objects within range of this readout
+		// project the reference objects to this chip
+		for (int i = 0; i < refs->n; i++) {
+		    pmAstromObj *ref = pmAstromObjCopy(refs->data[i]);
+	
+		    // XXX why is this still a private function?
+		    p_psProject (ref->TP, ref->sky, fpa->projection);
+		    psPlaneDistortApply (ref->FP, fpa->fromTangentPlane, ref->TP, 0.0, 0.0);
+		    psPlaneTransformApply (ref->chip, chip->fromFPA, ref->FP);
+
+		    // limit the X,Y range of the refs to the selected chip
+		    if (ref->chip->x < minX) goto skip;
+		    if (ref->chip->x > maxX) goto skip;
+		    if (ref->chip->y < minY) goto skip;
+		    if (ref->chip->y > maxY) goto skip;
+
+		    psArrayAdd (refstars, 100, ref);
+		skip:
+		    psFree (ref);
+		}
+		psTrace ("psastro", 4, "Added %ld refstars\n", refstars->n);
+
+		psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.REFSTARS", PS_DATA_ARRAY, "astrometry matches", refstars);
+
+		psastroRefstarSubset (readout);
+
+		psFree (refstars);
+	    }
+	}
+    }
+
+    psFree (view);
+    return true;
+}
Index: unk/psastro/src/psastroLoadReferences.c
===================================================================
--- /trunk/psastro/src/psastroLoadReferences.c	(revision 9586)
+++ 	(revision )
@@ -1,106 +1,0 @@
-# include "psastro.h"
-// int mkstemp(char *template);
-# define ELIXIR_MODE 1
-# define PIPE_MODE 0
-
-psArray *psastroLoadReferences (pmConfig *config) {
-
-    int fd;
-    bool status;
-    char tempLine[256];
-
-    // select the DVO database?
-
-    // select the current recipe
-    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, "PSASTRO");
-
-    // DVO APIs expect decimal degrees
-    float RAmin  = DEG_RAD*psMetadataLookupF32(NULL, recipe, "RA_MIN");
-    float RAmax  = DEG_RAD*psMetadataLookupF32(NULL, recipe, "RA_MAX");
-    float DECmin = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MIN");
-    float DECmax = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MAX");
-
-    char *CATDIR = psMetadataLookupStr(NULL, recipe, "DVO.CATDIR");
-    if (CATDIR == NULL) {
-	psLogMsg ("psastro", 2, "warning: missing DVO.CATDIR, using HOME/.ptolemyrc definition\n");
-    }
-
-    // XXX need to add a padding area
-    // issue the following command:
-    // getstar -region RAmin RAmax DECmin DECmax
-
-    char tempFile[64];
-    sprintf (tempFile, "/tmp/psastro.XXXXXX");
-    if ((fd = mkstemp (tempFile)) == -1) {
-        fprintf (stderr, "error creating temp output file\n");
-        return NULL;
-    }
-    close (fd);
-
-    // use fork to add timeout capability
-    // use cfitsio |filename format to avoid tempFile
-    # if ELIXIR_MODE
-    if (CATDIR) {
-	sprintf (tempLine, "getstar -D CATDIR %s -D CATFORMAT elixir -D CATMODE mef -region %f %f %f %f -o %s", CATDIR, RAmin, DECmin, RAmax, DECmax, tempFile);
-    } else {
-	sprintf (tempLine, "getstar -D CATFORMAT elixir -D CATMODE mef -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
-    }
-    # else
-    if (CATDIR) {
-	sprintf (tempLine, "getstar -D CATDIR %s -D CATFORMAT panstarrs -D CATMODE mef -region %f %f %f %f -o %s", CATDIR, RAmin, DECmin, RAmax, DECmax, tempFile);
-    } else {
-	sprintf (tempLine, "getstar -D CATFORMAT panstarrs -D CATMODE mef -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
-    }
-    # endif
-
-    psTrace ("psastro", 3, "%s\n", tempLine);
-    status = system (tempLine);
-    if (status) {
-        fprintf (stderr, "error loading reference data\n");
-        return NULL;
-    }
-
-    // the output from getstar is a file with the Average table
-    psFits *fits = psFitsOpen (tempFile, "r");
-
-    # if ELIXIR_MODE
-    psFitsMoveExtName (fits, "DVO_AVERAGE_ELIXIR");
-    # else
-    psFitsMoveExtName (fits, "DVO_AVERAGE_PANSTARRS");
-    # endif
-
-    psMetadata *header = psFitsReadHeader (NULL, fits);
-    psArray *table = psFitsReadTable (fits);
-    psFitsClose (fits);
-    unlink (tempFile);
-
-    // convert the Average table to the pmAstromObj entries
-    psArray *refs = psArrayAlloc (table->n);
-    for (int i = 0; i < table->n; i++) {
-        pmAstromObj *ref = pmAstromObjAlloc ();
-
-        psMetadata *row = table->data[i];
-
-        // DVO tables are stored in degrees
-        # if ELIXIR_MODE
-        ref->sky->r   = RAD_DEG*psMetadataLookupF32 (&status, row, "RA");
-        ref->sky->d   = RAD_DEG*psMetadataLookupF32 (&status, row, "DEC");
-        ref->Mag      = 0.001*psMetadataLookupS32 (&status, row, "MAG");  // XXX ELIXIR uses millimags, PANSTARRS uses mags
-        # else
-        ref->sky->r   = RAD_DEG*psMetadataLookupF64 (&status, row, "RA");
-        ref->sky->d   = RAD_DEG*psMetadataLookupF64 (&status, row, "DEC");
-        ref->Mag      = psMetadataLookupF32 (&status, row, "MAG");
-        # endif
-
-        psArrayAdd (refs, 100, ref);
-        psFree (ref);
-    }
-    psFree (header);
-    psFree (table);
-
-    psTrace ("psastro", 3, "loaded %ld reference stars from (%10.6f,%10.6f) - (%10.6f,%10.6f)\n",
-             refs->n, RAmin, DECmin, RAmax, DECmax);
-    return refs;
-}
-
-// XXX this function needs clarifiction of the getstar output format
Index: /trunk/psastro/src/psastroLoadRefstars.c
===================================================================
--- /trunk/psastro/src/psastroLoadRefstars.c	(revision 9587)
+++ /trunk/psastro/src/psastroLoadRefstars.c	(revision 9587)
@@ -0,0 +1,106 @@
+# include "psastro.h"
+// int mkstemp(char *template);
+# define ELIXIR_MODE 1
+# define PIPE_MODE 0
+
+psArray *psastroLoadRefstars (pmConfig *config) {
+
+    int fd;
+    bool status;
+    char tempLine[256];
+
+    // select the DVO database?
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, "PSASTRO");
+
+    // DVO APIs expect decimal degrees
+    float RAmin  = DEG_RAD*psMetadataLookupF32(NULL, recipe, "RA_MIN");
+    float RAmax  = DEG_RAD*psMetadataLookupF32(NULL, recipe, "RA_MAX");
+    float DECmin = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MIN");
+    float DECmax = DEG_RAD*psMetadataLookupF32(NULL, recipe, "DEC_MAX");
+
+    char *CATDIR = psMetadataLookupStr(NULL, recipe, "DVO.CATDIR");
+    if (CATDIR == NULL) {
+	psLogMsg ("psastro", 2, "warning: missing DVO.CATDIR, using HOME/.ptolemyrc definition\n");
+    }
+
+    // XXX need to add a padding area
+    // issue the following command:
+    // getstar -region RAmin RAmax DECmin DECmax
+
+    char tempFile[64];
+    sprintf (tempFile, "/tmp/psastro.XXXXXX");
+    if ((fd = mkstemp (tempFile)) == -1) {
+        fprintf (stderr, "error creating temp output file\n");
+        return NULL;
+    }
+    close (fd);
+
+    // use fork to add timeout capability
+    // use cfitsio |filename format to avoid tempFile
+    # if ELIXIR_MODE
+    if (CATDIR) {
+	sprintf (tempLine, "getstar -D CATDIR %s -D CATFORMAT elixir -D CATMODE mef -region %f %f %f %f -o %s", CATDIR, RAmin, DECmin, RAmax, DECmax, tempFile);
+    } else {
+	sprintf (tempLine, "getstar -D CATFORMAT elixir -D CATMODE mef -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
+    }
+    # else
+    if (CATDIR) {
+	sprintf (tempLine, "getstar -D CATDIR %s -D CATFORMAT panstarrs -D CATMODE mef -region %f %f %f %f -o %s", CATDIR, RAmin, DECmin, RAmax, DECmax, tempFile);
+    } else {
+	sprintf (tempLine, "getstar -D CATFORMAT panstarrs -D CATMODE mef -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
+    }
+    # endif
+
+    psTrace ("psastro", 3, "%s\n", tempLine);
+    status = system (tempLine);
+    if (status) {
+        fprintf (stderr, "error loading reference data\n");
+        return NULL;
+    }
+
+    // the output from getstar is a file with the Average table
+    psFits *fits = psFitsOpen (tempFile, "r");
+
+    # if ELIXIR_MODE
+    psFitsMoveExtName (fits, "DVO_AVERAGE_ELIXIR");
+    # else
+    psFitsMoveExtName (fits, "DVO_AVERAGE_PANSTARRS");
+    # endif
+
+    psMetadata *header = psFitsReadHeader (NULL, fits);
+    psArray *table = psFitsReadTable (fits);
+    psFitsClose (fits);
+    unlink (tempFile);
+
+    // convert the Average table to the pmAstromObj entries
+    psArray *refs = psArrayAlloc (table->n);
+    for (int i = 0; i < table->n; i++) {
+        pmAstromObj *ref = pmAstromObjAlloc ();
+
+        psMetadata *row = table->data[i];
+
+        // DVO tables are stored in degrees
+        # if ELIXIR_MODE
+        ref->sky->r   = RAD_DEG*psMetadataLookupF32 (&status, row, "RA");
+        ref->sky->d   = RAD_DEG*psMetadataLookupF32 (&status, row, "DEC");
+        ref->Mag      = 0.001*psMetadataLookupS32 (&status, row, "MAG");  // XXX ELIXIR uses millimags, PANSTARRS uses mags
+        # else
+        ref->sky->r   = RAD_DEG*psMetadataLookupF64 (&status, row, "RA");
+        ref->sky->d   = RAD_DEG*psMetadataLookupF64 (&status, row, "DEC");
+        ref->Mag      = psMetadataLookupF32 (&status, row, "MAG");
+        # endif
+
+        psArrayAdd (refs, 100, ref);
+        psFree (ref);
+    }
+    psFree (header);
+    psFree (table);
+
+    psTrace ("psastro", 3, "loaded %ld reference stars from (%10.6f,%10.6f) - (%10.6f,%10.6f)\n",
+             refs->n, RAmin, DECmin, RAmax, DECmax);
+    return refs;
+}
+
+// XXX this function needs clarifiction of the getstar output format
Index: /trunk/psastro/src/psastroLuminosityFunction.c
===================================================================
--- /trunk/psastro/src/psastroLuminosityFunction.c	(revision 9587)
+++ /trunk/psastro/src/psastroLuminosityFunction.c	(revision 9587)
@@ -0,0 +1,94 @@
+# include "psastro.h"
+# define dMag 0.1
+// XXX put this in config?
+
+static void pmLumFuncFree (pmLumFunc *func) {
+
+  if (func == NULL) return;
+
+  return;
+}
+
+pmLumFunc *pmLumFuncAlloc (double mMin, double mMax, double offset, double slope) {
+
+  pmLumFunc *func = (pmLumFunc *) psAlloc(sizeof(pmLumFunc));
+  psMemSetDeallocator(func, (psFreeFunc) pmLumFuncFree);
+
+  func->mMin = 0;
+  func->mMax = 0;
+  func->slope = 0;
+  func->offset = 0;
+
+  return func;
+}
+
+pmLumFunc *psastroRefstarSubset (psArray *stars) {
+
+  // determine the max and min magnitude for the array of stars
+  pmAstromObj *star = stars->data[0];
+  mMin = star->Mag;
+  mMax = star->Mag;
+  for (int i = 0; i < stars->n; i++) {
+    star = stars->data[i];
+    mMin = PS_MIN (star->Mag, mMin);
+    mMax = PS_MAX (star->Mag, mMax);
+  }
+
+  int nBin = 1 + (nMax - nMin) / dMag;
+  if (nBin <= 1) {
+    psError(PSASTRO_ERR_DATA, true, "magnitude range of 0.0\n");
+    return NULL;
+  }
+  
+  // create a histogram of the magnitudes
+  // bin[0] = mMin : mMin + dMag
+  // bin[i] = mMin + i*dMag : mMin + (i+1)*dMag
+  psVector *nMags = psVectorAlloc (nBin, PS_TYPE_F32);
+  for (int i = 0; i < stars->n; i++) {
+    star = stars->data[i];
+    int bin = (star->Mag - mMin) / dMag;
+    nMags->data.F32[bin] += 1.0;
+  }
+
+  psVector *lnMag = psVectorAlloc (nBin, PS_TYPE_F32);
+  psVector *Mag = psVectorAlloc (nBin, PS_TYPE_F32);
+
+  // create 2 vectors represnting the dlogN/dlogS line
+  // exclude bins with no stars
+  int n = 0;
+  for (int i = 0; i < stars->n; i++) {
+    if (nMags->data.F32[i] < 1) continue;
+    lnMag->data.F32[n] = log10 (nMags->data.F32[i]);
+    Mag->data.F32[n] = mMin + (i + 0.5)*dMag;
+    n++;
+  }
+
+  psVector *mask = psVectorAlloc (nBin, PS_TYPE_MASK);
+  psPolynomial1D *line = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 1);
+  psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
+  stats->clipSigma = 3.0;
+  stats->clipIter = 3;
+
+  line = psVectorClipFitPolynomial1D(line, stats, mask, 1, lnMag, NULL, Mag);
+
+  // find min and max unmasked magnitudes
+  mMinValid = NAN;
+  mMaxValid = NAN;
+  for (int i = 0; i < Mag->n; i++) {
+    if (mask->data.U8[i]) continue;
+    if (isnan(mMinValid) || (Mag->data.F32[i] < mMinValid)) {
+      mMinValid = Mag->data.F32[i];
+    }
+    if (isnan(mMaxValid) || (Mag->data.F32[i] > mMaxValid)) {
+      mMaxValid = Mag->data.F32[i];
+    }
+  }
+
+  psLogMsg ("psastro", 4, "logN %f + %f mag\n", line->coeff[0], line->coeff[1]);
+  psLogMsg ("psastro", 4, "logN vs mag residuals: %f +/- %f\n", stats->sampleMedian, stats->sampleStdev);
+
+  pmLumFunc *lumFunc = pmLumFuncAlloc (mMinValid, mMaxValid, line->coeff[0], line->coeff[1]);
+  return (lumFunc);
+}
+
+  
Index: unk/psastro/src/psastroMosaicGetRefstars.c
===================================================================
--- /trunk/psastro/src/psastroMosaicGetRefstars.c	(revision 9586)
+++ 	(revision )
@@ -1,87 +1,0 @@
-# include "psastro.h"
-
-bool psastroMosaicGetRefstars (pmConfig *config, psArray *refs) {
-
-    bool status;
-    pmChip *chip = NULL;
-    pmCell *cell = NULL;
-    pmReadout *readout = NULL;
-
-    // select the current recipe
-    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, "PSASTRO");
-    if (!recipe) {
-	psError(PSASTRO_ERR_CONFIG, true, "Can't find PSASTRO recipe!\n");
-	return false;
-    }
-
-    // select the input data sources
-    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT");
-    if (!input) {
-	psError(PSASTRO_ERR_CONFIG, true, "Can't find input data!\n");
-	return false;
-    }
-
-    float fieldExtra = psMetadataLookupS32 (&status, recipe, "PSASTRO.FIELD.EXTRA"); 
-    if (!status) fieldExtra = 0.0;
-
-    pmFPAview *view = pmFPAviewAlloc (0);
-    pmFPA *fpa = input->fpa;
-
-    // this loop selects the matched stars for all chips
-    while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) {
-        psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
-        if (!chip->process || !chip->file_exists) { continue; }
-	
-	while ((cell = pmFPAviewNextCell (view, fpa, 1)) != NULL) {
-            psTrace ("psastro", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
-            if (!cell->process || !cell->file_exists) { continue; }
-
-	    // process each of the readouts
-	    // XXX there can only be one readout per chip, right?
-	    while ((readout = pmFPAviewNextReadout (view, fpa, 1)) != NULL) {
-		if (! readout->data_exists) { continue; }
-
-		// read WCS data from the corresponding header
-		pmHDU *hdu = pmFPAviewThisHDU (view, fpa);
-
-		int Nx = psMetadataLookupS32 (&status, hdu->header, "NAXIS1"); 
-		int Ny = psMetadataLookupS32 (&status, hdu->header, "NAXIS2"); 
-
-		float minX = -fieldExtra*Nx;
-		float maxX = (1+fieldExtra)*Nx;
-		float minY = -fieldExtra*Ny;
-		float maxY = (1+fieldExtra)*Ny;
-
-		// the refstars is a subset within range of this chip
-		psArray *refstars = psArrayAlloc (100);
-
-		// select the reference objects within range of this readout
-		// project the reference objects to this chip
-		for (int i = 0; i < refs->n; i++) {
-		    pmAstromObj *ref = pmAstromObjCopy(refs->data[i]);
-	
-		    p_psProject (ref->TP, ref->sky, fpa->projection);
-		    psPlaneDistortApply (ref->FP, fpa->fromTangentPlane, ref->TP, 0.0, 0.0);
-		    psPlaneTransformApply (ref->chip, chip->fromFPA, ref->FP);
-
-		    // limit the X,Y range of the refs to the selected chip
-		    if (ref->chip->x < minX) goto skip;
-		    if (ref->chip->x > maxX) goto skip;
-		    if (ref->chip->y < minY) goto skip;
-		    if (ref->chip->y > maxY) goto skip;
-
-		    psArrayAdd (refstars, 100, ref);
-		skip:
-		    psFree (ref);
-		}
-		psTrace ("psastro", 4, "Added %ld refstars\n", refstars->n);
-		psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.REFSTARS", PS_DATA_ARRAY, "astrometry matches", refstars);
-
-		psFree (refstars);
-	    }
-	}
-    }
-
-    psFree (view);
-    return true;
-}
Index: /trunk/psastro/src/psastroRefstarSubset.c
===================================================================
--- /trunk/psastro/src/psastroRefstarSubset.c	(revision 9587)
+++ /trunk/psastro/src/psastroRefstarSubset.c	(revision 9587)
@@ -0,0 +1,42 @@
+# include "psastro.h"
+
+bool psastroRefstarSubset (pmReadout *readout) {
+
+  // select the raw objects for this readout
+  psArray *rawstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.RAWSTARS");
+  if (rawstars == NULL) { continue; }
+
+  // select the raw objects for this readout
+  psArray *refstars = psMetadataLookupPtr (NULL, readout->analysis, "PSASTRO.REFSTARS");
+  if (refstars == NULL) { continue; }
+
+  // calculate luminosity functions for rawstars and refstars
+  // the samples cover the same area (the chip), so no area correction
+  // is needed...
+  pmLumFunc *rawfunc = psastroLuminosityFunction (rawstars);
+  pmLumFunc *reffunc = psastroLuminosityFunction (refstars);
+
+  // what is the offset between the two lines at the average magnitude? 
+  mRef = 0.5*(reffunc->mMin + reffunc->mMax);
+  logRho = mRef * reffunc->slope + reffunc->offset;
+  mRaw = (logRho - rawfunc->offset) / rawfunc->slope;
+
+  psLogMsg ("psastro", 4, "mRef: %f, logRho: %f, mRaw: %f\n", mRef, logRho, mRaw);
+
+  mRefMax = rawfunc->mMax - mRaw + mRef;
+  psLogMsg ("psastro", 4, "clipping stars fainter than %f\n", mRefMax);
+
+  psArray *subset = psArrayAlloc (100);
+  for (int i = 0; i < refstars->n; i++) {
+    pmAstromObj *ref = refstars->data[i];
+    if (ref->Mag > mRefMax) continue;
+    psArrayAdd (subset, ref);
+  }
+
+  psLogMsg ("psastro", 4, "keeping %d of %d reference stars\n", subset->n, refstars->n);
+
+  psMetadataRemoveKey (readout->analysis, "PSASTRO.REFSTARS");
+  psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSASTRO.REFSTARS", PS_DATA_ARRAY, "astrometry matches", subset);
+
+  return true;
+}
