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");
Index: trunk/Ohana/src/opihi/dimm/Image.c
===================================================================
--- trunk/Ohana/src/opihi/dimm/Image.c	(revision 15442)
+++ trunk/Ohana/src/opihi/dimm/Image.c	(revision 15487)
@@ -55,10 +55,10 @@
   Matrix matrix;
 
+  gfits_init_header (&header);
+
   header.Naxes = 2;
   header.Naxis[0] = image[0].Nx;
   header.Naxis[1] = image[0].Ny;
   header.bitpix = 16;
-  header.bzero = 0;
-  header.bscale = 1;
 
   gfits_create_header (&header);
Index: trunk/Ohana/src/opihi/doc/rd-upgrades.txt
===================================================================
--- trunk/Ohana/src/opihi/doc/rd-upgrades.txt	(revision 15487)
+++ trunk/Ohana/src/opihi/doc/rd-upgrades.txt	(revision 15487)
@@ -0,0 +1,10 @@
+
+rd a file.fits : read from PHU
+rd a file.fits -x N : read from extension N (0 - N)
+rd a file.fits -n name : read from extension name
+
+-plane : read only slice N
+
+* this function needs to check for compressed data:
+
+  * if PHU has been compressed, 
Index: trunk/Ohana/src/opihi/dvo/cmpread.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/cmpread.c	(revision 15442)
+++ trunk/Ohana/src/opihi/dvo/cmpread.c	(revision 15487)
@@ -83,5 +83,5 @@
   } else {
     gprint (GP_ERR, "reading from FITS cmp file %s\n", argv[2]);
-    Nbytes = gfits_matrix_size (&header);
+    Nbytes = gfits_data_size (&header);
     fseek (f, Nbytes, SEEK_CUR); 
     stars = cmpReadFits (f, &Nstars);
Index: trunk/Ohana/src/opihi/dvo/imbox.c
===================================================================
--- trunk/Ohana/src/opihi/dvo/imbox.c	(revision 15442)
+++ trunk/Ohana/src/opihi/dvo/imbox.c	(revision 15487)
@@ -79,5 +79,5 @@
     }
   skip:
-    Nskip = gfits_matrix_size (&header);
+    Nskip = gfits_data_size (&header);
     fseek (f, Nskip, SEEK_CUR); 
     gfits_free_header (&header);
Index: trunk/Ohana/src/opihi/lib.shell/BufferOps.c
===================================================================
--- trunk/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 15442)
+++ trunk/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 15487)
@@ -76,8 +76,4 @@
   /* assign the necessary internal values */
   buf[0].header.bitpix   = -32;
-  buf[0].header.unsign   = FALSE;
-  buf[0].header.bzero    = 0;
-  buf[0].header.bscale   = 1;
-  
   buf[0].header.Naxes = 2;
   buf[0].header.Naxis[0] = Nx;
@@ -85,5 +81,4 @@
 
   buf[0].bitpix = bitpix;
-  buf[0].unsign = FALSE;
   buf[0].bzero  = bzero;
   buf[0].bscale = bscale;
Index: trunk/Ohana/src/opihi/pantasks/task_trange.c
===================================================================
--- trunk/Ohana/src/opihi/pantasks/task_trange.c	(revision 15442)
+++ trunk/Ohana/src/opihi/pantasks/task_trange.c	(revision 15487)
@@ -57,4 +57,7 @@
   }
 
+  /* allow a syntax which means something like "every hour at MM:SS"
+     this could by something like *:MM:SS ? */
+
   /* test for HH:MM:SS */
   if (hms_to_sec (argv[1], &range.start)) {
