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):
class NotConnectedContoursError(Exception):
pass
pass
\ No newline at end of file
......@@ -24,19 +24,19 @@ import numpy as np
from multiprocessing import Process, Queue, Event
import queue
from .imagestitch import imageStacking
import os
import sys, os
import cv2
from .helperfunctions import cv2imread_fix, cv2imwrite_fix
from time import time
import datetime
import sys
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):
if ishdr:
merge_mertens = cv2.createMergeMertens()
merge_mertens = cv2.createMergeMertens()
fp = None
if logpath != '':
try:
......@@ -221,18 +221,19 @@ class PointCoordinates(QtWidgets.QGridLayout):
else:
points[i,:] = np.nan
return points
class OpticalScan(QtWidgets.QWidget):
imageUpdate = QtCore.pyqtSignal(str, name='imageUpdate') #str = 'df' (= darkfield) or 'bf' (=bright field)
boundaryUpdate = QtCore.pyqtSignal()
backGroundSavedToPath = QtCore.pyqtSignal(int, str)
def __init__(self, ramanctrl, dataset, logpath='', parent=None):
super().__init__(parent, QtCore.Qt.Window)
self.logpath = logpath
self.view = parent
vbox = QtWidgets.QVBoxLayout()
mainLayout = QtWidgets.QVBoxLayout()
pointgroup = QtWidgets.QGroupBox("Point coordinates [µm]", self)
self.ramanctrl = ramanctrl
self.dataset = dataset
......@@ -267,34 +268,25 @@ class OpticalScan(QtWidgets.QWidget):
self.radiusincreaseedit.setSingleStep(20)
self.radiusincreaseedit.setMaximumWidth(100)
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.setChecked(False)
self.zLevelSetter = ZLevelSetter()
self.zLevelSetter.sizeChanged.connect(self._updateSize)
self.prun = QtWidgets.QPushButton("Run", self)
self.pexit = QtWidgets.QPushButton("Cancel", self)
self.pareaselect.released.connect(self.areaSelect)
self.prun.released.connect(self.run)
self.pexit.released.connect(self.stopScan)
self.prun.setEnabled(False)
self.timelabeltext = "Estimated time to finish: "
self.progressbar = QtWidgets.QProgressBar(self)
self.progresstime = QtWidgets.QLabel(self.timelabeltext, self)
self.progresstime.setEnabled(False)
self.progressbar.setEnabled(False)
radioGroup = QtWidgets.QGroupBox('Shape')
radioLayout = QtWidgets.QHBoxLayout()
self.circlerad = QtWidgets.QRadioButton("Circle")
......@@ -330,29 +322,40 @@ class OpticalScan(QtWidgets.QWidget):
areaLayout.addRow(self.pareaselect)
self.areaOptionsGroup.setLayout(areaLayout)
self.areaOptionsGroup.setDisabled(True)
furtherOptionsGroup = QtWidgets.QGroupBox('Further Options')
furtherOptionsLayout = QtWidgets.QFormLayout()
furtherOptionsLayout.addRow(label2, self.zmaxedit)
furtherOptionsLayout.addRow(label3, self.nzedit)
furtherOptionsLayout.addRow(self.hdrcheck)
furtherOptionsLayout.addRow(self.deleteImgChecker)
furtherOptionsGroup.setLayout(furtherOptionsLayout)
btnLayout = QtWidgets.QHBoxLayout()
btnLayout.addWidget(self.prun)
btnLayout.addWidget(self.pexit)
btnLayout.addStretch()
vbox.addWidget(pointgroup)
vbox.addWidget(bkggroup)
vbox.addWidget(self.areaOptionsGroup)
vbox.addWidget(furtherOptionsGroup)
vbox.addLayout(btnLayout)
vbox.addWidget(self.progresstime)
vbox.addWidget(self.progressbar)
self.setLayout(vbox)
vbox1 = QtWidgets.QVBoxLayout()
vbox2 = QtWidgets.QVBoxLayout()
vbox1.addWidget(pointgroup)
vbox1.addWidget(self.zLevelSetter)
vbox1.addStretch()
vbox2.addWidget(self.areaOptionsGroup)
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)
def enableDisableBackground(self):
......@@ -361,8 +364,7 @@ class OpticalScan(QtWidgets.QWidget):
self.backGroundManager.calculateAverageImage()
else:
self.deleteBackGroundImage()
def showHideBackgroundWindow(self):
if self.backGroundManager.isHidden():
self.backGroundManager.show()
......@@ -373,7 +375,11 @@ class OpticalScan(QtWidgets.QWidget):
def managerWasClosed(self):
self.showBgkManagerBtn.setText('Show Background Manager Window')
@QtCore.pyqtSlot()
def _updateSize(self):
self.adjustSize()
@QtCore.pyqtSlot()
def stopScan(self):
if self.process is not None and self.process.is_alive():
......@@ -552,19 +558,26 @@ class OpticalScan(QtWidgets.QWidget):
# convert z to software z, which is relative to current user z
softwarez = self.ramanctrl.getSoftwareZ() # get current software z
points[:,2] += softwarez-self.ramanctrl.getUserZ()
Nz = self.nzedit.value()
zmaxstack = self.zmaxedit.value()
if Nz==1:
try:
zrange = self.zLevelSetter.getZLevels()
except ValueError:
return
zmaxstack = max(zrange)
if len(zrange) == 1:
zmaxstack = 0.0
self.dataset.zpositions = np.array([0.0])
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
print("Width, height, rotation:", width, height, rotationvalue)
print("Points x:", points[:,0].min(), points[:,0].max())
print("Points y:", points[:,1].min(), points[:,1].max())
print("Points z:", points[:,2].min(), points[:,2].max())
A = np.ones((points.shape[0],3))
A[:,:2] = points[:,:2]
b = points[:,2]
......@@ -678,17 +691,7 @@ class OpticalScan(QtWidgets.QWidget):
self.close()
return
self.timer.start(100.)
def closeEvent(self, event):
self.backGroundManager.close()
event.accept()
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_())
event.accept()
\ No newline at end of file
# -*- 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