def field(self, key): """ A view of a `Column`'s data as an array. """ indx = _get_index(self.names, key) recformat = self._coldefs._recformats[indx] # If field's base is a FITS_rec, we can run into trouble because it # contains a reference to the ._coldefs object of the original data; # this can lead to a circular reference; see ticket #49 base = self while isinstance(base, FITS_rec) and \ isinstance(base.base, np.recarray): base = base.base # base could still be a FITS_rec in some cases, so take care to # use rec.recarray.field to avoid a potential infinite # recursion field = np.recarray.field(base, indx) if self._convert[indx] is None: # for X format if isinstance(recformat, _FormatX): _nx = recformat._nx dummy = np.zeros(self.shape + (_nx,), dtype=np.bool_) _unwrapx(field, dummy, _nx) self._convert[indx] = dummy return self._convert[indx] (_str, _bool, _number, _scale, _zero, bscale, bzero, dim) = \ self._get_scale_factors(indx) # for P format buff = None if isinstance(recformat, _FormatP): dummy = _VLF([None] * len(self), dtype=recformat.dtype) for i in range(len(self)): _offset = field[i, 1] + self._heapoffset if self._file is not None: self._file.seek(_offset) def get_pdata(dtype, count): return _array_from_file(self._file, dtype=dtype, count=count, sep='') else: # There must be a _buffer or something is wrong # Sometimes the buffer is already a Numpy array; in # particular this can occur in compressed HDUs. # Hypothetically other cases as well. if buff is None: buff = self._buffer if not isinstance(buff, np.ndarray): # Go ahead and great a single ndarray from the # buffer if it is not already one; we will then # take slices from it. This is more efficient than # the previous approach that created separate # arrays for each VLA. buff = np.fromstring(buff, dtype=np.uint8) def get_pdata(dtype, count): dtype = np.dtype(dtype) nbytes = count * dtype.itemsize slc = slice(_offset, _offset + nbytes) return buff[slc].view(dtype=dtype) if recformat.dtype == 'a': count = field[i, 0] dt = recformat.dtype + str(1) da = get_pdata(dt, count) dummy[i] = np.char.array(da, itemsize=count) dummy[i] = decode_ascii(dummy[i]) else: count = field[i, 0] dt = recformat.dtype dummy[i] = get_pdata(dt, count) dummy[i].dtype = dummy[i].dtype.newbyteorder('>') # scale by TSCAL and TZERO if _scale or _zero: for i in range(len(self)): dummy[i][:] = dummy[i] * bscale + bzero # Boolean (logical) column if recformat.dtype == FITS2NUMPY['L']: for i in range(len(self)): dummy[i] = np.equal(dummy[i], ord('T')) self._convert[indx] = dummy return self._convert[indx] # ASCII table, convert strings to numbers if not _str and self._coldefs._tbtype == 'TableHDU': _fmap = {'I': np.int32, 'F': np.float32, 'E': np.float32, 'D': np.float64} _type = _fmap[self._coldefs.formats[indx][0]] # if the string = TNULL, return ASCIITNULL nullval = self._coldefs.nulls[indx].strip().encode('ascii') dummy = field.replace('D'.encode('ascii'), 'E'.encode('ascii')) dummy = np.where(dummy.strip() == nullval, str(ASCIITNULL), dummy) dummy = np.array(dummy, dtype=_type) self._convert[indx] = dummy else: dummy = field # Test that the dimensions given in dim are sensible; otherwise # display a warning and ignore them if dim: # See if the dimensions already match, if not, make sure the # number items will fit in the specified dimensions if dummy.ndim > 1: actual_shape = dummy[0].shape if _str: actual_shape = (dummy[0].itemsize,) + actual_shape else: actual_shape = len(dummy[0]) if dim == actual_shape: # The array already has the correct dimensions, so we # ignore dim and don't convert dim = None else: nitems = reduce(operator.mul, dim) if _str: actual_nitems = dummy.itemsize else: actual_nitems = dummy.shape[1] if nitems != actual_nitems: warnings.warn( 'TDIM%d value %s does not fit with the size of ' 'the array items (%d). TDIM%d will be ignored.' % (indx + 1, self._coldefs.dims[indx], actual_nitems, indx + 1)) dim = None # further conversion for both ASCII and binary tables if _number and (_scale or _zero): # only do the scaling the first time and store it in _convert self._convert[indx] = np.array(dummy, dtype=np.float64) if _scale: np.multiply(self._convert[indx], bscale, self._convert[indx]) if _zero: self._convert[indx] += bzero elif _bool: self._convert[indx] = np.equal(dummy, ord('T')) elif _str: try: self._convert[indx] = decode_ascii(dummy) except UnicodeDecodeError: pass if dim: if self._convert[indx] is None: self._convert[indx] = dummy if _str: fmt = self._convert[indx].dtype.char dtype = ('|%s%d' % (fmt, dim[-1]), dim[:-1]) self._convert[indx].dtype = dtype else: self._convert[indx].shape = (dummy.shape[0],) + dim if self._convert[indx] is not None: return self._convert[indx] else: return dummy