docs: def read(filename, ext=None, extver=None, **keys):
      """
      Convenience function to read data from the specified FITS HDU
  
      By default, all data are read.  For tables, send columns= and rows= to
      select subsets of the data.  Table data are read into a recarray; use a
      FITS object and read_column() to get a single column as an ordinary array.
      For images, create a FITS object and use slice notation to read subsets.
  
      Under the hood, a FITS object is constructed and data are read using
      an associated FITSHDU object.
  
      parameters
      ----------
      filename: string
          A filename.
      ext: number or string, optional
          The extension.  Either the numerical extension from zero
          or a string extension name. If not sent, data is read from
          the first HDU that has data.
      extver: integer, optional
          FITS allows multiple extensions to have the same name (extname).  These
          extensions can optionally specify an EXTVER version number in the
          header.  Send extver= to select a particular version.  If extver is not
          sent, the first one will be selected.  If ext is an integer, the extver
          is ignored.
      columns: list or array, optional
          An optional set of columns to read from table HDUs.  Default is to
          read all.  Can be string or number.
      rows: optional
          An optional list of rows to read from table HDUS.  Default is to
          read all.
      header: bool, optional
          If True, read the FITS header and return a tuple (data,header)
          Default is False.
      case_sensitive: bool, optional
          Match column names and extension names with case-sensitivity.  Default
          is False.
      lower: bool, optional
          If True, force all columns names to lower case in output
      upper: bool, optional
          If True, force all columns names to upper case in output
      vstorage: string, optional
          Set the default method to store variable length columns.  Can be
          'fixed' or 'object'.  See docs on fitsio.FITS for details.
      """
  
      with FITS(filename, **keys) as fits:
  
          header = keys.pop('header', False)
  
          if ext is None:
              for i in xrange(len(fits)):
                  if fits[i].has_data():
                      ext = i
                      break
              if ext is None:
                  raise IOError("No extensions have data")
  
          item = _make_item(ext, extver=extver)
  
          data = fits[item].read(**keys)
          if header:
              h = fits[item].read_header()
              return data, h
          else:
              return data