Index: /branches/eam_branches/ipp-20150616/Ohana/src/addstar/Makefile
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/addstar/Makefile	(revision 38517)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/addstar/Makefile	(revision 38518)
@@ -256,5 +256,8 @@
 $(SRC)/loadgalphot_readstars.$(ARCH).o \
 $(SRC)/loadgalphot_fit2d.$(ARCH).o \
+$(SRC)/loadgalphot_join.$(ARCH).o \
 $(SRC)/loadgalphot_table.$(ARCH).o \
+$(SRC)/strhash.$(ARCH).o \
+$(SRC)/sortIDs.$(ARCH).o \
 $(SRC)/psps_ids.$(ARCH).o
 
Index: /branches/eam_branches/ipp-20150616/Ohana/src/addstar/include/loadgalphot.h
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/addstar/include/loadgalphot.h	(revision 38517)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/addstar/include/loadgalphot.h	(revision 38518)
@@ -30,4 +30,10 @@
 } GalPhot_Stars;
 
+typedef struct {
+  int *ID;
+  int *type;
+  int  N;
+} GalPhotIDset;
+
 AddstarClientOptions args_loadgalphot (int argc, char **argv, AddstarClientOptions options);
 
@@ -53,2 +59,7 @@
 int fit2d (Fit2D *fit, float *xval, float *yval, float *zval, float *zfit, char *mask, int Npts);
 int fit2d_reset (Fit2D *fit);
+
+int *join_IDs (GalPhotIDset *gal, GalPhotIDset *fit);
+int strhash (char *string, int module);
+
+void sort_IDs_seqonly (int *X, int *S, int N);
Index: /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/loadgalphot_join.c
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/loadgalphot_join.c	(revision 38517)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/loadgalphot_join.c	(revision 38518)
@@ -1,10 +1,4 @@
 # include "addstar.h"
 # include "loadgalphot.h"
-
-typedef struct {
-  int *ID;
-  int *type;
-  int  N;
-} GalPhotIDset;
 
 // find the entries in 'fit' which match entries in 'gal'
@@ -12,15 +6,17 @@
 int *join_IDs (GalPhotIDset *gal, GalPhotIDset *fit) {
   
-  off_t ifit, igal, first_ifit, Ifit, Igal, *seq_fit, *seq_gal, Nmatch, NMATCH;
-  opihi_int dID;
+  int Nmatch = 0;
+  int NMATCH = gal->N;
+  int *idx_gal = NULL;
+  ALLOCATE (idx_gal, int, gal->N);
 
-  NMATCH = gal->N;
-  ALLOCATE (idx_gal, off_t, gal->N);
-
-  ALLOCATE (seq_gal, off_t, gal->N);
-  ALLOCATE (seq_fit, off_t, fit->N);
-
-  for (i = 0; i < gal->N; i++) { seq_gal[i] = i; }
-  for (i = 0; i < fit->N; i++) { seq_fit[i] = i; }
+  int *seq_fit, *seq_gal;
+  ALLOCATE (seq_gal, int, gal->N);
+  ALLOCATE (seq_fit, int, fit->N);
+  { 
+    int i;
+    for (i = 0; i < gal->N; i++) { seq_gal[i] = i; }
+    for (i = 0; i < fit->N; i++) { seq_fit[i] = i; }
+  }
 
   // sort the sequences 
@@ -28,10 +24,10 @@
   sort_IDs_seqonly (fit->ID, seq_fit, fit->N);
 
-  Nmatch = 0;
+  int ifit, igal;
   for (ifit = igal = 0; (igal < gal->N) && (ifit < fit->N);) {
-    Igal = seq_gal[i];
-    Ifit = seq_fit[j];
+    int Igal = seq_gal[igal];
+    int Ifit = seq_fit[ifit];
 
-    dID = gal->ID[Igal] - fit->ID[Ifit];
+    int dID = gal->ID[Igal] - fit->ID[Ifit];
 
     if (dID < 0) { igal++; continue; }
@@ -40,30 +36,35 @@
     // look for all matches of list2() to list1(i)
     // this allows for multiple values of ID1 or ID2
-    first_ifit = ifit;
-    for (ifit = first_ifit; (dID == 0) && (ifit < fit->N); ifit++) {
-      Ifit = seq_fit[j];
+    int ifit_first = ifit;
+    int found = FALSE;
+    for (ifit = ifit_first; (dID == 0) && (ifit < fit->N); ifit++) {
+      Ifit = seq_fit[ifit];
       dID = gal->ID[Igal] - fit->ID[Ifit];
-      if (dID == 0) {
-	// XXX find the matching model types
-	index1->elements.Int[Nmatch] = I;
-	index2->elements.Int[Nmatch] = J;
-
+      if ((dID == 0) && (gal->type[Igal] == fit->type[Ifit])){
+	idx_gal[Igal] = Ifit;
+	found = TRUE;
 	Nmatch ++;
 	if (Nmatch >= NMATCH) {
-	  NMATCH += DMATCH;
-	  REALLOCATE (index1->elements.Int, opihi_int, NMATCH);
-	  REALLOCATE (index2->elements.Int, opihi_int, NMATCH);
+	  NMATCH += 1000;
+	  REALLOCATE (idx_gal, int, NMATCH);
 	}
+	break;
       }
     }
-    j = first_j;
-    i++;
+    myAssert (found, "gal entry not found?");
+    ifit = ifit_first;
+    igal ++;
   }
-  index1->Nelements = Nmatch;
-  index2->Nelements = Nmatch;
+  free (seq_gal);
+  free (seq_fit);
 
-  free (N1);
-  free (N2);
+  myAssert (Nmatch == gal->N, "did not find matches for all galaxies");
+  
+  for (igal = 0; igal < gal->N; igal++) {
+    ifit = idx_gal[igal];
+    myAssert (fit->ID[ifit]   == gal->ID[igal],   "ID mis-match");
+    myAssert (fit->type[ifit] == gal->type[igal], "type mis-match");
+  }
 
-  return (TRUE);
+  return (idx_gal);
 }
Index: /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/loadgalphot_readstars.c
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/loadgalphot_readstars.c	(revision 38517)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/loadgalphot_readstars.c	(revision 38518)
@@ -22,5 +22,5 @@
   if (f == NULL) Shutdown ("can't read stellar parameter file: %s", filename);
 
-  int i, Ncol, Nsample;
+  int i, j, Ncol, Nsample;
   off_t Nrow = 0;
   off_t NrowNew;
@@ -35,39 +35,4 @@
     fclose (f);
     return NULL;
-  }
-
-  // in xgal, we have numerical values to specify the model types
-  // in xfit, we have strings.  these are listed with their numerical 
-  // match in the PHU.  I need to read the list of names and set up a string hash
-
-  if (!gfits_scan (PHU, "MTNUM", "%d", 1, &ModelTypeN)) { myAbort ("fail"); }
-  ALLOCATE (ModelTypeName, char *, ModelTypeN);
-  ALLOCATE (ModelTypeNum,  int, ModelTypeN);
-  ALLOCATE (ModelTypeHash, int, ModelTypeN);
-
-  int tmpnumber, namehash[256][3];
-  for (i = 0; i < 256; i++) {
-    namehash[i][0] = -1;
-    namehash[i][1] = -1;
-    namehash[i][2] = -1;
-  }
-
-  char name[256], tmpname[256];
-  for (i = 0; i < ModelTypeN; i++) {
-    snprintf (name, 64, "MTNAM%02d", i);
-    if (!gfits_scan (PHU, name, "%s", 1, tmpname)) { myAbort ("fail"); }
-    ModelTypeName[i] = strcreate (tmpname);
-    int found = FALSE;
-    int myHash = strhash (tmpname);
-    ModelTypeHash[i] = myHash;
-    for (j = 0; (j < 3) && !found; j++) {
-      if (namehash[myHash][j] != -1) continue;
-      found = TRUE;
-      namehash[myHash][j] = i;
-    }
-    myAssert (found, "hash conflict");
-    snprintf (name, 64, "MTVAL%02d", i);
-    if (!gfits_scan (PHU, name, "%d", 1, &tmpnumber)) { myAbort ("fail"); }
-    ModelTypeNum[i] = tmpnumber;
   }
 
@@ -81,6 +46,45 @@
     return NULL;
   }
-
   ftable_xfit.header = &header_xfit;
+
+  // in xgal, we have numerical values to specify the model types
+  // in xfit, we have strings.  these are listed with their numerical 
+  // match in the PHU.  I need to read the list of names and set up a string hash
+
+  int ModelTypeN;
+  char **ModelTypeName;
+  int *ModelTypeNum;
+  int *ModelTypeHash;
+  if (!gfits_scan (&header_xfit, "MTNUM", "%d", 1, &ModelTypeN)) { myAbort ("fail"); }
+  ALLOCATE (ModelTypeName, char *, ModelTypeN);
+  ALLOCATE (ModelTypeNum,  int, ModelTypeN);
+  ALLOCATE (ModelTypeHash, int, ModelTypeN);
+
+  int tmpnumber, namehash[256][3];
+  for (i = 0; i < 256; i++) {
+    namehash[i][0] = -1;
+    namehash[i][1] = -1;
+    namehash[i][2] = -1;
+  }
+
+  char name[256], tmpname[256];
+  for (i = 0; i < ModelTypeN; i++) {
+    snprintf (name, 64, "MTNAM%02d", i);
+    if (!gfits_scan (&header_xfit, name, "%s", 1, tmpname)) { myAbort ("fail"); }
+    ModelTypeName[i] = strcreate (tmpname);
+    int found = FALSE;
+    int myHash = strhash (tmpname, 0xff);
+    fprintf (stderr, "model %s, hash: %d\n", tmpname, myHash);
+    ModelTypeHash[i] = myHash;
+    for (j = 0; (j < 3) && !found; j++) {
+      if (namehash[myHash][j] != -1) continue;
+      found = TRUE;
+      namehash[myHash][j] = i;
+    }
+    myAssert (found, "hash conflict");
+    snprintf (name, 64, "MTVAL%02d", i);
+    if (!gfits_scan (&header_xfit, name, "%d", 1, &tmpnumber)) { myAbort ("fail"); }
+    ModelTypeNum[i] = tmpnumber;
+  }
 
   if (!gfits_fread_ftable_data (f, &ftable_xfit, FALSE)) {
@@ -94,5 +98,5 @@
   firstCol = TRUE;
   GET_COLUMN (xfit, ID_fit,         "IPP_IDET",      int);
-  GET_COLUMN (xfit, MODEL_TYPE_str, "MODEL_TYPE",    char); NcharModel = Ncol;
+  GET_COLUMN (xfit, MODEL_TYPE_str, "MODEL_TYPE",    char);  int NcharModel = Ncol;
   GET_COLUMN (xfit, EXT_WIDTH_MAJ,  "EXT_WIDTH_MAJ", float);
   GET_COLUMN (xfit, EXT_WIDTH_MIN,  "EXT_WIDTH_MIN", float);
@@ -102,20 +106,28 @@
   int Nfit = Nrow;
 
+  myAssert (NcharModel < 256, "max model type name is very long: %d", NcharModel);
+
   // free the memory associated with the FITS files
   gfits_free_header (&header_xfit);
   gfits_free_table (&ftable_xfit);
 
+  char string[256];
+
   // convert MODEL_TYPE_str to MODEL_TYPE_fit (transforming strings to values)
+  int *MODEL_TYPE_fit;
   ALLOCATE (MODEL_TYPE_fit, int, Nfit);
   for (i = 0; i < Nfit; i++) {
-    int myHash = strhash (MODEL_TYPE_str[i]);
+    memset (string, 0, 256);
+    memcpy (string, &MODEL_TYPE_str[i*NcharModel], NcharModel); string[NcharModel] = 0;
+    stripwhite (string);
+    int myHash = strhash (string, 0xff);
     int found = FALSE;
     for (j = 0; !found && (j < 3); j++) {
       int n = namehash[myHash][j];
-      if (strcmp(ModelTypeName[n], MODEL_TYPE_str[i])) continue;
+      if (strcmp(ModelTypeName[n], string)) continue;
       MODEL_TYPE_fit[i] = ModelTypeNum[n];
       found = TRUE;
     }
-    myAssert (found, "unknown model name? %s", MODEL_TYPE_str[i]);
+    myAssert (found, "unknown model name? %s", string);
   }
 
@@ -155,15 +167,15 @@
   GET_COLUMN (xgal, FR_MINOR_MAX,  "FR_MINOR_MAX", float);
   GET_COLUMN (xgal, FR_MINOR_DEL,  "FR_MINOR_DEL", float);
-  Ngal = Nrow;
+  int Ngal = Nrow;
 
   // i need to match the two lists based on (ID_gal == ID_fit), (MODEL_TYPE_gal == MODEL_TYPE_fit)
-  GalPhotIDset fit, gal;
-  fit.ID   = ID_fit;
-  fit.type = MODEL_TYPE_fit;
-  fit.N    = Nfit;
-  gal.ID   = ID_gal;
-  gal.type = MODEL_TYPE_gal;
-  gal.N    = Ngal;
-  int *index = join_IDs (&gal, &fit);
+  GalPhotIDset fitSet, galSet;
+  fitSet.ID   = ID_fit;
+  fitSet.type = MODEL_TYPE_fit;
+  fitSet.N    = Nfit;
+  galSet.ID   = ID_gal;
+  galSet.type = MODEL_TYPE_gal;
+  galSet.N    = Ngal;
+  int *idx_gal = join_IDs (&galSet, &fitSet);
 
   // free the memory associated with the FITS files
@@ -192,4 +204,6 @@
   for (i = 0; i < Nrow; i++) {
 
+    int ifit = idx_gal[i];
+
     double R, D;
     XY_to_RD (&R, &D, X_FIT[i], Y_FIT[i], &coords);
@@ -208,6 +222,10 @@
     // theta, theta_err, index, 
     // note that FR_MAJOR, etc are the fractions of the stack fit value
-    stars[i].galphot.theta = NAN;
-    stars[i].galphot.thetaErr = NAN;
+    stars[i].galphot.theta     = EXT_THETA[ifit];
+    stars[i].galphot.thetaErr  = EXT_THETA_ERR[ifit];
+    stars[i].galphot.index     = INDEX[ifit];
+    stars[i].galphot.Npix      = NPIX[i];
+    stars[i].galphot.modelType = MODEL_TYPE_gal[i];
+    stars[i].galphot.detID     = ID_gal[i];
 
     // I have a grid of measurements with (Flux, dFlux, Chisq) at each point
@@ -217,4 +235,10 @@
       Nbad ++;
     }
+
+    // I could either multiply FR_MAJOR_MIN, etc above or the fitted values below
+    stars[i].galphot.majorAxis    *= EXT_WIDTH_MAJ[ifit];
+    stars[i].galphot.majorAxisErr *= EXT_WIDTH_MAJ[ifit];
+    stars[i].galphot.minorAxis    *= EXT_WIDTH_MIN[ifit];
+    stars[i].galphot.minorAxisErr *= EXT_WIDTH_MIN[ifit];
   }
 
