Index: /trunk/Ohana/src/addstar/Makefile
===================================================================
--- /trunk/Ohana/src/addstar/Makefile	(revision 7687)
+++ /trunk/Ohana/src/addstar/Makefile	(revision 7688)
@@ -88,4 +88,13 @@
 $(SRC)/get2mass_as.$(ARCH).o \
 $(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o
+
+LOAD-2MASS = \
+$(SRC)/load2mass.$(ARCH).o \
+$(SRC)/load2mass_as_data.$(ARCH).o \
+$(SRC)/get2mass_ops.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/args.$(ARCH).o \
 $(SRC)/Shutdown.$(ARCH).o \
 $(SRC)/SetSignals.$(ARCH).o
Index: /trunk/Ohana/src/addstar/include/2mass.h
===================================================================
--- /trunk/Ohana/src/addstar/include/2mass.h	(revision 7687)
+++ /trunk/Ohana/src/addstar/include/2mass.h	(revision 7688)
@@ -13,4 +13,10 @@
 } TMBands;
 
+typedef struct {
+  double R, D;
+  int offset;
+  int flag;
+} TMStars;
+
 short TM_J, TM_H, TM_K;
 
Index: /trunk/Ohana/src/addstar/src/get2mass_as.c
===================================================================
--- /trunk/Ohana/src/addstar/src/get2mass_as.c	(revision 7687)
+++ /trunk/Ohana/src/addstar/src/get2mass_as.c	(revision 7688)
@@ -29,25 +29,5 @@
   DEC1 = MIN (patch[0].Dmax, UserPatch.Dmax);
 
-  FilterSkip = TimeSkip = Qentry = 0;
-  if (photcode == TM_J) {
-      FilterSkip = 6;
-      // TimeSkip = 23;
-      TimeSkip = 28;
-      Qentry   = 0;
-  }
-  if (photcode == TM_H) {
-      FilterSkip = 10;
-      // TimeSkip = 19;
-      TimeSkip = 24;
-      Qentry   = 1;
-  }
-  if (photcode == TM_K) {
-      FilterSkip = 14;
-      // looks like this should be 20, not 15...
-      // TimeSkip = 15;
-      TimeSkip = 20;
-      Qentry   = 2;
-  }
-  if (!FilterSkip) Shutdown ("invalid photcode %s", GetPhotcodeNamebyCode(photcode));
+  get2mass_setup (photcode);
 
   gf = gzopen (filename, "rb");
@@ -75,8 +55,5 @@
     while (1) {
 
-      RA = strtod (p, NULL);
-      ptr = skipNbounds (p, '|', 1, Nbyte - (p - buffer));
-      DEC = strtod (ptr, NULL);
-      if (DEC > 90) Shutdown ("weird DEC value: something is wrong");
+      get2mass_coords (p, &RA, &DEC, Nbyte - (p - buffer));
 
       /* skip stars which are outside desired region */
@@ -86,25 +63,5 @@
       if (RA >  RA1)  goto skip_star;
 
-      ptr = skipNbounds (p, '|', FilterSkip, Nbyte - (p - buffer));
-      if (ptr == NULL) Shutdown ("format error in 2mass");
-      M  = strtod (ptr, NULL);
-      ptr = skipNbounds (ptr, '|', 1, Nbyte - (ptr - buffer));
-      dM = strtod (ptr, NULL);
-      time = get2mass_time (ptr, buffer, TimeSkip, Nbyte);
-
-      /* filter on the ph_qual flag for this filter (field 19) */
-      if (SELECT_2MASS_QUALITY != NULL) {
-	ptr = skipNbounds (p, '|', 18, Nbyte - (p - buffer));
-	qc  = ptr[Qentry];
-	if (strchr (SELECT_2MASS_QUALITY, qc) == NULL) goto skip_star;
-      }
-
-      stars[Nstars].R     = RA;
-      stars[Nstars].D     = DEC;
-      stars[Nstars].M     = M;
-      stars[Nstars].dM    = dM;
-      stars[Nstars].code  = photcode;
-      stars[Nstars].t     = time;
-      stars[Nstars].found = -1;
+      get2mass_star (&stars[Nstars], p, Nbyte - (p - buffer));
 
       Nstars ++;
@@ -149,56 +106,4 @@
 */
 
-/* return a pointer to the first char after Nbound of value bound */
-char *skipNbounds (char *line, char bound, int Nbound, int Nbyte) {
-
-  int i;
-  char *p, *q;
-
-  p = line;
-  for (i = 0; i < Nbound; i++) {
-    q = memchr (p, bound, Nbyte - (p - line));
-    if (q == NULL) return (NULL);
-    p = q + 1;
-    if (p - line == Nbyte) return (NULL);
-  }
-  return (p);
-}
-  
-// this function retrieves the time from the DATE field
-e_time get2mass_date (char *ptr, char *buffer, int Nbound, int Nbyte) {
-
-  e_time time;
-  char *p, *end;
-
-  p = skipNbounds (ptr, '|', Nbound, Nbyte - (ptr - buffer));
-  if (p == NULL) Shutdown ("format error in 2mass");
-  end = memchr (p, '|', Nbyte - (p - buffer));
-  if (end == NULL) Shutdown ("format error in 2mass");
-  *end = 0;
-  time = date_to_sec (ptr);
-  *end = '|';
-
-  return (time);
-}
-
-// this function retrieves the time from the JDATE field (%12.4f)
-e_time get2mass_time (char *ptr, char *buffer, int Nbound, int Nbyte) {
-
-  e_time time;
-  double jd;
-  char *p, *end;
-
-  p = skipNbounds (ptr, '|', Nbound, Nbyte - (ptr - buffer));
-  if (p == NULL) Shutdown ("format error in 2mass");
-  end = memchr (p, '|', Nbyte - (p - buffer));
-  if (end == NULL) Shutdown ("format error in 2mass");
-  *end = 0;
-  jd = strtod (p, NULL);
-  time = jd_to_sec (jd);
-  *end = '|';
-
-  return (time);
-}
-
 # if (0)
     /** need to re-think this test **/
Index: /trunk/Ohana/src/addstar/src/get2mass_as_raw.c
===================================================================
--- /trunk/Ohana/src/addstar/src/get2mass_as_raw.c	(revision 7687)
+++ /trunk/Ohana/src/addstar/src/get2mass_as_raw.c	(revision 7688)
@@ -31,25 +31,5 @@
   DEC1 = MIN (patch[0].Dmax, UserPatch.Dmax);
 
-  FilterSkip = TimeSkip = Qentry = 0;
-  if (photcode == TM_J) {
-      FilterSkip = 6;
-      // TimeSkip = 23;
-      TimeSkip = 28;
-      Qentry   = 0;
-  }
-  if (photcode == TM_H) {
-      FilterSkip = 10;
-      // TimeSkip = 19;
-      TimeSkip = 24;
-      Qentry   = 1;
-  }
-  if (photcode == TM_K) {
-      FilterSkip = 14;
-      // looks like this should be 20, not 15...
-      // TimeSkip = 15;
-      TimeSkip = 20;
-      Qentry   = 2;
-  }
-  if (!FilterSkip) Shutdown ("invalid photcode %s", GetPhotcodeNamebyCode(photcode));
+  get2mass_setup (photcode);
 
   f = fopen (filename, "r");
@@ -60,48 +40,4 @@
   NSTARS = 10000;
   ALLOCATE (stars, Stars, NSTARS);
-
-  /* I want to add a seek-ahead test to find a good starting position in the file
-     this is very expensive using gzseek / gzread.  */
-
-  # if 0
-  if (patch[0].Rmin > 5) {
-    // each 2MASS record is a random length of ~ 330 bytes
-    // guess at start, then used a binary search to narrow down
-    // first guess at start:
-    dNoffset = region[0].childE / 360.0;
-    Noffset = dNoffset * patch[0].Rmin;
-    fseek (f, Noffset * NBREC, SEEK_SET);
-    Nbyte = fread (buffer, 1, 10*NBREC, f);
-    q = memchr (p, '\n', Nbyte);
-    if (q == NULL) Shutdown ("incomplete line at end of file\n");
-    q++; // first (or second) complete line
-  
-    // get coords for this line
-    RA = strtod (q, NULL);
-    ptr = skipNbounds (q, '|', 1, Nbyte - (q - buffer));
-    DEC = strtod (ptr, NULL);
-    if (DEC > 90) Shutdown ("weird DEC value: something is wrong");
-
-    // if we are beyond, spin back in ~5 deg chunks 'till we are below
-    while (RA > patch[0].Rmin) {
-      fseek (f, -5 * dNoffset * NBREC, SEEK_CUR);
-      Nbyte = fread (buffer, 1, 10*NBREC, f);
-      q = memchr (p, '\n', Nbyte);
-      if (q == NULL) Shutdown ("incomplete line at end of file\n");
-      q++; // first (or second) complete line
-  
-      // get coords for this line
-      RA = strtod (q, NULL);
-      ptr = skipNbounds (q, '|', 1, Nbyte - (q - buffer));
-      DEC = strtod (ptr, NULL);
-      if (DEC > 90) Shutdown ("weird DEC value: something is wrong");
-
-      Nextra = Nbyte - (q - buffer);
-      memmove (buffer, q, Nextra);
-    }
-  } else {
-    Nextra = 0;
-  }
-  # endif
 
   Nextra = 0;
@@ -119,8 +55,5 @@
     while (1) {
 
-      RA = strtod (p, NULL);
-      ptr = skipNbounds (p, '|', 1, Nbyte - (p - buffer));
-      DEC = strtod (ptr, NULL);
-      if (DEC > 90) Shutdown ("weird DEC value: something is wrong");
+      get2mass_coords (p, &RA, &DEC, Nbyte - (p - buffer));
 
       /* skip stars which are outside desired region */
@@ -130,25 +63,5 @@
       if (RA >  RA1)  goto skip_star;
 
-      ptr = skipNbounds (p, '|', FilterSkip, Nbyte - (p - buffer));
-      if (ptr == NULL) Shutdown ("format error in 2mass");
-      M  = strtod (ptr, NULL);
-      ptr = skipNbounds (ptr, '|', 1, Nbyte - (ptr - buffer));
-      dM = strtod (ptr, NULL);
-      time = get2mass_time (ptr, buffer, TimeSkip, Nbyte);
-
-      /* filter on the ph_qual flag for this filter (field 19) */
-      if (SELECT_2MASS_QUALITY != NULL) {
-	ptr = skipNbounds (p, '|', 18, Nbyte - (p - buffer));
-	qc  = ptr[Qentry];
-	if (strchr (SELECT_2MASS_QUALITY, qc) == NULL) goto skip_star;
-      }
-
-      stars[Nstars].R     = RA;
-      stars[Nstars].D     = DEC;
-      stars[Nstars].M     = M;
-      stars[Nstars].dM    = dM;
-      stars[Nstars].code  = photcode;
-      stars[Nstars].t     = time;
-      stars[Nstars].found = -1;
+      get2mass_star (&stars[Nstars], p, Nbyte - (p - buffer));
 
       Nstars ++;
Index: /trunk/Ohana/src/addstar/src/get2mass_ops.c
===================================================================
--- /trunk/Ohana/src/addstar/src/get2mass_ops.c	(revision 7688)
+++ /trunk/Ohana/src/addstar/src/get2mass_ops.c	(revision 7688)
@@ -0,0 +1,171 @@
+# include "addstar.h"
+# include "2mass.h"
+
+static int FilterSkip;
+static int TimeSkip;
+static int Qentry;
+static int Photcode;
+
+int get2mass_setup (int photcode) {
+
+  FilterSkip = TimeSkip = Qentry = 0;
+  Photcode = photcode;
+
+  if (photcode == TM_J) {
+      FilterSkip = 6;
+      TimeSkip = 28;
+      Qentry   = 0;
+  }
+  if (photcode == TM_H) {
+      FilterSkip = 10;
+      TimeSkip = 24;
+      Qentry   = 1;
+  }
+  if (photcode == TM_K) {
+      FilterSkip = 14;
+      TimeSkip = 20;
+      Qentry   = 2;
+  }
+  if (!FilterSkip) Shutdown ("invalid photcode %s", GetPhotcodeNamebyCode(photcode));
+  return TRUE;
+}
+
+int get2mass_star (Stars *star, char *line, int Nmax) {
+
+  ptr = skipNbounds (p, '|', FilterSkip, Nmax);
+  if (ptr == NULL) Shutdown ("format error in 2mass");
+  M  = strtod (ptr, NULL);
+  ptr = skipNbounds (ptr, '|', 1, Nmax - (ptr - line));
+  dM = strtod (ptr, NULL);
+  time = get2mass_time (ptr, buffer, TimeSkip, Nbyte);
+
+  /* filter on the ph_qual flag for this filter (field 19) */
+  if (SELECT_2MASS_QUALITY != NULL) {
+    ptr = skipNbounds (p, '|', 18, Nmax - (ptr - line));
+    qc  = ptr[Qentry];
+    if (strchr (SELECT_2MASS_QUALITY, qc) == NULL) return (FALSE);
+  }
+
+  stars[0].M     = M;
+  stars[0].dM    = dM;
+  stars[0].code  = photcode;
+  stars[0].t     = time;
+  stars[0].found = -1;
+
+  return TRUE;
+}
+
+int get2mass_coords (Stars *star, double *R, double *D, int Nmax) {
+
+  *R = strtod (p, NULL);
+  ptr = skipNbounds (p, '|', 1, Nmax);
+  *D = strtod (ptr, NULL);
+  if (*D > 90) Shutdown ("weird DEC value: something is wrong");
+
+  return TRUE;
+}
+
+// this function retrieves the time from the DATE field
+e_time get2mass_date (char *ptr, int Nbound, int Nmax) {
+
+  e_time time;
+  char *p, *end;
+
+  p = skipNbounds (ptr, '|', Nbound, Nmax);
+  if (p == NULL) Shutdown ("format error in 2mass");
+  end = memchr (p, '|', Nmax - (p - ptr));
+  if (end == NULL) Shutdown ("format error in 2mass");
+  *end = 0;
+  time = date_to_sec (ptr);
+  *end = '|';
+
+  return (time);
+}
+
+// this function retrieves the time from the JDATE field (%12.4f)
+e_time get2mass_time (char *ptr, int Nbound, int Nmax) {
+
+  e_time time;
+  double jd;
+  char *p, *end;
+
+  p = skipNbounds (ptr, '|', Nbound, Nmax);
+  if (p == NULL) Shutdown ("format error in 2mass");
+  end = memchr (p, '|', Nmax - (p - ptr));
+  if (end == NULL) Shutdown ("format error in 2mass");
+  *end = 0;
+  jd = strtod (p, NULL);
+  time = jd_to_sec (jd);
+  *end = '|';
+
+  return (time);
+}
+
+/* return a pointer to the first char after Nbound of value bound */
+char *skipNbounds (char *line, char bound, int Nbound, int Nbyte) {
+
+  int i;
+  char *p, *q;
+
+  p = line;
+  for (i = 0; i < Nbound; i++) {
+    q = memchr (p, bound, Nbyte - (p - line));
+    if (q == NULL) return (NULL);
+    p = q + 1;
+    if (p - line == Nbyte) return (NULL);
+  }
+  return (p);
+}
+  
+/* watch for patches which cross 0,360 boundary */
+SkyTable *load2mass_acc (char *path, char *accel) {
+
+  int Nregions, NREGIONS, Nrec;
+  char accelfile[1024], line[256], filename[128], datafile[256], **filenames;
+  FILE *f;
+  double Rs, Re, Ds, De;
+
+  SkyTable *sky;
+  SkyRegion *regions;
+
+  sprintf (accelfile, "%s/%s", path, accel);
+  f = fopen (accelfile, "r");
+  if (f == NULL) Shutdown ("can't read data from accelerator %s", accelfile);
+
+  Nregions = 0;
+  NREGIONS = 200;
+  ALLOCATE (regions, SkyRegion, NREGIONS);
+  ALLOCATE (filenames, char *, NREGIONS);
+
+  /* read in stars line-by-line */
+  while (scan_line (f, line) != EOF) {
+    stripwhite (line);
+    if (line[0] == 0) continue;
+    if (line[0] == '#') continue;
+    sscanf (line, "%s %lf %lf %lf %lf %d", filename, &Rs, &Re, &Ds, &De, &Nrec);
+    Rs *= 15.0;
+    Re *= 15.0;
+    regions[Nregions].Rmin = Rs;
+    regions[Nregions].Rmax = Re;
+    regions[Nregions].Dmin = Ds;
+    regions[Nregions].Dmax = De;
+    regions[Nregions].childE = Nrec; // a cheat since 2MASS only has one depth
+
+    sprintf (datafile, "%s/%s", path, filename);
+    filenames[Nregions] = strcreate (datafile);
+
+    Nregions ++;
+    if (Nregions >= NREGIONS) {
+	NREGIONS += 20;
+	REALLOCATE (regions, SkyRegion, NREGIONS);
+	REALLOCATE (filenames, char *, NREGIONS);
+    }
+  }    
+  fclose (f);
+
+  ALLOCATE (sky, SkyTable, 1);
+  sky[0].regions = regions;
+  sky[0].filename = filenames;
+  sky[0].Nregions = Nregions;
+  return (sky);
+}
Index: /trunk/Ohana/src/addstar/src/load2mass.c
===================================================================
--- /trunk/Ohana/src/addstar/src/load2mass.c	(revision 7688)
+++ /trunk/Ohana/src/addstar/src/load2mass.c	(revision 7688)
@@ -0,0 +1,38 @@
+# include "addstar.h"
+# include "2mass.h"
+
+int main (int argc, char **argv) {
+
+  char *path;
+  int i, N, Nrefcat;
+  SkyTable *sky;
+
+  if (argc == 2) {
+    load2mass_as_data (argv[1]);
+    exit (0);
+  }
+
+  // need to construct these options with args_load2mass...
+  options = ConfigInit (&argc, argv);
+  options = args (argc, argv, options);
+
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: load2mass [options: see addstar]\n");
+    exit (2);
+  }
+
+  path = TWO_MASS_DIR_AS;
+
+  // the accel.dat file has the raw filenames
+  // test if the file exists, or else try the .gz version
+  sky = load2mass_acc (path, "accel.dat");
+  
+  for (i = 0; i < sky[0].Nregions; i++) {
+    fprintf (stderr, "loading %s\n", sky[0].filename[i]);
+    load2mass_as_data (skytable, sky[0].filename[i], options);
+  }
+  exit (0);
+}  
Index: /trunk/Ohana/src/addstar/src/load2mass_as_raw.c
===================================================================
--- /trunk/Ohana/src/addstar/src/load2mass_as_raw.c	(revision 7688)
+++ /trunk/Ohana/src/addstar/src/load2mass_as_raw.c	(revision 7688)
@@ -0,0 +1,155 @@
+# include "addstar.h"
+# include "2mass.h"
+
+/* unlike the DR2 data, the AS data is NOT fixed bytes/row 
+ * we need to handle fractional lines at the end of each read block
+ */
+
+/* read in chunks of ~16MB */
+# define NBYTE 0x1000000
+# define NBREC 330
+
+int load2mass_as_rawdata (SkyTable *skytable, char *filename, AddstarClientOptions options) {
+  
+  int Nstars, NSTARS, Ntstars, NTSTARS;
+  int Nbyte, Nextra, Ntotal;
+
+  FILE *f;
+  char *buffer, *p, *q;
+
+  Stars *stars;
+  TMStars *tstars;
+
+  get2mass_setup (options.photcode);
+
+  ALLOCATE (buffer, char, NBYTE);
+
+  // scan through the entire 2MASS file
+  f = fopen (filename, "r");
+  if (f == NULL) Shutdown ("can't read 2mass data file: %s", filename);
+  // test if this is a raw datafile or gzipped...
+
+  Nextra = 0;  // number excess bytes from lsat partial row
+  Ntotal = 0;  // track the total number of bytes read 
+  while ((Nbyte = fread (&buffer[Nextra], 1, NBYTE-Nextra, f)) != 0) {
+    if (Nbyte == -1) Shutdown ("error reading from raw file %s", filename);
+    Nbyte += Nextra;
+
+    if (VERBOSE) fprintf (stderr, ".");
+
+    /* find bounds on first complete line */
+    p = buffer;
+    q = memchr (p, '\n', Nbyte);
+    if (q == NULL) Shutdown ("incomplete line at end of file\n");
+    offset = p - buffer; // offset within this scan
+
+    Ntstars = 0;
+    NTSTARS = 10000;
+    ALLOCATE (tstars, TMStars, NTSTARS);
+
+    // scan through entire buffer for star coords
+    while (1) {
+      get2mass_coords (p, &tstars[Ntstars].R, &tstars[Ntstars].D, Nbyte - offset);
+      tstars[Ntstars].offset = offset; // offset within scan
+      tstars[Ntstars].flag = FALSE;
+
+      Ntstars ++;
+      CHECK_REALLOCATE (tstars, TMStars, NTSTARS, Ntstars, 10000);
+
+      /* start of the next line */
+      p = q + 1;
+      offset = p - buffer; // offset within this scan
+      if (offset == Nbyte) {
+	// last line in buffer is a complete line
+	Nextra = 0;
+	break;
+      }
+      /* end of the next line */
+      q = memchr (p, '\n', Nbyte - offset);
+      if (q == NULL) {
+	// last, incomplete line in buffer
+	Nextra = Nbyte - offset;
+	break;
+      } 
+    }
+
+    // scan through the stars, loading the containing catalogs
+    // skip through table for unsaved stars
+    for (i = 0; i < Ntstars; ) {
+      if (tstars[i].flag) continue;
+
+      // collect stars in a new output catalog
+      Nstars = 0;
+      NSTARS = 10000;
+      ALLOCATE (stars, Stars, NSTARS);
+	
+      // identify the relevant catalog
+      skylist = SkyRegionByPoint (skytable, -1, tstars[i].R, tstars[i].D);
+      region = skylist[0].regions[0];
+
+      for (j = i; j < Ntstars; j++) {
+	if (tstars[j].flag) continue;
+
+	// check if in skyregion
+	if (tstars[j].R < region[0].Rmin) continue;
+	if (tstars[j].R > region[0].Rmax) continue;
+	if (tstars[j].D < region[0].Dmin) continue;
+	if (tstars[j].D > region[0].Dmax) continue;
+	  
+	offset = tstars[j].offset;
+
+	stars[Nstars].R = tstars[j].R;
+	stars[Nstars].D = tstars[j].R;
+	get2mass_star (&stars[Nstars], &buffer[offset], Nbyte - offset);
+	tstars[j].flag = TRUE;
+
+	Nstars ++;
+	CHECK_REALLOCATE (stars, Stars, NSTARS, Nstars, 5000);
+      }
+      if (!Nstars) {
+	free (stars);
+	continue;
+      }
+
+      // now we have all of the loaded stars in this catalog
+      catalog.filename = skylist[0].filename[0];
+      load_pt_catalog (&catalog, skylist[0].regions[0]);
+
+      // create the subset pointers
+      ALLOCATE (subset, Stars, *, Nstars);
+      for (j = 0; j < Nstars; j++) subset[j] = &stars[j];
+
+      find_matches_refstars (skylist[0].regions[0], subset, Nstars, &catalog, options);
+      free (subset);
+
+      unlock_catalog (&catalog);
+      free (catalog.filename);
+      free (stars);
+    }
+    free (tstars);
+
+    // at end, p points at the start of last, partial line
+    if (Nextra) memmove (buffer, p, Nextra);
+  }
+
+  if (VERBOSE) fprintf (stderr, "\n");
+  
+  fclose (f);
+  free (buffer);
+  *nstars = Nstars;
+  return (stars);
+}
+
+/*
+  for each 2mass file:
+  for each data block
+  generate a table of: R, D, byte, flag
+  for each unsaved star
+  find containing catalog
+  load catalog
+  find all contained stars
+  add to catalog
+  save catalog 
+  mark all contained stars
+*/
+
Index: /trunk/Ohana/src/addstar/src/scan2mass_as_data.c
===================================================================
--- /trunk/Ohana/src/addstar/src/scan2mass_as_data.c	(revision 7687)
+++ /trunk/Ohana/src/addstar/src/scan2mass_as_data.c	(revision 7688)
@@ -58,8 +58,6 @@
     while (1) {
 
-      Ro = strtod (p, NULL);
-      ptr = skipNbounds (p, '|', 1, Nbyte - (p - buffer));
-      Do = strtod (ptr, NULL);
-      if (Do > 90) Shutdown ("weird DEC value: something is wrong");
+      get2mass_coords (p, &Ro, &Do, Nbyte - (p - buffer));
+
       if (badStar) {
       fprintf (stderr, "next R,D: %10.6f %10.6f\n", Ro, Do);
Index: /trunk/Ohana/src/opihi/dvo/fitsed.c
===================================================================
--- /trunk/Ohana/src/opihi/dvo/fitsed.c	(revision 7687)
+++ /trunk/Ohana/src/opihi/dvo/fitsed.c	(revision 7688)
@@ -44,5 +44,5 @@
   KapaSection magSection, resSection;
 
-  Catalog catalog;
+  Catalog catalog, outcat;
   SkyList *skylist;
   SEDtableRow *SEDtableRaw, **SEDtable;
@@ -55,4 +55,9 @@
   catalog.measure = NULL;
   catalog.secfilt = NULL;
+
+  outcat.average = NULL;
+  outcat.measure = NULL;
+  outcat.secfilt = NULL;
+
   SEDtable = NULL;
   SEDtableRaw = NULL;
@@ -81,4 +86,11 @@
     remove_argument (N, &argc, argv);
     PLOT = TRUE;
+  }
+
+  SAVEDIR = NULL;
+  if ((N = get_argument (argc, argv, "-save"))) {
+    remove_argument (N, &argc, argv);
+    SAVEDIR = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
   }
 
