numpy 具有周期性边界条件的三维连通域

3qpi33ja  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(269)

我试图识别地球仪上的连接特征(即在球体上的时空中)。cc3d包已经让我完成了90%的工作,但是我很难处理日期边界(即三维中的一个周期性边界条件)。
在2DMap上,我的方法的问题变得明显(注意,在南极附近的0经度周围连接的购买不同标记的区域):

这是因为数据是在经度0到360之间定义的(而我在这里显示的是从-180到180,以使问题更加明显)。
对于这类问题,我的两个典型解决方案都不起作用:

  • 将逆子午线翻转到太平洋只是将问题转移,因此没有帮助。
  • 在右侧边界连接数据的副本也没有帮助,因为它会导致原始左侧和右侧粘贴数据之间的标签不明确
    MWE

问题的二维分解应如下:

import cc3d
import numpy as np
import matplotlib.pyplot as plt

arr = np.sin(np.random.RandomState(0).randn(100).reshape(10, 10)) > .3
labels = cc3d.connected_components(arr)
map = plt.pcolormesh(labels, vmin=.5)
map.cmap.set_under('none')

在这里,右上角的黄色结构应该连接到顶部结构的其余部分,底部的两个结构也是如此。请记住,任何有用的解决方案也应该适用于三维中的连接特征。
任何关于如何处理这一点的帮助都很感激。

44u64gxh

44u64gxh1#

好的,我有一个输出的修复。它相当慢,需要运行connected_components两次,但对我来说很有效。我把它放在这里,以防以后对任何人有帮助。
我将在这里修复MWE,但它等效于完整的3D时空数据(每天独立)。**我处理的数据的约定是经度是最后一个维度,所以(time,latitude,longitude)但它被绘制在x轴上,因此我对MWE示例中的所有函数调用都执行swapaxes
功能

def plot(arr):
    map = plt.pcolormesh(arr, vmin=.5)
    map.cmap.set_under('none')    
 
    for xx in range(len(arr)):
        for yy in range(len(arr)):
            plt.text(yy+.5, xx+.5, arr[xx, yy],
                     ha="center", va="center", color="k")

def cut_stitch(arr):  # equivalent to switching the antimeridian [0, 360[ -> [-180, 180[
    idx = len(arr) // 2
    return np.concatenate([arr[idx:], arr[:idx]], axis=0)

def fix_date_border(arr, arr_r):
    mask = arr == 0

    mapping = {}
    for key, value in zip(arr_r[~mask], arr[~mask]):
        try:
            mapping[key].add(value)
        except KeyError:
            mapping[key] = {value}  
    # if there is only one unique value per key its a one-to-one mapping and no problem
    conflicts = [list(values) for values in mapping.values() if len(values) != 1]
    
    print(mapping)  # DEBUG
    
    for conflict in conflicts:
        idx = np.any([arr == cc for cc in conflict[1:]], axis=0)
        arr[idx] = conflict[0]  # reassign in original (i.e., first) array
        
    return arr

在重新排列的字段上再次运行元件标签,然后再次重新排列:

arr2 = cut_stitch(arr.swapaxes(0, 1)).swapaxes(0, 1)
labels2 = cut_stitch(cc3d.connected_components(arr2).swapaxes(0, 1)).swapaxes(0, 1)
plot(labels)  # original
plot(labels2)

固定标签:

labels_fixed = fix_date_border(labels.swapaxes(0, 1), labels2.swapaxes(0, 1)).swapaxes(0, 1)
# {2: {1, 2}, 7: {8, 7}, 5: {4}, 3: {3}, 1: {1}, 4: {5}, 8: {7}, 6: {6}}
plot(labels_fixed, labels=True)

注意,在固定数组中,标签将不再严格连续!

相关问题