Skip to content

Commit

Permalink
Fix error when visualising 2D image (#439)
Browse files Browse the repository at this point in the history
- Edits the `numpy2vtkImage` converter to delete the extra array which causes the error.
- Adds argument to the calls of `QCILViewerWidget`.
- Adds example to check where the error is raised.
  • Loading branch information
DanicaSTFC authored Oct 8, 2024
1 parent 44c554f commit ab03bd0
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Enhancements:
- Adds methods to CILviewer and CILviewer2D #425

Bugfix:
- Fix error when visualising 2D images #439
- Hides the slider when one image dimension is 1 #432
- Differentiate 3D and 2D images in the converter `numpy2vtkImage` #437
- Edit slider min value #420
Expand Down
6 changes: 3 additions & 3 deletions Wrappers/Python/ccpi/viewer/iviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class SingleViewerCenterWidget(QtWidgets.QMainWindow):
def __init__(self, parent=None, viewer=viewer2D):
QtWidgets.QMainWindow.__init__(self, parent)

self.frame = QCILViewerWidget(viewer=viewer, shape=(600, 600))
self.frame = QCILViewerWidget(parent, viewer=viewer, shape=(600, 600))

if viewer == viewer3D:
self.frame.viewer.setVolumeRenderOpacityMethod('scalar')
Expand All @@ -41,8 +41,8 @@ def __init__(self, parent=None, viewer1='2D', viewer2='2D'):
elif viewer == '3D':
styles.append(vlink.Linked3DInteractorStyle)
viewers.append(eval('viewer' + viewer))
self.frame1 = QCILViewerWidget(viewer=viewers[0], shape=(600, 600), interactorStyle=styles[0])
self.frame2 = QCILViewerWidget(viewer=viewers[1], shape=(600, 600), interactorStyle=styles[1])
self.frame1 = QCILViewerWidget(parent, viewer=viewers[0], shape=(600, 600), interactorStyle=styles[0])
self.frame2 = QCILViewerWidget(parent, viewer=viewers[1], shape=(600, 600), interactorStyle=styles[1])

# Initially link viewers
self.linkedViewersSetup()
Expand Down
2 changes: 1 addition & 1 deletion Wrappers/Python/ccpi/viewer/standalone_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,4 @@ def main():


if __name__ == '__main__':
main()
main()
2 changes: 0 additions & 2 deletions Wrappers/Python/ccpi/viewer/ui/main_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import sys
from functools import partial
from pathlib import Path

import ccpi.viewer.viewerLinker as vlink
import vtk
from ccpi.viewer import CILViewer2D, CILViewer
Expand Down Expand Up @@ -381,7 +380,6 @@ def updateViewerCoordsDockWidgetWithCoords(self, reader=None):
The reader used to read the image. This contains some extra info about the
original image file.
'''

viewer = self.viewer_coords_dock.viewers[0]

if not isinstance(viewer, (CILViewer2D, CILViewer)):
Expand Down
35 changes: 23 additions & 12 deletions Wrappers/Python/ccpi/viewer/utils/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,24 +90,31 @@ class Converter(object):

@staticmethod
def numpy2vtkImage(nparray, spacing=(1., 1., 1.), origin=(0, 0, 0), deep=0, output=None):
"""The method converts a numpy array to a vtk image.
The vtk extent is set and needs to differentiate between 3D and 2D images."""
"""
The method converts a numpy array to a vtk image.
Raises an error if the dimension of the image is not 2 or 3.
The array is flattened in the correct order, either fortran or C.
The vtk extent is set and needs to differentiate between 3D and 2D images.
Creates a vtkImageData if `output` is None, otherwise uses the provided empty output.
Adds the vtkarray to the image's point data. If an array is already present, it removes it."""

shape = numpy.shape(nparray)
if (nparray.flags["FNC"]):
num_dims = len(shape)
if num_dims not in [2, 3]:
raise ValueError("Only 2D or 3D numpy arrays are supported.")

if nparray.flags["FNC"]:
order = "F"
i = 0
k = len(shape) - 1
i, k = 0, num_dims - 1
else:
order = "C"
i = len(shape) - 1
k = 0
i, k = num_dims - 1, 0

nparray = nparray.ravel(order)
vtkarray = numpy_support.numpy_to_vtk(num_array=nparray,
deep=deep,
array_type=numpy_support.get_vtk_array_type(nparray.dtype))
vtkarray.SetName('vtkarray')

if output is None:
img_data = vtk.vtkImageData()
Expand All @@ -117,12 +124,16 @@ def numpy2vtkImage(nparray, spacing=(1., 1., 1.), origin=(0, 0, 0), deep=0, outp
else:
img_data = output

img_data.GetPointData().AddArray(vtkarray)
if len(shape) == 3:
point_data = img_data.GetPointData()
while point_data.GetNumberOfArrays() > 0:
point_data.RemoveArray(0)
vtkarray.SetName('ImageScalars')
point_data.AddArray(vtkarray)
img_data.GetPointData().SetScalars(vtkarray)
if num_dims == 3:
img_data.SetExtent(0, shape[i] - 1, 0, shape[1] - 1, 0, shape[k] - 1)
elif len(shape) == 2:
elif num_dims == 2:
img_data.SetExtent(0, shape[i] - 1, 0, shape[k] - 1, 0, 0)
img_data.GetPointData().SetActiveScalars('vtkarray')
img_data.SetOrigin(origin)
img_data.SetSpacing(spacing)

Expand Down
14 changes: 14 additions & 0 deletions Wrappers/Python/examples/2Dimage_reading.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from ccpi.viewer.CILViewer2D import CILViewer2D
import vtk

# This example imports a 2D tiff image and tests the 2D viewer
DATASET_TO_READ = [path] # insert path here
if DATASET_TO_READ is not None:
reader = vtk.vtkTIFFReader()
reader.SetFileName(DATASET_TO_READ)
reader.Update()

v = CILViewer2D()
print(reader.GetOutput())
v.setInputData(reader.GetOutput())
v.startRenderLoop()
3 changes: 2 additions & 1 deletion Wrappers/Python/examples/FourDockableLinkedViewerWidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ def __init__(self, parent=None, reader=None):
#self.resize(800,600)

# create the dockable widgets with the viewer inside
self.v00 = QCILDockableWidget(viewer=viewer2D,
self.v00 = QCILDockableWidget(parent,
viewer=viewer2D,
shape=(600, 600),
title="X",
interactorStyle=vlink.Linked2DInteractorStyle)
Expand Down
2 changes: 1 addition & 1 deletion Wrappers/Python/examples/SingleViewerCentralWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SingleViewerCenterWidget(QtWidgets.QMainWindow):
def __init__(self, parent=None, viewer=viewer2D):
QtWidgets.QMainWindow.__init__(self, parent)

self.frame = QCILViewerWidget(viewer=viewer, shape=(600, 600))
self.frame = QCILViewerWidget(parent, viewer=viewer, shape=(600, 600))

head = example_data.HEAD.get()

Expand Down
2 changes: 1 addition & 1 deletion Wrappers/Python/examples/SingleViewerCentralWidget2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SingleViewerCenterWidget(QtWidgets.QMainWindow):
def __init__(self, parent=None, viewer=viewer2D):
QtWidgets.QMainWindow.__init__(self, parent)
self.setGeometry(450, 250, 1000, 1000)
self.frame = QCILViewerWidget(viewer=viewer, shape=(2000, 2000))
self.frame = QCILViewerWidget(parent, viewer=viewer, shape=(2000, 2000))

head = example_data.HEAD.get()

Expand Down
10 changes: 8 additions & 2 deletions Wrappers/Python/examples/TwoLinkedViewersCentralWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
#self.resize(800,600)

self.frame1 = QCILViewerWidget(viewer=viewer2D, shape=(600, 600), interactorStyle=vlink.Linked2DInteractorStyle)
self.frame2 = QCILViewerWidget(viewer=viewer3D, shape=(600, 600), interactorStyle=vlink.Linked3DInteractorStyle)
self.frame1 = QCILViewerWidget(parent,
viewer=viewer2D,
shape=(600, 600),
interactorStyle=vlink.Linked2DInteractorStyle)
self.frame2 = QCILViewerWidget(parent,
viewer=viewer3D,
shape=(600, 600),
interactorStyle=vlink.Linked3DInteractorStyle)

head = example_data.HEAD.get()

Expand Down
2 changes: 1 addition & 1 deletion Wrappers/Python/examples/opacity_in_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class OpacityViewerWidget(SingleViewerCenterWidget):
def __init__(self, parent=None, viewer=viewer3D):
SingleViewerCenterWidget.__init__(self, parent)

self.frame = QCILViewerWidget(viewer=viewer, shape=(600, 600))
self.frame = QCILViewerWidget(parent, viewer=viewer, shape=(600, 600))

self.setCentralWidget(self.frame)

Expand Down

0 comments on commit ab03bd0

Please sign in to comment.