Commit 25423ad8 authored by Josef Brandt's avatar Josef Brandt

Further bugfixes and comort functions

Color mode is fixed (bgr2rgb not needed),
More hotkeys,
Preparation for Renishaw interface (handles raman measurement differently),
"Measure fraction of particles" now keeps all particles, but measures only a fraction of them,
Better Navigation in Analysisview (button press responses)
parent ad95af53
......@@ -14,3 +14,7 @@ external/build/
.idea/
*.pyd
ramancom/renishawcom.py
ramancom/renishawtesting.py
......@@ -205,12 +205,17 @@ class GEPARDMainWindow(QtWidgets.QMainWindow):
self.configRamanCtrlAct.setDisabled(True)
self.noOverlayAct = QtWidgets.QAction("&No Overlay", self)
self.noOverlayAct.setShortcut("1")
self.selOverlayAct = QtWidgets.QAction("&Selected Overlay", self)
self.selOverlayAct.setShortcut("2")
self.fullOverlayAct = QtWidgets.QAction("&Full Overlay", self)
self.fullOverlayAct.setShortcut("3")
self.transpAct = QtWidgets.QAction("&Transparent Overlay", self)
self.transpAct.setShortcut("T")
self.hideLabelAct = QtWidgets.QAction('&Hide Spectra Numbers', self)
self.hideLabelAct.setShortcut("H")
self.darkenAct = QtWidgets.QAction("&Darken Image", self)
self.darkenAct.setShortcut("D")
self.seedAct = QtWidgets.QAction("&Set Color Seed", self)
for act in [self.noOverlayAct, self.selOverlayAct, self.fullOverlayAct, self.hideLabelAct, self.transpAct, self.darkenAct, self.seedAct]:
......
......@@ -209,13 +209,19 @@ class PolymerNavigationToolbar(QtWidgets.QGroupBox):
self.particleSelector.setValue(partIndices.index(particleIndex)+1)
specIndices = self.particleContainer.getSpectraIndicesOfParticle(self.currentParticleIndex)
self.spectrumSelector.setValue(1)
self.spectrumSelector.setMaximum(len(specIndices))
if len(specIndices) > 0:
self.spectrumSelector.setDisabled(False)
self.spectrumSelector.setValue(1)
self.spectrumSelector.setMaximum(len(specIndices))
self.currentSpectrumIndex = specIndices[self.spectrumSelector.value()-1]
self.specNumberSelector.setValue(self.currentSpectrumIndex+1)
else:
self.spectrumSelector.setDisabled(True)
self.spectrumSelector.setValue(0)
self.spectrumSelector.setMaximum(0)
self.spectrumNumberLabel.setText(f'of {len(specIndices)} spectra')
self.currentSpectrumIndex = specIndices[self.spectrumSelector.value()-1]
self.specNumberSelector.setValue(self.currentSpectrumIndex+1)
self.typeSelectorCombo.currentIndexChanged.connect(self.setTypeSelector)
self.spectrumSelector.valueChanged.connect(self.setSpecSelector)
self.particleSelector.valueChanged.connect(self.setParticleSelector)
......@@ -232,10 +238,6 @@ class PolymerNavigationToolbar(QtWidgets.QGroupBox):
def setParticleSelector(self):
assignment = self.typeSelectorCombo.currentText()
if assignment != '':
# if self.lastParticleIndex is not None:
# self.currentParticleIndex = self.lastParticleIndex
# self.lastParticleIndex = None
# else:
partIndices = self.particleContainer.getIndicesOfParticleType(assignment)
self.currentParticleIndex = partIndices[self.particleSelector.value()-1]
......@@ -246,22 +248,22 @@ class PolymerNavigationToolbar(QtWidgets.QGroupBox):
self.setSpecSelector()
def setSpecSelector(self):
# if self.lastSpecIndex is not None:
# self.currentSpectrumIndex = self.lastSpecIndex
# self.lastSpecIndex = None
# else:
specIndices = self.particleContainer.getSpectraIndicesOfParticle(self.currentParticleIndex)
self.currentSpectrumIndex = specIndices[self.spectrumSelector.value()-1]
self.specNumberSelector.setValue(self.currentSpectrumIndex+1)
self.WidgetsUpdated.emit()
self.JumpToIndicatedSpec.emit()
if len(specIndices) == 0:
self.spectrumSelector.setDisabled(True)
else:
self.spectrumSelector.setDisabled(False)
self.currentSpectrumIndex = specIndices[self.spectrumSelector.value()-1]
self.specNumberSelector.setValue(self.currentSpectrumIndex+1)
if self.lastSpecIndex is not None:
self.currentParticleIndex = self.particleContainer.getParticleIndexContainingSpecIndex(self.lastSpecIndex)
self.lastSpecIndex = None
self.setWidgetsToNewParticleIndex(self.currentParticleIndex)
self.JumpToIndicatedSpec.emit()
self.WidgetsUpdated.emit()
class FindColoredParticleWindow(QtWidgets.QWidget):
......
......@@ -76,7 +76,6 @@ class ExpExcelDialog(QtWidgets.QDialog):
polymers = np.array(self.particleContainer.getListOfParticleAssignments())
sizes = np.array(self.particleContainer.getSizesOfAllParticles())
for box in self.checkBoxes:
if box.isChecked() == True:
if box.text() != 'Size Classes':
......
......@@ -121,7 +121,6 @@ class LoadTrueMatchResults(QtWidgets.QWidget):
print('spectra in batch:', len(resBatch))
for result in resBatch:
specIndex, polymertype, additive, hqi, addhqi = self.interpretEntry(resBatchIndex, numSpectraInPreviousBatches, result, numhits, numcomps)
print('assigning currentSpecIndex', specIndex)
self.polymertypes[specIndex] = polymertype
self.hqis[specIndex] = hqi
if numcomps > 1:
......
......@@ -44,13 +44,19 @@ class Particle(object):
meas.setHQI(100)
def getParticleAssignment(self):
return self.getMeasAssignmentWithHighestHQI() #probably another method could be more suitable...
assignment = 'NotYetMeasured'
if len(self.measurements) > 0:
assignment = self.getMeasAssignmentWithHighestHQI() #probably another method could be more suitable...
return assignment
def getHighestHQI(self):
hqis = []
for meas in self.measurements:
hqis.append(meas.getHQI())
return max(hqis)
maxHQI = None
if len(self.measurements) > 0:
hqis = []
for meas in self.measurements:
hqis.append(meas.getHQI())
maxHQI = max(hqis)
return maxHQI
def getHQIOfMeasurementIndex(self, index):
for meas in self.measurements:
......
......@@ -239,7 +239,7 @@ def getParticleCenterPoint(contour):
return x, y
def loadFullimageFromDataset(dataset):
return cv2imread_fix(dataset.getImageName(), cv2.COLOR_BGR2RGB)
return cv2imread_fix(dataset.getImageName())
def loadZValImageFromDataset(dataset):
return cv2imread_fix(dataset.getZvalImageName(), cv2.IMREAD_GRAYSCALE)
\ No newline at end of file
......@@ -44,6 +44,8 @@ class ParticleContainer(object):
def clearMeasurements(self):
self.measurements = []
for particle in self.particles:
particle.measurements = []
def setMeasurementScanIndex(self, indexOfMeasurment, scanIndex):
self.measurements[indexOfMeasurment].ramanScanIndex = scanIndex
......@@ -94,7 +96,7 @@ class ParticleContainer(object):
particle.contour = contours[index]
def setParticleStats(self, particlestats):
assert len(self.particles) == len(particlestats)
assert len(self.particles) == len(particlestats), f'numParticles = {len(self.particles)}, len partStats = {len(particlestats)}'
for index, particle in enumerate(self.particles):
particle.__dict__.update(particlestats[index].__dict__)
......
......@@ -148,7 +148,7 @@ class DataSet(object):
'minparticlearea': 20,
'minparticledistance': 20,
'measurefrac': 1,
'compactness': 0.1,
'compactness': 0.0,
'seedRad': 3}
self.particleContainer = ParticleContainer(self)
......
......@@ -20,11 +20,14 @@ If not, see <https://www.gnu.org/licenses/>.
"""
import numpy as np
from PyQt5 import QtCore, QtWidgets, QtGui
from .segmentation import Segmentation
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
import matplotlib.pyplot as plt
from threading import Thread
from .segmentation import Segmentation
from .analysis.particleCharacterization import getParticleStatsWithPixelScale, loadZValImageFromDataset
from .errors import InvalidParticleError
Nscreen = 1000
class HistWidget(QtWidgets.QWidget):
......@@ -377,8 +380,8 @@ class ParticleDetectionView(QtWidgets.QWidget):
grid.addWidget(label, i+1, 0, QtCore.Qt.AlignLeft)
grid.addWidget(self.seedradiusedit, i+1, 1, QtCore.Qt.AlignLeft)
grid.addWidget(self.showseedpoints, i+2, 0, 1, 2, QtCore.Qt.AlignLeft)
grid.addWidget(QtWidgets.QLabel("Use Ctrl for seeds and Ctrl+Shift for delete points"), i+3, 0, 1, 2, QtCore.Qt.AlignLeft)
grid.addWidget(QtWidgets.QLabel("Ctrl+Alt removes seeds near cursor"), i+4, 0, 1, 2, QtCore.Qt.AlignLeft)
grid.addWidget(QtWidgets.QLabel("Click mouse to add seeds, Click+Shift to add deletepoints"), i+3, 0, 1, 2, QtCore.Qt.AlignLeft)
grid.addWidget(QtWidgets.QLabel("Click+Alt removes seeds near cursor"), i+4, 0, 1, 2, QtCore.Qt.AlignLeft)
group.setLayout(grid)
vbox.addWidget(group)
......@@ -565,18 +568,12 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.seg.setParameters(**kwargs)
seedradius = self.seedradiusedit.value()
if showname is not None:
stepImg, imgtype = self.seg.apply2Image(img, self.imglabel.seedpoints,
self.imglabel.seeddeletepoints,
seedradius,
self.dataset,
return_step=showname)
stepImg, imgtype = self.seg.apply2Image(img, self.imglabel.seedpoints, self.imglabel.seeddeletepoints,
seedradius, self.dataset, return_step=showname)
self.imglabel.showStep(stepImg, imgtype)
else:
measurementpoints, contours, particlestats = self.seg.apply2Image(img,
self.imglabel.seedpoints,
self.imglabel.seeddeletepoints,
seedradius,
self.dataset)
measurementpoints, contours = self.seg.apply2Image(img, self.imglabel.seedpoints, self.imglabel.seeddeletepoints,
seedradius, self.dataset)
self.imglabel.updateDetectionResults(contours, measurementpoints)
@QtCore.pyqtSlot()
......@@ -628,15 +625,16 @@ class ParticleDetectionView(QtWidgets.QWidget):
def checkOnComputation(self):
if self.thread is not None:
if not self.threadrunning:
#self.thread.join()
self.thread = None
self.unBlockUI()
self.pdetectall.setText("Detect all")
self.imageUpdate.emit(self.view.microscopeMode)
if self.dataset is not None:
self.setWindowTitle(str(self.dataset.particleContainer.getNumberOfParticles()) + " Particles")
numParticles = self.dataset.particleContainer.getNumberOfParticles()
numMeasurements = self.dataset.particleContainer.getNumberOfMeasurements()
self.setWindowTitle(f'{numParticles} Particles ({numMeasurements} Measurements)')
else:
self.timer.start(100.)
self.timer.start(100.)
def _worker(self):
kwargs = {}
......@@ -648,27 +646,27 @@ class ParticleDetectionView(QtWidgets.QWidget):
kwargs[name] = valuefunc()
seedradius = self.seedradiusedit.value()
self.seg.setParameters(**kwargs)
measurementPoints, contours, particlestats = self.seg.apply2Image(self.img,
seedpoints,
deletepoints,
seedradius,
self.dataset)
measurementPoints, contours= self.seg.apply2Image(self.img, seedpoints, deletepoints, seedradius, self.dataset)
if measurementPoints is None: # computation was canceled
return
if self.dataset is not None:
self.applyResultsToDataset(measurementPoints, contours, particlestats)
self.applyResultsToDataset(measurementPoints, contours)
self.threadrunning = False
def applyResultsToDataset(self, measurementPoints, contours, particlestats):
def applyResultsToDataset(self, measurementPoints, contours):
self.dataset.ramanscandone = False
particlestats = self.getParticleStats(contours)
particleContainer = self.dataset.particleContainer
numParticles = len(contours)
particleContainer.initializeParticles(numParticles)
particleContainer.setParticleContours(contours)
particleContainer.setParticleStats(particlestats)
particleContainer.clearMeasurements()
for particleIndex in measurementPoints.keys():
measPoints = measurementPoints[particleIndex]
for index, point in enumerate(measPoints):
......@@ -680,3 +678,16 @@ class ParticleDetectionView(QtWidgets.QWidget):
self.dataset.particleDetectionDone = True
self.dataset.mode = "prepareraman"
self.dataset.save()
def getParticleStats(self, contours):
particlestats = []
zvalimg = loadZValImageFromDataset(self.dataset)
for contour in contours:
try:
stats = getParticleStatsWithPixelScale(contour, self.dataset, fullimage=self.img, zimg=zvalimg)
particlestats.append(stats)
except InvalidParticleError:
print('invalid contour in detection, skipping partile. Contour is:', contour)
continue
return particlestats
\ No newline at end of file
......@@ -77,6 +77,7 @@ def legacyConversion(dset, recreatefullimage=False):
del dset.particleimgs
dset.version = 1
dset.save()
if dset.version == 1:
print("Converting legacy version 1 to 2")
......@@ -95,17 +96,20 @@ def legacyConversion(dset, recreatefullimage=False):
dset.particles2spectra = [[int(np.where(dset.ramanscansortindex == i)[0])] for i in range(len(dset.ramanscansortindex))]
dset.version = 2
dset.save()
if dset.version == 2:
print("Converting legacy version 2 to 3")
transferParticleStatsToParticleContainer(dset)
dset.version = 3
dset.save()
if dset.version == 3:
print("Converting legacy version 3 to 4")
updateParticleStats(dset)
removeLegacyAttributes(dset)
dset.version = 4
dset.save()
# add later conversion for higher version numbers here
......
......@@ -93,7 +93,7 @@ class BackGroundManager(QtWidgets.QWidget):
QtWidgets.QMessageBox.about(self, 'Warning', 'No Background Image is aquired')
return
else:
from opticalscan import loadAndPasteImage
from .opticalscan import loadAndPasteImage
self.dataset = self.parentOSwidget.dataset
#acquire images in 3x3 area to preview quality of background subtraction
......
......@@ -94,7 +94,7 @@ def loadAndPasteImage(srcnames, fullimage, fullzval, width, height,
curImg = cv2imread_fix(name)
if background is not None:
curImg = subtractBackground(curImg, background)
colimgs.append(cv2.cvtColor(curImg, cv2.COLOR_BGR2RGB))
colimgs.append(curImg)
img, zval = imageStacking(colimgs)
x, y = p
......@@ -276,7 +276,7 @@ class OpticalScan(QtWidgets.QWidget):
self.zmaxedit.setMaximumWidth(100)
label3 = QtWidgets.QLabel("Focus steps:", self)
self.nzedit = QtWidgets.QSpinBox(self)
self.nzedit.setRange(2,20)
self.nzedit.setRange(1,20)
self.nzedit.setValue(3)
self.nzedit.setMaximumWidth(100)
self.hdrcheck = QtWidgets.QCheckBox("High dynamic range", self)
......@@ -451,7 +451,7 @@ class OpticalScan(QtWidgets.QWidget):
width, height, rotationvalue = self.ramanctrl.getImageDimensions(self.view.microscopeMode)
pshift = self.ramanctrl.getRamanPositionShift()
self.dataset.pshift = pshift
img = cv2.cvtColor(cv2imread_fix(self.dataset.getTmpImageName()), cv2.COLOR_BGR2RGB)
img = cv2imread_fix(self.dataset.getTmpImageName())
self.dataset.imagedim_bf = self.ramanctrl.getImageDimensions('bf')
self.dataset.pixelscale_bf = self.dataset.imagedim_bf[0]/img.shape[1] #=imagedim_width/shape[1]
......
......@@ -205,7 +205,7 @@ class WITecCOM(RamanBase):
z = self.PosZCurUserFloatMan.GetSingleValueAsDouble()[1]
return z
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011, debugReturn=False, measurementRunning=False):
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011):
assert self.connected
initpos = self.getPosition()
# move only if new position is really different; repeat if new position is ignored (happens some times)
......
......@@ -45,7 +45,7 @@ class RamanBase(object):
def getUserZ(self):
raise NotImplementedError
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011, debugReturn=False, measurementRunning=False):
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011):
raise NotImplementedError
def moveZto(self, z, epsz=0.011):
......
......@@ -39,10 +39,10 @@ class SimulatedRaman(RamanBase):
self.currentZ = 0.
# some plausible data to simulate consecutively changing positions
self.positionlist = np.array([[ -1201, 1376, -1290],
[ -1195, -9200, -1279],
[ 1097, -9254, -1297],
[ 2704.1, -1788.2, -138.1],
[ 3884. , -2650.8, -138.1]])
[ -1195, -1200, -1279],
[ 1097, -1254, -1297],
[ 2704.1, 1288.2, -1381],
[ 1884. , -1500.8, -1381]])
self.znum = 4
self.gridnum = 36
self.positionindex = 0
......@@ -78,7 +78,7 @@ class SimulatedRaman(RamanBase):
else:
return self.currentZ
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011, debugReturn=False, measurementRunning=False):
def moveToAbsolutePosition(self, x, y, z=None, epsxy=0.11, epsz=0.011):
assert self.connected
print('moving to:', x, y, z, file=stdout)
if z is None:
......
......@@ -67,7 +67,7 @@ def scan(ramanSettings, positions, controlclass, dataqueue, stopevent,
x, y, z = p
print("time:", time(), flush=True)
print("position:", x, y, z, flush=True)
ramanctrl.moveToAbsolutePosition(x, y, z, measurementRunning=True)
ramanctrl.moveToAbsolutePosition(x, y, z)
print("move done", flush=True)
ramanctrl.triggerMeasurement(i)
print("trigger done", flush=True)
......@@ -145,7 +145,6 @@ class RamanScanUI(QtWidgets.QWidget):
self.setLayout(vbox)
self.setWindowTitle("Raman Scan")
#self.show()
self.setVisible(False)
def makeGetFnameLambda(self, msg, path, fileType, btn):
......@@ -159,9 +158,10 @@ class RamanScanUI(QtWidgets.QWidget):
def resetDataset(self, ds):
self.dataset = ds
numParticles = self.dataset.particleContainer.getNumberOfParticles()
numMeasurements = self.dataset.particleContainer.getNumberOfMeasurements()
if numParticles>0:
self.prun.setEnabled(True)
self.setWindowTitle(str(numParticles) + " Particles")
self.setWindowTitle(f'{numParticles} Particles ({numMeasurements} Measurements)')
@QtCore.pyqtSlot()
def stopScan(self):
......@@ -234,27 +234,38 @@ class RamanScanUI(QtWidgets.QWidget):
self.view.saveDataSet()
self.view.prepareAnalysis()
self.view.zoomDisplay(2.0)
self.view.highLightRamanIndex(0)
self.view.blockUI()
self.group2.setEnabled(False)
self.progresstime.setEnabled(True)
self.progressbar.setEnabled(True)
self.progressbar.setRange(0, len(scanpoints))
self.progressbar.setValue(0)
self.ramanctrl.disconnect()
self.processstopevent = Event()
self.dataqueue = Queue()
self.process = Process(target=scan, args=(ramanSettings, scanpoints,
self.ramanctrl.__class__,
self.dataqueue,
self.processstopevent,
self.logpath))
self.process.start()
self.starttime = time()
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.checkOnScan)
self.timer.setSingleShot(True)
self.timer.start(10000.)
if self.ramanctrl.name == 'RenishawCOM':
QtWidgets.QMessageBox.about(self, "Info", "Control is headed over to Renishaw Instrument, Gepard is stopping here")
ramanSettings['Points'] = scanpoints
self.ramanctrl.initiateMeasurement(ramanSettings)
self.ramanctrl.disconnect()
self.dataset.ramanscandone = True
self.view.saveDataSet()
self.close()
return
else:
self.view.highLightRamanIndex(0)
self.view.blockUI()
self.group2.setEnabled(False)
self.progresstime.setEnabled(True)
self.progressbar.setEnabled(True)
self.progressbar.setRange(0, len(scanpoints))
self.progressbar.setValue(0)
self.ramanctrl.disconnect()
self.processstopevent = Event()
self.dataqueue = Queue()
self.process = Process(target=scan, args=(ramanSettings, scanpoints,
self.ramanctrl.__class__,
self.dataqueue,
self.processstopevent,
self.logpath))
self.process.start()
self.starttime = time()
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.checkOnScan)
self.timer.setSingleShot(True)
self.timer.start(10000.)
@QtCore.pyqtSlot()
def checkOnScan(self):
......
......@@ -193,7 +193,6 @@ class SampleView(QtWidgets.QGraphicsView):
self.oscanwidget.setVisible(False)
if self.detectionwidget is not None:
self.detectionwidget.close()
self.detectionwidget.destroy()
self.detectionwidget = None
self.ramanwidget.setVisible(False)
self.mode = mode
......@@ -530,7 +529,6 @@ class SampleView(QtWidgets.QGraphicsView):
if self.mode == "ParticleDetection" or self.mode == "ParticleAnalysis":
self.resetParticleContours()
if data is None and os.path.exists(fname):
# data = cv2.cvtColor(cv2imread_fix(fname), cv2.COLOR_BGR2RGB) ##With this line the B and R channel are swapped, which leads to a wrong presentation of the image in gepard..... Why was this line here?
data = cv2imread_fix(fname)
self.imgdata = data
if data is not None:
......@@ -579,10 +577,17 @@ class SampleView(QtWidgets.QGraphicsView):
Removes items from the GraphicsScene. ContourItems remain, however..
:return:
"""
for itemList in [self.fititems, self.scanitems, self.ramanscanitems]:
for item in itemList:
self.scene().removeItem(item)
itemList = []
for item in self.fititems:
self.scene().removeItem(item)
self.fititems = []
for item in self.scanitems:
self.scene().removeItem(item)
self.scanitems = []
for item in self.ramanscanitems:
self.scene().removeItem(item)
self.ramanscanitems = []
edges, nodes = self.boundaryitems
for item in edges:
......@@ -590,7 +595,6 @@ class SampleView(QtWidgets.QGraphicsView):
for item in nodes:
self.scene().removeItem(item)
self.boundaryitems = [], []
@QtCore.pyqtSlot()
def resetScanPositions(self):
......
......@@ -26,25 +26,15 @@ from scipy.interpolate import InterpolatedUnivariateSpline
from scipy import ndimage as ndi
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from random import random
from .errors import InvalidParticleError
import random
def closeHolesOfSubImage(subimg):
#Add padding to TrehsholdImage
subimg = cv2.copyMakeBorder(subimg, 1, 1, 1, 1, 0)
# Copy the thresholded image.
im_floodfill = subimg.copy()
# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = subimg.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)
# Floodfill from point (0, 0)
cv2.floodFill(im_floodfill, mask, (0,0), 255);
# Invert floodfilled image
im_floodfill_inv = cv2.bitwise_not(im_floodfill)
# Combine the two images to get the foreground.
im_out = subimg | im_floodfill_inv
return im_out[1:-1, 1:-1]
......@@ -83,11 +73,12 @@ class Segmentation(object):
'invertThresh': False,
'maxholebrightness': 0.5,
'minparticlearea': 20,
'maxparticlearea': 10000,
'enableMaxArea': False,
'maxparticlearea': 100000,
'minparticledistance': 20,
'closeBackground': True,
'measurefrac': 1,
'compactness': 0.,
'compactness': 0.0,
'seedRad': 3}
if dataset is not None:
self.detectParams = dataset.detectParams
......@@ -111,6 +102,7 @@ class Segmentation(object):
Parameter("upThresh", float, self.detectParams['upThresh'], .01, 1.0, 2, .02, helptext="Upper threshold", show=True),
Parameter("maxholebrightness", float, self.detectParams['maxholebrightness'], 0, 1, 2, 0.02, helptext="Close holes brighter than..", show = True),
Parameter("minparticlearea", int, self.detectParams['minparticlearea'], 1, 1000, 0, 50, helptext="Min. particle pixel area", show=False),
Parameter("enableMaxArea", np.bool, self.detectParams['enableMaxArea'], helptext="enable filtering for maximal pixel area", show=False, linkedParameter='maxparticlearea'),
Parameter("maxparticlearea", int, self.detectParams['maxparticlearea'], 10, 1E9, 0, 50, helptext="Max. particle pixel area", show=True),
Parameter("minparticledistance", int, self.detectParams['minparticledistance'], 5, 1000, 0, 5, helptext="Min. distance between particles", show=False),
Parameter("measurefrac", float, self.detectParams['measurefrac'], 0, 1, 2, stepsize = 0.05, helptext="measure fraction of particles", show=False),
......@@ -256,10 +248,18 @@ class Segmentation(object):
subdist = cv2.distanceTransform(subimg, cv2.DIST_L2,3)
subfg = np.uint8(peak_local_max(