Commit 3ea53e47 authored by Josef Brandt's avatar Josef Brandt

RandomBoxSampling

Also Quarter RandomBoxSampling
parent c070f4ab
...@@ -43,6 +43,7 @@ def get_methods_to_test(dataset: dataset.DataSet, fractions: list = []) -> list: ...@@ -43,6 +43,7 @@ def get_methods_to_test(dataset: dataset.DataSet, fractions: list = []) -> list:
boxCreator: gmeth.BoxSelectionCreator = gmeth.BoxSelectionCreator(dataset) boxCreator: gmeth.BoxSelectionCreator = gmeth.BoxSelectionCreator(dataset)
methods += boxCreator.get_crossBoxSubsamplers_for_fraction(fraction) methods += boxCreator.get_crossBoxSubsamplers_for_fraction(fraction)
methods += boxCreator.get_spiralBoxSubsamplers_for_fraction(fraction) methods += boxCreator.get_spiralBoxSubsamplers_for_fraction(fraction)
methods += boxCreator.get_randomBoxSubsamplers_for_fraction(fraction)
# methods.append(cmeth.ChemometricSubsampling(particleContainer, fraction)) # methods.append(cmeth.ChemometricSubsampling(particleContainer, fraction))
return methods return methods
......
This diff is collapsed.
...@@ -4,7 +4,7 @@ sys.path.append("C://Users//xbrjos//Desktop//Python") ...@@ -4,7 +4,7 @@ sys.path.append("C://Users//xbrjos//Desktop//Python")
import gepard import gepard
from gepard import dataset from gepard import dataset
from gui.filterView import FilterView from gui.filterView import FilterView
from gui.measureModes import MeasureMode, CrossBoxMode, CrossBoxesControls, SpiralBoxMode from gui.measureModes import *
import helpers import helpers
from evaluation import SubsamplingResult from evaluation import SubsamplingResult
...@@ -55,10 +55,17 @@ class MainView(QtWidgets.QWidget): ...@@ -55,10 +55,17 @@ class MainView(QtWidgets.QWidget):
self._switch_to_default_mode() self._switch_to_default_mode()
def _add_measure_modes(self) -> None: def _add_measure_modes(self) -> None:
self.measureModes['spiralSelection'] = SpiralBoxMode(self.filterView) self.measureModes['Random Particle Selection'] = RandomMeasureMode(self.filterView)
self.measureModes['crossSelection'] = CrossBoxMode(self.filterView) self.measureModes['Spiral Box Selection'] = SpiralBoxMode(self.filterView)
self.modeSelector.addItem('spiralSelection') self.measureModes['Cross Box Selection'] = CrossBoxMode(self.filterView)
self.modeSelector.addItem('crossSelection') self.measureModes['Random Box Selection'] = RandomBoxMode(self.filterView)
self.measureModes['Quarter Random Box Selection'] = QuarterRandomBoxMode(self.filterView)
self.modeSelector.addItem('Random Particle Selection')
self.modeSelector.addItem('Spiral Box Selection')
self.modeSelector.addItem('Cross Box Selection')
self.modeSelector.addItem('Random Box Selection')
self.modeSelector.addItem('Quarter Random Box Selection')
for mode in self.measureModes.values(): for mode in self.measureModes.values():
mode.updatedResult.connect(self.infoWidget.update_results) mode.updatedResult.connect(self.infoWidget.update_results)
...@@ -101,8 +108,8 @@ class MainView(QtWidgets.QWidget): ...@@ -101,8 +108,8 @@ class MainView(QtWidgets.QWidget):
self.filterView.filter.update_filterSize(width, height, diameter, (offsetx, offsety)) self.filterView.filter.update_filterSize(width, height, diameter, (offsetx, offsety))
for mode in self.measureModes.values(): for mode in self.measureModes.values():
mode.boxSelectionMethod.particleContainer = dset.particleContainer mode.method.particleContainer = dset.particleContainer
mode.boxSelectionMethod.offset = (offsetx, offsety) mode.method.offset = (offsetx, offsety)
self.filterView.update_from_dataset(dset) self.filterView.update_from_dataset(dset)
self.activeMode.update_measure_viewItems() self.activeMode.update_measure_viewItems()
......
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
from gui.filterView import FilterView, MeasureBoxGraphItem from gui.filterView import FilterView, MeasureBoxGraphItem
from geometricMethods import BoxSelectionSubsamplingMethod, CrossBoxSubSampling, SpiralBoxSubsampling from methods import *
from geometricMethods import *
from evaluation import SubsamplingResult from evaluation import SubsamplingResult
class MeasureMode(QtCore.QObject): class MeasureMode(QtCore.QObject):
updatedResult: QtCore.pyqtSignal = QtCore.pyqtSignal(SubsamplingResult) updatedResult: QtCore.pyqtSignal = QtCore.pyqtSignal(SubsamplingResult)
def __init__(self, relatedFilterView: FilterView): def __init__(self, relatedFilterView: FilterView) -> None:
super(MeasureMode, self).__init__() super(MeasureMode, self).__init__()
self.filterView: FilterView = relatedFilterView self.filterView: FilterView = relatedFilterView
self.uiControls: QtWidgets.QGroupBox = QtWidgets.QGroupBox() self.uiControls: QtWidgets.QGroupBox = QtWidgets.QGroupBox()
self.boxSelectionMethod: BoxSelectionSubsamplingMethod = None self.method: SubsamplingMethod = None
self.subsamplingResult: SubsamplingResult = SubsamplingResult(self.boxSelectionMethod) self.subsamplingResult: SubsamplingResult = SubsamplingResult(self.method)
self.subParticles: list = [] self.subParticles: list = []
def get_control_groupBox(self) -> QtWidgets.QGroupBox: def get_control_groupBox(self) -> QtWidgets.QGroupBox:
return self.uiControls return self.uiControls
def update_measure_viewItems(self) -> None: def update_measure_viewItems(self) -> None:
raise NotImplementedError self.method.filterDiameter = self.filterView.filter.diameter
self.method.numBoxes = self.uiControls.numBoxesSpinbox.value()
self.method.fraction = self.uiControls.coverageSpinbox.value() / 100
topLefts: list = self.method.get_topLeft_of_boxes()
boxSize = self.method.boxSize
self.filterView.update_measure_boxes(topLefts, boxSize)
self.send_measuredParticles_to_filterview()
def send_measuredParticles_to_filterview(self) -> None: def send_measuredParticles_to_filterview(self) -> None:
if self.boxSelectionMethod.particleContainer is not None: if self.method.particleContainer is not None:
subParticles = self.boxSelectionMethod.apply_subsampling_method() subParticles = self.method.apply_subsampling_method()
self.subsamplingResult.method = self.boxSelectionMethod self.subsamplingResult.method = self.method
self.subsamplingResult.reset_results() self.subsamplingResult.reset_results()
self.subsamplingResult.add_result(self.boxSelectionMethod.particleContainer.particles, subParticles) self.subsamplingResult.add_result(self.method.particleContainer.particles, subParticles)
self.updatedResult.emit(self.subsamplingResult) self.updatedResult.emit(self.subsamplingResult)
self.filterView.update_measured_particles(subParticles) self.filterView.update_measured_particles(subParticles)
class RandomMeasureMode(MeasureMode):
updatedResult: QtCore.pyqtSignal = QtCore.pyqtSignal(SubsamplingResult)
def __init__(self, filterView: FilterView):
super(RandomMeasureMode, self).__init__(filterView)
self.method: RandomSampling = RandomSampling(None)
self.uiControls = ParticleModeControlGroup(self, 'Random Particle Measurement')
def update_measure_viewItems(self) -> None:
self.method.fraction = self.uiControls.coverageSpinbox.value() / 100
self.filterView.update_measure_boxes([], 0.0)
self.send_measuredParticles_to_filterview()
class ParticleModeControlGroup(QtWidgets.QGroupBox):
def __init__(self, measureModeParent: MeasureMode, title: str) -> None:
super(ParticleModeControlGroup, self).__init__()
self.measureModeParent = measureModeParent
self.setTitle(title)
layout = QtWidgets.QHBoxLayout()
self.setLayout(layout)
layout.addWidget(QtWidgets.QLabel('Desired Coverage (%)'))
self.coverageSpinbox = QtWidgets.QSpinBox()
self.coverageSpinbox.setFixedWidth(50)
self.coverageSpinbox.setMinimum(0)
self.coverageSpinbox.setMaximum(100)
self.coverageSpinbox.setValue(10)
self.coverageSpinbox.valueChanged.connect(self._config_changed)
layout.addWidget(self.coverageSpinbox)
def _config_changed(self) -> None:
self.measureModeParent.update_measure_viewItems()
class CrossBoxMode(MeasureMode): class CrossBoxMode(MeasureMode):
def __init__(self, *args): def __init__(self, *args):
super(CrossBoxMode, self).__init__(*args) super(CrossBoxMode, self).__init__(*args)
self.uiControls = CrossBoxesControls(self) self.uiControls = CrossBoxesControls(self)
self.boxSelectionMethod: CrossBoxSubSampling = CrossBoxSubSampling(None) self.method: CrossBoxSubSampling = CrossBoxSubSampling(None)
self.update_measure_viewItems() self.update_measure_viewItems()
def update_measure_viewItems(self) -> None: def update_measure_viewItems(self) -> None:
self.boxSelectionMethod.filterDiameter = self.filterView.filter.diameter self.method.filterDiameter = self.filterView.filter.diameter
self.boxSelectionMethod.numBoxesAcross = int(self.uiControls.numBoxesSelector.currentText()) self.method.numBoxesAcross = int(self.uiControls.numBoxesSelector.currentText())
desiredCoverage: int = self.uiControls.coverageSpinbox.value() desiredCoverage: int = self.uiControls.coverageSpinbox.value()
maxCoverage: int = int(self.boxSelectionMethod.get_maximum_achievable_fraction() * 100) maxCoverage: int = int(self.method.get_maximum_achievable_fraction() * 100)
self.uiControls.set_to_max_possible_coverage(maxCoverage) self.uiControls.set_to_max_possible_coverage(maxCoverage)
if desiredCoverage > maxCoverage: if desiredCoverage > maxCoverage:
desiredCoverage = maxCoverage desiredCoverage = maxCoverage
self.boxSelectionMethod.fraction = desiredCoverage / 100 self.method.fraction = desiredCoverage / 100
topLefts: list = self.boxSelectionMethod.get_topLeft_of_boxes() topLefts: list = self.method.get_topLeft_of_boxes()
boxSize = self.boxSelectionMethod.boxSize boxSize = self.method.boxSize
self.filterView.update_measure_boxes(topLefts, boxSize) self.filterView.update_measure_boxes(topLefts, boxSize)
self.send_measuredParticles_to_filterview() self.send_measuredParticles_to_filterview()
...@@ -96,33 +141,14 @@ class CrossBoxesControls(QtWidgets.QGroupBox): ...@@ -96,33 +141,14 @@ class CrossBoxesControls(QtWidgets.QGroupBox):
self.coverageSpinbox.valueChanged.connect(self._config_changed) self.coverageSpinbox.valueChanged.connect(self._config_changed)
class SpiralBoxMode(MeasureMode): class BoxControlGroup(QtWidgets.QGroupBox):
def __init__(self, *args):
super(SpiralBoxMode, self).__init__(*args)
self.uiControls: SpiralBoxControls = SpiralBoxControls(self)
self.boxSelectionMethod: SpiralBoxSubsampling = SpiralBoxSubsampling(None)
self.update_measure_viewItems()
def update_measure_viewItems(self) -> None:
self.boxSelectionMethod.filterDiameter = self.filterView.filter.diameter
self.boxSelectionMethod.numBoxes = self.uiControls.numBoxesSpinbox.value()
self.boxSelectionMethod.fraction = self.uiControls.coverageSpinbox.value() / 100
topLefts: list = self.boxSelectionMethod.get_topLeft_of_boxes()
boxSize = self.boxSelectionMethod.boxSize
self.filterView.update_measure_boxes(topLefts, boxSize)
self.send_measuredParticles_to_filterview()
class SpiralBoxControls(QtWidgets.QGroupBox):
""" """
Gives a groupbox with the controls for setting up the cross boxes. Gives a groupbox with the controls for setting up the cross boxes.
""" """
def __init__(self, measureModeParent: MeasureMode): def __init__(self, measureModeParent: MeasureMode, title: str) -> None:
super(SpiralBoxControls, self).__init__() super(BoxControlGroup, self).__init__()
self.setTitle('Spiral Box Controls') self.setTitle(title)
self.measureModeParent = measureModeParent self.measureModeParent = measureModeParent
layout = QtWidgets.QHBoxLayout() layout = QtWidgets.QHBoxLayout()
self.setLayout(layout) self.setLayout(layout)
...@@ -144,6 +170,46 @@ class SpiralBoxControls(QtWidgets.QGroupBox): ...@@ -144,6 +170,46 @@ class SpiralBoxControls(QtWidgets.QGroupBox):
self.coverageSpinbox.valueChanged.connect(self._config_changed) self.coverageSpinbox.valueChanged.connect(self._config_changed)
layout.addWidget(self.coverageSpinbox) layout.addWidget(self.coverageSpinbox)
def _config_changed(self): def _config_changed(self) -> None:
if self.numBoxesSpinbox.value() > 0: if self.numBoxesSpinbox.value() > 0:
numBoxes: int = self.numBoxesSpinbox.value()
self.measureModeParent.method.numBoxes = numBoxes
maxCoverage: float = self.measureModeParent.method.get_maximum_achievable_fraction()
self.set_to_max_possible_coverage(round(maxCoverage * 100))
self.measureModeParent.update_measure_viewItems() self.measureModeParent.update_measure_viewItems()
def set_to_max_possible_coverage(self, maxCoverage: int) -> None:
"""
Adjusts maximum of coverage spinbox and, if necessary, caps the current value.
:param maxCoverage: the maximum pssible converage IN PERCENT!!
:return:
"""
self.coverageSpinbox.setMaximum(maxCoverage)
if maxCoverage < self.coverageSpinbox.value():
self.coverageSpinbox.valueChanged.disconnect()
self.coverageSpinbox.setValue(maxCoverage)
self.coverageSpinbox.valueChanged.connect(self._config_changed)
class SpiralBoxMode(MeasureMode):
def __init__(self, *args):
super(SpiralBoxMode, self).__init__(*args)
self.uiControls: BoxControlGroup = BoxControlGroup(self, 'Spiral Box Controls')
self.method: SpiralBoxSubsampling = SpiralBoxSubsampling(None)
self.update_measure_viewItems()
class RandomBoxMode(MeasureMode):
def __init__(self, *args):
super(RandomBoxMode, self).__init__(*args)
self.uiControls: BoxControlGroup = BoxControlGroup(self, 'Random Box Controls')
self.method: RandomBoxSampling = RandomBoxSampling(None)
self.update_measure_viewItems()
class QuarterRandomBoxMode(MeasureMode):
def __init__(self, *args):
super(QuarterRandomBoxMode, self).__init__(*args)
self.uiControls: BoxControlGroup = BoxControlGroup(self, 'Quarter Random Box Controls')
self.method: RandomQuarterBoxes = RandomQuarterBoxes(None)
self.update_measure_viewItems()
...@@ -11,6 +11,8 @@ from helpers import ParticleBinSorter ...@@ -11,6 +11,8 @@ from helpers import ParticleBinSorter
class SubsamplingMethod(object): class SubsamplingMethod(object):
randomSeed = 15203018
def __init__(self, particleConatainer, desiredFraction: float = 0.2): def __init__(self, particleConatainer, desiredFraction: float = 0.2):
super(SubsamplingMethod, self).__init__() super(SubsamplingMethod, self).__init__()
self.particleContainer = particleConatainer self.particleContainer = particleConatainer
...@@ -65,6 +67,14 @@ class SubsamplingMethod(object): ...@@ -65,6 +67,14 @@ class SubsamplingMethod(object):
matches = (self.label.lower().find(pattern.lower()) != -1) matches = (self.label.lower().find(pattern.lower()) != -1)
return matches return matches
def config_is_valid(self) -> bool:
isValid: bool = False
if self.fraction <= self.get_maximum_achievable_fraction():
isValid = True
return isValid
def get_maximum_achievable_fraction(self) -> float:
raise NotImplementedError
class RandomSampling(SubsamplingMethod): class RandomSampling(SubsamplingMethod):
@property @property
...@@ -82,6 +92,9 @@ class RandomSampling(SubsamplingMethod): ...@@ -82,6 +92,9 @@ class RandomSampling(SubsamplingMethod):
def equals(self, otherMethod) -> bool: def equals(self, otherMethod) -> bool:
return type(otherMethod) == type(self) and otherMethod.fraction == self.fraction return type(otherMethod) == type(self) and otherMethod.fraction == self.fraction
def get_maximum_achievable_fraction(self) -> float:
return 1.0
class SizeBinFractioning(SubsamplingMethod): class SizeBinFractioning(SubsamplingMethod):
...@@ -117,3 +130,6 @@ class SizeBinFractioning(SubsamplingMethod): ...@@ -117,3 +130,6 @@ class SizeBinFractioning(SubsamplingMethod):
def equals(self, otherMethod) -> bool: def equals(self, otherMethod) -> bool:
return type(otherMethod) == type(self) and otherMethod.fraction == self.fraction return type(otherMethod) == type(self) and otherMethod.fraction == self.fraction
def get_maximum_achievable_fraction(self) -> float:
return 1.0
\ No newline at end of file
...@@ -28,3 +28,4 @@ def get_default_ParticleContainer() -> ParticleContainer: ...@@ -28,3 +28,4 @@ def get_default_ParticleContainer() -> ParticleContainer:
contours.append(np.array([[[x, 0]], [[x+10, 0]], [[x+10, 10]], [[x, 10]]], dtype=np.int32)) contours.append(np.array([[[x, 0]], [[x+10, 0]], [[x+10, 10]], [[x, 10]]], dtype=np.int32))
particleContainer.setParticleContours(contours) particleContainer.setParticleContours(contours)
return particleContainer return particleContainer
...@@ -258,14 +258,18 @@ class TestSampleResult(unittest.TestCase): ...@@ -258,14 +258,18 @@ class TestSampleResult(unittest.TestCase):
possibleRandomMethods = 2 possibleRandomMethods = 2
possibleCrossBoxMethods = 2 possibleCrossBoxMethods = 2
possibleSpiralBoxMethods = 3 possibleSpiralBoxMethods = 3
possibleRandomBoxMethods = 3
possibleChemometricMethods = 0 possibleChemometricMethods = 0
totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \ totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \
possibleSpiralBoxMethods + possibleChemometricMethods possibleSpiralBoxMethods + possibleChemometricMethods + \
possibleRandomBoxMethods
self.assertEqual(len(methods), totalPossible) self.assertEqual(len(methods), totalPossible)
self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction))) self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction)))
self.assertTrue(containsMethod(methods, meth.SizeBinFractioning(dset, desiredFraction))) self.assertTrue(containsMethod(methods, meth.SizeBinFractioning(dset, desiredFraction)))
self.assertTrue(containsMethod(methods, gmeth.CrossBoxSubSampling(dset, desiredFraction))) self.assertTrue(containsMethod(methods, gmeth.CrossBoxSubSampling(dset, desiredFraction)))
self.assertTrue(containsMethod(methods, gmeth.SpiralBoxSubsampling(dset, desiredFraction))) self.assertTrue(containsMethod(methods, gmeth.SpiralBoxSubsampling(dset, desiredFraction)))
self.assertTrue(containsMethod(methods, gmeth.RandomBoxSampling(dset, desiredFraction)))
desiredFraction = 0.5 desiredFraction = 0.5
methods = get_methods_to_test(dset, [desiredFraction]) methods = get_methods_to_test(dset, [desiredFraction])
...@@ -273,8 +277,10 @@ class TestSampleResult(unittest.TestCase): ...@@ -273,8 +277,10 @@ class TestSampleResult(unittest.TestCase):
possibleCrossBoxMethods = 1 possibleCrossBoxMethods = 1
possibleSpiralBoxMethods = 0 possibleSpiralBoxMethods = 0
possibleChemometricMethods = 0 possibleChemometricMethods = 0
possibleRandomBoxMethods = 0
totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \ totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \
possibleSpiralBoxMethods + possibleChemometricMethods possibleSpiralBoxMethods + possibleChemometricMethods + \
possibleRandomBoxMethods
self.assertEqual(len(methods), totalPossible) self.assertEqual(len(methods), totalPossible)
self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction))) self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction)))
self.assertTrue(containsMethod(methods, meth.SizeBinFractioning(dset, desiredFraction))) self.assertTrue(containsMethod(methods, meth.SizeBinFractioning(dset, desiredFraction)))
...@@ -286,9 +292,11 @@ class TestSampleResult(unittest.TestCase): ...@@ -286,9 +292,11 @@ class TestSampleResult(unittest.TestCase):
possibleRandomMethods = 2 possibleRandomMethods = 2
possibleCrossBoxMethods = 0 possibleCrossBoxMethods = 0
possibleSpiralBoxMethods = 0 possibleSpiralBoxMethods = 0
possibleRandomBoxMethods = 0
possibleChemometricMethods = 0 possibleChemometricMethods = 0
totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \ totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \
possibleSpiralBoxMethods + possibleChemometricMethods possibleSpiralBoxMethods + possibleChemometricMethods + \
possibleRandomBoxMethods
self.assertEqual(len(methods), totalPossible) self.assertEqual(len(methods), totalPossible)
self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction))) self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction)))
self.assertTrue(containsMethod(methods, meth.SizeBinFractioning(dset, desiredFraction))) self.assertTrue(containsMethod(methods, meth.SizeBinFractioning(dset, desiredFraction)))
...@@ -301,8 +309,10 @@ class TestSampleResult(unittest.TestCase): ...@@ -301,8 +309,10 @@ class TestSampleResult(unittest.TestCase):
possibleCrossBoxMethods = 3 possibleCrossBoxMethods = 3
possibleSpiralBoxMethods = 3 possibleSpiralBoxMethods = 3
possibleChemometricMethods = 0 possibleChemometricMethods = 0
possibleRandomBoxMethods = 3
totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \ totalPossible = possibleCrossBoxMethods + possibleRandomMethods + \
possibleSpiralBoxMethods + possibleChemometricMethods possibleSpiralBoxMethods + possibleChemometricMethods + \
possibleRandomBoxMethods
self.assertEqual(len(methods), totalPossible) self.assertEqual(len(methods), totalPossible)
for desiredFraction in desiredFractions: for desiredFraction in desiredFractions:
self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction))) self.assertTrue(containsMethod(methods, meth.RandomSampling(dset, desiredFraction)))
...@@ -492,6 +502,7 @@ class TestSubsamplingResult(unittest.TestCase): ...@@ -492,6 +502,7 @@ class TestSubsamplingResult(unittest.TestCase):
return nonMPParticles return nonMPParticles
def _get_MP_particle(self) -> Particle: def _get_MP_particle(self) -> Particle:
random.seed(15203018)
polymerNames = ['Poly (methyl methacrylate', polymerNames = ['Poly (methyl methacrylate',
'Polyethylene', 'Polyethylene',
'Silicone rubber', 'Silicone rubber',
......
This diff is collapsed.
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