Commit 5033b93c authored by Josef Brandt's avatar Josef Brandt

First Step of Recalculate Coordinate Transfer

Adds an interface for recalculating coordinate system of a dataset. Is found in toolbar of mainWindow: tools->Recalculate Coordinate System
parent 70b1c429
......@@ -203,6 +203,10 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
self.configRamanCtrlAct.triggered.connect(self.view.configureRamanControl)
if self.view.simulatedRaman:
self.configRamanCtrlAct.setDisabled(True)
self.recalculateCoordAct = QtWidgets.QAction("&Recalculate Coordinate System")
self.recalculateCoordAct.setDisabled(True)
self.recalculateCoordAct.triggered.connect(self.view.recalculateCoordinateSystem)
self.noOverlayAct = QtWidgets.QAction("&No Overlay", self)
self.noOverlayAct.setShortcut("1")
......@@ -223,18 +227,18 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
def updateModes(self, active=None, maxenabled=None):
ose, osc, pde, pdc, rse, rsc = [False]*6
if maxenabled=="OpticalScan":
if maxenabled == "OpticalScan":
ose = True
elif maxenabled=="ParticleDetection":
elif maxenabled == "ParticleDetection":
ose, pde = True, True
elif maxenabled=="RamanScan":
elif maxenabled == "RamanScan":
ose, pde, rse = True, True, True
if active=="OpticalScan" and ose:
if active == "OpticalScan" and ose:
osc = True
elif active=="ParticleDetection" and pde:
elif active == "ParticleDetection" and pde:
pdc = True
elif active=="RamanScan" and rse:
elif active == "RamanScan" and rse:
rsc = True
self.opticalScanAct.setEnabled(ose)
......@@ -292,6 +296,7 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
self.toolsMenu = QtWidgets.QMenu("&Tools")
self.toolsMenu.addAction(self.snapshotAct)
self.toolsMenu.addAction(self.configRamanCtrlAct)
self.toolsMenu.addAction(self.recalculateCoordAct)
self.dispMenu = QtWidgets.QMenu("&Display", self)
self.overlayActGroup = QtWidgets.QActionGroup(self.dispMenu)
......
import numpy as np
from scipy.optimize import least_squares
def getTransform(srcPoints: np.ndarray, dstPoints: np.ndarray, axisInvert: tuple = (False, False, False),
ramanShift: tuple = (0, 0)) -> tuple:
"""
Takes N points from source and target system and uses a least_squared method to find the transformation matrix
:param srcPoints: Nx3 array of xyz-points in source coordinate system
:param dstPoints: Nx3 array of xyz-points in target coordinate system
:param axisInvert: tuple of bools to indicate axis inversion in (x, y, z) dimension
:param ramanShift: x,y tuple of pixel offset of raman laset to image center
:returns resultTuple: transformMatrix, pc - shift, zpc, residuals
"""
points = srcPoints
points[:, 0] -= ramanShift[0]
points[:, 1] -= ramanShift[1]
Parity = np.mat(np.diag([-1. if axisInvert[0] else 1.,
-1. if axisInvert[1] else 1.,
-1. if axisInvert[2] else 1.]))
# zpoints = np.array([m.getPos() for m in self.markers], dtype=np.double)
zpoints = dstPoints
pc = points.mean(axis=0)
zpc = zpoints.mean(axis=0)
points -= pc[np.newaxis, :]
zpoints -= zpc[np.newaxis, :]
def getRotMat(angles):
c1, s1 = np.cos(angles[0]), np.sin(angles[0])
c2, s2 = np.cos(angles[1]), np.sin(angles[1])
c3, s3 = np.cos(angles[2]), np.sin(angles[2])
return np.mat([[c1 * c3 - s1 * c2 * s3, -c1 * s3 - s1 * c2 * c3, s1 * s2],
[s1 * c3 + c1 * c2 * s3, -s1 * s3 + c1 * c2 * c3, -c1 * s2],
[s1 * s3, s2 * c3, c2]])
# find the transformation matrix with best fit for small angles in
# [-45°,45°] for all permutation of markers
# permbest = None
# pointsbest = None
ppoints = points[:, :].copy()
def err(angles_shift):
T = (getRotMat(angles_shift[:3]).T * Parity).A
return (np.dot(zpoints, T) - angles_shift[np.newaxis, 3:] - ppoints).ravel()
angle = np.zeros(3)
opt = least_squares(err, np.concatenate((angle, np.zeros(3))),
bounds=(np.array([-np.pi / 4] * 3 + [-np.inf] * 3),
np.array([np.pi / 4] * 3 + [np.inf] * 3)),
method='dogbox')
permbest = opt
pointsbest = ppoints
optangles = permbest.x[:3]
shift = permbest.x[3:]
T = (getRotMat(optangles).T * Parity).A
error = (np.dot(zpoints, T) - shift[np.newaxis, :] - pointsbest)
# print("Transformation angles:", optangles, flush=True)
# print("Transformation shift:", shift, flush=True)
# print("Transformation err:", error, flush=True)
residuals = np.linalg.norm(error, axis=1)
# accept = True
if np.any(residuals > 1.):
print(f'Transformation residuals are large:{residuals}')
# ret = QtWidgets.QMessageBox.warning(self, 'Warning!',
# f'Transformation residuals are large:{residuals}',
# QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel,
# QtWidgets.QMessageBox.Ok)
# if ret == QtWidgets.QMessageBox.Cancel:
# accept = False
return T, pc - shift, zpc, residuals
class TrayMarker:
"""
Coordinate Marker on the sample tray. Is NOT in the actual optical image.
"""
index: int = -1
worldCoordX: float = np.nan
worldCoordY: float = np.nan
worldCoordZ: float = np.nan
class ImageMarker:
"""
Coordinate Marker of a characteristic feature within the optical image.
"""
index: int = -1
worldCoordX: float = np.nan
worldCoordY: float = np.nan
worldCoordZ: float = np.nan
imgCoordX: int = -1
imgCoordY: int = -1
......@@ -24,6 +24,7 @@ import numpy as np
import sys
import cv2
from copy import copy
from typing import List
from .analysis.particleContainer import ParticleContainer
from .legacyConvert import legacyConversion, currentVersion
from .helperfunctions import cv2imwrite_fix, cv2imread_fix
......@@ -31,9 +32,11 @@ from .helperfunctions import cv2imwrite_fix, cv2imread_fix
# (no relative import)
from . import dataset
from . import analysis
from .coordinatetransform import TrayMarker, ImageMarker
sys.modules['dataset'] = dataset
sys.modules['analysis'] = analysis
def loadData(fname):
retds = None
with open(fname, "rb") as fp:
......@@ -120,11 +123,11 @@ class DataSet(object):
self.version = currentVersion
self.lastpos = None
self.maxdim = None
self.pixelscale_df = None # µm / pixel --> scale of DARK FIELD camera (used for image stitching)
self.pixelscale_bf = None # µm / pixel of DARK FIELD camera (set to same as bright field, if both use the same camera)
self.pixelscale_df = None # µm / pixel --> scale of DARK FIELD camera (used for image stitching)
self.pixelscale_bf = None # µm / pixel of DARK FIELD camera (set to same as bright field, if both use the same camera)
self.imagedim_bf = None # width, height, angle of BRIGHT FIELD camera
self.imagedim_df = None # width, height, angle of DARK FIELD camera (set to same as bright field, if both use the same camera)
self.imagescanMode = 'df' #was the fullimage acquired in dark- or brightfield?
self.imagescanMode = 'df' # was the fullimage acquired in dark- or brightfield?
self.fitpoints = [] # manually adjusted positions aquired to define the specimen geometry
self.fitindices = [] # which of the five positions in the ui are already known
self.boundary = [] # scan boundary computed by a circle around the fitpoints + manual adjustments
......@@ -132,7 +135,9 @@ class DataSet(object):
self.zpositions = [] # z-positions for optical scan
self.heightmap = None
self.zvalimg = None
self.coordinatetransform = None # if imported form extern source coordinate system may be rotated
self.coordinatetransform = None # if imported form extern source coordinate system may be rotated
self.trayMarkers: List[TrayMarker] = [] # list of markers on the sample tray
self.imageMarkers: List[ImageMarker] = [] # list of coordinate markers within the image
self.signx = 1.
self.signy = -1.
......@@ -141,7 +146,6 @@ class DataSet(object):
# parameters specifically for raman scan
self.pshift = None # shift of raman scan position relative to image center
self.coordOffset = [0, 0] #offset of entire coordinate system
self.seedpoints = np.array([])
self.seeddeletepoints = np.array([])
self.detectParams = {'points': np.array([[50,0],[100,200],[200,255]]),
......@@ -242,8 +246,6 @@ class DataSet(object):
if not force:
assert not self.readin
p0 = copy(self.lastpos)
p0[0] += self.coordOffset[0]
p0[1] += self.coordOffset[1]
if mode == 'df':
p0[0] -= self.signx*self.imagedim_df[0]/2
p0[1] -= self.signy*self.imagedim_df[1]/2
......@@ -262,7 +264,7 @@ class DataSet(object):
if self.coordinatetransform is not None:
T, pc = self.coordinatetransform
x, y, z = (np.dot(np.array([x,y,z]), T) + pc)
x, y, z = (np.dot(np.array([x, y, z]), T) + pc)
if returnz:
return x, y, z
......
from PyQt5 import QtWidgets, QtGui, QtCore
import numpy as np
from typing import List
from copy import deepcopy
from ..coordinatetransform import ImageMarker, TrayMarker, getTransform
from ..ramancom.ramanbase import RamanBase
class CoordTransformUI(QtWidgets.QWidget):
def __init__(self, viewParent):
super(CoordTransformUI, self).__init__()
self.setWindowTitle('Recalculate Coordinate System')
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
self.viewParent = viewParent
self.ramanctrl: RamanBase = self.viewParent.ramanctrl
self.imageMarkers: List[ImageMarker] = [] # in the new coord system
self.newImageMarkers: List[ImageMarker] = []
self.imageMarkerWidgets: List[CoordinateSystemMarker] = []
self.trayMarkers: List[TrayMarker] = [] # in the new coord system
self.newTrayMarkers: List[TrayMarker] = [] # in the new coord system
self.layout = QtWidgets.QVBoxLayout()
self.setLayout(self.layout)
selectionLayout = QtWidgets.QHBoxLayout()
self.trayMarkersBtn: QtWidgets.QRadioButton = QtWidgets.QRadioButton('Use Tray Markers')
self.trayMarkersBtn.pressed.connect(self._useTrayMarkers)
self.trayMarkersBtn.setChecked(True)
self.imgMarkersBtn: QtWidgets.QRadioButton = QtWidgets.QRadioButton('Use Image Markers')
self.imgMarkersBtn.pressed.connect(self._useImageMarkers)
selectionLayout.addWidget(self.trayMarkersBtn)
selectionLayout.addWidget(self.imgMarkersBtn)
self.addMarkerBtn: QtWidgets.QPushButton = QtWidgets.QPushButton('Add New Markers')
self.addMarkerBtn.setStyleSheet("background-color : lightgrey")
self._formatAsToggleBtn(self.addMarkerBtn)
self.transferResult: QtWidgets.QLabel = QtWidgets.QLabel('No valid input')
self.trayMarkerGroup: QtWidgets.QGroupBox = self._getTrayMarkerGroup()
self.imgMarkerGroup: QtWidgets.QGroupBox = self._getImageMarkerGroup()
saveBtn: QtWidgets.QPushButton = QtWidgets.QPushButton('Save to Dataset')
saveBtn.clicked.connect(self._saveToDataset)
self.layout.addLayout(selectionLayout)
self.layout.addWidget(self.trayMarkerGroup)
self.layout.addWidget(self.transferResult)
self.layout.addWidget(saveBtn)
self._getMarkersFromDataset()
def _getMarkersFromDataset(self) -> None:
if self.viewParent is not None:
self.trayMarkers = deepcopy(self.viewParent.dataset.trayMarkers)
self.imageMarkers = deepcopy(self.viewParent.dataset.imageMarkers)
for index, imgMarker in enumerate(self.imageMarkers):
pxPos: tuple = (imgMarker.imgCoordX, imgMarker.imgCoordY)
newMarkerWidget: CoordinateSystemMarker = CoordinateSystemMarker(index, pxPos)
self.imageMarkerWidgets.append(newMarkerWidget)
self.viewParent.scene().addItem(newMarkerWidget)
def _formatAsToggleBtn(self, btn: QtWidgets.QPushButton) -> None:
btn.setCheckable(True)
btn.setChecked(False)
btn.clicked.connect(lambda: self._setBtnColor(btn))
def _getTrayMarkerGroup(self) -> QtWidgets.QGroupBox:
layout = QtWidgets.QGridLayout()
group: QtWidgets.QGroupBox = QtWidgets.QGroupBox('Sample Tray Markers')
group.setLayout(layout)
if len(self.trayMarkers) == 0:
layout.addWidget(QtWidgets.QLabel('No tray markers found.'))
for i in range(3):
layout.addWidget(QtWidgets.QLabel('New Marker Placeholder'))
return group
def _getImageMarkerGroup(self) -> QtWidgets.QGroupBox:
def makeCenterOnLambda(ind):
return lambda: self._centerOnImageMarker(ind)
def makeDeleteLambda(ind):
return lambda: self._deleteImageMarker(ind)
def makeReadNewPosLambda(ind):
return lambda: self._readNewImageMarker(ind)
layout = QtWidgets.QGridLayout()
group: QtWidgets.QGroupBox = QtWidgets.QGroupBox('Image Based Markers')
group.setLayout(layout)
layout.addWidget(self.addMarkerBtn)
if len(self.imageMarkers) == 0:
layout.addWidget(QtWidgets.QLabel('No image markers found.'))
else:
layout.addWidget(QtWidgets.QLabel('Number'), 1, 0)
layout.addWidget(QtWidgets.QLabel('Coordinates old'), 1, 1)
layout.addWidget(QtWidgets.QLabel('Coordinates new'), 1, 2)
for index, imgMarker in enumerate(self.imageMarkers):
# reset indices, as they could have been reordered by deleting a marker..
imgMarker.index = index
self.imageMarkerWidgets[index].index = index
newMarker: ImageMarker = self.newImageMarkers[index]
newMarker.index = index
newX, newY, newZ = newMarker.worldCoordX, newMarker.worldCoordY, newMarker.worldCoordZ
x, y, z = imgMarker.worldCoordX, imgMarker.worldCoordY, imgMarker.worldCoordZ
row: int = 2+index
updateBtn: QtWidgets.QPushButton = QtWidgets.QPushButton('Read Coordinates')
updateBtn.clicked.connect(makeReadNewPosLambda(index))
focusBtn: QtWidgets.QPushButton = QtWidgets.QPushButton('Center On')
focusBtn.clicked.connect(makeCenterOnLambda(index))
delBtn: QtWidgets.QPushButton = QtWidgets.QPushButton('Delete')
delBtn.clicked.connect(makeDeleteLambda(index))
layout.addWidget(QtWidgets.QLabel(str(imgMarker.index+1)), row, 0)
layout.addWidget(QtWidgets.QLabel(f'x: {round(x)} µm\ny: {round(y)} µm\nz: {round(z)} µm'), row, 1)
if np.nan in [newX, newY, newZ]:
layout.addWidget(QtWidgets.QLabel('Coordinates not yet read.'), row, 2)
else:
layout.addWidget(QtWidgets.QLabel(f'x: {round(newX)} µm\ny: {round(newY)} µm\nz: {round(newZ)} µm'), row, 2)
layout.addWidget(updateBtn, row, 3)
layout.addWidget(focusBtn, row, 4)
layout.addWidget(delBtn, row, 5)
return group
def _updateTransferResult(self) -> None:
oldMarkers: list = self.trayMarkers if self.trayMarkersBtn.isChecked() else self.imageMarkers
newMarkers: list = self.newTrayMarkers if self.trayMarkersBtn.isChecked() else self.newImageMarkers
srcPoints: np.ndarray = np.array(
[[marker.worldCoordX, marker.worldCoordY, marker.worldCoordZ] for marker in oldMarkers])
dstPoints: np.ndarray = np.array(
[[marker.worldCoordX, marker.worldCoordY, marker.worldCoordZ] for marker in newMarkers])
hasNan: bool = (np.any(np.isnan(srcPoints)) or np.any(np.isnan(dstPoints)))
if len(oldMarkers) == len(newMarkers) and len(oldMarkers) >= 3 and not hasNan:
transformMatrix, pc, zpc, residuals = getTransform(srcPoints, dstPoints)
self.transferResult.setText(f'Transform residuals (µm): {residuals}')
else:
self.transferResult.setText('No valid inputs for coordinate transfer')
def _setBtnColor(self, btn: QtWidgets.QPushButton):
"""
Sets color of the toggle button to indicate its status.
"""
if btn.isChecked():
btn.setStyleSheet("background-color : lightblue")
else:
btn.setStyleSheet("background-color : lightgrey")
def _useTrayMarkers(self) -> None:
"""
Use markers on the sample tray that are NOT in the microscope image.
"""
self.imgMarkerGroup.setParent(None)
self.trayMarkerGroup.setParent(None)
self.trayMarkerGroup = self._getTrayMarkerGroup()
self.layout.insertWidget(1, self.trayMarkerGroup)
def _useImageMarkers(self) -> None:
"""
Use markers that are defined through characteristic spots within the microscope image.
"""
self.imgMarkerGroup.setParent(None)
self.trayMarkerGroup.setParent(None)
self.imgMarkerGroup = self._getImageMarkerGroup()
self.layout.insertWidget(1, self.imgMarkerGroup)
self._updateTransferResult()
def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
if self.addMarkerBtn.isChecked() and event.button() == QtCore.Qt.LeftButton:
scenePos = self.viewParent.mapToScene(event.pos())
self._addNewImageMarker((scenePos.x(), scenePos.y()))
def _deleteImageMarker(self, markerIndex: int) -> None:
self.imageMarkers.remove(self.imageMarkers[markerIndex])
self.newImageMarkers.remove(self.newImageMarkers[markerIndex])
self.viewParent.scene().removeItem(self.imageMarkerWidgets[markerIndex])
self.imageMarkerWidgets.remove(self.imageMarkerWidgets[markerIndex])
self._useImageMarkers()
def _centerOnImageMarker(self, markerIndex: int) -> None:
self.viewParent.centerOn(self.imageMarkerWidgets[markerIndex])
def _addNewImageMarker(self, pos: tuple) -> None:
newImageMarker: ImageMarker = ImageMarker()
newImageMarker.index = len(self.imageMarkers)
x, y, z = self.ramanctrl.getPosition()
newImageMarker.worldCoordX = x
newImageMarker.worldCoordY = y
newImageMarker.worldCoordZ = z
newImageMarker.imgCoordX = pos[0]
newImageMarker.imgCoordY = pos[1]
self.imageMarkers.append(newImageMarker)
newNewImageMarker: ImageMarker = ImageMarker()
newNewImageMarker.imgCoordX = pos[0]
newNewImageMarker.imgCoordY = pos[1]
self.newImageMarkers.append(newNewImageMarker)
newMarkerWidget: CoordinateSystemMarker = CoordinateSystemMarker(len(self.imageMarkers), pos)
self.imageMarkerWidgets.append(newMarkerWidget)
self.viewParent.scene().addItem(newMarkerWidget)
self._useImageMarkers()
def _readNewImageMarker(self, index: int) -> None:
"""Reads current instrument coordinates and assignes them to the respective "new image marker" """
x, y, z = self.ramanctrl.getPosition()
self.newImageMarkers[index].worldCoordX = x
self.newImageMarkers[index].worldCoordY = y
self.newImageMarkers[index].worldCoordZ = z
self._useImageMarkers()
def _saveToDataset(self) -> None:
if self.trayMarkersBtn.isChecked():
print('saving tray markers to dataset')
else:
print('saving image makers to dataset')
def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
reply = QtWidgets.QMessageBox.question(self, 'Close without saving',
'The window is about to be closed.\nSave markers prior to closing?',
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
QtWidgets.QMessageBox.Yes)
if reply == QtWidgets.QMessageBox.Yes:
self._saveToDataset()
if self.viewParent is not None:
self.viewParent.showHiddenWidgets()
self.viewParent.coordTransferWidget = None
del self
class CoordinateSystemMarker(QtWidgets.QGraphicsItem):
def __init__(self, index: int, position: tuple):
super().__init__()
self.setPos(position[0], position[1])
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
self.setCacheMode(QtWidgets.QGraphicsItem.DeviceCoordinateCache)
self.index = index
self.pxSize: int = 101
self.gapSize: int = 10
# self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges)
# self.poschanged = False
def boundingRect(self) -> QtCore.QRectF:
return QtCore.QRectF(-self.pxSize/2, -self.pxSize/2, self.pxSize, self.pxSize)
def paint(self, painter: QtGui.QPainter, option, widget) -> None:
halfSize: int = int(round(self.pxSize / 2))
halfGapSize: int = int(round(self.gapSize / 2))
painter.setPen(QtCore.Qt.green)
painter.setBrush(QtGui.QColor(30, 255, 30, 64))
painter.drawEllipse(-halfSize, -halfSize, self.pxSize, self.pxSize)
# horizontal lines
painter.drawLine(-halfSize, 0, -halfGapSize, 0)
painter.drawLine(halfGapSize, 0, halfSize, 0)
# vertical lines
painter.drawLine(0, -halfSize, 0, -halfGapSize)
painter.drawLine(0, halfGapSize, 0, halfSize)
painter.drawText(-halfSize, -halfSize, str(f'Marker {self.index+1}'))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
coordUI = CoordTransformUI(None)
coordUI.show()
ret = app.exec_()
......@@ -37,6 +37,7 @@ from .analysis.particleEditor import ParticleEditor
from .ramancom.configRaman import RamanConfigWin
from .scenePyramid import ScenePyramid
from .gepardlogging import setDefaultLoggingConfig
from .gui.coordTransferGUI import CoordTransformUI
class SampleView(QtWidgets.QGraphicsView):
......@@ -83,7 +84,7 @@ class SampleView(QtWidgets.QGraphicsView):
self.pyramid = ScenePyramid(self, self.logger)
self.particleEditor = None
self.fititems = []
self.boundaryitems = [[],[]]
self.boundaryitems = [[], []]
self.scanitems = []
self.ramanscanitems = []
self.particleInfoBox = None
......@@ -93,6 +94,7 @@ class SampleView(QtWidgets.QGraphicsView):
self.selectedParticleIndices = []
self.seedPoints = []
self.particlePainter = None
self.coordTransferWidget = None
self.detectionwidget = None
self.ramanwidget = RamanScanUI(self.ramanctrl, None, self.logger, self)
......@@ -103,6 +105,7 @@ class SampleView(QtWidgets.QGraphicsView):
self.setMinimumSize(600, 600)
self.darkenPixmap = False
self.microscopeMode = None
self.hiddenWidgets: list = []
self.update()
......@@ -141,10 +144,9 @@ class SampleView(QtWidgets.QGraphicsView):
self.disconnectRaman()
self.saveDataSet()
event.accept()
self.oscanwidget.close()
if self.detectionwidget is not None:
self.detectionwidget.close()
self.ramanwidget.close()
for widget in [self.oscanwidget, self.detectionwidget, self.ramanwidget, self.coordTransferWidget]:
if widget is not None:
widget.close()
else:
event.ignore()
......@@ -257,6 +259,7 @@ class SampleView(QtWidgets.QGraphicsView):
self.imgdata = None
self.activateMaxMode(loadnew=True)
self.imparent.snapshotAct.setEnabled(True)
self.imparent.recalculateCoordAct.setEnabled(True)
self.setupLoggerToDataset()
def importProject(self, fname):
......@@ -279,6 +282,7 @@ class SampleView(QtWidgets.QGraphicsView):
self.imgdata = None
self.activateMaxMode(loadnew=True)
self.imparent.snapshotAct.setEnabled(True)
self.imparent.recalculateCoordAct.setEnabled(True)
self.setupLoggerToDataset()
def setupLoggerToDataset(self):
......@@ -362,26 +366,27 @@ class SampleView(QtWidgets.QGraphicsView):
self.imparent.updateModes(self.mode, self.getMaxMode())
def mousePressEvent(self, event):
if event.button()==QtCore.Qt.MiddleButton:
if event.button() == QtCore.Qt.MiddleButton:
self.drag = event.pos()
if self.particlePainter is None:
if event.button()==QtCore.Qt.LeftButton:
if self.particlePainter is not None:
self.particlePainter.mousePressEvent(event)
elif self.coordTransferWidget is not None:
self.coordTransferWidget.mousePressEvent(event)
else:
if event.button() == QtCore.Qt.LeftButton:
if self.mode in ["OpticalScan", "RamanScan"] and event.modifiers()==QtCore.Qt.ControlModifier:
p0 = self.mapToScene(event.pos())
self.moveStageToPosition(p0)
elif self.mode=="ParticleDetection":
elif self.mode == "ParticleDetection":
p0 = self.mapToScene(event.pos())
self.detectionwidget.setImageCenter([p0.x(), p0.y()])
else:
p0 = self.mapToScene(event.pos())
super(SampleView, self).mousePressEvent(event)
else:
self.particlePainter.mousePressEvent(event)
def mouseMoveEvent(self, event):
if self.drag is not None:
......@@ -845,3 +850,21 @@ class SampleView(QtWidgets.QGraphicsView):
for seedpoint in self.seedPoints:
self.scene().removeItem(seedpoint)
self.seedPoints = []
def recalculateCoordinateSystem(self):
for widget in [self.oscanwidget, self.detectionwidget, self.ramanwidget]:
if widget is not None:
if not widget.isHidden():
self.hideWidget(widget)
self.coordTransferWidget = CoordTransformUI(self)
self.coordTransferWidget.show()
def hideWidget(self, widget: QtWidgets.QWidget) -> None:
self.hiddenWidgets.append(widget)
widget.hide()
def showHiddenWidgets(self) -> None:
for widget in self.hiddenWidgets:
widget.show()