Index: /trunk/Ohana/src/imregister/doc/spdb.txt
===================================================================
--- /trunk/Ohana/src/imregister/doc/spdb.txt	(revision 3490)
+++ /trunk/Ohana/src/imregister/doc/spdb.txt	(revision 3491)
@@ -73,2 +73,6 @@
        - spload-mef converts to a single 
 
+-----
+
+database interactions vs autocode FITS tables
+
Index: /trunk/Ohana/src/imregister/include/spreg.h
===================================================================
--- /trunk/Ohana/src/imregister/include/spreg.h	(revision 3490)
+++ /trunk/Ohana/src/imregister/include/spreg.h	(revision 3491)
@@ -1,3 +1,27 @@
 # include <signal.h>
+
+/*** fits_db test APIs ***/
+typedef struct {
+  FILE  *f;
+  char  *extname;
+  int    dbstate;
+  int    lockstat;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+} DB;
+
+DB *fits_db_init ();
+DB *fits_db_lock (DB *db, char *filename);
+int fits_db_load (DB *db);
+int fits_db_save (DB *db);
+int fits_db_free (DB *db);
+int fits_db_update (DB *db, VTable *vtable);
+int fits_db_close (DB *db);
+int fits_db_print_status (DB *db, char *message);
+int fits_db_escape (DB *db, char *message);
+
+/**** move to fitsio.h ***/
 
 enum {
Index: /trunk/Ohana/src/imregister/spreg/db2.c
===================================================================
--- /trunk/Ohana/src/imregister/spreg/db2.c	(revision 3491)
+++ /trunk/Ohana/src/imregister/spreg/db2.c	(revision 3491)
@@ -0,0 +1,134 @@
+# include "imregister.h"
+# include "spreg.h"
+
+DB *fits_db_init (int lockstate) {
+
+  DB *db;
+
+  ALLOCATE (db, DB, 1);
+  db[0].header.buffer = NULL;
+  db[0].matrix.buffer = NULL;
+  db[0].ftable.buffer = NULL;
+  db[0].ftable.header = &db[0].theader;
+  db[0].lockstate = lockstate;
+  return (db);
+}
+
+DB *fits_db_lock (DB *db, char *filename) {
+  
+  /* database name must be set first */
+  if (filename == (char *) NULL) {
+    fprintf (stderr, "ERROR: db file is not set\n");
+    return (FALSE);
+  }
+
+  /* database name must be set first */
+  if (db == (char *) NULL) {
+    fprintf (stderr, "ERROR: db is not set\n");
+    return (FALSE);
+  }
+
+  /* lock & open database */
+  db[0].f = fsetlockfile (filename, db[0].timeout, db[0].lockstate, &db[0].dbstate);
+  if (db[0].f == NULL) {
+    fprintf (stderr, "ERROR: cannot set lock on db\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* load the complete db table into memory - only loads first extension, does not validate EXTNAME */
+int fits_db_load (DB *db) {
+
+  int Nx, Ny;
+
+  /* database name must be set first */
+  if (db == (char *) NULL) {
+    fprintf (stderr, "ERROR: db is not set\n");
+    return (FALSE);
+  }
+
+  /* init & load in FITS table data */
+  if (!fits_fread_header (db[0].f, &db[0].header))                fits_db_escape (db, "ERROR: can't read primary header"); 
+  if (!fits_fread_matrix (db[0].f, &db[0].matrix, &db[0].header)) fits_db_escape (db, "ERROR: can't read primary matrix");
+  if (!fits_fread_header (db[0].f, &db[0].theader))               fits_db_escape (db, "ERROR: can't read table header");
+  if (!fits_fload_ftable (db[0].f, &db[0].table))                 fits_db_escape (db, "ERROR: can't read table data");
+  return (TRUE);
+}
+
+/* write complete db file */
+int fits_db_save (DB *db) {
+
+  /* write all data to file */
+  make_backup (db[0].filename);
+  Fseek (db[0].f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (db[0].f, &db[0].header))  fits_db_escape (db, "ERROR: can't write primary header");
+  if (!fits_fwrite_matrix  (db[0].f, &db[0].matrix))  fits_db_escape (db, "ERROR: can't write primary matrix");
+  if (!fits_fwrite_Theader (db[0].f, &db[0].theader)) fits_db_escape (db, "ERROR: can't write table header");
+  if (!fits_fwrite_table   (db[0].f, &db[0].table))   fits_db_escape (db, "ERROR: can't write table data");
+  fclearlockfile (db[0].filename, db[0].f, db[0].lockstate, &db[0].dbstate);
+  return (TRUE);
+}
+
+/* write vtable to db file (also appends rows to the end of the table) */
+int fits_db_update (DB *db, VTable *vtable) {
+
+  /* this section is not valid if we have changed the size of header, matrix, theader */
+
+  /* write subset to file */
+  make_backup (db[0].filename);
+  Fseek (db[0].f, 0, SEEK_SET);
+  if (!fits_fwrite_header   (db[0].f, &db[0].header))  fits_db_escape (LOCK, "ERROR: can't update primary header");
+  if (!fits_fwrite_matrix   (db[0].f, &db[0].matrix))  fits_db_escape (LOCK, "ERROR: can't update primary matrix");
+  if (!fits_fwrite_Theader  (db[0].f, &db[0].theader)) fits_db_escape (LOCK, "ERROR: can't update table header");
+  if (!fits_fwrite_vtable   (db[0].f, &db[0].vtable))  fits_db_escape (LOCK, "ERROR: can't update table data");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+  fits_free_vtable (&vtable);
+  fits_free_table  (&table);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+int fits_db_free (DB *db) {
+  fits_free_header (&db[0].header);
+  fits_free_matrix (&db[0].matrix);
+  fits_free_header (&db[0].theader);
+  fits_free_table  (&db[0].table);
+  return (TRUE);
+}
+
+/* close the db files  */
+int fits_db_close (DB *db) {
+  if (dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  if ((Nimage == 0) && (lockstate != LCK_SOFT)) unlink (dBFile);
+
+  return (TRUE);
+}  
+
+int fits_db_print_status (DB *db, char *message) {
+
+  int fd;
+
+  if (!output.verbose) return (0);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "%s - db: %s - fd: %d\n", message, "null", -1);
+    return (0);
+  }
+  fd = fileno (f);
+  fprintf (stderr, "%s - db: %s - fd: %d\n", message, dBFile, fd);
+  return (TRUE);
+}
+
+int fits_db_escape (DB *db, char *message) {
+  
+  if (mode == UNLOCK) close_db ();
+  fprintf (stderr, "%s\n", message);
+  exit (1);
+}
Index: /trunk/Ohana/src/imregister/spreg/delete.c
===================================================================
--- /trunk/Ohana/src/imregister/spreg/delete.c	(revision 3490)
+++ /trunk/Ohana/src/imregister/spreg/delete.c	(revision 3491)
@@ -2,11 +2,9 @@
 # include "spreg.h"
 
-void DeleteSubset (int *match, int Nmatch) {
+void DeleteSubset (DB *db, Spectrum *spectrum, int Nspectrum, int *match, int Nmatch) {
 
   int i, j;
-  int *keep, Nbad, Nspectrum, Nsubset;
-  Spectrum *spectrum, *subset;
-
-  spectrum = get_spectra (&Nspectrum);
+  int *keep, Nbad, Nsubset;
+  Spectrum *subset;
 
   ALLOCATE (keep, int, MAX (Nspectrum, 1));
@@ -33,8 +31,7 @@
 
   free (keep);
-  set_spectra (subset, Nsubset);
 
-  save_db ();
+  fits_table_set_Spectrum (&db[0].table, subset, Nsubset);
+  fits_db_save (db);
   exit (0);
-
 }
Index: /trunk/Ohana/src/imregister/spreg/match.c
===================================================================
--- /trunk/Ohana/src/imregister/spreg/match.c	(revision 3490)
+++ /trunk/Ohana/src/imregister/spreg/match.c	(revision 3491)
@@ -2,12 +2,11 @@
 # include "spreg.h"
 
-int *match_criteria (int *Nmatch) {
+int *match_criteria (Spectrum *spectrum, int Nspectrum, int *Nmatch) {
 
-  int i, j, Nspectrum;
+  int i, j;
   int N, NMATCH;
   int *match;
   int reject;
   int Nfilename, Nobject, Ntelescope, Ninstrument;
-  Spectrum *spectrum;
 
   /* create selection index */
@@ -18,10 +17,8 @@
   Nfilename = Nobject = Ntelescope = Ninstrument = 0;
 
-  if (criteria.FilenameSelect) Nfilename     = strlen (criteria.Filename);
-  if (criteria.ObjectSelect) Nobject         = strlen (criteria.Object);
-  if (criteria.TelescopeSelect) Ntelescope   = strlen (criteria.Telescope);
+  if (criteria.FilenameSelect)   Nfilename   = strlen (criteria.Filename);
+  if (criteria.ObjectSelect)     Nobject     = strlen (criteria.Object);
+  if (criteria.TelescopeSelect)  Ntelescope  = strlen (criteria.Telescope);
   if (criteria.InstrumentSelect) Ninstrument = strlen (criteria.Instrument);
-
-  spectrum = get_spectra (&Nspectrum);
 
   /* find entries that matches criteria */
Index: /trunk/Ohana/src/imregister/spreg/modify.c
===================================================================
--- /trunk/Ohana/src/imregister/spreg/modify.c	(revision 3490)
+++ /trunk/Ohana/src/imregister/spreg/modify.c	(revision 3491)
@@ -2,15 +2,12 @@
 # include "spreg.h"
 
-void ModifySubset (int *match, int Nmatch) {
+void ModifySubset (DB *db, Spectrum *spectrum, int Nspectrum, int *match, int Nmatch) {
 
   int i, j, Nold;
   char *tmppath;
-  int Nspectrum;
-  Spectrum *spectrum;
+  VTable vtable;
 
   Nold = 0;
   tmppath = NULL;
-
-  spectrum = get_spectra (&Nspectrum);
 
   /* create some necessary variables */
@@ -41,5 +38,9 @@
   }
 
-  update_db (match, Nmatch);
+  fits_vtable_from_ftable (&vtable, &db[0].ftable, match, Nmatch);
+  for (i = 0; i < Nmatch; i++) {
+    fits_convert_Spectrum (vtable.buffer[i], 1);
+  }
+  fits_db_update (db, &vtable);
   fprintf (stderr, "SUCCESS\n");
   exit (0);
Index: /trunk/Ohana/src/imregister/spreg/output.c
===================================================================
--- /trunk/Ohana/src/imregister/spreg/output.c	(revision 3490)
+++ /trunk/Ohana/src/imregister/spreg/output.c	(revision 3491)
@@ -3,5 +3,5 @@
 
 static int RegTimeMode = FALSE;
-static int PTstyle = FALSE;
+static int PTstyle     = FALSE;
 
 void SetOutputMode (char *mode) {
@@ -19,10 +19,5 @@
 
 /* given a subset list, write out the selected spectra, if desired */
-void OutputSubset (int *match, int Nmatch) {
-
-  int Nspectrum;
-  Spectrum *spectrum;
-
-  spectrum = get_spectra (&Nspectrum);
+void OutputSubset (Spectrum *spectra, int Nspectra, int *match, int Nmatch) {
 
   if (output.table != (char *) NULL) {
@@ -42,12 +37,11 @@
 
   int i, j;
-  Header header, theader;
+  Header header;
   Matrix matrix;
-  FTable table;
+  Header theader;
+  FTable ftable;
   Spectrum *subset;
 
-  /* define table layout */
-  define_table (&header, &matrix, &theader, &table);
-
+  /* extract subset list to single array */
   ALLOCATE (subset, Spectrum, MAX (1, Nmatch));
   for (i = 0; i < Nmatch; i++){
@@ -55,14 +49,32 @@
     memcpy (&subset[i], &spectrum[j], sizeof (Spectrum));
   }
-  ConvertStruct ((char *) subset, sizeof (Spectrum), Nmatch, "spectrum");
-  fits_add_rows (&table, (char *) subset, Nmatch, sizeof (Spectrum));
 
-  fits_write_header  (filename, &header);
-  fits_write_matrix  (filename, &matrix);
-  fits_write_Theader (filename, &theader);
-  fits_write_table   (filename, &table);
+  /* open file for output */
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", filename);
+    exit (1);
+  }
+
+  /* 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);
+
+  ftable.header = &theader;
+  fits_table_set_Spectrum (&ftable, subset, Nmatch);
+
+  fits_fwrite_header   (f, &header);
+  fits_fwrite_matrix   (f, &matrix);
+  fits_fwrite_Theader  (f, &theader);
+  fits_fwrite_ftable   (f, &ftable));
+  fclose (f);
+
   exit (0);
 }
 
+/* can the table definition here be autocoded as well? */
 void DumpFitsTable (char *filename, Spectrum *spectrum, int *match, int Nmatch) {
   
@@ -94,5 +106,5 @@
   fits_modify (&theader, "DATE", "%s", 1, datestr);
 
-  /* define table layout */
+  /* define table layout (can this be autocoded?) */
   fits_define_table_column (&theader, "A32",  "FILENAME",   "filename in db",        "");
   fits_define_table_column (&theader, "A64",  "PATHNAME",   "fullpath in db",        "");
Index: /trunk/Ohana/src/imregister/spreg/unique.c
===================================================================
--- /trunk/Ohana/src/imregister/spreg/unique.c	(revision 3490)
+++ /trunk/Ohana/src/imregister/spreg/unique.c	(revision 3491)
@@ -3,10 +3,9 @@
 
 /* input is a subset index of spectrum list, output is a new subset */
-int *unique_entries (int *subset, int *Nmatch) {
+int *unique_entries (Spectrum *spectrum, int Nspectrum, int *subset, int *Nmatch) {
 
-  int i, j, m, Nspectrum, Nsubset;
+  int i, j, m, Nsubset;
   int N, NMATCH;
   int *match, *entry;
-  Spectrum *spectrum;
   char idxline[128];
   char **index;
@@ -20,5 +19,4 @@
 
   Nsubset = *Nmatch;
-  spectrum = get_spectra (&Nspectrum);
 
   /* index = filename */
Index: /trunk/Ohana/src/imregister/src/spsearch.c
===================================================================
--- /trunk/Ohana/src/imregister/src/spsearch.c	(revision 3490)
+++ /trunk/Ohana/src/imregister/src/spsearch.c	(revision 3491)
@@ -1,63 +1,40 @@
 # include "imregister.h"
 # include "spreg.h"
-static char *version = "imsearch $Revision: 1.1.1.1 $";
+static char *version = "spsearch $Revision: 1.2 $";
 
 int main (int argc, char **argv) {
  
-  int status, Nmatch;
+  int status, Nmatch, Nspectra;
   int *match;
+  DB *db;
+  Spectrum *spectra;
 
   get_version (argc, argv, version);
   args (argc, argv);
 
-  set_db (SpectrumDB);
+  lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+  db = fits_db_init (lockstate);
 
-  status = load_db ();
-  if (!status) {
-    close_db ();
-    exit (0);
+  if (!fits_db_lock (db, SpectrumDB)) {
+    fits_db_close (db);
+    exit (1);
   }
-  if (!output.modify && !output.delete) close_db ();
   
-  match = match_criteria (&Nmatch);
-  match = unique_entries (match, &Nmatch);
+  if (!fits_db_load (db)) {
+    fits_db_close (db);
+    exit (1);
+  }
+  if (!output.modify && !output.delete) fits_db_close (db);
 
-  if (output.modify) ModifySubset (match, Nmatch);
-  if (output.delete) DeleteSubset (match, Nmatch);
+  spectrum = fits_table_get_Spectrum (&db[0].table, &Nspectrum);
+  
+  match = match_criteria (spectra, Nspectra, &Nmatch);
+  match = unique_entries (spectra, Nspectra, match, &Nmatch);
 
-  OutputSubset (match, Nmatch);
+  if (output.modify) ModifySubset (db, spectra, Nspectra, match, Nmatch);
+  if (output.delete) DeleteSubset (db, spectra, Nspectra, match, Nmatch);
+
+  OutputSubset (spectra, Nspectra, match, Nmatch);
 
   exit (0);
 }
-
-/* 
-
-FITS table version:
-
-   load_db - open, read in database, store as RegImage structure
-   match   - return index 'match' to matched images
-   modify  - change value of selected images
-             write out subset of rows
-   delete  - remove selected images from image structure
-             write out entire table
-   output  - write out subset in various formats
-
-   get_images returns pointer to complete image structure
-
-
-SQL version:
-
-   load_db - set up connection
-   match   - convert criteria to SQL where clause and do:
-             'select from images [where clause]'
-             images structure is filled with result from query
-   modify  - change value of subset selection (identical)
-             update selected rows
-   delete  - user where clause and do 
-             'delete from images where clause'
-   output  - (identical)
-
-   get_images returns pointer to image subset from query
-   match[i] = i
-
-*/
