数据数组

每个 DataSet 包含允许您访问底层数值数据的属性。此数值数据可能与点、单元关联,或者不与点或单元关联并一般附加到网格。

为了说明 PyVista 中的数据数组,让我们首先构建一个比我们之前示例稍微复杂一点的网格。这里,我们通过从 ImageData 开始然后将其强制转换为 UnstructuredGrid 使用 cast_to_unstructured_grid() 来创建一个包含四个等距单元的简单网格。

code.matlab
>>> grid = pv.ImageData(dimensions=(3, 3, 1))
>>> ugrid = grid.cast_to_unstructured_grid()
>>> ugrid

让我们也绘制这个基本网格:

code.matlab
pl = pv.Plotter()
pl.add_mesh(ugrid, show_edges=True, line_width=5)
label_coords = ugrid.points + [0, 0, 0.02]
point_labels = [f'Point {i}' for i in range(ugrid.n_points)]
pl.add_point_labels(
    label_coords, point_labels, font_size=25, point_size=20
)
cell_labels = [f'Cell {i}' for i in range(ugrid.n_cells)]
pl.add_point_labels(ugrid.cell_centers(), cell_labels, font_size=25)
pl.camera_position = 'xy'
pl.show()
Document Image
\[\]

现在我们有一个简单的网格可以使用,我们可以开始为它分配数据。可以关联到网格的主要有两种数据:标量数据和向量数据。标量数据是单一或多组件的非定向数据,可能包括温度值,或者在多组件数据的情况下,RGBA 值。向量数据具有幅度和方向,表示为每个数据点包含三个组件的数组。

绘制时,我们可以轻松显示标量数据,但此数据必须“关联”到点或单元。例如,我们可能希望为我们示例网格的单元分配值,我们可以通过访问网格的 cell_data 属性来实现。

单元数据

向 DataSet 添加标量数据的最简单方法是使用 [] 运算符。继续我们上面的示例,让我们为每个单元分配一个整数。我们可以使用 Python list 并使其与 UnstructuredGrid 中的单元数长度相同来完成此操作。或者作为更简单的示例,使用适当长度的 range。这里我们创建范围,将其添加到 cell_data,然后使用 [] 运算符访问它。

code.matlab
>>> simple_range = range(ugrid.n_cells)
>>> ugrid.cell_data['my-data'] = simple_range
>>> ugrid.cell_data['my-data']
pyvista_ndarray([0, 1, 2, 3])

注意我们如何返回 pyvista.pyvista_ndarray。由于 VTK 需要 C 数组,PyVista 将在内部包装或转换所有输入为 C 数组。然后我们可以使用以下方式绘制它:

code.matlab
ugrid.plot(cpos='xy', show_edges=True)
Document Image
\[\]

注意我们不必指定要绘制哪个单元数据,因为 [] 运算符自动设置活动标量:

code.matlab
>>> ugrid.cell_data
pyvista DataSetAttributes
 Association     : CELL
 Active Scalars  : my-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(4,)                 SCALARS

我们还可以向绘图添加标签以显示哪些单元分配了哪些标量。注意这与我们分配的标量顺序相同。

code.matlab
pl = pv.Plotter()
pl.add_mesh(ugrid, show_edges=True, line_width=5)
cell_labels = [f'Cell {i}' for i in range(ugrid.n_cells)]
pl.add_point_labels(ugrid.cell_centers(), cell_labels, font_size=25)
pl.camera_position = 'xy'
pl.show()
Document Image
\[\]

我们可以继续使用 [] 运算符向我们的 DataSet 分配单元数据,但如果您不希望新数组成为活动数组,可以使用 set_array() 添加它

code.matlab
>>> data = np.linspace(0, 1, ugrid.n_cells)
>>> ugrid.cell_data.set_array(data, 'my-cell-data')
>>> ugrid.cell_data
pyvista DataSetAttributes
 Association     : CELL
 Active Scalars  : my-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(4,)                 SCALARS
  my-cell-data            float64(4,)

现在,ugrid 包含两个数组,其中一个是“活动”标量。这组活动标量将是在 add_mesh() 或 pyvista.plot() 中未设置 scalars 时默认自动绘制的。这使得可以拥有许多与数据集关联的单元数组,并跟踪哪个将默认绘制为活动单元标量。

活动标量也可以通过 active_scalars 访问,活动标量数组的名称可以通过 active_scalars_name 访问或设置。

code.matlab
>>> ugrid.cell_data.active_scalars_name = 'my-cell-data'
>>> ugrid.cell_data
pyvista DataSetAttributes
 Association     : CELL
 Active Scalars  : my-cell-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(4,)
  my-cell-data            float64(4,)                 SCALARS

点数据

数据可以以与单元数据相同的方式关联到点。point_data 属性允许您将数据关联到 DataSet 的点。这里,我们将使用 [] 运算符将简单列表关联到点。

code.matlab
>>> simple_list = list(range(ugrid.n_points))
>>> ugrid.point_data['my-data'] = simple_list
>>> ugrid.point_data['my-data']
pyvista_ndarray([0, 1, 2, 3, 4, 5, 6, 7, 8])

同样,这些值是默认通过 [] 运算符成为点数组中的活动标量:

code.matlab
>>> ugrid.point_data
pyvista DataSetAttributes
 Association     : POINT
 Active Scalars  : my-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(9,)                 SCALARS

