Index: /trunk/Ohana/src/addstar/Makefile
===================================================================
--- /trunk/Ohana/src/addstar/Makefile	(revision 7695)
+++ /trunk/Ohana/src/addstar/Makefile	(revision 7696)
@@ -17,5 +17,5 @@
 #  
 INCS	= 	-I$(INC) -I$(LINC) -I$(XINC)
-LIBS	= 	-L$(LLIB) -ldvo -lFITS -lohana -lz -lm
+LIBS	= 	-L$(LLIB) -ldvo -lkapa -lFITS -lohana -lX11 -lz -lm
 CFLAGS	=	$(INCS)
 LFLAGS	=	$(LIBS) 
@@ -101,4 +101,17 @@
 $(SRC)/replace_match.$(ARCH).o \
 $(SRC)/update_coords.$(ARCH).o \
+$(SRC)/gcatalog.$(ARCH).o \
+$(SRC)/mkcatalog.$(ARCH).o \
+$(SRC)/wcatalog.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o
+
+SEDSTAR = \
+$(SRC)/sedstar.$(ARCH).o \
+$(SRC)/SEDtableLoad.$(ARCH).o \
+$(SRC)/SEDfit.$(ARCH).o \
+$(SRC)/SEDops.$(ARCH).o \
+$(SRC)/args_sedstar.$(ARCH).o \
 $(SRC)/gcatalog.$(ARCH).o \
 $(SRC)/mkcatalog.$(ARCH).o \
@@ -256,4 +269,8 @@
 load2mass.install        : $(DESTBIN)/load2mass
 
+sedstar                  : $(BIN)/sedstar.$(ARCH)
+$(BIN)/sedstar.$(ARCH)   : $(SEDSTAR)
+sedstar.install          : $(DESTBIN)/sedstar
+
 all: addstar addstarc addstard addstart 
 
Index: /trunk/Ohana/src/addstar/include/addstar.h
===================================================================
--- /trunk/Ohana/src/addstar/include/addstar.h	(revision 7695)
+++ /trunk/Ohana/src/addstar/include/addstar.h	(revision 7696)
@@ -91,4 +91,5 @@
 double CAL_INSTMAG_MIN;
 int    VERBOSE;
+int    PLOT;
 
 /* modify server behavior (make this an addstar cleanup mode?) */
@@ -191,4 +192,5 @@
 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);
Index: /trunk/Ohana/src/addstar/include/sedstar.h
===================================================================
--- /trunk/Ohana/src/addstar/include/sedstar.h	(revision 7695)
+++ /trunk/Ohana/src/addstar/include/sedstar.h	(revision 7696)
@@ -1,13 +1,11 @@
+# include "addstar.h"
+# include "kapa.h"
 
-typedef structu {
-  int Nfilter;
-  float *wavecode;
-  float *vegaToAB;
-  int *hashcode;
-  int codeP;
-  int codeM;
-  SEDtableRow **row;
-  int Nrow;
-} SEDtable;
+typedef enum {
+  SED_FIT,
+  SED_REQ,
+  SED_MODEL,
+  SED_SAMPLE,
+} SEDtableModes;
 
 typedef struct {
@@ -24,6 +22,23 @@
 } SEDfit;
 
+typedef struct {
+  int Nfilter;
+  float *wavecode;
+  float *vegaToAB;
+  int *mode;
+  int *hashcode;
+  int *code;
+  int codeP;
+  int codeM;
+  SEDtableRow **row;
+  int Nrow;
+} SEDtable;
+
 SEDtableRow **sort_SEDtable (SEDtableRow *raw, int N);
-int SEDcolorBracket (SEDtableRow **table, int Ntable, float color);
 SEDfit SEDchisq (SEDtableRow *ref, SEDtableRow *data, SEDtableRow *error, int Nfilter);
-
+SEDtable *SEDtableLoad (char *filename);
+int SEDcolorBracket (SEDtable *table, float color);
+int SEDfitInit (SEDtable *table);
+int SEDfitPlot (SEDtable *table, double R, double D, SEDfit *minFit, SEDtableRow *sourceValue, SEDtableRow *sourceError);
+int SEDfitCatalog (Catalog *outcat, Catalog *incat, SEDtable *table);
+void SetLimitsRaw (float *xvec, float *yvec, int Nelements, Graphdata *graphmode);
Index: /trunk/Ohana/src/addstar/src/SEDfit.c
===================================================================
--- /trunk/Ohana/src/addstar/src/SEDfit.c	(revision 7695)
+++ /trunk/Ohana/src/addstar/src/SEDfit.c	(revision 7696)
@@ -1,60 +1,27 @@
-# include "addstar.h"
 # include "sedstar.h"
 
