Korzystając z kartonu, chciałbym mieć pełną kontrolę nad tym, gdzie znajduje się mój pasek kolorów. Zwykle robię to, ustawiając aktualną pozycję osi, a następnie tworzę nowe osie dla paska kolorów. Działa to dobrze w standardowych osiach matplotlib, ale nie w przypadku użycia Cartopy i geo_axes, ponieważ spowoduje to zniekształcenie osi.Prawidłowe umiejscowienie paska kolorów względem osi geograficznych (koszyk)
Moje pytanie brzmi: jak uzyskać dokładną pozycję moich geo_ax?
Oto przykład kodu na podstawie Dokumenty Cartopy http://scitools.org.uk/cartopy/docs/latest/matplotlib/advanced_plotting.html:
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()
wynikową, przy użyciu "set_aspect":
wynikową gdy pominięcie "set_aspect":
Zasadniczo chciałbym uzyskać pierwszą figurę (poprawnie umieszczony pasek kolorów), ale bez użycia "set_aspect". Myślę, że powinno to być możliwe z pewnymi transformacjami, ale nie znalazłem dotychczas rozwiązania.
Dzięki!
Świetna odpowiedź! Nigdy nie znalazłbym tego rozwiązania na własną rękę! – user3497890
Może krótkie pytanie boczne, jeśli mogę: Czy możliwe jest umieszczenie definicji resize_colorbar gdzie indziej i przekazanie ax i cbar_ax jako argumentów (aby ta funkcja stała się wielokrotnego użytku)? – user3497890
Aktualizacja: podczas gdy plt.show() dostarcza poprawnego wyniku, plt.savefig ('sst.png') nie ma (kolor paska pozostaje w pierwotnej pozycji przy [0,0,0.1,0.1]). Próbowałem zmienić backend na matplotlib.use ('Agg'), ale to nie pomaga. Jakiś pomysł, jak mogę go uruchomić z savefig? – user3497890