Index: /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/include/dvomerge.h	(revision 37584)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/include/dvomerge.h	(revision 37585)
@@ -153,4 +153,9 @@
 Lensing   *sort_lensing     	  PROTO((Average *average, off_t Naverage, Lensing *lensing, off_t Nlensing, off_t *next));
 
+off_t 	  *build_starpar_links    PROTO((Average *average, off_t Naverage, StarPar *starpar, off_t Nstarpar));
+off_t 	  *init_starpar_links     PROTO((Average *average, off_t Naverage, StarPar *starpar, off_t Nstarpar));
+int   	   add_star_link     	  PROTO((Average *average, off_t *next, off_t Nstarpar, off_t NSTARPAR));
+StarPar   *sort_starpar     	  PROTO((Average *average, off_t Naverage, StarPar *starpar, off_t Nstarpar, off_t *next));
+
 off_t 	  *init_missing_links     PROTO((Average *average, off_t Naverage, Missing *missing, off_t Nmissing));
 int   	   add_miss_link     	  PROTO((Average *average, off_t *next, off_t Nmissing));
Index: /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/LoadCatalog.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/LoadCatalog.c	(revision 37584)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/LoadCatalog.c	(revision 37585)
@@ -8,5 +8,5 @@
 
     // always load all of the data (if any exists)
-    catalog[0].catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF | LOAD_LENSING | LOAD_LENSOBJ;
+    catalog[0].catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF | LOAD_LENSING | LOAD_LENSOBJ | LOAD_STARPAR;
 
     catalog[0].catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
Index: /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/build_links.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/build_links.c	(revision 37584)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/build_links.c	(revision 37585)
@@ -377,3 +377,153 @@
 }
 
-
+/********  StarPar ********************************************************************************/
+
+/* build the initial links assuming the table is sorted, 
+   not partial, and has a correct set of average[].starparOffset,Nstarpar values */
+off_t *init_starpar_links (Average *average, off_t Naverage, StarPar *starpar, off_t Nstarpar) {
+
+  off_t i, j, N;
+  off_t *next_star;
+
+  N = 0;
+
+  ALLOCATE (next_star, off_t, Nstarpar);
+  for (i = 0; i < Naverage; i++) {
+    if (!average[i].Nstarpar) continue;
+    for (j = 0; j < average[i].Nstarpar - 1; j++, N++) {
+      next_star[N] = N + 1;
+      if (N >= Nstarpar) {
+	fprintf (stderr, "WARNING: N out of bounds (1)\n");
+      }
+    }
+    next_star[N] = -1;
+    if (N >= Nstarpar) {
+      fprintf (stderr, "WARNING: N out of bounds (2)\n");
+    }
+
+    if (N >= Nstarpar) {
+      fprintf (stderr, "overflow in init_starpar_links\n");
+      abort ();
+    }
+    N++;
+  }
+  return (next_star);
+}
+
+/* construct starpar links which are valid FOR THIS LOAD
+ * - if we have a full load, we will get links which can
+ *   be used by other programs (eg, relphot, etc)
+ * - if we have a partial load, the links are only valid
+ *   for that partial load
+ */ 
+
+off_t *build_starpar_links (Average *average, off_t Naverage, StarPar *starpar, off_t Nstarpar) {
+
+  off_t i, m, k, Nm, averef;
+  off_t *next_star;
+
+  ALLOCATE (next_star, off_t, Nstarpar);
+
+  /* reset the Nm, offset values for average */
+  for (i = 0; i < Naverage; i++) {
+    average[i].starparOffset = -1;
+    average[i].Nstarpar     =  0;
+  }
+
+  for (Nm = 0; Nm < Nstarpar; Nm++) {
+    averef = starpar[Nm].averef;
+    m = average[averef].starparOffset;  
+    next_star[Nm] = -1;
+
+    if (m == -1) { /* no links yet for source */
+      average[averef].starparOffset = Nm;
+      average[averef].Nstarpar     = 1;
+      continue;
+    }
+
+    for (k = 0; next_star[m] != -1; k++) {
+      m = next_star[m];
+      if (m >= Nstarpar) {
+	fprintf (stderr, "WARNING: m out of bounds (1)\n");
+      }
+    }
+
+    average[averef].Nstarpar = k + 2;
+    next_star[m] = Nm;
+    if (m >= Nstarpar) {
+      fprintf (stderr, "WARNING: m out of bounds (2)\n");
+    }
+  }
+  return (next_star);
+}
+
+/* average[].starparOffset, average[].Nstarpar are valid within an addstar run */
+int add_star_link (Average *average, off_t *next_star, off_t Nstarpar, off_t NSTARPAR) {
+
+  off_t k, m;
+
+  /* if we have trouble, check validity of next_star[m] : m < Nstarpar */
+  m = average[0].starparOffset;  
+
+  for (k = 0; k < average[0].Nstarpar - 1; k++)  {
+    m = next_star[m];
+    if (m >= NSTARPAR) {
+      fprintf (stderr, "WARNING: m out of bounds (3)\n");
+    }
+  }
+
+  /* set up references */
+  next_star[Nstarpar] = -1;
+  if (Nstarpar >= NSTARPAR) {
+    fprintf (stderr, "WARNING: Nstarpar out of bounds (1)\n");
+  }
+
+  if (m == -1) {
+    average[0].starparOffset = Nstarpar;
+  } else {
+    next_star[m] = Nstarpar;
+    if (m >= NSTARPAR) {
+      fprintf (stderr, "WARNING: m out of bounds (4)\n");
+    }
+  }
+
+  return (TRUE);
+}
+
+StarPar *sort_starpar (Average *average, off_t Naverage, StarPar *starpar, off_t Nstarpar, off_t *next_star) {
+
+  off_t i, k, n, np, N;
+  StarPar *tmpstarpar;
+
+  /*
+  for (i = 0; i < Naverage; i++) {
+    if (average[i].Nstarpar != 4) {
+      fprintf (stderr, "check %d %d %d\n", (int) i, (int) average[i].Nstarpar, (int) average[i].starparOffset);
+    }
+  }
+  */
+
+  /* fix order of StarPar (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpstarpar, StarPar, Nstarpar);
+  for (i = 0; i < Naverage; i++) {
+    if (!average[i].Nstarpar) continue;
+    n = average[i].starparOffset;
+    average[i].starparOffset = N;
+    for (k = 0; k < average[i].Nstarpar; k++, N++) {
+      if (n == -1) {
+	fprintf (stderr, "entry after %d has a problem\n", (int) np);
+	abort();
+      }
+      tmpstarpar[N] = starpar[n]; 
+      if (starpar[n].averef != i) abort();
+      tmpstarpar[N].averef = i;
+      np = n;
+      n = next_star[n];
+    }
+  }
+  free (starpar);
+  return (tmpstarpar);
+}
+
+
Index: /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/merge_catalogs_new.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/merge_catalogs_new.c	(revision 37584)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/merge_catalogs_new.c	(revision 37585)
@@ -11,5 +11,5 @@
   
   off_t i, j, offset;
-  off_t NAVERAGE, NMEASURE, NLENSING, Naverage, Nmeasure, Nlensing, NsecfiltIn, NsecfiltOut, Nm;
+  off_t NAVERAGE, NMEASURE, NLENSING, NSTARPAR, Naverage, Nmeasure, Nlensing, Nstarpar, NsecfiltIn, NsecfiltOut, Nm;
 
   Naverage = output[0].Naverage;
@@ -78,4 +78,20 @@
       output[0].average[Naverage].Nlensing = Nm;
 
+      Nm = 0;
+      for (j = 0; j < input[0].average[i].Nstarpar; j++) {
+	  offset = input[0].average[i].starparOffset + j;
+
+	  output[0].starpar[Nstarpar] = input[0].starpar[offset];
+	  output[0].starpar[Nstarpar].averef = Naverage;
+
+	  Nstarpar ++;
+	  Nm ++;
+	  if (Nstarpar == NSTARPAR) {
+	      NSTARPAR += 1000;
+	      REALLOCATE (output[0].starpar, StarPar, NSTARPAR);
+	  }
+      }
+      output[0].average[Naverage].Nstarpar = Nm;
+
       Naverage ++;
       if (Naverage == NAVERAGE) {
@@ -88,7 +104,9 @@
   REALLOCATE (output[0].measure, Measure, MAX (Nmeasure, 1));
   REALLOCATE (output[0].lensing, Lensing, MAX (Nlensing, 1));
+  REALLOCATE (output[0].starpar, StarPar, MAX (Nstarpar, 1));
   REALLOCATE (output[0].secfilt, SecFilt, NsecfiltOut*MAX (Naverage, 1));
   output[0].Naverage = Naverage;
   output[0].Nlensing = Nlensing;
+  output[0].Nstarpar = Nstarpar;
   output[0].Nsecf_mem = Naverage * NsecfiltOut;
 
Index: /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/merge_catalogs_old.c
===================================================================
--- /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/merge_catalogs_old.c	(revision 37584)
+++ /branches/eam_branches/ipp-20140904/Ohana/src/dvomerge/src/merge_catalogs_old.c	(revision 37585)
@@ -14,6 +14,6 @@
   double *X1, *Y1, *X2, *Y2;
   double dX, dY, dR;
-  off_t *N1, *N2, *next_meas, *next_lens;
-  off_t Nave, NAVE, Nmeas, NMEAS, Nmatch, Nlens, NLENS;
+  off_t *N1, *N2, *next_meas, *next_lens, *next_star;
+  off_t Nave, NAVE, Nmeas, NMEAS, Nmatch, Nlens, NLENS, Nstar, NSTAR;
   int NsecfiltIn;
   int NsecfiltOut;
@@ -53,4 +53,5 @@
   NMEAS = Nmeas = output[0].Nmeasure;
   NLENS = Nlens = output[0].Nlensing;
+  NSTAR = Nstar = output[0].Nstarpar;
 
   // current max obj ID for this catalog
@@ -116,7 +117,9 @@
     next_meas = init_measure_links (output[0].average, Nave, output[0].measure, Nmeas);
     next_lens = init_lensing_links (output[0].average, Nave, output[0].lensing, Nlens);
+    next_star = init_starpar_links (output[0].average, Nave, output[0].starpar, Nstar);
   } else {
     next_meas = build_measure_links (output[0].average, Nave, output[0].measure, Nmeas);
     next_lens = build_lensing_links (output[0].average, Nave, output[0].lensing, Nlens);
+    next_star = build_starpar_links (output[0].average, Nave, output[0].starpar, Nstar);
   }    
 
@@ -180,8 +183,13 @@
       REALLOCATE (output[0].measure, Measure, NMEAS);
     }
-    if (Nlens + input[0].average[N].Nmeasure >= NLENS) {
-      NLENS = Nlens + input[0].average[N].Nmeasure + 1000;
+    if (Nlens + input[0].average[N].Nlensing >= NLENS) {
+      NLENS = Nlens + input[0].average[N].Nlensing + 1000;
       REALLOCATE (next_lens, off_t, NLENS);
       REALLOCATE (output[0].lensing, Lensing, NLENS);
+    }
+    if (Nstar + input[0].average[N].Nstarpar >= NSTAR) {
+      NSTAR = Nstar + input[0].average[N].Nstarpar + 1000;
+      REALLOCATE (next_star, off_t, NSTAR);
+      REALLOCATE (output[0].starpar, StarPar, NSTAR);
     }
 
@@ -270,4 +278,22 @@
     }
 
+    // if lensing measurements exist, add them too
+    if (output[0].starpar) {
+      for (Nin = 0; Nin < input[0].average[N].Nstarpar; Nin++) {
+	/* add to end of lensing list */
+	add_star_link (&output[0].average[n], next_star, Nstar, NSTAR);
+	
+	// set the new starpar
+	off_t staroff = input[0].average[N].starparOffset + Nin;
+	output[0].starpar[Nstar] = input[0].starpar[staroff];
+
+	output[0].starpar[Nstar].averef   = n;
+	output[0].starpar[Nstar].objID    = output[0].average[n].objID;
+	output[0].starpar[Nstar].catID    = output[0].catID;
+	output[0].average[n].Nstarpar ++;
+	Nstar ++;
+      }
+    }
+
     // update the average properties to reflect the incoming entries:
     // if the original value is NAN but the input value is not, accept the input:
