vtk.vtkOBJExporter not exporting entire rendering - python

I am trying to export a VTK rendering as an OBJ file to be viewed in Meshlab. Everything appears normal until I open the .obj file in Meshlab, where only the spheres have been exported and not any of the tubes I have connecting the spheres. I have tried exporting the rendering in different file types but only the spheres are exported for some reason. Could it be because the tube filter doesn't actually create a 3D object? Looking for any solutions to this problem! The writer is at the bottom of the code. Thanks
np={}
for n in G.nodes():
np[n]=node_pos[n]
nodePoints = vtk.vtkPoints()
i=0
for (x,y,z) in np.values():
nodePoints.InsertPoint(i, x, y, z)
i=i+1
# Create a polydata to be glyphed.
inputData = vtk.vtkPolyData()
inputData.SetPoints(nodePoints)
# Use sphere as glyph source.
balls = vtk.vtkSphereSource()
balls.SetRadius(.1)
balls.SetPhiResolution(20)
balls.SetThetaResolution(20)
glyphPoints = vtk.vtkGlyph3D()
glyphPoints.SetInputData(inputData)
glyphPoints.SetSourceData(balls.GetOutput())
glyphMapper = vtk.vtkPolyDataMapper()
glyphMapper.SetInputData(glyphPoints.GetOutput())
glyph = vtk.vtkActor()
glyph.SetMapper(glyphMapper)
glyph.GetProperty().SetDiffuseColor(plum)
glyph.GetProperty().SetSpecular(.3)
glyph.GetProperty().SetSpecularPower(30)
# Generate the polyline for the spline.
points = vtk.vtkPoints()
edgeData = vtk.vtkPolyData()
# Edges
lines = vtk.vtkCellArray()
i=0
for e in G.edges:
u=e[0]
v=e[1]
lines.InsertNextCell(2)
for n in (u,v):
(x,y,z)=node_pos[n]
points.InsertPoint(i, x, y, z)
lines.InsertCellPoint(i)
i=i+1
edgeData.SetPoints(points)
edgeData.SetLines(lines)
Tubes = vtk.vtkTubeFilter()
Tubes.SetNumberOfSides(16)
Tubes.SetInputData(edgeData)
Tubes.SetRadius(0.05) # edge RADIUS
profileMapper = vtk.vtkPolyDataMapper()
profileMapper.SetInputData(Tubes.GetOutput())
balls.Update()
glyphPoints.Update()
Tubes.Update()
profile = vtk.vtkActor()
profile.SetMapper(profileMapper)
profile.GetProperty().SetDiffuseColor(banana)
profile.GetProperty().SetSpecular(.3)
profile.GetProperty().SetSpecularPower(30)
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
ren.AddActor(profile)
ren.AddActor(glyph)
renWin.SetSize(1000, 1000)
iren.Initialize()
renWin.Render()
iren.Start()
writer = vtk.vtkOBJExporter()
writer.SetFilePrefix('test')
writer.SetInput(renWin)
writer.Write()

Related

How do I pass the object clicked on in a bokeh network graph

I have implemented a bokeh network graph with a datasource as follows:
# Create a Bokeh graph from the NetworkX input using nx.spring_layout
graph = from_networkx(G, nx.spring_layout, center=(0,0), scale=1.8)
plot.renderers.append(graph)
# Add some new columns to the node renderer data source
#graph.node_renderer.data_source.data['index'] = list(range(len(G)))
degrees = scale_degree_size([v[1] for v in G.degree()], 5, 20)
graph.node_renderer.data_source.data['degree'] = degrees
graph.node_renderer.data_source.data["color"] = [colors[G.nodes[x].get("isA")] if G.nodes[x].get("isA") else colors["default"]for x in nx.nodes(G)]
graph.node_renderer.data_source.data["type"] = [G.nodes[x].get("isA").split('/')[-1] if G.nodes[x].get("isA") else "Untyped" for x in nx.nodes(G)]
graph.node_renderer.data_source.data["aka"] = [G.nodes[x].get("aka").split('/')[-1] if G.nodes[x].get("aka") else "???" for x in nx.nodes(G)]
graph.node_renderer.glyph = Circle(size=15, fill_color="red") #Spectral4[0])
graph.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2])
graph.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1])
graph.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=3) # , end=OpenHead(line_color="firebrick", line_width=4)
graph.edge_renderer.selection_glyph = MultiLine(line_color=Spectral4[2], line_width=5)
graph.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5)
graph.selection_policy = NodesAndLinkedEdges()
graph.node_renderer.glyph.update(size='degree') #, fill_color="colors")
graph.node_renderer.glyph.update(fill_color='color')
This works without any problem. I now need to add the functionality of bringing up an info box when clicking on a node in the ui. So I have tried to add this function to Tap.
# setup button click
def callback(???):
return CustomJS(args=dict(degrees=graph.node_renderer.data_source.data), code='alert(`${???}`)')
plot.js_on_event('tap', callback(???))
show(plot)
My question is, how do I pass the information of what node was clicked into the CustomJs? I have look at cb_obj, but it only has the mouse position and I need info on the node clicked.
add Tap
plot.on_event(Tap, function)
and update your source with indices
def function():
print(source.selected.indices)
i dont have your data so cant help more.

