3D 带周期边界条件的连通组件

huangapple go评论60阅读模式
英文:

3D connected components with periodic boundary conditions

问题

我试图在地球上识别连接的特征(即,空间-时间上的球面上的特征)。cc3d 包已经帮助我解决了90%的问题,但我在处理日期边界时遇到了困难(即,在三个维度中的一个维度上的周期性边界条件)。

在二维地图上,我的方法的问题变得明显(请注意在南极附近0经度附近连接但标记不同的区域):

3D 带周期边界条件的连通组件

这是因为数据在经度从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')

3D 带周期边界条件的连通组件

在这里,右上角的黄色结构应该与顶部的其余结构连接在一起,底部的两个结构也是如此。请记住,任何有用的解决方案也应适用于三维中的连接特征。

对于如何解决这个问题,欢迎任何帮助。

英文:

I am trying to identify connected features on the globe (i.e., in space-time on a sphere). The cc3d package has gotten me 90% of the way but I am struggling to deal with the date border (i.e., the periodic boundary conditions in one of the three dimensions).

On a 2D map, the problem of my approach becomes apparent (note the connected buy differently labelled region around 0 longitude near the South Pole):

3D 带周期边界条件的连通组件

This appears because the data are defined on longitudes from 0 to 360 (while I show shown them from -180 to 180 here to make the problem more apparent).

My two typical solutions for these kinds of problems do not work:

  • Flipping the anti-meridian to the pacific just shifts the problem and therefore does not help.
  • Concatenating a copy of the data at right hand boundary does also not help because it leads to ambiguity in the labels between the original left side and the pasted data on the right

MWE

A break-down of the problem in 2 dimensions should be the following:

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')

3D 带周期边界条件的连通组件

Here the yellow structure in the right top should be connected to the rest of the top structure and same for the two structures at the bottom. Please keep in mind that any helpful solution should also work for connected features in 3 dimensions.

Any help on how to approach this is appreciated.

答案1

得分: 0

好的,以下是翻译的代码部分:

好的我有一个修复输出的方法它相当慢需要运行`connected_components`两次但对我来说有效我把它放在这里以防对其他人有帮助

我将在此处放置MWE的修复版本但对于完整的3D时空数据独立处理每一天),它的效果是等效的我正在处理的数据约定是经度是最后一个维度所以时间纬度经度),但它在x轴上绘制因此我在MWE示例中的所有函数调用中执行了`swapaxes`。

函数

```python
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):  # 相当于切换反子午线 [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}  
    # 如果每个键只有一个唯一值,那么它是一对一映射,没有问题
    conflicts = [list(values) for values in mapping.values() if len(values) != 1]
    
    print(mapping)  # 调试
    
    for conflict in conflicts:
        idx = np.any([arr == cc for cc in conflict[1:]], axis=0)
        arr[idx] = conflict[0]  # 在原始(即第一个)数组中重新分配
        
    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)  # 原始
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)

请注意,在修复后的数组中,标签将不再严格连续!


<details>
<summary>英文:</summary>

Okay I have a fix for the output. Its quite slow and requires to run `connected_components` twice but works for me. I&#39;m putting it here in case its helpful for anyone later. 

I&#39;ll put the fix for the MWE here but it works equivalently for full 3D space-time data (independently for each day). **The convention for the data I&#39;m working with is that the longitude is the last dimension, so (time, latitude, longitude) but it is plotted on the x-axis, therefore I do a `swapaxes` for all function calls in the MWE example.**

Functions

```python
def plot(arr):
    map = plt.pcolormesh(arr, vmin=.5)
    map.cmap.set_under(&#39;none&#39;)    
 
    for xx in range(len(arr)):
        for yy in range(len(arr)):
            plt.text(yy+.5, xx+.5, arr[xx, yy],
                     ha=&quot;center&quot;, va=&quot;center&quot;, color=&quot;k&quot;)


def cut_stitch(arr):  # equivalent to switching the antimeridian [0, 360[ -&gt; [-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

Run component labelling a second time on the rearranged field, then rearrange again:

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)

3D 带周期边界条件的连通组件
3D 带周期边界条件的连通组件

Fix the labels:

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)

3D 带周期边界条件的连通组件

Note that the labels will no longer be strictly consecutive in the fixed array!

huangapple
  • 本文由 发表于 2023年5月30日 02:40:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76359670.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定