Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/doc/parallel.txt
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/doc/parallel.txt	(revision 36516)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/doc/parallel.txt	(revision 36517)
@@ -1,2 +1,9 @@
+
+2014.02.15
+
+Nearly done with the relphot mods.  some outstanding questions;
+
+ * image vs mosaic?
+ * how do decide which images need to be shared?
 
 2014.02.14
@@ -22,5 +29,5 @@
  * from which hosts do I slurp mean mags?
  o function to merge a new meanmag array into the existing one
- * how to go from (objID,catID) to a given catalog[i].average[j]
+ o how to go from (objID,catID) to a given catalog[i].average[j]
 
 2014.02.06
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/ImageMagIO.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/ImageMagIO.c	(revision 36517)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/ImageMagIO.c	(revision 36517)
@@ -0,0 +1,206 @@
+# include "relphot.h"
+
+# define GET_COLUMN(OUT,NAME,TYPE) \
+  TYPE *OUT = gfits_get_bintable_column_data (&theader, &ftable, NAME, type, &Nrow, &Ncol); \
+  myAssert (!strcmp(type, #TYPE), "wrong column type");
+
+// this is nearly identical to the one in 'uniphot/src' used by setphot / setphot_client.
+// Here, we use a handful of different columns (if not, we could move to libdvo)
+ImageMag *ImageMagLoad(char *filename, off_t *nimage_mags) {
+
+  int i, Ncol;
+  off_t Nrow;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  *nimage_mags = 0;
+  ImageMag *image_mags = NULL;
+
+  FILE *f = fopen (filename, "r");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open image subset file %s\n", filename);
+    return NULL;
+  }
+
+  /* load in PHU segment (ignore) */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset header\n");
+    fclose (f);
+    return NULL;
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image subset matrix\n");
+    gfits_free_header (&header);
+    fclose (f);
+    return NULL;
+  }
+
+  ftable.header = &theader;
+
+  // load data for this header 
+  if (!gfits_load_header (f, &theader)) {
+    fclose (f);
+    return NULL;
+  }
+
+  // read the fits table bytes
+  if (!gfits_fread_ftable_data (f, &ftable, FALSE)) {
+    fclose (f);
+    return (NULL);
+  }
+  fclose (f);
+
+  // a bit annoying : we read the entire block of data, then extract the columns, then set the image structure values.
+  // this means I need 3 copies in memory at some point.  ugh.
+
+  char type[16];
+
+  GET_COLUMN (Mcal,              "MCAL",           float);
+  GET_COLUMN (dMcal,             "MCAL_ERR",       float);
+  GET_COLUMN (dMagSys,           "MCAL_SYSERR",    float);
+  GET_COLUMN (Xm,                "CHISQ",          float);
+  GET_COLUMN (nFitPhotom,        "NFIT",             int);
+  GET_COLUMN (flags,             "FLAGS",            int);
+  GET_COLUMN (ubercalDist,       "UDIST",            int);
+
+  ALLOCATE (image_mags, ImageMag, Nrow);
+  for (i = 0; i < Nrow; i++) {
+    image_mag[i].Mcal                      = Mcal       [i];
+    image_mag[i].dMcal                     = dMcal      [i];
+    image_mag[i].dMagSys                   = dMagSys    [i];
+    image_mag[i].Xm                        = Xm         [i];
+    image_mag[i].nFitPhotom                = nFitPhotom [i];
+    image_mag[i].flags                     = flags      [i];
+    image_mag[i].ubercalDist               = ubercalDist[i];
+  }
+  fprintf (stderr, "loaded data for %lld images\n", (long long) Nrow);
+
+  free (Mcal       );
+  free (dMcal      );
+  free (dMagSys    );
+  free (Xm         );
+  free (nFitPhotom );
+  free (flags      );
+  free (ubercalDist);
+
+  *nimage_mag = Nrow;
+  return image_mag;
+}
+
+// STATUS is value expected for success
+# define CHECK_STATUS(STATUS,MSG,...)                                   \
+  if (!(STATUS)) {                                                      \
+    fprintf (stderr, MSG, __VA_ARGS__);                                 \
+    return FALSE;                                                       \
+  }
+
+int ImageMagsSave(char *filename, ImageMags *image_mags, off_t Nimage_mags) {
+
+  int i;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  gfits_create_table_header (&theader, "BINTABLE", "IMAGE_MAGS");
+
+  gfits_define_bintable_column (&theader, "E", "MCAL",           "cal offset", "magnitudes", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "MCAL_ERR",       "cal error", "magnitudes", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "MCAL_SYSERR",    "systematic error", "magnitudes", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "CHISQ",          "cal chisq", "unitless", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "NFIT",           "number of fitted stars", "unitless", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "FLAGS",          "analysis flags", "unitless", 1.0, 0.0);
+  gfits_define_bintable_column (&theader, "E", "UDIST",          "distance to ubercal images", "images", 1.0, 0.0);
+
+  // generate the output array that carries the data
+  gfits_create_table (&theader, &ftable);
+
+  float *Mcal        ;
+  float *dMcal       ;
+  float *dMagSys     ;
+  float *Xm          ;
+  int   *nFitPhotom  ;
+  int   *flags       ;
+  int   *ubercalDist ;
+
+  // create intermediate storage arrays
+  ALLOCATE (Mcal        ,         float,          Nimage_mags);
+  ALLOCATE (dMcal       ,         float,          Nimage_mags);
+  ALLOCATE (dMagSys     ,         float,          Nimage_mags);
+  ALLOCATE (Xm          ,         float,          Nimage_mags);
+  ALLOCATE (nFitPhotom  ,           int,          Nimage_mags);
+  ALLOCATE (flags       ,           int,          Nimage_mags);
+  ALLOCATE (ubercalDist ,           int,          Nimage_mags);
+
+  // assign the storage arrays
+  for (i = 0; i < Nimage_mags; i++) {
+    Mcal       [i]   = image_mag[i].Mcal       ;
+    dMcal      [i]   = image_mag[i].dMcal      ;
+    dMagSys    [i]   = image_mag[i].dMagSys    ;
+    Xm         [i]   = image_mag[i].Xm         ;
+    nFitPhotom [i]   = image_mag[i].nFitPhotom ;
+    flags      [i]   = image_mag[i].flags      ;
+    ubercalDist[i]   = image_mag[i].ubercalDist;
+  }
+
+  // add the columns to the output array
+  gfits_set_bintable_column (&theader, &ftable, "MCAL",           Mcal       ,         Nimage_mags);
+  gfits_set_bintable_column (&theader, &ftable, "MCAL_ERR",       dMcal      ,         Nimage_mags);
+  gfits_set_bintable_column (&theader, &ftable, "MCAL_SYSERR",    dMagSys    ,         Nimage_mags);
+  gfits_set_bintable_column (&theader, &ftable, "CHISQ",          Xm         ,         Nimage_mags);
+  gfits_set_bintable_column (&theader, &ftable, "NFIT",           nFitPhotom ,         Nimage_mags);
+  gfits_set_bintable_column (&theader, &ftable, "FLAGS",          flags      ,         Nimage_mags);
+  gfits_set_bintable_column (&theader, &ftable, "UDIST",          ubercalDist,         Nimage_mags);
+
+  free (Mcal       );
+  free (dMcal      );
+  free (dMagSys    );
+  free (Xm         );
+  free (nFitPhotom );
+  free (flags      );
+  free (ubercalDist);
+
+  FILE *f = fopen (filename, "w");
+  if (!f) {
+    fprintf (stderr, "ERROR: cannot open image_mag file for output %s\n", filename);
+    return FALSE;
+  }
+
+  int status;
+  status = gfits_fwrite_header  (f, &header);
+  CHECK_STATUS (status, "ERROR: cannot write header for image_mags %s\n", filename);
+
+  status = gfits_fwrite_matrix  (f, &matrix);
+  CHECK_STATUS (status, "ERROR: cannot write matrix for image_mags %s\n", filename);
+
+  status = gfits_fwrite_Theader (f, &theader);
+  CHECK_STATUS (status, "ERROR: cannot write table header for image_mags %s\n", filename);
+
+  status = gfits_fwrite_table  (f, &ftable);
+  CHECK_STATUS (status, "ERROR: cannot write table data for image_mags %s\n", filename);
+
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+  gfits_free_table (&ftable);
+
+  int fd = fileno (f);
+
+  status = fflush (f);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image_mags %s\n", filename);
+
+  status = fsync (fd);
+  CHECK_STATUS (!status, "ERROR: cannot flush file image_mags %s\n", filename);
+
+  status = fclose (f);
+  CHECK_STATUS (!status, "ERROR: problem closing image_mags file %s\n", filename);
+
+  return TRUE;
+}
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/indexCatalog.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/indexCatalog.c	(revision 36516)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/indexCatalog.c	(revision 36517)
@@ -1,8 +1,55 @@
 # include "relphot.h"
