Index: trunk/Ohana/src/opihi/cmd.data/rd.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/rd.c	(revision 15442)
+++ trunk/Ohana/src/opihi/cmd.data/rd.c	(revision 15487)
@@ -5,5 +5,5 @@
   
   int i, N, status, plane, Nplane, extend, Nextend, Nskip, JustHead;
-  int ccdsel, done;
+  int ccdsel, done, Nword, IsCompressed;
   char region[512], *ccdid, *filename;
   FILE *f;
@@ -85,5 +85,9 @@
       return (FALSE);
     }
+    if (gfits_extension_is_compressed (&buf[0].header)) {
+	IsCompressed = TRUE;
+    }
   } 
+
   /* FITS extension by name */
   if (ccdsel) {
@@ -92,6 +96,6 @@
     CCDKeyword = get_variable ("CCDKEYWORD");
     if (CCDKeyword == (char *) NULL) {
-      gprint (GP_ERR, "CCDKEYWORD variable is not set; ");
-      gprint (GP_ERR, "using EXTNAME as default\n");
+      // gprint (GP_ERR, "CCDKEYWORD variable is not set; ");
+      // gprint (GP_ERR, "using EXTNAME as default\n");
       CCDKeyword = strcreate ("EXTNAME");
     }
@@ -106,5 +110,17 @@
 	return (FALSE);
       }
