Index: /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_get_column.c
===================================================================
--- /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_get_column.c	(revision 36998)
+++ /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_get_column.c	(revision 36999)
@@ -75,4 +75,9 @@
   Pout = array;
   if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = *(char *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "byte")) {
     for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
       *(char *)Pout = *(char *)Pin*Bscale + Bzero;
Index: /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_set_column.c
===================================================================
--- /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_set_column.c	(revision 36998)
+++ /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_set_column.c	(revision 36999)
@@ -81,5 +81,11 @@
   Pin = data;
   Pout = array;
+  // does it makes sense to scale 'char' data?
   if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
+    }
+  }
+  if (!strcmp (type, "byte")) {
     for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
       *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
@@ -221,4 +227,7 @@
   Pout = array;
 
+  // # define ASSIGN_DATA(ITYPE,INAME,ISIZE,OTYPE,ONAME)
+  // if (!strcmp (intype, #ITYPE)) {
+
   /** input == char **/
   if (!strcmp (outtype, "char") && !strcmp (intype, "char")) {
@@ -228,4 +237,10 @@
     }
   }
+  if (!strcmp (outtype, "byte") && !strcmp (intype, "char")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin+=NbytesIn, Pout+=NbytesOut) {
+      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
+    }
+  }
   if (!strcmp (outtype, "short") && !strcmp (intype, "char")) {
     int NbytesIn = 1;
@@ -265,4 +280,63 @@
   }
   if (!strcmp (outtype, "double") && !strcmp (intype, "char")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(double *)Pout = (*(char *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_DBLE;
+# endif
+    }
+  }
+
+  /** input == byte **/
+  if (!strcmp (outtype, "char") && !strcmp (intype, "byte")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin+=NbytesIn, Pout+=NbytesOut) {
+      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
+    }
+  }
+  if (!strcmp (outtype, "byte") && !strcmp (intype, "byte")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin+=NbytesIn, Pout+=NbytesOut) {
+      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
+    }
+  }
+  if (!strcmp (outtype, "short") && !strcmp (intype, "byte")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(short *)Pout = (*(char *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_BYTE;
+# endif
+    }  
+  }
+  if (!strcmp (outtype, "int") && !strcmp (intype, "byte")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(int *)Pout = (*(char *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "byte")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(int64_t *)Pout = (*(char *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_DBLE;
+# endif
+    }
+  }
+  if (!strcmp (outtype, "float") && !strcmp (intype, "byte")) {
+    int NbytesIn = 1;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(float *)Pout = (*(char *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (outtype, "double") && !strcmp (intype, "byte")) {
     int NbytesIn = 1;
     for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
@@ -281,4 +355,10 @@
     }
   }
+  if (!strcmp (outtype, "byte") && !strcmp (intype, "short")) {
+    int NbytesIn = 2;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(char *)Pout = (*(short *)Pin - Bzero) / Bscale;
+    }
+  }
   if (!strcmp (outtype, "short") && !strcmp (intype, "short")) {
     int NbytesIn = 2;
@@ -334,4 +414,10 @@
     }
   }
+  if (!strcmp (outtype, "byte") && !strcmp (intype, "int")) {
+    int NbytesIn = 4;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(char *)Pout = (*(int *)Pin - Bzero) / Bscale;
+    }
+  }
   if (!strcmp (outtype, "short") && !strcmp (intype, "int")) {
     int NbytesIn = 4;
@@ -387,4 +473,10 @@
     }
   }
+  if (!strcmp (outtype, "byte") && !strcmp (intype, "int64_t")) {
+    int NbytesIn = 8;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(char *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
+    }
+  }
   if (!strcmp (outtype, "short") && !strcmp (intype, "int64_t")) {
     int NbytesIn = 8;
@@ -440,4 +532,10 @@
     }
   }
+  if (!strcmp (outtype, "byte") && !strcmp (intype, "float")) {
+    int NbytesIn = 4;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(char *)Pout = (*(float *)Pin - Bzero) / Bscale;
+    }
+  }
   if (!strcmp (outtype, "short") && !strcmp (intype, "float")) {
     int NbytesIn = 4;
@@ -488,4 +586,10 @@
   /** input == double **/
   if (!strcmp (outtype, "char") && !strcmp (intype, "double")) {
+    int NbytesIn = 8;
+    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
+      *(char *)Pout = (*(double *)Pin - Bzero) / Bscale;
+    }
+  }
+  if (!strcmp (outtype, "byte") && !strcmp (intype, "double")) {
     int NbytesIn = 8;
     for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
Index: /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_table_format.c
===================================================================
--- /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_table_format.c	(revision 36998)
+++ /branches/eam_branches/ipp-20140610/Ohana/src/libfits/table/F_table_format.c	(revision 36999)
@@ -19,11 +19,14 @@
   if ((Nv == 0) && (Fchar == format)) Nv = 1;
 
+  // NOTE: X, L, B all are stored in 1-byte columns (X by default has at least room for 8 bits)
+  // I report these as type 'byte' as opposed to 'char', which is interpreted as a string
+
   *Nbytes = 0;
   switch (*Fchar) {
   case  'X':
-    { *Nbytes = 1;  strcpy (type, "char");   *Nval = 1 + (int) Nv / 8; }
+    { *Nbytes = 1;  strcpy (type, "byte");   *Nval = 1 + (int) Nv / 8; }
     break;
   case  'L':
-    { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+    { *Nbytes = 1;  strcpy (type, "byte");   *Nval = Nv;               }
     break;
   case  'A':
@@ -31,5 +34,5 @@
     break;
   case  'B':
-    { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+    { *Nbytes = 1;  strcpy (type, "byte");   *Nval = Nv;               }
     break;
   case  'I':
@@ -268,5 +271,14 @@
     }
 
+    // Does it make sense to scale 'char' data (as opposed to 'byte')?
     if (!strcmp (type, "char"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpChar = (char *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpChar = *tmpChar * tscale + tzero;
+	}
+      }
+    }
+    if (!strcmp (type, "byte"))   { 
       for (j = 0; j < Ny; j++) {
 	for (n = 0; n < Nval; n++) {
@@ -352,4 +364,5 @@
     }
 
+    // does this make sense? (see note above)
     if (!strcmp (type, "char"))   { 
       for (j = 0; j < Ny; j++) {
@@ -360,4 +373,12 @@
       }
     }
+    if (!strcmp (type, "byte"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpChar = (char *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpChar = (*tmpChar - tzero) / tscale;
+	}
+      }
+    }
     if (!strcmp (type, "short"))   { 
       for (j = 0; j < Ny; j++) {
Index: /branches/eam_branches/ipp-20140610/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- /branches/eam_branches/ipp-20140610/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 36998)
+++ /branches/eam_branches/ipp-20140610/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 36999)
@@ -321,6 +321,6 @@
 }
 
-# define ESCAPE(MSG) { \
-  gprint (GP_ERR, "%s\n", MSG); \
+# define ESCAPE(...) {		\
+  gprint (GP_ERR, __VA_ARGS__); \
   if (CCDKeyword != NULL) free (CCDKeyword); \
   gfits_free_table  (&table); \
@@ -331,5 +331,5 @@
 
   off_t Nbytes;
-  int i, j, k, N, Nextend, Ny, Binary, vecType, padIfShort;
+  int i, j, N, Nextend, Ny, Binary, vecType, padIfShort;
   char type[16], ID[80], *CCDKeyword;
   FTable table;
@@ -374,7 +374,7 @@
   // }
 
-  if (argc < 2) ESCAPE ("USAGE: read -fits extension [-extnum] [-keyword key] name name ...");
-
-  if (f == NULL) ESCAPE ("file not found");
+  if (argc < 2) ESCAPE ("USAGE: read -fits extension [-extnum] [-keyword key] name name ...\n");
+
+  if (f == NULL) ESCAPE ("file not found\n");
   fseeko (f, 0LL, SEEK_SET);
   table.header = &header;
@@ -384,5 +384,5 @@
     // first extension is PHU, cannot be a table. 
     // Nextend counts from 0 for first extension
-    if (!gfits_load_header (f, &header)) ESCAPE ("error reading primary header for file");
+    if (!gfits_load_header (f, &header)) ESCAPE ("error reading primary header for file\n");
     Nbytes = gfits_data_size (&header);
     fseeko (f, Nbytes, SEEK_CUR);
@@ -390,5 +390,5 @@
 
     for (i = 0; i < Nextend; i++) {
-      if (!gfits_load_header (f, &header)) ESCAPE ("extension not found");
+      if (!gfits_load_header (f, &header)) ESCAPE ("extension %d not found\n", i);
       Nbytes = gfits_data_size (&header);
       /* skip the prior data buffers */
@@ -396,6 +396,6 @@
       gfits_free_header (&header);
     }
-    if (!gfits_load_header (f, &header)) ESCAPE ("error reading header for extension");
-    if (!gfits_fread_ftable_data (f, &table, padIfShort)) ESCAPE ("error reading table for extension");
+    if (!gfits_load_header (f, &header)) ESCAPE ("error reading header for extension %d\n", Nextend);
+    if (!gfits_fread_ftable_data (f, &table, padIfShort)) ESCAPE ("error reading table for extension %d\n", Nextend);
 
   } else {
@@ -428,5 +428,5 @@
 	continue;
       }
-      if (!gfits_fread_ftable_data (f, &table, padIfShort)) ESCAPE ("error reading table for extension");
+      if (!gfits_fread_ftable_data (f, &table, padIfShort)) ESCAPE ("error reading table for extension\n");
       break;
     }
@@ -437,5 +437,5 @@
   gfits_scan (&header, "XTENSION", "%s", 1, type);
   if (strcmp (type, "BINTABLE") && strcmp (type, "TABLE")) {
-    ESCAPE ("specified extension is not a table\n");
+    ESCAPE ("specified extension %s is not a table\n", type);
   }
   Binary = !strcmp (type, "BINTABLE");
@@ -497,44 +497,6 @@
       }
 
-      if (!strcmp (type, "short")) {
-	short *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[k][0].elements.Int[j] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "int")) {
-	int *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[k][0].elements.Int[j] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "int64_t")) {
-	int64_t *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[k][0].elements.Int[j] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "float")) {
-	float *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[k][0].elements.Flt[j] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "double")) {
-	double *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[k][0].elements.Flt[j] = *Ptr;
-	  }
-	}
-      }
+      if (!VectorAssignData (vec, type, data, Ny, Nval)) ESCAPE ("bad column type %s", type);
+
     } else {
       // define the multifield vector names (Ny vectors x Nval elements)
@@ -549,52 +511,5 @@
       }
 
