Index: /branches/dvo-mods-2007-02/Ohana/src/addstar/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/addstar/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/addstar/src/ConfigInit.c	(revision 12031)
@@ -7,5 +7,6 @@
   char *config, *file;
   char RadiusWord[80];
-  char PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
   AddstarClientOptions options;
 
@@ -61,6 +62,6 @@
   CAL_INSTMAG_MAX =  -9.0;
   CAL_INSTMAG_MIN = -13.0;
-  ScanConfig (config, "CAL_INSTMAG_MAX",   "%lf", 0, &CAL_INSTMAG_MAX);
-  ScanConfig (config, "CAL_INSTMAG_MIN",   "%lf", 0, &CAL_INSTMAG_MIN);
+  ScanConfig (config, "CAL_INSTMAG_MAX",        "%lf", 0, &CAL_INSTMAG_MAX);
+  ScanConfig (config, "CAL_INSTMAG_MIN",        "%lf", 0, &CAL_INSTMAG_MIN);
 
   /* location of needed data sources */
@@ -69,14 +70,14 @@
   ScanConfig (config, "GSCDIR",                 "%s",  0, GSCDIR);
 
-  if (!ScanConfig (config, "USNO_A_DIR",             "%s",  0, USNO_A_DIR)) {
-    ScanConfig (config, "USNO_CDROM",             "%s",  0, USNO_A_DIR);
+  if (!ScanConfig (config, "USNO_A_DIR",        "%s",  0, USNO_A_DIR)) {
+    ScanConfig (config, "USNO_CDROM",           "%s",  0, USNO_A_DIR);
   }
   ScanConfig (config, "USNO_B_DIR",             "%s",  0, USNO_B_DIR);
 
-  ScanConfig (config, "TYCHO_DIR",             "%s",  0, TYCHO_DIR);
+  ScanConfig (config, "TYCHO_DIR",             	"%s",  0, TYCHO_DIR);
 
-  GetConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
-  GetConfig (config, "CATDIR",                 "%s",  0, CATDIR);
-  GetConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+  GetConfig (config, "GSCFILE",                	"%s",  0, GSCFILE);
+  GetConfig (config, "CATDIR",                 	"%s",  0, CATDIR);
+  GetConfig (config, "PHOTCODE_FILE",          	"%s",  0, MasterPhotcodeFile);
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
@@ -147,6 +148,8 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcode file %s\n", PhotCodeFile);
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
     exit (1);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/delstar/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/delstar/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/delstar/src/ConfigInit.c	(revision 12031)
@@ -4,5 +4,6 @@
 
   char *config, *file;
-  char PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -22,5 +23,5 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
-  ScanConfig (config, "PHOTCODE_FILE",          "%s", 0, PhotCodeFile);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
 
   sprintf (ImageCat, "%s/Images.dat", CATDIR);
@@ -42,6 +43,8 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes\n");
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
     exit (1);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/gastro/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/gastro/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/gastro/src/ConfigInit.c	(revision 12031)
@@ -44,5 +44,4 @@
   ScanConfig (config, "CATDIR",            "%s",  0, CATDIR);           // location of ptolemy-format ref data
   ScanConfig (config, "ROUGH_ASTROMETRY",  "%s",  0, ROUGH_ASTROMETRY); // where to get initial guess (header, config)
-  ScanConfig (config, "PHOTCODE_FILE",     "%s",  0, PhotCodeFile);     // location of photcode table to convert supplied photcode
 
   if (strcasecmp (ROUGH_ASTROMETRY, "header") && 
Index: /branches/dvo-mods-2007-02/Ohana/src/gastro/src/gheader.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/gastro/src/gheader.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/gastro/src/gheader.c	(revision 12031)
@@ -14,16 +14,7 @@
   oldsize = header.size;
 
+  /* validating the photcode name should be the job of DVO/addstar */
+  /* here we are only writing the selected photcode name to the header */
   if (NEWPHOTCODE) {
-    /* we are going to write the photcode into the header
-       here we are just checking that the photcode provided
-       is a valid code */
-    if (!LoadPhotcodes (PhotCodeFile)) {
-      fprintf (stderr, "error loading photcodes\n");
-      exit (0);
-    }
-    if (!GetPhotcodeCodebyName (PHOTCODE)) {
-      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
-      exit (0);
-    }
     gfits_modify (&header, "PHOTCODE", "%s", 1, PHOTCODE);
   }    
Index: /branches/dvo-mods-2007-02/Ohana/src/getstar/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/getstar/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/getstar/src/ConfigInit.c	(revision 12031)
@@ -4,5 +4,6 @@
 
   char *config, *file;
-  char PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -20,5 +21,5 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
-  ScanConfig (config, "PHOTCODE_FILE",          "%s", 0, PhotCodeFile);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
   if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
     SKY_DEPTH = 2;
@@ -31,6 +32,8 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes\n");
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (MasterPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
     exit (1);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/imclean/src/AdjustHeader.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/imclean/src/AdjustHeader.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/imclean/src/AdjustHeader.c	(revision 12031)
@@ -18,16 +18,7 @@
   }
 
+  /* validating the photcode name should be the job of DVO/addstar */
+  /* here we are only writing the selected photcode name to the header */
   if (NEWPHOTCODE) {
-    /* we are going to write the photcode into the header
-       here we are just checking that the photcode provided
-       is a valid code */
-    if (!LoadPhotcodes (PhotCodeFile)) {
-      fprintf (stderr, "ERROR: can't load photcodes\n");
-      exit (1);
-    }
-    if (!GetPhotcodebyName (PHOTCODE)) {
-      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
-      exit (1);
-    }
     gfits_modify (header, "PHOTCODE", "%s", 1, PHOTCODE);
   }    
Index: /branches/dvo-mods-2007-02/Ohana/src/imregister/base/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/imregister/base/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/imregister/base/ConfigInit.c	(revision 12031)
@@ -7,4 +7,6 @@
   int i, NDB;
   char *config, *file, ElixirBase[80], catdir[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -25,8 +27,8 @@
 
   WarnConfig (config, "CATDIR",                      "%s", 0, catdir);
+  WarnConfig (config, "PHOTCODE_FILE",               "%s", 0, MasterPhotcodeFile);
   sprintf (ImPhotDB, "%s/Images.dat", catdir);
 
   /* small text databases: filters, camera defs */ 
-  WarnConfig (config, "PHOTCODE_FILE",               "%s", 0, PhotCodeFile);
   WarnConfig (config, "TEMPERATURE_LOG",             "%s", 0, TempLogFile);
   WarnConfig (config, "FILTER_LIST",                 "%s", 0, FilterList);
@@ -101,4 +103,11 @@
   }
 
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", catdir);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
   free (config);
   free (file);
Index: /branches/dvo-mods-2007-02/Ohana/src/imregister/imphot/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/imregister/imphot/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/imregister/imphot/ConfigInit.c	(revision 12031)
@@ -8,4 +8,6 @@
   int i, NDB;
   char *config, *file, ElixirBase[80], catdir[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -21,8 +23,8 @@
 
   WarnConfig (config, "CATDIR",                      "%s", 0, catdir);
+  WarnConfig (config, "PHOTCODE_FILE",         	     "%s", 0, MasterPhotcodeFile);
   sprintf (ImPhotDB, "%s/Images.dat", catdir);
 
   /* small text databases: filters, camera defs */ 
-  WarnConfig (config, "PHOTCODE_FILE",               "%s", 0, PhotCodeFile);
   WarnConfig (config, "TEMPERATURE_LOG",             "%s", 0, TempLogFile);
   WarnConfig (config, "FILTER_LIST",                 "%s", 0, FilterList);
@@ -97,4 +99,11 @@
   }
 
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
   free (config);
   free (file);
Index: /branches/dvo-mods-2007-02/Ohana/src/imregister/imphot/args.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/imregister/imphot/args.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/imregister/imphot/args.c	(revision 12031)
@@ -8,10 +8,4 @@
 
   ConfigInit (&argc, argv); /* load elixir config data */
-
-  /* load photcode data */
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes from %s\n", PhotCodeFile);
-    exit (1);
-  }
 
   /* interpret command-line arguments */
Index: /branches/dvo-mods-2007-02/Ohana/src/imregister/photreg/args.photreg.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/imregister/photreg/args.photreg.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/imregister/photreg/args.photreg.c	(revision 12031)
@@ -19,10 +19,4 @@
   if (get_argument (argc, argv, "-h")) usage ();
   if (get_argument (argc, argv, "--help")) usage ();
-
-  /* load photcode data */
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes from %s\n", PhotCodeFile);
-    exit (1);
-  }
 
   /* set the required database */
Index: /branches/dvo-mods-2007-02/Ohana/src/imregister/photreg/args.photsearch.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/imregister/photreg/args.photsearch.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/imregister/photreg/args.photsearch.c	(revision 12031)
@@ -9,10 +9,4 @@
   ConfigCamera ();
   ConfigFilter ();
