Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/Makefile
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/Makefile	(revision 41800)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/Makefile	(revision 41802)
@@ -1,3 +1,3 @@
-default: uniphot setphot setphot_client setfwhm setposangle setposangle_client setastrom setastrom_client setgalmodel setgalmodel_client fiximids fiximids_client fixstkids fixstkids_client ckids ckids_client
+default: uniphot setphot setphot_client setfwhm setposangle setposangle_client setastrom setastrom_client setgalmodel setgalmodel_client fixhsc fixhsc_client fiximids fiximids_client fixstkids fixstkids_client ckids ckids_client
 
 help:
@@ -28,4 +28,6 @@
 setgalmodel: $(BIN)/setgalmodel.$(ARCH)
 setgalmodel_client: $(BIN)/setgalmodel_client.$(ARCH)
+fixhsc: $(BIN)/fixhsc.$(ARCH)
+fixhsc_client: $(BIN)/fixhsc_client.$(ARCH)
 fiximids: $(BIN)/fiximids.$(ARCH)
 fiximids_client: $(BIN)/fiximids_client.$(ARCH)
@@ -35,5 +37,5 @@
 ckids_client: $(BIN)/ckids_client.$(ARCH)
 
-install: $(DESTBIN)/uniphot $(DESTBIN)/setfwhm $(DESTBIN)/setphot $(DESTBIN)/setphot_client $(DESTBIN)/setposangle $(DESTBIN)/setposangle_client $(DESTBIN)/setastrom $(DESTBIN)/setastrom_client $(DESTBIN)/setgalmodel $(DESTBIN)/setgalmodel_client $(DESTBIN)/fiximids $(DESTBIN)/fiximids_client $(DESTBIN)/fixstkids $(DESTBIN)/fixstkids_client $(DESTBIN)/ckids $(DESTBIN)/ckids_client
+install: $(DESTBIN)/uniphot $(DESTBIN)/setfwhm $(DESTBIN)/setphot $(DESTBIN)/setphot_client $(DESTBIN)/setposangle $(DESTBIN)/setposangle_client $(DESTBIN)/setastrom $(DESTBIN)/setastrom_client $(DESTBIN)/setgalmodel $(DESTBIN)/setgalmodel_client $(DESTBIN)/fixhsc $(DESTBIN)/fixhsc_client $(DESTBIN)/fiximids $(DESTBIN)/fiximids_client $(DESTBIN)/fixstkids $(DESTBIN)/fixstkids_client $(DESTBIN)/ckids $(DESTBIN)/ckids_client
 
 UNIPHOT = \
@@ -202,4 +204,30 @@
 $(BIN)/setfwhm.$(ARCH): $(SETFWHM)
 
