web-dev-qa-db-fra.com

Comment modifier la projection de sous-tracé matplotlib d'un axe existant?

J'essaie de construire une fonction simple qui prend une instance de sous-intrigue (matplotlib.axes._subplots.AxesSubplot) Et transforme sa projection en une autre projection, par exemple, en l'une des projections cartopy.crs.CRS.

L'idée ressemble à ceci

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)

Bien sûr, je peux simplement utiliser la fonction fig.add_subplot():

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()

mais je me demandais s'il y avait une méthode matplotlib appropriée pour changer une projection d'axe de sous-intrigue après elle a été définie. La lecture de l'API matplotlib n'a malheureusement pas aidé.

26
Denis Sergeev

Vous ne pouvez pas modifier la projection d'un axe existant, la raison est donnée ci-dessous. Cependant, la solution à votre problème sous-jacent consiste simplement à utiliser l'argument subplot_kw Pour plt.subplots() décrit dans la documentation de matplotlib ici . Par exemple, si vous vouliez que toutes vos sous-parcelles aient la projection cartopy.crs.PlateCarree Que vous pourriez faire

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()})

Concernant la question réelle, spécifier une projection lorsque vous créez un ensemble d'axes détermine la classe d'axes que vous obtenez, qui est différente pour chaque type de projection. Par exemple

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))

Ce code imprimera ce qui suit

<class 'matplotlib.axes._subplots.AxesSubplot'>
<class 'matplotlib.axes._subplots.PolarAxesSubplot'>
<class 'cartopy.mpl.geoaxes.GeoAxesSubplot'>

Remarquez comment chaque axe est en fait une instance d'une classe différente.

32
ajdawson

suite à la réponse à cette question:

En python, comment puis-je hériter et remplacer une méthode sur une instance de classe, en affectant cette nouvelle version au même nom que l'ancienne?

J'ai trouvé un hack pour changer la projection d'une hache après l'avoir créée, ce qui semble fonctionner au moins dans l'exemple simple ci-dessous, mais je ne sais pas si cette solution est la meilleure façon

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()
0
user2660966