Index: /trunk/Ohana/src/addstar/Makefile
===================================================================
--- /trunk/Ohana/src/addstar/Makefile	(revision 38466)
+++ /trunk/Ohana/src/addstar/Makefile	(revision 38467)
@@ -29,4 +29,5 @@
 loadICRF_client : $(BIN)/loadICRF_client.$(ARCH)
 loadwise     : $(BIN)/loadwise.$(ARCH)
+loadtycho    : $(BIN)/loadtycho.$(ARCH)
 dumpskycells : $(BIN)/dumpskycells.$(ARCH)
 findskycell  : $(BIN)/findskycell.$(ARCH)
@@ -35,7 +36,7 @@
 mkcmf        : $(BIN)/mkcmf.$(ARCH)
 
-all: addstar addstar_client sedstar load2mass loadstarpar loadstarpar_client loadICRF loadICRF_client skycells mkcmf loadwise loadsupercos dumpskycells findskycell
-
-INSTALL = addstar addstar_client sedstar load2mass loadstarpar loadstarpar_client loadICRF loadICRF_client skycells mkcmf loadwise loadsupercos dumpskycells findskycell
+all: addstar addstar_client sedstar load2mass loadstarpar loadstarpar_client loadICRF loadICRF_client skycells mkcmf loadwise loadtycho loadsupercos dumpskycells findskycell
+
+INSTALL = addstar addstar_client sedstar load2mass loadstarpar loadstarpar_client loadICRF loadICRF_client skycells mkcmf loadwise loadtycho loadsupercos dumpskycells findskycell
 
 # I need to fix the client/server version of addstar now that I have dropped Stars
@@ -49,5 +50,4 @@
 $(SRC)/SkyListForStars.$(ARCH).o \
 $(SRC)/SkyRegionUtils.$(ARCH).o \
-$(SRC)/SkyTableFromTychoIndex.$(ARCH).o \
 $(SRC)/addstar.$(ARCH).o \
 $(SRC)/addstar_create_ID.$(ARCH).o \
@@ -65,5 +65,4 @@
 $(SRC)/find_subset.$(ARCH).o \
 $(SRC)/getgsc.$(ARCH).o \
-$(SRC)/gettycho.$(ARCH).o \
 $(SRC)/getusno.$(ARCH).o \
 $(SRC)/getusnob.$(ARCH).o \
@@ -76,4 +75,5 @@
 $(SRC)/LoadData.$(ARCH).o \
 $(SRC)/LoadDataSDSS.$(ARCH).o \
+$(SRC)/LoadDataUKIRT.$(ARCH).o \
 $(SRC)/LoadDataPMM.$(ARCH).o \
 $(SRC)/in_image.$(ARCH).o \
@@ -90,4 +90,5 @@
 $(SRC)/ReadStarsTEXT.$(ARCH).o \
 $(SRC)/ReadStarsSDSS.$(ARCH).o \
+$(SRC)/ReadStarsUKIRT.$(ARCH).o \
 $(SRC)/ReadXradFITS.$(ARCH).o \
 $(SRC)/FilterStars.$(ARCH).o \
@@ -125,5 +126,4 @@
 $(SRC)/SkyListForStars.$(ARCH).o \
 $(SRC)/SkyRegionUtils.$(ARCH).o \
-$(SRC)/SkyTableFromTychoIndex.$(ARCH).o \
 $(SRC)/SocketOps.$(ARCH).o \
 $(SRC)/UpdateDatabase_Image.$(ARCH).o \
@@ -141,5 +141,4 @@
 $(SRC)/find_subset.$(ARCH).o \
 $(SRC)/getgsc.$(ARCH).o \
-$(SRC)/gettycho.$(ARCH).o \
 $(SRC)/getusno.$(ARCH).o \
 $(SRC)/getusnob.$(ARCH).o \
@@ -174,5 +173,4 @@
 $(SRC)/getusno.$(ARCH).o \
 $(SRC)/getusnob.$(ARCH).o \
-$(SRC)/gettycho.$(ARCH).o \
 $(SRC)/greference.$(ARCH).o \
 $(SRC)/in_image.$(ARCH).o \
@@ -186,5 +184,4 @@
 $(SRC)/edge_check.$(ARCH).o \
 $(SRC)/opening_angle.$(ARCH).o \
-$(SRC)/SkyTableFromTychoIndex.$(ARCH).o \
 $(SRC)/ListenClients_Thread.$(ARCH).o \
 $(SRC)/NewImage_Thread.$(ARCH).o \
@@ -204,4 +201,5 @@
 $(SRC)/LoadData.$(ARCH).o \
 $(SRC)/LoadDataSDSS.$(ARCH).o \
+$(SRC)/LoadDataUKIRT.$(ARCH).o \
 $(SRC)/LoadDataPMM.$(ARCH).o \
 $(SRC)/grefstars.$(ARCH).o \
@@ -213,4 +211,5 @@
 $(SRC)/ReadStarsTEXT.$(ARCH).o \
 $(SRC)/ReadStarsSDSS.$(ARCH).o \
+$(SRC)/ReadStarsUKIRT.$(ARCH).o \
 $(SRC)/ImageIndex.$(ARCH).o \
 $(SRC)/UpdateImageIDs.$(ARCH).o \
@@ -323,4 +322,19 @@
 $(SRC)/StarOps.$(ARCH).o \
 $(SRC)/find_matches_refstars.$(ARCH).o \
+$(SRC)/build_links.$(ARCH).o \
+$(SRC)/replace_match.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/update_coords.$(ARCH).o \
+$(SRC)/SkyRegionUtils.$(ARCH).o \
+$(SRC)/psps_ids.$(ARCH).o
+
+LOAD-TYCHO = \
+$(SRC)/loadtycho.$(ARCH).o \
+$(SRC)/loadtycho_rawdata.$(ARCH).o \
+$(SRC)/loadtycho_ops.$(ARCH).o \
+$(SRC)/args_loadtycho.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/find_matches_closest_refstars.$(ARCH).o \
 $(SRC)/build_links.$(ARCH).o \
 $(SRC)/replace_match.$(ARCH).o \
@@ -406,4 +420,5 @@
 $(BIN)/load2mass.$(ARCH)      : $(LOAD-2MASS)
 $(BIN)/loadwise.$(ARCH)       : $(LOAD-WISE)
+$(BIN)/loadtycho.$(ARCH)      : $(LOAD-TYCHO)
 $(BIN)/loadstarpar.$(ARCH)    : $(LOAD-STARPAR)
 $(BIN)/loadstarpar_client.$(ARCH) : $(LOAD-STARPAR-CLIENT)
Index: /trunk/Ohana/src/addstar/include/addstar.h
===================================================================
--- /trunk/Ohana/src/addstar/include/addstar.h	(revision 38466)
+++ /trunk/Ohana/src/addstar/include/addstar.h	(revision 38467)
@@ -77,5 +77,5 @@
 
 enum {ADDSTAR_MODE_NONE, ADDSTAR_MODE_IMAGE, ADDSTAR_MODE_REFLIST, ADDSTAR_MODE_REFCAT, ADDSTAR_MODE_FAKEIMAGE, ADDSTAR_MODE_RESORT, ADDSTAR_MODE_CREATE_ID};
-enum {NONE, SIMPLE_CMP, SIMPLE_CMF, SIMPLE_MEF, MOSAIC_CMP, MOSAIC_CMF, MOSAIC_MEF, MOSAIC_PHU, SDSS_OBJ};
+enum {NONE, SIMPLE_CMP, SIMPLE_CMF, SIMPLE_MEF, MOSAIC_CMP, MOSAIC_CMF, MOSAIC_MEF, MOSAIC_PHU, SDSS_OBJ, UKIRT_OBJ};
 /* note: MEF implies CMF */
 
@@ -221,5 +221,4 @@
 Stars     *greference             PROTO((char *Refcat, SkyRegion *catstats, int photcode, unsigned int *nstars));
 Stars     *getgsc                 PROTO((SkyRegion *patch, unsigned int *NSTARS));
-Stars     *gettycho               PROTO((SkyRegion *catstats, int photcode, unsigned int *Nstars));
 Stars     *getusno                PROTO((SkyRegion *catstats, int photcode, unsigned int *Nstars));
 Stars     *getusnob               PROTO((SkyRegion *catstats, int photcode, unsigned int *Nstars));
