【问题标题】:How to plot a Plotly Isosurface with non-analytic data?如何使用非分析数据绘制 Plotly 等值面?
【发布时间】:2020-12-03 13:46:54
【问题描述】:

我正在从天气模型中获取一些数据,并尝试将其绘制为 Plotly 内的等值面,但每次我都得到一个空白图表,没有任何错误消息。我是 plotly 的新手,所以这似乎是一个简单的问题。文档和教程页面没有任何帮助。

我已将输入数据缩减为 3x3x3 3D 数组(在发送到 go.Isosurface 之前被展平),3D 形式的数据是:

z_subset_tiled_2 = np.array([[[151.11943054, 151.11943054, 151.11943054],
        [151.11943054, 151.11943054, 151.11943054],
        [151.11943054, 151.11943054, 151.11943054]],

       [[255.65301514, 255.65301514, 255.65301514],
        [255.65301514, 255.65301514, 255.65301514],
        [255.65301514, 255.65301514, 255.65301514]],

       [[363.32260132, 363.32260132, 363.32260132],
        [363.32260132, 363.32260132, 363.32260132],
        [363.32260132, 363.32260132, 363.32260132]]], dtype='float32')

lat_subset_tiled_2 = np.array([[[14.10366  , 14.103652 , 14.103641 ],
        [14.112637 , 14.112626 , 14.1126175],
        [14.121613 , 14.121605 , 14.121593 ]],

       [[14.10366  , 14.103652 , 14.103641 ],
        [14.112637 , 14.112626 , 14.1126175],
        [14.121613 , 14.121605 , 14.121593 ]],

       [[14.10366  , 14.103652 , 14.103641 ],
        [14.112637 , 14.112626 , 14.1126175],
        [14.121613 , 14.121605 , 14.121593 ]]], dtype='float32')

lon_subset_tiled_2 = np.array([[[120.31331 , 120.32256 , 120.33182 ],
        [120.31332 , 120.32256 , 120.331825],
        [120.31332 , 120.32258 , 120.33184 ]],

       [[120.31331 , 120.32256 , 120.33182 ],
        [120.31332 , 120.32256 , 120.331825],
        [120.31332 , 120.32258 , 120.33184 ]],

       [[120.31331 , 120.32256 , 120.33182 ],
        [120.31332 , 120.32256 , 120.331825],
        [120.31332 , 120.32258 , 120.33184 ]]], dtype='float32')

theta_2 = np.array([[[301.3794 , 301.44308, 301.4732 ],
        [301.33685, 301.39835, 301.44403],
        [301.3008 , 301.35147, 301.40442]],

       [[301.39117, 301.46188, 301.48926],
        [301.34885, 301.41992, 301.46976],
        [301.31003, 301.37192, 301.43362]],

       [[301.49753, 301.57315, 301.5888 ],
        [301.4737 , 301.54742, 301.59207],
        [301.45   , 301.51346, 301.57153]]], dtype='float32')

绘图功能为:

import plotly.graph_objects as go

fig= go.Figure(data=go.Isosurface(
    x=lon_subset_tiled_2.flatten(),
    y=lat_subset_tiled_2.flatten(),
    z=z_subset_tiled_2.flatten(),
    value=theta_2.flatten(),
    isomin = 301.4, 
    isomax = 301.5, 
    caps=dict(x_show=False, y_show=False)
))

fig.show()

我得到的输出是:

它似乎连坐标都没有,所以我希望这里有一些明显的错误。但是,使用真实数据进行处理的文档并不存在。

【问题讨论】:

    标签: python plotly plotly-python


    【解决方案1】:

    如果有人由于依赖问题(比如我)而无法使用 mayavi 解决方法,则使用 np.mgridscipy.interpolate.griddata 将数据插入到常规网格中对我的情况很有效。

    在下面的示例中,z、lon 和 lat 分别是高度、x 和 y 的 3d 数组。数据数组是 (z,lon,lat) 处的值的 3d 数组

    # Data coordinates
    points = np.array( (z.flatten(), lon.flatten(), lat.flatten()) ).T
    # Data values @ above coords
    values = data.flatten()
    
    # Grid to interp to
    Z, X, Y = np.mgrid[z.min():z.max():20j, lon.min():lon.max():50j, lat.min():lat.max():50j]
    # New data values on interp grid
    newdata = griddata( points, values, (Z,X,Y) )
    
    fig = go.Figure(data=[
                go.Isosurface(x=X.flatten(),y=Y.flatten(),z=Z.flatten(),
                           value=newdata.flatten(),
                           opacity=0.3,
                           isomin=15,
                           isomax=30,
                           surface_count=5,
                           lighting=dict(ambient=0.7),
                           colorscale='amp',
                           showscale=False,
                           caps=dict(x_show=False, y_show=False)
                           ),
                ])
    

    无论出于何种原因,即使我的数据已经网格化,但当我将所有内容重新插入统一网格时,它仍然可以正常工作。效率不高,但很管用。

    【讨论】:

      【解决方案2】:

      我不是 Plotly 方面的专家,但您似乎无法使用未正确排序的点创建等值面(即形成一个表面但随后还包括该表面内部的更多点的点的集合)

      例如,请注意,虽然以下代码正确呈现:

      fig= go.Figure(data=go.Isosurface(
          x=np.array([0,0,0,0,1,1,1,1]),
          y=np.array([1,0,1,0,1,0,1,0]),
          z=np.array([1,1,0,0,1,1,0,0]),
          value=theta_2[0].flatten(),
          isomin = 301.3, 
          isomax = 301.6
      ))
      fig.show()
      

      交换第一个和最后一个 x,y,z 坐标意味着这不再是一个正确排序的表面,因此 Plotly 无法渲染图形。

      fig= go.Figure(data=go.Isosurface(
          x=np.array([1,0,0,0,1,1,1,0]),
          y=np.array([0,0,1,0,1,0,1,1]),
          z=np.array([0,1,0,0,1,1,0,1]),
          value=theta_2[0].flatten(),
          isomin = 301.3, 
          isomax = 301.6
      ))
      fig.show()
      

      我认为您很可能需要对其中一个数组进行排序(例如 x 坐标),然后围绕该数组重新排列其他数组。当我有更多空闲时间时,我很高兴重新审视这个问题,但希望这能让你朝着正确的方向开始!

      另外:任何在 3D 绘图方面比我更有经验的人,请加入!

      【讨论】:

      • 我认为您的初始点是正确的,并且看起来这是在正确的道路上,但是重新排序这些点以使其中一个数组按顺序排列并不能解决问题。我什至尝试对点进行排序,使数组按 x、y、z 顺序排列。我想知道问题是否在于这些不是矩形点?接下来我可以试试。
      • 哦,这些不是矩形点吗?你用的是什么坐标系?
      • 这些最初是地理极坐标点,但即使转换(和插值)为笛卡尔坐标也不起作用。
      • 由于 Plotly 等值面是在 3D 笛卡尔坐标中绘制的,因此我很确定您必须首先将地理极地立体坐标转换为笛卡尔坐标。之后,您将需要以某种方式重新排列这些点,使它们形成等值面——目前我们都无法从您的数据中弄清楚。从我所见,我认为您希望 (x,y) 坐标像 np.meshgrid 订单坐标一样排序
      • 同意你的第一点。不过,即使它们是笛卡尔坐标,它似乎也不喜欢我的坐标。顺便说一句,我的坐标来自来自 np.meshgrid。我最终不得不放弃这种方法,而是使用 mayavi 作为我的 3D 绘图。它当然看起来不那么好,但它实际上很好用。感谢您的帮助。
      猜你喜欢
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 2021-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多