denis sergeev
Estoy tratando de construir una función simple que tome una instancia de subtrama (matplotlib.axes._subplots.AxesSubplot
) y transforma su proyección a otra proyección, por ejemplo, a una de las cartopy.crs.CRS
proyecciones.
La idea se parece a esto
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
def make_ax_map(ax, projection=ccrs.PlateCarree()):
# set ax projection to the specified projection
...
# other fancy formatting
ax2.coastlines()
...
# Create a grid of plots
fig, (ax1, ax2) = plt.subplots(ncols=2)
# the first subplot remains unchanged
ax1.plot(np.random.rand(10))
# the second one gets another projection
make_ax_map(ax2)
Por supuesto, puedo usar fig.add_subplot()
función:
fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(121)
ax1.plot(np.random.rand(10))
ax2 = fig.add_subplot(122,projection=ccrs.PlateCarree())
ax2.coastlines()
pero me preguntaba si hay una adecuada matplotlib
método para cambiar la proyección de un eje de subtrama después fue definido. Desafortunadamente, leer la API de matplotlib no ayudó.
No puede cambiar la proyección de un eje existente, el motivo se indica a continuación. Sin embargo, la solución a su problema subyacente es simplemente usar el subplot_kw
argumento a plt.subplots()
descrito en la documentación de matplotlib aquí. Por ejemplo, si quisiera que todas sus subparcelas tuvieran el cartopy.crs.PlateCarree
proyección que podrías hacer
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
# Create a grid of plots
fig, (ax1, ax2) = plt.subplots(ncols=2, subplot_kw={'projection': ccrs.PlateCarree()})
Con respecto a la pregunta real, especificar una proyección cuando crea un conjunto de ejes determina la clase de ejes que obtiene, que es diferente para cada tipo de proyección. Por ejemplo
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
ax1 = plt.subplot(311)
ax2 = plt.subplot(312, projection='polar')
ax3 = plt.subplot(313, projection=ccrs.PlateCarree())
print(type(ax1))
print(type(ax2))
print(type(ax3))
Este código imprimirá lo siguiente
<class 'matplotlib.axes._subplots.AxesSubplot'>
<class 'matplotlib.axes._subplots.PolarAxesSubplot'>
<class 'cartopy.mpl.geoaxes.GeoAxesSubplot'>
Observe cómo cada eje es en realidad una instancia de una clase diferente.
-
¡Gracias! Y solo para confirmar, el
projection
La palabra clave determina la clase para todas las subparcelas a la vez, por lo que no hay forma de pasar varias proyecciones ensubplot_kw
? P.ejprojection='polar'
para la primera columna yprojection=ccrs.PlateCarree()
para la segunda columna de un conjunto de subtramas creado porplt.subplots(ncols=2)
?– Denis Serguéiev
6 de enero de 2016 a las 9:19
-
Las palabras clave en
subplot_kw
se pasan a cada eje, por lo que no creo que puedas hacer lo que describes. lossubplots
La función es un contenedor de conveniencia para atender el caso de uso básico, si necesita algo más, puede escribir su propia función de contenedor usandoadd_subplot
o similar.– ajdawson
7 de enero de 2016 a las 9:42
-
¿Hay alguna manera de hacer esto con ImageGrid? Sería bueno poder tener el control sobre el espaciado del mapa y la ubicación de la barra de colores que permite ImageGrid, pero no veo una forma de establecer la proyección de las subparcelas en la cuadrícula.
–Daniel Watkins
14 de noviembre de 2017 a las 0:33
-
Sí, es posible usando
axes_class
palabra clave enImageGrid
(oAxesGrid
). Hay un ejemplo en la galería de cartopy. También hubo un PR para cartopy (aunque no aceptado) que se puede usar para crear un personalizadoGeoAxesGrid
clase.– Denis Serguéiev
15 de noviembre de 2017 a las 21:08
dominar
Suponiendo que se utilizan varios ejes para el trazado 2D, como…
fig = matplotlib.pyplot.Figure()
axs = fig.subplots(3, 4) # prepare for multiple subplots
# (some plotting here)
axs[0,0].plot([1,2,3])
… uno puede simplemente destruir uno de ellos y reemplazarlo por uno nuevo que tenga la proyección 3D:
axs[2,3].remove()
ax = fig.add_subplot(3, 4, 12, projection='3d')
ax.plot_surface(...)
Solo tenga en cuenta que, a diferencia del resto de Python, el add_subplot
utiliza la indexación fila-columna comenzando de 1 (no desde 0).
EDITAR: Cambié mi error tipográfico sobre la indexación.
usuario2660966
siguiendo la respuesta a esta pregunta:
En Python, ¿cómo puedo heredar y anular un método en una instancia de clase, asignando esta nueva versión al mismo nombre que la anterior?
Encontré un truco para cambiar la proyección de un hacha después de crearlo que parece funcionar al menos en el ejemplo simple a continuación, pero no tengo idea si esta solución es la mejor manera
from matplotlib.axes import Axes
from matplotlib.projections import register_projection
class CustomAxe(Axes):
name="customaxe"
def plotko(self, x):
self.plot(x, 'ko')
self.set_title('CustomAxe')
register_projection(CustomAxe)
if __name__ == '__main__':
import matplotlib.pyplot as plt
fig = plt.figure()
## use this syntax to create a customaxe directly
# ax = fig.add_subplot(111, projection="customaxe")
## change the projection after creation
ax = plt.gca()
ax.__class__ = CustomAxe
ax.plotko(range(10))
plt.show()
-
no funciona….
– Alí
5 oct a las 17:28