встроить небольшую карту (картопия) в рисунок matplotlib - PullRequest
1 голос
/ 27 марта 2019
# imports
from collections import namedtuple
import numpy as np
import xarray as xr
import shapely
import cartopy

Данные, которые у меня есть, выглядят так.

У меня есть область интересов (определяется здесь как all_region). У меня есть xr.DataArray, который содержит мою переменную. Что я хочу сделать, это выбрать один ПИКСЕЛ (широта, долгая пара) и построить небольшую карту в углу линейного графика, показывающую, что пиксель расположен.

Region = namedtuple('Region',field_names=['region_name','lonmin','lonmax','latmin','latmax'])
all_region = Region(
    region_name="all_region",
    lonmin = 32.6,
    lonmax = 51.8,
    latmin = -5.0,
    latmax = 15.2,
)

data = np.random.normal(0,1,(12, 414, 395))
lats = np.linspace(-4.909738, 15.155708, 414)
lons = np.linspace(32.605801, 51.794488, 395)
months = np.arange(1,13)
da = xr.DataArray(data, coords=[months, lats, lons], dims=['month','lat','lon'])

Это функции, которые мне нужно исправить, чтобы работать с осями врезки.

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

def plot_location(region):
    """ use cartopy to plot the region (defined as a namedtuple object)
    """
    lonmin,lonmax,latmin,latmax = region.lonmin,region.lonmax,region.latmin,region.latmax
    fig = plt.figure()
    ax = fig.gca(projection=cartopy.crs.PlateCarree())
    ax.add_feature(cartopy.feature.COASTLINE)
    ax.add_feature(cartopy.feature.BORDERS, linestyle=':')
    ax.set_extent([lonmin, lonmax, latmin, latmax])

    return fig, ax


def select_pixel(ds, loc):
    """ (lat,lon) """
    return ds.sel(lat=loc[1],lon=loc[0],method='nearest')


def turn_tuple_to_point(loc):
    """ (lat,lon) """
    from shapely.geometry.point import Point
    point = Point(loc[1], loc[0])
    return point


def add_point_location_to_map(point, ax, color=(0,0,0,1), **kwargs):
    """ """
    ax.scatter(point.x,
           point.y,
           transform=cartopy.crs.PlateCarree(),
           c=[color],
           **kwargs)
    return

Здесь я делаю сюжет

# choose a lat lon location that want to plot
loc = (2.407,38.1)

# 1. plot the TIME SERIES FOR THE POINT
fig,ax = plt.subplots()
pixel_da = select_pixel(da, loc)
pixel_da.plot.line(ax=ax, marker='o')

# 2. plot the LOCATION for the point
fig,ax = plot_location(all_region)
point = turn_tuple_to_point(loc)
add_point_location_to_map(point, ax)

Plot 1

Plot 2

У меня есть функция для построения региона, но я хочу поместить это на ось в углу моей фигуры! Как это:

Ideal output

Как бы я поступил так? Я взглянул на метод inset_locator , но, насколько я могу судить, mpl_toolkits.axes_grid1.parasite_axes.AxesHostAxes не имеет средств для назначения проекции, которая требуется для картопии.

from mpl_toolkits.axes_grid1.inset_locator import inset_axes

proj=cartopy.crs.PlateCarree
axins = inset_axes(ax, width="20%", height="20%", loc=2, projection=proj)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-162-9b5fd4f34c3e> in <module>
----> 1 axins = inset_axes(ax, width="20%", height="20%", loc=2, projection=proj)

TypeError: inset_axes() got an unexpected keyword argument 'projection'

Ответы [ 2 ]

3 голосов
/ 28 марта 2019

mpl_toolkits.axes_grid1.inset_locator.inset_axes не имеет ключевого слова projection.Он предоставляет только аргумент axes_class.Теперь может возникнуть соблазн предоставить cartopy.mpl.geoaxes.GeoAxes непосредственно этому аргументу, но при этом будет отсутствовать фактическая проекция в использовании.Кроме того, необходимо установить проекцию с помощью аргумента axes_kwargs.

inset_axes(...,  axes_class=cartopy.mpl.geoaxes.GeoAxes, 
                 axes_kwargs=dict(map_projection=cartopy.crs.PlateCarree()))

Полный пример:

import cartopy
import cartopy.mpl.geoaxes
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes


fig, ax = plt.subplots()
ax.plot([4,5,3,1,2])


axins = inset_axes(ax, width="40%", height="40%", loc="upper right", 
                   axes_class=cartopy.mpl.geoaxes.GeoAxes, 
                   axes_kwargs=dict(map_projection=cartopy.crs.PlateCarree()))
axins.add_feature(cartopy.feature.COASTLINE)


plt.show()

enter image description here

1 голос
/ 28 марта 2019

У меня не установлено cartopy для непосредственного тестирования, но я считаю, что вы можете обойти эту проблему, создавая свои встроенные оси вручную, , используя fig.add_axes().Если вы хотите указать его положение относительно главных осей, вы можете легко рассчитать параметр rect, используя информацию, возвращаемую основными осями get_position().

Например:

pad = 0.05
w = 0.4
h = 0.25

fig, ax = plt.subplots()
a = ax.get_position()
ax2 = fig.add_axes([a.x1-(w+pad)*a.width,a.y1-(h+pad)*a.height,w*a.width,h*a.height], projection="hammer")

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...