@@ -347,5 +371,5 @@
   // use bilinear interpolation to choose Flux @ (Xmin,Ymin)?
   galphot->mag    = -2.5*log10(flux[iMin]); // correct for exptime?
-  galphot->magErr = -2.5*log10(fluxErr[iMin]); // correct for exptime?
+  galphot->magErr = fluxErr[iMin] / flux[iMin];
   galphot->chisq  = chisqMin;
   
Index: /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/sortIDs.c
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/sortIDs.c	(revision 38518)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/sortIDs.c	(revision 38518)
@@ -0,0 +1,18 @@
+# include "addstar.h"
+# include "loadgalphot.h"
+
+/* sort a coordinate pair (X,Y) and the associated index (S) */
+void sort_IDs_seqonly (int *X, int *S, int N) {
+  
+# define SWAPFUNC(A,B){ off_t itmp; \
+  itmp = S[A]; S[A] = S[B]; S[B] = itmp; \
+}
+# define COMPARE(A,B)(X[S[A]] < X[S[B]])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
Index: /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/strhash.c
===================================================================
--- /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/strhash.c	(revision 38518)
+++ /branches/eam_branches/ipp-20150616/Ohana/src/addstar/src/strhash.c	(revision 38518)
@@ -0,0 +1,16 @@
+# include "addstar.h"
+
+int strhash (char *string, int modulus) {
+
+  myAssert (modulus < 0x100, "for the moment, (modulus) is limited to 255");
+
+  int Nchar = strlen (string);
+
+  int i;
+  int Nsum = 0;
+  for (i = 0; i < Nchar; i++) {
+    Nsum += (string[i] % modulus);
+  }
+  int value = Nsum % modulus;
+  return (value);
+}
