首页 > 解决方案 > 将外部环境中的 python 代码动态“注入”到 Paraview 可编程源中的最佳方法是什么?

问题描述

我正在尝试使用 Paraview 和外部 Python 环境构建强大的分析/可视化工作流。总而言之,paraview.simple包允许连接到“paraview 服务器”,同时本地 paraview 应用程序 gui 连接到同一服务器。

现在,我们可以直接从外部 python 环境运行这样的东西,甚至不需要在同一台机器上。

from paraview.simple import *
Connect("localhost")
c = Cone()
Show(c)

左侧的外部 ipython,右侧的 paraview 客户端都连接到在 docker 映像上运行的 pvserver

一切都按预期工作。但是,由于 pvserver 如何管理客户端会话的某些限制,将纯 vtk 对象发送到 pvserver 显然是一项不平凡的任务。例如以这种方式生成的对象。

# Script
import SimpleITK as sitk
from glob import glob
import itk
import vtk
from vtk.util import numpy_support as vtknp
import numpy as np
from paraview.simple import *

def ReadCSAX3D(PATH, time):
    reader = sitk.ImageSeriesReader()
    sitk_image = sitk.ReadImage(reader.GetGDCMSeriesFileNames(PATH + '/time_' + str(time)))
    return sitk_image

# Based on notebook examples provided # https://github.com/NVIDIA/ipyparaview/blob/master/notebooks/Iso-Surfaces_with_RTX.ipynb
def SitkToVTK(sitk_image):
    voldims = np.asarray(sitk_image.GetSize())
    npvol = sitk.GetArrayFromImage(sitk_image).reshape(np.prod(voldims))
    vtkimg = vtk.vtkImageData()
    vtkimg.SetDimensions(voldims)
    vtkimg.SetExtent([0,voldims[0]-1, 0,voldims[1]-1, 0,voldims[2]-1])
    vtkimg.SetSpacing(np.asarray(sitk_image.GetSpacing()))
    vtkimg.SetOrigin(np.asarray(sitk_image.GetOrigin()))

    # Get a VTK wrapper around the numpy volume
    dataName = 'MRI_STACK'
    vtkarr = vtknp.numpy_to_vtk(npvol)
    vtkarr.SetName(dataName)
    vtkimg.GetPointData().AddArray(vtkarr)
    vtkimg.GetPointData().SetScalars(vtkarr)
    return vtkimg

sitk_image = ReadCSAX3D("/path/to/image_file", time_step)
vtk_image = SitkToVTK(sitk_image)
Connect("localhost")
tp = TrivialProducer()
tp.GetClientSideObject().SetOutput(vtk_image)
# GetClientSideObject() returns None in this configuration --
Show(tp)

更多关于这里正如其中一个答案中所解释的,两个会话需要在服务器上共享相同的内存空间

我想出了一个基于 Paraview 指南关于使用可编程源和过滤器的有趣解决方法,它允许输入的源是 python 脚本。如果 paraview python 具有所有依赖项,这种方法非常有效。因此,现在我们可以直接从外部 Python 环境中注入 Python 代码,例如。

ps = ProgrammableSource()
ps.Script = "print('Hello')"
Show(ps)

但是现在从我的代码库中以编程方式注入代码的通用方法是什么?就:稍后代码库的最佳方法和可维护性而言(我目前正在考虑使用inspect模块将已定义函数的源代码行作为字符串并将它们发送到动态的可编程源。但是,我将如何evaluate部分脚本被发送以允许函数参数,我担心从长远来看这将很难维护。

更一般地说,类似问题的一个很好的例子是什么?即注入小的python 脚本,这可能需要在运行时进行更改。无论如何,让我们假设我可以在外部 python 环境中运行的任何代码也应该在 paraview 服务器中运行,我可以确保 python 环境/包是相同的。

标签: pythonipythonmetaprogrammingvtkparaview

解决方案


推荐阅读