+
+static int  *catIDseq = NULL;
+static int **objIDseq = NULL;
 
 int indexCatalogs (catalog, Ncatalog) {
 
-  // do I know 
+  // find the max value of catID
+  int catIDmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    catIDmax = MAX (catalog[i].catID, catIDmax);
+  }
+
+  ALLOCATE (catIDseq, int, catIDmax + 1);
+  for (i = 0; i < catIDmax + 1; i++) {
+    catIDseq[i] = -1;
+  }
+
+  for (i = 0; i < Ncatalog; i++) {
+    int catID = catalog[i].catID;
+    catIDseq[catID] = i;
+  }
   
-  
+  ALLOCATE (objIDseq, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    int objIDmax = 0;
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      objIDmax = MAX (catalog[i].average[j].objID, objIDmax);
+    }
+
+    ALLOCATE (objIDseq[i], int, objIDmax + 1);
+    for (j = 0; j < objIDmax + 1; j++) {
+      objIDseq[i][j] = -1;
+    }
+
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      int objID = catalog[i].average[j].objID;
+      objIDseq[i][objID] = j;
+    }
+  }
+  return TRUE;
 }
+
+int catID_and_objID_to_seq (int catID, int objID, *catSeq, *objSeq) {
+
+  int cat = catIDseq[catID];
+  if (cat < 1) return FALSE;
+
+  int obj = objIDseq[cat][objID];
+  if (obj < 1) return FALSE;
+
+  *catSeq = cat;
+  *objSeq = obj;
+  return TRUE;
+}
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_image_mags.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_image_mags.c	(revision 36516)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_image_mags.c	(revision 36517)
@@ -3,24 +3,23 @@
 // we are sharing image calibrations mags for all images which (a) I own and (b) which have unowned detections
 