@@ -315,4 +341,9 @@
       REALLOCATE (output[0].lensing, Lensing, NLENS);
     }
+    if (Nstar + input[0].average[N].Nstarpar >= NSTAR) {
+      NSTAR = Nstar + input[0].average[N].Nstarpar + 1000;
+      REALLOCATE (next_star, off_t, NSTAR);
+      REALLOCATE (output[0].starpar, StarPar, NSTAR);
+    }
     if (Nave >= NAVE) {
       NAVE = Nave + 1000;
@@ -412,4 +443,30 @@
     }
 
+    /** add starpar for this input average object **/
+    if (output[0].starpar) {
+      output[0].average[Nave].starparOffset  = Nstar;
+      for (Nin = 0; Nin < input[0].average[N].Nstarpar; Nin ++) {
+	// supply the starpar values from this detection
+	off_t staroff = input[0].average[N].starparOffset + Nin;
+	output[0].starpar[Nstar]           = input[0].starpar[staroff];
+
+	// the following starpar elements cannot be set until here:
+	output[0].starpar[Nstar].averef   = Nave;
+	output[0].starpar[Nstar].objID    = output[0].average[Nave].objID;
+	output[0].starpar[Nstar].catID    = output[0].catID;
+
+	// as we add starpar, update Nstarpar to match
+	output[0].average[Nave].Nstarpar ++;
+
+	/* we set next[Nstar] to -1 here, and update correctly below */
+	next_star[Nstar] = -1;
+	Nstar ++;
+      }
+      int Ngroup = input[0].average[N].Nstarpar;
+      for (j = 0; j < Ngroup - 1; j++) {
+	next_star[Nstar - Ngroup + j] = Nstar - Ngroup + j + 1;
+      }
+    }
+
     Nave ++;
   }
