tiempo real matrices graficos graficas graficar grafica encimar crear como barras python matplotlib astronomy polar-coordinates

real - matplotlib python



Produzca una gráfica de coordenadas ecuatoriales entre RA y DEC con python (2)

Intento generar una gráfica de coordenadas ecuatoriales que se parezca más o menos a esta:

(La figura está tomada de este artículo y muestra la posición de los MC grandes y pequeños en coordenadas ecuatoriales)

Cosas importantes que debe tener en cuenta sobre esta trama:

  • El eje theta (es decir: la ascensión recta) está en h: m: s (horas, minutos, segundos) como está acostumbrado en astronomía, en lugar de grados, como lo hace la opción polar predeterminada en matplotlib .
  • El eje r (es decir, la declinación) aumenta hacia afuera desde -90º y la cuadrícula se centra en (0h, -90º).
  • La trama está recortada , lo que significa que solo una parte de ella se muestra en oposición a todo el círculo (como matplotlib hace de manera predeterminada).

Utilizando la opción polar=True en matplotlib , el gráfico más cercano que he logrado producir es el siguiente ( MWE , archivo de datos aquí ; algunos puntos no están presentes en comparación con la imagen anterior, ya que el archivo de datos es un poco más pequeño):

También necesito agregar una tercera columna de datos a la trama, por lo que agrego una barra de color y coloreo cada punto según una matriz z :

Entonces, lo que más necesito en este momento es una forma de recortar la trama. Basado principalmente en esta pregunta y este ejemplo, @cphlewis estuvo bastante cerca de su respuesta , pero aún faltan varias cosas (mencionadas en su respuesta).

Cualquier ayuda y / o sugerencias con este tema serán muy apreciadas.

MWE

(Note que uso gridspec para posicionar la subtrama porque necesito generar varios de estos en el mismo archivo de imagen de salida)

import numpy as np import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec def skip_comments(f): '''''' Read lines that DO NOT start with a # symbol. '''''' for line in f: if not line.strip().startswith(''#''): yield line def get_data_bb(): ''''''RA, DEC data file. '''''' # Path to data file. out_file = ''bb_cat.dat'' # Read data file with open(out_file) as f: ra, dec = [], [] for line in skip_comments(f): ra.append(float(line.split()[0])) dec.append(float(line.split()[1])) return ra, dec # Read RA, DEC data from file. ra, dec = get_data_bb() # Convert RA from decimal degrees to radians. ra = [x / 180.0 * 3.141593 for x in ra] # Make plot. fig = plt.figure(figsize=(20, 20)) gs = gridspec.GridSpec(4, 2) # Position plot in figure using gridspec. ax = plt.subplot(gs[0], polar=True) ax.set_ylim(-90, -55) # Set x,y ticks angs = np.array([330., 345., 0., 15., 30., 45., 60., 75., 90., 105., 120.]) plt.xticks(angs * np.pi / 180., fontsize=8) plt.yticks(np.arange(-80, -59, 10), fontsize=8) ax.set_rlabel_position(120) ax.set_xticklabels([''$22^h$'', ''$23^h$'', ''$0^h$'', ''$1^h$'', ''$2^h$'', ''$3^h$'', ''$4^h$'', ''$5^h$'', ''$6^h$'', ''$7^h$'', ''$8^h$''], fontsize=10) ax.set_yticklabels([''$-80^{/circ}$'', ''$-70^{/circ}$'', ''$-60^{/circ}$''], fontsize=10) # Plot points. ax.scatter(ra, dec, marker=''o'', c=''k'', s=1, lw=0.) # Use this block to generate colored points with a colorbar. #cm = plt.cm.get_cmap(''RdYlBu_r'') #z = np.random.random((len(ra), 1)) # RGB values #SC = ax.scatter(ra, dec, marker=''o'', c=z, s=10, lw=0., cmap=cm) # Colorbar #cbar = plt.colorbar(SC, shrink=1., pad=0.05) #cbar.ax.tick_params(labelsize=8) #cbar.set_label(''colorbar'', fontsize=8) # Output png file. fig.tight_layout() plt.savefig(ra_dec_plot.png'', dpi=300)


Masticar el ejemplo de AxisArtist es realmente bastante prometedor (esto combina dos ejemplos de AxisArtist; no me sorprendería si AxisArtist se escribiera con argumentos de RA en mente):

Aún por hacer:

  1. La declinación debe ejecutarse desde -90 en el origen hasta 0
  2. Ser capaz de usar y agregar una barra de colores
  3. ajuste los límites si traza fuera de ellos

estético:

  1. Fuente Serif en etiquetas de eje
  2. Líneas de grilla discontinuas para la ascensión

¿Algo más?

""" An experimental support for curvilinear grid. """ import numpy as np import mpl_toolkits.axisartist.angle_helper as angle_helper import matplotlib.cm as cmap from matplotlib.projections import PolarAxes from matplotlib.transforms import Affine2D from mpl_toolkits.axisartist import SubplotHost from mpl_toolkits.axisartist import GridHelperCurveLinear def curvelinear_test2(fig): """ polar projection, but in a rectangular box. """ global ax1 # see demo_curvelinear_grid.py for details tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() extreme_finder = angle_helper.ExtremeFinderCycle(10, 60, lon_cycle = 360, lat_cycle = None, lon_minmax = None, lat_minmax = (0, np.inf), ) grid_locator1 = angle_helper.LocatorHMS(12) #changes theta gridline count tick_formatter1 = angle_helper.FormatterHMS() grid_locator2 = angle_helper.LocatorDMS(6) tick_formatter2 = angle_helper.FormatterDMS() grid_helper = GridHelperCurveLinear(tr, extreme_finder=extreme_finder, grid_locator1=grid_locator1, tick_formatter1=tick_formatter1, grid_locator2=grid_locator2, tick_formatter2=tick_formatter2 ) ax1 = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper) # make ticklabels of right and top axis visible. ax1.axis["right"].major_ticklabels.set_visible(True) ax1.axis["top"].major_ticklabels.set_visible(True) ax1.axis["bottom"].major_ticklabels.set_visible(True) #Turn off? # let right and bottom axis show ticklabels for 1st coordinate (angle) ax1.axis["right"].get_helper().nth_coord_ticks=0 ax1.axis["bottom"].get_helper().nth_coord_ticks=0 fig.add_subplot(ax1) grid_helper = ax1.get_grid_helper() ax1.set_aspect(1.) ax1.set_xlim(-4,15) # moves the origin left-right in ax1 ax1.set_ylim(-3, 20) # moves the origin up-down ax1.set_ylabel(''90$^/circ$ + Declination'') ax1.set_xlabel(''Ascension'') ax1.grid(True) #ax1.grid(linestyle=''--'', which=''x'') # either keyword applies to both #ax1.grid(linestyle='':'', which=''y'') # sets of gridlines return tr import matplotlib.pyplot as plt fig = plt.figure(1, figsize=(5, 5)) fig.clf() tr = curvelinear_test2(fig) # tr.transform_point((x, 0)) is always (0,0) # => (theta, r) in but (r, theta) out... r_test = [0, 1.2, 2.8, 3.8, 5, 8, 10, 13.3, 17] # distance from origin deg_test = [0, -7, 12, 28, 45, 70, 79, 90, 100] # degrees ascension out_test = tr.transform(zip(deg_test, r_test)) sizes = [40, 30, 10, 30, 80, 33, 12, 48, 45] #hues = [.9, .3, .2, .8, .6, .1, .4, .5,.7] # Oddly, floats-to-colormap worked for a while. hues = np.random.random((9,3)) #RGB values ax1.scatter(out_test[:,0], #ax1 is a global out_test[:,1], s=sizes, c=hues, #cmap=cmap.RdYlBu_r, zorder=9) #on top of gridlines plt.show()


Obtener la barra de color se puede hacer fusionando el código OP con la excelente respuesta de @ cphlewis . Lo publiqué como una solución llave en mano a petición del OP en el chat . La primera versión del código simplemente agrega una barra de color, la versión final (en EDIT 2) hace una traducción afín de los ejes y corrige algunos parámetros / simplifica el código para adaptarse exactamente a la especificación OP.

""" An experimental support for curvilinear grid. """ import numpy as np import mpl_toolkits.axisartist.angle_helper as angle_helper import matplotlib.cm as cmap from matplotlib.projections import PolarAxes from matplotlib.transforms import Affine2D from mpl_toolkits.axisartist import SubplotHost from mpl_toolkits.axisartist import GridHelperCurveLinear def curvelinear_test2(fig): """ polar projection, but in a rectangular box. """ global ax1 # see demo_curvelinear_grid.py for details tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() extreme_finder = angle_helper.ExtremeFinderCycle(10, 60, lon_cycle = 360, lat_cycle = None, lon_minmax = None, lat_minmax = (0, np.inf), ) grid_locator1 = angle_helper.LocatorHMS(12) #changes theta gridline count tick_formatter1 = angle_helper.FormatterHMS() grid_locator2 = angle_helper.LocatorDMS(6) tick_formatter2 = angle_helper.FormatterDMS() grid_helper = GridHelperCurveLinear(tr, extreme_finder=extreme_finder, grid_locator1=grid_locator1, tick_formatter1=tick_formatter1, grid_locator2=grid_locator2, tick_formatter2=tick_formatter2 ) ax1 = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper) # make ticklabels of right and top axis visible. ax1.axis["right"].major_ticklabels.set_visible(True) ax1.axis["top"].major_ticklabels.set_visible(True) ax1.axis["bottom"].major_ticklabels.set_visible(True) #Turn off? # let right and bottom axis show ticklabels for 1st coordinate (angle) ax1.axis["right"].get_helper().nth_coord_ticks=0 ax1.axis["bottom"].get_helper().nth_coord_ticks=0 fig.add_subplot(ax1) grid_helper = ax1.get_grid_helper() ax1.set_aspect(1.) ax1.set_xlim(-4,15) # moves the origin left-right in ax1 ax1.set_ylim(-3, 20) # moves the origin up-down ax1.set_ylabel(''90$^/circ$ + Declination'') ax1.set_xlabel(''Ascension'') ax1.grid(True) #ax1.grid(linestyle=''--'', which=''x'') # either keyword applies to both #ax1.grid(linestyle='':'', which=''y'') # sets of gridlines return tr import matplotlib.pyplot as plt fig = plt.figure(1, figsize=(5, 5)) fig.clf() tr = curvelinear_test2(fig) # tr.transform_point((x, 0)) is always (0,0) # => (theta, r) in but (r, theta) out... r_test = [0, 1.2, 2.8, 3.8, 5, 8, 10, 13.3, 17] # distance from origin deg_test = [0, -7, 12, 28, 45, 70, 79, 90, 100] # degrees ascension out_test = tr.transform(zip(deg_test, r_test)) sizes = [40, 30, 10, 30, 80, 33, 12, 48, 45] #hues = [.9, .3, .2, .8, .6, .1, .4, .5,.7] # Oddly, floats-to-colormap worked for a while. hues = np.random.random((9,3)) #RGB values # Use this block to generate colored points with a colorbar. cm = plt.cm.get_cmap(''RdYlBu_r'') z = np.random.random((len(r_test), 1)) # RGB values SC = ax1.scatter(out_test[:,0], #ax1 is a global out_test[:,1], s=sizes, c=z, cmap=cm, zorder=9) #on top of gridlines # Colorbar cbar = plt.colorbar(SC, shrink=1., pad=0.05) cbar.ax.tick_params(labelsize=8) cbar.set_label(''colorbar'', fontsize=8) plt.show()

EDITAR

Un poco de parámetros de ordenamiento, agregar datos OP, eliminar la redundancia produce el siguiente gráfico. Todavía necesito centrar los datos en -90 en lugar de 0 - en el momento en que se hackea, pero estoy seguro de que curvelinear_test2() se puede cambiar para dar cuenta de ello ...

EDIT 2

Después del comentario de OP sobre la versión intermedia en esta respuesta, una versión final como la que se muestra a continuación da la trama al final de la publicación, con -90 en el eje de declinación y la demo de subplot.

