Commit 1eba109f authored by Josef Brandt's avatar Josef Brandt

Code Cleanup

parent b99097d9
import numpy as np import numpy as np
from methods import SubsamplingMethod from methods import BoxSelectionSubsamplingMethod
from helpers import box_contains_contour
class CrossBoxSelector(SubsamplingMethod): class CrossBoxSelector(BoxSelectionSubsamplingMethod):
def __init__(self, particleContainer, desiredFraction:float = 0.1) -> None: def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None:
super(CrossBoxSelector, self).__init__(particleContainer, desiredFraction) super(CrossBoxSelector, self).__init__(particleContainer, desiredFraction)
self.filterWidth: float = 1000 self.filterWidth: float = 1000
self.filterHeight: float = 1000 self.filterHeight: float = 1000
self.numBoxesAcross: int = 3 #either 3 or 5 self.numBoxesAcross: int = 3 # either 3 or 5
@property @property
def boxSize(self) -> float: def boxSize(self) -> float:
assert self.get_maximum_achievable_fraction() >= self.fraction maxFraction = self.get_maximum_achievable_fraction()
if maxFraction < self.fraction:
self.fraction = maxFraction
totalBoxArea: float = ((self.filterWidth*self.filterHeight)*self.fraction) totalBoxArea: float = ((self.filterWidth*self.filterHeight)*self.fraction)
boxArea: float = totalBoxArea / (2*self.numBoxesAcross - 1) boxArea: float = totalBoxArea / (2*self.numBoxesAcross - 1)
return boxArea**0.5 return boxArea**0.5
...@@ -70,7 +74,7 @@ class CrossBoxSelector(SubsamplingMethod): ...@@ -70,7 +74,7 @@ class CrossBoxSelector(SubsamplingMethod):
return tileStarts return tileStarts
class SpiralSelector(SubsamplingMethod): class SpiralSelector(BoxSelectionSubsamplingMethod):
def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None: def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None:
super(SpiralSelector, self).__init__(particleContainer, desiredFraction) super(SpiralSelector, self).__init__(particleContainer, desiredFraction)
self.filterWidth: float self.filterWidth: float
...@@ -118,4 +122,4 @@ class SpiralSelector(SubsamplingMethod): ...@@ -118,4 +122,4 @@ class SpiralSelector(SubsamplingMethod):
def _get_xy_at_angle(self, theta: float, centerXY: tuple = (0, 0)) -> tuple: def _get_xy_at_angle(self, theta: float, centerXY: tuple = (0, 0)) -> tuple:
distance: float = self.spiralSlope * theta distance: float = self.spiralSlope * theta
return distance * np.cos(theta) + centerXY[0], distance * np.sin(theta) + centerXY[1] return distance * np.cos(theta) + centerXY[0], distance * np.sin(theta) + centerXY[1]
\ No newline at end of file
from PyQt5 import QtCore, QtWidgets from PyQt5 import QtCore, QtWidgets
# import os, sys, inspect
# currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
# parentdir = os.path.dirname(currentdir)
# sys.path.insert(0, parentdir)
# del currentdir, parentdir
from gui.filterView import FilterView, MeasureBoxGraphItem from gui.filterView import FilterView, MeasureBoxGraphItem
from geometricOperations import CrossBoxSelector, SpiralSelector from geometricMethods import CrossBoxSelector, SpiralSelector
class MeasureMode(QtCore.QObject): class MeasureMode(QtCore.QObject):
......
...@@ -5,6 +5,9 @@ Created on Tue Jan 28 19:32:50 2020 ...@@ -5,6 +5,9 @@ Created on Tue Jan 28 19:32:50 2020
@author: luna @author: luna
""" """
from PyQt5 import QtCore, QtGui
import numpy as np
class ParticleBinSorter(object): class ParticleBinSorter(object):
def __init__(self): def __init__(self):
...@@ -20,7 +23,7 @@ class ParticleBinSorter(object): ...@@ -20,7 +23,7 @@ class ParticleBinSorter(object):
return particlesInBins return particlesInBins
def _get_empty_bins(self): def _get_empty_bins(self):
return [[] for i in range(len(self.bins)+1)] return [[] for _ in range(len(self.bins)+1)]
def _get_binIndex_of_particle(self, particle): def _get_binIndex_of_particle(self, particle):
size = particle.getParticleSize() size = particle.getParticleSize()
...@@ -30,4 +33,18 @@ class ParticleBinSorter(object): ...@@ -30,4 +33,18 @@ class ParticleBinSorter(object):
break break
else: else:
binIndex += 1 binIndex += 1
return binIndex return binIndex
\ No newline at end of file
def box_contains_contour(boxXY: tuple, boxWidthHeight: tuple, contour: np.array) -> bool:
contourPolygon = QtGui.QPolygonF()
for point in contour:
contourPolygon.append(QtCore.QPointF(point[0, 0], point[0, 1]))
boxPolygon = QtGui.QPolygonF()
boxPolygon.append(QtCore.QPointF(boxXY[0], boxXY[1]))
boxPolygon.append(QtCore.QPointF(boxXY[0], boxXY[1] + boxWidthHeight[1]))
boxPolygon.append(QtCore.QPointF(boxXY[0] + boxWidthHeight[0], boxXY[1]))
boxPolygon.append(QtCore.QPointF(boxXY[0] + boxWidthHeight[0], boxXY[1] + boxWidthHeight[1]))
return contourPolygon.intersects(boxPolygon)
...@@ -9,21 +9,43 @@ import random ...@@ -9,21 +9,43 @@ import random
import numpy as np import numpy as np
from helpers import ParticleBinSorter from helpers import ParticleBinSorter
class SubsamplingMethod(object): class SubsamplingMethod(object):
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
self.fraction = desiredFraction self.fraction = desiredFraction
def apply_subsampling_method(self): def apply_subsampling_method(self) -> tuple:
"""
Takes all particles from the supplied particle conatiner and returns a new list of particles that
were measured by applying that subsampling procedure. Also, the actualy measured fraction is returned.
(The desired fraction may not always be achievable)
:returns actuallyMeasuredFraction, listOfSubParticles:
"""
raise NotImplementedError raise NotImplementedError
class RandomSampling(SubsamplingMethod): class BoxSelectionSubsamplingMethod(SubsamplingMethod):
#def __init__(self, particleContainer, desiredFraction=0.1): def __init__(self, *args):
#super(RandomSampling, self).__init__(particleContainer) super(BoxSelectionSubsamplingMethod, self).__init__(*args)
#self.fraction = desiredFraction
def apply_subsampling_method(self) -> tuple:
subParticles: list = []
topLefts: list = self.get_topLeft_of_boxes()
boxSize = self.boxSize
for particle in self.particleContainer.particles:
for topLeft in topLefts:
if box_contains_contour(topLeft, (boxSize, boxSize), particle.contour):
subParticles.append(particle)
return self.fraction, subParticles
def get_topLeft_of_boxes(self) -> list:
raise NotImplementedError
class RandomSampling(SubsamplingMethod):
def apply_subsampling_method(self): def apply_subsampling_method(self):
numOrigParticles = len(self.particleContainer.particles) numOrigParticles = len(self.particleContainer.particles)
numParticles = self._get_number_of_random_particles(numOrigParticles) numParticles = self._get_number_of_random_particles(numOrigParticles)
...@@ -73,7 +95,7 @@ class SizeBinFractioning(SubsamplingMethod): ...@@ -73,7 +95,7 @@ class SizeBinFractioning(SubsamplingMethod):
subParticlesPerBin: list = [] subParticlesPerBin: list = []
for particles in particlesInBins: for particles in particlesInBins:
numParticlesInBin: int = len(particles) numParticlesInBin: int = len(particles)
numSubParticlesPerBin:int = np.int(np.round(numParticlesInBin * self.fraction)) numSubParticlesPerBin: int = np.int(np.round(numParticlesInBin * self.fraction))
if numSubParticlesPerBin == 0 and numParticlesInBin > 0: if numSubParticlesPerBin == 0 and numParticlesInBin > 0:
numSubParticlesPerBin = 1 numSubParticlesPerBin = 1
...@@ -81,10 +103,3 @@ class SizeBinFractioning(SubsamplingMethod): ...@@ -81,10 +103,3 @@ class SizeBinFractioning(SubsamplingMethod):
subParticlesPerBin.append(subParticlesInBin) subParticlesPerBin.append(subParticlesInBin)
return subParticlesPerBin return subParticlesPerBin
class SelectSquaresFromFilter(SubsamplingMethod):
def __init__(self, particleContainer, desiredFraction):
super(SelectSquaresFromFilter, self).__init__(particleContainer)
self.fraction = desiredFraction
...@@ -45,7 +45,7 @@ for fraction in fractions: ...@@ -45,7 +45,7 @@ for fraction in fractions:
iterErrors.append(resultComparer._get_mp_count_error(origParticles, randomParticles, randomFraction)) iterErrors.append(resultComparer._get_mp_count_error(origParticles, randomParticles, randomFraction))
bins, errorsPerBin = resultComparer._get_mp_count_error_per_bin(origParticles, randomParticles, randomFraction) bins, errorsPerBin = resultComparer._get_mp_count_error_per_bin(origParticles, randomParticles, randomFraction)
binIterErrors.append(errorsPerBin) binIterErrors.append(errorsPerBin)
errors.append(round(np.mean(iterErrors)*100)) #from fraction to % errors.append(round(np.mean(iterErrors)*100)) #from fraction to %
fractionBinErrors = [] fractionBinErrors = []
for binIndex in range(len(bins)+1): for binIndex in range(len(bins)+1):
......
import unittest import unittest
from geometricOperations import CrossBoxSelector from geometricMethods import CrossBoxSelector
class TestSelectBoxes(unittest.TestCase): class TestSelectBoxes(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
...@@ -10,7 +11,7 @@ class TestSelectBoxes(unittest.TestCase): ...@@ -10,7 +11,7 @@ class TestSelectBoxes(unittest.TestCase):
self.crossBoxSelector.fraction = 0.1 self.crossBoxSelector.fraction = 0.1
self.crossBoxSelector.numBoxesAcross = 3 self.crossBoxSelector.numBoxesAcross = 3
topLeftCorners:list = self.crossBoxSelector.get_topLeft_of_boxes() topLeftCorners: list = self.crossBoxSelector.get_topLeft_of_boxes()
self.assertEqual(len(topLeftCorners), 5) self.assertEqual(len(topLeftCorners), 5)
self.crossBoxSelector.numBoxesAcross = 5 self.crossBoxSelector.numBoxesAcross = 5
...@@ -44,7 +45,8 @@ class TestSelectBoxes(unittest.TestCase): ...@@ -44,7 +45,8 @@ class TestSelectBoxes(unittest.TestCase):
horizontalTileStarts: list = self.crossBoxSelector._get_horizontal_box_starts(halfBoxSize) horizontalTileStarts: list = self.crossBoxSelector._get_horizontal_box_starts(halfBoxSize)
verticalTileStarts: list = self.crossBoxSelector._get_vertical_box_starts(halfBoxSize) verticalTileStarts: list = self.crossBoxSelector._get_vertical_box_starts(halfBoxSize)
expectedOffset = (maxBoxSize - halfBoxSize) / 2 expectedOffset = (maxBoxSize - halfBoxSize) / 2
self.assertEqual(horizontalTileStarts, [0+expectedOffset, 100/5+expectedOffset, 2*100/5+expectedOffset, 3*100/5+expectedOffset, 4*100/5+expectedOffset]) self.assertEqual(horizontalTileStarts, [0+expectedOffset, 100/5+expectedOffset, 2*100/5+expectedOffset,
3*100/5+expectedOffset, 4*100/5+expectedOffset])
self.assertEqual(horizontalTileStarts, verticalTileStarts) self.assertEqual(horizontalTileStarts, verticalTileStarts)
def test_get_box_size(self) -> None: def test_get_box_size(self) -> None:
...@@ -59,4 +61,4 @@ class TestSelectBoxes(unittest.TestCase): ...@@ -59,4 +61,4 @@ class TestSelectBoxes(unittest.TestCase):
areaPerBox: float = totalBoxArea / numBoxes areaPerBox: float = totalBoxArea / numBoxes
boxSize: float = areaPerBox**0.5 boxSize: float = areaPerBox**0.5
self.assertEqual(self.crossBoxSelector.boxSize, boxSize) self.assertEqual(self.crossBoxSelector.boxSize, boxSize)
\ No newline at end of file
import unittest import unittest
from pytestqt import qtbot
from PyQt5.QtWidgets import QApplication from PyQt5.QtWidgets import QApplication
import sys import sys
from gui.mainView import MainView
from gui.measureModes import CrossBoxesControls
app = QApplication(sys.argv) app = QApplication(sys.argv)
class TestFilterViewGUI(unittest.TestCase): def test_hello(qtbot):
def setUp(self) -> None: widget = MainView()
pass qtbot.addWidget(widget)
print('nu')
def test_gui(self): #
#NEEDS TO BE IMPLEMENTED, too much was refactored to make the old test pass... # class TestMainViewGUI(unittest.TestCase):
self.assertTrue(False) # def setUp(self) -> None:
\ No newline at end of file # # self.qbot = qtbot.QtBot(None)
# self.mainView: MainView = MainView()
# # self.qbot.addWidget(self.mainView)
#
# def test_switchModes_modes(self, qtbot = qtbot.QtBot):
# self.mainView._activate_mode('crossSelection')
# controls = self.mainView.activeModeControl
# self.assertTrue(type(controls) == CrossBoxesControls)
#
# numBoxComboBox = controls.numBoxesSelector
# qtbot.addWidget(self.mainView)
\ No newline at end of file
...@@ -7,12 +7,14 @@ Created on Tue Jan 28 19:35:04 2020 ...@@ -7,12 +7,14 @@ Created on Tue Jan 28 19:35:04 2020
""" """
import unittest import unittest
from helpers import ParticleBinSorter from helpers import ParticleBinSorter, box_contains_contour
import numpy as np
import sys import sys
sys.path.append("C://Users//xbrjos//Desktop//Python") sys.path.append("C://Users//xbrjos//Desktop//Python")
import gepard import gepard
from gepard.analysis.particleAndMeasurement import Particle from gepard.analysis.particleAndMeasurement import Particle
class TestBinSorter(unittest.TestCase): class TestBinSorter(unittest.TestCase):
def setUp(self): def setUp(self):
self.sorter = ParticleBinSorter() self.sorter = ParticleBinSorter()
...@@ -20,10 +22,13 @@ class TestBinSorter(unittest.TestCase): ...@@ -20,10 +22,13 @@ class TestBinSorter(unittest.TestCase):
def test_sort_particles_into_bins(self): def test_sort_particles_into_bins(self):
particleList = [] particleList = []
upperBinLimit = None
for upperBinLimit in self.bins: for upperBinLimit in self.bins:
newParticle = Particle() newParticle = Particle()
newParticle.longSize = newParticle.shortSize = upperBinLimit - 1 newParticle.longSize = newParticle.shortSize = upperBinLimit - 1
particleList.append(newParticle) particleList.append(newParticle)
lastParticle = Particle() lastParticle = Particle()
lastParticle.longSize = lastParticle.shortSize = upperBinLimit + 1 lastParticle.longSize = lastParticle.shortSize = upperBinLimit + 1
particleList.append(lastParticle) particleList.append(lastParticle)
...@@ -58,7 +63,18 @@ class TestBinSorter(unittest.TestCase): ...@@ -58,7 +63,18 @@ class TestBinSorter(unittest.TestCase):
particle.longSize = particle.shortSize = 1000 particle.longSize = particle.shortSize = 1000
binIndex = self.sorter._get_binIndex_of_particle(particle) binIndex = self.sorter._get_binIndex_of_particle(particle)
self.assertEqual(binIndex, 7) self.assertEqual(binIndex, 7)
if __name__ == '__main__': class TestOther(unittest.TestCase):
unittest.main() def test_box_contains_contour(self):
\ No newline at end of file boxXY: tuple = 0, 0
boxWidthHeight: tuple = 10, 10
contourPoints = np.array([[[0, 0]], [[5, 5]], [[3, 3]]]) # fully enclosed
self.assertTrue(box_contains_contour(boxXY, boxWidthHeight, contourPoints))
contourPoints = np.array([[[-5, -5]], [[0, 5]], [[-5, -10]]]) # only one point touches border
self.assertTrue(box_contains_contour(boxXY, boxWidthHeight, contourPoints))
contourPoints = np.array([[[-5, -5]], [[-1, 5]], [[-5, -10]]]) # outside the box
self.assertFalse(box_contains_contour(boxXY, boxWidthHeight, contourPoints))
...@@ -16,11 +16,13 @@ from gepard.analysis.particleAndMeasurement import Particle ...@@ -16,11 +16,13 @@ from gepard.analysis.particleAndMeasurement import Particle
from methods import IvlevaSubsampling, RandomSampling, SizeBinFractioning from methods import IvlevaSubsampling, RandomSampling, SizeBinFractioning
from helpers import ParticleBinSorter from helpers import ParticleBinSorter
def get_default_particle_container(numParticles=1000): def get_default_particle_container(numParticles=1000):
particleContainer = ParticleContainer(None) particleContainer = ParticleContainer(None)
particleContainer.initializeParticles(numParticles) particleContainer.initializeParticles(numParticles)
return particleContainer return particleContainer
class TestIvleva(unittest.TestCase): class TestIvleva(unittest.TestCase):
def test_get_ivleva_fraction(self): def test_get_ivleva_fraction(self):
self.particleContainer = get_default_particle_container() self.particleContainer = get_default_particle_container()
...@@ -62,7 +64,7 @@ class TestSizeBinFractioning(unittest.TestCase): ...@@ -62,7 +64,7 @@ class TestSizeBinFractioning(unittest.TestCase):
self.sizeBinFrac = SizeBinFractioning(None) self.sizeBinFrac = SizeBinFractioning(None)
sorter = ParticleBinSorter() sorter = ParticleBinSorter()
sizes = [limit-1 for limit in sorter.bins] sizes = [limit-1 for limit in sorter.bins]
sizes.append(sorter.bins[-1]+1) #the last bin, that goes until infinity sizes.append(sorter.bins[-1]+1) # the last bin, that goes until infinity
self.numMPparticlesPerBin = 10 self.numMPparticlesPerBin = 10
self.particles = [] self.particles = []
...@@ -84,10 +86,6 @@ class TestSizeBinFractioning(unittest.TestCase): ...@@ -84,10 +86,6 @@ class TestSizeBinFractioning(unittest.TestCase):
for subParticles in subParticlesPerBin: for subParticles in subParticlesPerBin:
self.assertEqual(len(subParticles), numParticlesPerBinExpected) self.assertEqual(len(subParticles), numParticlesPerBinExpected)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
\ 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