-int SEDfit (Catalog *outcat, Catalog *incat, SEDtable *table) {
+int SEDfitCatalog (Catalog *outcat, Catalog *incat, SEDtable *table) {
   
-  Graphdata graphdata;
-  KapaSection magSection, resSection;
+  int i, j, m, idx, start, done, row, Nsec, Nfit, Nphot, fd;
+  int Nave, Nmeas, NAVE, NMEAS;
+  unsigned short USNOred, USNOblu;
+  float color;
+  int *found, valid;
 
   SEDtableRow sourceValue, sourceError;
   SEDfit minFit, testFit;
 
-  /* defaults */
-  outcat.average = NULL;
-  outcat.measure = NULL;
-  outcat.secfilt = NULL;
-
-  SEDtable = NULL;
-  SEDtableRaw = NULL;
   sourceValue.mags = NULL;
   sourceError.mags = NULL;
-  wavecode = NULL;
-  hashcode = NULL;
-  RegionName = NULL;
-  RegionList = NULL;
-  magSection.name = NULL;
-  resSection.name = NULL;
 
-  oldsignal = signal (SIGINT, handle_interrupt);
-  interrupt = FALSE;
+  Nsec = GetPhotcodeNsecfilt ();
+  Nave = outcat[0].Naverage;
+  Nmeas = outcat[0].Nmeasure;
 
-  /* load photcode information */
-  if (!InitPhotcodes ()) goto escape;
-  Nsec = GetPhotcodeNsecfilt ();
-
-  /* interpret command-line options */
-  if (!SetRegionSelection (&argc, argv, &RegionName, &RegionList)) goto escape;
-  if (!SetPhotSelections (&argc, argv, 4)) goto usage;
-
-  PLOT = FALSE;
-  if ((N = get_argument (argc, argv, "-plot"))) {
-    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);
-  }
-
-  /* interpret command-line options */
-  if (argc != 6) goto usage;
-
-  Nfit = 0;
-  colorP = GetPhotcodeCodebyName (argv[3]);
-  colorM = GetPhotcodeCodebyName (argv[5]);
-  if (!colorP || !colorM) goto color_undefined;
+  NAVE = 100;
+  NMEAS = 100;
+  REALLOCATE (outcat[0].average, Average, NAVE);
+  REALLOCATE (outcat[0].secfilt, SecFilt, NAVE*Nsec);
+  REALLOCATE (outcat[0].measure, Measure, NMEAS);
 
   // artificially set USNOred and blu errors to 0.3
@@ -62,291 +29,153 @@
   USNOblu = GetPhotcodeCodebyName ("USNO_BLUE");
 
-  // load SED table
-  f = fopen (argv[1], "r");
-  if (f == NULL) goto table_missing;
+  // create holder for the source data
+  ALLOCATE (sourceValue.mags, float, table[0].Nfilter);
+  ALLOCATE (sourceError.mags, float, table[0].Nfilter);
+  ALLOCATE (found, int, table[0].Nfilter);
 
-  // XXX add error checks for header data
-  scan_line (f, line);
-  sscanf (line, "%*s %*s %d", &Nfilter);
+  if (PLOT) SEDfitInit (table);
 
-  // load SED table photcodes, generate the photcode hashtable
-  ALLOCATE (hashcode, int, 0x10000);
-  ALLOCATE (wavecode, float, Nfilter);
-  ALLOCATE (vegaToAB, float, Nfilter);
+  // perform the fit to all sources
+  for (i = 0; i < incat[0].Naverage; i++) {
 
-  for (i = 0; i < 0x10000; i++) hashcode[i] = -1;
-  for (i = 0; i < Nfilter; i++) {
-    scan_line (f, line);
-    sscanf (line, "%*s %s %f %f", name, &wavecode[i], &vegaToAB[i]);
-    code = GetPhotcodeCodebyName (name);
-    if (code == 0) goto code_missing;
-    hashcode[code] = i;
-  }
-  codeP = hashcode[colorP];
-  codeM = hashcode[colorM];
-  if ((codeP == -1) || (codeM == -1)) goto color_missing;
-    
-  // skip remaining header lines
-  scan_line (f, line);
-  scan_line (f, line);
-  scan_line (f, line);
-  scan_line (f, line);
-  
-  // load the SED table data
-  Nrow = 0;
-  NROW = 100;
-  ALLOCATE (SEDtableRaw, SEDtableRow, NROW);
-  while (scan_line(f, line) != EOF) {
-    fparse (&SEDtableRaw[Nrow].Temp, 1, line);
-    fparse (&SEDtableRaw[Nrow].Av, 2, line);
-    ALLOCATE (SEDtableRaw[Nrow].mags, float, Nfilter);
-    for (i = 0; i < Nfilter; i++) {
-      fparse (&SEDtableRaw[Nrow].mags[i], i + 3, line);
+    // blank out the source array
+    for (j = 0; j < table[0].Nfilter; j++) {
+      sourceValue.mags[j] = 100;
+      found[j] = FALSE;
+    }	
+
+    // load the measurements for this source
+    m = incat[0].average[i].offset;
+    Nphot = 0;
+    for (j = 0; j < incat[0].average[i].Nm; j++) {
+      idx = table[0].hashcode[incat[0].measure[m+j].source];
+      if (idx == -1) continue;
+      // only fit the selected photcodes (mode == "fit")
+      if (table[0].mode[idx] == SED_MODEL) continue; 
+      if (table[0].mode[idx] == SED_SAMPLE) continue; 
+      // XXX do something more clever if more than one value exists per photcode
+      sourceValue.mags[idx] = incat[0].measure[m+j].M_PS + table[0].vegaToAB[idx];
+      sourceError.mags[idx] = incat[0].measure[m+j].dM_PS;
+      if (incat[0].measure[m+j].source == USNOred) sourceError.mags[idx] = 0.3;
+      if (incat[0].measure[m+j].source == USNOblu) sourceError.mags[idx] = 0.3;
+      found[idx] = TRUE;
+      Nphot ++;
     }
-    SEDtableRaw[Nrow].color = SEDtableRaw[Nrow].mags[codeP] - SEDtableRaw[Nrow].mags[codeM];
-    Nrow ++;
-    CHECK_REALLOCATE (SEDtableRaw, SEDtableRow, NROW, Nrow, 100);
-  }      
+    if (Nphot < 3) continue;
 
-  // sort the SEDtable by the reference colors
-  SEDtable = sort_SEDtable (SEDtableRaw, Nrow);
+    valid = TRUE;
+    for (j = 0; valid && (j < table[0].Nfilter); j++) {
+      if ((table[0].mode[j] == SED_REQ) && !found[j]) valid = FALSE;
+    }
+    if (!valid) continue;
 
-  // create holder for the source data
-  ALLOCATE (sourceValue.mags, float, Nfilter);
-  ALLOCATE (sourceError.mags, float, Nfilter);
+    // skip sources without ref color
+    if (sourceValue.mags[table[0].codeP] > 50) continue;
+    if (sourceValue.mags[table[0].codeM] > 50) continue;
+    color = sourceValue.mags[table[0].codeP] - sourceValue.mags[table[0].codeM];
 
-  if (PLOT) {
-    if (!GetGraph (&graphdata, &fd, NULL)) return (FALSE);
-    SetLimitsRaw (wavecode, NULL, Nfilter, &graphdata);
-    graphdata.style = 2;
-    graphdata.ptype = 2;
-    KapaClear (fd, TRUE);
-    magSection.name = strcreate ("mag");
-    magSection.x  = 0;
-    magSection.dx = 1;
-    magSection.y  = 0.5;
-    magSection.dy = 0.5;
-    resSection.name = strcreate ("res");
-    resSection.x  = 0.0;
-    resSection.dx = 1.0;
-    resSection.y  = 0.0;
-    resSection.dy = 0.5;
-    
-    KapaSetFont (fd, "helvetica", 14);
-    ALLOCATE (fitmags, float, Nfilter);
-    ALLOCATE (fiterrs, float, Nfilter);
-  }
+    // find tableRow within 0.1 mag of color 
+    // XXX : check on the delta value
+    start = SEDcolorBracket (table, color);
+    minFit = SEDchisq (table[0].row[start], &sourceValue, &sourceError, table[0].Nfilter);
+    minFit.row = start;
 
-  /* load region corresponding to selection above */
-  if ((skylist = SelectRegions (RegionName, RegionList)) == NULL) goto escape;
-
-  /* loop over regions, extract data for each region */
-  // XXX add interrupt checks
-  fprintf (stderr, "using %d possible regions\n", skylist[0].Nregions);
-  for (k = 0; k < skylist[0].Nregions; k++) {
-    /* lock, load, unlock catalog */
-    catalog.filename = skylist[0].filename[k];
-    switch (lock_catalog (&catalog, LCK_SOFT)) {
-      case 2:
-	unlock_catalog (&catalog);
-      case 0:
-	catalog.Naverage = 0;
-	continue;
-    }
-    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
-    if (!load_catalog (&catalog, TRUE)) {
-      catalog.Naverage = 0;
-      unlock_catalog (&catalog);
-      continue;
+    // search for min chisq backwards
+    // XXX : check on the delta value
+    done = FALSE;
+    row = start - 1;
+    while (!done && (row > 0)) {
+      testFit = SEDchisq (table[0].row[row], &sourceValue, &sourceError, table[0].Nfilter);
+      if (testFit.chisq < minFit.chisq) {
+	minFit = testFit;
+	minFit.row = row;
+      }
+      if (fabs(table[0].row[row][0].color - color) > 0.5) done = TRUE;
+      row --;
     }
 
-    // perform the fit to all sources
-    for (i = 0; i < catalog.Naverage; i++) {
+    // search for min chisq forwards
+    // XXX : check on the delta value
+    done = FALSE;
+    row = start + 1;
+    while (!done && (row < table[0].Nrow)) {
+      testFit = SEDchisq (table[0].row[row], &sourceValue, &sourceError, table[0].Nfilter);
+      if (testFit.chisq < minFit.chisq) {
+	minFit = testFit;
+	minFit.row = row;
+      }
+      if (fabs(table[0].row[row][0].color - color) > 0.5) done = TRUE;
+      row ++;
+    }
 
-      // blank out the source array
-      for (j = 0; j < Nfilter; j++) {
-	sourceValue.mags[j] = 100;
-      }	
+    Nfit ++;
+    // create the vectors for the example plots
+    if (PLOT) SEDfitPlot (table, incat[0].average[i].R, incat[0].average[i].D, &minFit, &sourceValue, &sourceError);
 
-      // load the measurements for this source
-      m = catalog.average[i].offset;
-      for (j = 0; j < catalog.average[i].Nm; j++) {
-	idx = hashcode[catalog.measure[m+j].source];
-	if (idx == -1) continue;
-	// XXX do something more clever if more than one value exists per photcode
-	sourceValue.mags[idx] = catalog.measure[m+j].M_PS + vegaToAB[idx];
-	sourceError.mags[idx] = catalog.measure[m+j].dM_PS;
-	if ((catalog.measure[m+j].source == USNOred) || (catalog.measure[m+j].source == USNOblu)) {
-	  sourceError.mags[idx] = 0.3;
-	}
-      }
+    // construct an average object for this object
+    // XXX for now, the output objects will have limited astrometric interpretation...
+    outcat[0].average[Nave].R         = incat[0].average[i].R;
+    outcat[0].average[Nave].D         = incat[0].average[i].D;
+    outcat[0].average[Nave].dR    = 0;
+    outcat[0].average[Nave].dD    = 0;
+    outcat[0].average[Nave].uR    = 0;
+    outcat[0].average[Nave].uD    = 0;
+    outcat[0].average[Nave].duR   = 0;
+    outcat[0].average[Nave].duD   = 0;
+    outcat[0].average[Nave].P     = 0;
+    outcat[0].average[Nave].dP    = 0;
 
-      // XXX for the moment, skip sources without ref color
-      if (sourceValue.mags[codeP] > 50) continue;
-      if (sourceValue.mags[codeM] > 50) continue;
-      color = sourceValue.mags[codeP] - sourceValue.mags[codeM];
+    // XXX for now, set the average mag data to NULL
+    outcat[0].average[Nave].M         = NO_MAG;
+    outcat[0].average[Nave].dM        = NO_MAG;
+    outcat[0].average[Nave].Nm        = 0;
+    outcat[0].average[Nave].Nn        = 0;
+    outcat[0].average[Nave].Xp        = NO_MAG;
+    outcat[0].average[Nave].Xm        = NO_MAG;
+    outcat[0].average[Nave].Xg        = NO_MAG;
+    outcat[0].average[Nave].offset    = Nmeas;
+    outcat[0].average[Nave].missing   = -1;
+    outcat[0].average[Nave].code      = 0;
 
-      // XXX find tableRow within 0.1 mag of color
-      start = SEDcolorBracket (SEDtable, Nrow, color);
-      minFit = SEDchisq (SEDtable[start], &sourceValue, &sourceError, Nfilter);
-      minFit.row = start;
+    for (j = 0; j < Nsec; j++) {
+      outcat[0].secfilt[Nave*Nsec+j].M_PS  = NO_MAG;
+      outcat[0].secfilt[Nave*Nsec+j].dM_PS = NO_MAG;
+      outcat[0].secfilt[Nave*Nsec+j].Xm    = NO_MAG;
+    }
 
-      // search for min chisq backwards
-      done = FALSE;
-      row = start - 1;
-      while (!done && (row > 0)) {
-	testFit = SEDchisq (SEDtable[row], &sourceValue, &sourceError, Nfilter);
-	if (testFit.chisq < minFit.chisq) {
-	  minFit = testFit;
-	  minFit.row = row;
-	}
-	if (fabs(SEDtable[row][0].color - color) > 0.5) done = TRUE;
-	row --;
-      }
+    // we now have the min chisq row. use this to supply the other filter values....
+    for (j = 0; valid && (j < table[0].Nfilter); j++) {
+      if (table[0].mode[j] != SED_MODEL) continue;
+      outcat[0].measure[Nmeas].dR_PS       = 0.0;
+      outcat[0].measure[Nmeas].dD_PS       = 0.0;
+      outcat[0].measure[Nmeas].M_PS        = MIN (table[0].row[minFit.row][0].mags[j] + minFit.Md,  NO_MAG);
+      outcat[0].measure[Nmeas].dM_PS       = 0.0;
+      outcat[0].measure[Nmeas].Mcal_PS     = 0;
+      outcat[0].measure[Nmeas].t           = TIMEREF;
+      outcat[0].measure[Nmeas].averef      = Nave;
+      outcat[0].measure[Nmeas].source      = table[0].code[j];
+      outcat[0].measure[Nmeas].dophot      = 0;
+      outcat[0].measure[Nmeas].flags       = 0;
+      outcat[0].measure[Nmeas].dt_PS       = 0xffff;
 
-      // search for min chisq forwards
-      done = FALSE;
-      row = start + 1;
-      while (!done && (row < Nrow)) {
-	testFit = SEDchisq (SEDtable[row], &sourceValue, &sourceError, Nfilter);
-	if (testFit.chisq < minFit.chisq) {
-	  minFit = testFit;
-	  minFit.row = row;
-	}
-	if (fabs(SEDtable[row][0].color - color) > 0.5) done = TRUE;
-	row ++;
-      }
+      outcat[0].measure[Nmeas].Mgal_PS     = NO_MAG;
+      outcat[0].measure[Nmeas].airmass_PS  = 0;
+      outcat[0].measure[Nmeas].FWx         = NO_MAG;
+      outcat[0].measure[Nmeas].FWy         = NO_ERR;
+      outcat[0].measure[Nmeas].theta       = NO_ERR;
+      Nmeas ++;
+      CHECK_REALLOCATE (outcat[0].measure, Measure, NMEAS, Nmeas, 100);
+    }
 
-      Nfit ++;
-      // create the vectors for the example plots
-      if (PLOT) {
-	double tmp;
-	// find plot range
-	SetLimitsRaw (NULL, SEDtable[minFit.row][0].mags, Nfilter, &graphdata);
-	SWAP (graphdata.ymin, graphdata.ymax);
-
-	KapaClear (fd, TRUE);
-	KapaSetSection (fd, &magSection);
-    	KapaSetLimits (fd, &graphdata);
-	KapaBox (fd, &graphdata);
-	graphdata.color = KapaColorByName ("blue");
-	graphdata.etype = 0;
-	KapaPrepPlot (fd, Nfilter, &graphdata);
-	KapaPlotVector (fd, Nfilter, wavecode);
-	KapaPlotVector (fd, Nfilter, SEDtable[minFit.row][0].mags);
-	graphdata.color = KapaColorByName ("red");
-	graphdata.etype = 1;
-	for (j = 0; j < Nfilter; j++) {
-	  fitmags[j] = 100;
-	  fiterrs[j] = 0;
-	  if (sourceValue.mags[j] > 50) continue;
-	  fitmags[j] = sourceValue.mags[j] - minFit.Md;
-	  fiterrs[j] = sourceError.mags[j];
-	}
-	KapaPrepPlot (fd, Nfilter, &graphdata);
-	KapaPlotVector (fd, Nfilter, wavecode);
-	KapaPlotVector (fd, Nfilter, fitmags);
-	KapaPlotVector (fd, Nfilter, fiterrs);
-	KapaPlotVector (fd, Nfilter, fiterrs);
-	KapaSendLabel (fd, "model,fit (mags)", 1);
-
-	sprintf (line, "star: %10.6f %10.6f  T: %5.0fK  A_V|: %4.2f  M_D|: %5.2f  &sc&h^2|: %5.2f", 
-		 catalog.average[i].R, catalog.average[i].D, 
-		 SEDtable[minFit.row][0].Temp, SEDtable[minFit.row][0].Av, minFit.Md, minFit.chisq);
-	KapaSendLabel (fd, line, 2);
-	KapaSendLabel (fd, "model,fit (mags)", 1);
-
-	KapaSetSection (fd, &resSection);
-	graphdata.ymin = -1.0;
-	graphdata.ymax = +1.0;
-    	KapaSetLimits (fd, &graphdata);
-	KapaBox (fd, &graphdata);
-	graphdata.color = KapaColorByName ("red");
-	graphdata.etype = 1;
-
-	for (j = 0; j < Nfilter; j++) {
-	  fitmags[j] = 100;
-	  fiterrs[j] = 0;
-	  if (sourceValue.mags[j] > 50) continue;
-	  fitmags[j] = sourceValue.mags[j] - minFit.Md - SEDtable[minFit.row][0].mags[j];
-	  fiterrs[j] = sourceError.mags[j];
-	}
-	KapaPrepPlot (fd, Nfilter, &graphdata);
-	KapaPlotVector (fd, Nfilter, wavecode);
-	KapaPlotVector (fd, Nfilter, fitmags);
-	KapaPlotVector (fd, Nfilter, fiterrs);
-	KapaPlotVector (fd, Nfilter, fiterrs);
-	KapaSendLabel (fd, "wavelength (nm)", 0);
-	KapaSendLabel (fd, "resid (mags)", 1);
-
-	KiiCursorOn (fd);
-	while (KiiCursorRead (fd, &X, &Y, key)) {
-	  fprintf (stderr, "window: %f %f (%s)\n", X, Y, key);
-	  if (!strcasecmp (key, "Q")) {
-	    KiiCursorOff (fd);
-	    break;
-	  }
-	  if (!strcasecmp (key, "ESCAPE")) {
-	    KiiCursorOff (fd);
-	    unlock_catalog (&catalog);
-	    goto escape;
-	  }
-	}
-      }
-
-      // we now have the min chisq row. use this to supply the other filter values....
+    Nave ++;
+    if (Nave >= NAVE) {
+      NAVE += 100;
+      REALLOCATE (outcat[0].average, Average, NAVE);
+      REALLOCATE (outcat[0].secfilt, SecFilt, NAVE*Nsec);
     }
-    unlock_catalog (&catalog);
   }
-  fprintf (stderr, "fitted %d stars\n", Nfit);
-  status = TRUE;
-  goto finish;
+  outcat[0].Naverage = Nave;
+  outcat[0].Nmeasure = Nmeas;
   
-usage:
-  fprintf (stderr, "USAGE: fitset (sedtable) : (F) - (F)\n");
-  goto escape;
-
-table_missing:
-  fprintf (stderr, "ERROR: can't open the SED table\n");
-  goto escape;
-
-color_missing:
-  fprintf (stderr, "ERROR: reference color not in SED table\n");
-  goto escape;
-
-color_undefined:
-  fprintf (stderr, "ERROR: undefined photcode in reference color\n");
-  goto escape;
-
-code_missing:
-  fprintf (stderr, "ERROR: undefined photcode in SED table\n");
-  goto escape;
-
-escape:
-  status = FALSE;
-  goto finish;
-
-finish:
-  if (skylist != NULL) SkyListFree (skylist, ((RegionName != NULL) || (RegionList != NULL)));
-  if (catalog.average != NULL) free (catalog.average);
-  if (catalog.secfilt != NULL) free (catalog.secfilt);
-  if (catalog.measure != NULL) free (catalog.measure);
-
-  if (RegionName != NULL) free (RegionName);
-  if (RegionList != NULL) free (RegionList);
-  if (wavecode != NULL) free (wavecode);
-  if (hashcode != NULL) free (hashcode);
-  if (SEDtableRaw != NULL) {
-    for (i = 0; i < Nrow; i++) {
-      free (SEDtableRaw[i].mags);
-    }
-    free (SEDtableRaw);
-  }
-  if (SEDtable != NULL) free (SEDtable);
-  if (sourceValue.mags != NULL) free (sourceValue.mags);
-  if (sourceError.mags != NULL) free (sourceError.mags);
-
-  signal (SIGINT, oldsignal);
-  return (status);
+  SEDfitClear ();
 }
-
Index: /trunk/Ohana/src/addstar/src/SEDops.c
===================================================================
--- /trunk/Ohana/src/addstar/src/SEDops.c	(revision 7695)
+++ /trunk/Ohana/src/addstar/src/SEDops.c	(revision 7696)
@@ -1,3 +1,2 @@
-# include "addstar.h"
 # include "sedstar.h"
 
@@ -35,16 +34,16 @@
 
 // find the first table row within 0.1 mag of the requested color (or within 10)
-int SEDcolorBracket (SEDtableRow **table, int Ntable, float color) {
+int SEDcolorBracket (SEDtable *table, float color) {
 
   int Nlo, Nhi, N;
   float tcolor;
 
-  N = Nlo = 0; Nhi = Ntable;
-  tcolor = table[Nlo][0].color;
+  N = Nlo = 0; Nhi = table[0].Nrow;
+  tcolor = table[0].row[Nlo][0].color;
   while ((Nhi - Nlo > 10) && (fabs(tcolor-color) > 0.1)) {
     N = 0.5*(Nlo + Nhi);
     N = MAX (N, 0);
-    N = MIN (N, Ntable - 1);
-    tcolor = table[N][0].color;
+    N = MIN (N, table[0].Nrow - 1);
+    tcolor = table[0].row[N][0].color;
     if (tcolor < color) {
       Nlo = N;
@@ -100,2 +99,171 @@
 }
 
+static Graphdata graphdata;
+static KapaSection magSection, resSection;
+static int Xgraph;
+static float *fitmags, *fiterrs;
+
+int SEDfitInit (SEDtable *table) {
+
+  Xgraph = KiiOpen ("kapa", "sedstar");
+  KapaInitGraph (&graphdata);
+  SetLimitsRaw (table[0].wavecode, NULL, table[0].Nfilter, &graphdata);
+  graphdata.style = 2;
+  graphdata.ptype = 2;
+  KapaClear (Xgraph, TRUE);
+  magSection.name = strcreate ("mag");
+  magSection.x  = 0;
+  magSection.dx = 1;
+  magSection.y  = 0.5;
+  magSection.dy = 0.5;
+  resSection.name = strcreate ("res");
+  resSection.x  = 0.0;
+  resSection.dx = 1.0;
+  resSection.y  = 0.0;
+  resSection.dy = 0.5;
+    
+  KiiResize (Xgraph, 900, 500);
+  KapaSetFont (Xgraph, "helvetica", 14);
+  ALLOCATE (fitmags, float, table[0].Nfilter);
+  ALLOCATE (fiterrs, float, table[0].Nfilter);
+  return (TRUE);
+}
+
+int SEDfitClear () {
+
+  free (fitmags);
+  free (fiterrs);
+  KiiClose (Xgraph);
+  return (TRUE);
+}
+
+int SEDfitPlot (SEDtable *table, double R, double D, SEDfit *minFit, SEDtableRow *sourceValue, SEDtableRow *sourceError) {
+
+  int j, minRow, Nfilter;
+  double tmp, X, Y;
+  char line[1024], key[20];
+
+  minRow = minFit[0].row;
+  Nfilter = table[0].Nfilter;
+
+  // we want to plot the OBSERVED magnitudes
+  for (j = 0; j < Nfilter; j++) {
+    fitmags[j] = table[0].row[minRow][0].mags[j] + minFit[0].Md;
+  }
+
+  // find plot range
+  SetLimitsRaw (NULL, fitmags, Nfilter, &graphdata);
+  SWAP (graphdata.ymin, graphdata.ymax);
+
+  KapaClear (Xgraph, TRUE);
+  KapaSetSection (Xgraph, &magSection);
+  KapaSetLimits (Xgraph, &graphdata);
+  KapaBox (Xgraph, &graphdata);
+  graphdata.color = KapaColorByName ("blue");
+  graphdata.etype = 0;
+  graphdata.ptype = 7;
+  KapaPrepPlot (Xgraph, Nfilter, &graphdata);
+  KapaPlotVector (Xgraph, Nfilter, table[0].wavecode);
+  KapaPlotVector (Xgraph, Nfilter, fitmags);
+
+  graphdata.color = KapaColorByName ("red");
+  graphdata.etype = 1;
+  graphdata.ptype = 2;
+  for (j = 0; j < Nfilter; j++) {
+    fitmags[j] = 100;
+    fiterrs[j] = 0;
+    if (sourceValue[0].mags[j] > 50) continue;
+    fitmags[j] = sourceValue[0].mags[j];
+    fiterrs[j] = sourceError[0].mags[j];
+  }
+  KapaPrepPlot (Xgraph, Nfilter, &graphdata);
+  KapaPlotVector (Xgraph, Nfilter, table[0].wavecode);
+  KapaPlotVector (Xgraph, Nfilter, fitmags);
+  KapaPlotVector (Xgraph, Nfilter, fiterrs);
+  KapaPlotVector (Xgraph, Nfilter, fiterrs);
+  KapaSendLabel (Xgraph, "model,fit (mags)", 1);
+
+  sprintf (line, "star: %10.6f %10.6f  T: %5.0fK  A_V|: %4.2f  M_D|: %5.2f  &sc&h^2|: %5.2f", 
+	   R, D, 
+	   table[0].row[minRow][0].Temp, 
+	   table[0].row[minRow][0].Av, 
+	   minFit[0].Md, minFit[0].chisq);
+  KapaSendLabel (Xgraph, line, 2);
+  KapaSendLabel (Xgraph, "model,fit (mags)", 1);
+
+  KapaSetSection (Xgraph, &resSection);
+  graphdata.ymin = -1.0;
+  graphdata.ymax = +1.0;
+  KapaSetLimits (Xgraph, &graphdata);
+  KapaBox (Xgraph, &graphdata);
+  graphdata.color = KapaColorByName ("red");
+  graphdata.etype = 1;
+
+  for (j = 0; j < Nfilter; j++) {
+    fitmags[j] = 100;
+    fiterrs[j] = 0;
+    if (sourceValue[0].mags[j] > 50) continue;
+    fitmags[j] = sourceValue[0].mags[j] - minFit[0].Md - table[0].row[minRow][0].mags[j];
+    fiterrs[j] = sourceError[0].mags[j];
+  }
+  KapaPrepPlot (Xgraph, Nfilter, &graphdata);
+  KapaPlotVector (Xgraph, Nfilter, table[0].wavecode);
+  KapaPlotVector (Xgraph, Nfilter, fitmags);
+  KapaPlotVector (Xgraph, Nfilter, fiterrs);
+  KapaPlotVector (Xgraph, Nfilter, fiterrs);
+  KapaSendLabel (Xgraph, "wavelength (nm)", 0);
+  KapaSendLabel (Xgraph, "resid (mags)", 1);
+
+  KiiCursorOn (Xgraph);
+  while (KiiCursorRead (Xgraph, &X, &Y, key)) {
+    // fprintf (stderr, "window: %f %f (%s)\n", X, Y, key);
+    if (!strcasecmp (key, "Q")) {
+      KiiCursorOff (Xgraph);
+      break;
+    }
+    if (!strcasecmp (key, "ESCAPE")) {
+      KiiCursorOff (Xgraph);
+      PLOT = FALSE;
+      return (TRUE);
+    }
+    if (!strcasecmp (key, "X")) {
+      KiiCursorOff (Xgraph);
+      Shutdown ("quitting sedstar");
+    }
+  }
+  return (TRUE);
+}
+
+void SetLimitsRaw (float *xvec, float *yvec, int Nelements, Graphdata *graphmode) {
+
+  double maxX, minX, maxY, minY, range;
+  int i;
+
+  if (xvec != NULL) {
+    maxX = minX = xvec[0];
+    for (i = 1; i < Nelements; i++) {
+      if (!finite(xvec[i])) continue;
+      maxX = MAX (maxX, xvec[i]);
+      minX = MIN (minX, xvec[i]);
+    }
+    range = maxX - minX;
+    if (range == 0) range = 0.001 * maxX;
+    if (range == 0) range = 0.001;
+    graphmode[0].xmin = minX - 0.05*range;
+    graphmode[0].xmax = maxX + 0.05*range;
+  }
+
+  if (yvec != NULL) {
+    maxY = minY = yvec[0];
+    for (i = 1; i < Nelements; i++) {
+      if (!finite(yvec[i])) continue;
+      maxY = MAX (maxY, yvec[i]);
+      minY = MIN (minY, yvec[i]);
+    }
+    range = maxY - minY;
+    if (range == 0) range = 0.0011 * maxY;
+    if (range == 0) range = 0.0011;
+    graphmode[0].ymin = minY - 0.05*range;
+    graphmode[0].ymax = maxY + 0.05*range;
+  }
+}
Index: /trunk/Ohana/src/addstar/src/SEDtableLoad.c
===================================================================
--- /trunk/Ohana/src/addstar/src/SEDtableLoad.c	(revision 7695)
+++ /trunk/Ohana/src/addstar/src/SEDtableLoad.c	(revision 7696)
@@ -1,3 +1,2 @@
-# include "addstar.h"
 # include "sedstar.h"
 
@@ -6,8 +5,10 @@
 
   FILE *f;
-  char line[1024], name[64];
+  char line[1024], name[64], mode[64];
   char colornameP[64], colornameM[64];
-  int colorP, colorM;
+  int colorP, colorM, code;
   int i, Nrow, NROW;
+  SEDtable *table;
+  SEDtableRow *raw;
 
   ALLOCATE (table, SEDtable, 1);
@@ -15,5 +16,6 @@
   // load SED table
   f = fopen (filename, "r");
-  if (f == NULL) 
+  if (f == NULL) Shutdown ("failure to open SED table");
+
 
   // XXX add error checks for header data
@@ -25,13 +27,26 @@
   ALLOCATE (table[0].wavecode, float, table[0].Nfilter);
   ALLOCATE (table[0].vegaToAB, float, table[0].Nfilter);
+  ALLOCATE (table[0].mode,     int,   table[0].Nfilter);
+  ALLOCATE (table[0].code,     int,   table[0].Nfilter);
 
   for (i = 0; i < 0x10000; i++) table[0].hashcode[i] = -1;
   for (i = 0; i < table[0].Nfilter; i++) {
     scan_line (f, line);
-    sscanf (line, "%*s %s %f %f", name, &table[0].wavecode[i], &table[0].vegaToAB[i]);
+    sscanf (line, "%*s %s %f %f %s", name, &table[0].wavecode[i], &table[0].vegaToAB[i], mode);
     code = GetPhotcodeCodebyName (name);
-    if (code == 0) goto code_missing;
+    table[0].code[i] = code;
+    if (code == 0) Shutdown ("undefined photcode in SED table");
     table[0].hashcode[code] = i;
+
+    table[0].mode[i] = -1;     
+    if (!strcasecmp(mode, "fit")) table[0].mode[i] = SED_FIT; 
+    if (!strcasecmp(mode, "req")) table[0].mode[i] = SED_REQ; 
+    if (!strcasecmp(mode, "model")) table[0].mode[i] = SED_MODEL; 
+    if (!strcasecmp(mode, "sample")) table[0].mode[i] = SED_SAMPLE; 
+    if (table[0].mode[i] == -1) Shutdown ("invalid photcode mode in SED table");
   }
+
+  // load color key
+  scan_line (f, line);
 
   // define the selection color codes
@@ -44,28 +59,24 @@
   if (table[0].codeM == -1) Shutdown ("missing positive color filter");
     
-  // skip remaining header lines
-  scan_line (f, line);
-  scan_line (f, line);
-  scan_line (f, line);
-  scan_line (f, line);
-  
   // load the SED raw table rows
   Nrow = 0;
   NROW = 100;
-  ALLOCATE (SEDtableRaw, SEDtableRow, NROW);
+  ALLOCATE (raw, SEDtableRow, NROW);
   while (scan_line(f, line) != EOF) {
-    fparse (&SEDtableRaw[Nrow].Temp, 1, line);
-    fparse (&SEDtableRaw[Nrow].Av, 2, line);
-    ALLOCATE (SEDtableRaw[Nrow].mags, float, table[0].Nfilter);
+    stripwhite (line);
+    if (line[0] == '#') continue;
+    fparse (&raw[Nrow].Temp, 1, line);
+    fparse (&raw[Nrow].Av, 2, line);
+    ALLOCATE (raw[Nrow].mags, float, table[0].Nfilter);
     for (i = 0; i < table[0].Nfilter; i++) {
-      fparse (&SEDtableRaw[Nrow].mags[i], i + 3, line);
+      fparse (&raw[Nrow].mags[i], i + 3, line);
     }
-    SEDtableRaw[Nrow].color = SEDtableRaw[Nrow].mags[codeP] - SEDtableRaw[Nrow].mags[codeM];
+    raw[Nrow].color = raw[Nrow].mags[table[0].codeP] - raw[Nrow].mags[table[0].codeM];
     Nrow ++;
-    CHECK_REALLOCATE (SEDtableRaw, SEDtableRow, NROW, Nrow, 100);
+    CHECK_REALLOCATE (raw, SEDtableRow, NROW, Nrow, 100);
   }      
 
   // sort the SEDtable by the reference colors
-  table[0].row = sort_SEDtable (SEDtableRaw, Nrow);
+  table[0].row = sort_SEDtable (raw, Nrow);
   table[0].Nrow = Nrow;
   return (table);
Index: /trunk/Ohana/src/addstar/src/args_sedstar.c
===================================================================
--- /trunk/Ohana/src/addstar/src/args_sedstar.c	(revision 7695)
+++ /trunk/Ohana/src/addstar/src/args_sedstar.c	(revision 7696)
@@ -42,4 +42,11 @@
   }
 
+  /* extra error messages */
+  PLOT = FALSE;
+  if ((N = get_argument (argc, argv, "-plot"))) {
+    PLOT = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
   /* other defaults */
   options.timeref = 0; 
Index: /trunk/Ohana/src/addstar/src/sedstar.c
===================================================================
--- /trunk/Ohana/src/addstar/src/sedstar.c	(revision 7695)
+++ /trunk/Ohana/src/addstar/src/sedstar.c	(revision 7696)
@@ -1,11 +1,13 @@
-# include "addstar.h"
+# include "sedstar.h"
 
 int main (int argc, char **argv) {
 
-  char *path;
-  int i, N, Nrefcat;
+  char *root, *ext;
+  int i, N, Nrefcat, status;
+  SkyList *skylist;
   SkyTable *sky, *sky2mass;
   AddstarClientOptions options;
   Catalog incatalog, outcatalog;
+  SEDtable *sedtable;
 
   // need to construct these options with args_load2mass...
@@ -24,28 +26,40 @@
   for (i = 0; i < skylist[0].Nregions; i++) {
     incatalog.filename = skylist[0].filename[i];
-    load_pt_catalog (&incatalog, skylist[0].regions[i]);
+    incatalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+
+    // lock and open input catalog
+    status = lock_catalog (&incatalog, LCK_XCLD);
+    if (status != 1) {
+	if (VERBOSE) fprintf (stderr, "skipping empty region\n");
+	continue;
+    }
+    gcatalog (&incatalog);
 
     // create output catalog filename
+    // XXX make the output catalog optional
     root = strstr (incatalog.filename, CATDIR);
     if (root == NULL) Shutdown ("error with input catalog name");
 
-    extension = incatalog.filename + strlen(CATDIR);
-    ALLOCATE (outcatalog.filename, char, strlen(argv[2]) + strlen(extension) + 2);
-    sprintf (outcatalog.filename, "%s/%s", argv[2], extension);
+    ext = incatalog.filename + strlen(CATDIR);
+    ALLOCATE (outcatalog.filename, char, strlen(argv[2]) + strlen(ext) + 2);
+    sprintf (outcatalog.filename, "%s/%s", argv[2], ext);
 
-    status = lock_catalog (outcatalog, LCK_XCLD);
+    if (!check_file_access (outcatalog.filename, TRUE, TRUE)) Shutdown ("can't create output directory");
+
+    status = lock_catalog (&outcatalog, LCK_XCLD);
     if (status != 2) Shutdown ("error: output catalog exists");
-    mkcatalog (region, catalog); /* fills in new header info */
+    mkcatalog (skylist[0].regions[i], &outcatalog); /* fills in new header info */
 
-    SEDfit (&outcatalog, &incatalog, sedtable);
+    SEDfitCatalog (&outcatalog, &incatalog, sedtable);
     
-    wcatalog (outcatalog);
-    unlock_catalog (outcatalog);
+    wcatalog (&outcatalog);
+    unlock_catalog (&outcatalog);
     free (outcatalog.filename);
+
+    unlock_catalog (&incatalog);
   }
 
   exit (0);
 }  
-
 
 /**  sedstar: 