-
-  /* load photcode data */
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes from %s\n", PhotCodeFile);
-    exit (1);
-  }
 
   criteria.Ntimes = 0;
Index: /branches/dvo-mods-2007-02/Ohana/src/imregister/src/imphotmerge.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/imregister/src/imphotmerge.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/imregister/src/imphotmerge.c	(revision 12031)
@@ -4,5 +4,5 @@
 
 Image *LoadImageTable (FILE *f, Header *header, int *nimage);
-static char *version = "imphotcopy $Revision: 1.5.4.1 $";
+static char *version = "imphotcopy $Revision: 1.5.4.2 $";
 
 int main (int argc, char **argv) {
@@ -22,10 +22,4 @@
   get_version (argc, argv, version);
   ConfigInit (&argc, argv);
-
-  /* load photcode data */
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes from %s\n", PhotCodeFile);
-    exit (1);
-  }
 
   /* interpret command-line arguments */
Index: /branches/dvo-mods-2007-02/Ohana/src/libdvo/Makefile
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/libdvo/Makefile	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/libdvo/Makefile	(revision 12031)
@@ -29,5 +29,8 @@
 $(SRC)/version.$(ARCH).o	 \
 $(SRC)/coordops.$(ARCH).o	 \
+$(SRC)/dvo_photcode_ops.$(ARCH).o \
 $(SRC)/LoadPhotcodes.$(ARCH).o   \
+$(SRC)/LoadPhotcodesText.$(ARCH).o   \
+$(SRC)/LoadPhotcodesFITS.$(ARCH).o   \
 $(SRC)/imreg_datatypes.$(ARCH).o \
 $(SRC)/mosaic_astrom.$(ARCH).o   \
Index: /branches/dvo-mods-2007-02/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/libdvo/include/dvo.h	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/libdvo/include/dvo.h	(revision 12031)
@@ -39,5 +39,5 @@
 
 /* photometry code types */
-# define PHOT_PRI 0x01
+// # define PHOT_PRI 0x01
 # define PHOT_SEC 0x02
 # define PHOT_DEP 0x03
@@ -133,8 +133,9 @@
 
 typedef struct {
-  int Ncode;
-  int Nsecfilt;
-  int hashcode[0x10000];
-  int hashNsec[0x10000];
+  int Ncode;					  // number of photcodes
+  int Nsecfilt;					  // number of average magnitudes
+  int hashcode[0x10000];		  // index from photcode value to sequence
+  int hashNsec[0x10000];		  // index from photcode value to Nsec seq
+  int codeNsec[0x10000];		  // index from Nsec seq to photcode value
   PhotCode *code;
 } PhotCodeData;
@@ -235,5 +236,10 @@
 int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);
 
-int LoadPhotcodes (char *filename);
+PhotCodeData *GetPhotcodeTable ();
+
+int LoadPhotcodes (char *catdir_file, char *master_file);
+int LoadPhotcodesText (char *filename);
+int LoadPhotcodesFITS (char *filename);
+
 int GetPhotcodeCodebyName (char *name);
 int GetPhotcodeEquivCodebyName (char *name);
Index: /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodes.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodes.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodes.c	(revision 12031)
@@ -1,696 +1,12 @@
 # include <dvo.h>
 
