Create ImageData

I’m writing a filter that creates a 2D ImageData based on a 3D ImageData input. It seems to be working correctly, but the new structure won’t render as a surface. It looks correct as Gaussian Points.

I believe I simply haven’t finished creating the new structure, but I’m not sure what is missing. The following works as a programmable filter with the Wavelet source, to show what I mean.

from vtk.util.numpy_support import vtk_to_numpy, numpy_to_vtk
nx, ny, nz = inputs[0].GetDimensions()
dx, dy, dz = inputs[0].GetSpacing()
integrand = vtk_to_numpy(inputs[0].PointData['RTData']).reshape(nz, ny, nx)
out_numpy = numpy.add.reduce(integrand, axis=0, keepdims=True)*dz
out_vtk = numpy_to_vtk(out_numpy.flatten(), deep=1)
out = self.GetOutput()
out.SetDimensions(nx, ny, 1)

the missing part was the RequestInformationScript where the extents needs to be set. I also streamlined the data access of your numpy arrays since the PointData dictionnary gives direct access to them. (2.9 KB)

1 Like

When I copy the RequestInformation script into my pipeline, it works on my data. Unfortunately, it fails on reload, with the upstream pipeline object missing all of its Point and Cell Data fields. The same behavior happens when using the simpler version from: Python Programmable Filter - KitwarePublic (

pdi = self.GetInput()
exts = pdi.GetExtent()[:4]+(0,0) 
util.SetOutputWholeExtent(self, exts)```

Does anyone know how to resolve this issue? I am able to use the Slice representation as a workaround, but I would like to know how to create this object cleanly and correctly, especially since Slice doesn’t work once I convert the Image to a Structured Grid.

I think that I’ve figured it out. The answer was very close to what @jfavre suggested, and he correctly diagnosed the problem.

The extents of the data need to be set in the RequestInformationScript, like this:

outInfo = executive.GetOutputInformation(0)
inInfo = executive.GetInputInformation(0,0)
exts = inInfo.Get(executive.WHOLE_EXTENT())
outInfo.Set(executive.WHOLE_EXTENT(), *exts[:4],0,0)

The key difference is that the extents of the input must be obtained from the executive, rather than from the input data using e.g. inputs[0] or self.GetInput(). I think that this is because the input data object is empty the first time this filter is called. It’s easy to miss in development, because at that point the data object is cached from earlier invocations.