@@ -332,4 +331,7 @@
 
 
+Stars *ReadStarsUKIRT (FILE *f, char *name, Header *header, Image *images, off_t *nimages, unsigned int *nstars);
+int LoadDataUKIRT (FILE *f, char *file, Image **images, off_t *nimages, Stars **stars, unsigned int *Nstars, Header **headers, off_t *extsize, HeaderSet *headerSets, off_t NheaderSets);
+
 /** 
     there is an inconsistency to be resolved: fixed structures (like Image)
Index: /trunk/Ohana/src/addstar/include/tycho.h
===================================================================
--- /trunk/Ohana/src/addstar/include/tycho.h	(revision 38467)
+++ /trunk/Ohana/src/addstar/include/tycho.h	(revision 38467)
@@ -0,0 +1,17 @@
+
+# define NGROUP 6
+
+typedef struct {
+  double R, D;
+  Average average;
+  Measure measure[NGROUP];
+  int flag;
+} Tycho_Stars;
+
+AddstarClientOptions args_loadtycho (int *argc, char **argv, AddstarClientOptions options);
+
+int loadtycho_rawdata (SkyList *skytable, char *filename, AddstarClientOptions options);
+
+int gettycho_setup ();
+int gettycho_sortStars (Tycho_Stars *tstars, int Ntstars);
+int gettycho_star (Tycho_Stars *star, char *line);
Index: /trunk/Ohana/src/addstar/src/FilterStars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/FilterStars.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/FilterStars.c	(revision 38467)
@@ -43,4 +43,6 @@
     XY_to_RD (&stars[N].average.R, &stars[N].average.D, stars[N].measure.Xccd, stars[N].measure.Yccd, &image[0].coords);
     stars[N].average.R = ohana_normalize_angle (stars[N].average.R);
+    stars[N].measure.R = stars[N].average.R;
+    stars[N].measure.D = stars[N].average.D;
 
     stars[N].measure.photcode = image[0].photcode;
Index: /trunk/Ohana/src/addstar/src/GetFileMode.c
===================================================================
--- /trunk/Ohana/src/addstar/src/GetFileMode.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/GetFileMode.c	(revision 38467)
@@ -24,4 +24,14 @@
     if (VERBOSE) fprintf (stderr, "found SDSS objects\n");
     return SDSS_OBJ;
+  }
+
+    
+  // UKIRT files have TELESCOP = UKIRT and INSTRUME = WFCAM:
+  char telescope[81], instrument[81];
+  int have_TELESCOPE  = gfits_scan (header, "TELESCOP", "%s", 1, telescope);
+  int have_INSTRUMENT = gfits_scan (header, "INSTRUME", "%s", 1, instrument);
+  if (have_TELESCOPE && have_INSTRUMENT && !strcmp(telescope, "UKIRT") && !strcmp(instrument, "WFCAM")) {
+    if (VERBOSE) fprintf (stderr, "found UKIRT data\n");
+    return UKIRT_OBJ;
   }
 
Index: /trunk/Ohana/src/addstar/src/LoadDataUKIRT.c
===================================================================
--- /trunk/Ohana/src/addstar/src/LoadDataUKIRT.c	(revision 38467)
+++ /trunk/Ohana/src/addstar/src/LoadDataUKIRT.c	(revision 38467)
@@ -0,0 +1,47 @@
+# include "addstar.h"
+
+// examine the header sets and set the Image entries for the the valid images
+// UKIRT data has the WCS/image metadata header intermixed with the bintable header
+int LoadDataUKIRT (FILE *f, char *file, Image **images, off_t *nimages, Stars **stars, unsigned int *Nstars, Header **headers, off_t *extsize, HeaderSet *headerSets, off_t NheaderSets) {
+
+  off_t Nskip, Nvalid, NVALID;
+  char *name;
+  int i, j, Nhead, Ndata;
+  unsigned int Ninstars;
+  Stars *inStars;
+
+  // create or update image table 
+  if (images[0] == NULL) {
+    Nvalid = 0;
+    NVALID = NheaderSets;
+    ALLOCATE (images[0], Image, NVALID);
+  } else {
+    Nvalid = *nimages;
+    NVALID = Nvalid + NheaderSets;
+    REALLOCATE (images[0], Image, NVALID);
+  }    
+
+  // find image rootname
+  name = filebasename (file);
+
+  // validate the number of headers sets == 4
+  for (i = 0; i < NheaderSets; i++) {
+    if (VERBOSE) fprintf (stderr, "reading header for %s (%s)\n", headerSets[i].exthead, headerSets[i].extdata);
+
+    // advance the pointer to the start of the corresponding table block
+    Nhead = headerSets[i].extnum_head;
+    Ndata = headerSets[i].extnum_data;
+    Nskip = 0;
+    for (j = 0; j < Ndata; j++) {
+      Nskip += extsize[j];
+    }
+    fseeko (f, Nskip, SEEK_SET); 
+
+    inStars = ReadStarsUKIRT (f, name, headers[Nhead], images[0], &Nvalid, &Ninstars);
+    *stars = MergeStars (*stars, Nstars, inStars, Ninstars);
+
+    *nimages = Nvalid;
+  }    
+  return (TRUE);
+}
+
Index: /trunk/Ohana/src/addstar/src/LoadHeaders.c
===================================================================
--- /trunk/Ohana/src/addstar/src/LoadHeaders.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/LoadHeaders.c	(revision 38467)
@@ -24,4 +24,5 @@
     if (i == 0) {
       *mode = GetFileMode (headers[0]);
+      // CMP mode has no binary table, just image header and text blocks
       if ((*mode == SIMPLE_CMP) || (*mode == MOSAIC_CMP)) {
 	*Nheaders = i;
Index: /trunk/Ohana/src/addstar/src/LoadStars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/LoadStars.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/LoadStars.c	(revision 38467)
@@ -100,4 +100,10 @@
     }
 
+    // if these are SDSS data, load with SDSS-specific wrapper
+    if (headerSets[0].exttype && !strcmp (headerSets[0].exttype, "UKIRT_OBJ")) {
+      LoadDataUKIRT (f, file[i], images, Nimages, &stars, Nstars, headers, extsize, headerSets, NheaderSets);
+      continue;
+    }
+
     LoadData (f, file[i], images, Nimages, &stars, Nstars, headers, extsize, headerSets, NheaderSets, options);
 
Index: /trunk/Ohana/src/addstar/src/MatchHeaders.c
===================================================================
--- /trunk/Ohana/src/addstar/src/MatchHeaders.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/MatchHeaders.c	(revision 38467)
@@ -18,4 +18,5 @@
   mode = GetFileMode (headers[0]);
 
+  // mosaic mef can be identified from the PHU
   if (mode == MOSAIC_MEF) {
     headerSets[Nimage].exthead     = strcreate ("PHU");
@@ -26,4 +27,5 @@
   }
 
+  // sdss obj can be identified from the PHU
   if (mode == SDSS_OBJ) {
     // XXX these should have two headers (phu + table)
@@ -38,4 +40,39 @@
     return headerSets;
   }
+
+  // check for ukirt mode
+  // check if headers[1] is UKIRT_OBJ (and all others)
+  if (Nheaders > 1) { 
+    int myMode = GetFileMode (headers[1]);
+    if (myMode != UKIRT_OBJ) goto other_modes;
+    for (i = 2; i < Nheaders; i++) {
+      myMode = GetFileMode (headers[i]);
+      if (myMode != UKIRT_OBJ) {
+	fprintf (stderr, "inconsistent headers for UKIRT\n");
+	exit (2);
+      }
+    }
+
+    // the 0th entry is an empty PHU
+    extsize[0][0] = headers[0][0].datasize + gfits_data_size (headers[0]);
+
+    for (i = 1; i < Nheaders; i++) {
+      extsize[0][i] = headers[i][0].datasize + gfits_data_size (headers[i]);
+
+      gfits_scan (headers[i], ExtnameKeyword, "%s", 1, extname);
+      headerSets[Nimage].exttype = strcreate ("UKIRT_OBJ");
+      headerSets[Nimage].extdata = strcreate (extname);
+      headerSets[Nimage].exthead = strcreate (extname);
+      headerSets[Nimage].extxrad = NULL;
+      headerSets[Nimage].extnum_data = i;
+      headerSets[Nimage].extnum_head = i;
+      headerSets[Nimage].extnum_xrad = -1;
+      Nimage ++;
+    }
+    *nimage = Nimage;
+    return headerSets;
+  }
+
+other_modes:
 
   // now examine the headers, count the table entries, find corresponding headers
@@ -71,4 +108,5 @@
     if (!strcmp (exttype, "PS1_DV4")) goto keep;
     if (!strcmp (exttype, "PS1_DV5")) goto keep;
+
     continue;
 
Index: /trunk/Ohana/src/addstar/src/ReadStarsSDSS.c
===================================================================
--- /trunk/Ohana/src/addstar/src/ReadStarsSDSS.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/ReadStarsSDSS.c	(revision 38467)
@@ -155,4 +155,6 @@
       stars[N].average.dD        = NAN;
 
+      stars[N].measure.R         = stars[N].average.R;
+      stars[N].measure.D         = stars[N].average.D;
       stars[N].measure.Xccd      = colc[N];
       stars[N].measure.Yccd      = rowc[N];
Index: /trunk/Ohana/src/addstar/src/ReadStarsUKIRT.c
===================================================================
--- /trunk/Ohana/src/addstar/src/ReadStarsUKIRT.c	(revision 38467)
+++ /trunk/Ohana/src/addstar/src/ReadStarsUKIRT.c	(revision 38467)
@@ -0,0 +1,264 @@
+# include "addstar.h"
+
+# define GET_COLUMN(NAME,TYPE) \
+  TYPE *NAME; \
+  NAME = (TYPE *) gfits_get_bintable_column_data (table.header, &table, #NAME, type, &Nrow, &Ncol); \
+  assert (NAME); assert (!strcmp (type, #TYPE)); assert (Nrow == Nstars); assert (Ncol == 1);
+
+// given a file with the pointer at the start of the table block and the 
+// corresponding image header, load the stars from the table
+Stars *ReadStarsUKIRT (FILE *f, char *name, Header *header, Image *images, off_t *nimages, unsigned int *nstars) {
+
+  off_t Nrow;
+  int Ncol;
+  char type[80];
+  FTable table;
+  Stars *stars;
+  
+  // ohana_memcheck_func (TRUE);
+
+  // the FITS binary table header is the same as the image header
+  table.header = header;
+
+  // put the file pointer at the start of the fits table data
+  off_t Nskip = header[0].datasize;
+  fseeko (f, Nskip, SEEK_CUR); 
+
+  /* load the table data */
+  if (!gfits_fread_ftable_data (f, &table, FALSE)) {
+    fprintf (stderr, "ERROR: can't read table data\n");
+    exit (1);
+  }
+
+  // ohana_memcheck_func (TRUE);
+
+  Coords coords;
+  if (!GetCoords (&coords, header)) {
+    fprintf (stderr, "unable to read header WCS info\n");
+    exit (3);
+  }
+
+  // longitude and latitude for UKIRT:
+  // Latitude = 19.822433, Longitude = -155.470289 W (from google maps)
+  // longitude = 155.470289 deg = 10.3646859333 h
+
+  double Longitude = 10.3646859333;	// hours (+ = W)
+  double Latitude  = 19.822433;	// degrees
+
+  // DETECTID tells us which chip supplied the data
+  char detIDstr[80];
+  if (!gfits_scan (header, "DETECTID", "%s", 1, detIDstr)) {
+    fprintf (stderr, "missing DETECTID\n");
+    exit (3);
+  }
+  
+  int detID = 0;
+  if (!strcmp (detIDstr, "RSC:H2:60")) { detID = 1; }
+  if (!strcmp (detIDstr, "RSC:H2:63")) { detID = 2; }
+  if (!strcmp (detIDstr, "RSC:H2:76")) { detID = 3; }
+  if (!strcmp (detIDstr, "RSC:H2:41")) { detID = 4; }
+  if (!detID) {
+    fprintf (stderr, "unknown DETECTID %s\n", detIDstr);
+    exit (3);
+  }
+
+  char filter[80];
+  if (!gfits_scan (header, "FILTER", "%s", 1, filter)) {
+    fprintf (stderr, "missing FILTER\n");
+    exit (3);
+  }
+
+  int knownFilter = FALSE;
+  if (!strcmp (filter, "Z")) { knownFilter = TRUE; }
+  if (!strcmp (filter, "Y")) { knownFilter = TRUE; }
+  if (!strcmp (filter, "J")) { knownFilter = TRUE; }
+  if (!strcmp (filter, "H")) { knownFilter = TRUE; }
+  if (!strcmp (filter, "K")) { knownFilter = TRUE; }
+  if (!knownFilter) {
+    fprintf (stderr, "unknown FILTER %s\n", filter);
+    exit (3);
+  }
+  
+  char photcodeName[64];
+  snprintf (photcodeName, 64, "UKIRT.%s.%02d", filter, detID);
+  PhotCode *code = GetPhotcodebyName (photcodeName);
+  if (code == NULL) {
+    fprintf (stderr, "ERROR:  photcode %s not found in photcode table\n", photcodeName);
+    exit (3); 
+  }
+  int photcode = code[0].code;
+
+  float zeropt;
+  if (!gfits_scan (header, "MAGZPT", "%f", 1, &zeropt)) {
+    fprintf (stderr, "ERROR:  missing MAGZPT\n");
+    exit (3); 
+  }
+  // Mrel = Minst + K*(airmass - 1.0) + zp_nom - Mcal
+  // Mrel = Minst + K*(airmass - 1.0) + zp
+  // zp = zp_nom - Mcal
+  // Mcal = zp_nom - zp
+  float Mcal = code[0].C*0.001 - zeropt;
+
+  float ApCor4, ApCor7;
+  if (!gfits_scan (header, "APCOR4", "%f", 1, &ApCor4)) {
+    fprintf (stderr, "ERROR:  missing APCOR4\n");
+    exit (3); 
+  }
+  if (!gfits_scan (header, "APCOR7", "%f", 1, &ApCor7)) {
+    fprintf (stderr, "ERROR:  missing APCOR7\n");
+    exit (3); 
+  }
+
+  // ohana_memcheck_func (TRUE);
+
+  double mjd;
+  gfits_scan (header, "MJD-OBS", "%lf", 1, &mjd);
+  time_t tzero = ohana_mjd_to_sec (mjd);
+  double jd = ohana_sec_to_jd (tzero);
+
+  double sidtime  = ohana_lst (jd, Longitude); // sidtime in hours
+  double sidtime_deg = 15.0*sidtime; // sidtime in degrees
+
+  float seeing;
+  gfits_scan (header, "SEEING", "%f", 1, &seeing);
+
+  float exptime;
+  gfits_scan (header, "EXP_TIME", "%f", 1, &exptime);
+  float magtime = 2.5*log10(exptime);
+
+  float ZeroPt = GetZeroPoint();
+
+  // ohana_memcheck_func (TRUE);
+
+  // create a Star entry for each filter and detection
+  int Nstars = table.header[0].Naxis[1];
+  ALLOCATE (stars, Stars, Nstars);
+
+  GET_COLUMN (X_coordinate, float);
+  GET_COLUMN (Y_coordinate, float);
+
+  GET_COLUMN (X_coordinate_err, float);
+  GET_COLUMN (Y_coordinate_err, float);
+
+  GET_COLUMN (Aper_flux_4, float); // 1 arcsec aperture
+  GET_COLUMN (Aper_flux_4_err, float);
+
+  GET_COLUMN (Aper_flux_7, float); // 4 arcsec aperture
+  GET_COLUMN (Aper_flux_7_err, float);
+
+  GET_COLUMN (Kron_flux, float);
+  GET_COLUMN (Kron_flux_err, float);
+
+  GET_COLUMN (Sky_level, float);
+  GET_COLUMN (Sky_rms, float);
+
+  double R, D, alt, az;
+
+  // ohana_memcheck_func (TRUE);
+
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    InitStar (&stars[i]);
+      
+    // any values not explicitly set are left at 0.0
+    XY_to_RD (&R, &D, X_coordinate[i], Y_coordinate[i], &coords);
+
+    stars[i].average.R         = R;
+    stars[i].average.D         = D;
+    stars[i].average.dR        = NAN;
+    stars[i].average.dD        = NAN;
+
+    stars[i].measure.R         = stars[i].average.R;
+    stars[i].measure.D         = stars[i].average.D;
+    stars[i].measure.Xccd      = X_coordinate[i];
+    stars[i].measure.Yccd      = Y_coordinate[i];
+    stars[i].measure.dXccd     = ToShortPixels(X_coordinate_err[i]);
+    stars[i].measure.dYccd     = ToShortPixels(Y_coordinate_err[i]);
+
+    stars[i].measure.M         = -2.5*log10(Aper_flux_4[i]) + ZeroPt + magtime + ApCor4;
+    stars[i].measure.dM        = Aper_flux_4_err[i] / Aper_flux_4[i];
+    stars[i].measure.Map       = -2.5*log10(Aper_flux_7[i]) + ZeroPt + magtime + ApCor7;
+    stars[i].measure.dMap      = Aper_flux_7_err[i] / Aper_flux_7[i];
+    stars[i].measure.Mkron     = -2.5*log10(Kron_flux[i]) + ZeroPt + magtime;
+    stars[i].measure.dMkron    = Kron_flux_err[i] / Kron_flux[i];
+    stars[i].measure.Sky       = Sky_level[i]; // adjust this to counts?
+    stars[i].measure.dSky      = Sky_rms[i];
+    stars[i].measure.FWx       = ToShortPixels(seeing); // reported in arcsec?
+    stars[i].measure.FWy       = ToShortPixels(seeing);
+
+    stars[i].measure.Mcal      = Mcal;
+
+    stars[i].measure.detID     = i;
+    stars[i].measure.t         = tzero; // time since row 0
+    stars[i].measure.dt        = magtime; // 2.5 * log(exptime) 
+
+    altaz (&alt, &az, sidtime_deg - stars[i].average.R, stars[i].average.D, Latitude);
+
+    stars[i].measure.airmass   = 1.0 / dCOS(90.0 - alt);
+    stars[i].measure.az        = az;
+    stars[i].measure.photcode  = photcode;
+    stars[i].measure.imageID   = *nimages; // set imageID to entry for this filter
+  }
+
+  if (1) {
+    int N = *nimages;
+    
+    // ohana_memcheck_func (TRUE);
+
+    images[N].coords = coords;
+
+    int Nx, Ny;
+    gfits_scan (header, "NXOUT", "%d", 1, &Nx);
+    gfits_scan (header, "NYOUT", "%d", 1, &Ny);
+
+    images[N].NX = Nx;
+    images[N].NY = Ny;
+  
+    images[N].tzero = tzero;
+    images[N].cerror = 0.0;
+ 
+    // set photcodes for the 5 images (SDSS_U,G,R,I,Z)
+    images[N].photcode = photcode;
+
+    // calculate this from : C_OBS, TRACKING, and NY
+    images[N].exptime = exptime;
+  
+    images[N].apmifit = 0.0;
+    images[N].dapmifit = 0.0;
+    images[N].detection_limit = 0.0; 
+    images[N].saturation_limit = 0.0;
+    images[N].fwhm_x = seeing * 25.0 * images[N].coords.cdelt1 * 3600.0;
+    images[N].fwhm_y = seeing * 25.0 * images[N].coords.cdelt1 * 3600.0;
+
+    images[N].sidtime  = sidtime;
+    images[N].latitude = Latitude;
+
+    XY_to_RD (&R, &D, 0.5*images[N].NX, 0.5*images[N].NY, &coords);
+    altaz (&alt, &az, sidtime_deg - R, D, Latitude);
+
+    images[N].trate = 0.0;
+    images[N].secz = 1.0 / sin (RAD_DEG * alt);
+    images[N].ccdnum = detID;
+
+    // secz is in units milli-airmass
+    images[N].Mcal = Mcal;
+    images[N].Xm   = NAN_S_SHORT;
+    images[N].flags = 0;
+
+    images[N].nstar = Nstars;
+  
+    images[N].imageID = N;
+    images[N].externID = 0;
+    images[N].sourceID = 0;
+    images[N].parentID = UINT32_MAX; // UpdateImageIDs sets parentID = 0
+
+    // save the filename
+    snprintf (images[N].name, DVO_IMAGE_NAME_LEN, "%s[%02d]", name, detID);
+    *nimages = N + 1;
+  }
+  
+  // ohana_memcheck_func (TRUE);
+
+  *nstars = Nstars;
+  return (stars);
+}
Index: /trunk/Ohana/src/addstar/src/SEDfit.c
===================================================================
--- /trunk/Ohana/src/addstar/src/SEDfit.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/SEDfit.c	(revision 38467)
@@ -152,5 +152,5 @@
 
     for (j = 0; j < Nsec; j++) {
-      dvo_secfilt_init (&outcat[0].secfilt[Nave*Nsec+j]);
+      dvo_secfilt_init (&outcat[0].secfilt[Nave*Nsec+j], SECFILT_RESET_ALL);
     }
 
Index: /trunk/Ohana/src/addstar/src/UpdateImageIDs.c
===================================================================
--- /trunk/Ohana/src/addstar/src/UpdateImageIDs.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/UpdateImageIDs.c	(revision 38467)
@@ -20,5 +20,5 @@
     dvo_image_create (&db, GetZeroPoint());
     ImageIndexFileInit ();
-  isEmpty = TRUE;
+    isEmpty = TRUE;
   } else {
     /* position to start of file */
Index: /trunk/Ohana/src/addstar/src/args_loadtycho.c
===================================================================
--- /trunk/Ohana/src/addstar/src/args_loadtycho.c	(revision 38467)
+++ /trunk/Ohana/src/addstar/src/args_loadtycho.c	(revision 38467)
@@ -0,0 +1,94 @@
+# include "addstar.h"
+# include "tycho.h"
+static void help (void);
+
+AddstarClientOptions args_loadtycho (int *argc, char **argv, AddstarClientOptions options) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    help ();
+  }
+
+  // a global used by find_matches_closest_refstars.c (value is 1 except for loadwise & loadtycho)
+  NREFSTAR_GROUP = NGROUP;
+
+  /*** check for command line options ***/
+
+  /* we do not allow a subset to be extracted -- all or nothing, babe */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax= 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+
+  /* only add to existing regions */
+  options.existing_regions = FALSE;
+  if ((N = get_argument (*argc, argv, "-existing-regions"))) {
+    options.existing_regions = TRUE;
+    remove_argument (N, argc, argv);
+  }
+  /* only add to existing objects */
+  options.only_match = FALSE;
+  if ((N = get_argument (*argc, argv, "-only-match"))) {
+    options.only_match = TRUE;
+    remove_argument (N, argc, argv);
+  }
+  /* replace measurement, don't duplicate (ref/cat only) */
+  options.replace = FALSE;
+  if ((N = get_argument (*argc, argv, "-replace"))) {
+    options.replace = TRUE;
+    remove_argument (N, argc, argv);
+  }
+  /* accept proper-motion data from reference */
+  ACCEPT_MOTION = FALSE;
+  if ((N = get_argument (*argc, argv, "-accept-motion"))) {
+    ACCEPT_MOTION = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  /* other addstar options which cannot be used in loadtycho */
+  options.photcode = 0;
+  options.timeref = 0; 
+  options.mosaic = FALSE;
+  options.skip_missed = FALSE;
+  options.closest = FALSE;
+  options.nosort = FALSE;
+  options.update = FALSE;
+  options.only_images = FALSE;
+  options.calibrate = FALSE;
+  options.quality_airmass = FALSE;
+  ACCEPT_ASTROM = FALSE;
+  FORCE_READ = FALSE;
+  TEXTMODE = FALSE;
+  SUBPIX = FALSE;
+  DUMP = NULL;
+
+  if (*argc < 2) {
+    fprintf (stderr, "USAGE: loadtycho [options] (tychofile) [..more files]\n");
+    exit (2);
+  }
+  return (options);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE: loadtycho [options] (tychofile) [..more files]\n");
+  fprintf (stderr, "  add data from Tycho catalog to DVO\n\n");
+
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -only-match           	  : only add measurements to existing objects\n");
+  fprintf (stderr, "  -replace              	  : replace time/photcode measurements (no duplication)\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
Index: /trunk/Ohana/src/addstar/src/find_matches.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/find_matches.c	(revision 38467)
@@ -154,6 +154,4 @@
 
       // the following measure elements cannot be set until here:
-      catalog[0].measure[Nmeas].R        = stars[N].average.R;
-      catalog[0].measure[Nmeas].D        = stars[N].average.D;
       catalog[0].measure[Nmeas].dbFlags  = 0;
       catalog[0].measure[Nmeas].averef   = n; // this must be an absolute sequence number, if partial average is loaded 
@@ -266,5 +264,5 @@
 
     for (j = 0; j < Nsecfilt; j++) {
-      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j]);
+      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j], SECFILT_RESET_ALL);
     }
 
@@ -274,8 +272,6 @@
 
       // the following measure elements cannot be set until here:
-      catalog[0].measure[Nmeas].R       	= stars[i].average.R;
-      catalog[0].measure[Nmeas].D       	= stars[i].average.D;
-      catalog[0].measure[Nmeas].dbFlags 	= 0;
-      catalog[0].measure[Nmeas].averef   	= Nave; // XXX EAM : must be absolute Nave if partial read
+      catalog[0].measure[Nmeas].dbFlags   = 0;
+      catalog[0].measure[Nmeas].averef    = Nave; // XXX EAM : must be absolute Nave if partial read
       catalog[0].measure[Nmeas].objID     = catalog[0].average[Nave].objID;
       catalog[0].measure[Nmeas].catID     = catalog[0].catID;
Index: /trunk/Ohana/src/addstar/src/find_matches_closest.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_closest.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/find_matches_closest.c	(revision 38467)
@@ -189,7 +189,4 @@
 
     // measure now carries R,D (not dR,dD) 
-    // note that ReadStarsFITS does not set measure.R,D and average.R,D
-    catalog[0].measure[Nmeas].R        = stars[N].average.R;
-    catalog[0].measure[Nmeas].D        = stars[N].average.D;
     catalog[0].measure[Nmeas].dbFlags  = 0;
     catalog[0].measure[Nmeas].averef   = n;
@@ -300,5 +297,5 @@
 
     for (j = 0; j < Nsecfilt; j++) {
-      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j]);
+      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j], SECFILT_RESET_ALL);
     }
 
@@ -309,6 +306,4 @@
 
       // the following measure elements cannot be set until here:
-      catalog[0].measure[Nmeas].R        = stars[i].average.R;
-      catalog[0].measure[Nmeas].D        = stars[i].average.D;
       catalog[0].measure[Nmeas].dbFlags  = 0;
       catalog[0].measure[Nmeas].averef   = Nave;
Index: /trunk/Ohana/src/addstar/src/find_matches_closest_refstars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_closest_refstars.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/find_matches_closest_refstars.c	(revision 38467)
@@ -1,3 +1,12 @@
 # include "addstar.h"
+
+/* differences with find_matches_closest():
+ * accepts Stars **stars (vs Stars *stars)
+ * NREFSTAR_GROUP vs NSTAR_GROUP
+ * does not update lensing fields
+ * allows option to replace existing entries
+ * allows multiple photcodes
+
+ */
 
 int find_matches_closest_refstars (SkyRegion *region, Stars **stars, unsigned int NstarsIn, Catalog *catalog, AddstarClientOptions options) {
@@ -13,7 +22,13 @@
   int Nsecfilt;
 
-  if ((NREFSTAR_GROUP != 1) && (NREFSTAR_GROUP != 3)) {
-    fprintf (stderr, "ERROR: NREFSTAR_GROUP NOT SET!\n");
-    exit (1);
+  switch (NREFSTAR_GROUP) {
+    case 1:
+    case 3:
+    case 4:
+    case 6:
+      break;
+    default:
+      fprintf (stderr, "ERROR: NREFSTAR_GROUP NOT SET!\n");
+      exit (1);
   }
 
@@ -123,4 +138,10 @@
       j++;
       continue;
+    }
+
+    if (stars[N1[i]][0].found != -1) {
+        /* this star has already been assigned to an object in this or another catalog */
+        i++;
+        continue;
     }
 
@@ -173,7 +194,4 @@
     catalog[0].measure[Nmeas]          = stars[N][0].measure;
 
-    /** *** dR,dD now in arcsec *** **/
-    catalog[0].measure[Nmeas].R        = stars[N][0].average.R;
-    catalog[0].measure[Nmeas].D        = stars[N][0].average.D;
     catalog[0].measure[Nmeas].dbFlags  = 0;
     catalog[0].measure[Nmeas].averef   = n;
@@ -201,4 +219,6 @@
     // we can choose to accept the proper-motion and parallax from the reference catalog
     if (ACCEPT_MOTION) {
+      catalog[0].average[n].dR         = stars[N][0].average.dR;
+      catalog[0].average[n].dD         = stars[N][0].average.dD;
       catalog[0].average[n].uR         = stars[N][0].average.uR;
       catalog[0].average[n].uD         = stars[N][0].average.uD;
@@ -207,4 +227,5 @@
       catalog[0].average[n].P          = stars[N][0].average.P;
       catalog[0].average[n].dP         = stars[N][0].average.dP;
+      catalog[0].average[n].Tmean      = stars[N][0].average.Tmean;
     }
 
@@ -273,4 +294,5 @@
       catalog[0].average[Nave].P     	   = stars[N][0].average.P;
       catalog[0].average[Nave].dP    	   = stars[N][0].average.dP;
+      catalog[0].average[Nave].Tmean   	   = stars[N][0].average.Tmean;
     }
 
@@ -278,5 +300,5 @@
 
     for (j = 0; j < Nsecfilt; j++) {
-      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j]);
+      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j], SECFILT_RESET_ALL);
     }
 
@@ -285,7 +307,4 @@
 
       catalog[0].measure[Nmeas]          = stars[N][0].measure;
-
-      catalog[0].measure[Nmeas].R       = catalog[0].average[Nave].R;
-      catalog[0].measure[Nmeas].D       = catalog[0].average[Nave].D;
       catalog[0].measure[Nmeas].dbFlags  = 0;
       catalog[0].measure[Nmeas].averef   = Nave;
@@ -311,4 +330,5 @@
   // XXX allow for unsorted output?
   catalog[0].measure = sort_measure (catalog[0].average, Nave, catalog[0].measure, Nmeas, next_meas);
+  catalog[0].sorted = TRUE;
 
   /* note stars which have been found in this catalog */
Index: /trunk/Ohana/src/addstar/src/find_matches_refstars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_refstars.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/find_matches_refstars.c	(revision 38467)
@@ -138,6 +138,4 @@
 
       /** measure now stores R,D **/
-      catalog[0].measure[Nmeas].R        = stars[N][0].average.R;
-      catalog[0].measure[Nmeas].D        = stars[N][0].average.D;
       catalog[0].measure[Nmeas].dbFlags  = 0;
       catalog[0].measure[Nmeas].averef   = n;
@@ -252,5 +250,5 @@
 
     for (j = 0; j < Nsecfilt; j++) {
-      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j]);
+      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j], SECFILT_RESET_ALL);
     }
 
@@ -259,7 +257,4 @@
 
       catalog[0].measure[Nmeas]          = stars[N][0].measure;
-
-      catalog[0].measure[Nmeas].R        = stars[N][0].average.R;
-      catalog[0].measure[Nmeas].D        = stars[N][0].average.D;
 
       catalog[0].measure[Nmeas].t        = (stars[N][0].measure.t == 0) ? TIMEREF : stars[N][0].measure.t;      /** careful : time_t vs e_time **/
Index: /trunk/Ohana/src/addstar/src/find_matches_starpar.c
===================================================================
--- /trunk/Ohana/src/addstar/src/find_matches_starpar.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/find_matches_starpar.c	(revision 38467)
@@ -182,5 +182,5 @@
 
     for (j = 0; j < Nsecfilt; j++) {
-      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j]);
+      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsecfilt+j], SECFILT_RESET_ALL);
     }
 
Index: /trunk/Ohana/src/addstar/src/getgsc.c
===================================================================
--- /trunk/Ohana/src/addstar/src/getgsc.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/getgsc.c	(revision 38467)
@@ -79,4 +79,7 @@
       if (stars[Nstars].average.D > UserPatch.Dmax) continue;
 
+      stars[Nstars].measure.R = stars[Nstars].average.R;
+      stars[Nstars].measure.D = stars[Nstars].average.D;
+
       fparse (&stars[Nstars].measure.M, 3, &buffer[Nbyte]);
       stars[Nstars].measure.dM 	      = NAN;
Index: unk/Ohana/src/addstar/src/gettycho.c
===================================================================
--- /trunk/Ohana/src/addstar/src/gettycho.c	(revision 38466)
+++ 	(revision )
@@ -1,133 +1,0 @@
-# include "addstar.h"
-# define NZONE 180
-# define NBYTE 207
-# define NITEM 100
-
-static SkyTable *tychoTable = NULL;
-
-Stars *gettycho (SkyRegion *catstats, int photcode, unsigned int *nstars) {
-
-  int i, j, nitems;
-  char *buffer;
-  char filename[128], *line;
-  FILE *f;
-  int NTYCHO, Ntycho;
-  off_t firstRow, firstByte;
-  short int TYCHO_B, TYCHO_V;
-  e_time TychoEpoch;
-  SkyRegion *region;
-  SkyList  *skylist;
-  Stars *stars;
-
-  /* require photcode */
-  NAMED_PHOTCODE (TYCHO_B, "TYCHO_B");
-  NAMED_PHOTCODE (TYCHO_V, "TYCHO_V");
-  if (photcode == TYCHO_B) goto good_code;
-  if (photcode == TYCHO_V) goto good_code;
-  Shutdown ("TYCHO photcode not specified");
-good_code:
-
-  fprintf (stderr, "loading TYCHO catalog\n");
-
-  /* load tycho index file into sky table */
-  if (tychoTable == NULL) {
-    sprintf (filename, "%s/index.dat", TYCHO_DIR);
-    tychoTable = SkyTableFromTychoIndex (filename, VERBOSE);
-    if (tychoTable == NULL) {
-      fprintf (stderr, "ERROR: problem loading tycho data\n");
-      exit (2);
-    }
-  }
-
-  /* identify tycho region files overlapping the requested region */
-  skylist = SkyListByPatch (tychoTable, 2, catstats);
-
-  /* open the Tycho catalog file */
-  sprintf (filename, "%s/tycho.dat", TYCHO_DIR);
-  f = fopen (filename, "r");
-
-  Ntycho = 0;
-  NTYCHO = 5000;
-  ALLOCATE (stars, Stars, NTYCHO);
-
-  ALLOCATE (buffer, char, NITEM*NBYTE);
-
-  TychoEpoch = ohana_date_to_sec ("1991/04/02,07:30:00");
-
-  for (i = 0; i < skylist[0].Nregions; i++) {
-    region = skylist[0].regions[i];
-    if (VERBOSE) fprintf (stderr, "section %d (%f - %f, %f - %f)...", i, 
-			  region[0].Rmin, region[0].Rmax, region[0].Dmin, region[0].Dmax);
-
-    firstRow  = strtol (region[0].name, NULL, 0);
-    firstByte = firstRow * NBYTE;
-    fseeko (f, firstByte, SEEK_SET);
-
-    while (1) {
-      nitems = fread (buffer, NBYTE, NITEM, f);
-      if (nitems == 0) break;
-
-      for (j = 0; j < nitems; j++) {
-
-	line = &buffer[j*NBYTE];
-
-	InitStar (&stars[Ntycho]);
-
-	stars[Ntycho].average.R = atof (&line[15]);
-	stars[Ntycho].average.D = atof (&line[28]);
-
-	if (stars[Ntycho].average.R < region[0].Rmin) goto next_section;
-	if (stars[Ntycho].average.R > region[0].Rmax) goto next_section;
-	if (stars[Ntycho].average.D < region[0].Dmin) goto next_section;
-	if (stars[Ntycho].average.D > region[0].Dmax) goto next_section;
-
-	if (stars[Ntycho].average.R < UserPatch.Rmin) continue;
-	if (stars[Ntycho].average.R > UserPatch.Rmax) continue;
-	if (stars[Ntycho].average.D < UserPatch.Dmin) continue;
-	if (stars[Ntycho].average.D > UserPatch.Dmax) continue;
-
-	stars[Ntycho].average.dR  = 1000 * atof (&line[57]);
-	stars[Ntycho].average.dD  = 1000 * atof (&line[64]);
-
-	/* XXX : we need to apply uR,uD to R,D to advance to 2000.0 */
-	stars[Ntycho].average.uR  = atof (&line[41]);
-	stars[Ntycho].average.uD  = atof (&line[49]);
-
-	stars[Ntycho].average.duR = atof (&line[69]);
-	stars[Ntycho].average.duD = atof (&line[75]);
-
-	/* Tycho uses J2000 equinox and 1991.25 epoch for coordinates */
-	/* the magnitudes have no temporal information */ 
-	stars[Ntycho].measure.t   = TychoEpoch;
-
-	/* one pass of addstar does either r or b */
-	if (photcode == TYCHO_B) {
-	  stars[Ntycho].measure.M     	 = atof (&line[110]);
-	  stars[Ntycho].measure.dM    	 = atof (&line[117]);
-	  stars[Ntycho].measure.photcode = TYCHO_B;
-	} else {
-	  stars[Ntycho].measure.M     	 = atof (&line[123]);
-	  stars[Ntycho].measure.dM    	 = atof (&line[130]);
-	  stars[Ntycho].measure.photcode = TYCHO_V;
-	}	
-      
-	Ntycho ++;
-	CHECK_REALLOCATE (stars, Stars, NTYCHO, Ntycho, 5000);
-      }
-
-      if (nitems != NITEM) break;
-    }
-  next_section:
-    if (VERBOSE) fprintf (stderr, "%d stars\n", Ntycho);
-  }
-  fclose (f);
-
-  SkyListFree (skylist);
-
-  free (buffer);
-  REALLOCATE (stars, Stars, MAX (1, Ntycho));
-
-  *nstars = Ntycho;
-  if (VERBOSE) fprintf (stderr, "%d stars from Tycho\n", Ntycho);
-  return (stars);
-}
Index: /trunk/Ohana/src/addstar/src/getusno.c
===================================================================
--- /trunk/Ohana/src/addstar/src/getusno.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/getusno.c	(revision 38467)
@@ -114,4 +114,6 @@
       stars[Nusno].average.R     = buf[0]/360000.0;
       stars[Nusno].average.D     = buf[1]/360000.0 - 90.0;
+      stars[Nusno].measure.R     = stars[Nusno].average.R;
+      stars[Nusno].measure.D     = stars[Nusno].average.D;
       stars[Nusno].measure.dM    = NAN;
 
Index: /trunk/Ohana/src/addstar/src/getusnob.c
===================================================================
--- /trunk/Ohana/src/addstar/src/getusnob.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/getusnob.c	(revision 38467)
@@ -143,4 +143,7 @@
       stars[Nusno].average.dP  = 0;
 
+      stars[Nusno].measure.R   = stars[Nusno].average.R;
+      stars[Nusno].measure.D   = stars[Nusno].average.D;
+
       /* USNO magnitude errors are reported as a fixed 0.3 mag */
       stars[Nusno].measure.dM  = 0.3;
Index: /trunk/Ohana/src/addstar/src/greference.c
===================================================================
--- /trunk/Ohana/src/addstar/src/greference.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/greference.c	(revision 38467)
@@ -24,7 +24,16 @@
   }
 
-  /* get stars from the USNO B catalog for the given region */
+  /* get stars from the Tycho catalog for the given region */
   if (!strcasecmp (Refcat, "TYCHO")) {
-    stars = gettycho (region, photcode, &Nstars);
+    // stars = gettycho2 (region, photcode, &Nstars);
+    fprintf (stderr, "Tycho load via addstar is deprecated: use loadtycho\n");
+    exit (2);
+  }
+
+  /* get stars from the Tycho catalog for the given region (old ingest) */
+  if (!strcasecmp (Refcat, "TYCHO_OLD")) {
+    // stars = gettycho (region, photcode, &Nstars);
+    fprintf (stderr, "Tycho load via addstar is deprecated: use loadtycho\n");
+    exit (2);
   }
 
Index: /trunk/Ohana/src/addstar/src/grefstars.c
===================================================================
--- /trunk/Ohana/src/addstar/src/grefstars.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/grefstars.c	(revision 38467)
@@ -24,10 +24,17 @@
     InitStar (&stars[N]);
 
-    dparse (&stars[N].average.R,  1, line);
-    dparse (&stars[N].average.D,  2, line);
+    int status = sscanf (line, "%lf %lf %f %f %x", 
+		     &stars[N].average.R,  &stars[N].average.D,  
+		     &stars[N].measure.M, &stars[N].measure.dM, 
+		     &stars[N].measure.photFlags);
+    if ((status != 4) && (status != 5)) {
+      fprintf (stderr, "error reading line: %s\n", line);
+      N --;
+      continue;
+    }
     stars[N].average.R = ohana_normalize_angle (stars[N].average.R);
 
-    fparse (&stars[N].measure.M,  3, line);
-    fparse (&stars[N].measure.dM, 4, line);
+    stars[N].measure.R = stars[N].average.R;
+    stars[N].measure.D = stars[N].average.D;
 
     stars[N].measure.photcode = photcode;
Index: /trunk/Ohana/src/addstar/src/load2mass_catalog.c
===================================================================
--- /trunk/Ohana/src/addstar/src/load2mass_catalog.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/load2mass_catalog.c	(revision 38467)
@@ -29,5 +29,5 @@
 
     for (j = 0; j < Nsec; j++) {
-      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsec+j]);
+      dvo_secfilt_init (&catalog[0].secfilt[Nave*Nsec+j], SECFILT_RESET_ALL);
     }
 
Index: /trunk/Ohana/src/addstar/src/loadsupercos_rawdata.c
===================================================================
--- /trunk/Ohana/src/addstar/src/loadsupercos_rawdata.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/loadsupercos_rawdata.c	(revision 38467)
@@ -73,4 +73,7 @@
 	tstars[i].average.D = sstars[i].dec;
 
+	tstars[i].measure.R = sstars[i].ra;
+	tstars[i].measure.D = sstars[i].dec;
+
 	int Ni = imlist[sstars[i].plateID];
 	if (Ni == -1) abort();
Index: /trunk/Ohana/src/addstar/src/loadtycho.c
===================================================================
--- /trunk/Ohana/src/addstar/src/loadtycho.c	(revision 38467)
+++ /trunk/Ohana/src/addstar/src/loadtycho.c	(revision 38467)
@@ -0,0 +1,46 @@
+# include "addstar.h"
+# include "tycho.h"
+
+/* This is the DVO program to upload tycho detections into a DVO database.
+   It is modeled on the load2mass program, but unlike that case, it is expected to be run only
+   rarely (once?).  The tycho data are delivered as *.bz2 files.  This program assumes the files
+   have been decompressed.  It does not allow a subset of the sky to be uploaded; entire tycho
+   files are loaded if supplied on the command line.
+
+   USAGE: loadtycho -D CATDIR (catdir) (tychofile) [...more files]
+
+*/
+
+int main (int argc, char **argv) {
+
+  int i;
+  SkyTable *sky;
+  SkyList *skylist = NULL;
+  AddstarClientOptions options;
+
+  // need to construct these options with args_loadtycho...
+  options = ConfigInit (&argc, argv);
+  options = args_loadtycho (&argc, argv, options);
+
+  // load the full sky description table:
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  // generate the subset matching the user-selected region
+  skylist = SkyListByPatch (sky, -1, &UserPatch);
+
+  // if we only match to existing (already populated) regions, limit the select to those regions:
+  if (options.existing_regions) {
+    SkyList *tmp;
+    tmp = SkyListExistingSubset (skylist, CATDIR);
+    SkyListFree (skylist);
+    skylist = tmp;
+  }
+
+  for (i = 1; i < argc; i++) {
+    fprintf (stderr, "loading %s\n", argv[i]);
+    loadtycho_rawdata (skylist, argv[i], options);
+  }
+  exit (0);
+}  
+
Index: /trunk/Ohana/src/addstar/src/loadtycho_ops.c
===================================================================
--- /trunk/Ohana/src/addstar/src/loadtycho_ops.c	(revision 38467)
+++ /trunk/Ohana/src/addstar/src/loadtycho_ops.c	(revision 38467)
@@ -0,0 +1,133 @@
+# include "addstar.h"
+# include "tycho.h"
+
+static short TYCHO_B = 0;
+static short TYCHO_V = 0;
+static time_t J1990 = 0;
+static time_t J2000 = 0;
+static time_t J2012 = 0;
+
+int gettycho_setup () {
+
+  J1990 = ohana_date_to_sec ("1990/01/01,00:00:00");
+  J2000 = ohana_date_to_sec ("2000/01/01,00:00:00");
+  J2012 = ohana_date_to_sec ("2012/01/01,00:00:00");
+  NAMED_PHOTCODE (TYCHO_B, "TYCHO_B");
+  NAMED_PHOTCODE (TYCHO_V, "TYCHO_V");
+
+  return TRUE;
+}
+
+int gettycho_star (Tycho_Stars *star, char *line) {
+
+  int i;
+
+  star[0].flag = FALSE; // has this yet been matched in dvo?
+  dvo_average_init (&star[0].average);
+  for (i = 0; i < NGROUP; i++) {
+    dvo_measure_init (&star[0].measure[i]);
+  }
+
+  double jyR = atof (&line[178]); // EpRAm (tycho epoch for RA - 1990.0)
+  double jyD = atof (&line[183]); // EpRAm (tycho epoch for DEC - 1990.0)
+
+  time_t TychoEpoch = 0.5*(jyR + jyD) * 365.25 * 86400.0 + J1990;
+
+  // the observed (~1991) position is that at the TychoEpoch
+  double Robs = atof (&line[152]);
+  double Dobs = atof (&line[165]);
+  double Rref = atof (&line[15]); // RAmdeg (mean RA,  epoch J2000)
+  double Dref = atof (&line[28]); // DEmdeg (mean DEC, epoch J2000)
+
+  double Rps1, Dps1;
+
+  if (line[13] == 'X') {
+    star[0].average.R = Robs; // no valid pm, mean epoch position
+    star[0].average.D = Dobs; // 
+
+    star[0].average.dR  = atof (&line[188]) / 1000.0; // e_RAmdeg
+    star[0].average.dD  = atof (&line[194]) / 1000.0; // e_DEmdeg
+
+    star[0].average.uR  = NAN;
+    star[0].average.uD  = NAN;
+
+    star[0].average.duR = NAN;
+    star[0].average.duD = NAN;
+
+    star[0].average.Tmean = TychoEpoch;
+
+    Rref = Robs;
+    Rps1 = Robs;
+    Dref = Dobs;
+    Dps1 = Dobs;
+  } else {
+    star[0].average.dR  = atof (&line[57]) / 1000.0; // e_RAmdeg
+    star[0].average.dD  = atof (&line[61]) / 1000.0; // e_DEmdeg
+
+    star[0].average.uR  = atof (&line[41]) / 1000.0; // pmRA
+    star[0].average.uD  = atof (&line[49]) / 1000.0; // pmDE
+
+    star[0].average.duR = atof (&line[65]) / 1000.0; // e_pmRA
+    star[0].average.duD = atof (&line[70]) / 1000.0; // e_pmDE
+
+    Rps1 = Rref + ((2012.0 - 2000.0)/3600.0)*star[0].average.uR*cos(RAD_DEG*Dref);
+    Dps1 = Dref + ((2012.0 - 2000.0)/3600.0)*star[0].average.uD;
+
+    // use the mean (J2000) position for average or determine J2012?
+    star[0].average.R = Rps1;
+    star[0].average.D = Dps1;
+
+    star[0].average.Tmean = J2000;
+  }
+
+  float  M_B = atof (&line[110]); // BTmag
+  float dM_B = atof (&line[117]); // e_BTmag
+  float  M_V = atof (&line[123]); // VTmag
+  float dM_V = atof (&line[130]); // e_VTmag
+
+  // we have NGROUP measurements (B,V) x (MeanEpoch, J2000, J2012)
+  star[0].measure[0].t   = TychoEpoch;
+  star[0].measure[1].t   = TychoEpoch;
+  star[0].measure[2].t   = J2000;
+  star[0].measure[3].t   = J2000;
+  star[0].measure[4].t   = J2012;
+  star[0].measure[5].t   = J2012;
+
+  star[0].measure[0].R   = Robs;
+  star[0].measure[0].D   = Dobs;
+  star[0].measure[1].R   = Robs;
+  star[0].measure[1].D   = Dobs;
+
+  star[0].measure[2].R   = Rref;
+  star[0].measure[2].D   = Dref;
+  star[0].measure[3].R   = Rref;
+  star[0].measure[3].D   = Dref;
+
+  star[0].measure[4].R   = Rps1;
+  star[0].measure[4].D   = Dps1;
+  star[0].measure[5].R   = Rps1;
+  star[0].measure[5].D   = Dps1;
+
+  for (i = 0; i < NGROUP; i+=2) {
+    star[0].measure[i+0].M        =  M_B;
+    star[0].measure[i+0].dM       = dM_B;
+    star[0].measure[i+0].photcode = TYCHO_B;
+    star[0].measure[i+1].M        =  M_V;
+    star[0].measure[i+1].dM       = dM_V;
+    star[0].measure[i+1].photcode = TYCHO_V;
+  }
+  return TRUE;
+}
+
+int gettycho_sortStars (Tycho_Stars *stars, int Nstars) {
+
+# define SWAPFUNC(A,B){ Tycho_Stars temp = stars[A]; stars[A] = stars[B]; stars[B] = temp; }
+# define COMPARE(A,B)(stars[A].average.R < stars[B].average.R)
+
+  OHANA_SORT (Nstars, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+  
+  return TRUE;
+}
Index: /trunk/Ohana/src/addstar/src/loadtycho_rawdata.c
===================================================================
--- /trunk/Ohana/src/addstar/src/loadtycho_rawdata.c	(revision 38467)
+++ /trunk/Ohana/src/addstar/src/loadtycho_rawdata.c	(revision 38467)
@@ -0,0 +1,164 @@
+# include "addstar.h"
+# include "tycho.h"
+
+// the tycho data files do not have a fixed RA,DEC range but they have fixed width lines
+// files are small (~26M each) so load entire file at once.
+
+// sequence is:
+// * load all stars from the tycho file
+// * sort the stars by RA
+// * loop over stars
+//   * load catalogs 
+
+// lines are fixed length (207 bytes)
+# define DEBUG 1
+# define NBYTE 207
+# define NITEM 200000
+
+int loadtycho_rawdata (SkyList *skytable, char *filename, AddstarClientOptions options) {
+  
+  int i, j, k, Nitem;
+  char *buffer;
+
+  Tycho_Stars *tstars;
+  Stars *stars, **starrefs; // this is an array of pointers to be consistent with input to find_match_refstars
+  SkyList *skylist;
+  SkyRegion *region;
+  Catalog catalog;
+
+  gettycho_setup ();
+
+  ALLOCATE (buffer, char, NBYTE*NITEM);
+
+  // scan through the entire Tycho file
+  FILE *f = fopen (filename, "r");
+  if (f == NULL) Shutdown ("can't read Tycho data file: %s", filename);
+
+  // We are going to read the file in blocks of NBYTE*NITEM bytes.  (this may be set
+  // larger than a full file).  The entire block of stars will then be ingested
+
+  while ((Nitem = fread (buffer, NBYTE, NITEM, f)) != 0) {
+    if (Nitem == -1) Shutdown ("error reading from raw file %s", filename);
+    if (DEBUG) fprintf (stderr, " read %d items ", Nitem);
+
+    if (VERBOSE) fprintf (stderr, "read .. ");
+
+    // each row generates NGROUP measurements (B,V) x (MeanEpoch, J2000, J2012)
+    int Ntstars = Nitem;
+    ALLOCATE (tstars, Tycho_Stars, Ntstars);
+
+    double Rmin = 360.0;
+    double Rmax =   0.0;
+    double Dmin = +90.0;
+    double Dmax = -90.0;
+
+    // convert buffer into tstars, store ra,dec range
+    for (i = 0; i < Nitem; i++) {
+      gettycho_star (&tstars[i], &buffer[NBYTE*i]);
+      Rmin = MIN (Rmin, tstars[i].average.R);
+      Rmax = MAX (Rmax, tstars[i].average.R);
+      Dmin = MIN (Dmin, tstars[i].average.D);
+      Dmax = MAX (Dmax, tstars[i].average.D);
+    }
+
+    if (VERBOSE) fprintf (stderr, "scan %d stars (%10.6f - %10.6f, %10.6f - %10.6f) .. \n", Nitem, Rmin, Rmax, Dmin, Dmax);
+
+    // sort the array of stars
+    gettycho_sortStars (tstars, Ntstars);
+
+    // scan through the stars, find the next unused containing catalog
+    // skip through table for unsaved stars
+    for (i = 0; i < Ntstars; i++) {
+      if (tstars[i].flag) continue;
+
+      // scan forward until we reach the UserPatch
+      if (tstars[i].average.R < UserPatch.Rmin) continue;
+      if (tstars[i].average.R > UserPatch.Rmax) break;
+      if (tstars[i].average.D < UserPatch.Dmin) continue;
+      if (tstars[i].average.D > UserPatch.Dmax) continue;
+
+      // identify the relevant catalog
+      skylist = SkyRegionByPoint_List (skytable, -1, tstars[i].average.R, tstars[i].average.D);
+      if (skylist[0].Nregions == 0) {
+	  SkyListFree (skylist);
+	  continue;
+      }
+      region = skylist[0].regions[0];
+      if (DEBUG) fprintf (stderr, "writing to %s\n", skylist[0].filename[0]);
+
+      // collect array of (Stars *) stars in a new output catalog
+      int Nstars = 0;
+      int NSTARS = (NGROUP*1000);
+      ALLOCATE (stars, Stars, NSTARS);
+
+      // loop over stars in this WISE region that are also in this output region
+      for (j = i; j < Ntstars; j++) {
+	if (tstars[j].flag) continue;
+
+	// check if in skyregion
+	if (tstars[j].average.R < region[0].Rmin) continue;
+	if (tstars[j].average.R > region[0].Rmax) break;
+	if (tstars[j].average.D < region[0].Dmin) continue;
+	if (tstars[j].average.D > region[0].Dmax) continue;
+	  
+	// check if in UserPatch
+	if (tstars[j].average.R < UserPatch.Rmin) continue;
+	if (tstars[j].average.R > UserPatch.Rmax) break;
+	if (tstars[j].average.D < UserPatch.Dmin) continue;
+	if (tstars[j].average.D > UserPatch.Dmax) continue;
+	  
+	for (k = 0; k < NGROUP; k++) {
+	  stars[Nstars+k].average = tstars[j].average;
+	  stars[Nstars+k].measure = tstars[j].measure[k];
+	  stars[Nstars+k].found = -1;
+	}	  
+	tstars[j].flag = TRUE;
+
+	Nstars += NGROUP;
+	if (Nstars >= NSTARS - NGROUP) {
+	  NSTARS += (NGROUP*1000);
+	  REALLOCATE (stars, Stars, NSTARS);
+	}
+      }
+
+      ALLOCATE (starrefs, Stars *, NSTARS);
+      for (j = 0; j < Nstars; j++) {
+	starrefs[j] = &stars[j];
+      }
+
+      // now we have all of the loaded stars in this catalog
+      catalog.filename = skylist[0].filename[0];
+      catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+      catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+      catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+      catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+      int verbose = FALSE;
+
+      // an error exit status here is a significant error
+      if (!dvo_catalog_open (&catalog, skylist[0].regions[0], verbose, "w")) {
+	fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+	exit (2);
+      }
+
+      // assume no input star matches an existing star 
+      // simply add to the existing table
+      find_matches_closest_refstars(region, starrefs, Nstars, &catalog, options);
+
+      dvo_catalog_save (&catalog, verbose);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+
+      SkyListFree (skylist);
+      free (stars);
+      free (starrefs);
+    }
+    free (tstars);
+    if (VERBOSE) fprintf (stderr, "done\n");
+  }
+  if (VERBOSE) fprintf (stderr, "\n");
+  
+  fclose (f);
+  free (buffer);
+  return (TRUE);
+}
Index: /trunk/Ohana/src/addstar/src/loadwise_rawdata.c
===================================================================
--- /trunk/Ohana/src/addstar/src/loadwise_rawdata.c	(revision 38466)
+++ /trunk/Ohana/src/addstar/src/loadwise_rawdata.c	(revision 38467)
@@ -12,5 +12,5 @@
 int loadwise_rawdata (SkyList *skytable, char *filename, AddstarClientOptions options) {
   
-  int i, j, verbose;
+  int i, j, k, verbose;
   int Nstars, NSTARS, Ntstars, NTSTARS;
   int Nbyte, Nextra, offset;
@@ -140,22 +140,12 @@
 	offset = tstars[j].offset;
 
-	ALLOCATE (stars[Nstars+0], Stars, 1);
-	ALLOCATE (stars[Nstars+1], Stars, 1);
-	ALLOCATE (stars[Nstars+2], Stars, 1);
-	ALLOCATE (stars[Nstars+3], Stars, 1);
-
-	InitStar (stars[Nstars+0]);
-	InitStar (stars[Nstars+1]);
-	InitStar (stars[Nstars+2]);
-	InitStar (stars[Nstars+3]);
-
-	stars[Nstars+0][0].average.R = tstars[j].R;
-	stars[Nstars+0][0].average.D = tstars[j].D;
-	stars[Nstars+1][0].average.R = tstars[j].R;
-	stars[Nstars+1][0].average.D = tstars[j].D;
-	stars[Nstars+2][0].average.R = tstars[j].R;
-	stars[Nstars+2][0].average.D = tstars[j].D;
-	stars[Nstars+3][0].average.R = tstars[j].R;
-	stars[Nstars+3][0].average.D = tstars[j].D;
+	for (k = 0; k < 4; k++) {
+	  ALLOCATE (stars[Nstars + k], Stars, 1);
+	  InitStar (stars[Nstars + k]);
+	  stars[Nstars+k][0].average.R = tstars[j].R;
+	  stars[Nstars+k][0].average.D = tstars[j].D;
+	  stars[Nstars+k][0].measure.R = tstars[j].R;
+	  stars[Nstars+k][0].measure.D = tstars[j].D;
+	}	  
 	
 	switch (MODE) {
