Index: /trunk/Ohana/src/addstar/Makefile
===================================================================
--- /trunk/Ohana/src/addstar/Makefile	(revision 10936)
+++ /trunk/Ohana/src/addstar/Makefile	(revision 10937)
@@ -41,5 +41,4 @@
 $(SRC)/fakeimage.$(ARCH).o \
 $(SRC)/find_matches.$(ARCH).o \
-$(SRC)/find_matches_closest.$(ARCH).o \
 $(SRC)/find_matches_refstars.$(ARCH).o \
 $(SRC)/find_subset.$(ARCH).o \
@@ -53,5 +52,4 @@
 $(SRC)/getusno.$(ARCH).o \
 $(SRC)/getusnob.$(ARCH).o \
-$(SRC)/gimages.$(ARCH).o \
 $(SRC)/greference.$(ARCH).o \
 $(SRC)/grefstars.$(ARCH).o \
@@ -63,8 +61,15 @@
 $(SRC)/replace_match.$(ARCH).o \
 $(SRC)/resort_catalog.$(ARCH).o \
-$(SRC)/rfits.$(ARCH).o \
-$(SRC)/rtext.$(ARCH).o \
-$(SRC)/sort_lists.$(ARCH).o \
+$(SRC)/ReadStarsFITS.$(ARCH).o \
+$(SRC)/ReadStarsTEXT.$(ARCH).o \
+$(SRC)/FilterStars.$(ARCH).o \
+$(SRC)/sort_lists.$(ARCH).o \
+$(SRC)/ImageOptions.$(ARCH).o \
+$(SRC)/GetFileMode.$(ARCH).o \
+$(SRC)/ReadImageHeader.$(ARCH).o \
 $(SRC)/update_coords.$(ARCH).o
+
+# $(SRC)/gimages.$(ARCH).o \
+# $(SRC)/find_matches_closest.$(ARCH).o \
 
 ADDSTARD = \
Index: /trunk/Ohana/src/addstar/doc/notes.txt
===================================================================
--- /trunk/Ohana/src/addstar/doc/notes.txt	(revision 10936)
+++ /trunk/Ohana/src/addstar/doc/notes.txt	(revision 10937)
@@ -1,2 +1,87 @@
+
+2007.01.04
+
+  Use of options.photcode:
+    - M_REFLIST: used to assign a photcode value to the loaded data
+    - M_REFCAT: used to select data from the reference of the given photcode
+    - M_FAKEIMAGE: used to assign a photcode value to the generated data
+    - M_RESORT: unused
+    - M_IMAGE: is used to override or supply the image header photcode
+	       * only valid for single chip runs
+
+  Re: MOSAIC_PHU
+      - the mosaic phu needs to have the time to enable the image/mosaic match
+
+      - NX,NY are used for plotting the mosaic outline.  the center of
+        the mosaic is 0,0, and the mosaic outline is drawn from
+        -NX/2,-NY/2 to NX/2,NY/2.  A problem: NX,NY in Image is using
+        a short int.  If the units of the FPA/TPA coords are microns, this overflows.
+	* change NX,NY to int?
+	* require the use of mm not microns?
+	* for GPC, NX,NY ~ 384000 um excluding gaps
+
+      - only the astrometry, time, and NX,NY are loaded for MOSAIC_PHU headers.
+
+2007.01.03
+
+  I am working on adding the ability to read MEF files containing
+  multiple tables and multiple image headers.  Here are the details:
+
+  SIMPLE CMP:
+    PHU:
+      NAXIS = 2 or
+      SIMPLE = FALSE or
+      TEXTMODE = TRUE (use option; global variable)
+
+  SIMPLE CMF:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 exists, > 0
+      NAXIS2 exists, > 0
+    EXT:
+      EXTNAME = SMPDATA, PS1DATA, etc (defines layout)
+
+  SIMPLE MEF:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 does not exist
+      NAXIS2 does not exist
+      &CTYPE[4] is not "-DIS"
+      EXTEND is true
+    EXT HEAD:
+      EXTTYPE = IMAGE
+      EXTNAME = image.name
+      EXTDATA = table.name
+    EXT DATA:
+      EXTTYPE = SMPDATA, PS1DATA, etc (defines layout)
+      EXTNAME = table.name
+      EXTHEAD = image.name
+
+  MOSAIC MEF:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 does not exist
+      NAXIS2 does not exist
+      &CTYPE[4] is "-DIS"
+      EXTEND is true
+    EXT HEAD:
+      EXTTYPE = IMAGE
+      EXTNAME = image.name
+      EXTDATA = table.name
+    EXT DATA:
+      EXTTYPE = SMPDATA, PS1DATA, etc (defines layout)
+      EXTNAME = table.name
+      EXTHEAD = image.name
+
+  MOSAIC PHU:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 does not exist
+      NAXIS2 does not exist
+      &CTYPE[4] is "-DIS"
+      NEXTEND = 0 or  
+      EXTEND is false
+
+    
 
 2006.04.02
Index: /trunk/Ohana/src/addstar/include/addstar.h
===================================================================
--- /trunk/Ohana/src/addstar/include/addstar.h	(revision 10936)
+++ /trunk/Ohana/src/addstar/include/addstar.h	(revision 10937)
@@ -11,5 +11,5 @@
 
 /* used in find_matches, find_matches_refstars */
-# define IN_CATALOG(R,D) ( \
+# define IN_REGION(R,D) ( \
 ((D) >= region[0].Dmin) && ((D) < region[0].Dmax) && \
 ((R) >= region[0].Rmin)  && ((R) < region[0].Rmax))
@@ -35,6 +35,8 @@
 
 enum {M_IMAGE, M_REFLIST, M_REFCAT, M_FAKEIMAGE, M_RESORT};
-
-/* global which define database info / data sources (KEEP) */
+enum {NONE, SIMPLE_CMP, SIMPLE_CMF, SIMPLE_MEF, MOSAIC_CMP, MOSAIC_CMF, MOSAIC_MEF, MOSAIC_PHU};
+/* note: MEF implies CMF */
+
+/* globals which define database info / data sources (KEEP) */
 char   ImageCat[256];
 char   GSCFILE[256];
@@ -108,4 +110,5 @@
 
 /*** addstar prototypes ***/
+
 void       AddToCalibration       PROTO((Average *average, Measure *measure, Measure *new, int *next, int Nstar));
 AddstarClientOptions ConfigInit   PROTO((int *argc, char **argv));
@@ -126,6 +129,6 @@
 int        edge_check             PROTO((double *x1, double *y1, double *x2, double *y2));
 Image     *fakeimage              PROTO((char *rootname, int *Nimage, int photcode));
-int        find_matches           PROTO((SkyRegion *region, Stars *stars, int Nstars, Catalog *catalog, Image *image, Image *overlap, int Noverlap, Coords *mosaic, AddstarClientOptions options));
-int        find_matches_closest   PROTO((SkyRegion *region, Stars *stars, int Nstars, Catalog *catalog, Image *image, Image *overlap, int Noverlap, Coords *mosaic, AddstarClientOptions options));
+int        find_matches           PROTO((SkyRegion *region, Stars *stars, int Nstars, Catalog *catalog, AddstarClientOptions options));
+int        find_matches_closest   PROTO((SkyRegion *region, Stars *stars, int Nstars, Catalog *catalog, AddstarClientOptions options));
 int        find_matches_refstars  PROTO((SkyRegion *region, Stars **stars, int Nstars, Catalog *catalog, AddstarClientOptions options));
 Stars    **find_subset            PROTO((SkyRegion *region, Stars *stars, int Nstars, int *NSTARS));
@@ -140,5 +143,5 @@
 Stars     *grefcat                PROTO((char *Refcat, SkyRegion *catstats, int photcode, int *nstars));
 Stars     *grefstars              PROTO((char *file, int photcode, int *Nstars));
-Stars     *gstars                 PROTO((char *file, int *NSTARS, int photcode, Image *image));
+Stars     *gstars                 PROTO((char *file, int *Nstars, Image **images, int *Nimages, int photcode));
 int        in_image               PROTO((double r, double d, Image *image));
 int        load_pt_catalog        PROTO((Catalog *catalog, SkyRegion *region));  /*** choose new name ***/
@@ -156,4 +159,9 @@
 Stars     *rfits                  PROTO((FILE *f, unsigned int *nstars));
 Stars     *rtext                  PROTO((FILE *f, unsigned int *nstars));
