Это запутанная проблема, и она проистекает из того факта, что в astropy.io.fits
есть много уровней унаследованных классов и структур данных (вытекающих из более ранних версий PyFITS).Например, вы можете видеть в своем примере, что hdu.data
- это объект FITS_rec
, который похож на массив данных Numpy (сам по себе устаревший класс с мягким устареванием), но он также имеет атрибут .columns
(так как выПримечание):
>>> bug.columns
ColDefs(
name = 'target'; format = '20A'
name = 'V_mag'; format = 'E'
)
Это, в свою очередь, фактически содержит ссылки на исходные массивы, из которых вы описали столбцы.Например:
>>> bug.columns['target'].array
chararray(['NGC1001', 'NGC1002', 'NGC1003'],
dtype='|S20')
Здесь вы можете видеть, что, хотя bug
является «срезом» вашей исходной таблицы, массивы, на которые ссылается bug.columns
, все еще содержат исходные данные не нарезанного массива.Поэтому, когда вы делаете что-то похожее на исходное сообщение
>>> col0 = bug.columns
>>> col1 = fits.ColDefs([fits.Column(name='new',format='D',array=bug.field("V_mag")+1.)])
, он делает все возможное, чтобы выяснить намерение, но col0
здесь не имеет ни малейшего представления, что bug
является частью оригинальной таблицы., он имеет только оригинальные "coldefs" с полными столбцами, на которые можно положиться.
Большинство этих классов, включая FITS_rec
, Column
и особенно ColDefs
почти , никогда должны быть использованы напрямую больше.К сожалению, не вся документация была обновлена, чтобы отразить этот факт, и есть много более старых руководств и примеров кода, которые показывают использование этих классов.Никто с необходимыми знаниями не смог найти время, чтобы обновить документы и уточнить этот момент.
Иногда Column
полезно, если у вас уже есть столбчатые данные с каждым столбцом в отдельном массиве, и выхочу построить таблицу из нее и дать некоторые специфические атрибуты FITS столбцам таблицы.Но я переработал большую часть API, чтобы вы могли брать собственные структуры данных Python, такие как массивы Numpy, и сохранять их в файлах FITS, не беспокоясь о деталях реализации FITS или раздражая такие вещи, как коды формата данных FITSво многих случаях.
Эта работа немного не завершена, потому что кажется, что если вы хотите определить таблицу FITS из некоторых столбчатых массивов, вам все равно нужно использовать класс Column
и указать как минимум формат FITS(но вам никогда не нужно использовать ColDefs
напрямую):
>>> hdu = fits.BinTableHDU.from_columns([fits.Column(name='target', format='20A', array=a1), fits.Column(name='V_mag', format='E', array=a2)])
>>> hdu.data
FITS_rec([('NGC1001', 11.1), ('NGC1002', 12.3), ('NGC1003', 15.2)],
dtype=(numpy.record, [('target', 'S20'), ('V_mag', '<f4')]))
Тем не менее, вы также можете напрямую работать со структурированными массивами Numpy, и я обычно нахожу это проще лично, так как это позволяет вам игнорировать большинство FITSи просто сосредоточиться на ваших данных, для тех случаев, когда не важно точно настроить FITS-специфические вещи.Например, чтобы определить структурированный массив для ваших данных, есть несколько способов сделать это, но вы можете попробовать:
>>> nrows = 3
>>> data = np.empty(nrows, dtype=[('target', 'S20'), ('V_mag', np.float32)])
>>> data['target'] = a1
>>> data['V_mag'] = a2
>>> data
array([('NGC1001', 11.100000381469727), ('NGC1002', 12.300000190734863),
('NGC1003', 15.199999809265137)],
dtype=[('target', 'S20'), ('V_mag', '<f4')])
и затем вы можете создать экземпляр BinTableHDU
непосредственно из этого массива:
>>> hdu = fits.BinTableHDU(data)
>>> hdu.data
FITS_rec([('NGC1001', 11.1), ('NGC1002', 12.3), ('NGC1003', 15.2)],
dtype=(numpy.record, [('target', 'S20'), ('V_mag', '<f4')]))
>>> hdu.header
XTENSION= 'BINTABLE' / binary table extension
BITPIX = 8 / array data type
NAXIS = 2 / number of array dimensions
NAXIS1 = 24 / length of dimension 1
NAXIS2 = 3 / length of dimension 2
PCOUNT = 0 / number of group parameters
GCOUNT = 1 / number of groups
TFIELDS = 2 / number of table fields
TTYPE1 = 'target '
TFORM1 = '20A '
TTYPE2 = 'V_mag '
TFORM2 = 'E '
Точно так же, когда речь идет о таких вещах, как маскирование, нарезка и добавление новых столбцов, лучше всего работать напрямую с собственными структурами данных Numpy.
Или, как предлагается в ответах на другой вопрос , используйте API Astropy Table
и вообще не связывайтесь с вещами низкого уровня FITS, если вы можете помочь.Потому что, как я уже говорил, он содержит несколько уровней унаследованных интерфейсов, которые запутывают вещи (и этот долгосрочный период, вероятно, следует очистить, но это трудно сделать, потому что код, использующий их тем или иным способом, распространен ).API таблиц был спроектирован с нуля, чтобы сделать манипуляции с таблицами, включая маскировку строк и добавление столбцов, относительно простой.Принимая во внимание, что старые API PyFITS никогда не работали во многих простых случаях.
Я надеюсь, что этот ответ был назидательным - я знаю, что он может быть немного длинным и запутанным.Если есть что-то конкретное, что я могу выяснить, дайте мне знать.