+FIXHSC = \
+$(SRC)/fixhsc.$(ARCH).o	         \
+$(SRC)/initialize_fixhsc.$(ARCH).o     \
+$(SRC)/load_images_fixhsc.$(ARCH).o    \
+$(SRC)/load_rules_fixhsc.$(ARCH).o    \
+$(SRC)/update_dvo_fixhsc.$(ARCH).o     \
+$(SRC)/update_catalog_fixhsc.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o	         \
+$(SRC)/Shutdown.$(ARCH).o	    
+
+$(FIXHSC): $(INC)/fixhsc.h
+$(BIN)/fixhsc.$(ARCH): $(FIXHSC)
+
+FIXHSC_CLIENT = \
+$(SRC)/fixhsc_client.$(ARCH).o	 \
+$(SRC)/initialize_fixhsc.$(ARCH).o     \
+$(SRC)/load_images_fixhsc.$(ARCH).o    \
+$(SRC)/load_rules_fixhsc.$(ARCH).o    \
+$(SRC)/update_dvo_fixhsc.$(ARCH).o     \
+$(SRC)/update_catalog_fixhsc.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o	         \
+$(SRC)/Shutdown.$(ARCH).o
+
+$(FIXHSC_CLIENT): $(INC)/fixhsc.h
+$(BIN)/fixhsc_client.$(ARCH): $(FIXHSC_CLIENT)
+
 FIXIMIDS = \
 $(SRC)/fiximids.$(ARCH).o	         \
Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/include/fixhsc.h
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/include/fixhsc.h	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/include/fixhsc.h	(revision 41802)
@@ -0,0 +1,42 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+
+/* global variables set in parameter file */
+# define DVO_MAX_PATH 1024
+char         ImageCat[DVO_MAX_PATH];
+char        *CATDIR;
+int          HOST_ID;
+char        *HOSTDIR;
+char        *SINGLE_CPT;
+int          VERBOSE;
+int          UPDATE;
+int          PARALLEL;
+int          PARALLEL_MANUAL;
+int          PARALLEL_SERIAL;
+
+SkyRegion    UserPatch;
+
+/***** prototypes ****/
+int           main                              PROTO((int argc, char **argv));
+void          ConfigInit                        PROTO((int *argc, char **argv));
+
+void          initialize_fixhsc                 PROTO((int argc, char **argv));
+void          initialize_fixhsc_client          PROTO((int argc, char **argv));
+
+int           load_rules_fixhsc                 PROTO((char *filename));
+int           get_rules_fixhsc                  PROTO((e_time time));
+
+void          set_db                            PROTO((FITS_DB *in));
+int           Shutdown                          PROTO((char *format, ...) OHANA_FORMAT(printf, 1, 2) );
+void          TrapSignal                        PROTO((int sig));
+void          SetProtect                        PROTO((int mode));
+int           SetSignals                        PROTO((void));
+
+Image        *load_images_fixhsc                PROTO((FITS_DB *db, off_t *Nimage));
+void          update_images_fixhsc              PROTO((Image *image, off_t Nimage));
+
+int           update_dvo_fixhsc                 PROTO((void));
+int           update_dvo_fixhsc_parallel        PROTO((SkyTable *sky));
+					        
+void          update_catalog_fixhsc             PROTO((Catalog *catalog));
Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/fixhsc.c
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/fixhsc.c	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/fixhsc.c	(revision 41802)
@@ -0,0 +1,64 @@
+# include "fixhsc.h"
+
+int main (int argc, char **argv) {
+
+  off_t Nimage;
+  int status;
+  FITS_DB db;
+
+  /* get configuration info, args, lockfile */
+  SetSignals ();
+  initialize_fixhsc (argc, argv);
+
+  set_db (&db);
+  gfits_db_init (&db);
+  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+  if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+
+  // load images
+  Image *image  = load_images_fixhsc (&db, &Nimage);
+
+  // need to update image table here:
+  update_images_fixhsc (image, Nimage);
+
+  // write image table (even if some remote clients failed)
+  if (UPDATE) {
+    SetProtect (TRUE);
+    dvo_image_save (&db, VERBOSE);
+    dvo_image_unlock (&db); 
+    SetProtect (FALSE);
+  }
+  
+  status = update_dvo_fixhsc ();
+
+  if (!status) exit (1);
+  exit (0);
+}
+  
+
+/* fixhsc : modify the photcode values based on the time perido
+
+   current HSC photcodes: 
+     g = 20000 - 20111 
+     r = 21000 - 21111
+
+   goal HSC photcodes:
+     g ,North = 20000 - 20111 
+     g ,South = 20200 - 20311 
+     r ,North = 21000 - 21111
+     r ,South = 21200 - 21311
+     r2,North = 21400 - 21511
+     r2,South = 21600 - 21711
+
+   I can define rules which specify the goal photcode for a time period,
+   then the code can use the value % 1000 to get the chip ID
+
+   rule file:
+   start stop photcode (start & stop in MJD, photcode = value for chip 00, e.g., 21200)
+
+   ** load images (save subset with imageID, time, photcode, seq)
+   ** load catalogs 
+   ** update detection
+   ** count detections / image ID?
+ */
Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/fixhsc_client.c
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/fixhsc_client.c	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/fixhsc_client.c	(revision 41802)
@@ -0,0 +1,21 @@
+# include "fixhsc.h"
+
+// fixhsc_client is run on a remote host and is responsible for updating the catalogs
+// owned by that host.  
+
+// fixhsc_client -hostname (hostname) -catdir (catdir) -hostdir (hostdir) -images (images)
+// load the SkyTable and HostTable from (catdir) [contains the host responsibilities]
+// load the image data from (images) [contains the zp infomation to apply]
+// loop over tables from SkyTable with my host ID
+// the calling program tells the client which host they are (or host ID?); we do not actually have to run this on the real host
+
+int main (int argc, char **argv) {
+
+  // get configuration info, args, lockfile (set CATDIR, HOST_ID, HOSTDIR, IMAGES)
+  SetSignals ();
+  initialize_fixhsc_client (argc, argv);
+
+  update_dvo_fixhsc ();
+
+  exit (0);
+}
Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/initialize_fixhsc.c
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/initialize_fixhsc.c	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/initialize_fixhsc.c	(revision 41802)
@@ -0,0 +1,272 @@
+# include "fixhsc.h"
+int args_fixhsc (int argc, char **argv);
+int args_fixhsc_client (int argc, char **argv);
+
+void usage_fixhsc () {
+    fprintf (stderr, "USAGE: fixhsc rules.txt [options]\n");
+    fprintf (stderr, "  rules.txt : file with time-based photcode rules:\n\n");
+    fprintf (stderr, "  options:\n");
+    fprintf (stderr, "    -v : verbose mode\n");
+    fprintf (stderr, "    -cpt n0000/0000.00.cpt : only repair this cpt file \n");
+    fprintf (stderr, "    -region Rmin Rmax Dmin Dmax : only repair this region\n");
+    fprintf (stderr, "    -update : actually write results to detections tables\n");
+    fprintf (stderr, "    -parallel : run in parallel mode\n\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_fixhsc (int argc, char **argv) {
+
+  int N;
+  struct stat statbuffer;
+  char CatdirPhotcodeFile[256];
+
+  if ((N = get_argument (argc, argv, "-h"))) usage_fixhsc();
+  if ((N = get_argument (argc, argv, "-help"))) usage_fixhsc();
+  if ((N = get_argument (argc, argv, "--h"))) usage_fixhsc();
+  if ((N = get_argument (argc, argv, "--help"))) usage_fixhsc();
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args_fixhsc (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_fixhsc (int argc, char **argv) {
+
+  int N;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  SINGLE_CPT = NULL;
+  if ((N = get_argument (argc, argv, "-cpt"))) {
+    remove_argument (N, &argc, argv);
+    SINGLE_CPT = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  // region of interest
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  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,
+  // fixhsc 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 fixhsc_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 != 2) usage_fixhsc();
+
+  load_rules_fixhsc (argv[1]);
+
+  return (TRUE);
+}
+
+void usage_fixhsc_client () {
+  fprintf (stderr, "USAGE: fixhsc_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_fixhsc_client (int argc, char **argv) {
+
+  int N;
+  struct stat statbuffer;
+  char CatdirPhotcodeFile[256];
+
+  if ((N = get_argument (argc, argv, "-h"))) usage_fixhsc_client();
+  if ((N = get_argument (argc, argv, "-help"))) usage_fixhsc_client();
+  if ((N = get_argument (argc, argv, "--h"))) usage_fixhsc_client();
+  if ((N = get_argument (argc, argv, "--help"))) usage_fixhsc_client();
+
+  SetZeroPoint (25.0); // XXX is this needed?
+  args_fixhsc_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_fixhsc_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;
+  }
+
+  SINGLE_CPT = NULL;
+  if ((N = get_argument (argc, argv, "-cpt"))) {
+    remove_argument (N, &argc, argv);
+    SINGLE_CPT = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  // region of interest
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  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_fixhsc_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_fixhsc_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_fixhsc_client();
+
+  if (argc != 1) usage_fixhsc_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-dev-20210817/Ohana/src/uniphot/src/load_images_fixhsc.c
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/load_images_fixhsc.c	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/load_images_fixhsc.c	(revision 41802)
@@ -0,0 +1,46 @@
+# include "fixhsc.h"
+
+Image *load_images_fixhsc (FITS_DB *db, off_t *Nimage_load) {
+
+  Image *image;
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  /* read entire db table */
+  if (!dvo_image_load (db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db[0].filename);
+
+  /* use a vtable to keep the images to be calibrated */
+  image = gfits_table_get_Image (&db[0].ftable, Nimage_load, &db[0].scaledValue, &db[0].nativeOrder);
+  if (!image) {
+      fprintf (stderr, "ERROR: failed to read images\n");
+      exit (2);
+  }
+
+  fprintf (stderr, "loaded "OFF_T_FMT" images\n", *Nimage_load);
+
+  return (image);
+}
+
+void update_images_fixhsc (Image *image, off_t Nimage) {
+
+  for (off_t i = 0; i < Nimage; i++) {
+
+    // skip photcode == 0 images (PHU)
+    short photcode = image[i].photcode;
+    if (!photcode) continue;
+
+    // we have a measure with a given photcode and time:
+    e_time time = image[i].tzero;
+
+    int newbase = get_rules_fixhsc (time);
+    if (!newbase) continue;
+    
+    // the rule is the new base photcode
+    // this is robust against multiple passes
+    short chipcode = 1000 * (int)(photcode / 1000);
+
+    short newcode  = newbase + chipcode;
+    image[i].photcode = newcode;
+  }
+}
+
Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/load_rules_fixhsc.c
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/load_rules_fixhsc.c	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/load_rules_fixhsc.c	(revision 41802)
@@ -0,0 +1,52 @@
+# include "fixhsc.h"
+
+static int    Nrule = 0;
+static double *startRule     = NULL;
+static double *stopRule      = NULL;
+static int    *photbaseRule  = NULL;
+
+int load_rules_fixhsc (char *filename) {
+
+  // the rule file contains
+  // Start Stop Photbase
+
+  FILE *f = fopen (filename, "r");
+  if (!f) { fprintf (stderr, "file %s not found", filename); abort(); }
+
+  int NRULE = 10000;
+
+  ALLOCATE_PTR (startRule, double, NRULE);
+  ALLOCATE_PTR (stopRule,  double, NRULE);
+  ALLOCATE_PTR (photbaseRule, int, NRULE);
+
+  while (fscanf (f, "%lf %lf %d", &startRule[Nrule], &stopRule[Nrule], &photbaseRule[Nrule]) != EOF) {
+    Nrule ++;
+
+    if (Nrule >= NRULE) {
+      NRULE += 10000;
+      REALLOCATE (startRule, double, NRULE);
+      REALLOCATE (stopRule,  double, NRULE);
+      REALLOCATE (photbaseRule, int, NRULE);
+    }
+  }
+
+  // dsortpair (ruleR, ruleD, Nrule); 
+
+  return TRUE;
+}
+
+int get_rules_fixhsc (e_time time) {
+
+  // find the rule that encompases this time, return the rule
+
+  for (int i = 0; i < Nrule; i++) {
+    if (time < startRule[i]) continue;
+    if (time > stopRule[i]) continue;
+
+    return photbaseRule[i];
+  }
+
+  // if we return false, no match was found, keep the old photcode
+  return FALSE;
+
+}
Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/update_catalog_fixhsc.c
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/update_catalog_fixhsc.c	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/update_catalog_fixhsc.c	(revision 41802)
@@ -0,0 +1,22 @@
+# include "fixhsc.h"
+
+void update_catalog_fixhsc (Catalog *catalog) {
+
+  for (int i = 0; i < catalog[0].Nmeasure; i++) {
+    
+    // we have a measure with a given photcode and time:
+    e_time time = catalog[0].measure[i].t;
+
+    int newbase = get_rules_fixhsc (time);
+    if (!newbase) continue;
+    
+    short photcode = catalog[0].measure[i].photcode;
+
+    // the rule is the new base photcode
+    // this is robust against multiple passes
+    short chipcode = 1000 * (int)(photcode / 1000);
+
+    short newcode  = newbase + chipcode;
+    catalog[0].measure[i].photcode = newcode;
+  }
+}
Index: branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/update_dvo_fixhsc.c
===================================================================
--- branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/update_dvo_fixhsc.c	(revision 41802)
+++ branches/eam_branches/ipp-dev-20210817/Ohana/src/uniphot/src/update_dvo_fixhsc.c	(revision 41802)
@@ -0,0 +1,145 @@
+# include "fixhsc.h"
+
+int update_dvo_fixhsc (void) {
+
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+  Catalog catalog;
+  off_t i;
+
+  // 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_fixhsc_parallel (sky);
+    return TRUE;
+  }
+
+  // determine the populated SkyRegions overlapping the requested area (default depth)
+  if (SINGLE_CPT) {
+      skylist = SkyRegionByCPT (sky, SINGLE_CPT);
+  } else {
+      skylist = SkyListByPatch (sky, -1, &UserPatch);
+  }
+  myAssert (skylist, "ooops!");
+
+  // 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
+    dvo_catalog_init (&catalog, TRUE);
+    catalog.filename  = HOST_ID ? localFilename : skylist[0].filename[i];
+    catalog.catflags  = DVO_LOAD_AVERAGE | DVO_LOAD_MEASURE | DVO_LOAD_MISSING | DVO_LOAD_SECFILT;
+    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.Naverage_disk) {
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    update_catalog_fixhsc (&catalog);
+
+    if (!UPDATE) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+    
+    if (VERBOSE) fprintf (stderr, "saving catalog %s\n", catalog.filename);
+    
+    SetProtect (TRUE);
+    if (!dvo_catalog_save (&catalog, VERBOSE)) { fprintf (stderr, "ERROR: failed to save %s\n", catalog.filename); exit (1); }
+    if (!dvo_catalog_unlock (&catalog)) { fprintf (stderr, "ERROR: failed to unlock %s\n", catalog.filename); exit (1); }
+    SetProtect (FALSE);
+    dvo_catalog_free (&catalog);
+  }
+
+  return (TRUE);
+}      
+
+# define DEBUG 1
+
+int update_dvo_fixhsc_parallel (SkyTable *sky) {
+
+  char uniquer[12];
+  int TIME = time(NULL);
+  int PID = getpid();
+  snprintf_nowarn (uniquer, 12, "%05d.%05d", PID, TIME % 100000);
+
+  // now launch the fixhsc_client jobs to the parallel hosts
+
+  // load the list of hosts
+  HostTable *table = HostTableLoad (CATDIR, sky->hosts);
+
+  // fix this if you ever try on a parallel database
+  fprintf (stderr, "update code to supply rule file to clients\n");
+  exit (2);
+
+  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;
+
+    ALLOCATE (table->hosts[i].results, char, 1024);
+    snprintf (table->hosts[i].results, 1024, "%s/fixhsc.results.%s.dat", table->hosts[i].pathname, uniquer);
+
+    char *command = NULL;
+    strextend (&command, "fixhsc_client -hostID %d -catdir %s -hostdir %s -region %f %f %f %f", 
+	      table->hosts[i].hostID, CATDIR, table->hosts[i].pathname,
+	      UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax);
+
+    if (VERBOSE)     { strextend (&command, "-v"); }
+    if (SINGLE_CPT)  { strextend (&command, "-cpt %s", SINGLE_CPT); }
+    if (UPDATE)      { strextend (&command, "-update"); }
+
+    fprintf (stderr, "command: %s\n", command);
+
+    if (PARALLEL_MANUAL) continue;
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running fixhsc_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 fixhsc_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);
+}      
+
