2016-11-26 14 views
3

Рассмотрим следующий код (скачать test.fits):Координаты не сохраняются после кадрирования припадки файл

from astropy.io import fits 
from photutils.utils import cutout_footprint 

# Read fits file. 
hdulist = fits.open('test.fits') 
hdu_data = hdulist[0].data 
hdulist.close() 

# Some center and box to crop 
xc, yc, xbox, ybox = 267., 280., 50., 100. 
# Crop image. 
hdu_crop = cutout_footprint(hdu_data, (xc, yc), (ybox, xbox))[0] 
# Add comment to header 
prihdr = hdulist[0].header 
prihdr['COMMENT'] = "= Cropped fits file") 
# Write cropped frame to new fits file. 
fits.writeto('crop.fits', hdu_crop, prihdr) 

Оригинал (слева) и обрезано (справа) изображения выглядят следующим образом:

enter image description here

(ra, dec) equatorial coordinates для звезды в центре кадра:

Original frame: 12:10:32 +39:24:17 
Cropped frame: 12:12:07 +39:06:50 

Почему координаты разные в обрезанной кадре?


Это два способа решить эту проблему, используя два разных метода.

from astropy.io import fits 
from photutils.utils import cutout_footprint 
from astropy.wcs import WCS 
from astropy.nddata.utils import Cutout2D 
import datetime 

# Read fits file. 
hdulist = fits.open('test.fits') 
hdu = hdulist[0].data 
# Header 
hdr = hdulist[0].header 
hdulist.close() 

# Some center and box to crop 
xc, yc, xbox, ybox = 267., 280., 50., 100. 

# First method using cutout_footprint 
# Crop image. 
hdu_crop = cutout_footprint(hdu, (xc, yc), (ybox, xbox))[0] 
# Read original WCS 
wcs = WCS(hdr) 
# Cropped WCS 
wcs_cropped = wcs[yc - ybox // 2:yc + ybox // 2, xc - xbox // 2:xc + xbox // 2] 
# Update WCS in header 
hdr.update(wcs_cropped.to_header()) 
# Add comment to header 
hdr['COMMENT'] = "= Cropped fits file ({}).".format(datetime.date.today()) 
# Write cropped frame to new fits file. 
fits.writeto('crop.fits', hdu_crop, hdr) 

# Second method using Cutout2D 
# Crop image 
hdu_crop = Cutout2D(hdu, (xc, yc), (xbox, ybox), wcs=WCS(hdr)) 
# Cropped WCS 
wcs_cropped = hdu_crop.wcs 
# Update WCS in header 
hdr.update(wcs_cropped.to_header()) 
# Add comment to header 
hdr['COMMENT'] = "= Cropped fits file ({}).".format(datetime.date.today()) 
# Write cropped frame to new fits file. 
fits.writeto('crop.fits', hdu_crop.data, hdr) 
+1

Габриэль - Ах, хорошо, спасибо за давая мне знать. Когда я нажимаю тег photutils, я получаю: «В теге photutils нет руководства по использованию, можете ли вы помочь нам его создать?» и когда я нажимаю «детали», информация сбивает с толку, я не вижу, что вы предложили. Я не являюсь сильным пользователем, если вы и знаете, где сообщить об этом, пожалуйста. Это похоже на то, что они могут улучшить в своем процессе или новые предложенные теги. – Christoph

+0

Описание тега, которое я дал, ожидает экспертной оценки. Я предположил, что вы это видите. Можете ли вы задать вопрос по этому вопросу в Meta? http://meta.stackoverflow.com/ – Gabriel

+0

@Gabriel Вместо того, чтобы редактировать решение в своем вопросе, отправьте ответ, содержащий ваше решение (например, Cutout2D), и снова удалите часть решения из вопроса. Вы даже можете принять это как ответ! – MSeifert

ответ

3

photutils.utils.cutout_footprint только вырезает пиксели, он не обновляет WCS, который используется для преобразования координат между пикселями и мирами.

Используйте вместо этого astropy.nddata.utils.Cutout2D.

+0

Я попытался использовать 'Cutout2D' (' cutout = Cutout2D (hdu_data, (xc, yc), (xbox, ybox))), но он возвращает объект, который вызывает объект KeyError: ', когда я пытаюсь сэкономить it: 'fits.writeto ('crop.fits', cutout, prihdr)'. Я попытался преобразовать его, используя 'hdu_crop = fits.PrimaryHDU (cutout.data)', но он по-прежнему приводит к той же ошибке. – Gabriel

+0

Прочитайте docstring 'Cutout2D'. В нем говорится, что вам нужно передать wcs отдельно, то есть 'from astropy.wcs import WCS; cutout = Cutout2D (data = hdu.data, wcs = WCS (hdu.header) '. Затем посмотрите на выходной объект' cutout'. Согласно документам, он должен иметь новый атрибут 'data' и' wcs' для вашего вы можете снова превратить wcs в заголовок и сделать HDU из данных и заголовков, если вам это нужно. Это помогает? Я сейчас в сети, но могу опубликовать рабочий код завтра, если нет. На самом деле должно быть пример с WCS в документах 'Cutout2D', кто-то должен отправить запрос на перенос. – Christoph

+0

В тестах есть два примера использования Cutout2D с wcs: https://github.com/astropy/astropy/blob/master/astropy/nddata/ tests/test_utils.py # L441 Обязательно должно быть в документах, но теперь может быть полезно для вас. – Christoph

2

Координаты изменены, потому что вы нарезали изображение, но не изменили информацию WCS (особенно значения опорных пикселей).

Один из способов будут использовать astropy.WCS:

from astropy.wcs import WCS 
wcs = WCS(hdulist[0].header) 
wcs_cropped = wcs[280-50 : 280+50 , 267-25 : 267+25] 

, а затем скопировать эти обновленные туалеты в ваш заголовок:

prihdr.update(wcs_cropped.to_header()) 

перед сохранением файла.

Я не уверен, что такое cutout_footprint, возможно, вам нужно изменить индексы среза при создании wcs_cropped.

Существует функциональность удобства в astropy.nddata с именем Cutout2D, которая по умолчанию обновляет WCS.

+0

Это приближает коорды к исходным значениям, но все еще выключено: '12:10:37 +39: 25: 13'. Вы пробовали это решение? Он работает так, как ожидалось для вас? Также запускается предупреждение: «ПРЕДУПРЕЖДЕНИЕ: FITSFixedWarning: RADECSYS =« FK5 »/ WORLD COORDINATE FRAME ключевое слово RADECSYS устарело, используйте RADESYSa. [astropy.wcs.wcs] ВНИМАНИЕ: FITSFixedWarning: 'datfix' произвел изменение 'Изменено '13/03/95' до '1995-03-13' '. [astropy.wcs.wcs] ' – Gabriel

+0

Я думаю, причина в том, что photutils использует соглашение (x, y) при использовании' cutout_footprint'. Можете ли вы попробовать использовать '[280-50: 280 + 50, 267-25: 267 + 25]' при разрезании WCS? – MSeifert

+0

Да, вот и все. Класс 'Cutout2D' также выглядит интересным, я проверю его. Спасибо, MSeifert! – Gabriel

1

Другой ответ, потому что он требует дополнительного пакета: ccdproc особенно класс CCDData, который основан на astropy.nddata.NDData:

Это упрощает чтение файла:

from ccdproc import CCDData 
ccd = CCDData.read(filename, unit='erg/cm**2/s/AA') 

Агрегат должен быть указан, так как блок заголовка не совместим с модулем astropy.units.

Важно о CCDData является то, что вы (в основном) не нужно заботиться о units, wcsheader, и masks сами, они сохраняются как атрибуты и самые основные операции сохранения (и обновление) их соответственно.Например, нарезка:

xc, yc, xbox, ybox = 267., 280., 50., 100. 
ccd_cropped = ccd[int(yc - ybox // 2) : int(yc + ybox // 2), 
        int(xc - xbox // 2) : int(xc + xbox // 2)] 

Это нарезанный ccd_cropped уже обновил информацию WCS, так что вы можете просто продолжать его обработку (например, сохранить его еще раз):

ccd_cropped.write('cropped.fits') 

И он должен иметь правильно обновленные координаты. Отрезая часть на самом деле можно также с помощью astropy.nddata.NDDataRef, только read и write часть реализуются явно в ccdproc.CCDData