Skip to content

io.fits.Column dim keyword fails for 2D column of strings #5279

Closed

Description

@sbailey

This might be user error, but I think the dim keyword for astropy.io.fits.Column doesn't work properly for the case of 2D column of strings. Testing under python 2.7.11 with astropy 1.2.1:

It is possible to write a numpy structured array that contains a 2D column of strings to a fits file:

from astropy.io import fits
import numpy as np

dtype = [
    ('x', (str, 5)),        #- 1D column of 5-character strings
    ('y', (str, 3), (4,)),  #- 2D column; each row is four 3-char strings
]
data = np.zeros(2, dtype=dtype)
data['x'] = ['abcde', 'xyz']
data['y'][0] = ['A', 'BC', 'DEF', '123']
data['y'][1] = ['X', 'YZ', 'PQR', '999']

fits.writeto('blat.fits', data, clobber=True)
dx, hdr = fits.getdata('blat.fits', header=True)

hdr =

XTENSION= 'BINTABLE'           / binary table extension                         
BITPIX  =                    8 / array data type                                
NAXIS   =                    2 / number of array dimensions                     
NAXIS1  =                   17 / length of dimension 1                          
NAXIS2  =                    2 / length of dimension 2                          
PCOUNT  =                    0 / number of group parameters                     
GCOUNT  =                    1 / number of groups                               
TFIELDS =                    2 / number of table fields                         
TTYPE1  = 'x       '                                                            
TFORM1  = '5A      '                                                            
TTYPE2  = 'y       '                                                            
TFORM2  = '12A     '                                                            
TDIM2   = '(3,4)   '                                                            

Trying to create the 2D column by hand using the dim keyword fails, however:

col1 = fits.Column(name='x', format='5A', array=data['x'])
col2 = fits.Column(name='y', format='12A', array=data['y'], dim=(3,4))

Traceback:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-0d4ea33cdccc> in <module>()
      1 col1 = fits.Column(name='x', format='5A', array=data['x'])
----> 2 col2 = fits.Column(name='y', format='12A', array=data['y'], dim=(3,4))

/Users/sbailey/anaconda/lib/python2.7/site-packages/astropy/io/fits/column.pyc in __init__(self, name, format, unit, null, bscale, bzero, disp, start, dim, array, ascii)
    589                                          'format `%s`.' % format)
    590 
--> 591         array = self._convert_to_valid_data_type(array)
    592 
    593         # We have required (through documentation) that arrays passed in to

/Users/sbailey/anaconda/lib/python2.7/site-packages/astropy/io/fits/column.pyc in _convert_to_valid_data_type(self, array)
   1084                 shape = dims[:-1] if 'A' in format else dims
   1085                 shape = (len(array),) + shape
-> 1086                 array = array.reshape(shape)
   1087 
   1088             if 'P' in format or 'Q' in format:

ValueError: total size of new array must be unchanged

It is quite possible that I'm misunderstanding how to specify the format and dim keywords, but I would have expected them to match desired TFORMn and TDIMn keywords of the output fits file.

Activity

  1. pllim commented on Aug 30, 2016

    @pllim
    Member

    I think you have to explicitly create the Column objects first before constructing the FITS table. I am able to get something working like this:

    >>> col1 = fits.Column(name='x', format='5A', array=data['x'])
    >>> col2 = fits.Column(name='y', format='12A', array=data['y'], dim='(3,4)')
    >>> cols = fits.ColDefs([col1, col2])
    >>> tbhdu = fits.BinTableHDU.from_columns(cols)
    >>> tbhdu.writeto('blat.fits', clobber=True)
    >>> 
    >>> from astropy.table import Table
    >>> tab = Table.read('blat.fits', format='fits')
    >>> tab
    <Table length=2>
      x    y [4]  
     str5   str3  
    ----- --------
    abcde A .. 123
      xyz X .. 999

    If this solves your problem, please close the issue. Thanks.

  2. sbailey commented on Aug 30, 2016

    @sbailey
    ContributorAuthor

    User error! the dim option needs to be a str (as the documentation says...) instead of a tuple as I was providing. Thanks for the quick reply. Closing issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions