I am visualising multiple outputs in the same view depending on choices by the user (i.e. highlighting points on top of glyphs etc).
However, I am finding that as I add additional glyphs the colours of other sources change. This seems to only occur when you update the geometries of the view.
I have written a small example below.
Class to create the glyphs
Can either take in inputs as polydata
, with the associated scalars, or as data points which are coloured manually
import vtk
class spherePipeline:
def __init__(self):
self.sphereSrc = vtk.vtkSphereSource()
self.sphereSrc.SetRadius(0.5)
self.glyphs = vtk.vtkGlyph3D()
self.glyphs.ScalingOff()
self.glyphs.SetColorModeToColorByScalar()
self.glyphs.SetSourceConnection(self.sphereSrc.GetOutputPort())
def setInput(self, data):
self.glyphs.SetInputData(data)
def setInputPoints(self, pts):
# Set the data
self.dataPoints = vtk.vtkPolyData()
pd = vtk.vtkPoints()
for pt in pts:
pd.InsertNextPoint(pt[0], pt[1], pt[2])
self.dataPoints.SetPoints(pd)
def setPointColour(self, colorRGB):
# Colour the data
color = vtk.vtkUnsignedCharArray()
color.SetName("colors")
color.SetNumberOfComponents(3)
for i in range(3):
color.InsertTypedTuple(i, colorRGB)
self.dataPoints.GetPointData().SetScalars(color)
self.dataPoints.GetPointData().SetActiveScalars('colors')
self.glyphs.SetInputData(self.dataPoints)
def getGeometry(self):
self.glyphs.Update()
return self.glyphs.GetOutput()
Create instances of the class and pass in POINT data and colour the points
points1 = spherePipeline()
points2 = spherePipeline()
points3 = spherePipeline()
points1.setInputPoints(pts=[[0,0,0], [1,0,0], [2,0,0]])
points2.setInputPoints(pts=[[0,1,0], [1,1,0], [2,1,0]])
points3.setInputPoints(pts=[[0,2,0], [1,2,0], [2,2,0]])
points1.setPointColour(colorRGB=[255,0,0])
points2.setPointColour(colorRGB=[0,255,0])
points3.setPointColour(colorRGB=[0,0,255])
Show the geometries in the viewer
import itkwidgets
View = itkwidgets.view(geometries=None, background=[0.0, 0.0, 0.0])
View.geometries = [points1.getGeometry(), points2.getGeometry(), points3.getGeometry()]
View
Viewer Output: As Expected
Create Polydata (data & scalar) to be passed as input to new glyph
data = np.array([[0,3,0], [1,3,0], [2,3,0]])
scalarName = 'test'
scalars = np.array(['1','2','3'])
def convertToPolydata(data, scalarName, scalars):
pointData = vtk.vtkPoints()
for ptId in range(data.shape[0]):
dataPt = data[ptId]
toPad = 3 - data.shape[1]
if toPad > 0:
embedPt = np.pad(dataPt, (0,toPad))
pointData.InsertNextPoint(dataPt[0], dataPt[1], dataPt[2])
polydata = vtk.vtkPolyData()
polydata.SetPoints(pointData)
scalarAr = vtk.vtkFloatArray()
scalarAr.SetName(scalarName)
scalarAr.SetNumberOfValues(len(scalars))
ptId = 0
if not isinstance(scalars[0], np.ndarray):
newArray = np.unique(scalars, return_inverse=True)[1]
for val in newArray:
scalarAr.SetValue(ptId, float(val))
ptId += 1
else:
for val in scalars:
scalarAr.SetValue(ptId, float(val))
ptId += 1
polydata.GetPointData().AddArray(scalarAr)
polydata.GetPointData().SetActiveScalars(scalarName)
return polydata
polydata = convertToPolydata(data, scalarName, scalars)
Create instances of the class and pass in POLYDATA (points to be coloured by scalars)
data1 = spherePipeline()
data1.setInput(polydata)
Show the geometries in the viewer
View.geometries = [data1.getGeometry(), points1.getGeometry(), points2.getGeometry(), points3.getGeometry()]
View
Viewer Output:
Note that the Blue glyphs have changed colour!
NOTE: If I create a new Viewer (i.e.
itkwidgets.view(geometries=[data1.getGeometry(), points1.getGeometry(), points2.getGeometry(), points3.getGeometry()], background=[0.0, 0.0, 0.0])
the colours are presented correctly.