让我们绘制点数据。注意这与单元数据图不同;每个单独的点被分配一个标量值,该值在单元上插值以在点 0 的最低值和点 8 的最高值之间创建平滑的颜色映射。

code.matlab
pl = pv.Plotter()
pl.add_mesh(ugrid, show_edges=True, line_width=5)
label_coords = ugrid.points + [0, 0, 0.02]
point_labels = [f'Point {i}' for i in range(ugrid.n_points)]
pl.add_point_labels(
    label_coords, point_labels, font_size=25, point_size=20
)
pl.camera_position = 'xy'
pl.show()
Document Image
\[\]

如在单元数据中,我们可以使用 set_array() 向 point_data 分配多个数组。

code.matlab
>>> data = np.linspace(0, 1, ugrid.n_points)
>>> ugrid.point_data.set_array(data, 'my-point-data')
>>> ugrid.point_data
pyvista DataSetAttributes
 Association     : POINT
 Active Scalars  : my-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(9,)                 SCALARS
  my-point-data           float64(9,)

同样,这里现在有两个数组关联到该点数据,并且只有一个是“活动”标量数组。如同在单元数据中,我们可以使用 active_scalars 检索它,活动标量数组的名称可以通过 active_scalars_name 访问或设置。

code.matlab
>>> ugrid.point_data.active_scalars_name = 'my-point-data'
>>> ugrid.point_data
pyvista DataSetAttributes
 Association     : POINT
 Active Scalars  : my-point-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(9,)
  my-point-data           float64(9,)                 SCALARS

数据集活动标量

从前面的部分继续,我们的 ugrid 数据集现在包含点和单元数据:

code.matlab
>>> ugrid.point_data
pyvista DataSetAttributes
 Association     : POINT
 Active Scalars  : my-point-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(9,)
  my-point-data           float64(9,)                 SCALARS
>>> ugrid.cell_data
pyvista DataSetAttributes
 Association     : CELL
 Active Scalars  : my-cell-data
 Active Vectors  : None
 Active Texture  : None
 Active Normals  : None
 Contains arrays :
  my-data                 int64(4,)
  my-cell-data            float64(4,)                 SCALARS

在点和单元数据中都有活动标量,但在数据集级别只能有一个类型的标量为“活动”。原因是只有一种标量类型(无论是点还是单元)可以一次绘制,并且可以从 active_scalars_info 获取此数据:

code.matlab
>>> ugrid.active_scalars_info
ActiveArrayInfoTuple(association=<FieldAssociation.POINT: 0>, name='my-point-data')

注意活动标量默认是点标量。您可以通过使用 set_active_scalars() 设置活动标量来更改它。注意,如果您想设置活动标量并且点和单元数据都具有相同名称的数组,则必须指定偏好:

code.matlab
>>> ugrid.set_active_scalars('my-data', preference='cell')
>>> ugrid.active_scalars_info
ActiveArrayInfoTuple(association=<FieldAssociation.CELL: 1>, name='my-data')

这也可以在绘制时使用 add_mesh() 或 pyvista.plot() 中的 preference 参数设置。

字段数据

字段数组与 point_data 和 cell_data 不同,因为它们不与 DataSet 的几何关联。这意味着虽然不可能将字段数据指定为活动标量或向量,但您可以使用它来“附加”任何形状的数组。您甚至可以在字段数据中添加字符串数组:

code.matlab
>>> ugrid.field_data['my-field-data'] = ['hello', 'world']
>>> ugrid.field_data['my-field-data']
pyvista_ndarray(['hello', 'world'], dtype='<U5')

注意字段数据自动传输到 VTK C 风格数组,然后表示为 numpy 数据格式。

列出当前字段数据时,注意关联为“NONE”:

code.matlab
>>> ugrid.field_data
pyvista DataSetAttributes
 Association     : NONE
 Contains arrays :
  my-field-data           <U5(2,)

这是因为数据不与点或单元关联,并且不能如此,因为字段数据预计不匹配单元或点的数量。因此,它也不能被绘制。

向量、纹理坐标和法线属性

单元和点数据都可以存储以下“特殊”属性以及 active_scalars:

活动法线

active_normals 数组是一个特殊数组,指定网格的局部法线方向。它用于创建基于物理的渲染、使用 Phong 插值渲染平滑着色、按标量扭曲等。如果在以 smooth_shading=True 或 pbr=True 绘制时未设置此数组,它将被计算。

活动纹理坐标

active_texture_coordinates 数组用于渲染纹理。有关使用此数组的示例,请参阅应用纹理。

活动向量

active_vectors 是包含具有幅度和方向(具体地,三个组件)的数量的数组。例如,包含在各个坐标处的风速的向量场。这与 active_scalars 不同,因为标量预期为非定向的,即使它们包含多个组件(如 RGB 数据的情况)。

向量在使用 transform() 过滤器执行转换时,在 VTK 中的处理方式与标量不同。与标量数组不同,向量数组将与几何一起转换,因为这些向量表示具有方向的数量。

注意

VTK 只允许一个“活动”向量。如果您有多个希望转换的向量数组,请在 transform() 中设置 transform_all_input_vectors=True。请注意,这将转换任何具有三个组件的数组,因此在转换后必须丢弃像 RGB 数组这样的多组件标量数组。