Commit 8289ee92 authored by Josef Brandt's avatar Josef Brandt

Merge branch 'CustomLevelsInOpticalScan' into Development

parents aaa767c1 2e588d5b
...@@ -25,5 +25,4 @@ class InvalidParticleError(Exception): ...@@ -25,5 +25,4 @@ class InvalidParticleError(Exception):
class NotConnectedContoursError(Exception): class NotConnectedContoursError(Exception):
pass pass
\ No newline at end of file
...@@ -24,19 +24,19 @@ import numpy as np ...@@ -24,19 +24,19 @@ import numpy as np
from multiprocessing import Process, Queue, Event from multiprocessing import Process, Queue, Event
import queue import queue
from .imagestitch import imageStacking from .imagestitch import imageStacking
import os import sys, os
import cv2 import cv2
from .helperfunctions import cv2imread_fix, cv2imwrite_fix from .helperfunctions import cv2imread_fix, cv2imwrite_fix
from time import time from time import time
import datetime import datetime
import sys
from .opticalbackground import BackGroundManager from .opticalbackground import BackGroundManager
from .zlevelsetter import ZLevelSetter
def scan(path, sol, zpositions, grid, controlclass, dataqueue, def scan(path, sol, zpositions, grid, controlclass, dataqueue,
stopevent, logpath='', ishdr=False): stopevent, logpath='', ishdr=False):
if ishdr: if ishdr:
merge_mertens = cv2.createMergeMertens() merge_mertens = cv2.createMergeMertens()
fp = None fp = None
if logpath != '': if logpath != '':
try: try:
...@@ -221,18 +221,19 @@ class PointCoordinates(QtWidgets.QGridLayout): ...@@ -221,18 +221,19 @@ class PointCoordinates(QtWidgets.QGridLayout):
else: else:
points[i,:] = np.nan points[i,:] = np.nan
return points return points
class OpticalScan(QtWidgets.QWidget): class OpticalScan(QtWidgets.QWidget):
imageUpdate = QtCore.pyqtSignal(str, name='imageUpdate') #str = 'df' (= darkfield) or 'bf' (=bright field) imageUpdate = QtCore.pyqtSignal(str, name='imageUpdate') #str = 'df' (= darkfield) or 'bf' (=bright field)
boundaryUpdate = QtCore.pyqtSignal() boundaryUpdate = QtCore.pyqtSignal()
backGroundSavedToPath = QtCore.pyqtSignal(int, str) backGroundSavedToPath = QtCore.pyqtSignal(int, str)
def __init__(self, ramanctrl, dataset, logpath='', parent=None): def __init__(self, ramanctrl, dataset, logpath='', parent=None):
super().__init__(parent, QtCore.Qt.Window) super().__init__(parent, QtCore.Qt.Window)
self.logpath = logpath self.logpath = logpath
self.view = parent self.view = parent
vbox = QtWidgets.QVBoxLayout() mainLayout = QtWidgets.QVBoxLayout()
pointgroup = QtWidgets.QGroupBox("Point coordinates [µm]", self) pointgroup = QtWidgets.QGroupBox("Point coordinates [µm]", self)
self.ramanctrl = ramanctrl self.ramanctrl = ramanctrl
self.dataset = dataset self.dataset = dataset
...@@ -267,34 +268,25 @@ class OpticalScan(QtWidgets.QWidget): ...@@ -267,34 +268,25 @@ class OpticalScan(QtWidgets.QWidget):
self.radiusincreaseedit.setSingleStep(20) self.radiusincreaseedit.setSingleStep(20)
self.radiusincreaseedit.setMaximumWidth(100) self.radiusincreaseedit.setMaximumWidth(100)
self.radiusincreaseedit.valueChanged.connect(self.areaSelect) self.radiusincreaseedit.valueChanged.connect(self.areaSelect)
label2 = QtWidgets.QLabel("Maximal focus height [µm]:", self)
self.zmaxedit = QtWidgets.QDoubleSpinBox(self)
self.zmaxedit.setMinimum(1)
self.zmaxedit.setMaximum(1000)
self.zmaxedit.setDecimals(0)
self.zmaxedit.setValue(50)
self.zmaxedit.setMaximumWidth(100)
label3 = QtWidgets.QLabel("Focus steps:", self)
self.nzedit = QtWidgets.QSpinBox(self)
self.nzedit.setRange(1,20)
self.nzedit.setValue(3)
self.nzedit.setMaximumWidth(100)
self.hdrcheck = QtWidgets.QCheckBox("High dynamic range", self) self.hdrcheck = QtWidgets.QCheckBox("High dynamic range", self)
self.hdrcheck.setChecked(False) self.hdrcheck.setChecked(False)
self.zLevelSetter = ZLevelSetter()
self.zLevelSetter.sizeChanged.connect(self._updateSize)
self.prun = QtWidgets.QPushButton("Run", self) self.prun = QtWidgets.QPushButton("Run", self)
self.pexit = QtWidgets.QPushButton("Cancel", self) self.pexit = QtWidgets.QPushButton("Cancel", self)
self.pareaselect.released.connect(self.areaSelect) self.pareaselect.released.connect(self.areaSelect)
self.prun.released.connect(self.run) self.prun.released.connect(self.run)
self.pexit.released.connect(self.stopScan) self.pexit.released.connect(self.stopScan)
self.prun.setEnabled(False) self.prun.setEnabled(False)
self.timelabeltext = "Estimated time to finish: " self.timelabeltext = "Estimated time to finish: "
self.progressbar = QtWidgets.QProgressBar(self) self.progressbar = QtWidgets.QProgressBar(self)
self.progresstime = QtWidgets.QLabel(self.timelabeltext, self) self.progresstime = QtWidgets.QLabel(self.timelabeltext, self)
self.progresstime.setEnabled(False) self.progresstime.setEnabled(False)
self.progressbar.setEnabled(False) self.progressbar.setEnabled(False)
radioGroup = QtWidgets.QGroupBox('Shape') radioGroup = QtWidgets.QGroupBox('Shape')
radioLayout = QtWidgets.QHBoxLayout() radioLayout = QtWidgets.QHBoxLayout()
self.circlerad = QtWidgets.QRadioButton("Circle") self.circlerad = QtWidgets.QRadioButton("Circle")
...@@ -330,29 +322,40 @@ class OpticalScan(QtWidgets.QWidget): ...@@ -330,29 +322,40 @@ class OpticalScan(QtWidgets.QWidget):
areaLayout.addRow(self.pareaselect) areaLayout.addRow(self.pareaselect)
self.areaOptionsGroup.setLayout(areaLayout) self.areaOptionsGroup.setLayout(areaLayout)
self.areaOptionsGroup.setDisabled(True) self.areaOptionsGroup.setDisabled(True)
furtherOptionsGroup = QtWidgets.QGroupBox('Further Options') furtherOptionsGroup = QtWidgets.QGroupBox('Further Options')
furtherOptionsLayout = QtWidgets.QFormLayout() furtherOptionsLayout = QtWidgets.QFormLayout()
furtherOptionsLayout.addRow(label2, self.zmaxedit)
furtherOptionsLayout.addRow(label3, self.nzedit)
furtherOptionsLayout.addRow(self.hdrcheck) furtherOptionsLayout.addRow(self.hdrcheck)
furtherOptionsLayout.addRow(self.deleteImgChecker) furtherOptionsLayout.addRow(self.deleteImgChecker)
furtherOptionsGroup.setLayout(furtherOptionsLayout) furtherOptionsGroup.setLayout(furtherOptionsLayout)
btnLayout = QtWidgets.QHBoxLayout() btnLayout = QtWidgets.QHBoxLayout()
btnLayout.addWidget(self.prun) btnLayout.addWidget(self.prun)
btnLayout.addWidget(self.pexit) btnLayout.addWidget(self.pexit)
btnLayout.addStretch() btnLayout.addStretch()
vbox.addWidget(pointgroup) vbox1 = QtWidgets.QVBoxLayout()
vbox.addWidget(bkggroup) vbox2 = QtWidgets.QVBoxLayout()
vbox.addWidget(self.areaOptionsGroup)
vbox.addWidget(furtherOptionsGroup) vbox1.addWidget(pointgroup)
vbox.addLayout(btnLayout) vbox1.addWidget(self.zLevelSetter)
vbox.addWidget(self.progresstime) vbox1.addStretch()
vbox.addWidget(self.progressbar)
vbox2.addWidget(self.areaOptionsGroup)
self.setLayout(vbox) vbox2.addWidget(bkggroup)
vbox2.addWidget(furtherOptionsGroup)
vbox2.addStretch()
optionsLayout = QtWidgets.QHBoxLayout()
optionsLayout.addLayout(vbox1)
optionsLayout.addLayout(vbox2)
mainLayout.addLayout(optionsLayout)
mainLayout.addWidget(self.progresstime)
mainLayout.addWidget(self.progressbar)
mainLayout.addLayout(btnLayout)
self.setLayout(mainLayout)
self.setVisible(False) self.setVisible(False)
def enableDisableBackground(self): def enableDisableBackground(self):
...@@ -361,8 +364,7 @@ class OpticalScan(QtWidgets.QWidget): ...@@ -361,8 +364,7 @@ class OpticalScan(QtWidgets.QWidget):
self.backGroundManager.calculateAverageImage() self.backGroundManager.calculateAverageImage()
else: else:
self.deleteBackGroundImage() self.deleteBackGroundImage()
def showHideBackgroundWindow(self): def showHideBackgroundWindow(self):
if self.backGroundManager.isHidden(): if self.backGroundManager.isHidden():
self.backGroundManager.show() self.backGroundManager.show()
...@@ -373,7 +375,11 @@ class OpticalScan(QtWidgets.QWidget): ...@@ -373,7 +375,11 @@ class OpticalScan(QtWidgets.QWidget):
def managerWasClosed(self): def managerWasClosed(self):
self.showBgkManagerBtn.setText('Show Background Manager Window') self.showBgkManagerBtn.setText('Show Background Manager Window')
@QtCore.pyqtSlot()
def _updateSize(self):
self.adjustSize()
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def stopScan(self): def stopScan(self):
if self.process is not None and self.process.is_alive(): if self.process is not None and self.process.is_alive():
...@@ -552,19 +558,26 @@ class OpticalScan(QtWidgets.QWidget): ...@@ -552,19 +558,26 @@ class OpticalScan(QtWidgets.QWidget):
# convert z to software z, which is relative to current user z # convert z to software z, which is relative to current user z
softwarez = self.ramanctrl.getSoftwareZ() # get current software z softwarez = self.ramanctrl.getSoftwareZ() # get current software z
points[:,2] += softwarez-self.ramanctrl.getUserZ() points[:,2] += softwarez-self.ramanctrl.getUserZ()
Nz = self.nzedit.value()
zmaxstack = self.zmaxedit.value() try:
if Nz==1: zrange = self.zLevelSetter.getZLevels()
except ValueError:
return
zmaxstack = max(zrange)
if len(zrange) == 1:
zmaxstack = 0.0 zmaxstack = 0.0
self.dataset.zpositions = np.array([0.0]) self.dataset.zpositions = np.array([0.0])
else: else:
self.dataset.zpositions = np.linspace(0, zmaxstack, Nz) # self.dataset.zpositions = np.linspace(0, zmaxstack, Nz)
self.dataset.zpositions = zrange
width, height, rotationvalue = self.dataset.imagedim_df width, height, rotationvalue = self.dataset.imagedim_df
print("Width, height, rotation:", width, height, rotationvalue) print("Width, height, rotation:", width, height, rotationvalue)
print("Points x:", points[:,0].min(), points[:,0].max()) print("Points x:", points[:,0].min(), points[:,0].max())
print("Points y:", points[:,1].min(), points[:,1].max()) print("Points y:", points[:,1].min(), points[:,1].max())
print("Points z:", points[:,2].min(), points[:,2].max()) print("Points z:", points[:,2].min(), points[:,2].max())
A = np.ones((points.shape[0],3)) A = np.ones((points.shape[0],3))
A[:,:2] = points[:,:2] A[:,:2] = points[:,:2]
b = points[:,2] b = points[:,2]
...@@ -678,17 +691,7 @@ class OpticalScan(QtWidgets.QWidget): ...@@ -678,17 +691,7 @@ class OpticalScan(QtWidgets.QWidget):
self.close() self.close()
return return
self.timer.start(100.) self.timer.start(100.)
def closeEvent(self, event): def closeEvent(self, event):
self.backGroundManager.close() self.backGroundManager.close()
event.accept() event.accept()
\ No newline at end of file
if __name__ == "__main__":
from ramancom.simulatedraman import SimulatedRaman
from dataset import DataSet
app = QtWidgets.QApplication(sys.argv)
ds = DataSet('Test')
optscan = OpticalScan(SimulatedRaman(), ds)
optscan.show()
sys.exit(app.exec_())
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 25 09:39:14 2019
@author: brandt
"""
from PyQt5 import QtWidgets, QtCore
import sys
import numpy as np
class ZLevelSetter(QtWidgets.QLabel):
"""
Allows refining settings for the focus-z-stacking
:return:
"""
sizeChanged = QtCore.pyqtSignal()
def __init__(self):
super(ZLevelSetter, self).__init__()
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
self.radioGroup = QtWidgets.QButtonGroup()
layout.addWidget(self._createRangeGroupBox())
layout.addLayout(self._createLevelSelectionLayout())
self._addRadioBtnsToGroup()
self._updateLevels()
def _createRangeGroupBox(self):
"""
Creates Widgets for setting range of z-levels
:return:
"""
rangeGroupBox = QtWidgets.QGroupBox('Select Range of z-steps')
rangesLayout = QtWidgets.QHBoxLayout()
rangeGroupBox.setLayout(rangesLayout)
rangeGroupBox.setFixedHeight(60)
self.minLevelSpinbox = QtWidgets.QSpinBox()
self.minLevelSpinbox.setMinimum(-1000)
self.minLevelSpinbox.setMaximum(1000)
self.minLevelSpinbox.setValue(0)
self.minLevelSpinbox.valueChanged.connect(self._minLevelBoxChanged)
self.maxLevelSpinbox = QtWidgets.QSpinBox()
self.maxLevelSpinbox.setValue(50)
self._minLevelBoxChanged()
self.numLevelsSpinbox = QtWidgets.QSpinBox()
self.numLevelsSpinbox.setMinimum(1)
self.numLevelsSpinbox.setMaximum(100)
self.numLevelsSpinbox.setValue(5)
for box in [self.minLevelSpinbox, self.maxLevelSpinbox, self.numLevelsSpinbox]:
box.valueChanged.connect(self._updateLevels)
rangesLayout.addWidget(QtWidgets.QLabel('z_min (µm): '))
rangesLayout.addWidget(self.minLevelSpinbox)
rangesLayout.addWidget(QtWidgets.QLabel(', z_max (µm): '))
rangesLayout.addWidget(self.maxLevelSpinbox)
rangesLayout.addWidget(QtWidgets.QLabel(', Num. steps: '))
rangesLayout.addWidget(self.numLevelsSpinbox)
return rangeGroupBox
def _createLevelSelectionLayout(self):
"""
Creates the Parent Group for selecting mode of level distribution
:return:
"""
modeLayout = QtWidgets.QHBoxLayout()
modeLayout.addWidget(self._createLinGroup())
modeLayout.addWidget(self._createLogGroup())
modeLayout.addWidget(self._createCustomGroup())
return modeLayout
def _createLinGroup(self):
"""
Creates Widget group for linear level distribution
:return:
"""
linGroup = QtWidgets.QGroupBox()
linLayout = QtWidgets.QVBoxLayout()
linGroup.setLayout(linLayout)
linGroup.sizePolicy().setVerticalPolicy(QtWidgets.QSizePolicy.Expanding)
self.linChecker = QtWidgets.QRadioButton('Linear')
self.linChecker.setChecked(True)
self.linChecker.toggled.connect(self._updateLevels)
linLayout.addWidget(self.linChecker)
self.linPreviewLayout = QtWidgets.QVBoxLayout()
linLayout.addLayout(self.linPreviewLayout)
self.linPreviewSteps = []
self._updateLinPreview()
return linGroup
def _createLogGroup(self):
"""
Creates Widget group for logarithmic level distribution
:return:
"""
logGroup = QtWidgets.QGroupBox()
logLayout = QtWidgets.QVBoxLayout()
logGroup.setLayout(logLayout)
logGroup.sizePolicy().setVerticalPolicy(QtWidgets.QSizePolicy.Expanding)
self.logChecker = QtWidgets.QRadioButton('Logarithmic')
self.logChecker.setChecked(False)
self.logChecker.toggled.connect(self._updateLevels)
logLayout.addWidget(self.logChecker)
self.logPreviewLayout = QtWidgets.QVBoxLayout()
logLayout.addLayout(self.logPreviewLayout)
self.logPreviewSteps = []
self._updateLogPreview()
return logGroup
def _createCustomGroup(self):
"""
Creates Widget group for custom level distribution
:return:
"""
customGroup = QtWidgets.QGroupBox()
customLayout = QtWidgets.QVBoxLayout()
customGroup.setLayout(customLayout)
customGroup.sizePolicy().setVerticalPolicy(QtWidgets.QSizePolicy.Expanding)
self.customChecker = QtWidgets.QRadioButton('Custom')
self.customChecker.setChecked(False)
self.customChecker.toggled.connect(self._updateLevels)
customLayout.addWidget(self.customChecker)
self.customPreviewLayout = QtWidgets.QVBoxLayout()
customLayout.addLayout(self.customPreviewLayout)
self.customPreviewSteps = []
self._updateCustomPreview()
return customGroup
def _updateLevels(self):
"""
Updates the previewed levels for all modes
:return:
"""
self._updateLinPreview()
self._updateLogPreview()
self._updateCustomPreview()
self._updateSize()
def _updateLinPreview(self):
"""
Updates linear level preview
:return:
"""
for entry in self.linPreviewSteps:
entry.setParent(None)
zRange = np.linspace(self.minLevelSpinbox.value(), self.maxLevelSpinbox.value(), self.numLevelsSpinbox.value())
self.linPreviewSteps = []
for val in zRange:
newLabel = QtWidgets.QLabel(str(round(val, 1)))
newLabel.setEnabled(self.linChecker.isChecked())
self.linPreviewSteps.append(newLabel)
self.linPreviewLayout.addWidget(newLabel)
def _updateLogPreview(self):
"""
Updates logarithmic level preview
:return:
"""
for entry in self.logPreviewSteps:
entry.setParent(None)
zmin = self.minLevelSpinbox.value()
zmax = np.log2(self.maxLevelSpinbox.value())
zRange = np.logspace(zmin, zmax, self.numLevelsSpinbox.value(), base=2)
self.logPreviewSteps = []
for val in zRange:
newLabel = QtWidgets.QLabel(str(round(val, 1)))
newLabel.setEnabled(self.logChecker.isChecked())
self.logPreviewSteps.append(newLabel)
self.logPreviewLayout.addWidget(newLabel)
def _updateCustomPreview(self):
"""
Updates custom level preview
:return:
"""
numCurrentEntries = len(self.customPreviewSteps)
numDesiredEntries = self.numLevelsSpinbox.value()
for i in range(max([numCurrentEntries, numDesiredEntries])):
if i < numCurrentEntries:
try:
self.customPreviewSteps[i].setEnabled(self.customChecker.isChecked())
except IndexError:
print(i, self.customPreviewSteps)
elif i >= numCurrentEntries:
newEntry = QtWidgets.QLineEdit()
newEntry.setEnabled(self.customChecker.isChecked())
self.customPreviewSteps.append(newEntry)
self.customPreviewLayout.addWidget(newEntry)
if i >= numDesiredEntries:
entry = self.customPreviewSteps[i]
entry.setParent(None)
self.customPreviewSteps.remove(entry)
def _updateSize(self):
"""
Updates the size so that all entries are well visible
:return:
"""
width = 400
height = 100 + self.numLevelsSpinbox.value()*30
self.setFixedSize(width, height)
self.sizeChanged.emit()
def _minLevelBoxChanged(self):
"""
Adjusts maxLevelSpinbox to show always values larger then minLevelSpinbox
:return:
"""
self.maxLevelSpinbox.setMinimum(self.minLevelSpinbox.value()+1)
self.maxLevelSpinbox.setMaximum(self.maxLevelSpinbox.value()+1000)
def _addRadioBtnsToGroup(self):
"""
Group Radio Buttons to have them in exclusive check mode
:return:
"""
self.radioGroup.addButton(self.linChecker)
self.radioGroup.addButton(self.logChecker)
self.radioGroup.addButton(self.customChecker)
def getZLevels(self):
"""
retrieves the z-levels according to the chosen settings
:return:
"""
zLevels = []
if self.linChecker.isChecked():
zLevels = [float(entry.text()) for entry in self.linPreviewSteps]
elif self.logChecker.isChecked():
zLevels = [float(entry.text()) for entry in self.logPreviewSteps]
elif self.customChecker.isChecked():
try:
zLevels = self._getCustomLevels()
except ValueError:
QtWidgets.QMessageBox.critical(self, 'Error', 'Invalid entry in custom level selection')
raise ValueError
return np.array(zLevels)
def _getCustomLevels(self):
"""
Reads out the custom level range
:return:
"""
levels = []
for lineEdit in self.customPreviewSteps:
try:
levels.append(float(lineEdit.text()))
except:
raise ValueError
return sorted(levels)
if __name__ == '__main__':
try:
del app
except:
pass
app = QtWidgets.QApplication(sys.argv)
zSetter = ZLevelSetter()
zSetter.show()
ret = app.exec_()
sys.exit(1)
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment