Любопытное (плохое?) Поведение, создающее проекции всего неба с помощью matplotlib

1

Я пытаюсь сделать график плотности "все-небо", полный в RA (т.е. от 0 до 360 градусов), но неполный в DEC (скажем, от -45 до 90 градусов). Если я рисую это без какой-либо проекции, это нормально, но когда я пытаюсь построить с использованием проекции "mollweide", я не восстанавливаю входные данные, но если я немного изменю код, я восстановил ожидаемое поведение (однако, я не имеют последовательного объяснения этого изменения, как вы увидите в примере).

Давайте посмотрим на самодостаточный пример с более ясными выходами:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.backends.backend_agg
from math import pi

#array between 0 and 360 deg
RA = np.random.random(10000)*360
#array between -45 and 90 degrees. By construction!
DEC= np.random.random(10000)*135-45

fig = plt.Figure((10, 4.5))
ax = fig.add_subplot(111,projection='mollweide')
ax.grid(True)
ax.set_xlabel('RA')
ax.set_ylabel('DEC')

ax.set_xticklabels(np.arange(30,331,30))
hist,xedges,yedges = np.histogram2d(DEC,RA,bins=[90,180],range=[[-90,90],[0,360]])
#TO RECOVER THE EXPECTED BEHAVIOUR, I HAVE TO CHANGE -90 FOR -80 IN THE PREVIOUS LINE:
#hist,xedges,yedges = np.histogram2d(DEC,RA,bins=[90,180],range=[[-80,90],[0,360]])
#I DO NOT WHY!

extent = (-pi,pi,-pi/2.,pi/2.)
image = ax.imshow(hist,extent=extent,clip_on=False,aspect=0.5,origin='lower')

cb = fig.colorbar(image, orientation='horizontal')
canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig)

fig.canvas.print_figure("image1.png")

И выходное изображение: [Поскольку я новичок здесь, мне не разрешено размещать изображения, поэтому я опубликую ссылку, если она не работает, напишите мне электронное письмо, и я могу поделиться папкой Dropbox с изображениями;) ]

Выходное изображение, которое я получаю

Там, где вы можете ясно видеть, что RA в порядке, поэтому он находится в диапазоне от 0 до 360, НО DEC варьируется от -35 до 90 вместо -45 до 90. До сих пор я не понимаю, почему мне не хватает 10 град.

Однако, если я немного изменил код, заменив строку

гист, xedges, yedges = np.histogram2d (DEC, RA, бит = [90, 180], диапазон = [[ -90, 90], [0,360]]

для

гист, xedges, yedges = np.histogram2d (DEC, RA, бит = [90, 180], диапазон = [[ -80, 90], [0,360]]

Я получаю то, что, я думаю, должен получить, вот этот сюжет:

Выходное изображение 2

[Опять же, если ссылка не работает, сообщите мне, и я могу поделиться с вами папкой Dropbox]

где DEC теперь колеблется от -45 до 90, как ожидалось, потому что я создал DEC таким образом.

Однако изменение -90 для -80 не имеет смысла (я думаю). Так что, вероятно, я делаю что-то не так, что я не могу заметить сейчас, или я неправильно понимаю что-то в коде или есть любопытная ошибка в matplotlib??

Пожалуйста, любая помощь/подсказка/исправление будут очень признательны

Эдуардо

  • 0
    По сути, matplotlib не проецирует изображения. Это давняя ошибка / ограничение. Для быстрого и грязного решения используйте pcolormesh вместо imshow . Вы можете вручную перепроектировать его и отобразить с помощью imshow, но в большинстве случаев это более болезненно, чем стоит.
  • 0
    Спасибо @Joe за твой ответ. Я, наконец, решил проблему (я думаю) благодаря вашему ответу и ответу Мэтта Дэвиса в списке рассылки по астропии. На этот раз я использовал pcolormesh вместо imshow и получил следующее изображение: Image Единственная «проблема» в том, что теперь я не могу показать «сетку» (ax.grid (True) не работает), поэтому, если кто-то знает, как добавить сетка, пожалуйста, дайте мне знать;) (хотя это всего лишь деталь) Если это полезно для кого-то еще, вот «исправленная версия» моего кода (который приводит изображение выше).
Теги:
matplotlib
plot

2 ответа

2
Лучший ответ

Если это полезно для кого-то другого, это "исправленная версия" моего кода, которая дает в качестве вывода это изображение. Основное изменение заключается в использовании pcolormesh вместо imshow (как предлагалось @Joe):

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.backends.backend_agg

#array between 0 and 360 deg
#CAVEAT: it seems that is needed an array from -180 to 180, so is just a
#shift in the coordinates
RA = np.random.random(10000)*360-180
#array between -45 and 90 degrees
DEC= np.random.random(10000)*135-45

fig = plt.Figure((10, 5))
ax = fig.add_subplot(111,projection='mollweide')

ax.set_xlabel('RA')
ax.set_ylabel('DEC')
ax.set_xticklabels(np.arange(30,331,30))

hist,xedges,yedges = np.histogram2d(DEC,RA,bins=[60,40],range=[[-90,90],[-180,180]])

X,Y = np.meshgrid(np.radians(yedges),np.radians(xedges))

image = ax.pcolormesh(X,Y,hist)
ax.grid(True)
cb = fig.colorbar(image, orientation='horizontal')
canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig)
fig.canvas.print_figure("image4.png")
2

если вы не возражаете в зависимости от внешнего пакета, вы можете сделать это с помощью healpy, который обеспечивает проекцию Mollweide для пикселизации неба Healpix:

https://github.com/healpy/healpy

См. Пример, похожий на ваш скрипт:

https://gist.github.com/1215159

Узнать больше о healpix:

http://healpix.jpl.nasa.gov/html/intro.htm

Ouput image: Изображение 174551

Ещё вопросы

Сообщество Overcoder
Наверх
Меню