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

Modifications to the AmpScan GUI to better handle AmpObjects

parent 1c76ba7d
No related branches found
No related tags found
No related merge requests found
Pipeline #148 passed
...@@ -6,10 +6,11 @@ Created on Thu Sep 14 13:15:30 2017 ...@@ -6,10 +6,11 @@ Created on Thu Sep 14 13:15:30 2017
""" """
import numpy as np import numpy as np
import vtk
from scipy import spatial from scipy import spatial
from scipy.optimize import minimize from scipy.optimize import minimize
from .core import AmpObject from .core import AmpObject
from .ampVis import vtkRenWin
class align(object): class align(object):
r""" r"""
...@@ -96,16 +97,19 @@ class align(object): ...@@ -96,16 +97,19 @@ class align(object):
def __init__(self, moving, static, method = 'P2P'): def __init__(self, moving, static, method = 'P2P'):
self.m = moving self.m = moving
self.s = static self.s = static
self.icp() if method is not None:
amp = AmpObject() getattr(self, method)()
#self.icp()
#amp = AmpObject()
def icp(): def icp(self):
""" """
Automated alignment function between two meshes Automated alignment function between two meshes
""" """
tTree = spatial.cKDTree(self.baseline.vert) tTree = spatial.cKDTree(self.s.vert)
rot = np.array([0,0,0], dtype=float) rot = np.array([0,0,0], dtype=float)
res = minimize(self.calcDistError, rot, method='BFGS', res = minimize(self.calcDistError, rot, method='BFGS',
options={'gtol':1e-6, 'disp':True}) options={'gtol':1e-6, 'disp':True})
...@@ -132,4 +136,36 @@ class align(object): ...@@ -132,4 +136,36 @@ class align(object):
dist = dist.min(axis=1) dist = dist.min(axis=1)
return dist.sum() return dist.sum()
def display(self):
r"""
Function to display the two aligned meshes in
"""
if not hasattr(self.s, 'actor'):
self.s.addActor()
if not hasattr(self.m, 'actor'):
self.m.addActor()
# Generate a renderer window
win = vtkRenWin()
# Set the number of viewports
win.setnumViewports(1)
# Set the background colour
win.setBackground([1,1,1])
# Set camera projection
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(win)
renderWindowInteractor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
# Set camera projection
win.setView()
self.s.actor.setColor([1.0, 0.0, 0.0])
self.s.actor.setOpacity(0.5)
self.m.actor.setColor([0.0, 0.0, 1.0])
self.m.actor.setOpacity(0.5)
win.renderActors([self.s.actor, self.m.actor], shading=True)
win.Render()
win.rens[0].GetActiveCamera().Azimuth(180)
win.rens[0].GetActiveCamera().SetParallelProjection(True)
win.Render()
return win
...@@ -47,6 +47,7 @@ class vtkRenWin(vtk.vtkRenderWindow): ...@@ -47,6 +47,7 @@ class vtkRenWin(vtk.vtkRenderWindow):
self.rens[viewport].AddActor(actor) self.rens[viewport].AddActor(actor)
self.rens[viewport].ResetCamera() self.rens[viewport].ResetCamera()
self.rens[viewport].GetActiveCamera().Zoom(zoom) self.rens[viewport].GetActiveCamera().Zoom(zoom)
self.Render()
def setScalarBar(self, actor, title=''): def setScalarBar(self, actor, title=''):
""" """
...@@ -261,7 +262,7 @@ class visMixin(object): ...@@ -261,7 +262,7 @@ class visMixin(object):
#self._v = numpy_support.numpy_to_vtk(self.vert, deep=0) #self._v = numpy_support.numpy_to_vtk(self.vert, deep=0)
self.actor.setVert(self.vert) self.actor.setVert(self.vert)
self.actor.setFaces(self.faces) self.actor.setFaces(self.faces)
#self.actor.setNorm() self.actor.setNorm()
# Test if values array is non-zero # Test if values array is non-zero
if self.values.any(): if self.values.any():
self.actor.setValues(self.values) self.actor.setValues(self.values)
......
import AmpScan
import sys import sys
import numpy as np import numpy as np
from vtk.util import numpy_support from vtk.util import numpy_support
from AmpScan.core import AmpObject from AmpScan import AmpObject
from AmpScan.registration import registration from AmpScan.registration import registration
from AmpScan.ampVis import qtVtkWindow from AmpScan.ampVis import qtVtkWindow
from AmpScan.pressSens import pressSense from AmpScan.pressSens import pressSense
...@@ -10,9 +9,9 @@ from PyQt5.QtCore import QPoint, QSize, Qt, QTimer, QRect, pyqtSignal ...@@ -10,9 +9,9 @@ from PyQt5.QtCore import QPoint, QSize, Qt, QTimer, QRect, pyqtSignal
from PyQt5.QtGui import (QColor, QFontMetrics, QImage, QPainter, QIcon, from PyQt5.QtGui import (QColor, QFontMetrics, QImage, QPainter, QIcon,
QOpenGLVersionProfile) QOpenGLVersionProfile)
from PyQt5.QtWidgets import (QAction, QApplication, QGridLayout, from PyQt5.QtWidgets import (QAction, QApplication, QGridLayout,
QMainWindow, QMessageBox, QMainWindow, QMessageBox, QComboBox,
QOpenGLWidget, QFileDialog, QOpenGLWidget, QFileDialog,QLabel,QPushButton,
QSlider, QWidget) QSlider, QWidget, QTableWidget, QTableWidgetItem)
class AmpScanGUI(QMainWindow): class AmpScanGUI(QMainWindow):
...@@ -35,7 +34,8 @@ class AmpScanGUI(QMainWindow): ...@@ -35,7 +34,8 @@ class AmpScanGUI(QMainWindow):
self.renWin = self.vtkWidget._RenderWindow self.renWin = self.vtkWidget._RenderWindow
self.renWin.setBackground() self.renWin.setBackground()
self.mainWidget = QWidget() self.mainWidget = QWidget()
self.AmpObj = None self.files = {}
self.filesDrop = list(self.files.keys())
# self.CMap = np.array([[212.0, 221.0, 225.0], # self.CMap = np.array([[212.0, 221.0, 225.0],
# [31.0, 73.0, 125.0]])/255.0 # [31.0, 73.0, 125.0]])/255.0
self.setCentralWidget(self.mainWidget) self.setCentralWidget(self.mainWidget)
...@@ -47,6 +47,9 @@ class AmpScanGUI(QMainWindow): ...@@ -47,6 +47,9 @@ class AmpScanGUI(QMainWindow):
self.setWindowTitle("AmpScan Visualiser") self.setWindowTitle("AmpScan Visualiser")
self.resize(800, 800) self.resize(800, 800)
self.show() self.show()
self.fileManager = fileManager(self)
self.fileManager.show()
self.fileManager.table.itemChanged.connect(self.display)
def chooseOpenFile(self): def chooseOpenFile(self):
""" """
...@@ -60,68 +63,91 @@ class AmpScanGUI(QMainWindow): ...@@ -60,68 +63,91 @@ class AmpScanGUI(QMainWindow):
@Josh_Steer if no stl is selected then the window crashes! @Josh_Steer if no stl is selected then the window crashes!
""" """
self.fname = QFileDialog.getOpenFileName(self, 'Open file', fname = QFileDialog.getOpenFileName(self, 'Open file',
filter="Meshes (*.stl)") filter="Meshes (*.stl)")
if self.AmpObj is not None: if fname[0] == '':
self.renWin.renderActors([self.AmpObj.actor,]) return
self.AmpObj = AmpObject(self.fname[0], 'limb') name = fname[0][:-4].split('/')[-1]
self.AmpObj.addActor() self.files[name] = AmpObject(fname[0], 'limb')
amp = self.files[name]
amp.addActor()
self.fileManager.addRow(name, amp)
self.display()
self.filesDrop.append(name)
if hasattr(self, 'alCont'):
self.alCont.getNames()
if hasattr(self, 'regCont'):
self.regCont.getNames()
# self.AmpObj.lp_smooth() # self.AmpObj.lp_smooth()
self.renWin.setnumViewports(1)
self.renWin.setProjection()
self.renWin.renderActors([self.AmpObj.actor,])
def chooseSocket(self): def display(self):
""" render = []
Button in GUI. for r in range(self.fileManager.n):
[name, _, color, opacity, display] = self.fileManager.getRow(r)
if display == 2:
render.append(self.files[name].actor)
color = color[1:-1].split(',')
color = [float(c) for c in color]
self.files[name].actor.setColor(color)
self.files[name].actor.setOpacity(float(opacity))
self.renWin.renderActors(render)
"""
self.sockfname = QFileDialog.getOpenFileName(self, 'Open file',
filter="Meshes (*.stl)")
self.socket = AmpObject(self.sockfname[0], stype='socket')
self.socket.addActor()
self.socket.lp_smooth()
def align(self): def align(self):
""" """
Numpy style docstring. Numpy style docstring.
""" """
self.renWin.setnumViewports(2) self.alCont = AlignControls(self.filesDrop, self)
self.renWin.setView(view=[-1, 0, 0], viewport=1) self.alCont.show()
self.renWin.setProjection(True, 0) self.alCont.icp.clicked.connect(self.runICP)
self.renWin.setProjection(True, 1) # self.renWin.setnumViewports(2)
# self.renWin.render(self.AmpObj.actors, dispActors=['limb',]) # self.renWin.setView(view=[-1, 0, 0], viewport=1)
# self.renWin.render(self.AmpObj.actors, dispActors=['socket',], # self.renWin.setProjection(True, 0)
# self.renWin.setProjection(True, 1)
## self.renWin.render(self.AmpObj.actors, dispActors=['limb',])
## self.renWin.render(self.AmpObj.actors, dispActors=['socket',],
## viewport=1)
# self.renWin.renderActors([self.AmpObj.actor, self.socket.actor],
# viewport=0)
# self.renWin.renderActors([self.AmpObj.actor, self.socket.actor],
# viewport=1) # viewport=1)
self.renWin.renderActors([self.AmpObj.actor, self.socket.actor], # self.AmpObj.actor.setColor([1.0, 0.0, 0.0])
viewport=0) # self.AmpObj.actor.setOpacity(0.5)
self.renWin.renderActors([self.AmpObj.actor, self.socket.actor], # self.socket.actor.setColor([0.0, 0.0, 1.0])
viewport=1) # self.socket.actor.setOpacity(0.5)
self.AmpObj.actor.setColor([1.0, 0.0, 0.0])
self.AmpObj.actor.setOpacity(0.5) def runICP(self):
self.socket.actor.setColor([0.0, 0.0, 1.0]) static = str(self.alCont.static.currentText())
self.socket.actor.setOpacity(0.5) moving = str(self.alCont.moving.currentText())
print('Run the ICP code between %s and %s' % (static, moving))
def runRegistration(self):
baseline = str(self.regCont.baseline.currentText())
target = str(self.regCont.target.currentText())
print('Run the Registration code between %s and %s' % (baseline, target))
def register(self): def register(self):
""" """
Numpy style docstring. Numpy style docstring.
""" """
self.regCont = RegistrationControls(self.filesDrop, self)
self.regCont.show()
self.regCont.reg.clicked.connect(self.runRegistration)
self.renWin.setnumViewports(1) # self.renWin.setnumViewports(1)
self.renWin.setProjection() # self.renWin.setProjection()
self.RegObj = registration(self.socket, self.AmpObj) # self.RegObj = registration(self.socket, self.AmpObj)
self.RegObj.addActor(CMap=self.AmpObj.CMapN2P) # self.RegObj.addActor(CMap=self.AmpObj.CMapN2P)
self.renWin.renderActors([self.RegObj.actor,]) # self.renWin.renderActors([self.RegObj.actor,])
self.renWin.setScalarBar(self.RegObj.actor) # self.renWin.setScalarBar(self.RegObj.actor)
def analyse(self): def analyse(self):
""" """
Numpy style docstring. Numpy style docstring.
""" """
#self.RegObj.plot_slices() #self.RegObj.plot_slices()
self.AmpObj.vert[:, 0] *= 2 self.AmpObj.vert[:, 0] *= 2
self.AmpObj.actor.points.Modified() self.AmpObj.actor.points.Modified()
...@@ -173,8 +199,6 @@ class AmpScanGUI(QMainWindow): ...@@ -173,8 +199,6 @@ class AmpScanGUI(QMainWindow):
self.openFile = QAction(QIcon('open.png'), 'Open', self, self.openFile = QAction(QIcon('open.png'), 'Open', self,
shortcut='Ctrl+O', shortcut='Ctrl+O',
triggered=self.chooseOpenFile) triggered=self.chooseOpenFile)
self.openSocket = QAction(QIcon('open.png'), 'Open Socket', self,
triggered=self.chooseSocket)
self.openFE = QAction(QIcon('open.png'), 'Open FE', self, self.openFE = QAction(QIcon('open.png'), 'Open FE', self,
triggered=self.chooseFE) triggered=self.chooseFE)
self.openPress = QAction(QIcon('open.png'), 'Open Press', self, self.openPress = QAction(QIcon('open.png'), 'Open Press', self,
...@@ -195,7 +219,6 @@ class AmpScanGUI(QMainWindow): ...@@ -195,7 +219,6 @@ class AmpScanGUI(QMainWindow):
""" """
self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu = self.menuBar().addMenu("&File")
self.fileMenu.addAction(self.openFile) self.fileMenu.addAction(self.openFile)
self.fileMenu.addAction(self.openSocket)
self.fileMenu.addSeparator() self.fileMenu.addSeparator()
self.fileMenu.addAction(self.exitAct) self.fileMenu.addAction(self.exitAct)
self.alignMenu = self.menuBar().addMenu("&Align") self.alignMenu = self.menuBar().addMenu("&Align")
...@@ -209,6 +232,131 @@ class AmpScanGUI(QMainWindow): ...@@ -209,6 +232,131 @@ class AmpScanGUI(QMainWindow):
self.kineticMenu = self.menuBar().addMenu("&Kinetic Measurements") self.kineticMenu = self.menuBar().addMenu("&Kinetic Measurements")
self.kineticMenu.addAction(self.openPress) self.kineticMenu.addAction(self.openPress)
class fileManager(QMainWindow):
"""
Controls to manage the displayed
Example
-------
Perhaps an example implementation:
>>> from AmpScan.AmpScanGUI import AmpScanGUI
"""
def __init__(self, parent = None):
super(fileManager, self).__init__(parent)
self.main = QWidget()
self.table = QTableWidget()
self.setCentralWidget(self.main)
self.layout = QGridLayout()
self.layout.addWidget(self.table, 0, 0)
self.main.setLayout(self.layout)
self.setWindowTitle("AmpObject Manager")
self.table.setRowCount(0)
self.table.setColumnCount(5)
self.table.setHorizontalHeaderLabels(['Name', 'Type', 'Colour', 'Opacity', 'Display'])
self.n = self.table.rowCount()
def addRow(self, name, amp):
self.table.insertRow(self.n)
self.table.setItem(self.n, 0, QTableWidgetItem(name))
self.table.setItem(self.n, 1, QTableWidgetItem(amp.stype))
self.table.setItem(self.n, 2, QTableWidgetItem(str(amp.actor.GetProperty().GetColor())))
self.table.setItem(self.n, 3, QTableWidgetItem(str(amp.actor.GetProperty().GetOpacity())))
chkBoxItem = QTableWidgetItem()
chkBoxItem.setTextAlignment(Qt.AlignCenter)
chkBoxItem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
chkBoxItem.setCheckState(Qt.Checked)
self.table.setItem(self.n,4,chkBoxItem)
self.n = self.table.rowCount()
def getRow(self, i):
row = []
for r in range(self.table.columnCount() - 1):
row.append(self.table.item(i, r).text())
row.append(self.table.item(i, r+1).checkState())
return row
class AlignControls(QMainWindow):
"""
Pop up for controls to align the
Example
-------
Perhaps an example implementation:
>>> from AmpScan.AmpScanGUI import AmpScanGUI
"""
def __init__(self, names, parent = None):
super(AlignControls, self).__init__(parent)
self.main = QWidget()
self.names = names
self.static = QComboBox()
self.moving = QComboBox()
self.icp = QPushButton("Run ICP")
self.setCentralWidget(self.main)
self.layout = QGridLayout()
self.layout.addWidget(QLabel('Static'), 0, 0)
self.layout.addWidget(QLabel('Moving'), 1, 0)
self.layout.addWidget(self.static, 0, 1)
self.layout.addWidget(self.moving, 1, 1)
self.layout.addWidget(self.icp, 2, 0, 1, -1)
self.main.setLayout(self.layout)
self.setWindowTitle("Alignment Manager")
self.getNames()
def getNames(self):
"""
"""
self.static.clear()
self.static.addItems(self.names)
self.moving.clear()
self.moving.addItems(self.names)
class RegistrationControls(QMainWindow):
"""
Pop up for controls to align the
Example
-------
Perhaps an example implementation:
>>> from AmpScan.AmpScanGUI import AmpScanGUI
"""
def __init__(self, names, parent = None):
super(RegistrationControls, self).__init__(parent)
self.main = QWidget()
self.names = names
self.baseline = QComboBox()
self.target = QComboBox()
self.reg = QPushButton("Run Registration")
self.setCentralWidget(self.main)
self.layout = QGridLayout()
self.layout.addWidget(QLabel('Baseline'), 0, 0)
self.layout.addWidget(QLabel('Target'), 1, 0)
self.layout.addWidget(self.baseline, 0, 1)
self.layout.addWidget(self.target, 1, 1)
self.layout.addWidget(self.reg, 2, 0, 1, -1)
self.main.setLayout(self.layout)
self.setWindowTitle("Alignment Manager")
self.getNames()
def getNames(self):
"""
"""
self.baseline.clear()
self.baseline.addItems(self.names)
self.target.clear()
self.target.addItems(self.names)
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
mainWin = AmpScanGUI() mainWin = AmpScanGUI()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment