2014-02-07 7 views
2

Мне нужно сделать контурный график и наложить контуры на изображение. Я использовал aplpy-библиотеку, чтобы наложить контуры на астрономический образ. Я скачал данные 2MASS в сайте APlpy (https://github.com/aplpy/aplpy-examples/tree/master/data) и написал следующий фрагмент кода:Как преобразовать контурный график (matplotlib) в формат FITS с заголовком?

import numpy as np 
import aplpy 
import atpy 
from pyavm import AVM 
import scipy 
import matplotlib.pyplot as plt 
import scipy.ndimage 
from matplotlib import cm 
import montage_wrapper 
import matplotlib.colors as colors 
from scipy import stats 

def get_contour_verts(cn): 
    contours = [] 
    # for each contour line 
    for cc in cn.collections: 
     paths = [] 
     # for each separate section of the contour line 
     for pp in cc.get_paths(): 
      xy = [] 
      # for each segment of that section 
      for vv in pp.iter_segments(): 
       xy.append(vv[0]) 
      paths.append(np.vstack(xy)) 
     contours.append(paths) 
    return contours 

# Convert all images to common projection 
aplpy.make_rgb_cube(['2MASS_h.fits', '2MASS_j.fits', '2MASS_k.fits'], '2MASS_rgb.fits') 

# Customize it 
aplpy.make_rgb_image('2MASS_rgb.fits','2MASS_rgb_contour.png',embed_avm_tags=True) 

# Launch APLpy figure of 2D cube 
img = aplpy.FITSFigure('2MASS_rgb_contour.png') 
img.show_rgb() 

# Modify the tick labels for precision and format 
img.tick_labels.set_xformat('hhmm') 
img.tick_labels.set_yformat('ddmm') 
# Move the tick labels 
img.tick_labels.set_xposition('top') 
img.tick_labels.set_yposition('right') 
img.tick_labels.set_font(size='small', family='sans-serif', style='normal') 

data = scipy.loadtxt('sources.txt') 
m1=data[:,0] 
m2=data[:,1] 
xmin = m1.min() 
xmax = m1.max() 
ymin = m2.min() 
ymax = m2.max() 
#Gridding the data 

X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j] 
positions = np.vstack([X.ravel(), Y.ravel()]) 
values = np.vstack([m1, m2]) 
kernel = stats.gaussian_kde(values) 
Z = np.reshape(kernel(positions).T, X.shape) 
fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.imshow(np.rot90(Z), cmap=plt.cm.gist_earth_r, extent=[xmin, xmax, ymin, ymax]) 
ax.plot(m1, m2, 'k.', markersize=2) 
ax.set_xlim([xmin, xmax]) 
ax.set_ylim([ymin, ymax]) 

CS = plt.contour(X, Y, Z) 
Contour_arrays=get_contour_verts(CS) 

#Adding contour plots 
for contours_at_level in Contour_arrays: 
    radec = [img.pixel2world(*verts.T) for verts in contours_at_level] 
    new_radec=[] 
    for coor in radec: 
     #new_radec.append(np.column_stack((coor[0], coor[1]))) 
     new_radec.append(np.vstack((coor[0], coor[1]))) 
    print new_radec 
    img.show_lines(new_radec,color='red', zorder=100) 

img.save('tutorial.png') 

Кажется, он все еще не работает.

+0

О создании контурных участков с matplotlib у вас есть много примеров вокруг StackOverflow. Теперь, если вы хотите сохранить сюжет как файл FITS, вам нужно сначала преобразовать график в массив numpy (например, следуя описанному процессу [здесь] (http://www.icare.univ-lille1.fr/ wiki/index.php/How_to_convert_a_matplotlib_figure_to_a_numpy_array_or_a_PIL_image)), а затем используйте PyFITS для создания файла FITS с массивом. –

+0

@ RicardoCárdenes Как я могу передать информацию из координат прямого восхождения и склонения, когда я конвертирую контур matplotlib в массив? – Dalek

+0

@Dalek - измените свою петлю в соответствии с моим измененным. Я сделал ошибку; созданные вами контуры * уже * в координатах ra/dec, поэтому вам не нужно преобразовывать пиксель-> мир. Обратите внимание, что связанный пример (github.com/aplpy/aplpy-examples/pull/1) имеет правильную версию – keflavich

ответ

2

Вы не можете «сохранить контуры как файл FITS» напрямую, но есть и другие подходы, которые вы можете попробовать.

Вы можете использовать инструмент matplotlib._cntr, как описано здесь: Python: find contour lines from matplotlib.pyplot.contour(), чтобы получить конечные точки в координатах фигуры, а затем использовать WCS для преобразования координат между пикселями и мирами. aplpy.FITSFigure s имеет удобные функции, F.world2pixel и F.pixel2world, каждый из которых принимают 2 массив:

F.pixel2world(arange(5),arange(5)) 

Так что, если вы работаете с сеткой, которая идентичной к показанному в FITSFigure окна, вы можете конвертировать ваши очки для Мировые координаты и сюжет их с show_lines:

ra,dec = F.pixel2world(xpix,ypix) 
F.show_lines([[ra,dec]]) 

или для более реалистичного контура случае, в настоящее время копирования кода из связанной статьи:

import numpy as np 
import aplpy 

def get_contour_verts(cn): 
    contours = [] 
    # for each contour line 
    for cc in cn.collections: 
     paths = [] 
     # for each separate section of the contour line 
     for pp in cc.get_paths(): 
      xy = [] 
      # for each segment of that section 
      for vv in pp.iter_segments(): 
       xy.append(vv[0]) 
      paths.append(np.vstack(xy)) 
     contours.append(paths) 

    return contours 

# This line is copied from the question's code, and assumes that has been run previously 
CS = plt.contour(Xgrid, Ygrid, Hsmooth,levels=loglvl,extent=extent,norm=LogNorm()) 

contours = get_contour_verts(CS) # use the linked code 


gc = aplpy.FITSFigure('2MASS.fits',figsize=(10,9)) 

# each level comes with a different set of vertices, so you have to loop over them 
for contours_at_level in Contour_arrays: 
    clines = [cl.T for cl in contours_at_level] 
    img.show_lines(clines,color='red', zorder=100) 

Тем не менее, самый простой подход - если у вас есть файл FITS, из которого вы создаете указанные контуры, просто используйте этот файл напрямую. Или если у вас нет файла FITS, вы можете сделать его с помощью pyfits, создав свой собственный заголовок.

+0

, не могли бы вы подробнее рассказать о том, как я могу использовать WCS (это от астрологии), чтобы преобразовать данные с сеткой в ​​контур Участвовать в WCS? – Dalek

+0

Dalek: подробный ответ добавлен – keflavich

+0

все еще очень расплывчато для меня, как я должен его реализовать. если я использую c = cntr.Cntr (Xgrid, Ygrid, Hsmooth), то c.get_cdata() дает мне массив (nx, ny), но это количество каждой точки сетки, а с другой стороны c.trace (z) список точек в контуре, находящихся в ra и dec координатах. Какой из них нужно преобразовать в файл fits, и не могли бы вы объяснить немного больше, которое можно прочитать show_contour() в aplpy.FITSFigure()? Спасибо – Dalek

 Смежные вопросы

  • Нет связанных вопросов^_^