VTK can not create its own map vtk.vtkDataSetMapper - Python

There is here such code.
import vtk
file_name = "1.vtk"
reader = vtk.vtkUnstructuredGridReader()
reader.SetFileName(file_name)
reader.Update() # Needed because of GetScalarRange
output = reader.GetOutput()
scalar_range = output.GetScalarRange()
lut = vtk.vtkLookupTable()
mapper = vtk.vtkDataSetMapper()
if vtk.VTK_MAJOR_VERSION <= 5:
mapper.SetInput(output)
else:
mapper.SetInputData(output)
mapper.SetScalarRange(scalar_range )
mapper.SetLookupTable(lut)
print(mapper)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
scalar_bar = vtk.vtkScalarBarActor()
scalar_bar.SetLookupTable(lut)
scalar_bar.SetTitle(u'AS1_X\nARM')
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
renderer.SetBackground(0.1, 0.2, 0.4)
renderer.AddActor2D(scalar_bar)
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window.SetSize(800, 600)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
interactor.Initialize()
render_window.Render()
interactor.Start()
He gives this picture
https://i.stack.imgur.com/jgsWP.png
But I do not like such a map, I need to get this card ...
https://i.stack.imgur.com/Nochv.png
I also would like to sign the values in the scalar bar.
In principle, I do all this with the help of Paraview, but there it must be fairly hands on it, I would like to automatically create everything.

Example for vtkContourGrid

I am trying to make contour plot from unstructured grid. My code does not work and I could not find an example to follow. I did not include the input file, hoping that a sample unstructured grid is easy to find. I managed to make work on Paraview by converting cell data to point data and then contouring "p" scalar. But I cannot do it with vtk. What's wrong in my code?
from vtk import *
file_name = "results.vtk"
reader = vtkUnstructuredGridReader()
reader.SetFileName(file_name)
reader.Update()
output = reader.GetOutput()
scalar_range = output.GetScalarRange()
c2p = vtkCellDataToPointData()
c2p.SetInputData(output)
contours = vtkContourGrid()
contours.SetInputData(c2p.GetOutput())
contours.SetValue(0, 0.007009505294263363)
gridmapper = vtkDataSetMapper()
gridmapper.SetInputData(output)
gridmapper.GetInput().GetCellData().SetActiveScalars("p")
gridmapper.SetScalarVisibility(1)
gridmapper.SetScalarRange(scalar_range)
mapper = vtkPolyDataMapper()
#mapper = vtkDataSetMapper()
mapper.SetInputConnection(contours.GetOutputPort())
actor = vtkActor()
actor.SetMapper(mapper)
gridactor = vtkActor()
gridactor.SetMapper(gridmapper)
gridactor.GetProperty().EdgeVisibilityOn()
renderer = vtkRenderer()
renderer.AddActor(actor)
renderer.AddActor(gridactor)
#renderer.SetBackground(1, 1, 1) # Set background to white
renderer_window = vtkRenderWindow()
renderer_window.AddRenderer(renderer)
interactor = vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderer_window)
interactor.Initialize()
interactor.Start()

update live pointcloud data in vtk python

