Index: /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/astrom_correction.c
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/astrom_correction.c	(revision 34866)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/astrom_correction.c	(revision 34866)
@@ -0,0 +1,95 @@
+# include "setastrom.h"
+
+// astrometry correction functions:
+// load the correction set from a file
+
+// the correction is saved as a set of splines, one per file extension
+// extensions have names of the form XYnn.Dx.Td
+
+// where nn = 00 - 77, the chip number
+// x is X or Y, the correction direction
+// d is 0 or 1, pre or post camera correction
+
+// the interpolating spline has valu
+typedef struct {
+  int Nknots;
+  opihi_flt *xk;
+  opihi_flt *yk;
+  opihi_flt *y2;
+  char *name;
+} Spline;
+
+int load_astrom_correction (char *filename) {
+
+  Header header;
+  Header theader;
+  FTable ftable;
+
+  FILE *f = NULL;
+
+  /* open file for input */
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't open file for read : %s\n", filename);
+    return FALSE;
+  }
+
+  // read the PHU header
+  if (!gfits_load_header (f, &header)) return (FALSE);
+  
+  int Nbytes = gfits_data_size (&header);
+  fseeko (f, Nbytes, SEEK_CUR);
+  // XXX gfits_free_header (&header);
+
+  ftable.header = &theader;
+
+  // we have a N-D array of splines:
+  // splineset[subset][dir][chip]
+  ALLOCATE (splineset, Spline ***, 2);
+  for (sub = 0; sub < 2; sub++) {
+    ALLOCATE (splineset[sub], Spline **, 2);
+    for (dir = 0; dir < 2; dir++) {
+      ALLOCATE (splineset[sub][dir], Spline *, 78);
+      for (chip = 0; chip < 78; chip ++) {
+	splineset[sub][dir][chip] = NULL;
+      }
+    }
+  }
+
+  for () {
+    /* load data for this header */
+    if (!gfits_load_header (f, &theader)) return (FALSE);
+    
+    if (!gfits_fread_ftable_data (f, &table, FALSE)) return (FALSE);
+    
+    if (!gfits_scan (header, "EXTNAME", "%s", 1, extname)) return (FALSE);
+
+    // figure out the chip ID, diretion, and sequence from the EXTNAME
+
+    int chip = XX;
+    int dir = XX;
+    int subset = XX;
+
+    splineset[sub][dir][chip] = CreateSpline (Nrow);
+
+    // XXX: need to handle case of spline data not existing...
+    
+    // need to create and assign to flat-field correction
+    double *xk = gfits_get_bintable_column_data (&theader, &ftable, "X_KNOT", type, &Nrow, &Ncol);
+    assert (!strcmp(type, "double"));
+    
+    // need to create and assign to flat-field correction
+    double *yk = gfits_get_bintable_column_data (&theader, &ftable, "Y_KNOT", type, &Nrow, &Ncol);
+    assert (!strcmp(type, "double"));
+    
+    // need to create and assign to flat-field correction
+    double *y2 = gfits_get_bintable_column_data (&theader, &ftable, "DY2_DX", type, &Nrow, &Ncol);
+    assert (!strcmp(type, "double"));
+    
+    splineset[sub][dir][chip]->xk = xk;
+    splineset[sub][dir][chip]->yk = yk;
+    splineset[sub][dir][chip]->y2 = y2;
+    
+  }
+  return (TRUE);
+}
Index: /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/initialize_setastrom.c
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/initialize_setastrom.c	(revision 34866)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/initialize_setastrom.c	(revision 34866)
@@ -0,0 +1,226 @@
+# include "setastrom.h"
+
+void usage_setastrom () {
+    fprintf (stderr, "USAGE: setastrom [options]\n");
+    fprintf (stderr, "  options:\n");
+    fprintf (stderr, "    -v : verbose mode\n");
+    fprintf (stderr, "    -update : actually write results to detections tables\n");
+    fprintf (stderr, "    -parallel : run in parallel mode\n");
+    fprintf (stderr, "    -h     : this help list\n");
+    fprintf (stderr, "    -help  : this help list\n");
+    fprintf (stderr, "    --h    : this help list\n");
+    fprintf (stderr, "    --help : this help list\n");
+    fprintf (stderr, "    Note that the dvo db can be specified by -D CATDIR (directory)\n");
+    exit (2);
+}
+
+void initialize_setastrom (int argc, char **argv) {
+
+  int N;
+  struct stat statbuffer;
+  char CatdirPhotcodeFile[256];
+
+  if ((N = get_argument (argc, argv, "-h"))) usage_setastrom();
+  if ((N = get_argument (argc, argv, "-help"))) usage_setastrom();
+  if ((N = get_argument (argc, argv, "--h"))) usage_setastrom();
+  if ((N = get_argument (argc, argv, "--help"))) usage_setastrom();
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args_setastrom (argc, argv);
+
+  if (stat (CATDIR, &statbuffer)) {
+    fprintf (stderr, "error accessing dvo database directory '%s'\n", CATDIR);
+    exit (1);
+  }
+
+  // load the photcode table
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, NULL, FALSE)) {
+    fprintf (stderr, "error loading photcode table %s\n", CatdirPhotcodeFile);
+    exit (1);
+  }
+}
+
+int args_setastrom (int argc, char **argv) {
+
+  int N;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  // XXX I want to avoid running this on all data all the time
+  // some options: gpc1 only (hardwired), require photcodes (fairly tedious),
+  // exclude some photcodes?
+  // XXX for now, hardwire gpc1 photcodes
+
+  PARALLEL = FALSE;
+  if ((N = get_argument (argc, argv, "-parallel"))) {
+    PARALLEL = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  // this is a test mode : rather than launching the remote jobs and waiting for completion,
+  // setastrom will simply list the remote command and wait for the user to signal completion
+  PARALLEL_MANUAL = FALSE;
+  if ((N = get_argument (argc, argv, "-parallel-manual"))) {
+    PARALLEL = TRUE; // -parallel-manual implies -parallel
+    PARALLEL_MANUAL = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  // this is a test mode : rather than launching the setastrom_client jobs remotely, they are 
+  // run in serial via 'system'
+  PARALLEL_SERIAL = FALSE;
+  if ((N = get_argument (argc, argv, "-parallel-serial"))) {
+    if (PARALLEL_MANUAL) {
+      fprintf (stderr, "ERROR: cannot mix -parallel-manual and -parallel-serial\n");
+      exit (1);
+    }
+    PARALLEL = TRUE; // -parallel-serial implies -parallel
+    PARALLEL_SERIAL = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  if (argc != 1) usage_setastrom();
+
+  return (TRUE);
+}
+
+void usage_setastrom_client () {
+  fprintf (stderr, "USAGE: setastrom_client -hostID (hostID) -catdir (catdir) -hostdir (hostdir) -images (images) [options]\n");
+  fprintf (stderr, "  options:\n");
+  fprintf (stderr, "    -v : verbose mode\n");
+  fprintf (stderr, "    -update : actually write results to detections tables\n");
+  exit (2);
+}
+
+void initialize_setastrom_client (int argc, char **argv) {
+
+  int N;
+  struct stat statbuffer;
+  char CatdirPhotcodeFile[256];
+
+  if ((N = get_argument (argc, argv, "-h"))) usage_setastrom_client();
+  if ((N = get_argument (argc, argv, "-help"))) usage_setastrom_client();
+  if ((N = get_argument (argc, argv, "--h"))) usage_setastrom_client();
+  if ((N = get_argument (argc, argv, "--help"))) usage_setastrom_client();
+
+  SetZeroPoint (25.0); // XXX is this needed?
+  args_setastrom_client (argc, argv);
+
+  if (stat (CATDIR, &statbuffer)) {
+    fprintf (stderr, "error accessing dvo database directory '%s'\n", CATDIR);
+    exit (1);
+  }
+
+  // load the photcode table : XXX needed?
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, NULL, FALSE)) {
+    fprintf (stderr, "error loading photcode table %s\n", CatdirPhotcodeFile);
+    exit (1);
+  }
+}
+
+int args_setastrom_client (int argc, char **argv) {
+
+  int N;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  HOST_ID = 0;
+  if ((N = get_argument (argc, argv, "-hostID"))) {
+    remove_argument (N, &argc, argv);
+    HOST_ID = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!HOST_ID) usage_setastrom_client();
+
+  HOSTDIR = NULL;
+  if ((N = get_argument (argc, argv, "-hostdir"))) {
+    remove_argument (N, &argc, argv);
+    HOSTDIR = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!HOSTDIR) usage_setastrom_client();
+
+  if ((N = get_argument (argc, argv, "-catdir"))) {
+    remove_argument (N, &argc, argv);
+    CATDIR = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!CATDIR) usage_setastrom_client();
+
+  IMAGES = NULL;
+  if ((N = get_argument (argc, argv, "-images"))) {
+    remove_argument (N, &argc, argv);
+    IMAGES = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!IMAGES) usage_setastrom_client();
+
+  if (argc != 1) usage_setastrom_client();
+  return (TRUE);
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char  *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  // force CATDIR to be absolute (so parallel mode will work)
+  char *tmpcatdir = NULL;
+  ALLOCATE (tmpcatdir, char, DVO_MAX_PATH);
+  GetConfig (config, "CATDIR",                 "%s",  0, tmpcatdir);
+  CATDIR = abspath (tmpcatdir, DVO_MAX_PATH);
+  free (tmpcatdir);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  free (config);
+  free (file);
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/setastrom.c
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/setastrom.c	(revision 34866)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/setastrom.c	(revision 34866)
@@ -0,0 +1,25 @@
+# include "setastrom.h"
+
+int main (int argc, char **argv) {
+
+  int status;
+  FITS_DB db;
+
+  /* get configuration info, args, lockfile */
+  initialize_setastrom (argc, argv);
+
+  load_correction ();
+
+  status = update_dvo_setastrom (subset, Nimage);
+
+  if (!status) exit (1);
+  exit (0);
+}
+  
+
+/* setastrom : set the posangle & pltscale for measurements in the db
+
+   ** load images
+   ** load catalogs
+   ** update detection (& averages?)
+ */
Index: /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/update_catalog_setastrom.c
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/update_catalog_setastrom.c	(revision 34866)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/update_catalog_setastrom.c	(revision 34866)
@@ -0,0 +1,50 @@
+# include "setastrom.h"
+
+// XXX this function is dependent in two ways on the specific numerical values of the photcodes
+// 1) the examined measurements are limited to GPC1 values based on the photcode range 10000 - 10600
+// 2) the chip ID is determined from the numerical value of the photcode (chip = photcode % 100)
+
+int update_catalog_setastrom (Catalog *catalog) {
+
+  off_t i, j, found;
+
+  int timeRef = somefunc("2011/05/11");
+
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+
+    // XXX only do GPC1 data for now
+    if (catalog[0].measure[i].photcode < 10000) continue;
+    if (catalog[0].measure[i].photcode > 10600) continue;
+      
+    double Xccd = catalog[0].measure[i].Xccd;
+    double Yccd = catalog[0].measure[i].Yccd;
+    double posAngle = FromShortDegrees(catalog[0].measure[i].posangle);
+    double pltScale = fabs(catalog[0].measure[i].pltscale);
+
+    // I need to know which chip we have.  use photcode assuming range
+    int chip = catalog[0].measure[i].photcode % 100;
+
+    // correction is in arcseconds
+    if (catalog[0].measure[i].t < timeRef) {
+      get_correction (0, chip, &dX, &dY);
+    } else {
+      get_correction (1, chip, &dX, &dY);
+    }
+
+    myAssert(!isfinite(catalog[0].measure[i].Xraw), "error: Xraw is not NAN, did we already correct?");
+    myAssert(!isfinite(catalog[0].measure[i].Yraw), "error: Yraw is not NAN, did we already correct?");
+    catalog[0].measure[i].Xraw = Xccd;
+    catalog[0].measure[i].Yraw = Yccd;
+
+    catalog[0].measure[i].Xccd = Xccd + dX / pltScale;
+    catalog[0].measure[i].Yccd = Yccd + dY / pltScale;
+
+    found ++;
+  }
+
+  if (found) {
+    fprintf (stderr, "found "OFF_T_FMT" matches\n", found);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/update_dvo_setastrom.c
===================================================================
--- /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/update_dvo_setastrom.c	(revision 34866)
+++ /branches/eam_branches/ipp-20121219/Ohana/src/uniphot/src/update_dvo_setastrom.c	(revision 34866)
@@ -0,0 +1,131 @@
+# include "setastrom.h"
+
+int update_dvo_setastrom () {
+
+  SkyRegion UserPatch;
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+  Catalog catalog;
+  off_t i, maxID, *index;
+
+  // load the current sky table (layout of all SkyRegions) 
+  sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, -1, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  if (PARALLEL && !HOST_ID) {
+    update_dvo_setastrom_parallel (sky);
+    return TRUE;
+  }
+
+  // determine the populated SkyRegions overlapping the requested area (default depth)
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  skylist = SkyListByPatch (sky, -1, &UserPatch);
+
+  // update measurements for each populated catalog
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // does this host ID match the desired location for the table?
+    if (!HostTableTestHost(skylist[0].regions[i], HOST_ID)) continue;
+
+    char localFilename[1024];
+    snprintf (localFilename, 1024, "%s/%s.cpt", HOSTDIR, skylist->regions[i]->name);
+
+    // set up the basic catalog info
+    catalog.filename  = HOST_ID ? localFilename : skylist[0].filename[i];
+    catalog.catformat = DVO_FORMAT_UNDEF; // not needed since we skip empty catalogs
+    catalog.catmode   = DVO_MODE_UNDEF;	  // not needed since we skip empty catalogs
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (!catalog.Naves_disk) {
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    update_catalog_setastrom (&catalog);
+
+    if (!UPDATE) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+    
+  XXX: update format here
+
+    if (VERBOSE) fprintf (stderr, "saving catalog %s\n", catalog.filename);
+    
+    dvo_catalog_save (&catalog, VERBOSE); 
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+  return (TRUE);
+}      
+
+# define DEBUG 1
+
+int update_dvo_setastrom_parallel (SkyTable *sky) {
+
+  // now launch the setastrom_client jobs to the parallel hosts
+
+  // load the list of hosts
+  HostTable *table = HostTableLoad (CATDIR, sky->hosts);
+
+  int i;
+  for (i = 0; i < table->Nhosts; i++) {
+
+    // ensure that the paths are absolute path names
+    char *tmppath = abspath (table->hosts[i].pathname, DVO_MAX_PATH);
+    free (table->hosts[i].pathname);
+    table->hosts[i].pathname = tmppath;
+
+    char command[1024];
+    snprintf (command, 1024, "setastrom_client -hostID %d -catdir %s -hostdir %s", 
+	      table->hosts[i].hostID, CATDIR, table->hosts[i].pathname);
+
+    fprintf (stderr, "command: %s\n", command);
+
+    char tmpline[1024];
+    if (VERBOSE)       { snprintf (tmpline, 1024, "%s -v",              command);                    strcpy (command, tmpline); }
+    if (UPDATE)        { snprintf (tmpline, 1024, "%s -update",         command); 		     strcpy (command, tmpline); }
+
+    if (PARALLEL_MANUAL) continue;
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running setastrom_client\n");
+	exit (2);
+      }
+    } else {
+      // launch the job on the remote machine (no handshake)
+      int errorInfo = 0;
+      int pid = rconnect ("ssh", table->hosts[i].hostname, command, table->hosts[i].stdio, &errorInfo, FALSE);
+      if (!pid) {
+	if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", table->hosts[i].hostname, errorInfo);
+	exit (1);
+      }
+      table->hosts[i].pid = pid; // save for future reference
+    }
+  }
+
+  // wait for the remote jobs to be completed
+  if (PARALLEL_MANUAL) {
+    fprintf (stderr, "run the setastrom_client commands above.  when these are done, hit return\n");
+    getchar();
+  }
+  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
+    int status = HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+    if (!status) return FALSE;
+  }
+
+  return (TRUE);
+}      
