Правильное размещение цветной панели относительно геоосевых (картографических)

Используя Cartopy, я хотел бы иметь полный контроль над тем, куда идет цветной план. Обычно я делаю это, получая текущую позицию осей в качестве основы, а затем создаю новые оси для цветной панели. Это хорошо работает для стандартных осей matplotlib, но не при использовании Cartopy и geo_axes, поскольку это искажает оси.

Итак, мой вопрос: как мне получить точную позицию моего geo_axes?

Вот пример кода, основанный на документах 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() 

Результирующая фигура при использовании «set_aspect»: введите описание изображения здесь

Результирующая фигура при отключении «set_aspect»: введите описание изображения здесь

В принципе, я бы хотел получить первую цифру (правильно размещенную строку цвета), но без использования «set_aspect». Я думаю, это должно быть возможно с некоторыми преобразованиями, но пока я не нашел решения.

Благодаря!

One Solution collect form web for “Правильное размещение цветной панели относительно геоосевых (картографических)”

Отличный вопрос! Благодарим за код и фотографии, что значительно облегчает понимание проблемы, а также упрощает быстрое повторение возможных решений.

Проблема здесь в основном является matplotlib. Cartopy вызывает ax.set_aspect('equal') поскольку это часть декартовых единиц определения проекции.

Функция равномерного соотношения сторон Matplotlib изменяет размеры осей в соответствии с ограничениями x и y, вместо того, чтобы изменять пределы, подходящие к прямоугольнику осей. Именно по этой причине оси не заполняют пространство, выделенное ему на рисунке. Если вы интерактивно измените размер фигуры, вы увидите, что количество пространства, которое занимают оси, варьируется в зависимости от аспекта, по которому вы изменяете размер фигуры.

Самый простой способ определения местоположения осей – это ax.get_position() который вы уже использовали. Однако, как мы теперь знаем, эта «позиция» изменяется с размером фигуры. Таким образом, одним из решений является перерасчет положения цветной панели каждый раз при изменении размера фигуры.

Механизм событий matplotlib имеет «resize_event», который запускается каждый раз при изменении размера фигуры. Если мы используем этот механизм для вашего colorbar, наше событие может выглядеть примерно так:

 def resize_colobar(event): # Tell matplotlib to re-draw everything, so that we can get # the correct location from get_position. plt.draw() posn = ax.get_position() colorbar_ax.set_position([posn.x0 + posn.width + 0.01, posn.y0, 0.04, axpos.height]) fig.canvas.mpl_connect('resize_event', resize_colobar) 

Поэтому, если мы свяжем это обратно с картографией и вашим первоначальным вопросом, теперь можно изменить размер цветовой панели на основе положения геооси. Полный код для этого может выглядеть так:

 import cartopy.crs as ccrs import matplotlib.pyplot as plt import os from netCDF4 import Dataset as netcdf_dataset from cartopy import config 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'][:] fig, ax = plt.subplots(1, 1, figsize=(10,5), subplot_kw={'projection': ccrs.PlateCarree()}) # Add the colorbar axes anywhere in the figure. Its position will be # re-calculated at each figure resize. cbar_ax = fig.add_axes([0, 0, 0.1, 0.1]) fig.subplots_adjust(hspace=0, wspace=0, top=0.925, left=0.1) sst_contour = ax.contourf(lons, lats, sst, 60, transform=ccrs.PlateCarree()) def resize_colobar(event): plt.draw() posn = ax.get_position() cbar_ax.set_position([posn.x0 + posn.width + 0.01, posn.y0, 0.04, posn.height]) fig.canvas.mpl_connect('resize_event', resize_colobar) ax.coastlines() plt.colorbar(sst_contour, cax=cbar_ax) ax.gridlines() ax.set_extent([-20, 60, 33, 63]) plt.show() 
  • проблемы в "pandas datetime convert to num"
  • Преобразование двумерной фигуры в цилиндр в Python
  • Как добавить вторую ось x в нижней части первой в matplotlib.?
  • Создание тепловой карты путем выборки и балансировки из трехмерного массива
  • Плотность плотности распределения по образцу с помощью matplotlib
  • Определение средней точки цветовой карты в matplotlib
  • Как вычеркнуть изображение плотины matplotlib за пределами границ прямоугольника
  • Использование индекса данных данных Pandas в качестве значений для оси x в графике matplotlib
  • Python - лучший язык программирования в мире.