-      if (!strcmp (type, "char")) {
-	char *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[j][0].elements.Int[k] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "short")) {
-	short *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[j][0].elements.Int[k] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "int")) {
-	int *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[j][0].elements.Int[k] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "int64_t")) {
-	int64_t *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[j][0].elements.Int[k] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "float")) {
-	float *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[j][0].elements.Flt[k] = *Ptr;
-	  }
-	}
-      }
-      if (!strcmp (type, "double")) {
-	double *Ptr = data;
-	for (j = 0; j < Ny; j++) {
-	  for (k = 0; k < Nval; k++, Ptr++) {
-	    vec[j][0].elements.Flt[k] = *Ptr;
-	  }
-	}
-      }
+      if (!VectorAssignDataTranspose (vec, type, data, Ny, Nval)) ESCAPE ("bad column type %s", type);
     }
     free (data);
Index: /branches/eam_branches/ipp-20140610/Ohana/src/opihi/include/dvomath.h
===================================================================
--- /branches/eam_branches/ipp-20140610/Ohana/src/opihi/include/dvomath.h	(revision 36998)
+++ /branches/eam_branches/ipp-20140610/Ohana/src/opihi/include/dvomath.h	(revision 36999)
@@ -170,4 +170,7 @@
 Vector      **ReadVectorTableFITS   PROTO((char *filename, char *extname, int *Nvec));
 
+int           VectorAssignData          PROTO((Vector **vec, char *type, void *data, int Nrows, int Nval));
+int           VectorAssignDataTranspose PROTO((Vector **vec, char *type, void *data, int Nrows, int Nval));
+
 /* buffer handling */
 Buffer       *InitBuffer            PROTO((void));
Index: /branches/eam_branches/ipp-20140610/Ohana/src/opihi/lib.shell/VectorIO.c
===================================================================
--- /branches/eam_branches/ipp-20140610/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 36998)
+++ /branches/eam_branches/ipp-20140610/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 36999)
@@ -134,5 +134,5 @@
   FTable ftable;
 
-  int i, j, k;
+  int i, j;
   FILE *f = NULL;
 
@@ -202,20 +202,9 @@
     assert (status);
 
-# define ASSIGN_DATA(TYPE,OPTYPE) \
-    /* assign the data to the actual vector */ \
-    if (!strcmp (type, #TYPE)) { \
-      TYPE *Ptr = data;	    \
-      for (k = 0; k < Nrows; k++) { \
-	for (j = 0; j < Nval; j++, Ptr++) { \
-	  vec[Nvec + j][0].elements.OPTYPE[k] = *Ptr; \
-	} } }
-
-    // assign the data to the actual vector
-    ASSIGN_DATA(char,    Int);
-    ASSIGN_DATA(short,   Int);
-    ASSIGN_DATA(int,     Int);
-    ASSIGN_DATA(int64_t, Int);
-    ASSIGN_DATA(float,   Flt);
-    ASSIGN_DATA(double,  Flt);
+    if (!VectorAssignData(&vec[Nvec], type, data, Nrows, Nval)) {
+      // free unneeded things
+      gprint (GP_ERR, "trouble parsing data block type %s\n", type);
+      return (NULL);
+    }
 
     free (data);
@@ -241,2 +230,52 @@
 //  return (FALSE);
 }
+
+# define ASSIGN_DATA(TYPE,DTYPE,OPTYPE)	       \
+    /* assign the data to the actual vector */ \
+    if (!strcmp (type, #TYPE)) { \
+      DTYPE *Ptr = data;		    \
+      for (k = 0; k < Nrows; k++) { \
+	for (j = 0; j < Nval; j++, Ptr++) { \
+	  vec[j][0].elements.OPTYPE[k] = *Ptr; \
+	  } } return TRUE; }
+
+int VectorAssignData (Vector **vec, char *type, void *data, int Nrows, int Nval) {
+
+  int j, k;
+
+  // assign the data to the actual vector
+  ASSIGN_DATA(byte,    char,    Int);
+  ASSIGN_DATA(char,    char,    Int);
+  ASSIGN_DATA(short,   short,   Int);
+  ASSIGN_DATA(int,     int,     Int);
+  ASSIGN_DATA(int64_t, int64_t, Int);
+  ASSIGN_DATA(float,   float,   Flt);
+  ASSIGN_DATA(double,  double,  Flt);
+
+  return FALSE;
+}
+
+# define ASSIGN_DATA_TRANSPOSE(TYPE,DTYPE,OPTYPE)	\
+    /* assign the data to the actual vector */ \
+    if (!strcmp (type, #TYPE)) { \
+      DTYPE *Ptr = data;		    \
+      for (k = 0; k < Nrows; k++) { \
+	for (j = 0; j < Nval; j++, Ptr++) { \
+	  vec[k][0].elements.OPTYPE[j] = *Ptr; \
+	  } } return TRUE; }
+
+int VectorAssignDataTranspose (Vector **vec, char *type, void *data, int Nrows, int Nval) {
+
+  int j, k;
+
+  // assign the data to the actual vector
+  ASSIGN_DATA_TRANSPOSE(byte,    char,    Int);
+  ASSIGN_DATA_TRANSPOSE(char,    char,    Int);
+  ASSIGN_DATA_TRANSPOSE(short,   short,   Int);
+  ASSIGN_DATA_TRANSPOSE(int,     int,     Int);
+  ASSIGN_DATA_TRANSPOSE(int64_t, int64_t, Int);
+  ASSIGN_DATA_TRANSPOSE(float,   float,   Flt);
+  ASSIGN_DATA_TRANSPOSE(double,  double,  Flt);
+
+  return FALSE;
+}
