-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathiviewer.py
164 lines (128 loc) · 5.32 KB
/
iviewer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import sys
import vtk
from PySide2 import QtCore, QtWidgets
from ccpi.viewer import viewer2D, viewer3D
from ccpi.viewer.QCILViewerWidget import QCILViewerWidget
import ccpi.viewer.viewerLinker as vlink
from ccpi.viewer.utils.conversion import Converter
import numpy as np
from ccpi.viewer.utils import example_data
class SingleViewerCenterWidget(QtWidgets.QMainWindow):
def __init__(self, parent=None, viewer=viewer2D):
QtWidgets.QMainWindow.__init__(self, parent)
self.frame = QCILViewerWidget(parent, viewer=viewer, shape=(600, 600))
if viewer == viewer3D:
self.frame.viewer.setVolumeRenderOpacityMethod('scalar')
self.setCentralWidget(self.frame)
self.show()
def set_input(self, data):
self.frame.viewer.setInputData(data)
class TwoLinkedViewersCenterWidget(QtWidgets.QMainWindow):
def __init__(self, parent=None, viewer1='2D', viewer2='2D'):
QtWidgets.QMainWindow.__init__(self, parent)
#self.resize(800,600)
styles = []
viewers = []
for viewer in [viewer1, viewer2]:
if viewer == '2D':
styles.append(vlink.Linked2DInteractorStyle)
elif viewer == '3D':
styles.append(vlink.Linked3DInteractorStyle)
viewers.append(eval('viewer' + viewer))
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()
self.linker.enable()
layout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight)
layout.addWidget(self.frame1)
layout.addWidget(self.frame2)
cw = QtWidgets.QWidget()
cw.setLayout(layout)
self.setCentralWidget(cw)
self.central_widget = cw
self.show()
def linkedViewersSetup(self):
v1 = self.frame1.viewer
v2 = self.frame2.viewer
self.linker = vlink.ViewerLinker(v1, v2)
self.linker.setLinkPan(True)
self.linker.setLinkZoom(True)
self.linker.setLinkWindowLevel(True)
self.linker.setLinkSlice(True)
def set_input(self, data1, data2):
self.frame1.viewer.setInputData(data1)
self.frame2.viewer.setInputData(data2)
class iviewer(object):
'''
a Qt interactive viewer that can be used as plotter2D with one single dataset
Parameters
----------
data: vtkImageData
image to be displayed
moredata: vtkImageData, optional
extra image to be displayed
viewer1: string - '2D' or '3D'
the type of viewer to display the first image on
viewer2: string - '2D' or '3D', optional
the type of viewer to display the second image on (if present)
'''
def __init__(self, data, *moredata, **kwargs):
'''Creator'''
app = QtWidgets.QApplication(sys.argv)
self.app = app
self.setUp(data, *moredata, **kwargs)
self.show()
def setUp(self, data, *moredata, **kwargs):
if len(moredata) == 0:
# can change the behaviour by setting which viewer you want
# between viewer2D and viewer3D
viewer_type = kwargs.get('viewer1', '2D')
if viewer_type == '2D':
viewer = viewer2D
elif viewer_type == '3D':
viewer = viewer3D
window = SingleViewerCenterWidget(viewer=viewer)
window.set_input(self.convert_to_vtkImage(data))
else:
viewer1 = kwargs.get('viewer1', '2D')
viewer2 = kwargs.get('viewer2', '2D')
window = TwoLinkedViewersCenterWidget(viewer1=viewer1, viewer2=viewer2)
window.set_input(self.convert_to_vtkImage(data), self.convert_to_vtkImage(moredata[0]))
viewer_type = None
self.viewer1_type = viewer1
self.viewer2_type = viewer2
self.window = window
self.viewer_type = viewer_type
self.has_run = None
def show(self):
if self.has_run is None:
self.has_run = self.app.exec_()
else:
print('No instance can be run interactively again. Delete and re-instantiate.')
def __del__(self):
'''destructor'''
self.app.exit()
def convert_to_vtkImage(self, data):
'''convert the data to vtkImageData for the viewer'''
if isinstance(data, vtk.vtkImageData):
vtkImage = data
elif isinstance(data, np.ndarray):
vtkImage = Converter.numpy2vtkImage(data)
elif hasattr(data, 'as_array'):
# this makes it likely it is a CIL/SIRF DataContainer
# currently this will only deal with the actual data
# but it will parse the metadata in future
return self.convert_to_vtkImage(data.as_array())
return vtkImage
if __name__ == "__main__":
err = vtk.vtkFileOutputWindow()
err.SetFileName("viewer.log")
vtk.vtkOutputWindow.SetInstance(err)
data = example_data.HEAD.get()
iviewer(data, data, viewer1='2D', viewer2='3D')
# To use your own metaimage file, uncomment:
# reader = vtk.vtkMetaImageReader()
# reader.SetFileName('head.mha')
# reader.Update()
#iviewer(reader.GetOutput(), reader.GetOutput(), viewer1='2D', viewer2='3D')