Index: /trunk/Ohana/src/imregister/photreg/args.photreg.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/args.photreg.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/args.photreg.c	(revision 90)
@@ -0,0 +1,136 @@
+# include "imregister.h"
+# include "photreg.h"
+
+void usage ();
+
+int regargs (int argc, char **argv, PhotPars *newdata) {
+
+  int N, Np, required, photcode, Ntimes;
+  double dtime;
+  unsigned long *tstart, *tstop;
+
+  ConfigInit (&argc, argv);
+
+  output.modify = TRUE;
+  required = 0x0;
+  bzero (newdata, sizeof(PhotPars));
+
+  if (get_argument (argc, argv, "-h")) usage ();
+  if (get_argument (argc, argv, "--help")) usage ();
+
+  /* set the required database */
+  set_db ("phot");
+  if (N = get_argument (argc, argv, "-trans")) {
+    remove_argument (N, &argc, argv);
+    set_db ("trans");
+  }
+
+  /* load photcode data */
+  if (!LoadPhotcodes (PhotCodeFile, &photcodes)) {
+    fprintf (stderr, "error loading photcodes from %s\n", PhotCodeFile);
+    exit (1);
+  }
+
+  /*** optional fields ***/
+  strcpy (newdata[0].label, "elixir");
+  if (N = get_argument (argc, argv, "-label")) {
+    remove_argument (N, &argc, argv);
+    strcpy (newdata[0].label, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  newdata[0].Nmeas = 1;
+  if (N = get_argument (argc, argv, "-Nmeas")) {
+    remove_argument (N, &argc, argv);
+    newdata[0].Nmeas = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  newdata[0].Ntime = 1;
+  if (N = get_argument (argc, argv, "-Ntime")) {
+    remove_argument (N, &argc, argv);
+    newdata[0].Ntime = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.offset = FALSE;
+  if (N = get_argument (argc, argv, "-offset")) {
+    remove_argument (N, &argc, argv);
+    output.offset = TRUE;
+  }
+
+  /**** required arguments ****/
+  if (!get_trange_arguments (&argc, argv, &tstart, &tstop, &Ntimes)) usage ();
+  if (Ntimes != 1) usage ();
+  newdata[0].tstart = tstart[0];
+  newdata[0].tstop = tstop[0];
+  required |= 0x03;
+
+  /* observed zero point */
+  if (N = get_argument (argc, argv, "-zp")) {
+    remove_argument (N, &argc, argv);
+    newdata[0].ZP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    required |= 0x04;
+  }
+
+  /* error on observed zero point */
+  if (N = get_argument (argc, argv, "-dzp")) {
+    remove_argument (N, &argc, argv);
+    newdata[0].dZP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    required |= 0x08;
+  }
+
+  /* error on observed zero point */
+  if (N = get_argument (argc, argv, "-photcode")) {
+    remove_argument (N, &argc, argv);
+    if (!GetPhotcodeRefs (&photcodes, argv[N], &photcode, &Np)) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (1);
+    }
+    newdata[0].photcode = photcode;
+    remove_argument (N, &argc, argv);
+    required |= 0x10;
+  }
+
+  if (required ^ 0x1f) {
+    fprintf (stderr, "missing required field\n");
+    usage ();
+  }
+
+  /* remainding newdata values can be set once photcode is known 
+     be careful about consistency for offset definition:
+     dM == ZPi - ZPo  (ZPo = nominal zero point, ZPi = specific observed zero point)
+     ie, clouds = -dM (ZPi < ZPo)
+  */
+  
+  newdata[0].ZPo = 0.001*photcodes.code[Np].C;
+  if (output.offset) {
+    newdata[0].ZP += newdata[0].ZPo;
+  }
+  newdata[0].K = photcodes.code[Np].K;
+  newdata[0].X = photcodes.code[Np].X;
+  newdata[0].c1 = photcodes.code[Np].c1;
+  newdata[0].c2 = photcodes.code[Np].c2;
+  
+}
+
+/* differences between phot.db & trans.db:
+
+   Ntime : photreg = 1 : transreg = N
+   dBFile: phot.db     : trans.db
+   ASCII EXTNAME: IMAGE_ZPTS : SUMMARY_ZPTS
+   BINARY EXTNAME: ZERO_POINTS_3.0 : TRANS_POINTS_3.0
+   
+   photreg -photcode B -zp 26.1 -dzp 0.02 -date 2003/1/1,10:00:00 -Nmeas 5 -Ntime 1 -db trans
+   photsearch -db trans
+   photsearch -db phot
+   
+*/
+
+void usage () {  
+  fprintf (stderr, "USAGE: photreg (-zp zp) (-dzp dzp) (-tstart date) (-dt dt) (-photcode code)\n");
+  fprintf (stderr, "       [-label label] [-offset] [-Nmeas N] [-Ntime N] [-db trans]\n");
+  exit (1);
+}
Index: /trunk/Ohana/src/imregister/photreg/args.photsearch.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/args.photsearch.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/args.photsearch.c	(revision 90)
@@ -0,0 +1,128 @@
+# include "imregister.h"
+# include "photreg.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  ConfigInit (&argc, argv);
+  ConfigCamera ();
+  ConfigFilter ();
+
+  criteria.Ntimes = 0;
+  if (!get_trange_arguments (&argc, argv, &criteria.tstart, &criteria.tstop, &criteria.Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  criteria.PhotCodeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    remove_argument (N, &argc, argv);
+    criteria.PhotCode = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.PhotCodeSelect = TRUE;
+  }
+
+  criteria.LabelSelect = FALSE;
+  if (N = get_argument (argc, argv, "-label")) {
+    remove_argument (N, &argc, argv);
+    criteria.Label = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.LabelSelect = TRUE;
+  }
+
+  output.delete = FALSE;
+  if (N = get_argument (argc, argv, "-delete")) {
+    remove_argument (N, &argc, argv);
+    output.delete = TRUE;
+  }
+
+  output.equiv = FALSE;
+  if (N = get_argument (argc, argv, "-equiv")) {
+    remove_argument (N, &argc, argv);
+    output.equiv = TRUE;
+  }
+
+  output.offset = FALSE;
+  if (N = get_argument (argc, argv, "-offset")) {
+    remove_argument (N, &argc, argv);
+    output.offset = TRUE;
+  }
+
+  output.table = (char *) NULL;
+  if (N = get_argument (argc, argv, "-table")) {
+    remove_argument (N, &argc, argv);
+    output.table = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.bintable = (char *) NULL;
+  if (N = get_argument (argc, argv, "-bintable")) {
+    remove_argument (N, &argc, argv);
+    output.bintable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.verbose = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (N, &argc, argv);
+    output.verbose = TRUE;
+  }
+
+  output.convert = FALSE;
+  if (N = get_argument (argc, argv, "-convert")) {
+    remove_argument (N, &argc, argv);
+    output.convert = TRUE;
+    if (output.delete || output.modify) {
+      fprintf (stderr, "can't changed old format table\n");
+      exit (1);
+    }
+  }
+
+  if (N = get_argument (argc, argv, "-image")) {
+    remove_argument (N, &argc, argv);
+    if (argc < N + 3) {
+      fprintf (stderr, "missing arguments to -image\n");
+      exit (1);
+    }
+    getImageData (argv[N], argv[N+1], argv[N+2]);
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.db = strcreate ("phot");
+  if (N = get_argument (argc, argv, "-trans")) {
+    remove_argument (N, &argc, argv);
+    output.db = strcreate ("trans");
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: photsearch [config ops] [-v] [-version]\n");
+    fprintf (stderr, "       [-trange start stop/range] [-photcode code]\n");
+    fprintf (stderr, "       [-label label] [-delete]\n");
+    fprintf (stderr, "       [-table table.fits] [-bintable bintable.fits]\n");
+    exit (1);
+  }
+ 
+  /* load photcode data */
+  if (!LoadPhotcodes (PhotCodeFile, &photcodes)) {
+    fprintf (stderr, "error loading photcodes from %s\n", PhotCodeFile);
+    exit (1);
+  }
+
+  /* set up photcode information */
+  if (criteria.PhotCodeSelect) {
+    if (output.equiv) {
+      if (!GetPhotcodeEquiv (&photcodes, criteria.PhotCode, &criteria.PHOTCODE, &N)) {
+	fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+	exit (1);
+      }
+    } else {
+      if (!GetPhotcodeRefs (&photcodes, criteria.PhotCode, &criteria.PHOTCODE, &N)) {
+	fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+	exit (1);
+      }
+    }
+  }
+}
Index: /trunk/Ohana/src/imregister/photreg/db.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/db.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/db.c	(revision 90)
@@ -0,0 +1,300 @@
+# include "imregister.h"
+# include "photreg.h"
+
+/* variables which describe the db */
+char *dBFile = (char *) NULL;
+FILE *f;
+Header header;
+Header theader;
+Matrix matrix;
+FTable table;
+PhotPars *image;
+int Nimage;
+int lockstate;
+int dbstate = LCK_UNLOCK;
+static char *BinaryName = (char *) NULL;
+
+/* photreg vs transreg database selection */
+int set_db (char *db) {
+
+  /* be careful: don't change db without closing old db */
+  if (!strcmp (db, "phot")) {
+    dBFile = PhotDB;    
+    BinaryName = "ZERO_POINTS_3.0";
+    set_Binary_name (BinaryName);
+    set_ASCII_name ("IMAGE_ZPTS");
+    return (TRUE);
+  }
+  if (!strcmp (db, "phot_old")) {
+    dBFile = PhotDB;    
+    BinaryName = "ZERO_POINTS";
+    set_Binary_name (BinaryName);
+    set_ASCII_name ("IMAGE_ZPTS");
+    return (TRUE);
+  }
+  if (!strcmp (db, "trans")) {
+    dBFile = TransDB;    
+    BinaryName = "TRANS_POINTS_3.0";
+    set_Binary_name (BinaryName);
+    set_ASCII_name ("SUMMARY_ZPTS");
+    return (TRUE);
+  }
+  if (!strcmp (db, "trans_old")) {
+    dBFile = TransDB;    
+    BinaryName = "TRANS_POINTS";
+    set_Binary_name (BinaryName);
+    set_ASCII_name ("SUMMARY_ZPTS");
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+PhotPars *get_images (int *N) {
+  *N = Nimage;
+  return (image);
+}
+
+int set_images (PhotPars *new, int Nnew) {
+
+  int Nbytes;
+
+  /* assign pointers to new data block */
+  free (image);
+  Nimage = Nnew;
+  image = new;
+
+  /* update header, table structures */
+  fits_modify (table.header, "NAXIS2", "%d", 1, Nnew);
+  table.header[0].Naxis[1] = Nnew;
+  Nbytes = fits_matrix_size (table.header);
+
+  /* add padding space to buffer */
+  REALLOCATE ((char *) image, char, Nbytes);
+  table.buffer = (char *) image;
+  table.size = Nbytes;
+
+  return (TRUE);
+}
+
+int load_db () {
+
+  int Nx, Ny, status;
+
+  if (output.convert) {
+    status = load_old_db ();
+    return (status);
+  }
+  set_db (output.db);
+
+  lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+
+  if (dBFile == (char *) NULL) {
+    fprintf (stderr, "ERROR: db file is not set\n");
+    exit (1);
+  }
+
+  /* lock database */
+  f = fsetlockfile (dBFile, 300.0, lockstate, &dbstate);
+  if (dbstate == LCK_EMPTY) return (0);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", dBFile);
+    exit (1);
+  }
+
+  /* load in table data */
+  table.header = &theader;
+  if (!fits_fread_header (f, &header))            escape (UNLOCK, "ERROR: can't read primary header"); 
+  if (!fits_fread_matrix (f, &matrix, &header))   escape (UNLOCK, "ERROR: can't read primary header");
+  if (!fits_fread_ftable (f, &table, BinaryName)) escape (UNLOCK, "ERROR: can't read primary header");
+
+  /* convert to internal format */
+  image = (PhotPars *) table.buffer;
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+  Nimage = Ny;
+
+  if (!ConvertStruct ((char *) image, sizeof (PhotPars), Nimage, "photpars"))
+    escape (UNLOCK, "ERROR: can't read primary header"); 
+
+  return (1);
+}
+
+int load_old_db () {
+
+  OldPhotPars *oldimage;
+  int i, Nx, Ny;
+  char tmpname[64];
+
+  sprintf (tmpname, "%s_old", output.db);
+  set_db (tmpname);
+
+  lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+
+  if (dBFile == (char *) NULL) {
+    fprintf (stderr, "ERROR: db file is not set\n");
+    exit (1);
+  }
+
+  /* lock database */
+  f = fsetlockfile (dBFile, 300.0, lockstate, &dbstate);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", dBFile);
+    exit (1);
+  }
+  if (dbstate == LCK_EMPTY) return (0);
+
+  /* load in table data */
+  table.header = &theader;
+  if (!fits_fread_header (f, &header))            escape (UNLOCK, "ERROR: can't read primary header"); 
+  if (!fits_fread_matrix (f, &matrix, &header))   escape (UNLOCK, "ERROR: can't read primary header");
+  if (!fits_fread_ftable (f, &table, BinaryName)) escape (UNLOCK, "ERROR: can't read primary header");
+
+  /* convert to internal format */
+  oldimage = (OldPhotPars *) table.buffer;
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+  Nimage = Ny;
+
+  if (!ConvertStruct ((char *) oldimage, sizeof (OldPhotPars), Nimage, "oldphotpars"))
+    escape (UNLOCK, "ERROR: can't read primary header"); 
+
+  ALLOCATE (image, PhotPars, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    image[i].ZP       = oldimage[i].ZP;
+    image[i].ZPo      = oldimage[i].ZPo;
+    image[i].dZP      = oldimage[i].dZP;
+    image[i].K        = oldimage[i].K;
+    image[i].X        = oldimage[i].X;
+    image[i].tstart   = oldimage[i].tstart;
+    image[i].tstop    = oldimage[i].tstop;
+    image[i].c1       = oldimage[i].c1;
+    image[i].c2       = oldimage[i].c2;
+    image[i].photcode = oldimage[i].photcode;
+    strcpy (image[i].label, oldimage[i].label);
+    image[i].Nmeas = 0;
+    image[i].Ntime = 0;
+  }
+  free (oldimage);
+  close_db ();
+  set_db (output.db);
+  return (1);
+}
+
+/* save complete db file */
+int save_db () {
+
+  if (!ConvertStruct ((char *) image, sizeof (PhotPars), Nimage, "photpars")) 
+    escape (UNLOCK, "ERROR: can't convert from native format");
+
+  /* write all images to file */
+  make_backup (dBFile);
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (f, &header))  escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_matrix  (f, &matrix))  escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_table   (f, &table))   escape (LOCK, "ERROR: can't update db");
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+/* save subset in db file */
+int update_db (int *match, int Nmatch) {
+
+  int i, N, Nx, Ny;
+  VTable vtable;
+
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+
+  /* make empty vtable from table */
+  vtable.header = table.header;
+  vtable.size = table.size;
+  vtable.Nrow = Ny;
+  vtable.pad = vtable.size - Nx*Ny;
+
+  /* insert selected rows in vtable */ 
+  ALLOCATE (vtable.row, int, Nmatch);
+  ALLOCATE (vtable.buffer, char *, Nmatch);
+  for (N = i = 0; i < Nmatch; i++) {
+    if (match[i] == -1) continue;
+    vtable.row[N] = match[i];
+    ALLOCATE (vtable.buffer[N], char, Nx);
+    memcpy (vtable.buffer[N], &image[match[i]], sizeof (PhotPars));
+    ConvertStruct ((char *) vtable.buffer[N], sizeof (PhotPars), 1, "photpars");
+    N++;
+  }
+  vtable.Nrow = N;
+
+  /* write subset to file */
+  make_backup (dBFile);
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (f, &header))  escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_matrix  (f, &matrix))  escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_vtable  (f, &vtable))  escape (LOCK, "ERROR: can't update db");
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+int append_db (PhotPars *new, int Nnew) {
+
+  VTable vtable;
+
+  /* add error checks! */
+  fits_table_to_vtable (&table, &vtable, 0, 0);
+
+  ConvertStruct ((char *) new, sizeof (PhotPars), Nnew, "photpars");
+  fits_vadd_rows (&vtable, new, Nnew, sizeof(PhotPars));
+
+  /* write subset to file */
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (f, &header))  escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_matrix  (f, &matrix))  escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_vtable  (f, &vtable))  escape (LOCK, "ERROR: can't append to db");
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+int create_db () {
+
+  /* f & dBFile set by load_db */
+
+  /* define table layout */
+  define_table (&header, &matrix, &theader, &table);
+
+  /* convert to internal format */
+  image = (PhotPars *) table.buffer;
+  Nimage = 0;
+
+  return (TRUE);
+}
+
+int close_db () {
+  if (dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}  
+
+int close_lock_db () {
+  if (dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (dBFile, f, LCK_XCLD, &dbstate);
+  return (TRUE);
+}  
+
+int print_db_fd () {
+
+  int fd;
+
+  fd = fileno (f);
+  fprintf (stderr, "db: %s, fd: %d\n", dBFile, fd);
+}
+
+int escape (int mode, char *message) {
+  
+  if (mode == UNLOCK) close_db ();
+  fprintf (stderr, "%s\n", message);
+  exit (1);
+}
+
Index: /trunk/Ohana/src/imregister/photreg/define.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/define.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/define.c	(revision 90)
@@ -0,0 +1,40 @@
+# include "imregister.h"
+# include "photreg.h"
+
+static char *BinaryName = (char *) NULL;
+
+int set_Binary_name (char *name) {
+  BinaryName = name;
+}
+
+int define_table (Header *header, Matrix *matrix, Header *theader, FTable *table) {
+
+  /* create primary header */
+  fits_init_header (header);    
+  header[0].extend = TRUE;
+  fits_create_header (header);
+  fits_create_matrix (header, matrix);
+  fits_print (header, "NEXTEND", "%d", 1, 1);
+    
+  /* define bintable header layout */
+  fits_create_table_header (theader, "BINTABLE", BinaryName);
+
+  fits_define_bintable_column (theader, "E",   "ZP_OBS",     "measured zero point",       "mag",                           1.0, 0.0);
+  fits_define_bintable_column (theader, "E",   "ZP_REF",     "nominal zero point",        "mag",                           1.0, 0.0);
+  fits_define_bintable_column (theader, "E",   "ZP_ERR",     "error on zero point",       "mag",                           1.0, 0.0);
+  fits_define_bintable_column (theader, "E",   "C_AIRMASS",  "airmass coeff",             "mag per airmass",               1.0, 0.0); 
+  fits_define_bintable_column (theader, "E",   "C_COLOR",    "color coeff",               "mag per mag",                   1.0, 0.0);
+  fits_define_bintable_column (theader, "J",   "START_TIME", "start time of measurement", "seconds since Jan 1, 1970 UT",  1.0, 0.0);
+  fits_define_bintable_column (theader, "J",   "STOP_TIME",  "stop time of measurement",  "seconds since Jan 1, 1970 UT",  1.0, 0.0);
+  fits_define_bintable_column (theader, "I",   "C1_CODE",    "code 1 for color",          "photcode",                      1.0, 0.0);
+  fits_define_bintable_column (theader, "I",   "C2_CODE",    "code 2 for color",          "photcode",                      1.0, 0.0);
+  fits_define_bintable_column (theader, "I",   "PHOTCODE",   "photcode",                  "photcode",                      1.0, 0.0);
+  fits_define_bintable_column (theader, "66A", "LABEL",      "data label",                "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "J",   "N_TIME",     "number of times",           "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "J",   "N_MEAS",     "number of measurements",    "",                              1.0, 0.0);
+  
+  /* create table, add data values */
+  fits_create_table (theader, table);
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/imregister/photreg/delete.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/delete.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/delete.c	(revision 90)
@@ -0,0 +1,42 @@
+# include "imregister.h"
+# include "photreg.h"
+
+void DeleteSubset (int *match, int Nmatch) {
+
+  int i, j;
+  int *keep, Nbad, Nphotdata, Nsubset;
+  PhotPars *photdata, *subset;
+
+  photdata = get_images (&Nphotdata);
+
+  ALLOCATE (keep, int, MAX (Nphotdata, 1));
+  for (i = 0; i < Nphotdata; i++) keep[i] = TRUE;
+  fprintf (stderr, "total of %d photdata\n", Nphotdata);
+
+  Nbad = 0;
+  for (i = 0; i < Nmatch; i++) {
+    j = match[i];
+    if (j == -1) continue;
+    keep[j] = FALSE;
+    Nbad ++;
+  }
+  fprintf (stderr, "delete %d photdata\n", Nbad);
+
+  Nsubset = Nphotdata - Nbad;
+  ALLOCATE (subset, PhotPars, MAX (1, Nsubset));
+  fprintf (stderr, "keeping %d photdata\n", Nsubset);
+  for (j = i = 0; i < Nphotdata; i++) {
+    if (!keep[i]) continue;
+    subset[j] = photdata[i];
+    /* this or memcpy ? */
+    j++;
+  }
+
+  free (keep);
+  set_images (subset, Nsubset);
+
+  save_db ();
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
Index: /trunk/Ohana/src/imregister/photreg/getImageData.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/getImageData.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/getImageData.c	(revision 90)
@@ -0,0 +1,67 @@
+# include "imregister.h"
+# include "photreg.h"
+
+getImageData (char *Image, char *ImageCCD, char *ImageMode) {
+
+  Header header;
+  char detector[64], filter[64], *PhotCode;
+  int i, ccd, Nfilter;
+  
+  /* extract time & photcode from header */
+
+  /* load options from the image header */
+  if (!fits_read_header (Image, &header)) {
+    if (output.verbose) fprintf (stderr, "ERR: trouble reading image header\n");
+    exit (1);
+  }
+
+  /* get time from image header */
+  ALLOCATE (criteria.tstart, unsigned long, 1);
+  ALLOCATE (criteria.tstart, unsigned long, 1);
+  criteria.tstart[0] = parse_time (&header);
+  criteria.tstop[0] = criteria.tstart[0] + 1;
+  criteria.Ntimes = 1;
+
+  /** determine photcode from header **/
+  /* get camera */
+  fits_scan (&header, CameraKeyword, "%s", 1, detector);
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(detector); i++) { if (isspace (detector[i])) detector[i] = '.'; }
+    
+  /* get filter */
+  Nfilter = FILTER_NONE;
+  fits_scan (&header, FilterKeyword,   "%s", 1, filter);
+  for (i = 0; i < strlen (filter); i++) { if (isspace (filter[i])) filter[i] = '.'; }
+  for (i = 0; (i < NFILTER) && (Nfilter == FILTER_NONE); i++) {
+    if (!strcasecmp (filter, filtername[i])) {
+      Nfilter = filternum[i];
+    }
+  }      
+  if (Nfilter == FILTER_NONE) {
+    fprintf (stderr, "ERR: invalid filter %s\n", filter);
+    exit (1);
+  }
+  strcpy (filter, filtername[Nfilter]);
+
+  /* get ccd number */
+  if (!strcasecmp (ImageCCD, "phu")) {
+    ccd = 0;
+  } else {
+   if (!strcasecmp (ImageMode, "mef")) {
+     ccd = MatchCCDName (ImageCCD);
+   } else {
+     ccd = -1;
+     fits_scan (&header, CCDnumKeyword,  "%d", 1, &ccd);
+   }  
+   if (ccd == -1) {
+     fprintf (stderr, "ERR: invalid ccd %s %s\n", ImageCCD, ImageMode);
+     exit (1);
+   }
+  }
+
+  ALLOCATE (PhotCode, char, 64);
+  sprintf (PhotCode, "%s.%s.%02d", detector, filter, ccd);
+  criteria.PhotCodeSelect = TRUE;
+  criteria.PhotCode = PhotCode;
+
+}
Index: /trunk/Ohana/src/imregister/photreg/match.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/match.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/match.c	(revision 90)
@@ -0,0 +1,37 @@
+# include "imregister.h"
+# include "photreg.h"
+
+int *match_criteria (int *Nmatch) {
+
+  int i, j, Nphotdata;
+  int N, NMATCH;
+  int *match;
+  int reject;
+  PhotPars *photdata;
+
+  /* create selection index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  photdata = get_images (&Nphotdata);
+
+  /* find entries that matches criteria */
+  for (i = 0; i < Nphotdata; i++) {
+    for (j = 0, reject = TRUE; reject && (j < criteria.Ntimes); j++) {
+      reject = (photdata[i].tstop < criteria.tstart[j]) || (photdata[i].tstart > criteria.tstop[j]);
+    }
+    if (criteria.Ntimes && reject) continue;
+    if (criteria.PhotCodeSelect && (photdata[i].photcode != criteria.PHOTCODE)) continue;
+    if (criteria.LabelSelect && strcmp (photdata[i].label, criteria.Label)) continue;
+
+    match[N] = i;
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+  }
+  *Nmatch = N;
+  return (match);
+}
Index: /trunk/Ohana/src/imregister/photreg/output.c
===================================================================
--- /trunk/Ohana/src/imregister/photreg/output.c	(revision 90)
+++ /trunk/Ohana/src/imregister/photreg/output.c	(revision 90)
@@ -0,0 +1,191 @@
+# include "imregister.h"
+# include "photreg.h"
+
+static char *ASCIIName = (char *) NULL;
+
+set_ASCII_name (char *string) {
+  ASCIIName = string;
+}
+
+/* given a subset list, write out the selected images, if desired */
+void OutputSubset (int *match, int Nmatch) {
+
+  int Nphotdata;
+  PhotPars *photdata;
+
+  photdata = get_images (&Nphotdata);
+
+  if (output.table != (char *) NULL) {
+    DumpFitsTable (output.table, photdata, match, Nmatch);
+  } 
+
+  if (output.bintable != (char *) NULL) {
+    DumpFitsBintable (output.bintable, photdata, match, Nmatch);
+  } 
+
+  PrintSubset (photdata, match, Nmatch);
+  if (output.verbose) fprintf (stderr, "SUCCESS\n");
+
+  exit (0);
+}
+
+/* write out complete binary FITS table in format of db */
+void DumpFitsBintable (char *filename, PhotPars *photdata, int *match, int Nmatch) {
+
+  int i, j, Nx;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  PhotPars *subset;
+
+  /* define table layout */
+  define_table (&header, &matrix, &theader, &table);
+
+  ALLOCATE (subset, PhotPars, MAX (1, Nmatch));
+  for (i = 0; i < Nmatch; i++){
+    j = match[i];
+    memcpy (&subset[i], &photdata[j], sizeof (PhotPars));
+  }
+  ConvertStruct ((char *) subset, sizeof (PhotPars), Nmatch, "photpars");
+  fits_add_rows (&table, subset, Nmatch, sizeof (PhotPars));
+
+  fits_write_header  (filename, &header);
+  fits_write_matrix  (filename, &matrix);
+  fits_write_Theader (filename, &theader);
+  fits_write_table   (filename, &table);
+  exit (0);
+}
+
+void DumpFitsTable (char *filename, PhotPars *photdata, int *index, int Nkeep) {
+  
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  PhotPars *newdata;
+  FILE *f;
+  char *startstr, *stopstr, *datestr, *line;
+  char *c1, *c2, *code;
+  int i, n;
+  unsigned int tsecond;
+
+  /* create primary header */
+  fits_init_header (&header);    
+  header.extend = TRUE;
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+  fits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* create table header */
+  fits_create_table_header (&theader, "TABLE", ASCIIName);
+    
+  /* add current date/time to header */
+  str_to_time ("now", (unsigned long *)&tsecond);
+  datestr = sec_to_date (tsecond);
+  fits_modify (&header,  "DATE", "%s", 1, datestr);
+  fits_modify (&theader, "DATE", "%s", 1, datestr);
+  free (datestr);
+     
+  /* define table layout */
+  fits_define_table_column (&theader, "F8.4", "ZP_OBS",     "measured zero point",       "mag");
+  fits_define_table_column (&theader, "F8.4", "ZP_REF",     "nominal zero point",        "mag");
+  fits_define_table_column (&theader, "F7.4", "ZP_ERR",     "error on zero point",       "mag");
+  fits_define_table_column (&theader, "F7.3", "C_AIRMASS",  "airmass coeff",             "mag per airmass"); 
+  fits_define_table_column (&theader, "F6.3", "C_COLOR",    "color coeff",               "mag per mag");
+  fits_define_table_column (&theader, "A20",  "START_TIME", "start time of measurement", "yyyy/mm/dd,hh:mm:ss");
+  fits_define_table_column (&theader, "A20",  "STOP_TIME",  "stop time of measurement",  "yyyy/mm/dd,hh:mm:ss");
+  fits_define_table_column (&theader, "A12",  "C1_NAME",    "filter 1 for color",        "");
+  fits_define_table_column (&theader, "A12",  "C2_NAME",    "filter 2 for color",        "");
+  fits_define_table_column (&theader, "A12",  "FILTER",     "filter",                    "");
+  fits_define_table_column (&theader, "A70",  "LABEL",      "data label",                "");
+  
+  /* define TNULL, TNVAL values */
+  fits_modify (&theader, "TNULL1",  "%s", 1, "NaN");   /* ZP_OBS     */
+  fits_modify (&theader, "TNULL2",  "%s", 1, "NaN");   /* ZP_REF     */
+  fits_modify (&theader, "TNULL3",  "%s", 1, "NaN");   /* ZP_ERR     */
+  fits_modify (&theader, "TNULL4",  "%s", 1, "NaN");   /* C_AIRMASS  */
+  fits_modify (&theader, "TNULL5",  "%s", 1, "NaN");   /* C_COLOR    */
+  fits_modify (&theader, "TNULL6",  "%s", 1, "NULL");  /* START_TIME */
+  fits_modify (&theader, "TNULL7",  "%s", 1, "NULL");  /* STOP_TIME  */
+  fits_modify (&theader, "TNULL8",  "%s", 1, "NULL");  /* C1_NAME    */
+  fits_modify (&theader, "TNULL9",  "%s", 1, "NULL");  /* C2_NAME    */
+  fits_modify (&theader, "TNULL10", "%s", 1, "NULL");  /* FILTER     */
+  fits_modify (&theader, "TNULL11", "%s", 1, "NULL");  /* LABEL      */
+
+  fits_modify (&theader, "TNVAL1",  "%s", 1, "Inf");   /* ZP_OBS     */
+  fits_modify (&theader, "TNVAL2",  "%s", 1, "Inf");   /* ZP_REF     */
+  fits_modify (&theader, "TNVAL3",  "%s", 1, "Inf");   /* ZP_ERR     */
+  fits_modify (&theader, "TNVAL4",  "%s", 1, "Inf");   /* C_AIRMASS  */
+  fits_modify (&theader, "TNVAL5",  "%s", 1, "Inf");   /* C_COLOR    */
+  fits_modify (&theader, "TNVAL6",  "%s", 1, "NA");    /* START_TIME */
+  fits_modify (&theader, "TNVAL7",  "%s", 1, "NA");    /* STOP_TIME  */
+  fits_modify (&theader, "TNVAL8",  "%s", 1, "NA");    /* C1_NAME    */
+  fits_modify (&theader, "TNVAL9",  "%s", 1, "NA");    /* C2_NAME    */
+  fits_modify (&theader, "TNVAL10", "%s", 1, "NA");    /* FILTER     */
+  fits_modify (&theader, "TNVAL11", "%s", 1, "NA");    /* LABEL      */
+
+  /* create table, add data values */
+  fits_create_table (&theader, &table);
+  
+  /* add data to table */
+  for (i = 0; i < Nkeep; i++) {
+    newdata = &photdata[index[i]];
+    startstr = sec_to_date (newdata[0].tstart);
+    stopstr = sec_to_date (newdata[0].tstop);
+    n = photcodes.hashcode[newdata[0].c1];
+    c1 = photcodes.code[n].name;
+    n = photcodes.hashcode[newdata[0].c2];
+    c2 = photcodes.code[n].name;
+    n = photcodes.hashcode[newdata[0].photcode];
+    code = photcodes.code[n].name;
+
+    line = fits_table_print (&table, newdata[0].ZP, newdata[0].ZPo, newdata[0].dZP, 
+	      newdata[0].K, newdata[0].X, startstr, stopstr,
+	      c1, c2, code, newdata[0].label);
+    if (!fits_add_rows (&table, line, 1, strlen(line))) escape (IGNORE, (FILE *) NULL, (char *) NULL, NULL, "error writing dataline");
+
+    free (line);
+    free (startstr);
+    free (stopstr);
+  }
+ 
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Failure writing fits table\n");
+    exit (1);
+  }
+  fits_fwrite_header  (f, &header);
+  fits_fwrite_matrix  (f, &matrix);
+  fits_fwrite_Theader (f, &theader);
+  fits_fwrite_table   (f, &table);
+  fclose (f);
+  exit (0);
+}
+
+/* Select, TimeMode are global */
+int PrintSubset (PhotPars *photdata, int *match, int Nmatch) {
+  
+  int i, j;
+  char *photstr, *timestr, *c1, *c2;
+  
+  /* print the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+    
+    i = match[j];
+    
+    /* convert UNIX time to Elixir-style date string */
+    timestr = sec_to_date (photdata[i].tstart);
+    
+    /* convert photcode to filter name */
+    photstr = GetPhotnamebyCode (&photcodes, photdata[i].photcode);
+    c1      = GetPhotnamebyCode (&photcodes, photdata[i].c1);
+    c2      = GetPhotnamebyCode (&photcodes, photdata[i].c2);
+    if (photstr == (char *) NULL) photstr = PhotError;
+    if (c1      == (char *) NULL) photstr = PhotError;
+    if (c2      == (char *) NULL) photstr = PhotError;
+      
+    fprintf (stdout, "%s %s  %7.4f %7.4f %7.4f  %3d %3d  %7.4f %7.4f  %s %s %s\n", 
+	     photstr, timestr, photdata[i].ZP, photdata[i].ZPo, photdata[i].dZP, photdata[i].Nmeas, photdata[i].Ntime, photdata[i].X, photdata[i].K, c1, c2, photdata[i].label); 
+    free (timestr);
+  }
+  return (TRUE);
+}
Index: /trunk/Ohana/src/imregister/src/cameraconfig.c
===================================================================
--- /trunk/Ohana/src/imregister/src/cameraconfig.c	(revision 90)
+++ /trunk/Ohana/src/imregister/src/cameraconfig.c	(revision 90)
@@ -0,0 +1,257 @@
+# include <ohana.h>
+static char *version = "cameraconfig $Revision: 1.1 $";
+
+main (int argc, char **argv) {
+
+  int i, Nccd, Nx, Ny, mosaic_x, mosaic_y, N, use_biassec;
+  int dx, dy;
+  char *config, *file;
+  char CameraConfig[256];
+  char field[64], name[64], line[256], keyword[64];
+  char ID[64], *IDsel;
+  double x, y, Xo, Yo, theta;
+  int Choice, GetID, SEQ, GetN, Nsel;
+  int NCCD, AXES, CCDS, CCDN, XOFF, YOFF, XFLIP, YFLIP, XO, YO, THETA;
+  int AXIS0, AXIS1, MOSAIC_X, MOSAIC_Y, DATASEC, BIASSEC, USE_BIASSEC;
+  char datasec[64], biassec[64];
+
+  get_version (argc, argv, version);
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (!ScanConfig (config, "CAMERA_CONFIG", "%s", 0, CameraConfig)) {
+    fprintf (stderr, "ERROR: can't find CAMERA_CONFIG in configuration file\n");
+    exit (1);
+  }
+  free (config);
+  free (file);
+
+  /* load camera config file */
+  config = LoadConfigFile (CameraConfig);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find camera config file %s\n", CameraConfig);
+    exit (1);
+  }
+
+  if (argc == 1) { 
+    fprintf (stderr, "USAGE: cameraconfig [-options]\n");
+    fprintf (stderr, "using %s for config information\n", CameraConfig);
+    exit (1);
+  }
+
+  /* command line options */
+  if (N = get_argument (argc, argv, "-h")) usage ();
+
+  /* command line options */
+  NCCD = FALSE;
+  if (N = get_argument (argc, argv, "-Nccd")) {
+    remove_argument (N, &argc, argv);
+    NCCD = TRUE;
+  }
+
+  AXES = FALSE;
+  if (N = get_argument (argc, argv, "-axes")) {
+    remove_argument (N, &argc, argv);
+    AXES = TRUE;
+  }
+
+  AXIS0 = FALSE;
+  if (N = get_argument (argc, argv, "-axis0")) {
+    remove_argument (N, &argc, argv);
+    AXIS0 = TRUE;
+  }
+
+  AXIS1 = FALSE;
+  if (N = get_argument (argc, argv, "-axis1")) {
+    remove_argument (N, &argc, argv);
+    AXIS1 = TRUE;
+  }
+
+  MOSAIC_X = FALSE;
+  if (N = get_argument (argc, argv, "-mosaicx")) {
+    remove_argument (N, &argc, argv);
+    MOSAIC_X = TRUE;
+  }
+  MOSAIC_Y = FALSE;
+  if (N = get_argument (argc, argv, "-mosaicy")) {
+    remove_argument (N, &argc, argv);
+    MOSAIC_Y = TRUE;
+  }
+
+  CCDS = FALSE;
+  if (N = get_argument (argc, argv, "-ccds")) {
+    remove_argument (N, &argc, argv);
+    CCDS = TRUE;
+  }
+
+  CCDN = FALSE;
+  if (N = get_argument (argc, argv, "-ccdn")) {
+    remove_argument (N, &argc, argv);
+    CCDN = TRUE;
+  }
+
+  SEQ = FALSE;
+  if (N = get_argument (argc, argv, "-seq")) {
+    remove_argument (N, &argc, argv);
+    SEQ = TRUE;
+  }
+
+  XOFF = FALSE;
+  if (N = get_argument (argc, argv, "-xoff")) {
+    remove_argument (N, &argc, argv);
+    XOFF = TRUE;
+  }
+
+  YOFF = FALSE;
+  if (N = get_argument (argc, argv, "-yoff")) {
+    remove_argument (N, &argc, argv);
+    YOFF = TRUE;
+  }
+
+  XO = FALSE;
+  if (N = get_argument (argc, argv, "-Xo")) {
+    remove_argument (N, &argc, argv);
+    XO = TRUE;
+  }
+
+  YO = FALSE;
+  if (N = get_argument (argc, argv, "-Yo")) {
+    remove_argument (N, &argc, argv);
+    YO = TRUE;
+  }
+
+  THETA = FALSE;
+  if (N = get_argument (argc, argv, "-theta")) {
+    remove_argument (N, &argc, argv);
+    THETA = TRUE;
+  }
+
+  XFLIP = FALSE;
+  if (N = get_argument (argc, argv, "-xflip")) {
+    remove_argument (N, &argc, argv);
+    XFLIP = TRUE;
+  }
+
+  YFLIP = FALSE;
+  if (N = get_argument (argc, argv, "-yflip")) {
+    remove_argument (N, &argc, argv);
+    YFLIP = TRUE;
+  }
+
+  DATASEC = FALSE;
+  if (N = get_argument (argc, argv, "-datasec")) {
+    remove_argument (N, &argc, argv);
+    DATASEC = TRUE;
+  }
+  BIASSEC = FALSE;
+  if (N = get_argument (argc, argv, "-biassec")) {
+    remove_argument (N, &argc, argv);
+    BIASSEC = TRUE;
+  }
+  USE_BIASSEC = FALSE;
+  if (N = get_argument (argc, argv, "-usebiassec")) {
+    remove_argument (N, &argc, argv);
+    USE_BIASSEC = TRUE;
+  }
+
+  GetID = FALSE;
+  if (N = get_argument (argc, argv, "-ID")) {
+    GetID = TRUE;
+    remove_argument (N, &argc, argv);
+    Nsel = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  GetN = FALSE;
+  if (N = get_argument (argc, argv, "-N")) {
+    GetN = TRUE;
+    remove_argument (N, &argc, argv);
+    IDsel = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) { 
+    fprintf (stderr, "USAGE: cameraconfig [-options]\n");
+    exit (1);
+  }
+
+  /* load data from config file */
+  ScanConfig (config, "NCCD", "%d", 1, &Nccd);
+  ScanConfig (config, "NAXIS1", "%d", 1, &Nx);
+  ScanConfig (config, "NAXIS2", "%d", 1, &Ny);
+  ScanConfig (config, "MOSAIC_X", "%d", 1, &mosaic_x);
+  ScanConfig (config, "MOSAIC_Y", "%d", 1, &mosaic_y);
+  ScanConfig (config, "USE_BIASSEC", "%d", 1, &use_biassec);
+  
+  if (NCCD) fprintf (stdout, "%d\n", Nccd);
+  if (AXES) fprintf (stdout, "%d %d\n", Nx, Ny);
+  if (AXIS0) fprintf (stdout, "%d\n", Nx);
+  if (AXIS1) fprintf (stdout, "%d\n", Ny);
+  if (MOSAIC_X) fprintf (stdout, "%d\n", mosaic_x);
+  if (MOSAIC_Y) fprintf (stdout, "%d\n", mosaic_y);
+  if (USE_BIASSEC) fprintf (stdout, "%d\n", use_biassec);
+  
+  ScanConfig (config, "CHIPID_KEYWORD", "%s", 1, keyword);
+  
+  Choice = SEQ || CCDS || CCDN || XOFF || YOFF || XFLIP || YFLIP || DATASEC || BIASSEC || XO || YO || THETA;
+
+  for (i = 0; i < Nccd; i++) {
+    sprintf (field, "CCD.%d", i);
+    ScanConfig (config, field, "%s", 1, line);
+    sscanf (line, "%s %lf %lf %d %d %s %s %lf %lf %lf", 
+	    ID, &x, &y, &dx, &dy, datasec, biassec, &Xo, &Yo, &theta);
+
+    if (GetID && (Nsel == i)) fprintf (stdout, "%s\n", ID);
+    if (GetN  && strnumcmp (IDsel, ID)) fprintf (stdout, "%d\n", i);
+    if (SEQ)     fprintf (stdout, "%d ", i);
+    if (CCDS)    fprintf (stdout, "%s ", ID);
+    if (CCDN)    fprintf (stdout, "%02d", i);
+    if (XOFF)    fprintf (stdout, "%f ", x);
+    if (YOFF)    fprintf (stdout, "%f ", y);
+    if (XFLIP)   fprintf (stdout, "%d ", dx);
+    if (YFLIP)   fprintf (stdout, "%d ", dy);
+    if (DATASEC) fprintf (stdout, "%s ", datasec);
+    if (BIASSEC) fprintf (stdout, "%s ", biassec);
+
+    if (XO)      fprintf (stdout, "%7.1f ", Xo);
+    if (YO)      fprintf (stdout, "%7.1f ", Yo);
+    if (THETA)   fprintf (stdout, "%7.3f ", theta);
+
+    if (Choice) fprintf (stdout, "\n");
+
+  }
+
+  exit (0);
+}
+
+usage () {
+
+  fprintf (stderr, "cameraconfig [option] : lookup camera parameters\n");
+  fprintf (stderr, "   -Nccd         : number of CCDs\n");
+  fprintf (stderr, "   -axes         : x & y dimensions\n");
+  fprintf (stderr, "   -axis0        : x dimension (CCD)\n");
+  fprintf (stderr, "   -axis1        : y dimension (CCD)\n");
+  fprintf (stderr, "   -mosaicx      : x dimension (mosaic)\n");
+  fprintf (stderr, "   -mosaicy      : y dimension (mosaic)\n");
+  fprintf (stderr, "   -usebiassec   : use header BIASSEC\n");
+
+  fprintf (stderr, "   -seq          : chip sequence number\n");
+  fprintf (stderr, "   -ccds         : chip extension ID\n");
+  fprintf (stderr, "   -xoff         : x offset in mosaic\n");
+  fprintf (stderr, "   -yoff         : y offset in mosaic\n");
+  fprintf (stderr, "   -xflip        : x flip in mosaic\n");
+  fprintf (stderr, "   -yflip        : y flip in mosaic\n");
+  fprintf (stderr, "   -datasec      : DATASEC value\n");
+  fprintf (stderr, "   -biassec      : BIASSEC value\n");
+
+  fprintf (stderr, "   -ID [N]       : return ID for seq\n");
+  fprintf (stderr, "   -N [ID]       : return seq for ID\n");
+  exit (2);
+
+}
Index: /trunk/Ohana/src/imregister/src/filtnames.c
===================================================================
--- /trunk/Ohana/src/imregister/src/filtnames.c	(revision 90)
+++ /trunk/Ohana/src/imregister/src/filtnames.c	(revision 90)
@@ -0,0 +1,168 @@
+# include <ohana.h>
+static char *version = "filtnames $Revision: 1.1 $";
+
+typedef struct {
+  int code, calibrated;
+  char name[64], ref[64], c1[64], c2[64];
+} FiltCode;
+
+main (int argc, char **argv) {
+
+  int i, code, Ncode, Nmatch, Nfield, N, Select, CalibrationData;
+  int Nfiltcode, NFILTCODE;
+  char *config, *file, *target;
+  char FilterList[256];
+  char name[64], ref[64], c1[64], c2[64], line[256], *c;
+  FILE *f;
+  FiltCode *filtcode;
+
+  get_version (argc, argv, version);
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (!ScanConfig (config, "FILTER_LIST", "%s", 0, FilterList)) {
+    fprintf (stderr, "ERROR: can't find FILTER_LIST in configuration file\n");
+    exit (1);
+  }
+  free (config);
+  free (file);
+
+  /* image type (dark, flat, bias, etc) */
+  Select = TRUE;
+  if (N = get_argument (argc, argv, "-all")) {
+    remove_argument (N, &argc, argv);
+    Select = FALSE;
+  }
+ 
+  /* image type (dark, flat, bias, etc) */
+  CalibrationData = FALSE;
+  if (N = get_argument (argc, argv, "-cal")) {
+    remove_argument (N, &argc, argv);
+    CalibrationData = TRUE;
+  }
+ 
+  if (argc != 2) { 
+    fprintf (stderr, "USAGE: filtnames (filtername)\n");
+    fprintf (stderr, "       filtnames list : list all unique filters\n");
+    fprintf (stderr, "       [-all] : list all names for given filter(s)\n");
+    fprintf (stderr, "       [-cal] : print calibration data for filter(s)\n");
+    exit (1);
+  }
+
+  target = argv[1];
+  for (i = 0; i < strlen (target); i++) { if (isspace (target[i])) target[i] = '.'; }
+
+  /* open filter list file */
+  f = fopen (FilterList, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error reading photcodes\n");
+    exit (1);
+  }
+
+  /* load filter list & codes */
+  NFILTCODE = 100;
+  Nfiltcode = 0;
+  ALLOCATE (filtcode, FiltCode, NFILTCODE);
+
+  while (scan_line (f, line) != EOF) {
+    for (c = line; isspace (*c); c++);
+    if (*c == '#') continue;
+    if (*c == 0) continue;
+    Nfield = sscanf (c, "%d %s %s %s %*s %s", &code, name, ref, c1, c2);
+    if ((Nfield != 2) && (Nfield != 5)) {
+      fprintf (stderr, "error reading line: %s\n", c);
+      exit (1);
+    }
+
+    filtcode[Nfiltcode].code = code;
+    filtcode[Nfiltcode].calibrated = FALSE;
+    strcpy (filtcode[Nfiltcode].name, name);
+    filtcode[Nfiltcode].ref[0] = 0;
+    filtcode[Nfiltcode].c1[0] = 0;
+    filtcode[Nfiltcode].c2[0] = 0;
+    if (Nfield == 5) {
+      filtcode[Nfiltcode].calibrated = TRUE;
+      strcpy (filtcode[Nfiltcode].ref, ref);
+      strcpy (filtcode[Nfiltcode].c1, c1);
+      strcpy (filtcode[Nfiltcode].c2, c2);
+    }
+    Nfiltcode ++;
+
+    if (Nfiltcode == NFILTCODE - 1) {
+      NFILTCODE += 100;
+      REALLOCATE (filtcode, FiltCode, NFILTCODE);
+    }
+  }
+
+  /* special target: list -- list all filters */
+  if (!strcasecmp (target, "list")) {
+    
+    int *uniq, Nuniq, j, found;
+    ALLOCATE (uniq, int, Nfiltcode);
+
+    /* identify unique filter codes */
+    Nuniq = 0;
+    for (i = 0; i < Nfiltcode; i++) {
+      found = FALSE;
+      for (j = 0; !found && (j < Nuniq); j++) {
+	if (filtcode[i].code == uniq[j]) found = TRUE;
+      }
+      if (found) continue;
+      uniq[Nuniq] = filtcode[i].code;
+      Nuniq ++;
+    }
+
+    /* list the entries of the unique codes.  skip code == 0 (none) */
+    for (i = 0; i < Nuniq; i++) {
+      if (uniq[i] == 0) continue;
+      for (j = 0; j < Nfiltcode; j++) {
+	if (uniq[i] != filtcode[j].code) continue;
+	if (CalibrationData) {
+	  fprintf (stdout, "%s %d %s %s %s\n", filtcode[j].name, filtcode[j].calibrated, filtcode[j].ref, filtcode[j].c1, filtcode[j].c2);
+	} else {
+	  fprintf (stdout, "%s\n", filtcode[j].name);
+	}
+	if (Select) break;
+      }
+    }
+    exit (0);
+  }
+
+  /* find given name in filter list (case insensitive) */
+  Ncode = 0;
+  for (i = 0; i < Nfiltcode; i++) {
+    if (strcasecmp (target, filtcode[i].name)) continue;
+    Ncode = filtcode[i].code;
+    break;
+  }
+  if (!Ncode) {
+    fprintf (stderr, "no filter match found\n");
+    exit (1);
+  }
+
+  /* find first entry with this code */
+  Nmatch = 0;
+  for (i = 0; i < Nfiltcode; i++) {
+    if (Ncode != filtcode[i].code) continue;
+    if (CalibrationData) {
+      fprintf (stdout, "%s %d %s %s %s\n", filtcode[i].name, filtcode[i].calibrated, filtcode[i].ref, filtcode[i].c1, filtcode[i].c2);
+    } else {
+      fprintf (stdout, "%s\n", filtcode[i].name);
+    }
+    Nmatch ++;
+    if (Select) break;
+  }
+
+  if (!Nmatch) {
+    fprintf (stderr, "no filter code error: code mis-match\n");
+    exit (1);
+  }
+
+  exit (0);
+}
Index: /trunk/Ohana/src/imregister/src/imphotsearch.c
===================================================================
--- /trunk/Ohana/src/imregister/src/imphotsearch.c	(revision 90)
+++ /trunk/Ohana/src/imregister/src/imphotsearch.c	(revision 90)
@@ -0,0 +1,282 @@
+# include "imregister.h"
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
+char *sec_to_date (unsigned long second);
+static char PhotError[] = "unknown";
+PhotCodeData photcodes;
+static char *version = "imphotsearch $Revision: 1.1 $";
+
+main (int argc, char **argv) {
+ 
+  FILE *f;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  int i, j, status, N, TimeSelect;
+  char *dBFile, *Label, *PhotCode, *timestr, *photstr;
+  int Nimage, nimage, Nskip, *index, Ntimes;
+  unsigned long *tstart, *tstop;
+  int VERBOSE, FORCE_READ, PHOTCODE, dbstate, lockstate;
+  Image *image;
+  int PhotCodeSelect, LabelSelect, Np, Nin;
+  int Delete, *Dellist, Nkeep;
+  char *FitsOutput, *NameSelect;
+  int NameSelectLength;
+  struct stat filestatus;
+  int size;
+
+  get_version (argc, argv, version);
+  ConfigInit (&argc, argv);
+
+  /* interpret command-line arguments */
+  if (!get_trange_arguments (&argc, argv, &tstart, &tstop, &Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  PhotCodeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    remove_argument (N, &argc, argv);
+    PhotCode = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    PhotCodeSelect = TRUE;
+  }
+
+  /* string in image name */
+  NameSelect = (char *) NULL;
+  if (N = get_argument (argc, argv, "-name")) {
+    remove_argument (N, &argc, argv);
+    NameSelect = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    NameSelectLength = strlen (NameSelect);
+  }
+
+  FitsOutput = (char *) NULL;
+  if (N = get_argument (argc, argv, "-fits")) {
+    remove_argument (N, &argc, argv);
+    FitsOutput = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  VERBOSE = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  FORCE_READ = FALSE;
+  if (N = get_argument (argc, argv, "-force")) {
+    remove_argument (N, &argc, argv);
+    FORCE_READ = TRUE;
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: imphotsearch [config ops] [-trange start stop/delta] [-photcode code] [-fits out.fits]\n");
+    exit (1);
+  }
+ 
+  /* load photcode data */
+  if (!LoadPhotcodes (PhotCodeFile, &photcodes)) {
+    fprintf (stderr, "error loading photcodes from %s\n", PhotCodeFile);
+    exit (1);
+  }
+  if (PhotCodeSelect) {
+    if (!GetPhotcodeRefs (&photcodes, argv[1], &PHOTCODE, &Np)) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (1);
+    }
+  }
+
+  /* load image database - still a non-FITS file */
+  dBFile = ImPhotDB;
+
+  f = fsetlockfile (dBFile, 120.0, LCK_SOFT, &dbstate);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock on %s, state is %d\n", dBFile, dbstate);
+    exit (1);
+  }
+  Fseek (f, 0, SEEK_SET);
+
+  /* read header */
+  if (!fits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "ERROR: can't read image catalog %s\n", dBFile);
+    exit (1);
+  }
+
+  /* check that file size makes sense */
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (stat (dBFile, &filestatus) == -1) {
+    if (VERBOSE) fprintf (stderr, "ERROR: failed to get status of image catalog\n");
+    exit (1);
+  }
+  size = Nimage*sizeof(Image) + header.size;
+  if (size != filestatus.st_size) {
+    int Ndata;
+
+    Ndata = (filestatus.st_size - header.size) / sizeof (Image);
+    if (VERBOSE) fprintf (stderr, "ERROR: image catalog has inconsistent size\n");
+    if (VERBOSE) fprintf (stderr, "header: %d, data: %d\n", Nimage, Ndata);
+    if (!FORCE_READ) exit (1);
+    Nimage = Ndata;
+  } 
+
+  /* alloc, read images */
+  ALLOCATE (image, Image, MAX (Nimage, 1));
+  nimage = Fread (image, sizeof(Image), Nimage, f, "image");
+  if (nimage != Nimage) {
+    if (VERBOSE) fprintf (stderr, "ERROR: problem loading image catalog\n");
+    exit (1);
+  } 
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+
+  /* allocate space for reference lists */
+  Nin = 0;
+  ALLOCATE (index, int, Nimage);
+  
+  /* note that we are looking for overlap only with tstart */
+  for (i = 0; i < Nimage; i++) {
+    for (j = 0, status = FALSE; !status && (j < Ntimes); j++) {
+      status = (image[i].tzero >= tstart[j]) && (image[i].tzero <= tstop[j]);
+    }
+    if (!status && Ntimes) continue;
+    if (PhotCodeSelect && (image[i].source != PHOTCODE)) continue;
+    if ((NameSelect != (char *) NULL) && (strncasecmp (image[i].name, NameSelect, NameSelectLength))) continue;
+
+    index[Nin] = i;
+    Nin ++;
+  }
+
+  /* output the selected entries */
+  if (FitsOutput != (char *) NULL) {
+    status = DumpFitsTable (FitsOutput, image, Nimage, index, Nin);
+  } else {
+    for (j = 0; j < Nin; j++) {
+      i = index[j];
+      
+      /* convert UNIX time to Elixir-style date string */
+      timestr = sec_to_date (image[i].tzero);
+      
+      /* convert photcode to filter name */
+      photstr = GetPhotnamebyCode (&photcodes, image[i].source);
+      if (photstr == (char *) NULL) photstr = PhotError;
+      
+      fprintf (stdout, "%s %s %s  %7.4f %d\n", image[i].name, photstr, timestr, image[i].secz, image[i].nstar); 
+      free (timestr);
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+DumpFitsTable (char *filename, Image *image, int Nentry, int *index, int Nkeep) {
+  
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  Image *newdata;
+  FILE *f;
+  char *startstr, *filtstr, *datestr, *line;
+  int i;
+  double zp, dzp, ra, dec, airmass, sky;
+  unsigned long tsecond;
+
+  /* create primary header */
+  fits_init_header (&header);    
+  header.extend = TRUE;
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+  fits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* create table header */
+  fits_create_table_header (&theader, "TABLE", "ZPTS");
+    
+  /* add current date/time to header */
+  str_to_time ("now", &tsecond);
+  datestr = sec_to_date (tsecond);
+  fits_modify (&header,  "DATE", "%s", 1, datestr);
+  fits_modify (&theader, "DATE", "%s", 1, datestr);
+  
+  /* define table layout */
+  fits_define_table_column (&theader, "A20",   "START_TIME", "start time of measurement", "yyyy/mm/dd,hh:mm:ss");
+  fits_define_table_column (&theader, "A10",   "FILTER",     "filter and camera name",    "");
+  fits_define_table_column (&theader, "F8.4",  "ZP_OBS",     "measured zero point",       "mag");
+  fits_define_table_column (&theader, "F7.4",  "ZP_ERR",     "error on zero point",       "mag");
+  fits_define_table_column (&theader, "F11.6", "RA",         "RA (J2000)",                "dec. degrees");
+  fits_define_table_column (&theader, "F11.6", "DEC",        "DEC (J2000)",               "dec. degrees");
+  fits_define_table_column (&theader, "F7.3",  "C_AIRMASS",  "airmass coeff",             "mag per airmass"); 
+  fits_define_table_column (&theader, "F7.1",  "SKY",        "median sky flux",           "counts");
+  fits_define_table_column (&theader, "I6",    "NSTAR",      "Number of stars in image",  "stars");
+  
+  /* define TNULL, TNVAL values */
+  fits_modify (&theader, "TNULL1",  "%s", 1, "NULL"); /* START_TIME */
+  fits_modify (&theader, "TNULL2",  "%s", 1, "NULL"); /* FILTER     */
+  fits_modify (&theader, "TNULL3",  "%s", 1, "NaN");  /* ZP_OBS     */
+  fits_modify (&theader, "TNULL4",  "%s", 1, "NaN");  /* ZP_ERR     */
+  fits_modify (&theader, "TNULL5",  "%s", 1, "NaN");  /* RA         */
+  fits_modify (&theader, "TNULL6",  "%s", 1, "NaN");  /* DEC        */
+  fits_modify (&theader, "TNULL7",  "%s", 1, "NaN");  /* C_AIRMASS  */
+  fits_modify (&theader, "TNULL8",  "%s", 1, "NaN");  /* SKY        */
+  fits_modify (&theader, "TNULL9",  "%s", 1,  "-1");  /* NSTAR      */
+
+  fits_modify (&theader, "TNVAL1",  "%s", 1, "NA");   /* START_TIME */
+  fits_modify (&theader, "TNVAL2",  "%s", 1, "NA");   /* FILTER     */
+  fits_modify (&theader, "TNVAL3",  "%s", 1, "Inf");  /* ZP_OBS     */
+  fits_modify (&theader, "TNVAL4",  "%s", 1, "Inf");  /* ZP_ERR     */
+  fits_modify (&theader, "TNVAL5",  "%s", 1, "Inf");  /* RA         */
+  fits_modify (&theader, "TNVAL6",  "%s", 1, "Inf");  /* DEC        */
+  fits_modify (&theader, "TNVAL7",  "%s", 1, "Inf");  /* C_AIRMASS  */
+  fits_modify (&theader, "TNVAL8",  "%s", 1, "Inf");  /* SKY        */
+  fits_modify (&theader, "TNVAL9",  "%s", 1,  "-2");  /* NSTAR      */
+
+  /* create table, add data values */
+  fits_create_table (&theader, &table);
+  
+  /* add selected data to table */
+  for (i = 0; i < Nkeep; i++) {
+    newdata  = &image[index[i]];
+    startstr = sec_to_date (newdata[0].tzero);
+    filtstr  = GetPhotnamebyCode (&photcodes, newdata[0].source);
+    zp       = 0.001*newdata[0].Mcal;
+    dzp      = 0.001*newdata[0].dMcal;
+    
+    XY_to_RD (&ra, &dec, 0.0, 0.0, &newdata[0].coords);
+    airmass  = 0.001*newdata[0].secz;
+    sky      = newdata[0].Myyyy + 0x8000;
+
+    line = fits_table_print (&table, startstr, filtstr, zp, dzp, ra, dec, airmass, sky, newdata[0].nstar);
+    fits_add_rows (&table, line, 1, strlen(line));
+
+    free (line);
+    free (startstr);
+    free (filtstr);
+  }
+    
+  /* write data to output file */
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Failure writing fits table\n");
+    return (FALSE);
+  }
+  fits_fwrite_header  (f, &header);
+  fits_fwrite_matrix  (f, &matrix);
+  fits_fwrite_Theader (f, &theader);
+  fits_fwrite_table   (f, &table);
+  fclose (f);
+  return (TRUE);
+}
+
+/*
+
+  selection options:
+
+  CCDSelect
+  TypeSelect
+  TimeSelect
+  FilterSelect
+  ExptimeSelect
+  EntrySelect
+  LabelSelect
+
+*/
Index: /trunk/Ohana/src/imregister/src/photreg.c
===================================================================
--- /trunk/Ohana/src/imregister/src/photreg.c	(revision 90)
+++ /trunk/Ohana/src/imregister/src/photreg.c	(revision 90)
@@ -0,0 +1,23 @@
+# include "imregister.h"
+# include "photreg.h"
+static char *version = "photreg $Revision: 1.1 $";
+
+main (int argc, char **argv) {
+ 
+  int status;
+  PhotPars newdata;
+  
+  /* data values are set in args by matching flags */
+  get_version (argc, argv, version);
+  regargs (argc, argv, &newdata);
+
+  status = load_db ();
+  if (!status) {
+    create_db ();
+  }
+  append_db (&newdata, 1);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
Index: /trunk/Ohana/src/imregister/src/photsearch.c
===================================================================
--- /trunk/Ohana/src/imregister/src/photsearch.c	(revision 90)
+++ /trunk/Ohana/src/imregister/src/photsearch.c	(revision 90)
@@ -0,0 +1,26 @@
+# include "imregister.h"
+# include "photreg.h"
+static char *version = "photsearch $Revision: 1.1 $";
+
+main (int argc, char **argv) {
+
+  int status, Nmatch;
+  int *match;
+
+  /* db selection is set in args, based on -trans */
+  get_version (argc, argv, version);
+  args (argc, argv);
+  
+  status = load_db ();
+  if (!status) {
+    close_db ();
+    exit (0);
+  }
+  if (!output.modify && !output.delete) close_db ();
+
+  match = match_criteria (&Nmatch);
+
+  if (output.delete) DeleteSubset (match, Nmatch);
+
+  OutputSubset (match, Nmatch);
+}
