def read_columns(self, columns, **keys):
if self._info['<STR_LIT>'] == ASCII_TBL:<EOL><INDENT>keys['<STR_LIT>'] = columns<EOL>return self.read(**keys)<EOL><DEDENT>rows = keys.get('<STR_LIT>', None)<EOL>colnums = self._extract_colnums(columns)<EOL>if isinstance(colnums, int):<EOL><INDENT>return self.read_column(columns, **keys)<EOL><DEDENT>rows = self._extract_rows(rows)<EOL>dtype, offsets, isvar = self.get_rec_dtype(colnums=colnums, **keys)<EOL>w, = numpy.where(isvar == True)  <EOL>if w.size > <NUM_LIT:0>:<EOL><INDENT>vstorage = keys.get('<STR_LIT>', self._vstorage)<EOL>array = self._read_rec_with_var(<EOL>colnums, rows, dtype, offsets, isvar, vstorage)<EOL><DEDENT>else:<EOL><INDENT>if rows is None:<EOL><INDENT>nrows = self._info['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>nrows = rows.size<EOL><DEDENT>array = numpy.zeros(nrows, dtype=dtype)<EOL>colnumsp = colnums[:].copy()<EOL>colnumsp[:] += <NUM_LIT:1><EOL>self._FITS.read_columns_as_rec(self._ext+<NUM_LIT:1>, colnumsp, array, rows)<EOL>array = self._maybe_decode_fits_ascii_strings_to_unicode_py3(array)<EOL>for i in xrange(colnums.size):<EOL><INDENT>colnum = int(colnums[i])<EOL>name = array.dtype.names[i]<EOL>self._rescale_and_convert_field_inplace(<EOL>array,<EOL>name,<EOL>self._info['<STR_LIT>'][colnum]['<STR_LIT>'],<EOL>self._info['<STR_LIT>'][colnum]['<STR_LIT>'])<EOL><DEDENT><DEDENT>if (self._check_tbit(colnums=colnums)):<EOL><INDENT>array = self._fix_tbit_dtype(array, colnums)<EOL><DEDENT>lower = keys.get('<STR_LIT>', False)<EOL>upper = keys.get('<STR_LIT>', False)<EOL>if self.lower or lower:<EOL><INDENT>_names_to_lower_if_recarray(array)<EOL><DEDENT>elif self.upper or upper:<EOL><INDENT>_names_to_upper_if_recarray(array)<EOL><DEDENT>self._maybe_trim_strings(array, **keys)<EOL>return array<EOL>
read a subset of columns from this binary table HDU

By default, all rows are read.  Send rows= to select subsets of the
data.  Table data are read into a recarray for multiple columns,
plain array for a single column.

parameters
----------
columns: list/array
    An optional set of columns to read from table HDUs.  Can be string
    or number. If a sequence, a recarray is always returned.  If a
    scalar, an ordinary array is returned.
rows: list/array, optional
    An optional list of rows to read from table HDUS.  Default is to
    read all.
vstorage: string, optional
    Over-ride the default method to store variable length columns.  Can
    be 'fixed' or 'object'.  See docs on fitsio.FITS for details.
lower: bool, optional
    If True, force all columns names to lower case in output. Will over
    ride the lower= keyword from construction.
upper: bool, optional
    If True, force all columns names to upper case in output. Will over
    ride the lower= keyword from construction.