-// XXX Image vs Mosaic...
+# define D_NIMAGEMAGS 1000
 int share_image_mags (RegionHostTable *regionHosts, int nloop) {
 
-  Image *images = get_images (&Nimages);
+  Image *images = getimages (&Nimages, NULL);
 
+  off_t Nimage_mags = 0;
+  off_t NIMAGE_MAGS = D_NIMAGEMAGS;
+  
   ImageMag *image_mags = NULL;
   ALLOCATE (image_mags, ImageMag, NIMAGE_MAGS);
 
   for (i = 0; i < Nimages; i++) {
-    
-    // XXX do I need to test the center coordinates?
-
-    // does this object have missing detections (does someone else need it?)
-    // XXX : sky objects without missing detections
+    // XXX does this image have missing detections (does someone else need it?)
     if (imageExtra[i].Nmiss == 0) continue;
     
-    image_mags[Nimage_mags] = something(image[i]);
+    set_image_mags (&image_mags[Nimage_mags], &images[i]);
     Nimage_mags ++;
 
-    // check realloc..
+    CHECK_REALLOCATE (image_mags, ImageMag, NIMAGE_MAGS, Nimage_mags, D_NIMAGEMAGS);
   }
 
@@ -38,12 +37,15 @@
 }
 
-int slurp_image_mags (Catalog *catalog, int Ncatalog, RegionHostTable *regionHosts, int nloop) {
+int slurp_image_mags (RegionHostTable *regionHosts, int nloop) {
 
+  Image *getimages (&Nimage, NULL);
+
+  int Nimage_mags = 0;
   ImageMag *image_mags = NULL;
-  ALLOCATE (image_mags, ImageMag, NIMAGE_MAGS);
+  ALLOCATE (image_mags, ImageMag, 1);
 
   for (i = 0; i < Nhost; i++) {
-    if (not_neighbor(host[i])) continue;
-    // XXX skip regions->hosts[i].hostID == REGION_HOST_ID
+    if (regionHosts->hosts.hostsID == REGION_HOST_ID) continue;
+    // XXX add neighbor check? : if (not_neighbor(host[i])) continue;
 
     check_imsync_file (regionHosts->hosts[i].hostname, nloop);
@@ -51,5 +53,5 @@
     char filename[1024];
     snprintf (filename, 1024, "%s/%s.imagemags.fits", CATDIR, regionHosts->hosts[i].hostname);
-    image_mags_subset = LoadImageMags (host[i], &Nsubset);
+    ImageMag *image_mags_subset = ImageMagLoad (host[i], &Nsubset);
 
     image_mags = merge_image_mags (image_mags, &Nimage_mags, image_mags_subset, Nsubset);
@@ -57,6 +59,16 @@
 
   for (i = 0; i < Nimage_mags; i++) {
-    seq = Image_ID_to_seq (image_mags[i].ID);
-    image[seq].mag = image_mags[i].mag;
+    seq = getImageByID (image_mags[i].ID);
+    if (seq < 0) {
+      // XXX is this a problem? (no, other hosts don't know which images I own)
+      continue;
+    }
+    image[seq].Mcal  	   = image_mags[i].Mcal;
+    image[seq].dMcal  	   = image_mags[i].dMcal;
+    image[seq].dMagSys	   = image_mags[i].dMagSys;
+    image[seq].Xm  	   = image_mags[i].Xm;
+    image[seq].nFitPhotom  = image_mags[i].nFitPhotom;
+    image[seq].flags 	   = image_mags[i].flags;
+    image[seq].ubercalDist = image_mags[i].ubercalDist;
   }
 }
@@ -69,5 +81,4 @@
   sprintf (filename, "%s/%s.image.sync", CATDIR, hostname);
 
-  // XXX I need a rule to generate the filename for each host
   FILE *f = NULL; 
 
@@ -115,2 +126,35 @@
   return TRUE;
 }
+
+int clear_imsync_file (char *hostname) {
+
+  char filename[1024];
+  sprintf (filename, "%s/%s.image.sync", CATDIR, hostname);
+
+  // delete file contents
+  truncate (filename, 0);
+
+  return TRUE;
+}
+
+int set_image_mags (ImageMag *image_mags, Image *image) {
+
+  image_mags->M  = image->Mcal;
+
+  return TRUE;
+}
+
+ImageMag *merge_image_mags (ImageMag *target, int *ntarget, ImageMag *source, int Nsource) {
+
+  REALLOCATE (target, ImageMag, *ntarget + Nsource);
+  for (i = 0; i < Nsource; i++) {
+    int n = i + *ntarget;
+    target[n] = source[i];
+  }
+  
+  free (source);
+
+  *ntarget += Nsource;
+  return (target);
+}
+
Index: /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_mean_mags.c
===================================================================
--- /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_mean_mags.c	(revision 36516)
+++ /branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/share_mean_mags.c	(revision 36517)
@@ -80,7 +80,8 @@
 
     // set the mean mag
-    // XXX I need to figure out how to go from catID,objID to catSeq,objSeq
-    catSeq = catalog_ID_to_seq (catID);
-    objSeq = object_ID_to_seq (catID, objID);
+    if (!catID_and_objID_to_seq (catID, objID, &catSeq, &objSeq)) {
+	// XXX what should I do if this does not match?
+	continue;
+    }
 
     Nsecfit = photcode_to_secfilt (meanmags[i].photcode);
@@ -123,4 +124,15 @@
     return TRUE;
   }
+}
+
+int clear_sync_file (char *hostname) {
+
+  char filename[1024];
+  sprintf (filename, "%s/%s.meanmags.sync", CATDIR, hostname);
+
+  // delete file contents
+  truncate (filename, 0);
+
+  return TRUE;
 }
 