+Stars     *ReadStarsFITS          PROTO((FILE *f, Header *header, Header *in_theader, unsigned int *nstars));
+Stars     *ReadStarsTEXT          PROTO((FILE *f, unsigned int *nstars));
+int        ReadImageHeader        PROTO((Header *header, Image *image, int photcode));
+Stars     *FilterStars            PROTO((Stars *instars, Image *image));
+Stars     *MergeStars             PROTO((Stars *stars, int *Nstars, Stars *instars, int Ninstars));
 void       save_pt_catalog        PROTO((Catalog *catalog));  /*** choose new name ***/
 double     scat_subpix            PROTO((double x, double y));
@@ -169,16 +177,46 @@
 void       create_image_db        PROTO((FITS_DB *db));
 void       set_db                 PROTO((FITS_DB *in));
-
 void       uppercase              PROTO((char *string));
 void       fsort                  PROTO((float *X, int N));
 void       fsort2                 PROTO((float *X, float *Y, int N));
-
-int *init_measure_links (Average *average, int Naverage, Measure *measure, int Nmeasure);
-int *init_missing_links (Average *average, int Naverage, Missing *missing, int Nmissing);
-int add_meas_link (Average *average, int *next, int Nmeasure, int NMEASURE);
-int add_miss_link (Average *average, int *next, int Nmissing);
-int *build_measure_links (Average *average, int Naverage, Measure *measure, int Nmeasure);
-Measure *sort_measure (Average *average, int Naverage, Measure *measure, int Nmeasure, int *next);
-Missing *sort_missing (Average *average, int Naverage, Missing *missing, int Nmissing, int *next_miss);
+int 	  *init_measure_links     PROTO((Average *average, int Naverage, Measure *measure, int Nmeasure));
+int 	  *init_missing_links     PROTO((Average *average, int Naverage, Missing *missing, int Nmissing));
+int 	   add_meas_link     	  PROTO((Average *average, int *next, int Nmeasure, int NMEASURE));
+int 	   add_miss_link     	  PROTO((Average *average, int *next, int Nmissing));
+int 	  *build_measure_links    PROTO((Average *average, int Naverage, Measure *measure, int Nmeasure));
+Measure   *sort_measure     	  PROTO((Average *average, int Naverage, Measure *measure, int Nmeasure, int *next));
+Missing   *sort_missing     	  PROTO((Average *average, int Naverage, Missing *missing, int Nmissing, int *next_miss));
+Stars     *ConvertSMPDATA	  PROTO((FTable *table, int *nstars));
+// Stars *ConvertPS1DATA	  PROTO((FTable *table, int *nstars));
+int        ImageOptions		  PROTO((AddstarClientOptions *options, Image *images, int Nimages));
+int        GetFileMode		  PROTO((Header *header));
+AddstarClientOptions args_client  PROTO((int argc, char **argv, AddstarClientOptions options));
+AddstarClientOptions args_load2mass PROTO((int argc, char **argv, AddstarClientOptions options));
+AddstarClientOptions args_sedstar PROTO((int argc, char **argv, AddstarClientOptions options));
+void	   args_server		  PROTO((int argc, char **argv));
+int 	   CheckPassword	  PROTO((int BindSocket));
+int 	   NewImage		  PROTO((int BindSocket));
+int 	   NewReflist		  PROTO((int BindSocket));
+int 	   NewRefcat		  PROTO((int BindSocket));
+int 	   InitServerSocket	  PROTO((SockAddress *Address));
+int 	   WaitServerSocket	  PROTO((int InitSocket, SockAddress *Address, int *validIP, int Nvalid));
+int 	   GetClientSocket	  PROTO((char *hostname));
+int 	   UpdateDatabase_Image	  PROTO((AddstarClientOptions *options, Image *image, Coords *mosaic, Stars *stars, int Nstars));
+int 	   UpdateDatabase_Reflist PROTO((AddstarClientOptions *options, Stars *stars, int Nstars));
+int 	   UpdateDatabase_Refcat  PROTO((AddstarClientOptions *options, SkyRegion *UserPatch, char *refcat));
+SkyList   *SkyListForStars	  PROTO((SkyTable *table, int depth, Stars *stars, int Nstars));
+SkyList   *SkyListExistingSubset  PROTO((SkyList *input, char *path));
+int        SkyListSetPath	  PROTO((SkyList *list, char *path));
+SkyTable  *SkyTableLoadOptimal	  PROTO(());
+int 	   InitDataset		  PROTO(());
+int 	   PushDataset		  PROTO((DVO_DATA *data));
+DVO_DATA  *PopDataset		  PROTO((void));
+void	  *ListenClients_Thread	  PROTO((void *data));
+int 	   NewImage_Thread	  PROTO((int BindSocket));
+int 	   NewRefcat_Thread	  PROTO((int BindSocket));
+int 	   NewReflist_Thread	  PROTO((int BindSocket));
+
+// this is a gnu extension?? caution!
+void *memrchr(const void *s, int c, size_t n);
 
 /** 
@@ -191,38 +229,5 @@
 **/
 
+
 /** function for client / server **/ 
 
-AddstarClientOptions args_client (int argc, char **argv, AddstarClientOptions options);
-AddstarClientOptions args_load2mass (int argc, char **argv, AddstarClientOptions options);
-AddstarClientOptions args_sedstar (int argc, char **argv, AddstarClientOptions options);
-
-void args_server (int argc, char **argv);
-
-int CheckPassword (int BindSocket);
-int NewImage (int BindSocket);
-int NewReflist (int BindSocket);
-int NewRefcat (int BindSocket);
-
-int InitServerSocket (SockAddress *Address);
-int WaitServerSocket (int InitSocket, SockAddress *Address, int *validIP, int Nvalid);
-int GetClientSocket (char *hostname);
-
-int UpdateDatabase_Image (AddstarClientOptions *options, Image *image, Coords *mosaic, Stars *stars, int Nstars);
-int UpdateDatabase_Reflist (AddstarClientOptions *options, Stars *stars, int Nstars);
-int UpdateDatabase_Refcat (AddstarClientOptions *options, SkyRegion *UserPatch, char *refcat);
-
-SkyList *SkyListForStars (SkyTable *table, int depth, Stars *stars, int Nstars);
-SkyList *SkyListExistingSubset (SkyList *input, char *path);
-int SkyListSetPath (SkyList *list, char *path);
-SkyTable *SkyTableLoadOptimal ();
-
-int InitDataset ();
-int PushDataset (DVO_DATA *data);
-DVO_DATA *PopDataset (void);
-void *ListenClients_Thread (void *data);
-int NewImage_Thread (int BindSocket);
-int NewRefcat_Thread (int BindSocket);
-int NewReflist_Thread (int BindSocket);
-
-// this is a gnu extension?? caution!
-void *memrchr(const void *s, int c, size_t n);
Index: /trunk/Ohana/src/addstar/src/FilterStars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/FilterStars.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/FilterStars.c	(revision 10937)
@@ -4,8 +4,13 @@
 
   int j, N;
+  float MTIME, dMs;
+  Stars *stars;
+
+  /* correct instrumental mags for exposure time */
+  MTIME = (image[0].exptime > 0) ? 2.500*log10(image[0].exptime) : 0.0;
 
   /* modify resulting star list */
-  ALLOCATE (stars, Stars, image[0].nstars);
-  for (N = j = 0; j < image[0].nstars; j++) {
+  ALLOCATE (stars, Stars, image[0].nstar);
+  for (N = j = 0; j < image[0].nstar; j++) {
     /* allow for some dynamic filtering of star list */
     if (SNLIMIT && instars[j].dM > SNLIMIT) continue;
@@ -20,6 +25,18 @@
     while (stars[N].R >= 360.0) stars[N].R -= 360.0;
     stars[N].found = -1;
-    stars[N].code = photcode;
+    stars[N].code = image[0].source;
 
+    /** additional quantities to supply to Stars based on the image data **/
+
+    /* calculate accurate per-star airmass */
+    stars[N].airmass = airmass (image[0].secz_PS, stars[N].R, stars[N].D, image[0].sidtime, image[0].latitude);
+    stars[N].Mcal    = image[0].Mcal_PS;
+    stars[N].t       = image[0].tzero + 1e-4*stars[N].Y*image[0].trate;  /* trate is in 0.1 msec / row */
+
+    stars[N].M       = MIN (stars[N].M + MTIME, NO_MAG);
+    stars[N].dM      = MIN (stars[N].dM, NO_ERR);
+
+    stars[N].Mgal    = MIN (stars[N].Mgal + MTIME, NO_MAG);
+    
     if (SUBPIX) {
       dMs = get_subpix (stars[N].X, stars[N].Y);
@@ -40,5 +57,7 @@
 }
 
-Stars *MergeStars (Stars *instars, int Ninstars, Stars *stars, int *Nstars) {
+Stars *MergeStars (Stars *stars, int *Nstars, Stars *instars, int Ninstars) {
+
+  int i, j;
 
   if (stars == NULL) {
@@ -48,5 +67,5 @@
   }
 
-  for (j = 0, i = *Nstars; i < *Nstars + Ninstars; i++) {
+  for (j = 0, i = *Nstars; i < *Nstars + Ninstars; i++, j++) {
     stars[i] = instars[j];
   }
Index: /trunk/Ohana/src/addstar/src/GetFileMode.c
===================================================================
--- /trunk/Ohana/src/addstar/src/GetFileMode.c	(revision 10937)
+++ /trunk/Ohana/src/addstar/src/GetFileMode.c	(revision 10937)
@@ -0,0 +1,45 @@
+# include "addstar.h"
+
+// examine the PHU of this file and determine the file mode
+int GetFileMode (Header *header) {
+
+  char ctype[80];
+  int Naxis, Nx, Ny;
+  int simple, extend, haveNaxis, haveNx, haveNy, haveCTYPE;
+
+  gfits_scan (header, "SIMPLE", "%t", 1, &simple);
+  haveNaxis = gfits_scan (header, "NAXIS",  "%d", 1, &Naxis);
+  haveNx    = gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  haveNy    = gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  haveCTYPE = gfits_scan (header, "CTYPE1", "%s", 1, ctype);
+
+  gfits_scan (header, "EXTEND", "%t", 1, &extend);
+    
+  if ((Naxis == 2) || TEXTMODE || !simple) {
+    if (!strcmp (&ctype[4], "-WRP")) {
+      return MOSAIC_CMP;
+    }
+    return SIMPLE_CMP;
+  }
+
+  if (!extend && strcmp (&ctype[4], "-DIS")) {
+    if (!strcmp (&ctype[4], "-WRP")) {
+      return MOSAIC_CMF;
+    }
+    return SIMPLE_CMF;
+  }
+
+  if (!extend && !strcmp (&ctype[4], "-DIS")) {
+    return MOSAIC_PHU;
+  }
+
+  if (extend && strcmp (&ctype[4], "-DIS")) {
+    return SIMPLE_MEF;
+  }
+
+  if (extend && !strcmp (&ctype[4], "-DIS")) {
+    return MOSAIC_MEF;
+  }
+
+  return (NONE);
+}
Index: /trunk/Ohana/src/addstar/src/ImageOptions.c
===================================================================
--- /trunk/Ohana/src/addstar/src/ImageOptions.c	(revision 10937)
+++ /trunk/Ohana/src/addstar/src/ImageOptions.c	(revision 10937)
@@ -0,0 +1,39 @@
+# include "addstar.h"
+
+/* set specific options based on the image collection */
+int ImageOptions (AddstarClientOptions *options, Image *images, int Nimages) {
+
+  int i, equivPhotcode;
+  float maxError;
+  PhotCode *photcode;
+
+  // set the radius to the maximum error circle
+  if (options[0].radius == 0) {
+    maxError = 0;
+    for (i = 0; i < Nimages; i++) {
+      maxError = MAX (maxError, 0.02 * images[i].cerror);
+    }
+    options[0].radius = options[0].Nsigma * maxError;
+  }     
+
+  // check that all images have the same equiv photcode and save it
+  equivPhotcode = 0;
+
+  for (i = 0; i < Nimages; i++) {
+    /* MOSAIC_PHU images do not have a photcode */
+    if (!strcmp (&images[0].coords.ctype[4], "-DIS")) continue;
+
+    photcode = GetPhotcodebyCode (images[i].source);
+
+    if (equivPhotcode) {
+      if (equivPhotcode != photcode[0].equiv) {
+	fprintf (stderr, "ERROR: mismatch in equiv photcode values\n");
+	exit (2);
+      }
+    } else {
+      equivPhotcode = photcode[0].equiv;
+    }
+  }
+  options[0].photcode = equivPhotcode;
+  return (TRUE);
+}
Index: /trunk/Ohana/src/addstar/src/ReadImageHeader.c
===================================================================
--- /trunk/Ohana/src/addstar/src/ReadImageHeader.c	(revision 10937)
+++ /trunk/Ohana/src/addstar/src/ReadImageHeader.c	(revision 10937)
@@ -0,0 +1,144 @@
+# include "addstar.h"
+
+/* read an image header corresponding to a CMF / CMP data block */
+// XXX need to pass AddstarClientOptions?
+int ReadImageHeader (Header *header, Image *image, int photcode) {
+
+  int Nastro, ccdnum, hour, min, simple;
+  double tmp, sec, dMs;
+  char *name, *c, photname[64], line[80];
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, header)) {
+    fprintf (stderr, "ERROR: no astrometric solution in header\n");
+    exit (1);
+  }
+  gfits_scan (header, "NAXIS1",   "%hd", 1, &image[0].NX);
+  gfits_scan (header, "NAXIS2",   "%hd", 1, &image[0].NY);
+
+  if (!gfits_scan (header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    image[0].tzero = parse_time (header);
+  }
+
+  /* only load astrometry, NAXIS1,2, and time if this is a MOSAIC_PHU (ctype is ....-DIS) */
+  if (!strcmp (&image[0].coords.ctype[4], "-DIS")) {
+    MOSAIC = &image[0].coords;
+    return (TRUE);
+  }
+
+  /* require Nastro > 0 unless or ACCEPT_ASTROM */
+  Nastro = 0;
+  gfits_scan (header, "NASTRO", "%d", 1, &Nastro);
+  if ((Nastro == 0) && !ACCEPT_ASTROM) {
+    fprintf (stderr, "ERROR: bad astrometric solution in header\n");
+    exit (1);
+  }
+  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) {
+    if (MOSAIC == NULL) {
+      fprintf (stderr, "ERROR: no mosaic for WRP image (use -mosaic)\n");
+      exit (1);
+    }
+    RegisterMosaic (MOSAIC);
+  } else {
+    /* force image to lie in 0-360 range */
+    while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+    while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+  }
+    
+  /* CERROR in data file is in arcsec */
+  if (!gfits_scan (header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
+  image[0].cerror = tmp * 50.0;
+ 
+  /* get photcode from header */
+  if (photcode == 0) {
+    if (!gfits_scan (header, "PHOTCODE", "%s", 1, photname)) {
+      fprintf (stderr, "ERROR: photcode not supplied in header\n");
+      exit (1);
+    }
+    photcode = GetPhotcodeCodebyName (photname);
+    if (photcode == 0) {
+      fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", photname);
+      exit (1);
+    }
+  }
+  if (photcode == 0) { 
+    fprintf (stderr, "ERROR: no valid photcode is supplied\n");
+    exit (1);
+  }
+  image[0].source = photcode;
+
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+  gfits_scan (header, ExptimeKeyword,  "%lf", 1, &tmp);
+  image[0].exptime = tmp;
+  
+  /*** why are we no longer using APMIFIT?? ***/
+  tmp = 0;
+  /* gfits_scan (header, "APMIFIT",  "%lf", 1, &tmp); */
+  image[0].apmifit_PS = tmp;
+
+  tmp = 0;
+  /* gfits_scan (header, "dAPMIFIT", "%lf", 1, &tmp); */
+  image[0].dapmifit_PS = tmp;
+
+  tmp = 0;
+  gfits_scan (header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  gfits_scan (header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  tmp = 0;
+  gfits_scan (header, "FWHM_X",   "%lf", 1, &tmp);
+  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  tmp = 0;
+  gfits_scan (header, "FWHM_Y",   "%lf", 1, &tmp);
+  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  if (STKeyword[0]) {
+    /* get ST (used for airmass calculation) */
+    gfits_scan (header, STKeyword, "%s", 1, line);
+    /* remove ':' characters */
+    for (c = strchr (line, ':'); c != (char *) NULL; c = strchr (line, ':')) { *c = ' '; }
+    sscanf (line, "%d %d %lf", &hour, &min, &sec);
+    image[0].sidtime = hour + min/60.0 + sec/3600.0;
+  } else {
+    double jd;
+    jd = sec_to_jd (image[0].tzero);
+    image[0].sidtime  = ohana_lst (jd, Longitude);
+  }
+  image[0].latitude = Latitude;
+
+  tmp = 0;
+  gfits_scan (header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  gfits_scan (header, AirmassKeyword, "%lf", 1, &tmp);
+  image[0].secz_PS = MIN (NO_MAG, tmp);
+
+  if (!gfits_scan (header, CCDNumKeyword, "%d", 1, &ccdnum)) {
+    image[0].ccdnum = 0xff;
+  } else {
+    image[0].ccdnum = ccdnum;
+  }
+
+  gfits_scan (header, "ZERO_PT", "%lf", 1, &ZeroPt);
+  SetZeroPoint (ZeroPt);
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal_PS = 0.0;
+  image[0].Xm   = NO_MAG;
+  image[0].code = 0;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find expected number of stars */
+  if (!gfits_scan (header, "NSTARS", "%d", 1, &image[0].nstar)) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/addstar/src/ReadStarsFITS.c
===================================================================
--- /trunk/Ohana/src/addstar/src/ReadStarsFITS.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/ReadStarsFITS.c	(revision 10937)
@@ -5,5 +5,6 @@
 Stars *ReadStarsFITS (FILE *f, Header *header, Header *in_theader, unsigned int *nstars) {
 
-  int i, Nstars;
+  int i, Nskip, Nstars;
+  char type[80];
   Header theader;
   FTable table;
@@ -33,5 +34,5 @@
   }
 
-  if (!gfits_scan (header, "EXTTYPE", "%s", 1, type)) {
+  if (!gfits_scan (&theader, "EXTTYPE", "%s", 1, type)) {
     strcpy (type, "SMPDATA");
   }
@@ -41,7 +42,9 @@
     stars = ConvertSMPDATA (&table, &Nstars);
   }
+# if (0)
   if (!strcmp (type, "PS1DATA")) {
     stars = ConvertPS1DATA (&table, &Nstars);
   }
+# endif
   if (stars == NULL) {
     fprintf (stderr, "ERROR: invalid table type %s\n", type);
@@ -49,7 +52,7 @@
   }
   if (*nstars != Nstars) {
-    fprintf (stderr, "ERROR: inconsistent number of stars? %d vs %d\n", *nstars, Nstars);
-    exit (1);
+    fprintf (stderr, "WARNING: inconsistent number of stars? %d vs %d\n", *nstars, Nstars);
   }
+  *nstars = Nstars;
   return stars;
 }
@@ -57,9 +60,11 @@
 Stars *ConvertSMPDATA (FTable *table, int *nstars) {
 
-  int i, Nstars;
-  Stars *stars;
-  SMPData *smpdata;
+  int i, Nstars, swapped;
+  Stars *stars = NULL;
+  SMPData *smpdata = NULL;
 
-  smpdata = gfits_table_get_SMPData (table, &Nstars, NULL);
+  swapped = FALSE;
+  smpdata = gfits_table_get_SMPData (table, &Nstars, &swapped);
+  /* XXX we need to check at least the size of the loaded table */
 
   ALLOCATE (stars, Stars, Nstars);
@@ -68,5 +73,5 @@
     stars[i].Y      = smpdata[i].Y;
     stars[i].M      = smpdata[i].M;
-    stars[i].dM     = smpdata[i].dM;
+    stars[i].dM     = smpdata[i].dM*0.001;
     stars[i].dophot = smpdata[i].dophot;
 
@@ -81,4 +86,5 @@
 }
 
+# if (0)
 Stars *ConvertPS1DATA (FTable *table, int *nstars) {
 
@@ -106,2 +112,3 @@
   return (stars);
 }
+# endif
Index: /trunk/Ohana/src/addstar/src/Shutdown.c
===================================================================
--- /trunk/Ohana/src/addstar/src/Shutdown.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/Shutdown.c	(revision 10937)
@@ -1,9 +1,3 @@
 # include "addstar.h"
-
-static FITS_DB *db;
-
-void set_db (FITS_DB *in) {
-  db = in;
-}
 
 /* clean up open / locked ImageCat before shutting down */
@@ -21,6 +15,4 @@
   va_end (argp);
 
-  SetProtect (TRUE);
-  if (db != NULL) gfits_db_close (db);
   fprintf (stderr, "ERROR: addstar halted\n");
   exit (1);
Index: /trunk/Ohana/src/addstar/src/addstar.c
===================================================================
--- /trunk/Ohana/src/addstar/src/addstar.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/addstar.c	(revision 10937)
@@ -4,8 +4,8 @@
 
   int Nmatch, status;
-  int i, Nstars, Nimages, Noverlap, Nsubset;
+  int i, Nstars, Nimages, Nsubset;
   unsigned long long Naverage, Nmeasure;
   Stars *stars, **subset;
-  Image *images, *overlap;
+  Image *images;
   Catalog catalog;
   FITS_DB db;
@@ -29,23 +29,17 @@
   
   stars = NULL;
-  overlap = NULL;
-  set_db (&db);
 
-  /* we use the image table to lock db access -- perhaps this is not necessary? */
-  db.mode   = dvo_catalog_catmode (CATMODE);
-  db.format = dvo_catalog_catformat (CATFORMAT);
-  status    = dvo_image_lock (&db, ImageCat, 3600.0, LCK_XCLD);
-  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
-
+  /*** load in the new data (images, stars) ***/
   switch (options.mode) {
     case M_IMAGE:
-      stars = gstars (argv[1], &Nstars, options.photcode, &images, &Nimages);
+      stars = gstars (argv[1], &Nstars, &images, &Nimages, options.photcode);
       if ((DUMP != NULL) && !strcmp (DUMP, "rawstars")) dump_rawstars (stars, Nstars);
       RegisterMosaic (MOSAIC);
       for (i = 0; i < Nimages; i++) {
-	newlist = SkyListByImage (sky, -1, &image);
-	SkyListMergeLists (&skylist, &newlist);
+	newlist = SkyListByImage (sky, -1, &images[i]);
+	SkyListMerge (&skylist, newlist);
+	SkyListFree (newlist, FALSE);
       }
-      overlap = gimages (&db, &image, MOSAIC, &Noverlap);
+      ImageOptions (&options, images, Nimages);
       break;
     case M_REFLIST:
@@ -60,26 +54,14 @@
       images = fakeimage (argv[1], &Nimages, options.photcode);
       RegisterMosaic (MOSAIC);
+      ALLOCATE (skylist, SkyList, 1);
+      skylist[0].Nregions = 0;
+      break;
 
-      if (db.dbstate == LCK_EMPTY) {
-	dvo_image_create (&db, ZeroPt);
-      } else {
-	if (!dvo_image_load (&db, VERBOSE, FORCE_READ)) {
-	  Shutdown ("can't read image catalog %s", db.filename);
-	}
-      }	  
+    default:
+      fprintf (stderr, "ERROR: invalid mode\n");
+      exit (2);
+  }
 
-      dvo_image_addrows (&db, imageSet, Nimages);
-      SetProtect (TRUE);
-      dvo_image_update (&db, VERBOSE);
-      SetProtect (FALSE);
-
-      ohana_memcheck (FALSE);
-      dvo_image_unlock (&db); /* unlock? */
-
-      gettimeofday (&stop, NULL);
-      dtime = DTIME (stop, start);
-      fprintf (stderr, "SUCCESS: elapsed time %9.4f sec for fake image\n", dtime);
-      exit (0);
-  }
+  // in these cases, limit the sky catalogs to an existing subset
   if (options.only_match || options.existing_regions) {
     SkyList *tmp;
@@ -92,4 +74,5 @@
   /* XXX clean this up a bit : for only_image, I don't need to do this loop
      unless we are getting the calibration. */
+  /*** match stars to existing catalog data (or otherwise manipulate catalog data) ***/
   Nmatch = Naverage = Nmeasure = 0;
   for (i = 0; i < skylist[0].Nregions; i++) {
@@ -116,14 +99,11 @@
     }
 
-    Naverage += catalog.Naverage;
-    Nmeasure += catalog.Nmeasure;
-
     switch (options.mode) {
       case M_IMAGE:
 	Nsubset = Nstars;
 	if (options.closest) {
-	  Nmatch += find_matches_closest (skylist[0].regions[i], stars, Nstars, &catalog, &image, overlap, Noverlap, MOSAIC, options);
+	  // Nmatch += find_matches_closest (skylist[0].regions[i], stars, Nstars, &catalog, options);
 	} else {
-	  Nmatch += find_matches (skylist[0].regions[i], stars, Nstars, &catalog, &image, overlap, Noverlap, MOSAIC, options);
+	  Nmatch += find_matches (skylist[0].regions[i], stars, Nstars, &catalog, options);
 	}
 	break;
@@ -141,4 +121,7 @@
 	break;
     }
+    /* report total updated values */
+    Naverage += catalog.Naverage;
+    Nmeasure += catalog.Nmeasure;
 
     // write out catalog, if appropriate
@@ -154,22 +137,31 @@
   }
 
-  // XXX is it necessary to lock the image catalog during this entire process?
-  if (options.calibrate) { FindCalibration (&image); }
+  // We only measure a single value for the entire mosaic (add all images to this function)
+  if (options.calibrate) { FindCalibration (&images[0]); }
 
+  /*** update the image table ***/
+  /* setup image table format and lock */
+  db.mode   = dvo_catalog_catmode (CATMODE);
+  db.format = dvo_catalog_catformat (CATFORMAT);
+  status    = dvo_image_lock (&db, ImageCat, 3600.0, LCK_XCLD);  // shorter timeout?
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+
+  /* load or create the image table */
   if (db.dbstate == LCK_EMPTY) {
     if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
     dvo_image_create (&db, ZeroPt);
+  } else {
+    if (!dvo_image_load (&db, VERBOSE, FORCE_READ)) {
+      Shutdown ("can't read image catalog %s", db.filename);
+    }
   }
-  
-  ohana_memcheck (FALSE);
 
-  /* write out new image */
+  /* add the new images and save */
   if (options.mode == M_IMAGE) {
-    dvo_image_addrows (&db, &image, 1);
+    dvo_image_addrows (&db, images, Nimages);
     SetProtect (TRUE);
     dvo_image_update (&db, VERBOSE);
     SetProtect (FALSE);
   }
-  ohana_memcheck (FALSE);
   dvo_image_unlock (&db); /* unlock? */
 
@@ -177,4 +169,5 @@
   dtime = DTIME (stop, start);
   fprintf (stderr, "SUCCESS: elapsed time %9.4f sec for %5d stars (%5d matches), %6lld average, %7lld measure\n", dtime, Nstars, Nmatch, Naverage, Nmeasure);
+
   exit (0);
 }
@@ -185,2 +178,5 @@
    patch   - RA,DEC bounded portion of sky
 */
+
+// add in case of failures:
+// ohana_memcheck (FALSE);
Index: /trunk/Ohana/src/addstar/src/args.c
===================================================================
--- /trunk/Ohana/src/addstar/src/args.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/args.c	(revision 10937)
@@ -137,8 +137,10 @@
   }
   /* don't add missed pts to Missed table (image only) */
-  options.skip_missed = FALSE;
+  options.skip_missed = TRUE;
   if ((N = get_argument (argc, argv, "-missed"))) {
     options.skip_missed = TRUE;
     remove_argument (N, &argc, argv);
+    fprintf (stderr, "ERROR: addstar no longer supports -missed\n");
+    exit (2);
   }
   /* replace measurement, don't duplicate (ref/cat only) */
Index: /trunk/Ohana/src/addstar/src/find_matches.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/find_matches.c	(revision 10937)
@@ -1,12 +1,12 @@
 # include "addstar.h"
 
-int find_matches (SkyRegion *region, Stars *stars, int NstarsIn, Catalog *catalog, Image *image, Image *overlap, int Noverlap, Coords *mosaic, AddstarClientOptions options) {
+int find_matches (SkyRegion *region, Stars *stars, int NstarsIn, Catalog *catalog, AddstarClientOptions options) {
 
   int i, j, n, N, J, status, Nstars;
-  double X, Y, RADIUS, RADIUS2, secz;
+  double X, Y, RADIUS, RADIUS2;
   float *X1, *Y1, *X2, *Y2;
   float dX, dY, dR;
-  int *N1, *N2,  *next_meas, *next_miss;
-  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  int *N1, *N2,  *next_meas;
+  int Nave, NAVE, Nmeas, NMEAS, Nmatch;
   int Nsecfilt, Nsec;
   float Mcat, *Mval, MTIME;
@@ -14,26 +14,8 @@
   Coords tcoords;
 
-  /* changes needed to handle mosaic MEF images:
-     - options should not carry photcode: this is set per star in gstars 
-     - validate that all images have the same equiv code value (same Nsec)
-     - add dt to Stars.d and set in gstars, not here
-     - add airmass to Stars.d and set in gstars, not here
-     - set stars.t in gstars
-     - disallow mosaic and missed?  otherwise, need to loop over all images
-       for each missed source to see if it should have been found
-     - Mcal_PS is supplied by image, but is not correctly set: it is 
-       calculated *after* find_matches in addstar
-  */
-
-  /* XXX EAM : options.photcode overridden by image.source.... */
-  /* XXX this function could be modified to handle multiple photcodes as long
-     as they match the same equiv code value, resulting in the same value of Nsec */
-  code = GetPhotcodebyCode (image[0].source);
-
-  /* photcode data - must by of type DEP, (PRI, SEC) - probably should restrict to DEP */
-  // XXX : rely on catalog[0].Nsecfilt or GetPhotcodeNsecfilt??
+  /* photcode data - must by of type DEP; options.photcode is equiv PRI/SEC photcode */
+  /* this function requires incoming stars to have the same photcode.equiv value */
   Nsecfilt = GetPhotcodeNsecfilt ();
-  Nsec = (code[0].type == PHOT_DEP) ? GetPhotcodeNsec (code[0].equiv) : GetPhotcodeNsec (code[0].code);
-  /* this function requires incoming stars to have the same photcode */
+  Nsec     = GetPhotcodeNsec (options.photcode);
 
   /** allocate local arrays (stars) **/
@@ -53,28 +35,24 @@
   Nmatch = 0;
   NMEAS = Nmeas = catalog[0].Nmeasure;
-  NMISS = Nmiss = catalog[0].Nmissing;
   
   /* project onto rectilinear grid with 1 arcsec pixels. the choice of ZEA projection has the
-     advantage that every point in R,D has a mapping to a unique X,Y.  However, note that not all
-     possible X,Y points map back to R,D and the local plate scale changes substantially far from
-     the projection pole.  a better mapping might be ARC, not yet implemented (see
-     coordops.update.c).  We keep the original crpix1,2 and crref1,2.  For mosaic astrometry, the
-     grid should be w.r.t. the tangent-plane, not chip coords */
-
-  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) {
-    tcoords = mosaic[0];
-    tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
-    tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
-    tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
-    tcoords.Npolyterms = 1;
-    strcpy (tcoords.ctype, "RA---ZEA");
+   * advantage that every point in R,D has a mapping to a unique X,Y.  However, note that not all
+   * possible X,Y points map back to R,D and the local plate scale changes substantially far from
+   * the projection pole.  a better mapping might be ARC, not yet implemented (see
+   * coordops.update.c).  We use the center of the region (catalog) for crval1,2. 
+   */
+  tcoords.crval1 = 0.5*(region[0].Rmin + region[0].Rmax);
+  if (region[0].Rmax < 90) {
+    tcoords.crval2 = 0.5*(region[0].Dmin + region[0].Dmax);
   } else {
-    tcoords = image[0].coords;
-    tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
-    tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
-    tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
-    tcoords.Npolyterms = 1;
-    strcpy (tcoords.ctype, "RA---ZEA");
-  }
+    tcoords.crval2 = 90.0;
+  }
+  tcoords.crpix1 = 0;
+  tcoords.crpix2 = 0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  tcoords.Npolyterms = 1;
+  strcpy (tcoords.ctype, "RA---ZEA");
 
   /* build spatial index (RA sort) */
@@ -95,5 +73,5 @@
     free (Y2);
     free (N2);
-    return;
+    return (0);
   }
   if (Nstars > 1) sort_lists (X1, Y1, N1, Nstars);
@@ -107,5 +85,5 @@
   if (Nave > 1) sort_lists (X2, Y2, N2, Nave);
 
-  /* set up pointers for linked list of measure, missing */
+  /* set up pointers for linked list of measure */
   if (catalog[0].sorted) {
     next_meas = init_measure_links (catalog[0].average, Nave, catalog[0].measure, Nmeas);
@@ -113,17 +91,8 @@
     next_meas = build_measure_links (catalog[0].average, Nave, catalog[0].measure, Nmeas);
   }    
-  next_miss = init_missing_links (catalog[0].average, Nave, catalog[0].missing, Nmiss);
-  /* missing MUST be written 'sorted', or not at all */
-
-  /* choose a radius for matches */
-  if (options.radius == 0) {
-    RADIUS = options.Nsigma * 0.02 * image[0].cerror;  /* 0.02 corrects cerror to arcsec from storage units */
-  } else {
-    RADIUS = options.radius; /* provided by config */
-  }
+
+  /* choose a radius for matches (defined in args.c or ImageOptions.c) */
+  RADIUS = options.radius;
   RADIUS2 = RADIUS*RADIUS;
-
-  /* correct instrumental mags for exposure time */
-  MTIME = (image[0].exptime > 0) ? 2.500*log10(image[0].exptime) : 0.0;
 
   /** find matched stars **/
@@ -163,7 +132,4 @@
       add_meas_link (&catalog[0].average[n], next_meas, Nmeas, NMEAS);
 
-      /* calculate accurate per-star airmass */
-      secz = airmass (image[0].secz_PS, stars[N].R, stars[N].D, image[0].sidtime, image[0].latitude);
-      
       /** add measurements for this star **/
       /** dR,dD now represent arcsec **/
@@ -187,16 +153,16 @@
       }
       catalog[0].measure[Nmeas].dD_PS       = 3600.0*(catalog[0].average[n].D - stars[N].D);
-      catalog[0].measure[Nmeas].M_PS        = MIN (stars[N].M + MTIME, NO_MAG);
-      catalog[0].measure[Nmeas].dM_PS       = MIN (stars[N].dM, NO_ERR);  /* error in input files stored in thousandths of mag */
-      catalog[0].measure[Nmeas].Mcal_PS     = image[0].Mcal_PS;
-      catalog[0].measure[Nmeas].t           = image[0].tzero + 1e-4*stars[N].Y*image[0].trate;  /* trate is in 0.1 msec / row */
+      catalog[0].measure[Nmeas].M_PS        = stars[N].M;
+      catalog[0].measure[Nmeas].dM_PS       = stars[N].dM;  /* error in input files stored in thousandths of mag */
+      catalog[0].measure[Nmeas].Mcal_PS     = stars[N].Mcal;
+      catalog[0].measure[Nmeas].t           = stars[N].t;
       catalog[0].measure[Nmeas].averef      = n;              /* this must be an absolute sequence number, if partial average is loaded */
       catalog[0].measure[Nmeas].source      = stars[N].code;  /* photcode */
       catalog[0].measure[Nmeas].dophot      = stars[N].dophot;  
       catalog[0].measure[Nmeas].flags       = 0;
-      catalog[0].measure[Nmeas].dt_PS       = MTIME;
-      catalog[0].measure[Nmeas].airmass_PS  = secz;
-
-      catalog[0].measure[Nmeas].Mgal_PS     = MIN (stars[N].Mgal + MTIME, NO_MAG);
+      catalog[0].measure[Nmeas].dt_PS       = stars[N].dt;
+      catalog[0].measure[Nmeas].airmass_PS  = stars[N].airmass;
+
+      catalog[0].measure[Nmeas].Mgal_PS     = stars[N].Mgal;
       catalog[0].measure[Nmeas].FWx         = MIN (100*stars[N].fx, NO_MAG);
       catalog[0].measure[Nmeas].FWy         = MIN (100*stars[N].fy, NO_MAG);
@@ -247,28 +213,4 @@
   }
 
-  /* add reference for undetected catalog stars */
-  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) RegisterMosaic (mosaic);
-  for (j = 0; (j < Nave) && !options.skip_missed; j++) {
-    n = N2[j];
-    if (catalog[0].found[n] < 0) { 
-      /* make sure there is space for next entry */
-      if (Nmiss >= NMISS) {
-	NMISS = Nmiss + 1000;
-	REALLOCATE (next_miss, int, NMISS);
-	REALLOCATE (catalog[0].missing, Missing, NMISS);
-      }
-
-      /* should the catalog star be on this image? project into image coords */
-      if (!in_image (catalog[0].average[n].R, catalog[0].average[n].D, image)) continue;
-      add_miss_link (&catalog[0].average[n], next_miss, Nmiss);
-
-      /* calculate time of exposure for this coordinate in the image */
-      RD_to_XY (&X, &Y, catalog[0].average[n].R, catalog[0].average[n].D, &image[0].coords);	  
-      catalog[0].missing[Nmiss].t  = image[0].tzero + 1e-4*Y*image[0].trate;  /* trate is in 0.1 msec / row */
-      catalog[0].average[n].Nn ++;
-      Nmiss ++;
-    }
-  }
-
   /* incorporate unmatched image stars, if this star is in field of this catalog */
   /* these new entries are all written out in UPDATE mode */ 
@@ -288,7 +230,5 @@
     N = N1[i];
     if (stars[N].found >= 0) continue;
-    if (!IN_CATALOG (stars[N].R, stars[N].D)) continue;
-
-    secz = airmass (image[0].secz_PS, stars[N].R, stars[N].D, image[0].sidtime, image[0].latitude);
+    if (!IN_REGION (stars[N].R, stars[N].D)) continue;
 
     catalog[0].average[Nave].R         = stars[N].R;
@@ -322,14 +262,14 @@
     catalog[0].measure[Nmeas].dR_PS       = 0.0;
     catalog[0].measure[Nmeas].dD_PS       = 0.0;
-    catalog[0].measure[Nmeas].M_PS        = MIN (stars[N].M + MTIME, NO_MAG);
-    catalog[0].measure[Nmeas].dM_PS       = MIN (stars[N].dM, NO_ERR);
-    catalog[0].measure[Nmeas].Mcal_PS  	  = image[0].Mcal_PS;
-    catalog[0].measure[Nmeas].t        	  = image[0].tzero + 1e-4*stars[N].Y*image[0].trate; /* trate is in 0.1 msec / row */
+    catalog[0].measure[Nmeas].M_PS        = stars[N].M;
+    catalog[0].measure[Nmeas].dM_PS       = stars[N].dM;
+    catalog[0].measure[Nmeas].Mcal_PS  	  = stars[N].Mcal;
+    catalog[0].measure[Nmeas].t        	  = stars[N].t;
     catalog[0].measure[Nmeas].averef   	  = Nave;           /* XXX EAM : must be absolute Nave if partial read */
     catalog[0].measure[Nmeas].source   	  = stars[N].code;  /* photcode */
     catalog[0].measure[Nmeas].dophot   	  = stars[N].dophot;  
     catalog[0].measure[Nmeas].flags    	  = 0;
-    catalog[0].measure[Nmeas].dt_PS    	  = MTIME;
-    catalog[0].measure[Nmeas].airmass_PS  = secz;
+    catalog[0].measure[Nmeas].dt_PS    	  = stars[N].dt;
+    catalog[0].measure[Nmeas].airmass_PS  = stars[N].airmass;
 
     catalog[0].measure[Nmeas].Mgal_PS  	  = MIN (stars[N].Mgal + MTIME, NO_MAG);
@@ -341,23 +281,4 @@
     Mval = (Nsec == -1) ? &catalog[0].average[Nave].M : &catalog[0].secfilt[Nave*Nsecfilt+Nsec].M_PS;
     if (*Mval == NO_MAG) *Mval = Mcat;
-
-    /** now add references from all previous non-detection observations of this spot on the sky */
-    for (j = 0; (j < Noverlap) && !options.skip_missed; j++) {
-      /* make sure there is space for next entry */
-      if (Nmiss >= NMISS) {
-	NMISS = Nmiss + 1000;
-	REALLOCATE (next_miss, int, NMISS);
-	REALLOCATE (catalog[0].missing, Missing, NMISS);
-      }
-      if (!FindMosaicForImage (overlap, Noverlap, j)) continue;
-      if (!in_image (catalog[0].average[Nave].R, catalog[0].average[Nave].D, &overlap[j])) continue;
-      add_miss_link (&catalog[0].average[Nave], next_miss, Nmiss);
-
-      /* get time of exposure of this portion of the image */
-      RD_to_XY (&X, &Y, catalog[0].average[Nave].R, catalog[0].average[Nave].D, &overlap[j].coords);	  
-      catalog[0].missing[Nmiss].t  = overlap[j].tzero + 1e-4*Y*overlap[j].trate;  /* rough guess at time */
-      catalog[0].average[Nave].Nn ++;
-      Nmiss ++;
-    }
 
     /* next[Nmeas] should always be -1 in this context (it is always the only
@@ -371,5 +292,4 @@
   REALLOCATE (catalog[0].average, Average, Nave);
   REALLOCATE (catalog[0].measure, Measure, Nmeas);
-  REALLOCATE (catalog[0].missing, Missing, Nmiss);
  
   if (options.nosort) {
@@ -379,6 +299,4 @@
     catalog[0].measure = sort_measure (catalog[0].average, Nave, catalog[0].measure, Nmeas, next_meas);
   }
-  catalog[0].missing = sort_missing (catalog[0].average, Nave, catalog[0].missing, Nmiss, next_miss);
-  /* missing is REQUIRED to be sorted */
 
   /* note stars which have been found in this catalog */
@@ -394,6 +312,5 @@
   catalog[0].Naverage = Nave;
   catalog[0].Nmeasure = Nmeas;
-  catalog[0].Nmissing = Nmiss;
-  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas, Nmiss: %d %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmiss, Nmatch);
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas: %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmatch);
 
   free (catalog[0].found);
Index: /trunk/Ohana/src/addstar/src/find_missing.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_missing.c	(revision 10937)
+++ /trunk/Ohana/src/addstar/src/find_missing.c	(revision 10937)
@@ -0,0 +1,52 @@
+
+/* XXX I have dropped the -missed capability of addstar. This is an expensive operation which
+ * is only rarely needed.  It is more efficient to perform this operation as a crawler like
+ * relphot.  I am saving in this file the code which was used in find_matches to perform the
+ * missing matches.
+ */
+
+/** code to add references from all previous non-detection observations of this spot on the sky */
+for (j = 0; (j < Noverlap) && !options.skip_missed; j++) {
+  /* make sure there is space for next entry */
+  if (Nmiss >= NMISS) {
+    NMISS = Nmiss + 1000;
+    REALLOCATE (next_miss, int, NMISS);
+    REALLOCATE (catalog[0].missing, Missing, NMISS);
+  }
+  if (!FindMosaicForImage (overlap, Noverlap, j)) continue;
+  if (!in_image (catalog[0].average[Nave].R, catalog[0].average[Nave].D, &overlap[j])) continue;
+  add_miss_link (&catalog[0].average[Nave], next_miss, Nmiss);
+
+  /* get time of exposure of this portion of the image */
+  RD_to_XY (&X, &Y, catalog[0].average[Nave].R, catalog[0].average[Nave].D, &overlap[j].coords);	  
+  catalog[0].missing[Nmiss].t  = overlap[j].tzero + 1e-4*Y*overlap[j].trate;  /* rough guess at time */
+  catalog[0].average[Nave].Nn ++;
+  Nmiss ++;
+}
+
+/* add reference for undetected catalog stars */
+/* XXX allow this option only for single images? */
+if (!strcmp (&image[0].coords.ctype[4], "-WRP")) RegisterMosaic (mosaic);
+for (j = 0; (j < Nave) && !options.skip_missed; j++) {
+  n = N2[j];
+  if (catalog[0].found[n] < 0) { 
+    /* make sure there is space for next entry */
+    if (Nmiss >= NMISS) {
+      NMISS = Nmiss + 1000;
+      REALLOCATE (next_miss, int, NMISS);
+      REALLOCATE (catalog[0].missing, Missing, NMISS);
+    }
+
+    /* should the catalog star be on this image? project into image coords */
+    if (!in_image (catalog[0].average[n].R, catalog[0].average[n].D, image)) continue;
+    add_miss_link (&catalog[0].average[n], next_miss, Nmiss);
+
+    /* calculate time of exposure for this coordinate in the image */
+    RD_to_XY (&X, &Y, catalog[0].average[n].R, catalog[0].average[n].D, &image[0].coords);	  
+    catalog[0].missing[Nmiss].t  = image[0].tzero + 1e-4*Y*image[0].trate;  /* trate is in 0.1 msec / row */
+    catalog[0].average[n].Nn ++;
+    Nmiss ++;
+  }
+}
+  catalog[0].missing = sort_missing (catalog[0].average, Nave, catalog[0].missing, Nmiss, next_miss);
+
Index: /trunk/Ohana/src/addstar/src/gstars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/gstars.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/gstars.c	(revision 10937)
@@ -1,14 +1,14 @@
 # include "addstar.h"
 
-enum {NONE, SIMPLE_CMP, SIMPLE_CMF, SIMPLE_MEF, MOSAIC_CMP, MOSAIC_CMF, MOSAIC_MEF, MOSAIC_PHU};
-/* note: MEF implies CMF */
-
-Stars *gstars (char *filename, int *NSTARS, int photcode, Image **imageList, int Nimages) {
-
-  int i, Nfile, Nimage;
+// XXX where and when should I call RegisterMosaic??
+
+Stars *gstars (char *filename, int *Nstars, Image **images, int *Nimages, int photcode) {
+
+  int i, j, Nfile, Nheader, NHEADER, Nimage, NIMAGE;
+  int Nskip, Nhead, Ndata, done, status, mode, NinStars;
   char **file;
   FILE *f;
   glob_t globList;
-  char **exthead, **extdata;
+  char **exthead, **extdata, **exttype, tmpword[80];
   int *extnum_head, *extnum_data, *extsize;
   Header *header, **headers;
@@ -18,5 +18,5 @@
   // parse the filename as a glob
   globList.gl_offs = 0;
-  glob (file, 0, NULL, &globList);
+  glob (filename, 0, NULL, &globList);
 
   // if the glob does not match, save the literal word:
@@ -46,7 +46,7 @@
 
   stars = NULL;
-  Nstars = 0;
-
-  // valid for all but MEF files
+  *Nstars = 0;
+
+  /*** load data from a single PHU or a collection of PHU files ***/
   if ((mode != SIMPLE_MEF) && (mode != MOSAIC_MEF)) {
     Nimage = Nfile;
@@ -62,19 +62,19 @@
       }
 
-      ReadImageHeader (header, &image[i]);
+      ReadImageHeader (header, &image[i], photcode);
     
       switch (mode) {
 	case SIMPLE_CMP:
 	case MOSAIC_CMP:
-	  inStars = ReadStarsTEXT (f, header, NULL, &image[i].nstars);
+	  inStars = ReadStarsTEXT (f, &image[i].nstar);
 	  inStars = FilterStars (inStars, &image[i]);
-	  stars = MergeStars (inStars, NinStars, stars, &Nstars);
+	  stars = MergeStars (stars, Nstars, inStars, image[i].nstar);
 	  break;
 
 	case SIMPLE_CMF:
 	case MOSAIC_CMF:
-	  inStars = ReadStarsFITS (f, header, NULL, &image[i].nstars);
+	  inStars = ReadStarsFITS (f, header, NULL, &image[i].nstar);
 	  inStars = FilterStars (inStars, &image[i]);
-	  stars = MergeStars (inStars, NinStars, stars, &Nstars);
+	  stars = MergeStars (stars, Nstars, inStars, image[i].nstar);
 	  break;
 
@@ -87,46 +87,58 @@
       gfits_free_header (header);
     }
-  } else {
-    
-    /* we need to examine the extensions to determine the headers and the data */
-    NHEADER = 10;
-    ALLOCATE (headers, Header *, NHEADER);
-
-    // the first header is already loaded
-    headers[0] = header;
-    Nskip = gfits_matrix_size (header);
-    fseek (f, Nskip, SEEK_CUR); 
-
-    // load all headers into memory
-    done = FALSE;
-    for (i = 1; !done; i++) {
+    *Nimages = Nimage;
+    *images = image;
+    
+    return stars;
+  }
+    
+  /* we have a multi-chip image */
+
+  /* supplied photcode is incompatible with multi-chip images */
+  if (photcode) {
+    fprintf (stderr, "ERROR: photcode cannot be supplied to multi-chip images -- manually adjust the headers\n");
+    exit (1);
+  }
+
+  /* we need to examine the extensions to determine the headers and the data */
+  NHEADER = 10;
+  ALLOCATE (headers, Header *, NHEADER);
+
+  // the first header is already loaded
+  headers[0] = header;
+  Nskip = gfits_matrix_size (header);
+  fseek (f, Nskip, SEEK_CUR); 
+
+  // load all headers into memory
+  done = FALSE;
+  for (i = 1; !done; i++) {
       ALLOCATE (header, Header, 1);
       
       status = gfits_fread_header (f, header);
       if (!status) { 
-	done = TRUE;
+	  done = TRUE;
       } else {
-	headers[i] = header;
-	Nskip = gfits_matrix_size (header);
-	fseek (f, Nskip, SEEK_CUR); 
+	  headers[i] = header;
+	  Nskip = gfits_matrix_size (header);
+	  fseek (f, Nskip, SEEK_CUR); 
       }
       if (i == NHEADER - 1) {
-	NHEADER += 10;
-	REALLOCATE (headers, Header *, NHEADER);
-      }
-    }
-    Nheader = i;
-    
-    // space to store the images, indexes to the matching headers
-    Nimage = 0;
-    NIMAGE = Nheader;
-    ALLOCATE (image, Image, NIMAGE);
-    ALLOCATE (exthead, char **, NIMAGE);
-    ALLOCATE (extdata, char **, NIMAGE);
-    ALLOCATE (extnum_head, int, NIMAGE);
-    ALLOCATE (extnum_data, int, NIMAGE);
-    ALLOCATE (extsize, int, Nheader);
-
-    if (mode == MOSAIC_MEF) {
+	  NHEADER += 10;
+	  REALLOCATE (headers, Header *, NHEADER);
+      }
+  }
+  Nheader = i - 1; /* we failed on the last loop */
+    
+  // space to store the images, indexes to the matching headers
+  Nimage = 0;
+  NIMAGE = Nheader;
+  ALLOCATE (image, Image, NIMAGE);
+  ALLOCATE (exthead, char *, NIMAGE);
+  ALLOCATE (extdata, char *, NIMAGE);
+  ALLOCATE (extnum_head, int, NIMAGE);
+  ALLOCATE (extnum_data, int, NIMAGE);
+  ALLOCATE (extsize, int, Nheader);
+
+  if (mode == MOSAIC_MEF) {
       exthead[Nimage] = strcreate ("PHU");
       extdata[Nimage] = strcreate ("NONE");
@@ -134,39 +146,43 @@
       extnum_head[Nimage] = 0;
       Nimage ++;
-    }
-
-    // now examine the headers, count the table entries, find corresponding headers
-    for (i = 0; i < Nheader; i++) {
+  }
+
+  // now examine the headers, count the table entries, find corresponding headers
+  for (i = 0; i < Nheader; i++) {
       extsize[i] = headers[i][0].size + gfits_matrix_size (headers[i]);
       gfits_scan (headers[i], "EXTTYPE", "%s", 1, tmpword);
       if (!strcmp (tmpword, "SMPDATA") ||  
 	  !strcmp (tmpword, "PS1DATA")) {
-	exttype[Nimage] = strcreate (tmpword);
-	gfits_scan (headers[i], "EXTNAME", "%s", 1, tmpword);
-	extdata[Nimage] = strcreate (tmpword);
-	gfits_scan (header[i], "EXTHEAD", "%s", 1, tmpword);
-	exthead[Nimage] = strcreate (tmpword);
-	extnum_data[Nimage] = i;
-	extnum_head[Nimage] = -1;
-	// find the matching exthead entry
-	for (j = 0; j < Nheader; j++) {
-	  gfits_scan (header[j], "EXTNAME", "%s", 1, tmpword);
-	  if (!strcmp (tmpword, exthead[Nimage])) {
-	    extnum_head[Nimage] = j;
+	  exttype[Nimage] = strcreate (tmpword);
+	  gfits_scan (headers[i], "EXTNAME", "%s", 1, tmpword);
+	  extdata[Nimage] = strcreate (tmpword);
+	  gfits_scan (headers[i], "EXTHEAD", "%s", 1, tmpword);
+	  exthead[Nimage] = strcreate (tmpword);
+	  extnum_data[Nimage] = i;
+	  extnum_head[Nimage] = -1;
+	  // find the matching exthead entry
+	  for (j = 0; j < Nheader; j++) {
+	    if (gfits_scan (headers[j], "EXTNAME", "%s", 1, tmpword)) {
+	      if (!strcmp (tmpword, exthead[Nimage])) {
+		extnum_head[Nimage] = j;
+	      }
+	    }
 	  }
-	}
-	// skip or crash on table with missing matching header?
-	if (extnum_head[Nimage] == -1) {
-	  fprintf (stderr, "ERROR: can't read header for %s\n", file[0]);
-	  exit (1);
-	}
-	Nimage ++;
-      }
-    }
-
-    // now run through the images, interpret the headers and read the stars
-    for (i = 0; i < Nimage; i++) {
+	  // skip or crash on table with missing matching header?
+	  if (extnum_head[Nimage] == -1) {
+	      fprintf (stderr, "ERROR: can't read header for %s\n", file[0]);
+	      exit (1);
+	  }
+	  Nimage ++;
+      }
+  }
+  if (VERBOSE) fprintf (stderr, "file %s has %d headers, including %d images\n", file[0], Nheader, Nimage);
+
+  // now run through the images, interpret the headers and read the stars
+  for (i = 0; i < Nimage; i++) {
       Nhead = extnum_head[i];
-      ReadImageHeader (header[Nhead], &image[i]);
+
+      if (VERBOSE) fprintf (stderr, "reading header for %s (%s)\n", exthead[i], extdata[i]);
+      ReadImageHeader (headers[Nhead], &image[i], 0);
 
       if (!strcmp(exthead[i], "PHU")) continue;
@@ -176,10 +192,15 @@
       Nskip = 0;
       for (j = 0; j < Ndata; j++) {
-	Nskip += extsize[j];
+	  Nskip += extsize[j];
       }
       fseek (f, Nskip, SEEK_SET); 
 	 
-      inStars = ReadStarsFITS (f, header[Nhead], header[Ndata], &NinStars);
-      inStars = FilterStars (inStars, &NinStars, &image[i]);
-      stars = MergeStars (inStars, NinStars, stars, &Nstars);
-    }
+      inStars = ReadStarsFITS (f, headers[Nhead], headers[Ndata], &image[i].nstar);
+      inStars = FilterStars (inStars, &image[i]);
+      stars = MergeStars (stars, Nstars, inStars, image[i].nstar);
+  }
+  *Nimages = Nimage;
+  *images = image;
+
+  return stars;
+}
Index: /trunk/Ohana/src/addstar/src/parse_time.c
===================================================================
--- /trunk/Ohana/src/addstar/src/parse_time.c	(revision 10936)
+++ /trunk/Ohana/src/addstar/src/parse_time.c	(revision 10937)
@@ -14,5 +14,8 @@
   if (strcasecmp (JDKeyword, "NONE")) {
     uppercase (JDKeyword);
-    gfits_scan (header, JDKeyword, "%lf", 1, &jd);
+    if (!gfits_scan (header, JDKeyword, "%lf", 1, &jd)) {
+      fprintf (stderr, "ERROR: missing JD Keyword %s\n", JDKeyword);
+      exit (1);
+    }
     Nsec = (jd - 2440587.5)*86400;
     return (Nsec);
@@ -22,5 +25,8 @@
   if (strcasecmp (MJDKeyword, "NONE")) {
     uppercase (MJDKeyword);
-    gfits_scan (header, MJDKeyword, "%lf", 1, &jd);
+    if (!gfits_scan (header, MJDKeyword, "%lf", 1, &jd)) {
+      fprintf (stderr, "ERROR: missing MJD Keyword %s\n", MJDKeyword);
+      exit (1);
+    }
     Nsec = (jd - 40587.0)*86400;
     return (Nsec);
@@ -42,5 +48,8 @@
   /* get UT and DATE */
   uppercase (UTKeyword);
-  gfits_scan (header, UTKeyword, "%s", 1, line);
+  if (!gfits_scan (header, UTKeyword, "%s", 1, line)) {
+      fprintf (stderr, "ERROR: missing UT Keyword %s\n", UTKeyword);
+      exit (1);
+    }
   /* remove ':' characters */
   for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
@@ -81,5 +90,8 @@
   /* parse date entry */
   uppercase (DateKeyword);
-  gfits_scan (header, DateKeyword, "%s",  1, line);
+  if (!gfits_scan (header, DateKeyword, "%s",  1, line)) {
+    fprintf (stderr, "ERROR: missing DATE Keyword %s\n", DateKeyword);
+    exit (1);
+  }
   /* remove possible separators: ':', '/' '.', '-' */
   for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