-# define NCTERMS 4
-# define F 0.001
-/* # define NO_MAG 100.0 */
+int LoadPhotcodes (char *catdir_file, char *master_file) {
 
-static PhotCodeData *photcodes = NULL;
-static double ZERO_POINT;
-static short int Nseclist[0x10000];
+  /* first try to load the photcodes from the specified CATDIR location */
+  if (LoadPhotcodesFITS (catdir_file)) return TRUE;
+  
+  /* next try to load the photcodes from the master text photcode file */
+  if (LoadPhotcodesFITS (master_file)) return TRUE;
 
-/* static short int iZERO_POINT; */
-
-void SetZeroPoint (double ZP) {
-  ZERO_POINT = ZP;
-  /* iZERO_POINT = 1000 * ZP; */
+  return FALSE;
 }
-
-int LoadPhotcodes (char *filename) {
-  
-  FILE *f;
-  int i, Ns, Np, NPHOTCODE, Npri, Nfield;
-  PhotCode *photcode;
-  int code;
-  char *c;
-  char line[256];
-  char name[32], type[32], Zero[32], Airmass[32], Offset[32],
-    C1[32], C2[32], Slope[32], Color[32], Primary[32];
-  int c1, c2;
-
-  /* allocate space to photcode table, free existing data */
-  if (photcodes == NULL) {
-    ALLOCATE (photcodes, PhotCodeData, 1);
-    photcodes[0].code = NULL;
-  }
-  if (photcodes[0].code != NULL) free (photcodes[0].code);
-
-  f = fopen (filename, "r");
-  if (f == (FILE *) NULL) {
-    photcodes[0].Ncode    = 0;
-    photcodes[0].Nsecfilt = 0;
-    photcodes[0].code     = (PhotCode *) NULL;
-    return (FALSE);
-  }
-
-  Np = 0;
-  NPHOTCODE = 10;
-  ALLOCATE (photcode, PhotCode, NPHOTCODE);
-  photcodes[0].Nsecfilt = 0;
-  for (i = 0; i < 0x10000; i++) {
-    photcodes[0].hashcode[i] = -1;
-    photcodes[0].hashNsec[i] = -1;
-  }
-
-  while (scan_line (f, line) != EOF) {
-    for (c = line; isspace (*c); c++);
-    if (*c == '#') continue;
-    Nfield = sscanf (c, "%d %s %s %s %s %s %s %s %s %s %s", 
-		     &code, name, type, Zero, Airmass, Offset, C1, C2, Slope, Color, Primary);
-    if (Nfield != 11) { continue; }
-    
-    c1 = atof (C1);
-    c2 = atof (C2);
-    if (!strcmp (C1, "-")) { c1 = 0; }
-    if (!strcmp (C2, "-")) { c2 = 0; }
-
-    photcode[Np].type = 0;
-    photcode[Np].code = code;
-    strcpy (photcode[Np].name, name);
-    if (!strncasecmp (type, "pri", 3)) {
-      photcode[Np].type  = PHOT_PRI;
-      photcode[Np].C     = 1000*atof (Zero);
-      photcode[Np].K     = atof (Airmass);
-      photcode[Np].dC    = 1000*atof (Offset);
-      photcode[Np].dX    = 1000*atof (Color);
-      photcode[Np].c1    = c1;
-      photcode[Np].c2    = c2;
-      photcode[Np].equiv = atoi (Primary);
-      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
-      Nseclist[0] = Np;
-    }      
-    if (!strncasecmp (type, "sec", 3)) {
-      photcode[Np].type  = PHOT_SEC;
-      photcode[Np].C     = 1000*atof (Zero);
-      photcode[Np].K     = atof (Airmass);
-      photcode[Np].dC    = 1000*atof (Offset);
-      photcode[Np].dX    = 1000*atof (Color);
-      photcode[Np].c1    = c1;
-      photcode[Np].c2    = c2;
-      photcode[Np].equiv = atoi (Primary);
-      photcodes[0].Nsecfilt ++;
-      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
-      Nseclist[photcodes[0].Nsecfilt] = Np;
-    }      
-    if (!strncasecmp (type, "dep", 3)) {
-      photcode[Np].type  = PHOT_DEP;
-      photcode[Np].C     = 1000*atof (Zero);    /* zero point in millimags */
-      photcode[Np].K     = atof (Airmass);      /* airmass coeff (millimag / millimag) */
-      photcode[Np].dC    = 1000*atof (Offset);  /* color ref z.p. (millimag) */
-      photcode[Np].dX    = 1000*atof (Color);   /* average color (millimag) */
-      photcode[Np].c1    = c1;
-      photcode[Np].c2    = c2;
-      photcode[Np].equiv = atoi (Primary);
-      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
-    }      
-    if (!strncasecmp (type, "ref", 3)) {
-      photcode[Np].type  = PHOT_REF;
-      photcode[Np].C     = 0;
-      photcode[Np].K     = 0;
-      photcode[Np].dC    = 0;
-      photcode[Np].dX    = 0;
-      photcode[Np].c1    = 0;
-      photcode[Np].c2    = 0;
-      photcode[Np].equiv = atoi (Primary);
-      photcode[Np].X[0]  = 0;
-      photcode[Np].Nc    = 0;
-    }
-
-    /* alt photcodes are a little different: they have the SAME photcode as an existing
-       pri/sec photcode, but define an alternate transformation for that code */
-    if (!strncasecmp (type, "alt", 3)) {
-      photcode[Np].type  = PHOT_ALT;
-      photcode[Np].C     = 1000*atof (Zero);    /* zero point in millimags */
-      photcode[Np].K     = atof (Airmass);      /* airmass coeff (millimag / millimag) */
-      photcode[Np].dC    = 1000*atof (Offset);  /* color ref z.p. (millimag) */
-      photcode[Np].dX    = 1000*atof (Color);   /* average color (millimag) */
-      photcode[Np].c1    = c1;
-      photcode[Np].c2    = c2;
-      photcode[Np].equiv = atoi (Primary);
-      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
-    }
-    if (!photcode[Np].type) {
-      fprintf (stderr, "error in Photfile: unknown type %s\n", type);
-    }
-
-    Np++;
-    if (Np == NPHOTCODE) {
-      NPHOTCODE += 10;
-      REALLOCATE (photcode, PhotCode, NPHOTCODE);
-    }
-  }
-  fclose (f);
-  
-  /* set up hashcode for photcode refs:
-   * the hashcode gives the structure sequence for a given photcode:
-   * photcode[i].hashcode[photcode[i].code] == i
-   */
-
-  Ns = 0;
-  for (i = 0; i < Np; i++) {
-    if (photcode[i].type == PHOT_ALT) continue; /* no hashcode for ALT codes */
-    if (photcodes[0].hashcode[photcode[i].code] != -1) {
-      fprintf (stderr, "duplicate photcodes in file\n");
-      code = photcodes[0].hashcode[photcode[i].code];
-      fprintf (stderr, "conflict between %s (%d) and %s (%d)\n",
-	       photcode[i].name, photcode[i].code, photcode[code].name, photcode[code].code);
-      free (photcode);
-      return (FALSE);
-    }
-    photcodes[0].hashcode[photcode[i].code] = i;
-    if (photcode[i].type == PHOT_SEC) {
-      photcodes[0].hashNsec[photcode[i].code] = Ns;
-      Ns ++;
-    }
-  }
-  /* validity check for references */
-  for (i = 0; i < Np; i++) {
-    if (photcode[i].type == PHOT_DEP) {
-      Npri = photcodes[0].hashcode[photcode[i].equiv];
-      if ((Npri >= Np) || (Npri < 0)) {
-	fprintf (stderr, "reference for dependent photcode is not in photcodes\n");
-	free (photcode);
-	return (FALSE);
-      }
-      if ((photcode[Npri].type != PHOT_PRI) && (photcode[Npri].type != PHOT_SEC)) {
-	fprintf (stderr, "reference for dependent photcode is not a primary or secondary code\n");
-	free (photcode);
-	return (FALSE);
-      }
-    }
-    if (photcode[i].type == PHOT_ALT) {
-      Npri = photcodes[0].hashcode[photcode[i].code];
-      if ((Npri >= Np) || (Npri < 0)) {
-	fprintf (stderr, "reference for alternate photcode is not in photcodes\n");
-	free (photcode);
-	return (FALSE);
-      }
-      if ((photcode[Npri].type != PHOT_PRI) && (photcode[Npri].type != PHOT_SEC)) {
-	fprintf (stderr, "reference for alternate photcode is not a primary or secondary code\n");
-	free (photcode);
-	return (FALSE);
-      }
-    }
-  }
-  photcodes[0].code = photcode;
-  photcodes[0].Ncode = Np;
-
-  return (TRUE);
-
-}
-
-void ParseColorTerms (char *terms, float *X, int *N) {
-
-  int i;
-  char *p;
-
-  p = terms;
-
-  for (i = 0; (p != NULL) && (i < NCTERMS); i++) {
-    X[i] = atof (p);
-    p = strchr (p, ',');
-    if (p == (char *) NULL) continue;
-    p ++;
-  }
-  *N = i;
-}
-
-/********** photcode lookups **********/
-
-/* return photcode for given name */
-PhotCode *GetPhotcodebyName (char *name) {
-  
-  int i;
-
-  if (name == (char *) NULL ) return (NULL);
-  
-  for (i = 0; i < photcodes[0].Ncode; i++) {
-    if (!strcmp (photcodes[0].code[i].name, name)) {
-      return (&photcodes[0].code[i]);
-    }
-  }
-  return (NULL);
-}
-/* return photcode.code for given name */
-int GetPhotcodeCodebyName (char *name) {
-  
-  int i;
-  
-  if (name == (char *) NULL ) return (0);
-
-  for (i = 0; i < photcodes[0].Ncode; i++) {
-    if (!strcmp (photcodes[0].code[i].name, name)) {
-      return (photcodes[0].code[i].code);
-    }
-  }
-  return (0);
-}
-/* return equivalent photcode for given name */
-PhotCode *GetPhotcodeEquivbyName (char *name) {
-  
-  int i, equiv;
-  
-  if (name == (char *) NULL ) return (NULL);
-
-  for (i = 0; i < photcodes[0].Ncode; i++) {
-    if (!strcmp (photcodes[0].code[i].name, name)) {
-      if (photcodes[0].code[i].equiv == 0) return (NULL);
-      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
-      if (equiv == -1) return (NULL);
-      return (&photcodes[0].code[equiv]);
-    }
-  }
-  return (NULL);
-}
-/* return equivalent photcode.code for given name */
-int GetPhotcodeEquivCodebyName (char *name) {
-  
-  int i, equiv;
-  
-  if (name == (char *) NULL ) return (0);
-
-  for (i = 0; i < photcodes[0].Ncode; i++) {
-    if (!strcmp (photcodes[0].code[i].name, name)) {
-      if (photcodes[0].code[i].equiv == 0) return (0);
-      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
-      if (equiv == -1) return (0);
-      return (photcodes[0].code[equiv].code);
-    }
-  }
-  return (0);
-}
-
-/* return photcode for given code */
-PhotCode *GetPhotcodebyCode (int code) {
-  
-  int entry;
-  
-  if (code < 0) return (NULL);
-  if (code > 0x10000) return (NULL);
-
-  entry = photcodes[0].hashcode[code];
-  if (entry == -1) return (NULL);
-
-  return (&photcodes[0].code[entry]);
-}
-/* return photcode.code for given code */
-char *GetPhotcodeNamebyCode (int code) {
-  
-  int entry;
-  
-  if (code < 0) return (NULL);
-  if (code > 0x10000) return (NULL);
-
-  entry = photcodes[0].hashcode[code];
-  if (entry == -1) return (NULL);
-
-  return (photcodes[0].code[entry].name);
-}
-/* return equivalent photcode for given code */
-PhotCode *GetPhotcodeEquivbyCode (int code) {
-  
-  int entry, equiv;
-  
-  if (code < 0) return (NULL);
-  if (code > 0x10000) return (NULL);
-
-  entry = photcodes[0].hashcode[code];
-  if (entry == -1) return (NULL);
-
-  if (photcodes[0].code[entry].equiv == 0) return (NULL);
-  equiv = photcodes[0].hashcode[photcodes[0].code[entry].equiv];
-
-  if (equiv == -1) return (NULL);
-  return (&photcodes[0].code[equiv]);
-}
-/* return equivalent photcode.code for given code */
-int GetPhotcodeEquivCodebyCode (int code) {
-  
-  int entry;
-  
-  if (code < 0) return (0);
-  if (code > 0x10000) return (0);
-
-  entry = photcodes[0].hashcode[code];
-  if (entry == -1) return (0);
-  return (photcodes[0].code[entry].equiv);
-}
-
-int GetPhotcodeNsec (int code) {
-  
-  int Nsec;
-  
-  if (code < 0) return (-1);
-  if (code > 0x10000) return (-1);
-
-  Nsec = photcodes[0].hashNsec[code];
-  return (Nsec);
-}
-
-/* Nsec of 0 is PRI */
-PhotCode *GetPhotcodebyNsec (int Nsec) {
-  
-  if (Nsec > photcodes[0].Nsecfilt) return (NULL);
-  if (Nsec < 0) return (NULL);
-  
-  return (&photcodes[0].code[Nseclist[Nsec]]);
-}
-
-int GetPhotcodeNsecfilt () {
-  return (photcodes[0].Nsecfilt);
-}
-
-/* ALLOCATE and return list of all photcodes
-   with photcode.equiv == code */
-int *GetPhotcodeEquivList (int code, int *nlist) {
-
-  int i, Nlist;
-  int *list;
-
-  ALLOCATE (list, int, MAX (1, photcodes[0].Ncode));
-  Nlist = 0;
-  for (i = 0; i < photcodes[0].Ncode; i++) {
-    if (photcodes[0].code[i].equiv != code) continue;
-    list[Nlist] = photcodes[0].code[i].code;
-    Nlist ++;
-  }
-  REALLOCATE (list, int, MAX (1, Nlist));
-
-  *nlist = Nlist;
-  return (list);
-}
-
-/******** internal photometry conversions (keeps values in short int millimags) *********/
-float PhotInst (Measure *measure) {
-
-  int Np;
-  float M;
-
-  Np = photcodes[0].hashcode[measure[0].photcode];
-  if (Np == -1) return (NO_MAG);
-
-  if (photcodes[0].code[Np].type == PHOT_REF) {
-    M = measure[0].M;
-    return (M);
-  }
-
-  M = measure[0].M - measure[0].dt - ZERO_POINT;
-	  
-  return (M);
-
-}
-
-float PhotCat (Measure *measure) {
-
-  int Np;
-  float Mcat;
-  PhotCode *code;
-
-  Np = photcodes[0].hashcode[measure[0].photcode];
-  if (Np == -1) return (NO_MAG);
-
-  if (photcodes[0].code[Np].type == PHOT_REF) {
-    Mcat = measure[0].M;
-    return (Mcat);
-  }
-  code = &photcodes[0].code[Np];
-  Mcat = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + F*code[0].C;
-  
-  return (Mcat);
-}
-
-float PhotSys (Measure *measure, Average *average, SecFilt *secfilt) {
-
-  int i, Np;
-  float Mcat, Mcol, Msys, mc, Mc;
-  PhotCode *code;
-
-  Np = photcodes[0].hashcode[measure[0].photcode];
-  if (Np == -1) return (NO_MAG);
-
-  if (photcodes[0].code[Np].type == PHOT_REF) {
-    Msys = measure[0].M;
-    return (Msys);
-  }
-  code = &photcodes[0].code[Np];
-  Mcat = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + F*code[0].C;
-
-  /* for DEP, color must be made of PRI/SEC */
-  mc = PhotColorForCode (average, secfilt, NULL, code);
-  if (mc == NO_MAG) return (Mcat);
-  mc = mc - F*code[0].dX;
-
-  Mc = mc;
-  Mcol = 0;
-  for (i = 0; i < code[0].Nc; i++) {
-    Mcol += code[0].X[i]*Mc;
-    Mc *= mc;
-  }
-  Msys = Mcat + Mcol;
-  return (Msys);
-}
-
-float PhotRel (Measure *measure, Average *average, SecFilt *secfilt) {
-
-  int i, Np;
-  float Mcat, Mcol, Mrel, mc, Mc;
-  PhotCode *code;
-
-  Np = photcodes[0].hashcode[measure[0].photcode];
-  if (Np == -1) return (NO_MAG);
-
-  if (photcodes[0].code[Np].type == PHOT_REF) {
-    Mcat = measure[0].M;
-    return (Mcat);
-  }
-  code = &photcodes[0].code[Np];
-  Mrel = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + F*code[0].C - measure[0].Mcal;
-
-  /* for DEP, color must be made of PRI/SEC */
-  mc = PhotColorForCode (average, secfilt, NULL, code);
-  if (mc == NO_MAG) return (Mrel);
-  mc = mc - F*code[0].dX;
-
-  Mc = mc;
-  Mcol = 0;
-  for (i = 0; i < code[0].Nc; i++) {
-    Mcol += code[0].X[i]*Mc;
-    Mc *= mc;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
-  }
-  Mrel += Mcol;
-  return (Mrel);
-}
-
-/* return calibrated magnitude from measure for given photcode */
-float PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
-
-  int i, Np; 
-  float Mcal, Mrel, Mcol, mc, Mc;
-
-  /* code must be the matching PRI/SEC code for this measurement or an equivalent ALT */
-  Np = photcodes[0].hashcode[thisone[0].photcode];
-  if (Np == -1) {
-    return (NO_MAG);
-  }
-
-  if (photcodes[0].code[Np].type == PHOT_REF) {
-    Mrel = thisone[0].M;
-    return (Mrel);
-  }
-  if (code[0].code != photcodes[0].code[Np].equiv) {
-    return (NO_MAG);
-  }
-
-  Mcal = PhotRel (thisone, average, secfilt) + F*code[0].C;
-
-  mc = PhotColorForCode (average, secfilt, measure, code);
-  if (mc == NO_MAG) return (Mcal);
-  mc = mc - F*code[0].dX;
-
-  Mc = mc;
-  Mcol = 0;
-  for (i = 0; i < code[0].Nc; i++) {
-    Mcol += code[0].X[i]*Mc;
-    Mc *= mc;
-  }
-  Mcal += Mcol;
-  return (Mcal);
-}
-
-/* color term may not use DEP magnitude */
-float PhotColorForCode (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
-
-  int i, Ns1, Ns2, Ns;
-  float m1, m2, mc;
-  PhotCode *color;
-
-  m1 = m2 = NO_MAG;
-
-  if (measure == NULL) {
-    Ns1 = photcodes[0].hashNsec[code[0].c1];
-    Ns2 = photcodes[0].hashNsec[code[0].c2];
-  
-    m1 = (Ns1 == -1) ? NO_MAG : secfilt[Ns1].M;
-    m2 = (Ns2 == -1) ? NO_MAG : secfilt[Ns2].M;
-    mc = ((m1 == NO_MAG) || (m2 == NO_MAG)) ? NO_MAG : (m1 - m2);
-    return (mc);
-  }
-
-  /* find magnitude matching first color term */
-  color = GetPhotcodebyCode (code[0].c1);
-  if (color == NULL) return (NO_MAG);
-  if (color[0].type == PHOT_REF) {
-    for (i = 0; (i < average[0].Nm) && (m1 == NO_MAG); i++) {
-      if (measure[i].photcode == color[0].code) {
-	m1 = measure[i].M;
-      }
-    }
-  } else {
-    Ns = photcodes[0].hashNsec[color[0].code];
-    m1 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
-  }	
-
-  /* find magnitude matching second color term */
-  color = GetPhotcodebyCode (code[0].c2);
-  if (color == NULL) return (NO_MAG);
-  if (color[0].type == PHOT_REF) {
-    for (i = 0; (i < average[0].Nm) && (m2 == NO_MAG); i++) {
-      if (measure[i].photcode == color[0].code) {
-	m2 = measure[i].M;
-      }
-    }
-  } else {
-    Ns = photcodes[0].hashNsec[color[0].code];
-    m2 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
-  }	
-  mc = ((m1 == NO_MAG) || (m2 == NO_MAG)) ? NO_MAG : (m1 - m2);
-  return (mc);
-}
-
-/* return calibrated magnitude from average/secfilt for given photcode */
-float PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
-
-  int i, Ns;
-  float Mave, Mref, Mcol, mc;
-  double Mc;
-
-  Ns = photcodes[0].hashNsec[code[0].code];
-  Mave = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
-  Mref = Mave + F*code[0].C;
-
-  mc = PhotColorForCode (average, secfilt, measure, code);
-  if (mc == NO_MAG) return (Mref);
-  mc = mc - F*code[0].dX;
-
-  Mc = mc;
-  Mcol = 0;
-  for (i = 0; i < code[0].Nc; i++) {
-    Mcol += code[0].X[i]*Mc;
-    Mc *= mc;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
-  }
-  Mref += Mcol;
-  return (Mref);
-}
-
-/***/
-float PhotAve (PhotCode *code, Average *average, SecFilt *secfilt) {
-
-  int Ns;
-  float Mave;
-
-  Ns = photcodes[0].hashNsec[code[0].code];
-  Mave = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
-  return (Mave);
-}
-
-float PhotdM (PhotCode *code, Average *average, SecFilt *secfilt) {
-
-  int Ns;
-  float dM;
-
-  Ns = photcodes[0].hashNsec[code[0].code];
-  dM  = (Ns == -1) ? NO_MAG : secfilt[Ns].dM;
-  return (dM);
-}
-
-float PhotXm (PhotCode *code, Average *average, SecFilt *secfilt) {
-
-  int Ns;
-  short Mi;
-  float Xm;
-
-  Ns = photcodes[0].hashNsec[code[0].code];
-  Mi = (Ns == -1) ? NO_MAG : secfilt[Ns].Xm;
-  Xm = (Mi == NO_MAG) ? -1.0 : pow (10.0, 0.01*Mi);
-  return (Xm);
-}
-
-/* given a photcode pair c1 & c2, return the color of this star (NaN if not found) */
-int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color) {
-
-  int i, Ns;
-  double M1, M2, dM;
-  PhotCode *code;
-  
-  code = GetPhotcodebyCode (c1);
-  if (code == NULL) return (FALSE);
-  if (code[0].type == PHOT_REF) {
-    for (i = 0; i < average[0].Nm; i++) {
-      if (measure[i].photcode == c1) {
-	M1 = measure[i].M;
-	goto filter1;
-      }
-    }	
-    return (FALSE);
-  } else {
-    Ns = photcodes[0].hashNsec[code[0].code];
-    M1 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
-  }	
-
-filter1:
-  code = GetPhotcodebyCode (c2);
-  if (code == NULL) return (FALSE);
-  if (code[0].type == PHOT_REF) {
-    for (i = 0; i < average[0].Nm; i++) {
-      if (measure[i].photcode == c2) {
-	M2 = measure[i].M;
-	goto filter2;
-      }
-    }	
-    return (FALSE);
-  } else {
-    Ns = photcodes[0].hashNsec[code[0].code];
-    M2 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
-  }	
-  
-filter2:
-
-  dM = M1 - M2;
-  *color = dM;
-  
-  return (TRUE);
-}
-
-/* photcode table should have the following format: 
-
-# code name     type  zero  airmass  offset  c1 c2  slope  <color>  primary
-1    B        pri   24.0  0.15     -       -  -   -      -        -
-2    B        pri   24.0  0.15     -       -  -   -      -        -
-3    B1       sec   22.5  0.18     0.15    1  2   0.10   0.50     1
-1000 USNO_B   ref   -     -        -       -  -   -      -        -
-
-*/
-
-
-/*
-  Nc1 = photcodes[0].code[Np].c1;
-  Ns1 = photcodes[0].hashNsec[Nc1];
-
-  Nc2 = photcodes[0].code[Np].c2;
-  Ns2 = photcodes[0].hashNsec[Nc2];
-
-  Xlam = photcodes[0].code[Np].X[0];
-  Klam = photcodes[0].code[Np].K;
-  
-  m1 = (Ns1 == -1) ? average[0].M : secfilt[Ns1].M;
-  m2 = (Ns2 == -1) ? average[0].M : secfilt[Ns2].M;
-*/
Index: /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodesFITS.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodesFITS.c	(revision 12031)
+++ /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodesFITS.c	(revision 12031)
@@ -0,0 +1,107 @@
+# include <dvo.h>
+
+/* this is a read-only function to load the FITS photcode file into the internal photcode table */
+/* locking is used to avoid collisions with programs trying to update the photcodes values */
+/* XXX better distinction between NOT FOUND and FAILURE */
+int LoadPhotcodesFITS (char *filename) {
+
+  PhotCodeData *table = NULL;
+  PhotCode *photcode;
+  FITS_DB db;
+
+  int i, code, Ncode, Nsec;
+
+  /* XXX choose more sensible lock timeouts! */
+  db.lockstate = LCK_SOFT;
+  db.timeout   = 10.0;
+  gfits_db_init (&db);
+
+  /* does this mean the db is empty, non-existent, or has access errors? */
+  if (!gfits_db_lock (&db, filename)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    return FALSE;
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    fprintf (stderr, "ERROR: db is empty\n");
+    gfits_db_close (&db);
+    return FALSE;
+  } 
+  if (!gfits_db_load (&db)) {
+    fprintf (stderr, "ERROR: failure to load db\n");
+    gfits_db_close (&db);
+    return FALSE;
+  }
+  gfits_db_close (&db);
+
+  /* convert FITS format data to internal format (just byteswaps) */
+  photcode = gfits_table_get_PhotCode (&db.ftable, &Ncode, &db.swapped);
+
+  table = GetPhotcodeTable ();
+  if (table[0].code != NULL) free (table[0].code);
+  /* we are using a 16-bit int for the photcodes, so these indexes can be fixed-length */
+  /* XXX if we need to go with a larger photcode, we'll need to use a sequenced index and a
+     binary search to get to a given value (0x100000000 ints would take quite a few
+     bytes...) */
+  for (i = 0; i < 0x10000; i++) {
+    table[0].hashcode[i] = -1;
+    table[0].hashNsec[i] = -1;
+    table[0].codeNsec[i] = -1;
+  }
+
+  /* set up photcode indexes (see dvo_photcode_ops.c) */
+  Nsec = 0;
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_ALT) continue; /* no hashcode for ALT codes */
+    if (table[0].hashcode[photcode[i].code] != -1) {
+      fprintf (stderr, "duplicate photcodes in file\n");
+      code = table[0].hashcode[photcode[i].code];
+      fprintf (stderr, "conflict between %s (%d) and %s (%d)\n",
+	       photcode[i].name, photcode[i].code, photcode[code].name, photcode[code].code);
+      free (photcode);
+      return FALSE;
+    }
+    table[0].hashcode[photcode[i].code] = i;
+    if (photcode[i].type == PHOT_SEC) {
+      table[0].hashNsec[photcode[i].code] = Nsec;
+      table[0].codeNsec[Nsec] = photcode[i].code;
+      Nsec ++;
+    }
+  }
+
+  /* validity check for references */
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_DEP) {
+      Nsec = table[0].hashcode[photcode[i].equiv];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for dependent photcode is not in photcodes\n");
+	free (photcode);
+	return FALSE;
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for dependent photcode is not an average photcode\n");
+	free (photcode);
+	return FALSE;
+      }
+    }
+    if (photcode[i].type == PHOT_ALT) {
+      Nsec = table[0].hashcode[photcode[i].code];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for alternate photcode is not in photcodes\n");
+	free (photcode);
+	return FALSE;
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for alternate photcode is not an average photcode\n");
+	free (photcode);
+	return FALSE;
+      }
+    }
+  }
+
+  table[0].code     = photcode;
+  table[0].Ncode    = Ncode;
+  table[0].Nsecfilt = Nsec;
+
+  return (TRUE);
+}
Index: /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodesText.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodesText.c	(revision 12031)
+++ /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/LoadPhotcodesText.c	(revision 12031)
@@ -0,0 +1,200 @@
+# include <dvo.h>
+
+/* load the text photcode table */
+int LoadPhotcodesText (char *filename) {
+  
+  /* XXX fix these */
+  PhotCodeData *table = NULL;
+  PhotCode *photcode;
+
+  FILE *f;
+  int i, Nsec, Ncode, NPHOTCODE, Nfield;
+  int code;
+  char *c;
+  char line[256];
+  char name[32], type[32], Zero[32], Airmass[32], Offset[32],
+    C1[32], C2[32], Slope[32], Color[32], Primary[32];
+  int c1, c2;
+
+  table = GetPhotcodeTable ();
+  if (table[0].code != NULL) free (table[0].code);
+  /* we are using a 16-bit int for the photcodes, so these indexes can be fixed-length */
+  /* XXX if we need to go with a larger photcode, we'll need to use a sequenced index and a
+     binary search to get to a given value (0x100000000 ints would take quite a few
+     bytes...) */
+  for (i = 0; i < 0x10000; i++) {
+    table[0].hashcode[i] = -1;
+    table[0].hashNsec[i] = -1;
+    table[0].codeNsec[i] = -1;
+  }
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    table[0].Ncode    = 0;
+    table[0].Nsecfilt = 0;
+    table[0].code     = (PhotCode *) NULL;
+    return (FALSE);
+  }
+
+  Ncode = 0;
+  NPHOTCODE = 10;
+  ALLOCATE (photcode, PhotCode, NPHOTCODE);
+
+  while (scan_line (f, line) != EOF) {
+    for (c = line; isspace (*c); c++);
+    if (*c == '#') continue;
+    Nfield = sscanf (c, "%d %s %s %s %s %s %s %s %s %s %s", 
+		     &code, name, type, Zero, Airmass, Offset, C1, C2, Slope, Color, Primary);
+    if (Nfield != 11) { continue; }
+    
+    c1 = atof (C1);
+    c2 = atof (C2);
+    if (!strcmp (C1, "-")) { c1 = 0; }
+    if (!strcmp (C2, "-")) { c2 = 0; }
+
+    photcode[Ncode].type = 0;
+    photcode[Ncode].code = code;
+    strcpy (photcode[Ncode].name, name);
+    if (!strncasecmp (type, "pri", 3)) {
+      photcode[Ncode].type  = PHOT_SEC;
+      photcode[Ncode].C     = 1000*atof (Zero);
+      photcode[Ncode].K     = atof (Airmass);
+      photcode[Ncode].dC    = 1000*atof (Offset);
+      photcode[Ncode].dX    = 1000*atof (Color);
+      photcode[Ncode].c1    = c1;
+      photcode[Ncode].c2    = c2;
+      photcode[Ncode].equiv = atoi (Primary);
+      ParseColorTerms (Slope, photcode[Ncode].X, &photcode[Ncode].Nc);
+    }      
+    if (!strncasecmp (type, "sec", 3)) {
+      photcode[Ncode].type  = PHOT_SEC;
+      photcode[Ncode].C     = 1000*atof (Zero);
+      photcode[Ncode].K     = atof (Airmass);
+      photcode[Ncode].dC    = 1000*atof (Offset);
+      photcode[Ncode].dX    = 1000*atof (Color);
+      photcode[Ncode].c1    = c1;
+      photcode[Ncode].c2    = c2;
+      photcode[Ncode].equiv = atoi (Primary);
+      ParseColorTerms (Slope, photcode[Ncode].X, &photcode[Ncode].Nc);
+    }      
+    if (!strncasecmp (type, "dep", 3)) {
+      photcode[Ncode].type  = PHOT_DEP;
+      photcode[Ncode].C     = 1000*atof (Zero);    /* zero point in millimags */
+      photcode[Ncode].K     = atof (Airmass);      /* airmass coeff (millimag / millimag) */
+      photcode[Ncode].dC    = 1000*atof (Offset);  /* color ref z.p. (millimag) */
+      photcode[Ncode].dX    = 1000*atof (Color);   /* average color (millimag) */
+      photcode[Ncode].c1    = c1;
+      photcode[Ncode].c2    = c2;
+      photcode[Ncode].equiv = atoi (Primary);
+      ParseColorTerms (Slope, photcode[Ncode].X, &photcode[Ncode].Nc);
+    }      
+    if (!strncasecmp (type, "ref", 3)) {
+      photcode[Ncode].type  = PHOT_REF;
+      photcode[Ncode].C     = 0;
+      photcode[Ncode].K     = 0;
+      photcode[Ncode].dC    = 0;
+      photcode[Ncode].dX    = 0;
+      photcode[Ncode].c1    = 0;
+      photcode[Ncode].c2    = 0;
+      photcode[Ncode].equiv = atoi (Primary);
+      photcode[Ncode].X[0]  = 0;
+      photcode[Ncode].Nc    = 0;
+    }
+
+    /* alt photcodes are a little different: they have the SAME photcode as an existing
+       pri/sec photcode, but define an alternate transformation for that code */
+    if (!strncasecmp (type, "alt", 3)) {
+      photcode[Ncode].type  = PHOT_ALT;
+      photcode[Ncode].C     = 1000*atof (Zero);    /* zero point in millimags */
+      photcode[Ncode].K     = atof (Airmass);      /* airmass coeff (millimag / millimag) */
+      photcode[Ncode].dC    = 1000*atof (Offset);  /* color ref z.p. (millimag) */
+      photcode[Ncode].dX    = 1000*atof (Color);   /* average color (millimag) */
+      photcode[Ncode].c1    = c1;
+      photcode[Ncode].c2    = c2;
+      photcode[Ncode].equiv = atoi (Primary);
+      ParseColorTerms (Slope, photcode[Ncode].X, &photcode[Ncode].Nc);
+    }
+    if (!photcode[Ncode].type) {
+      fprintf (stderr, "error in Photfile: unknown type %s\n", type);
+    }
+
+    Ncode++;
+    if (Ncode == NPHOTCODE) {
+      NPHOTCODE += 10;
+      REALLOCATE (photcode, PhotCode, NPHOTCODE);
+    }
+  }
+  fclose (f);
+  
+  /* set up photcode indexes (see dvo_photcode_ops.c) */
+  Nsec = 0;
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_ALT) continue; /* no hashcode for ALT codes */
+    if (table[0].hashcode[photcode[i].code] != -1) {
+      fprintf (stderr, "duplicate photcodes in file\n");
+      code = table[0].hashcode[photcode[i].code];
+      fprintf (stderr, "conflict between %s (%d) and %s (%d)\n",
+	       photcode[i].name, photcode[i].code, photcode[code].name, photcode[code].code);
+      free (photcode);
+      return (FALSE);
+    }
+    table[0].hashcode[photcode[i].code] = i;
+    if (photcode[i].type == PHOT_SEC) {
+      table[0].hashNsec[photcode[i].code] = Nsec;
+      table[0].codeNsec[Nsec] = photcode[i].code;
+      Nsec ++;
+    }
+  }
+  table[0].Nsecfilt = Nsec;
+
+  /* validity check for references */
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_DEP) {
+      Nsec = table[0].hashcode[photcode[i].equiv];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for dependent photcode is not in photcodes\n");
+	free (photcode);
+	return (FALSE);
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for dependent photcode is not an average photcode\n");
+	free (photcode);
+	return (FALSE);
+      }
+    }
+    if (photcode[i].type == PHOT_ALT) {
+      Nsec = table[0].hashcode[photcode[i].code];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for alternate photcode is not in photcodes\n");
+	free (photcode);
+	return (FALSE);
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for alternate photcode is not an average photcode\n");
+	free (photcode);
+	return (FALSE);
+      }
+    }
+  }
+  table[0].code = photcode;
+  table[0].Ncode = Ncode;
+
+  return (TRUE);
+}
+
+# define NCTERMS 4
+void ParseColorTerms (char *terms, float *X, int *N) {
+
+  int i;
+  char *p;
+
+  p = terms;
+
+  for (i = 0; (p != NULL) && (i < NCTERMS); i++) {
+    X[i] = atof (p);
+    p = strchr (p, ',');
+    if (p == (char *) NULL) continue;
+    p ++;
+  }
+  *N = i;
+}
Index: /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/dvo_photcode_ops.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/dvo_photcode_ops.c	(revision 12031)
+++ /branches/dvo-mods-2007-02/Ohana/src/libdvo/src/dvo_photcode_ops.c	(revision 12031)
@@ -0,0 +1,519 @@
+# include <dvo.h>
+
+/* we use a static variable to save the pre-loaded the photcodes.
+   photcode conversion functions refer to this table for ref values */
+
+/* We have three indexes:
+
+   table[0].hashcode provides the table photcode sequence for a photcode value
+   table[0].hashNsec provides the Nsec sequence for a photcode value
+   table[0].codeNsec provides the photcode value for an Nsec sequence
+
+   given photcode = table[0].code[i] and code = photcode[0].code
+
+   hashcode[code] = i
+   hashNsec[code] = Nsec or -1 if not a PRI/SEC code
+   codeNsec[Nsec] = code
+*/
+
+static PhotCodeData *photcodes = NULL;
+
+PhotCodeData *GetPhotcodeTable () {
+
+  /* allocate space to photcode table, free existing data */
+  if (photcodes == NULL) {
+    ALLOCATE (photcodes, PhotCodeData, 1);
+    photcodes[0].code = NULL;
+  }
+  return photcodes;
+}
+
+/* the static ZERO_POINT is used by programs as an approximate nominal */
+static double ZERO_POINT;
+
+void SetZeroPoint (double ZP) {
+  ZERO_POINT = ZP;
+}
+
+# define SCALE 0.001
+
+/********** photcode lookup functions **********/
+
+/* return photcode for given name */
+PhotCode *GetPhotcodebyName (char *name) {
+  
+  int i;
+
+  if (name == NULL) return (NULL);
+  
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      return (&photcodes[0].code[i]);
+    }
+  }
+  return (NULL);
+}
+/* return photcode.code for given name */
+int GetPhotcodeCodebyName (char *name) {
+  
+  int i;
+  
+  if (name == NULL) return (0);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      return (photcodes[0].code[i].code);
+    }
+  }
+  return (0);
+}
+/* return equivalent photcode for given name */
+PhotCode *GetPhotcodeEquivbyName (char *name) {
+  
+  int i, equiv;
+  
+  if (name == NULL) return (NULL);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      if (photcodes[0].code[i].equiv == 0) return (NULL);
+      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
+      if (equiv == -1) return (NULL);
+      return (&photcodes[0].code[equiv]);
+    }
+  }
+  return (NULL);
+}
+/* return equivalent photcode.code for given name */
+int GetPhotcodeEquivCodebyName (char *name) {
+  
+  int i, equiv;
+  
+  if (name == NULL) return (0);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      if (photcodes[0].code[i].equiv == 0) return (0);
+      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
+      if (equiv == -1) return (0);
+      return (photcodes[0].code[equiv].code);
+    }
+  }
+  return (0);
+}
+
+/* return photcode for given code */
+PhotCode *GetPhotcodebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  return (&photcodes[0].code[entry]);
+}
+/* return photcode.code for given code */
+char *GetPhotcodeNamebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  return (photcodes[0].code[entry].name);
+}
+/* return equivalent photcode for given code */
+PhotCode *GetPhotcodeEquivbyCode (int code) {
+  
+  int entry, equiv;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  if (photcodes[0].code[entry].equiv == 0) return (NULL);
+  equiv = photcodes[0].hashcode[photcodes[0].code[entry].equiv];
+
+  if (equiv == -1) return (NULL);
+  return (&photcodes[0].code[equiv]);
+}
+/* return equivalent photcode.code for given code */
+int GetPhotcodeEquivCodebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (0);
+  if (code > 0x10000) return (0);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (0);
+  return (photcodes[0].code[entry].equiv);
+}
+
+int GetPhotcodeNsec (int code) {
+  
+  int Nsec;
+  
+  if (code < 0) return (-1);
+  if (code > 0x10000) return (-1);
+
+  Nsec = photcodes[0].hashNsec[code];
+  return (Nsec);
+}
+
+/* Nsec of 0 is PRI */
+PhotCode *GetPhotcodebyNsec (int Nsec) {
+  
+  if (Nsec > photcodes[0].Nsecfilt) return (NULL);
+  if (Nsec < 0) return (NULL);
+  
+  return (&photcodes[0].code[photcodes[0].codeNsec[Nsec]]);
+}
+
+int GetPhotcodeNsecfilt () {
+  return (photcodes[0].Nsecfilt);
+}
+
+/* ALLOCATE and return list of all photcodes
+   with photcode.equiv == code */
+int *GetPhotcodeEquivList (int code, int *nlist) {
+
+  int i, Nlist;
+  int *list;
+
+  ALLOCATE (list, int, MAX (1, photcodes[0].Ncode));
+  Nlist = 0;
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (photcodes[0].code[i].equiv != code) continue;
+    list[Nlist] = photcodes[0].code[i].code;
+    Nlist ++;
+  }
+  REALLOCATE (list, int, MAX (1, Nlist));
+
+  *nlist = Nlist;
+  return (list);
+}
+
+/******** photometry conversion functions *********/
+float PhotInst (Measure *measure) {
+
+  int Np;
+  float M;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    M = measure[0].M;
+    return (M);
+  }
+
+  M = measure[0].M - measure[0].dt - ZERO_POINT;
+	  
+  return (M);
+
+}
+
+float PhotCat (Measure *measure) {
+
+  int Np;
+  float Mcat;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mcat = measure[0].M;
+    return (Mcat);
+  }
+  code = &photcodes[0].code[Np];
+  Mcat = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + SCALE*code[0].C;
+  
+  return (Mcat);
+}
+
+float PhotSys (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  int i, Np;
+  float Mcat, Mcol, Msys, mc, Mc;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Msys = measure[0].M;
+    return (Msys);
+  }
+  code = &photcodes[0].code[Np];
+  Mcat = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + SCALE*code[0].C;
+
+  /* for DEP, color must be made of PRI/SEC */
+  mc = PhotColorForCode (average, secfilt, NULL, code);
+  if (mc == NO_MAG) return (Mcat);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;
+  }
+  Msys = Mcat + Mcol;
+  return (Msys);
+}
+
+float PhotRel (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  int i, Np;
+  float Mcat, Mcol, Mrel, mc, Mc;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mcat = measure[0].M;
+    return (Mcat);
+  }
+  code = &photcodes[0].code[Np];
+  Mrel = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + SCALE*code[0].C - measure[0].Mcal;
+
+  /* for DEP, color must be made of PRI/SEC */
+  mc = PhotColorForCode (average, secfilt, NULL, code);
+  if (mc == NO_MAG) return (Mrel);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Mrel += Mcol;
+  return (Mrel);
+}
+
+/* return calibrated magnitude from measure for given photcode */
+float PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
+
+  int i, Np; 
+  float Mcal, Mrel, Mcol, mc, Mc;
+
+  /* code must be the matching PRI/SEC code for this measurement or an equivalent ALT */
+  Np = photcodes[0].hashcode[thisone[0].photcode];
+  if (Np == -1) {
+    return (NO_MAG);
+  }
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mrel = thisone[0].M;
+    return (Mrel);
+  }
+  if (code[0].code != photcodes[0].code[Np].equiv) {
+    return (NO_MAG);
+  }
+
+  Mcal = PhotRel (thisone, average, secfilt) + SCALE*code[0].C;
+
+  mc = PhotColorForCode (average, secfilt, measure, code);
+  if (mc == NO_MAG) return (Mcal);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;
+  }
+  Mcal += Mcol;
+  return (Mcal);
+}
+
+/* color term may not use DEP magnitude */
+float PhotColorForCode (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
+
+  int i, Ns1, Ns2, Ns;
+  float m1, m2, mc;
+  PhotCode *color;
+
+  m1 = m2 = NO_MAG;
+
+  if (measure == NULL) {
+    Ns1 = photcodes[0].hashNsec[code[0].c1];
+    Ns2 = photcodes[0].hashNsec[code[0].c2];
+  
+    m1 = (Ns1 == -1) ? NO_MAG : secfilt[Ns1].M;
+    m2 = (Ns2 == -1) ? NO_MAG : secfilt[Ns2].M;
+    mc = ((m1 == NO_MAG) || (m2 == NO_MAG)) ? NO_MAG : (m1 - m2);
+    return (mc);
+  }
+
+  /* find magnitude matching first color term */
+  color = GetPhotcodebyCode (code[0].c1);
+  if (color == NULL) return (NO_MAG);
+  if (color[0].type == PHOT_REF) {
+    for (i = 0; (i < average[0].Nm) && (m1 == NO_MAG); i++) {
+      if (measure[i].photcode == color[0].code) {
+	m1 = measure[i].M;
+      }
+    }
+  } else {
+    Ns = photcodes[0].hashNsec[color[0].code];
+    m1 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
+  }	
+
+  /* find magnitude matching second color term */
+  color = GetPhotcodebyCode (code[0].c2);
+  if (color == NULL) return (NO_MAG);
+  if (color[0].type == PHOT_REF) {
+    for (i = 0; (i < average[0].Nm) && (m2 == NO_MAG); i++) {
+      if (measure[i].photcode == color[0].code) {
+	m2 = measure[i].M;
+      }
+    }
+  } else {
+    Ns = photcodes[0].hashNsec[color[0].code];
+    m2 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
+  }	
+  mc = ((m1 == NO_MAG) || (m2 == NO_MAG)) ? NO_MAG : (m1 - m2);
+  return (mc);
+}
+
+/* return calibrated magnitude from average/secfilt for given photcode */
+float PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
+
+  int i, Ns;
+  float Mave, Mref, Mcol, mc;
+  double Mc;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mave = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
+  Mref = Mave + SCALE*code[0].C;
+
+  mc = PhotColorForCode (average, secfilt, measure, code);
+  if (mc == NO_MAG) return (Mref);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Mref += Mcol;
+  return (Mref);
+}
+
+/***/
+float PhotAve (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  float Mave;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mave = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
+  return (Mave);
+}
+
+float PhotdM (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  float dM;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  dM  = (Ns == -1) ? NO_MAG : secfilt[Ns].dM;
+  return (dM);
+}
+
+float PhotXm (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  short Mi;
+  float Xm;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mi = (Ns == -1) ? NO_MAG : secfilt[Ns].Xm;
+  Xm = (Mi == NO_MAG) ? -1.0 : pow (10.0, 0.01*Mi);
+  return (Xm);
+}
+
+/* given a photcode pair c1 & c2, return the color of this star (NaN if not found) */
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color) {
+
+  int i, Ns;
+  double M1, M2, dM;
+  PhotCode *code;
+  
+  code = GetPhotcodebyCode (c1);
+  if (code == NULL) return (FALSE);
+  if (code[0].type == PHOT_REF) {
+    for (i = 0; i < average[0].Nm; i++) {
+      if (measure[i].photcode == c1) {
+	M1 = measure[i].M;
+	goto filter1;
+      }
+    }	
+    return (FALSE);
+  } else {
+    Ns = photcodes[0].hashNsec[code[0].code];
+    M1 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
+  }	
+
+filter1:
+  code = GetPhotcodebyCode (c2);
+  if (code == NULL) return (FALSE);
+  if (code[0].type == PHOT_REF) {
+    for (i = 0; i < average[0].Nm; i++) {
+      if (measure[i].photcode == c2) {
+	M2 = measure[i].M;
+	goto filter2;
+      }
+    }	
+    return (FALSE);
+  } else {
+    Ns = photcodes[0].hashNsec[code[0].code];
+    M2 = (Ns == -1) ? NO_MAG : secfilt[Ns].M;
+  }	
+  
+filter2:
+
+  dM = M1 - M2;
+  *color = dM;
+  
+  return (TRUE);
+}
+
+/* photcode table should have the following format: 
+
+# code name     type  zero  airmass  offset  c1 c2  slope  <color>  primary
+1    B        pri   24.0  0.15     -       -  -   -      -        -
+2    B        pri   24.0  0.15     -       -  -   -      -        -
+3    B1       sec   22.5  0.18     0.15    1  2   0.10   0.50     1
+1000 USNO_B   ref   -     -        -       -  -   -      -        -
+
+*/
+
+
+/*
+  Nc1 = photcodes[0].code[Np].c1;
+  Ns1 = photcodes[0].hashNsec[Nc1];
+
+  Nc2 = photcodes[0].code[Np].c2;
+  Ns2 = photcodes[0].hashNsec[Nc2];
+
+  Xlam = photcodes[0].code[Np].X[0];
+  Klam = photcodes[0].code[Np].K;
+  
+  m1 = (Ns1 == -1) ? average[0].M : secfilt[Ns1].M;
+  m2 = (Ns2 == -1) ? average[0].M : secfilt[Ns2].M;
+*/
Index: /branches/dvo-mods-2007-02/Ohana/src/markrock/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/markrock/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/markrock/src/ConfigInit.c	(revision 12031)
@@ -4,5 +4,6 @@
 
   char *config, *file;
-  char PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -20,4 +21,5 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
 
   /* unique to markrock */
@@ -30,5 +32,4 @@
   ScanConfig (config, "ROCK_MAX_DELAY",         "%lf", 0, &MAX_DELAY);
   ScanConfig (config, "ROCK_CATALOG",           "%s",  0, RockCat);
-  ScanConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
 
   ScanConfig (config, "BRIGHT_HALO_MAG",        "%lf", 0, &BRIGHT_HALO_MAG);
@@ -41,7 +42,9 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile, &photcodes)) {
-    fprintf (stderr, "error loading photcodes\n");
-    exit (0);
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
   }
 
Index: /branches/dvo-mods-2007-02/Ohana/src/markstar/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/markstar/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/markstar/src/ConfigInit.c	(revision 12031)
@@ -4,5 +4,6 @@
 
   char *config, *file;
-  char PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -20,4 +21,5 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
 
   sprintf (ImageCat, "%s/Images.dat", CATDIR);
@@ -46,12 +48,13 @@
   ScanConfig (config, "OPTICAL_AXIS1",   "%lf", 0, &OPTICAL_AXIS1);
   ScanConfig (config, "OPTICAL_AXIS2",   "%lf", 0, &OPTICAL_AXIS2);
-  ScanConfig (config, "PHOTCODE_FILE",          "%s", 0, PhotCodeFile);
  
   if (*CATMODE == 0) strcpy (CATMODE, "RAW");
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile, &photcodes)) {
-    fprintf (stderr, "error loading photcodes\n");
-    exit (0);
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
   }
 
Index: /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/dmt.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/dmt.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/dmt.c	(revision 12031)
@@ -44,6 +44,6 @@
     return (FALSE);
   }
-  if ((code[0].type != PHOT_SEC) && (code[0].type != PHOT_PRI)) {
-    gprint (GP_ERR, "first filter must be a PRIMARY or SECONDARY photometry type\n");
+  if (code[0].type != PHOT_SEC) {
+    gprint (GP_ERR, "first filter must be a average photometry type\n");
     return (FALSE);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/extract.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/extract.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/extract.c	(revision 12031)
@@ -119,6 +119,6 @@
   if (PhotcodeSelect) {
     Ns = GetPhotcodeNsec (code[0].code);
-    if ((mode != REF) && (code[0].type != PHOT_SEC) && (code[0].type != PHOT_PRI)) {
-      gprint (GP_ERR, "filter must be a PRIMARY or SECONDARY photometry type\n");
+    if ((mode != REF) && (code[0].type != PHOT_SEC)) {
+      gprint (GP_ERR, "filter must be a average photometry type\n");
       return (FALSE);
     }
Index: /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/gimages.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/gimages.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/gimages.c	(revision 12031)
@@ -83,5 +83,5 @@
 	if (code[0].code != image[i].photcode) continue;
       } 
-      if ((code[0].type == PHOT_PRI) || (code[0].type == PHOT_SEC)) {
+      if (code[0].type == PHOT_SEC) {
 	if (code[0].code != GetPhotcodeEquivCodebyCode (image[i].photcode)) continue;
       } 
Index: /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/imextract.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/imextract.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/imextract.c	(revision 12031)
@@ -63,5 +63,5 @@
       return (FALSE);
     }
-    if ((code[0].type != PHOT_PRI) && (code[0].type != PHOT_SEC) && (code[0].type != PHOT_DEP)) {
+    if ((code[0].type != PHOT_SEC) && (code[0].type != PHOT_DEP)) {
       gprint (GP_ERR, "photcode must be primary, secondary, or dependent code\n");
       return (FALSE);
Index: /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/lightcurve.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/lightcurve.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/lightcurve.c	(revision 12031)
@@ -112,5 +112,5 @@
 	    if (code[0].code != catalog.measure[m].photcode) continue;
 	  } 
-	  if ((code[0].type == PHOT_PRI) || (code[0].type == PHOT_SEC)) {
+	  if (code[0].type == PHOT_SEC) {
 	    if (code[0].code != GetPhotcodeEquivCodebyCode (catalog.measure[m].photcode)) continue;
 	  } 
Index: /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/photometry.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/photometry.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/opihi/dvo/photometry.c	(revision 12031)
@@ -9,5 +9,4 @@
       if (C[0].code != M.photcode) continue; \
       break; \
-    case PHOT_PRI: \
     case PHOT_SEC: \
       if (C[0].code != GetPhotcodeEquivCodebyCode (M.photcode)) continue; \
@@ -134,5 +133,5 @@
     if (mode == MAG_CAL)  status = TRUE;
   }  
-  if ((code[0].type == PHOT_PRI) || (code[0].type == PHOT_SEC)) {
+  if (code[0].type == PHOT_SEC) {
     if (mode == MAG_NONE) mode  = MAG_AVE;
     if (mode == MAG_INST) status = TRUE;
@@ -302,7 +301,6 @@
   }
   if (NeedPhotcode) {
-    if (code[0][0].type == PHOT_PRI) return (TRUE);
     if (code[0][0].type == PHOT_SEC) return (TRUE);
-    gprint (GP_ERR, "photcode selection problem: average value requires PRI/SEC photcode\n");
+    gprint (GP_ERR, "photcode selection problem: average value requires average photcode\n");
     return (FALSE);
   }
@@ -322,5 +320,7 @@
 
   double ZERO_POINT;
-  char PhotCodeFile[256];
+  char MasterPhotcodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char *catdir;
 
   if (VarConfig ("ZERO_PT", "%lf", &ZERO_POINT) == (char *) NULL) {
@@ -330,10 +330,17 @@
   SetZeroPoint (ZERO_POINT);
 
-  if (VarConfig ("PHOTCODE_FILE", "%s", PhotCodeFile) == (char *) NULL) {
+  catdir = GetCATDIR();
+  if (catdir == NULL) {
+    CatdirPhotcodeFile[0] = 0;
+  } else {
+    sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", catdir);
+  }
+
+  if (VarConfig ("PHOTCODE_FILE", "%s", MasterPhotcodeFile) == (char *) NULL) {
       gprint (GP_ERR, "PHOTCODE_FILE undefined in config\n");
       return (FALSE);
   }
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    gprint (GP_ERR, "error loading photcodes\n");
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    gprint (GP_ERR, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
     return (FALSE);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/photdbc/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/photdbc/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/photdbc/src/ConfigInit.c	(revision 12031)
@@ -13,4 +13,6 @@
 
   char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -46,7 +48,8 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
   sprintf (ImageCat, "%s/Images.dat", CATDIR);
 
-  WarnConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
   WarnConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
 
@@ -61,6 +64,8 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes\n");
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
     exit (1);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/relastro/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/relastro/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/relastro/src/ConfigInit.c	(revision 12031)
@@ -5,5 +5,6 @@
   double ZERO_POINT;
   char  *config, *file;
-  char   PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -32,4 +33,6 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
   sprintf (ImageCat, "%s/Images.dat", CATDIR);
 
@@ -41,5 +44,4 @@
   }
 
-  GetConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
   GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
 
@@ -52,6 +54,8 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes\n");
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
     exit (1);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/relastro/src/initialize.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/relastro/src/initialize.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/relastro/src/initialize.c	(revision 12031)
@@ -13,10 +13,9 @@
     exit (1);
   }
-  if ((photcode[0].type != PHOT_PRI) && (photcode[0].type != PHOT_SEC)) {
+  if (photcode[0].type != PHOT_SEC) {
     fprintf (stderr, "photcode %s is not a primary or secondary filter\n", argv[N]);
     exit (1);
   }
 
-  PhotPrimary = (photcode[0].type == PHOT_PRI);
   PhotNsec = GetPhotcodeNsecfilt ();
   PhotSec = GetPhotcodeNsec (photcode[0].code);
Index: /branches/dvo-mods-2007-02/Ohana/src/relphot/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/relphot/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/relphot/src/ConfigInit.c	(revision 12031)
@@ -5,5 +5,6 @@
   double ZERO_POINT;
   char  *config, *file;
-  char   PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -32,4 +33,6 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
   sprintf (ImageCat, "%s/Images.dat", CATDIR);
 
@@ -41,5 +44,4 @@
   }
 
-  GetConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
   GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
 
@@ -52,6 +54,8 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes\n");
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
     exit (1);
   }
Index: /branches/dvo-mods-2007-02/Ohana/src/relphot/src/initialize.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/relphot/src/initialize.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/relphot/src/initialize.c	(revision 12031)
@@ -13,5 +13,5 @@
     exit (1);
   }
-  if ((photcode[0].type != PHOT_PRI) && (photcode[0].type != PHOT_SEC)) {
+  if (photcode[0].type != PHOT_SEC) {
     fprintf (stderr, "photcode %s is not a primary or secondary filter\n", argv[N]);
     exit (1);
Index: /branches/dvo-mods-2007-02/Ohana/src/uniphot/src/ConfigInit.c
===================================================================
--- /branches/dvo-mods-2007-02/Ohana/src/uniphot/src/ConfigInit.c	(revision 12030)
+++ /branches/dvo-mods-2007-02/Ohana/src/uniphot/src/ConfigInit.c	(revision 12031)
@@ -5,5 +5,6 @@
   double ZERO_POINT;
   char  *config, *file;
-  char   PhotCodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
 
   /*** load configuration info ***/
@@ -20,7 +21,8 @@
   ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
   ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
   sprintf (ImageCat, "%s/Images.dat", CATDIR);
 
-  ScanConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
   ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
   SetZeroPoint (ZERO_POINT);
@@ -32,7 +34,9 @@
   if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
 
-  if (!LoadPhotcodes (PhotCodeFile)) {
-    fprintf (stderr, "error loading photcodes\n");
-    exit (0);
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
   }
 
