Index: trunk/Ohana/src/libdvo/Makefile
===================================================================
--- trunk/Ohana/src/libdvo/Makefile	(revision 15621)
+++ trunk/Ohana/src/libdvo/Makefile	(revision 15694)
@@ -36,4 +36,7 @@
 $(SRC)/version.$(ARCH).o	 \
 $(SRC)/coordops.$(ARCH).o	 \
+$(SRC)/dvo_photcode_ops.$(ARCH).o \
+$(SRC)/dvo_photcode_convert_elixir.$(ARCH).o \
+$(SRC)/dvo_photcode_convert_ps1_dev_1.$(ARCH).o \
 $(SRC)/dvo_photcode_ops.$(ARCH).o \
 $(SRC)/LoadPhotcodes.$(ARCH).o   \
Index: trunk/Ohana/src/libdvo/include/elixir_defs.h
===================================================================
--- trunk/Ohana/src/libdvo/include/elixir_defs.h	(revision 15621)
+++ trunk/Ohana/src/libdvo/include/elixir_defs.h	(revision 15694)
@@ -7,2 +7,5 @@
 SecFilt 	       	*SecFilt_Elixir_ToInternal (SecFilt_Elixir *in, int Nvalues);
 SecFilt_Elixir 	       	*SecFiltInternalTo_Elixir (SecFilt *in, int Nvalues);
+
+PhotCode *PhotCode_Elixir_To_Internal (PhotCode_Elixir *in, int Nvalues);
+PhotCode_Elixir *PhotCode_Internal_To_Elixir (PhotCode *in, int Nvalues);
Index: trunk/Ohana/src/libdvo/include/ps1_dev_1_defs.h
===================================================================
--- trunk/Ohana/src/libdvo/include/ps1_dev_1_defs.h	(revision 15621)
+++ trunk/Ohana/src/libdvo/include/ps1_dev_1_defs.h	(revision 15694)
@@ -7,2 +7,5 @@
 SecFilt 	       	*SecFilt_PS1_DEV_1_ToInternal (SecFilt_PS1_DEV_1 *in, int Nvalues);
 SecFilt_PS1_DEV_1       *SecFiltInternalTo_PS1_DEV_1 (SecFilt *in, int Nvalues);
+
+PhotCode *PhotCode_PS1_DEV_1_To_Internal (PhotCode_PS1_DEV_1 *in, int Nvalues);
+PhotCode_PS1_DEV_1 *PhotCode_Internal_To_PS1_DEV_1 (PhotCode *in, int Nvalues);
Index: trunk/Ohana/src/libdvo/src/LoadPhotcodesFITS.c
===================================================================
--- trunk/Ohana/src/libdvo/src/LoadPhotcodesFITS.c	(revision 15621)
+++ trunk/Ohana/src/libdvo/src/LoadPhotcodesFITS.c	(revision 15694)
@@ -9,4 +9,5 @@
   PhotCode *photcode;
   FITS_DB db;
+  char extname[80];
 
   int i, code, Ncode, Nsec, Nsecfilt;
@@ -37,5 +38,17 @@
 
   /* convert FITS format data to internal format (just byteswaps) */
-  photcode = gfits_table_get_PhotCode (&db.ftable, &Ncode, &db.swapped);
+  gfits_scan (&db.theader, "EXTNAME", "%s", 1, extname);
+
+  if (!strcmp (extname, "DVO_PHOTCODE") || !strcmp (extname, "DVO_PHOTCODE_ELIXIR")) {
+    PhotCode_Elixir *photcode_elixir = gfits_table_get_PhotCode_Elixir (&db.ftable, &Ncode, &db.swapped);
+    photcode = PhotCode_Elixir_To_Internal (photcode_elixir, Ncode);
+    free (photcode_elixir);
+  } 
+
+  if (!strcmp (extname, "DVO_PHOTCODE_PS1_DEV_1")) {
+    PhotCode_PS1_DEV_1 *photcode_ps1_dev_1 = gfits_table_get_PhotCode_PS1_DEV_1 (&db.ftable, &Ncode, &db.swapped);
+    photcode = PhotCode_PS1_DEV_1_To_Internal (photcode_ps1_dev_1, Ncode);
+    free (photcode_ps1_dev_1);
+  } 
 
   table = GetPhotcodeTable ();
