Skip to content
Snippets Groups Projects
Commit ec182bc3 authored by Joshua Steer's avatar Joshua Steer
Browse files

Updated qt/vtk interface so all works off single vtk renWin class, involves...

Updated qt/vtk interface so all works off single vtk renWin class, involves changes to GUI and ampVis. More documentation in core
parent 268662df
Branches
No related tags found
No related merge requests found
...@@ -18,6 +18,7 @@ class AmpScanGUI(QMainWindow): ...@@ -18,6 +18,7 @@ class AmpScanGUI(QMainWindow):
def __init__(self, parent = None): def __init__(self, parent = None):
super(AmpScanGUI, self).__init__() super(AmpScanGUI, self).__init__()
self.vtkWidget = qtVtkWindow() self.vtkWidget = qtVtkWindow()
self.renWin = self.vtkWidget._RenderWindow
self.mainWidget = QWidget() self.mainWidget = QWidget()
self.AmpObj = None self.AmpObj = None
# self.CMap = np.array([[212.0, 221.0, 225.0], # self.CMap = np.array([[212.0, 221.0, 225.0],
...@@ -36,13 +37,13 @@ class AmpScanGUI(QMainWindow): ...@@ -36,13 +37,13 @@ class AmpScanGUI(QMainWindow):
self.fname = QFileDialog.getOpenFileName(self, 'Open file', self.fname = QFileDialog.getOpenFileName(self, 'Open file',
filter="Meshes (*.stl)") filter="Meshes (*.stl)")
if self.AmpObj is not None: if self.AmpObj is not None:
self.vtkWidget.renderActors(self.AmpObj.actors, []) self.renWin.renderActors(self.AmpObj.actors, [])
self.AmpObj = AmpObject(self.fname[0], 'limb') self.AmpObj = AmpObject(self.fname[0], 'limb')
self.AmpObj.addActor(stype='limb') self.AmpObj.addActor(stype='limb')
self.AmpObj.lp_smooth(stype='limb') self.AmpObj.lp_smooth(stype='limb')
self.vtkWidget.setnumViewports(1) self.renWin.setnumViewports(1)
self.vtkWidget.setProjection() self.renWin.setProjection()
self.vtkWidget.renderActors(self.AmpObj.actors, ['limb',]) self.renWin.renderActors(self.AmpObj.actors, ['limb',])
def chooseSocket(self): def chooseSocket(self):
self.sockfname = QFileDialog.getOpenFileName(self, 'Open file', self.sockfname = QFileDialog.getOpenFileName(self, 'Open file',
...@@ -52,17 +53,17 @@ class AmpScanGUI(QMainWindow): ...@@ -52,17 +53,17 @@ class AmpScanGUI(QMainWindow):
self.AmpObj.lp_smooth(stype='socket') self.AmpObj.lp_smooth(stype='socket')
def align(self): def align(self):
self.vtkWidget.setnumViewports(2) self.renWin.setnumViewports(2)
self.vtkWidget.setView(view=[-1, 0, 0], viewport=1) self.renWin.setView(view=[-1, 0, 0], viewport=1)
self.vtkWidget.setProjection(True, 0) self.renWin.setProjection(True, 0)
self.vtkWidget.setProjection(True, 1) self.renWin.setProjection(True, 1)
# self.vtkWidget.render(self.AmpObj.actors, dispActors=['limb',]) # self.renWin.render(self.AmpObj.actors, dispActors=['limb',])
# self.vtkWidget.render(self.AmpObj.actors, dispActors=['socket',], # self.renWin.render(self.AmpObj.actors, dispActors=['socket',],
# viewport=1) # viewport=1)
self.vtkWidget.renderActors(self.AmpObj.actors, self.renWin.renderActors(self.AmpObj.actors,
dispActors=['limb', 'socket'], dispActors=['limb', 'socket'],
viewport=0) viewport=0)
self.vtkWidget.renderActors(self.AmpObj.actors, self.renWin.renderActors(self.AmpObj.actors,
dispActors=['limb', 'socket'], dispActors=['limb', 'socket'],
viewport=1) viewport=1)
self.AmpObj.actors['limb'].setColor([1.0, 0.0, 0.0]) self.AmpObj.actors['limb'].setColor([1.0, 0.0, 0.0])
...@@ -71,14 +72,14 @@ class AmpScanGUI(QMainWindow): ...@@ -71,14 +72,14 @@ class AmpScanGUI(QMainWindow):
self.AmpObj.actors['socket'].setOpacity(0.5) self.AmpObj.actors['socket'].setOpacity(0.5)
def register(self): def register(self):
self.vtkWidget.setnumViewports(1) self.renWin.setnumViewports(1)
self.vtkWidget.setProjection() self.renWin.setProjection()
self.RegObj = regObject(self.AmpObj) self.RegObj = regObject(self.AmpObj)
self.RegObj.registration(steps=5, baseline='socket', target='limb', self.RegObj.registration(steps=5, baseline='socket', target='limb',
reg = 'reglimb', direct=True) reg = 'reglimb', direct=True)
self.RegObj.addActor(stype='reglimb', CMap=self.AmpObj.CMapN2P) self.RegObj.addActor(stype='reglimb', CMap=self.AmpObj.CMapN2P)
self.vtkWidget.renderActors(self.AmpObj.actors, ['reglimb',], shading=False) self.renWin.renderActors(self.AmpObj.actors, ['reglimb',], shading=False)
self.vtkWidget.setScalarBar(self.AmpObj.actors['reglimb']) self.renWin.setScalarBar(self.AmpObj.actors['reglimb'])
def analyse(self): def analyse(self):
self.RegObj.plot_slices() self.RegObj.plot_slices()
...@@ -86,20 +87,20 @@ class AmpScanGUI(QMainWindow): ...@@ -86,20 +87,20 @@ class AmpScanGUI(QMainWindow):
def chooseFE(self): def chooseFE(self):
FEname = QFileDialog.getOpenFileName(self, 'Open file', FEname = QFileDialog.getOpenFileName(self, 'Open file',
filter="FE results (*.npy)") filter="FE results (*.npy)")
self.vtkWidget.setnumViewports(1) self.renWin.setnumViewports(1)
self.AmpObj.addFE([FEname[0],]) self.AmpObj.addFE([FEname[0],])
self.AmpObj.lp_smooth('FE', n=1) self.AmpObj.lp_smooth('FE', n=1)
self.AmpObj.addActor(stype='FE', CMap=self.AmpObj.CMap02P, bands=5) self.AmpObj.addActor(stype='FE', CMap=self.AmpObj.CMap02P, bands=5)
self.AmpObj.actors['FE'].setScalarRange(smin=0.0, smax=50) self.AmpObj.actors['FE'].setScalarRange(smin=0.0, smax=50)
self.vtkWidget.renderActors(self.AmpObj.actors, ['FE',], shading=True) self.renWin.renderActors(self.AmpObj.actors, ['FE',], shading=True)
self.vtkWidget.setScalarBar(self.AmpObj.actors['FE']) self.renWin.setScalarBar(self.AmpObj.actors['FE'])
def choosePress(self): def choosePress(self):
vName = QFileDialog.getOpenFileName(self, 'Open file', vName = QFileDialog.getOpenFileName(self, 'Open file',
filter="Sensor vertices (*.csv)") filter="Sensor vertices (*.csv)")
pName = QFileDialog.getOpenFileName(self, 'Open file', pName = QFileDialog.getOpenFileName(self, 'Open file',
filter="Sensor pressures (*.csv)") filter="Sensor pressures (*.csv)")
self.vtkWidget.setnumViewports(1) self.renWin.setnumViewports(1)
self.pSense = pressSense() self.pSense = pressSense()
self.pSense.calcFaces(d=5) self.pSense.calcFaces(d=5)
self.pSense.importVert(vName[0]) self.pSense.importVert(vName[0])
...@@ -108,8 +109,8 @@ class AmpScanGUI(QMainWindow): ...@@ -108,8 +109,8 @@ class AmpScanGUI(QMainWindow):
self.AmpObj.actors['antS'] = self.pSense.actors['antS'] self.AmpObj.actors['antS'] = self.pSense.actors['antS']
self.AmpObj.actors['socket'].setColor([1.0, 1.0, 1.0]) self.AmpObj.actors['socket'].setColor([1.0, 1.0, 1.0])
self.AmpObj.actors['socket'].setOpacity(1.0) self.AmpObj.actors['socket'].setOpacity(1.0)
self.vtkWidget.renderActors(self.AmpObj.actors, ['socket', 'antS']) self.renWin.renderActors(self.AmpObj.actors, ['socket', 'antS'])
self.vtkWidget.setScalarBar(self.AmpObj.actors['antS']) self.renWin.setScalarBar(self.AmpObj.actors['antS'])
def createActions(self): def createActions(self):
self.openFile = QAction(QIcon('open.png'), 'Open', self, self.openFile = QAction(QIcon('open.png'), 'Open', self,
......
...@@ -5,13 +5,14 @@ Created on Thu Sep 28 13:19:18 2017 ...@@ -5,13 +5,14 @@ Created on Thu Sep 28 13:19:18 2017
@author: js22g12 @author: js22g12
Functions that deal with the visualisation of the limb and data Functions that deal with the visualisation of the limb and data
Includes interfaces to deal
""" """
import numpy as np import numpy as np
import vtk import vtk
from vtk.util import numpy_support from vtk.util import numpy_support
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from PyQt5.QtWidgets import QWidget
class vtkRender(vtk.vtkRenderer): class vtkRender(vtk.vtkRenderer):
""" """
...@@ -69,17 +70,22 @@ class ampVTK(object): ...@@ -69,17 +70,22 @@ class ampVTK(object):
self.scalar_bar.SetPosition2(0.1, 0.3) self.scalar_bar.SetPosition2(0.1, 0.3)
self.rens[0].AddActor(self.scalar_bar) self.rens[0].AddActor(self.scalar_bar)
def setView(self, view = [0, -1, 0], viewport=0): def setView(self, view = [0, -1, 0], viewport=0):
self.cams[viewport].SetPosition(view[0], view[1], view[2]) self.cams[viewport].SetPosition(view[0], view[1], view[2])
self.cams[viewport].SetViewUp(-0.0, 0.0, 1.0) self.cams[viewport].SetViewUp(-0.0, 0.0, 1.0)
def setBackground(self, color=[0.1, 0.2, 0.4]): def setBackground(self, color=[0.1, 0.2, 0.4]):
"""
Set the background colour of the renderer
"""
for ren in self.rens: for ren in self.rens:
ren.SetBackground(color) ren.SetBackground(color)
def setProjection(self, perspective=False, viewport=0): def setProjection(self, perspective=False, viewport=0):
"""
Set the projection of the camera to either parallel or perspective
"""
self.cams[viewport].SetParallelProjection(perspective) self.cams[viewport].SetParallelProjection(perspective)
...@@ -109,55 +115,6 @@ class ampVTK(object): ...@@ -109,55 +115,6 @@ class ampVTK(object):
# self.rens[viewport].AddActor(self.axes[viewport]) # self.rens[viewport].AddActor(self.axes[viewport])
class qtVtkWindow(QVTKRenderWindowInteractor, ampVTK):
def __init__(self):
super(qtVtkWindow, self).__init__()
self.SetInteractorStyle(self.style)
self.GetRenderWindow().AddRenderer(self.rens[0])
self.iren = self.GetRenderWindow().GetInteractor()
self.iren.Initialize()
def setnumViewports(self, n):
"""
Function to set multiple viewports within the vtkWindow
Parameters
------------
n: int
number of viewports required
"""
dif = n - len(self.rens)
if dif == 0:
return
elif dif < 0:
for ren in self.rens[n:]:
self.GetRenderWindow().RemoveRenderer(ren)
self.rens = self.rens[:n]
elif dif > 0:
for i in range(dif):
self.rens.append(vtkRender())
self.axes.append(vtk.vtkCubeAxesActor())
self.GetRenderWindow().AddRenderer(self.rens[-1])
if len(self.cams) < len(self.rens):
self.cams.append(vtk.vtkCamera())
self.rens[-1].SetActiveCamera(self.cams[len(self.rens)-1])
for i, ren in enumerate(self.rens):
ren.SetViewport(float(i)/n, 0, float(i+1)/n, 1)
self.setBackground()
class vtkRenWin(vtk.vtkRenderWindow, ampVTK):
def __init__(self, winWidth=512, winHeight=512):
super(vtkRenWin, self).__init__()
self.winWidth = winWidth
self.winHeight = winHeight
self.SetSize(self.winWidth, self.winHeight)
self.OffScreenRenderingOn()
self.AddRenderer(self.rens[0])
self.Render()
def setnumViewports(self, n): def setnumViewports(self, n):
""" """
Function to set multiple viewports within the vtkWindow Function to set multiple viewports within the vtkWindow
...@@ -188,11 +145,11 @@ class vtkRenWin(vtk.vtkRenderWindow, ampVTK): ...@@ -188,11 +145,11 @@ class vtkRenWin(vtk.vtkRenderWindow, ampVTK):
def getImage(self): def getImage(self):
self.vtkRGB = vtk.vtkUnsignedCharArray() vtkRGB = vtk.vtkUnsignedCharArray()
self.GetPixelData(0, 0, self.winWidth-1, self.winHeight-1, self.GetPixelData(0, 0, self.winWidth-1, self.winHeight-1,
1, self.vtkRGB) 1, vtkRGB)
self.vtkRGB.Squeeze() vtkRGB.Squeeze()
self.im = np.flipud(np.resize(np.array(self.vtkRGB), self.im = np.flipud(np.resize(np.array(vtkRGB),
[self.winWidth, self.winHeight, 3])) / 255.0 [self.winWidth, self.winHeight, 3])) / 255.0
def getScreenshot(self, fname, mag=10): def getScreenshot(self, fname, mag=10):
...@@ -209,17 +166,54 @@ class vtkRenWin(vtk.vtkRenderWindow, ampVTK): ...@@ -209,17 +166,54 @@ class vtkRenWin(vtk.vtkRenderWindow, ampVTK):
writer.Write() writer.Write()
class vtkRenWin(vtk.vtkRenderWindow, ampVTK):
def __init__(self, qt = True, winWidth=512, winHeight=512):
super(vtkRenWin, self).__init__()
self.AddRenderer(self.rens[0])
if qt is False:
self.winWidth = winWidth
self.winHeight = winHeight
self.SetSize(self.winWidth, self.winHeight)
self.OffScreenRenderingOn()
self.Render()
class qtVtkWindow(QVTKRenderWindowInteractor):
"""
Create a vtk window to be embeded within a qt GUI
Inherites the QVTKRenderWindowInteractor class and the
Fix issue with SetInteractorStyle
"""
def __init__(self):
super(qtVtkWindow, self).__init__(rw=vtkRenWin())
#self.SetInteractorStyle(self.style)
self.iren = self._RenderWindow.GetInteractor()
self.iren.Initialize()
class visMixin(object): class visMixin(object):
"""
Visualisation methods that act upon the AmpObj itself
Methods for generating the custom AmpObj actor to interface with vtk
"""
def genIm(self, actor=['limb'], winWidth=512, winHeight=512, def genIm(self, actor=['limb'], winWidth=512, winHeight=512,
views=[[0, -1, 0]], background=[1.0, 1.0, 1.0], projection=True, views=[[0, -1, 0]], background=[1.0, 1.0, 1.0], projection=True,
shading=True, mag=10, out='im', name='test.tiff'): shading=True, mag=10, out='im', name='test.tiff'):
""" """
Output an image of an actor either as an array or a saved png file
""" """
win = vtkRenWin(winWidth, winHeight) # Generate a renderer window
win = vtkRenWin(False, winWidth, winHeight)
# Set the number of viewports
win.setnumViewports(len(views)) win.setnumViewports(len(views))
# Set the background colour
win.setBackground(background) win.setBackground(background)
# Set camera projection
win.setProjection(projection) win.setProjection(projection)
for i, view in enumerate(views): for i, view in enumerate(views):
win.addAxes(self.actors, color=[0.0, 0.0, 0.0], viewport=i) win.addAxes(self.actors, color=[0.0, 0.0, 0.0], viewport=i)
...@@ -227,8 +221,8 @@ class visMixin(object): ...@@ -227,8 +221,8 @@ class visMixin(object):
win.setProjection(projection, viewport=i) win.setProjection(projection, viewport=i)
win.renderActors(self.actors, actor, viewport=i, shading=shading, zoom=1.3) win.renderActors(self.actors, actor, viewport=i, shading=shading, zoom=1.3)
win.Render() win.Render()
win.getImage()
if out == 'im': if out == 'im':
win.getImage()
return win.im return win.im
elif out == 'fh': elif out == 'fh':
win.getScreenshot(name) win.getScreenshot(name)
...@@ -252,8 +246,6 @@ class visMixin(object): ...@@ -252,8 +246,6 @@ class visMixin(object):
Class that inherits methods from vtk actor Class that inherits methods from vtk actor
Contains functions to set vertices, faces, scalars and color map Contains functions to set vertices, faces, scalars and color map
from numpy arrays from numpy arrays
Add functions to add vert, add faces, cmap and make LUT
""" """
def __init__(self, data, CMap=None, bands=128): def __init__(self, data, CMap=None, bands=128):
......
...@@ -6,8 +6,6 @@ Created on Wed Sep 13 13:54:23 2017 ...@@ -6,8 +6,6 @@ Created on Wed Sep 13 13:54:23 2017
Core functions for the AmpObject Core functions for the AmpObject
Remove pd dependency and instead just use numpy arrays
Requires numpy 1.13 Requires numpy 1.13
...@@ -70,6 +68,14 @@ class AmpObject(alignMixin, trimMixin, smoothMixin, analyseMixin, ...@@ -70,6 +68,14 @@ class AmpObject(alignMixin, trimMixin, smoothMixin, analyseMixin,
raise ValueError('dtype not supported, please choose from ' + raise ValueError('dtype not supported, please choose from ' +
'limb, socket, reglimb, regsocket, MRI or AmpObj') 'limb, socket, reglimb, regsocket, MRI or AmpObj')
def createCMap(self, cmap=None, n = 50):
"""
Function to generate a colormap for the AmpObj
"""
if cmap is None:
cmap = n
def addData(self, Data, stype): def addData(self, Data, stype):
if isinstance(Data, str): if isinstance(Data, str):
...@@ -177,6 +183,9 @@ class AmpObject(alignMixin, trimMixin, smoothMixin, analyseMixin, ...@@ -177,6 +183,9 @@ class AmpObject(alignMixin, trimMixin, smoothMixin, analyseMixin,
data['faceEdges'][eF[~logic], 1] = fInd[~logic] data['faceEdges'][eF[~logic], 1] = fInd[~logic]
def vNorm(self, stype=0): def vNorm(self, stype=0):
"""
Function to compute the vertex normals
"""
if isinstance(stype, int): if isinstance(stype, int):
stype = self.stype[stype] stype = self.stype[stype]
data = getattr(self, stype) data = getattr(self, stype)
......
AmpScan ReadME File
--------------------
Author: Joshua Steer
To install the package, open the cmd prompt and type the following script
J:
cd J:\Shared Resources\AmpScan IfLS Team\100 PYTHON\Code
pip install .
To use the package
import AmpScan
import os
read_filename = '01_PhantomShell_ICEM_3mm.stl'
write_filename = '01_PhantomShell_ICEM_3mm_write.stl'
Data = AmpObject(target, 'limb')
Data.addData(baseline, 'socket')
Data.lp_smooth()
Data.man_rot([5,5,5])
Reg = regObject(Data)
Reg.registration(steps=5, baseline='socket', target='limb', reg = 'reglimb')
Reg.save(saveStr, stype='reglimb')
Reg.plot_slices()
Structure:
AmpScan structure
core.py
class AmpObject(Data, stype)
func addData
func read_stl
func unify_vertices
func computeEdges
func save
func calc_norm
func man_trans
func man_rot
func centre
smooth.py
class smoothMixin
func lp_smooth
autoAlign.py
class alignMixin
func icp
func calcDistError
trim.py
class trimMixin
func planarTrim
analyse.py
class analyseMixin
func plot_slices
func create_slice
func planeEdgeIntersect
ampVis.py
class visMixin
func genIm
func addActor
class ampActor
func setVert
func setFaces
func setRect
func setColor
func setOpacity
func setCMap
class vtkRender
class vtkWindow
func render
func setScalarBar
func setViewports
func addAxes
registration.py
class regObject
func registration
TSBSocketDesign.py
class mplCanvas
class dragSpline
func connect
func on_press
func on_motion
func on_release
func disconnect
func bezierCurve
SocketDesignGUI.py
class GUI
func plotRect
func chooseOpenFile
func createActions
func createMenus
AmpScanGUI
class GUI
func chooseOpenFile
func chooseSocket
func align
func register
func analyse
func createActions
func createMenus
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment