#!/usr/bin/env python # This example demonstrates the use of fields and use of # vtkProgrammableDataObjectSource. It creates fields the hard way (as # compared to reading a vtk field file), but shows you how to # interface to your own raw data. import os import re import vtk from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() xAxis = "INTEREST_RATE" yAxis = "MONTHLY_PAYMENT" zAxis = "MONTHLY_INCOME" scalar = "TIME_LATE" def getNumberFromLine(line): patn = re.compile('[-+]{0,1}[\d.]+e?[-+\d]*', re.M) val = patn.findall(line) ret = [] for i in val: ret.append(float(i)) return ret # Parse an ASCII file and manually create a field. Then construct a # dataset from the field. dos = vtk.vtkProgrammableDataObjectSource() # First define the function that will parse the data. def parseFile(): global VTK_DATA_ROOT, dos # Use Python to read an ASCII file file = open(os.path.join(VTK_DATA_ROOT, "Data/financial.txt"), "r") line = file.readline() numPts = int(getNumberFromLine(line)[0]) numLines = (numPts - 1)/8 # Get the data object's field data and allocate # room for 4, fields fieldData = dos.GetOutput().GetFieldData() fieldData.AllocateArrays(4) # read TIME_LATE - dependent variable # search the file until an array called TIME_LATE is found while file.readline()[:9] != "TIME_LATE": pass # Create the corresponding float array timeLate = vtk.vtkFloatArray() timeLate.SetName("TIME_LATE") # Read the values for i in range(0, numLines): val = getNumberFromLine(file.readline()) for j in range(0, 8): timeLate.InsertNextValue(val[j]) # Add the array fieldData.AddArray(timeLate) # MONTHLY_PAYMENT - independent variable while file.readline()[:15] != "MONTHLY_PAYMENT": pass monthlyPayment = vtk.vtkFloatArray() monthlyPayment.SetName("MONTHLY_PAYMENT") for i in range(0, numLines): val = getNumberFromLine(file.readline()) for j in range(0, 8): monthlyPayment.InsertNextValue(val[j]) fieldData.AddArray(monthlyPayment) # UNPAID_PRINCIPLE - skip while file.readline()[:16] != "UNPAID_PRINCIPLE": pass for i in range(0, numLines): file.readline() # LOAN_AMOUNT - skip while file.readline()[:11] != "LOAN_AMOUNT": pass for i in range(0, numLines): file.readline() # INTEREST_RATE - independent variable while file.readline()[:13] != "INTEREST_RATE": pass interestRate = vtk.vtkFloatArray() interestRate.SetName("INTEREST_RATE") for i in range(0, numLines): val = getNumberFromLine(file.readline()) for j in range(0, 8): interestRate.InsertNextValue(val[j]) fieldData.AddArray(interestRate) # MONTHLY_INCOME - independent variable while file.readline()[:14] != "MONTHLY_INCOME": pass monthlyIncome = vtk.vtkFloatArray() monthlyIncome.SetName("MONTHLY_INCOME") for i in range(0, numLines): val = getNumberFromLine(file.readline()) for j in range(0, 8): monthlyIncome.InsertNextValue(val[j]) fieldData.AddArray(monthlyIncome) # Arrange to call the parsing function when the programmable data # source is executed. dos.SetExecuteMethod(parseFile) # Create the dataset. # DataObjectToDataSetFilter can create geometry using fields from # DataObject's FieldData do2ds = vtk.vtkDataObjectToDataSetFilter() do2ds.SetInputConnection(dos.GetOutputPort()) # We are generating polygonal data do2ds.SetDataSetTypeToPolyData() do2ds.DefaultNormalizeOn() # All we need is points. Assign them. do2ds.SetPointComponent(0, xAxis, 0) do2ds.SetPointComponent(1, yAxis, 0) do2ds.SetPointComponent(2, zAxis, 0) # RearrangeFields is used to move fields between DataObject's # FieldData, PointData and CellData. rf = vtk.vtkRearrangeFields() rf.SetInputConnection(do2ds.GetOutputPort()) # Add an operation to "move TIME_LATE from DataObject's FieldData to # PointData" rf.AddOperation("MOVE", scalar, "DATA_OBJECT", "POINT_DATA") # Force the filter to execute. This is need to force the pipeline # to execute so that we can find the range of the array TIME_LATE rf.Update() # Set max to the second (GetRange returns [min,max]) of the "range of the # array called scalar in the PointData of the output of rf" max = rf.GetOutput().GetPointData().GetArray(scalar).GetRange()[1] # Use an ArrayCalculator to normalize TIME_LATE calc = vtk.vtkArrayCalculator() calc.SetInputConnection(rf.GetOutputPort()) # Working on point data calc.SetAttributeModeToUsePointData() # Map scalar to s. When setting function, we can use s to # represent the array scalar (TIME_LATE) calc.AddScalarVariable("s", scalar, 0) # Divide scalar by max (applies division to all components of the array) calc.SetFunction("s / %f"%max) # The output array will be called resArray calc.SetResultArrayName("resArray") # Use AssignAttribute to make resArray the active scalar field aa = vtk.vtkAssignAttribute() aa.SetInputConnection(calc.GetOutputPort()) aa.Assign("resArray", "SCALARS", "POINT_DATA") aa.Update() # construct pipeline for original population # GaussianSplatter -> Contour -> Mapper -> Actor popSplatter = vtk.vtkGaussianSplatter() popSplatter.SetInputConnection(aa.GetOutputPort()) popSplatter.SetSampleDimensions(50, 50, 50) popSplatter.SetRadius(0.05) popSplatter.ScalarWarpingOff() popSurface = vtk.vtkContourFilter() popSurface.SetInputConnection(popSplatter.GetOutputPort()) popSurface.SetValue(0, 0.01) popMapper = vtk.vtkPolyDataMapper() popMapper.SetInputConnection(popSurface.GetOutputPort()) popMapper.ScalarVisibilityOff() popActor = vtk.vtkActor() popActor.SetMapper(popMapper) popActor.GetProperty().SetOpacity(0.3) popActor.GetProperty().SetColor(.9, .9, .9) # This is for decoration only. def CreateAxes(): global xAxis, yAxis, zAxis, popSplatter # Create axes. popSplatter.Update() bounds = popSplatter.GetOutput().GetBounds() axes = vtk.vtkAxes() axes.SetOrigin(bounds[0], bounds[2], bounds[4]) axes.SetScaleFactor(popSplatter.GetOutput().GetLength()/5.0) axesTubes = vtk.vtkTubeFilter() axesTubes.SetInputConnection(axes.GetOutputPort()) axesTubes.SetRadius(axes.GetScaleFactor()/25.0) axesTubes.SetNumberOfSides(6) axesMapper = vtk.vtkPolyDataMapper() axesMapper.SetInputConnection(axesTubes.GetOutputPort()) axesActor = vtk.vtkActor() axesActor.SetMapper(axesMapper) # Label the axes. XText = vtk.vtkVectorText() XText.SetText(xAxis) XTextMapper = vtk.vtkPolyDataMapper() XTextMapper.SetInputConnection(XText.GetOutputPort()) XActor = vtk.vtkFollower() XActor.SetMapper(XTextMapper) XActor.SetScale(0.02, .02, .02) XActor.SetPosition(0.35, -0.05, -0.05) XActor.GetProperty().SetColor(0, 0, 0) YText = vtk.vtkVectorText() YText.SetText(yAxis) YTextMapper = vtk.vtkPolyDataMapper() YTextMapper.SetInputConnection(YText.GetOutputPort()) YActor = vtk.vtkFollower() YActor.SetMapper(YTextMapper) YActor.SetScale(0.02, .02, .02) YActor.SetPosition(-0.05, 0.35, -0.05) YActor.GetProperty().SetColor(0, 0, 0) ZText = vtk.vtkVectorText() ZText.SetText(zAxis) ZTextMapper = vtk.vtkPolyDataMapper() ZTextMapper.SetInputConnection(ZText.GetOutputPort()) ZActor = vtk.vtkFollower() ZActor.SetMapper(ZTextMapper) ZActor.SetScale(0.02, .02, .02) ZActor.SetPosition(-0.05, -0.05, 0.35) ZActor.GetProperty().SetColor(0, 0, 0) return axesActor, XActor, YActor, ZActor axesActor, XActor, YActor, ZActor = CreateAxes() # Create the render window, renderer, interactor ren = vtk.vtkRenderer() renWin = vtk.vtkRenderWindow() renWin.AddRenderer(ren) renWin.SetWindowName("vtk - Field Data") renWin.SetSize(500, 500) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) # Add the actors to the renderer, set the background and size ren.AddActor(axesActor) ren.AddActor(XActor) ren.AddActor(YActor) ren.AddActor(ZActor) ren.AddActor(popActor) ren.SetBackground(1, 1, 1) # Set the default camera position camera = vtk.vtkCamera() camera.SetClippingRange(.274, 13.72) camera.SetFocalPoint(0.433816, 0.333131, 0.449) camera.SetPosition(-1.96987, 1.15145, 1.49053) camera.SetViewUp(0.378927, 0.911821, 0.158107) ren.SetActiveCamera(camera) # Assign the camera to the followers. XActor.SetCamera(camera) YActor.SetCamera(camera) ZActor.SetCamera(camera) iren.Initialize() renWin.Render() iren.Start()