Index: trunk/Ohana/src/libdvo/src/LoadPhotcodesText.c
===================================================================
--- trunk/Ohana/src/libdvo/src/LoadPhotcodesText.c	(revision 15621)
+++ trunk/Ohana/src/libdvo/src/LoadPhotcodesText.c	(revision 15694)
@@ -1,3 +1,17 @@
 # include <dvo.h>
+
+static int PhotcodeNumberOrName (char *word) {
+
+  int value;
+  char *endpt;
+
+  if (!strcmp (word, "-")) return (0);
+
+  value = strtol (word, &endpt, 10);
+  if (endpt != word + strlen(word)) {
+    value = GetPhotcodeCodebyName (word);
+  }
+  return (value);
+}
 
 /* load the text photcode table */
@@ -12,8 +26,7 @@
   int code;
   char *c;
-  char line[256];
+  char line[256], **c1_names, **c2_names, **eq_names;
   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 ();
@@ -40,4 +53,7 @@
   NPHOTCODE = 10;
   ALLOCATE (photcode, PhotCode, NPHOTCODE);
+  ALLOCATE (eq_names, char *,   NPHOTCODE);
+  ALLOCATE (c1_names, char *,   NPHOTCODE);
+  ALLOCATE (c2_names, char *,   NPHOTCODE);
 
   while (scan_line (f, line) != EOF) {
@@ -46,11 +62,10 @@
     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);
+
+    // XXX to add the AstromError (and PhotError) terms, we need to add them to the photcode structure, and
+    // define methods to read (at least) the old and the new photcode versions.
+
     if (Nfield != 11) { continue; }
     
-    c1 = atof (C1);
-    c2 = atof (C2);
-    if (!strcmp (C1, "-")) { c1 = 0; }
-    if (!strcmp (C2, "-")) { c2 = 0; }
-
     if (!code) {
 	fprintf (stderr, "photcode values may not be 0: fix %s\n", name);
@@ -62,63 +77,54 @@
     memset (photcode[Ncode].name, 0, 32);
     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)) {
+      /* 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 */
       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);
-    }
+    }
+
+    switch (photcode[Ncode].type) {
+      case PHOT_SEC:
+      case PHOT_ALT:
+      case PHOT_DEP:
+	photcode[Ncode].C     = 1000*atof (Zero);
+	photcode[Ncode].K     = atof (Airmass);
+	photcode[Ncode].dC    = 1000*atof (Offset);
+	photcode[Ncode].dX    = 1000*atof (Color);
+	c1_names[Ncode]       = strcreate (C1);
+	c2_names[Ncode]       = strcreate (C2);
+	eq_names[Ncode]       = strcreate (Primary);
+	ParseColorTerms (Slope, photcode[Ncode].X, &photcode[Ncode].Nc);
+	break;
+
+      case PHOT_REF:
+	photcode[Ncode].C     = 0;
+	photcode[Ncode].K     = 0;
+	photcode[Ncode].dC    = 0;
+	photcode[Ncode].dX    = 0;
+	c1_names[Ncode]       = strcreate ("0");
+	c2_names[Ncode]       = strcreate ("0");
+	eq_names[Ncode]       = strcreate (Primary);
+	photcode[Ncode].X[0]  = 0;
+	photcode[Ncode].Nc    = 0;
+	break;
+
+      default:
+	fprintf (stderr, "error: invalid photcode type\n");
+	exit (2);
+    }      
+
     if (!photcode[Ncode].type) {
       fprintf (stderr, "error in Photfile: unknown type %s\n", type);
@@ -129,8 +135,24 @@
       NPHOTCODE += 10;
       REALLOCATE (photcode, PhotCode, NPHOTCODE);
+      REALLOCATE (eq_names, char *,   NPHOTCODE);
+      REALLOCATE (c1_names, char *,   NPHOTCODE);
+      REALLOCATE (c2_names, char *,   NPHOTCODE);
     }
   }
   fclose (f);
   
+  // convert the named references (c1, c2, equiv) to code values
+  for (i = 0; i < Ncode; i++) {
+    photcode[i].c1    = PhotcodeNumberOrName (c1_names[i]);
+    photcode[i].c2    = PhotcodeNumberOrName (c2_names[i]);
+    photcode[i].equiv = PhotcodeNumberOrName (eq_names[i]);
+    free (c1_names[i]);
+    free (c2_names[i]);
+    free (eq_names[i]);
+  }
+  free (c1_names);
+  free (c2_names);
+  free (eq_names);
+
   /* set up photcode indexes (see dvo_photcode_ops.c) */
   Nsecfilt = 0;
Index: trunk/Ohana/src/libdvo/src/SavePhotcodesFITS.c
===================================================================
--- trunk/Ohana/src/libdvo/src/SavePhotcodesFITS.c	(revision 15621)
+++ trunk/Ohana/src/libdvo/src/SavePhotcodesFITS.c	(revision 15694)
@@ -27,12 +27,16 @@
   }
 
-  /* convert FITS format data to internal format (just byteswaps) */
+  // for the moment, we simply support the latest photcode format for output
+  // XXX update this as needed as new formats are defined
+  PhotCode_PS1_DEV_1 *photcode_output = PhotCode_Internal_To_PS1_DEV_1 (table[0].code, table[0].Ncode);
+
+  /* convert FITS format data to internal format (byteswaps & EXTNAME) */
   gfits_db_create (&db);
-  gfits_table_set_PhotCode (&db.ftable, table[0].code, table[0].Ncode);
+  gfits_table_set_PhotCode_PS1_DEV_1 (&db.ftable, photcode_output, table[0].Ncode);
   gfits_db_save (&db);
   gfits_db_close (&db);
 
-  /* gfits_table_set_PhotCode performs the needed byte swap.  swap back */
-  gfits_convert_PhotCode (table[0].code, sizeof(PhotCode), table[0].Ncode);
+  free (photcode_output);
+
   return TRUE;
 }
Index: trunk/Ohana/src/libdvo/src/dvo_photcode_convert_elixir.c
===================================================================
--- trunk/Ohana/src/libdvo/src/dvo_photcode_convert_elixir.c	(revision 15694)
+++ trunk/Ohana/src/libdvo/src/dvo_photcode_convert_elixir.c	(revision 15694)
@@ -0,0 +1,57 @@
+# include <dvo.h>
+
+PhotCode_Elixir *PhotCode_Internal_To_Elixir (PhotCode *in, int Nvalues) {
+
+  int i;
+  PhotCode_Elixir *out;
+
+  ALLOCATE (out, PhotCode_Elixir, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+  }
+  return (out);
+}
+
+PhotCode *PhotCode_Elixir_To_Internal (PhotCode_Elixir *in, int Nvalues) {
+
+  int i;
+  PhotCode *out;
+
+  ALLOCATE (out, PhotCode, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    // not defined in Elixir:
+    out[i].astromScale = 1.0;
+    out[i].photSysErr = 1.0;
+  }
+  return (out);
+}
Index: trunk/Ohana/src/libdvo/src/dvo_photcode_convert_ps1_dev_1.c
===================================================================
--- trunk/Ohana/src/libdvo/src/dvo_photcode_convert_ps1_dev_1.c	(revision 15694)
+++ trunk/Ohana/src/libdvo/src/dvo_photcode_convert_ps1_dev_1.c	(revision 15694)
@@ -0,0 +1,59 @@
+# include <dvo.h>
+
+PhotCode_PS1_DEV_1 *PhotCode_Internal_To_PS1_DEV_1 (PhotCode *in, int Nvalues) {
+
+  int i;
+  PhotCode_PS1_DEV_1 *out;
+
+  ALLOCATE (out, PhotCode_PS1_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    out[i].astromScale = in[i].astromScale;  
+    out[i].photSysErr = in[i].photSysErr;   
+  }
+  return (out);
+}
+
+PhotCode *PhotCode_PS1_DEV_1_To_Internal (PhotCode_PS1_DEV_1 *in, int Nvalues) {
+
+  int i;
+  PhotCode *out;
+
+  ALLOCATE (out, PhotCode, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    out[i].astromScale = in[i].astromScale;  
+    out[i].photSysErr = in[i].photSysErr;   
+  }
+  return (out);
+}