-      if (!gfits_scan (&buf[0].header, CCDKeyword, "%s", 1, ID)) {
+
+      // for compressed data tables, EXTNAME may be duplicated, with the first one containing the
+      // word 'COMPRESSED_IMAGE'.  in this case, check the second EXTNAME, if CCDKeyword == EXTNAME 
+      // this may have to be a more obscure test specifically for 'imcopy' data...
+      // need to check each header, since file may contain a mix
+      
+      Nword = 1;
+      IsCompressed = FALSE;
+      if (gfits_extension_is_compressed (&buf[0].header)) {
+	if (!strcmp (CCDKeyword, "EXTNAME")) Nword = 2;
+	IsCompressed = TRUE;
+      }
+      if (!gfits_scan (&buf[0].header, CCDKeyword, "%s", Nword, ID)) {
 	gprint (GP_ERR, "%s not in header\n", CCDKeyword);
 	DeleteBuffer (buf);
@@ -123,11 +139,7 @@
   /* fix up header, if needed */
   if (extend || ccdsel) {
-    static char simple[] = "SIMPLE  =                    T / Standard FITS";
-    int Ns, No;
-
-    Ns = strlen (simple);
-    No = 80 - Ns;
-    strncpy (buf[0].header.buffer, simple, Ns);
-    memset (&buf[0].header.buffer[Ns], ' ', No);
+    if (!IsCompressed) {
+      gfits_extended_to_primary (&buf[0].header, TRUE, "Standard FITS");
+    }
   } else {
       gfits_fread_header (f, &buf[0].header);
@@ -135,6 +147,7 @@
 
   /* for JustHead, we skip reading the data segment */ 
+  // XXX for compressed data, we need to convert the header to the equivalent uncompressed version
   if (JustHead) {
-    /* should be in CreateMatrix / CreateBuffer function */
+    // XXX what are we doing here exactly?
     buf[0].header.Naxes = 0;
     ALLOCATE (buf[0].matrix.buffer, char, 1);
@@ -164,7 +177,18 @@
 
   /* load matrix data */
-  sprintf (region, "-1 -1 -1 -1 %d %d", (plane - 1), plane);
-  status = gfits_fread_matrix_segment (f, &buf[0].matrix, &buf[0].header, region);
-  fclose (f);
+  if (IsCompressed) {
+    FTable ftable;
+    Header theader;
+    ftable.header = &theader;
+    gfits_copy_header (&buf[0].header, ftable.header);
+    status = gfits_fread_ftable_data (f, &ftable);  // XXX does this do more than read the bytes?
+    status = gfits_uncompress_image (&buf[0].header, &buf[0].matrix, &ftable, !(ccdsel || extend));
+    gfits_free_table (&ftable);
+    // XXX this currently does not work for a cube (we get a cube back, not a specific plane)
+  } else {
+    sprintf (region, "-1 -1 -1 -1 %d %d", (plane - 1), plane);
+    status = gfits_fread_matrix_segment (f, &buf[0].matrix, &buf[0].header, region);
+    fclose (f);
+  }
 
   if (!status) {
Index: trunk/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 15442)
+++ trunk/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 15487)
@@ -150,45 +150,80 @@
 int read_table_vectors (int argc, char **argv, char *extname) {
 
-  int i, j, k, Nbytes, Nread, Nextend, Ny, Binary;
-  char type[16];
+  int i, j, k, N, Nbytes, Nread, Nextend, Ny, Binary;
+  char type[16], ID[80], *CCDKeyword;
   FTable table;
   Header header;
   Vector **vec;
 
+  table.buffer = NULL;
+  header.buffer = NULL;
+
+  CCDKeyword = NULL;
+  if ((N = get_argument (argc, argv, "-keyword"))) {
+    remove_argument (N, &argc, argv);
+    CCDKeyword = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Nextend = -1;
+  if ((N = get_argument (argc, argv, "-extnum"))) {
+    remove_argument (N, &argc, argv);
+    Nextend = atoi (extname);
+  }
+
   if (argc < 2) {
-    gprint (GP_ERR, "USAGE: read -fits extension name name ...\n");
+    gprint (GP_ERR, "USAGE: read -fits extension [-extnum] [-keyword key] name name ...\n");
     gprint (GP_ERR, "  ('extension' may be a name or number)\n");
-    return (FALSE);
-  }
-
-  if (f == (FILE *) NULL) return (FALSE);
+    goto escape;
+  }
+
+  if (f == (FILE *) NULL) goto escape;
   fseek (f, 0, SEEK_SET);
   table.header = &header;
 
   /* load appropriate extension (if extname is a number, use count) */
-  if (isdigit(extname[0])) {
-    Nextend = atoi (extname);
-
-    for (i = 0; i <= Nextend; i++) {
-      if (!gfits_load_header (f, &header)) return (FALSE);
-      Nbytes = gfits_matrix_size (&header);
+  if (Nextend > -1) {
+    // first extension is PHU, cannot be a table. 
+    // Nextend counts from 0 for first extension
+    if (!gfits_load_header (f, &header)) goto escape;
+    Nbytes = gfits_data_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+    gfits_free_header (&header);
+
+    for (i = 0; i < Nextend; i++) {
+      if (!gfits_load_header (f, &header)) goto escape;
+      Nbytes = gfits_data_size (&header);
       /* skip the prior data buffers */
-      if (i < Nextend) { 
+      fseek (f, Nbytes, SEEK_CUR);
+      gfits_free_header (&header);
+    }
+    if (!gfits_load_header (f, &header)) goto escape;
+    if (!gfits_fread_ftable_data (f, &table)) goto escape;
+
+  } else {
+    if (CCDKeyword == NULL) {
+      CCDKeyword = get_variable ("CCDKEYWORD");
+    }
+    if (CCDKeyword == NULL) {
+      CCDKeyword = strcreate ("EXTNAME");
+    }
+
+    while (1) {
+      if (!gfits_load_header (f, &header)) goto escape;
+      Nbytes = gfits_data_size (&header);
+
+      if (!gfits_scan (&header, CCDKeyword, "%s", 1, ID)) {
 	fseek (f, Nbytes, SEEK_CUR);
 	gfits_free_header (&header);
 	continue;
       }
-      /* on the desired header, load buffer */
-      ALLOCATE (table.buffer, char, Nbytes);
-      Nread = fread (table.buffer, sizeof (char), Nbytes, f);
-      if (Nread != Nbytes) {
-	gfits_free_table  (&table);
+      if (strcmp (ID, extname)) {
+	fseek (f, Nbytes, SEEK_CUR);
 	gfits_free_header (&header);
-	return (FALSE);
-      }
-      table.size = Nbytes;
-    }
-  } else {
-    if (!gfits_fread_ftable (f, &table, extname)) return (FALSE);
+	continue;
+      }
+      if (!gfits_fread_ftable_data (f, &table)) goto escape;
+      break;
+    }
   }
 
@@ -196,7 +231,9 @@
   Binary = FALSE;
   gfits_scan (&header, "XTENSION", "%s", 1, type);
-  if (!strcmp (type, "BINTABLE")) {
-    Binary = TRUE;
-  } 
+  if (strcmp (type, "BINTABLE") && strcmp (type, "TABLE")) {
+    gprint (GP_ERR, "specified extension (%s) is not a table\n", extname);
+    goto escape;
+  }
+  Binary = !strcmp (type, "BINTABLE");
   Ny = header.Naxis[1];
 
@@ -214,11 +251,11 @@
     Nval = 0;
     if (Binary) {
-      if (!gfits_get_bintable_column_type (&header, argv[i], type, &Nval)) return (FALSE);
-      if (!gfits_get_bintable_column (&header, &table, argv[i], &data)) return (FALSE);
+      if (!gfits_get_bintable_column_type (&header, argv[i], type, &Nval)) goto escape;
+      if (!gfits_get_bintable_column (&header, &table, argv[i], &data)) goto escape;
     } else {
-      if (!gfits_get_table_column_type (&header, argv[i], type)) return (FALSE);
-      if (!gfits_get_table_column (&header, &table, argv[i], &data)) return (FALSE);
-    }
-    if (Nval == 0) return (FALSE);
+      if (!gfits_get_table_column_type (&header, argv[i], type)) goto escape;
+      if (!gfits_get_table_column (&header, &table, argv[i], &data)) goto escape;
+    }
+    if (Nval == 0) goto escape;
 
     ALLOCATE (vec, Vector *, Nval);
@@ -228,5 +265,5 @@
       else
 	sprintf (name, "%s:%d", argv[i], j);
-      if ((vec[j] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+      if ((vec[j] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) goto escape;
       REALLOCATE (vec[j][0].elements, float, MAX (Ny,1));
       vec[j][0].Nelements = Ny;
@@ -276,6 +313,13 @@
     free (vec);
   }
+  if (CCDKeyword != NULL) free (CCDKeyword);
   gfits_free_table (&table);
   gfits_free_header (&header);
   return (TRUE);
+
+escape:
+  if (CCDKeyword != NULL) free (CCDKeyword);
+  gfits_free_table  (&table);
+  gfits_free_header (&header);
+  return (FALSE);
 }
Index: trunk/Ohana/src/opihi/cmd.data/wd.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.data/wd.c	(revision 15442)
+++ trunk/Ohana/src/opihi/cmd.data/wd.c	(revision 15487)
@@ -91,14 +91,9 @@
     if (!gfits_read_header (argv[2], &Xhead)) {
 
-      Xhead.simple = TRUE;
+      gfits_init_header (&Xhead);
       Xhead.bitpix = 16;
-      Xhead.Naxes = 0;
-      
       Xhead.extend = TRUE;
-      Xhead.bscale = 1.0;
-      Xhead.bzero  = 0.0;
-      Xhead.unsign = FALSE;
-      
       gfits_create_header (&Xhead);
+
       gfits_modify (&Xhead, "NEXTEND", "%d", 1, 0);
       f = fopen (argv[2], "w");