@@ -420,4 +477,5 @@
   REALLOCATE (output[0].measure, Measure, Nmeas);
   REALLOCATE (output[0].lensing, Lensing, Nlens);
+  REALLOCATE (output[0].starpar, StarPar, Nstar);
  
 # define NOSORT 0
@@ -428,4 +486,5 @@
     output[0].measure = sort_measure (output[0].average, Nave, output[0].measure, Nmeas, next_meas);
     output[0].lensing = sort_lensing (output[0].average, Nave, output[0].lensing, Nlens, next_lens);
+    output[0].starpar = sort_starpar (output[0].average, Nave, output[0].starpar, Nstar, next_star);
   }
 
@@ -444,4 +503,5 @@
   output[0].Nmeasure = Nmeas;
   output[0].Nlensing = Nlens;
+  output[0].Nstarpar = Nstar;
   output[0].Nsecf_mem = Nave*NsecfiltOut;
   if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas, Nlens: "OFF_T_FMT" "OFF_T_FMT" "OFF_T_FMT" "OFF_T_FMT", ("OFF_T_FMT" matches)\n",  Nstars,  Nave,  Nmeas,  Nlens, Nmatch);
@@ -449,4 +509,5 @@
   free (next_meas);
   free (next_lens);
+  free (next_star);
 
   free (X2);