""" An experimental support for curvilinear grid. """ import numpy as np import mpl_toolkits.axisartist.angle_helper as angle_helper import matplotlib.cm as cmap from matplotlib.projections import PolarAxes from matplotlib.transforms import Affine2D from mpl_toolkits.axisartist import SubplotHost from mpl_toolkits.axisartist import GridHelperCurveLinear def curvelinear_test2(fig, rect=111): """ polar projection, but in a rectangular box. """ # see demo_curvelinear_grid.py for details tr = Affine2D().translate(0,90) + Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() extreme_finder = angle_helper.ExtremeFinderCycle(10, 60, lon_cycle = 360, lat_cycle = None, lon_minmax = None, lat_minmax = (-90, np.inf), ) grid_locator1 = angle_helper.LocatorHMS(12) #changes theta gridline count tick_formatter1 = angle_helper.FormatterHMS() grid_helper = GridHelperCurveLinear(tr, extreme_finder=extreme_finder, grid_locator1=grid_locator1, tick_formatter1=tick_formatter1 ) ax1 = SubplotHost(fig, rect, grid_helper=grid_helper) # make ticklabels of right and top axis visible. ax1.axis["right"].major_ticklabels.set_visible(True) ax1.axis["top"].major_ticklabels.set_visible(True) ax1.axis["bottom"].major_ticklabels.set_visible(True) #Turn off? # let right and bottom axis show ticklabels for 1st coordinate (angle) ax1.axis["right"].get_helper().nth_coord_ticks=0 ax1.axis["bottom"].get_helper().nth_coord_ticks=0 fig.add_subplot(ax1) grid_helper = ax1.get_grid_helper() # You may or may not need these - they set the view window explicitly rather than using the # default as determined by matplotlib with extreme finder. ax1.set_aspect(1.) ax1.set_xlim(-4,25) # moves the origin left-right in ax1 ax1.set_ylim(-3, 30) # moves the origin up-down ax1.set_ylabel(''Declination'') ax1.set_xlabel(''Ascension'') ax1.grid(True) #ax1.grid(linestyle=''--'', which=''x'') # either keyword applies to both #ax1.grid(linestyle='':'', which=''y'') # sets of gridlines return ax1,tr def skip_comments(f): '''''' Read lines that DO NOT start with a # symbol. '''''' for line in f: if not line.strip().startswith(''#''): yield line def get_data_bb(): ''''''RA, DEC data file. '''''' # Path to data file. out_file = ''bb_cat.dat'' # Read data file with open(out_file) as f: ra, dec = [], [] for line in skip_comments(f): ra.append(float(line.split()[0])) dec.append(float(line.split()[1])) return ra, dec import matplotlib.pyplot as plt fig = plt.figure(1, figsize=(5, 5)) fig.clf() ax1, tr = curvelinear_test2(fig,121) # tr.transform_point((x, 0)) is always (0,0) # => (theta, r) in but (r, theta) out... # Read RA, DEC data from file. ra, dec = get_data_bb() out_test = tr.transform(zip(ra, dec)) # Use this block to generate colored points with a colorbar. cm = plt.cm.get_cmap(''RdYlBu_r'') z = np.random.random((len(ra), 1)) # RGB values SC = ax1.scatter(out_test[:,0], #ax1 is a global out_test[:,1], marker = ''o'', c=z, cmap=cm, lw = 0., zorder=9) #on top of gridlines # Colorbar cbar = plt.colorbar(SC, shrink=1., pad=0.1) cbar.ax.tick_params(labelsize=8) cbar.set_label(''colorbar'', fontsize=8) ax2, tr = curvelinear_test2(fig,122) # tr.transform_point((x, 0)) is always (0,0) # => (theta, r) in but (r, theta) out... # Read RA, DEC data from file. ra, dec = get_data_bb() out_test = tr.transform(zip(ra, dec)) # Use this block to generate colored points with a colorbar. cm = plt.cm.get_cmap(''RdYlBu_r'') z = np.random.random((len(ra), 1)) # RGB values SC = ax2.scatter(out_test[:,0], #ax1 is a global out_test[:,1], marker = ''o'', c=z, cmap=cm, lw = 0., zorder=9) #on top of gridlines # Colorbar cbar = plt.colorbar(SC, shrink=1., pad=0.1) cbar.ax.tick_params(labelsize=8) cbar.set_label(''colorbar'', fontsize=8) plt.show()

Parcela final: