Контуры нерегулярных данных в полигоне

Мне нужно создать заполненные контурные графики данных о температуре поверхности моря (SST) в пределах многоугольника, однако я не уверен, что это лучший способ сделать это. У меня есть три одномерных массива, содержащих данные для X, Y и SST, которые я рисую, используя следующее для создания прикрепленного графика:

p=PatchCollection(mypatches,color='none', alpha=1.0,edgecolor="purple",linewidth=2.0)
levels=np.arange(SST.min(),SST.max(),0.2)
datamap=mymap.scatter(x,y,c=SST, s=55, vmin=-2,vmax=3,alpha=1.0)

Я хотел бы иметь возможность отображать эти данные в виде заполненных контуров (contourf вместо разброса), которые ограничены (обрезаны) границами полигона (фиолетовая линия). Предложения о том, как этого добиться, приветствуются.

введите здесь описание изображения

Обновление: сначала я попробовал griddata, но не смог заставить его работать должным образом. Однако, основываясь на ответе @eatHam, я решил попробовать еще раз. Я не мог заставить свои scipy griddata работать, так как они продолжали зависать в сетке при выборе метода «кубический», однако, когда я переключился на matplotlib.mlab.griddata и использовал «линейную» интерполяцию, это сработало. Предложение по маскировке границ дало очень грубое и не такое точное решение, как мне бы хотелось. Изображение, показывающее решение с использованием маскированного вырезания

Я искал варианты того, как обрезать контуры в matplotlib, и нашел ответ @pelson на этом ссылка. Я попробовал предложенное решение, подразумеваемое в: «Сам набор контуров не имеет метода set_clip_path, но вы можете перебирать каждую из коллекций контуров и устанавливать соответствующие пути клипа». Мое новое и окончательное решение выглядит так (см. график ниже):

  p=PatchCollection(mypatches,color='none', alpha=1.0,edgecolor="purple",linewidth=2.0)
  levels=np.arange(SST.min(),SST.max(),0.2)
  grid_x, grid_y = np.mgrid[x.min()-0.5*(x.min()):x.max()+0.5*(x.max()):200j,
                          y.min()-0.5*(y.min()):y.max()+0.5*(y.max()):200j]
  grid_z = griddata(x,y,SST,grid_x,grid_y)

  cs=mymap.contourf(grid_x, grid_y, grid_z)

  for poly in mypatches:
      for artist in ax.get_children():
          artist.set_clip_path(poly)

      ax.add_patch(poly)
  mymap.drawcountries()
  mymap.drawcoastlines()
  mymap.fillcontinents(color='lightgrey',lake_color='none')
  mymap.drawmapboundary(fill_color='none')

Это решение также может быть улучшено, в частности, с точки зрения экстраполяции крайних границ на севере. Предложения о том, как действительно «заполнить» полный многоугольник, приветствуются. Я также хотел бы понять, почему mlab работал, а scipy нет.

Окончательное решение, показывающее обрезанные контуры с помощью set_clip_path


person Trond Kristiansen    schedule 12.09.2013    source источник
comment
Какие методы интерполяции вы пробовали?   -  person tacaswell    schedule 13.09.2013
comment
@tcaswell Пожалуйста, смотрите мой обновленный ответ   -  person Trond Kristiansen    schedule 13.09.2013
comment
scipy и mlab версия griddata и различные методы, так что это неудивительно. Я думаю, что проблема с интерполяцией за пределами данных, которые у вас есть, является более фундаментальной проблемой и потребует сомнительных методов обхода;)   -  person tacaswell    schedule 13.09.2013


Ответы (1)


Я бы интерполировал данные, используя scipy. данные сетки. Вы можете установить регион за пределами вашей области (mypatches) на np.nan. А затем просто используйте pyplot.contour, чтобы построить его.

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

def sst_data(x, y):
    return x*(1-x)*np.cos(4*np.pi*x) * np.sin(4*np.pi*y**2)**2

                         #replace with ...
x = np.random.rand(1000) #... your x
y = np.random.rand(1000) #... your y
sst = sst_data(x, y)     #... your sst

# interpolate to a grid
grid_x, grid_y = np.mgrid[0:1:100j, 0:1:200j] 
grid_z = griddata((x,y), sst, (grid_x, grid_y), method='cubic')

# mask out the area outside of your region
nr, nc = grid_z.shape
grid_z[-nr//3:, -nc//3:] = np.nan

plt.contourf(grid_x, grid_y, grid_z)

plt.show()

введите здесь описание изображения

РЕДАКТИРОВАТЬ: изменено имя переменной в вызове plt.contourf() (было ..(grid_z, grid_y, grid_z))

person thorink    schedule 13.09.2013
comment
Ваше предложение привело меня на правильный путь, поэтому я принял ваш ответ. - person Trond Kristiansen; 13.09.2013