I have a basic question as i am new to VTK. I have to draw live point cloud data in VTK. I have modified the code given in How to display point cloud in vtk in different colors?.
The pointcloud should update for number of times given in iterations(here 30). I have used Initialize() to avoid blocking control flow as mentioned in some solutions, in every iteration the point cloud is updated, and render() is called so that it can update the window with new data.
I cannot figure out why this is blocking the control flow, and the data is not updated. Only once the iterations are over, after renderWindowInteractor.Start() is called, the interaction is enabled.
import vtk
from numpy import random
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
def func(pointCloud):
# Renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(pointCloud.vtkActor)
renderer.SetBackground(.2, .3, .4)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Begin Interaction
renderWindow.Render()
renderWindowInteractor.Initialize()
return renderWindow,renderWindowInteractor
def main(iter):
while iter > 0:
pointCloud = VtkPointCloud()
for k in xrange(10000):
point = 20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
if iter == 30:
renderWindow,renderWindowInteractor = func(pointCloud)
else:
#pointCloud.vtkPolyData.Modified()
renderWindow.Render()
iter -= 1
renderWindowInteractor.Start()
main(30)
So you want to do an animation.
A better practice is to follow this sample explaining how to do use a TimerEvent.
Here is what it would look like with your code:
import vtk
from numpy import random
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
class AddPointCloudTimerCallback():
def __init__(self, renderer, iterations):
self.iterations = iterations
self.renderer = renderer
def execute(self, iren, event):
if self.iterations == 0:
iren.DestroyTimer(self.timerId)
pointCloud = VtkPointCloud()
self.renderer.AddActor(pointCloud.vtkActor)
pointCloud.clearPoints()
for k in xrange(10000):
point = 20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
iren.GetRenderWindow().Render()
if self.iterations == 30:
self.renderer.ResetCamera()
self.iterations -= 1
if __name__ == "__main__":
# Renderer
renderer = vtk.vtkRenderer()
renderer.SetBackground(.2, .3, .4)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderWindowInteractor.Initialize()
# Initialize a timer for the animation
addPointCloudTimerCallback = AddPointCloudTimerCallback(renderer, 30)
renderWindowInteractor.AddObserver('TimerEvent', addPointCloudTimerCallback.execute)
timerId = renderWindowInteractor.CreateRepeatingTimer(10)
addPointCloudTimerCallback.timerId = timerId
# Begin Interaction
renderWindow.Render()
renderWindowInteractor.Start()
Note that I renamed iter to iterations because iter is a reserved name in Python.

3d image visualisation with numpy/vtk

I'm trying to display further images (ct-scan) using numpy/vtk as describe in this sample code (http://www.vtk.org/Wiki/VTK/Examples/Python/vtkWithNumpy) but I don't get it and don't know why.
If someone could help me it would be kind.
Here's my code :
import vtk
import numpy as np
import os
import cv, cv2
import matplotlib.pyplot as plt
import PIL
import Image
DEBUG =True
directory="splitted_mri/"
w = 226
h = 186
d = 27
stack = np.zeros((w,d,h))
k=-1 #add the next picture in a differente level of depth/z-positions
for file in os.listdir(directory):
k+=1
img = directory + file
im = Image.open(img)
temp = np.asarray(im, dtype=int)
stack[:,k,:]= temp
print stack.shape
#~ plt.imshow(test)
#~ plt.show()
print type(stack[10,10,15])
res = np.amax(stack)
res1 = np.amin(stack)
print res, type(res)
print res1, type(res1)
#~ for (x,y,z), value in np.ndenumerate(stack):
#~ stack[x,y,z]=np.require(stack[x,y,z],dtype=np.int16)
#~ print type(stack[x,y,z])
stack = np.require(stack,dtype=np.uint16)
print stack.dtype
if DEBUG : print stack.shape
dataImporter = vtk.vtkImageImport()
data_string = stack.tostring()
dataImporter.CopyImportVoidPointer(data_string, len(data_string))
dataImporter.SetDataScalarTypeToUnsignedChar()
dataImporter.SetNumberOfScalarComponents(1)
dataImporter.SetDataExtent(0, w-1, 0, 1, 0, h-1)
dataImporter.SetWholeExtent(0, w-1, 0, 1, 0, h-1)
essai = raw_input()
alphaChannelFunc = vtk.vtkPiecewiseFunction()
colorFunc = vtk.vtkColorTransferFunction()
for i in range (0,255):
alphaChannelFunc.AddPoint(i, 0.9)
colorFunc.AddRGBPoint(i,i,i,i)
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)
#volumeProperty.ShadeOn()
volumeProperty.SetScalarOpacity(alphaChannelFunc)
# This class describes how the volume is rendered (through ray tracing).
compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
# We can finally create our volume. We also have to specify the data for it, as well as how the data will be rendered.
volumeMapper = vtk.vtkVolumeRayCastMapper()
volumeMapper.SetVolumeRayCastFunction(compositeFunction)
volumeMapper.SetInputConnection(dataImporter.GetOutputPort())
# The class vtkVolume is used to pair the preaviusly declared volume as well as the properties to be used when rendering that volume.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)
# With almost everything else ready, its time to initialize the renderer and window, as well as creating a method for exiting the application
renderer = vtk.vtkRenderer()
renderWin = vtk.vtkRenderWindow()
renderWin.AddRenderer(renderer)
renderInteractor = vtk.vtkRenderWindowInteractor()
renderInteractor.SetRenderWindow(renderWin)
# We add the volume to the renderer ...
renderer.AddVolume(volume)
# ... set background color to white ...
renderer.SetBackground(1, 1, 1)
# ... and set window size.
renderWin.SetSize(400, 400)
# A simple function to be called when the user decides to quit the application.
def exitCheck(obj, event):
if obj.GetEventPending() != 0:
obj.SetAbortRender(1)
# Tell the application to use the function as an exit check.
renderWin.AddObserver("AbortCheckEvent", exitCheck)
#to quit, press q
renderInteractor.Initialize()
# Because nothing will be rendered without any input, we order the first render manually before control is handed over to the main-loop.
renderWin.Render()
renderInteractor.Start()
I finally find out what was wrong
here's my new code
import vtk
import numpy as np
import os
import matplotlib.pyplot as plt
import PIL
import Image
DEBUG =False
directory="splitted_mri/"
l = []
k=0 #add the next picture in a differente level of depth/z-positions
for file in os.listdir(directory):
img = directory + file
if DEBUG : print img
l.append(img)
# the os.listdir function do not give the files in the right order
#so we need to sort them
l=sorted(l)
temp = Image.open(l[0])
h, w = temp.size
d = len(l)*5 #with our sample each images will be displayed 5times to get a better view
if DEBUG : print 'width, height, depth : ',w,h,d
stack = np.zeros((w,d,h),dtype=np.uint8)
for i in l:
im = Image.open(i)
temp = np.asarray(im, dtype=int)
for i in range(5):
stack[:,k+i,:]= temp
k+=5
#~ stack[:,k,:]= temp
#~ k+=1
if DEBUG :
res = np.amax(stack)
print 'max value',res
res1 = np.amin(stack)
print 'min value',res1
#convert the stack in the right dtype
stack = np.require(stack,dtype=np.uint8)
if DEBUG :#check if the image have not been modified
test = stack [:,0,:]
plt.imshow(test,cmap='gray')
plt.show()
if DEBUG : print 'stack shape & dtype' ,stack.shape,',',stack.dtype
dataImporter = vtk.vtkImageImport()
data_string = stack.tostring()
dataImporter.CopyImportVoidPointer(data_string, len(data_string))
dataImporter.SetDataScalarTypeToUnsignedChar()
dataImporter.SetNumberOfScalarComponents(1)
#vtk uses an array in the order : height, depth, width which is
#different of numpy (w,h,d)
w, d, h = stack.shape
dataImporter.SetDataExtent(0, h-1, 0, d-1, 0, w-1)
dataImporter.SetWholeExtent(0, h-1, 0, d-1, 0, w-1)
alphaChannelFunc = vtk.vtkPiecewiseFunction()
colorFunc = vtk.vtkColorTransferFunction()
for i in range(256):
alphaChannelFunc.AddPoint(i, 0.2)
colorFunc.AddRGBPoint(i,i/255.0,i/255.0,i/255.0)
# for our test sample, we set the black opacity to 0 (transparent) so as
#to see the sample
alphaChannelFunc.AddPoint(0, 0.0)
colorFunc.AddRGBPoint(0,0,0,0)
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)
#volumeProperty.ShadeOn()
volumeProperty.SetScalarOpacity(alphaChannelFunc)
# This class describes how the volume is rendered (through ray tracing).
compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
# We can finally create our volume. We also have to specify the data for
# it, as well as how the data will be rendered.
volumeMapper = vtk.vtkVolumeRayCastMapper()
# function to reduce the spacing between each image
volumeMapper.SetMaximumImageSampleDistance(0.01)
volumeMapper.SetVolumeRayCastFunction(compositeFunction)
volumeMapper.SetInputConnection(dataImporter.GetOutputPort())
# The class vtkVolume is used to pair the preaviusly declared volume as
#well as the properties to be used when rendering that volume.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)
# With almost everything else ready, its time to initialize the renderer and window,
# as well as creating a method for exiting the application
renderer = vtk.vtkRenderer()
renderWin = vtk.vtkRenderWindow()
renderWin.AddRenderer(renderer)
renderInteractor = vtk.vtkRenderWindowInteractor()
renderInteractor.SetRenderWindow(renderWin)
# We add the volume to the renderer ...
renderer.AddVolume(volume)
# ... set background color to white ...
renderer.SetBackground(1, 1, 1)
# ... and set window size.
renderWin.SetSize(550, 550)
renderWin.SetMultiSamples(4)
# A simple function to be called when the user decides to quit the application.
def exitCheck(obj, event):
if obj.GetEventPending() != 0:
obj.SetAbortRender(1)
# Tell the application to use the function as an exit check.
renderWin.AddObserver("AbortCheckEvent", exitCheck)
#to auit, press q
renderInteractor.Initialize()
# Because nothing will be rendered without any input, we order the first
# render manually before control is handed over to the main-loop.
renderWin.Render()
renderInteractor.Start()
If you are ok with a solution not using VTK, you could use Matplotlib imshow and interactive navigation with keys.
This tutorial shows how:
https://www.datacamp.com/community/tutorials/matplotlib-3d-volumetric-data
https://github.com/jni/mpl-volume-viewer
and here an implementation for viewing RTdose files:
https://github.com/pydicom/contrib-pydicom/pull/19
See also:
https://github.com/napari/napari

Categories

Resources