在4D numpy网格数据数组中查找不规则区域(lat / lon)

时间:2021-10-19 18:20:29

I have a large 4-dimensional dataset of Temperatures [time,pressure,lat,lon]. I need to find all grid points within a region defined by lat/lon indices and calculate an average over the region to leave me with a 2-dimensional array.

我有一个大的4维温度数据集[时间,压力,纬度,经度]。我需要找到由lat / lon索引定义的区域内的所有网格点,并计算该区域的平均值,以便给我留下一个二维数组。

I know how to do this if my region is a rectangle (or square) but how can this be done with an irregular polygon?

如果我的区域是一个矩形(或正方形),我知道如何做到这一点,但如何用不规则多边形完成?

Below is an image showing the regions I need to average together and the lat/lon grid the data is gridded to in the array

下面的图像显示了我需要在一起平均的区域以及数据在数组中被网格化的纬度/经度网格

在4D numpy网格数据数组中查找不规则区域(lat / lon)

2 个解决方案

#1


1  

I believe this should solve your problem.

我相信这应该可以解决你的问题。

The code below generates all cells in a polygon defined by a list of vertices. It "scans" the polygon row by row keeping track of the transition columns where you (re)-enter or exit the polygon.

下面的代码生成由顶点列表定义的多边形中的所有单元格。它逐行“扫描”多边形,跟踪您(重新)进入或退出多边形的过渡列。

def row(x, transitions):
    """ generator spitting all cells in a row given a list of transition (in/out) columns."""

    i = 1
    in_poly = True
    y = transitions[0]
    while i < len(transitions):
        if in_poly:
            while y < transitions[i]:
                yield (x,y)
                y += 1
            in_poly = False
        else:
            in_poly = True
            y = transitions[i]
        i += 1


def get_same_row_vert(i, vertices):
    """ find all vertex columns in the same row as vertices[i], and return next vertex index as well."""

    vert = []
    x = vertices[i][0]
    while i < len(vertices) and vertices[i][0] == x:
        vert.append(vertices[i][1])
        i += 1
    return vert, i


def update_transitions(old, new):
    """ update old transition columns for a row given new vertices. 

    That is: merge both lists and remove duplicate values (2 transitions at the same column cancel each other)"""

    if old == []:
        return new
    if new == []:
        return old
    o0 = old[0]
    n0 = new[0]
    if o0 == n0:
        return update_transitions(old[1:], new[1:])
    if o0 < n0:
        return [o0] + update_transitions(old[1:], new)
    return [n0] + update_transitions(old, new[1:])


def polygon(vertices):
    """ generator spitting all cells in the polygon defined by given vertices."""

    vertices.sort()
    x = vertices[0][0]
    transitions, i = get_same_row_vert(0, vertices)
    while i < len(vertices):
        while x < vertices[i][0]:            
            for cell in row(x, transitions):
                yield cell
            x += 1
        vert, i = get_same_row_vert(i, vertices)
        transitions = update_transitions(transitions, vert)


# define a "strange" polygon (hook shaped)
vertices = [(0,0),(0,3),(4,3),(4,0),(3,0),(3,2),(1,2),(1,1),(2,1),(2,0)]

for cell in polygon(vertices):
    print cell
    # or do whatever you need to do

#2


1  

The general class of problems is called "Point in Polygon", where the (fairly) standard algorithm is based on drawing a test line through the point under consideration and counting the number of times it crosses polygon boundaries (its really cool/weird that it works so simply, I think). This is a really good overview which includes implementation information.

一般类别的问题被称为“多边形点”,其中(公平)标准算法基于通过所考虑的点绘制测试线并计算它穿过多边形边界的次数(它真的很酷/很奇怪它我觉得这很简单。这是一个非常好的概述,其中包括实现信息。

For your problem in particular, since each of your regions are defined based on a small number of square cells - I think a more brute-force approach might be better. Perhaps something like:

特别是对于您的问题,因为您的每个区域都是基于少量方格单元定义的 - 我认为更强大的方法可能会更好。也许是这样的:

  • For each region, form a list of all of the (lat/lon) squares which define it. Depending on how your regions are defined, this may be trivial, or annoying...

    对于每个区域,形成定义它的所有(lat / lon)方块的列表。根据您所在地区的定义,这可能是微不足道的,或令人烦恼......

  • For each point you are examining, figure out which square it lives in. Since the squares are so well behaves, you can do this manually using opposite corners of each square, or using a method like numpy.digitize.

    对于您正在检查的每个点,找出它所处的方格。由于方块表现良好,您可以使用每个方块的相对角手动执行此操作,或使用numpy.digitize等方法。

  • Test whether the square the point lives in, is in one of the regions.

    测试该点所在的正方形是否位于其中一个区域。

If you're still having trouble, please provide some more details about your problem (specifically, how your regions are defined) --- that will make it easier to offer advice.

如果您仍然遇到问题,请提供有关您的问题的更多详细信息(具体来说,您的地区如何定义) - 这将使您更容易提供建议。

#1


1  

I believe this should solve your problem.

我相信这应该可以解决你的问题。

The code below generates all cells in a polygon defined by a list of vertices. It "scans" the polygon row by row keeping track of the transition columns where you (re)-enter or exit the polygon.

下面的代码生成由顶点列表定义的多边形中的所有单元格。它逐行“扫描”多边形,跟踪您(重新)进入或退出多边形的过渡列。

def row(x, transitions):
    """ generator spitting all cells in a row given a list of transition (in/out) columns."""

    i = 1
    in_poly = True
    y = transitions[0]
    while i < len(transitions):
        if in_poly:
            while y < transitions[i]:
                yield (x,y)
                y += 1
            in_poly = False
        else:
            in_poly = True
            y = transitions[i]
        i += 1


def get_same_row_vert(i, vertices):
    """ find all vertex columns in the same row as vertices[i], and return next vertex index as well."""

    vert = []
    x = vertices[i][0]
    while i < len(vertices) and vertices[i][0] == x:
        vert.append(vertices[i][1])
        i += 1
    return vert, i


def update_transitions(old, new):
    """ update old transition columns for a row given new vertices. 

    That is: merge both lists and remove duplicate values (2 transitions at the same column cancel each other)"""

    if old == []:
        return new
    if new == []:
        return old
    o0 = old[0]
    n0 = new[0]
    if o0 == n0:
        return update_transitions(old[1:], new[1:])
    if o0 < n0:
        return [o0] + update_transitions(old[1:], new)
    return [n0] + update_transitions(old, new[1:])


def polygon(vertices):
    """ generator spitting all cells in the polygon defined by given vertices."""

    vertices.sort()
    x = vertices[0][0]
    transitions, i = get_same_row_vert(0, vertices)
    while i < len(vertices):
        while x < vertices[i][0]:            
            for cell in row(x, transitions):
                yield cell
            x += 1
        vert, i = get_same_row_vert(i, vertices)
        transitions = update_transitions(transitions, vert)


# define a "strange" polygon (hook shaped)
vertices = [(0,0),(0,3),(4,3),(4,0),(3,0),(3,2),(1,2),(1,1),(2,1),(2,0)]

for cell in polygon(vertices):
    print cell
    # or do whatever you need to do

#2


1  

The general class of problems is called "Point in Polygon", where the (fairly) standard algorithm is based on drawing a test line through the point under consideration and counting the number of times it crosses polygon boundaries (its really cool/weird that it works so simply, I think). This is a really good overview which includes implementation information.

一般类别的问题被称为“多边形点”,其中(公平)标准算法基于通过所考虑的点绘制测试线并计算它穿过多边形边界的次数(它真的很酷/很奇怪它我觉得这很简单。这是一个非常好的概述,其中包括实现信息。

For your problem in particular, since each of your regions are defined based on a small number of square cells - I think a more brute-force approach might be better. Perhaps something like:

特别是对于您的问题,因为您的每个区域都是基于少量方格单元定义的 - 我认为更强大的方法可能会更好。也许是这样的:

  • For each region, form a list of all of the (lat/lon) squares which define it. Depending on how your regions are defined, this may be trivial, or annoying...

    对于每个区域,形成定义它的所有(lat / lon)方块的列表。根据您所在地区的定义,这可能是微不足道的,或令人烦恼......

  • For each point you are examining, figure out which square it lives in. Since the squares are so well behaves, you can do this manually using opposite corners of each square, or using a method like numpy.digitize.

    对于您正在检查的每个点,找出它所处的方格。由于方块表现良好,您可以使用每个方块的相对角手动执行此操作,或使用numpy.digitize等方法。

  • Test whether the square the point lives in, is in one of the regions.

    测试该点所在的正方形是否位于其中一个区域。

If you're still having trouble, please provide some more details about your problem (specifically, how your regions are defined) --- that will make it easier to offer advice.

如果您仍然遇到问题,请提供有关您的问题的更多详细信息(具体来说,您的地区如何定义) - 这将使您更容易提供建议。