FITS_rec и выбор данных: маскировка вместо «истинной» фильтрации? - PullRequest
0 голосов
/ 01 октября 2018

Вероятно, дубликат сообщения Эшли (но я не могу комментировать -yet;)).

У меня возникла та же проблема при попытке добавить столбец в подвыбор / выборку моего начального FITS_rec (на основе numpy ' recarray);все строки появляются снова (И заполнение этого нового столбца, кажется, не соблюдается ...).« hdu_sliced._get_raw_data () », предложенное Власом Соколовым, - это решение, которое очень хорошо работает для меня, но мне было интересно:

1) Какие «лучшие способы» предложеныIguananaut?Мне, конечно, нужен кто-то, чтобы просто гуглить это для меня;новичок меня чувствует себя застрявшим: $ (Требуется пребывание в FITS_rec ).

2) Это ожидаемое поведение?То есть мы действительно хотим работать с «замаскированным массивом», который будет копией нашего исходного массива?Больше всего меня беспокоит «коллапс» значений в новом вычисляемом столбце.См. Ниже:

# A nice FITS_rec
a1 = np.array(['NGC1001', 'NGC1002', 'NGC1003'])
a2 = np.array([11.1, 12.3, 15.2])
col1 = fits.Column(name='target', format='20A', array=a1)
col2 = fits.Column(name='V_mag', format='E', array=a2)

cols = fits.ColDefs([col1, col2])
hdu = fits.BinTableHDU.from_columns(cols)

ori_rec=hdu.data

ori_rec
`

FITS_rec ([('NGC1001', 11.1), ('NGC1002', 12.3), ('NGC1003', 15.2)], dtype = (numpy.record,[('target', 'S20'), ('V_mag', '

# Sub-selection
bug=ori_rec[ori_rec["V_mag"]>12.]
bug

FITS_rec ([(' NGC1002 ', 12.3), (' NGC1003 ', 15.2)], dtype= (numpy.record, [('target', 'S20'), ('V_mag', '

Пока все хорошо ...

# Let's add a new column
col0=bug.columns
col1 =fits.ColDefs([fits.Column(name='new',format='D',array=bug.field("V_mag")+1.)])
newbug = fits.BinTableHDU.from_columns(col0 + col1).data

FITS_rec ([('NGC1001', 11.1, 13.30000019), ('NGC1002, 12.3, 16.20000076), (' NGC1003 ', 15.2, 0.)], dtype = (numpy.record, [(' target ',' S20 '), ('V_mag', '

... AND ... значения нового столбца для NGC1002 и NGC1003 являются правильными, но в строке NGC1001 и NGC1002 соответственно ...: |

Любое просветление будет приветствоваться:)

1 Ответ

0 голосов
/ 02 октября 2018

Это запутанная проблема, и она проистекает из того факта, что в 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 никогда не работали во многих простых случаях.

Я надеюсь, что этот ответ был назидательным - я знаю, что он может быть немного длинным и запутанным.Если есть что-то конкретное, что я могу выяснить, дайте мне знать.

...