Mit Cartopy möchte ich die volle Kontrolle darüber haben, wohin meine Farbleiste geht. Normalerweise mache ich das, indem ich die aktuelle Achsenposition als Basis erhalte und dann neue Achsen für die Farbleiste erstelle. Dies funktioniert gut für Standard-Matplotlib-Achsen, aber nicht bei Verwendung von Cartopy und Geo-Achsen, da dies die Achsen verzerrt.Korrekte Platzierung der Farbleiste relativ zu Geoachsen (Cartopy)
Also, meine Frage ist: Wie bekomme ich die genaue Position meiner Geo_axe?
Hier ist ein Code-Beispiel für die Dokumentation http://scitools.org.uk/cartopy/docs/latest/matplotlib/advanced_plotting.html Cartopy basiert:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import os
from netCDF4 import Dataset as netcdf_dataset
from cartopy import config
def main():
fname = os.path.join(config["repo_data_dir"],
'netcdf', 'HadISST1_SST_update.nc'
)
dataset = netcdf_dataset(fname)
sst = dataset.variables['sst'][0, :, :]
lats = dataset.variables['lat'][:]
lons = dataset.variables['lon'][:]
#my preferred way of creating plots (even if it is only one plot)
ef, ax = plt.subplots(1,1,figsize=(10,5),subplot_kw={'projection': ccrs.PlateCarree()})
ef.subplots_adjust(hspace=0,wspace=0,top=0.925,left=0.1)
#get size and extent of axes:
axpos = ax.get_position()
pos_x = axpos.x0+axpos.width + 0.01# + 0.25*axpos.width
pos_y = axpos.y0
cax_width = 0.04
cax_height = axpos.height
#create new axes where the colorbar should go.
#it should be next to the original axes and have the same height!
pos_cax = ef.add_axes([pos_x,pos_y,cax_width,cax_height])
im = ax.contourf(lons, lats, sst, 60, transform=ccrs.PlateCarree())
ax.coastlines()
plt.colorbar(im, cax=pos_cax)
ax.coastlines(resolution='110m')
ax.gridlines()
ax.set_extent([-20, 60, 33, 63])
#when using this line the positioning of the colorbar is correct,
#but the image gets distorted.
#when omitting this line, the positioning of the colorbar is wrong,
#but the image is well represented (not distorted).
ax.set_aspect('auto', adjustable=None)
plt.savefig('sst_aspect.png')
plt.close()
if __name__ == '__main__': main()
Bild ergibt, wenn "set_aspect" verwendet:
so erhaltene, als "set_aspect" Weglassen:
Grundsätzlich möchte ich die erste Figur (korrekt platzierte Farbleiste) erhalten, aber ohne den "set_aspect" zu verwenden. Ich denke, das sollte mit einigen Transformationen möglich sein, aber ich habe bisher keine Lösung gefunden.
Danke!
Große Antwort! Ich hätte diese Lösung nie alleine gefunden! – user3497890
Vielleicht eine kurze Nebenfrage, wenn ich darf: Ist es möglich, die Definition von resize_colorbar woanders zu setzen und ax und cbar_ax als Argumente zu übergeben (damit diese Funktion wiederverwendbar wird)? – user3497890
Update: Während plt.show() das korrekte Ergebnis liefert, bleibt plt.savefig ('sst.png') (Farbbalken bleibt bei [0,0,0,1,0,1] an der ursprünglichen Position). Versucht, das Backend zu matplotlib.use ('Agg') zu ändern, aber das hilft nicht. Irgendeine Idee, wie ich es mit Savegig zum Laufen bringen könnte? – user3497890