Commit c8650c49 authored by Josef Brandt's avatar Josef Brandt

Code Cleanup

parent bc14998e
......@@ -7,6 +7,7 @@ Created on Wed Jan 22 13:57:28 2020
"""
from helpers import ParticleBinSorter
class ResultComparer(object):
def _get_mp_count_error_per_bin(self, allParticles, subParticles, fractionMeasured):
......@@ -27,7 +28,7 @@ class ResultComparer(object):
elif numMPEstimate == 0:
mpCountError = 0
else:
raise Exception #> 0 particles in subsample, whereas none in entire sample. This cannot be!
raise Exception # >0 particles in subsample, whereas none in entire sample. This cannot be!
return mpCountError
......
......@@ -7,8 +7,6 @@ from helpers import box_contains_contour
class CrossBoxSelector(BoxSelectionSubsamplingMethod):
def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None:
super(CrossBoxSelector, self).__init__(particleContainer, desiredFraction)
self.filterWidth: float = 1000
self.filterHeight: float = 1000
self.numBoxesAcross: int = 3 # either 3 or 5
@property
......@@ -17,7 +15,7 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
if maxFraction < self.fraction:
self.fraction = maxFraction
totalBoxArea: float = ((self.filterWidth*self.filterHeight)*self.fraction)
totalBoxArea: float = self.filterArea * self.fraction
boxArea: float = totalBoxArea / (2*self.numBoxesAcross - 1)
return boxArea**0.5
......@@ -39,14 +37,20 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
def get_maximum_achievable_fraction(self) -> float:
"""
Returns the maximum achievable fraction, given the desired number of boxes across.
It is with respect to a rectangular filter of width*height, for circular filter this has to be divided by 0.786
It is with respect to a circular filter, fitting in a rectangle of dimensions width*height
:return float:
"""
maxBoxWidth: float = self.filterWidth / self.numBoxesAcross
maxBoxHeight: float = self.filterHeight / self.numBoxesAcross
alpha: float = np.deg2rad(135)
r: float = self.filterSize/2
d: float = (self.numBoxesAcross-1) * r / self.numBoxesAcross # 2/3*r for numAcross = 3, 4/5*r numAcross = 5
delta: float = np.arcsin((np.sin(alpha) * d) / r)
gamma: float = np.pi - alpha - delta
longestBoxHalfDiagonal: float = r / np.sin(alpha) * np.sin(gamma)
maxBoxSize: float = 2 * longestBoxHalfDiagonal / np.sqrt(2)
numBoxes: int = 2*self.numBoxesAcross - 1
totalBoxArea: float = numBoxes * (maxBoxWidth * maxBoxHeight)
return totalBoxArea / (self.filterHeight * self.filterWidth)
totalBoxArea: float = numBoxes * (maxBoxSize**2)
maxFraction: float = totalBoxArea / self.filterArea
return maxFraction
def _get_horizontal_box_starts(self, boxSize: float) -> list:
"""
......@@ -54,7 +58,7 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
:param boxSize:
:return list:
"""
return self._get_box_starts(self.filterWidth, boxSize)
return self._get_box_starts(boxSize)
def _get_vertical_box_starts(self, boxSize: float) -> list:
"""
......@@ -62,14 +66,14 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
:param boxSize:
:return list:
"""
return self._get_box_starts(self.filterHeight, boxSize)
return self._get_box_starts(boxSize)
def _get_box_starts(self, filterSize: float, boxSize: float) -> list:
maxBoxSize: float = filterSize / self.numBoxesAcross
def _get_box_starts(self, boxSize: float) -> list:
maxBoxSize: float = self.filterSize / self.numBoxesAcross
assert maxBoxSize >= boxSize
tileStarts: list = []
for i in range(self.numBoxesAcross):
start: float = i * filterSize / self.numBoxesAcross + (maxBoxSize - boxSize) / 2
start: float = i * self.filterSize / self.numBoxesAcross + (maxBoxSize - boxSize) / 2
tileStarts.append(start)
return tileStarts
......@@ -78,15 +82,11 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
class SpiralSelector(BoxSelectionSubsamplingMethod):
def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None:
super(SpiralSelector, self).__init__(particleContainer, desiredFraction)
self.filterWidth: float
self.filterHeight: float
self.boxSize: float = 50
self.numBoxes = 20
@property
def spiralSlope(self) -> float:
assert self.filterHeight == self.filterWidth
return self.armDistance / (2*np.pi)
@property
......@@ -95,14 +95,14 @@ class SpiralSelector(BoxSelectionSubsamplingMethod):
@property
def actuallyCoveredFraction(self) -> float:
return self.numBoxes*self.boxSize**2 / (self.filterHeight*self.filterWidth)
return self.numBoxes*self.boxSize**2 / self.filterArea
def get_topLeft_of_boxes(self) -> list:
"""
Calculates the topLeft-points (x, y) of all measure boxes
The method uses an approximation for the spiral and is not purely accurate.
:return list:"""
filterCenter: tuple = self.filterWidth/2 - self.boxSize/2, self.filterHeight/2 - self.boxSize/2
filterCenter: tuple = self.filterSize/2 - self.boxSize/2, self.filterSize/2 - self.boxSize/2
slope = self.spiralSlope
theta: float = 0
boxDistance = self.boxSize * 1.1
......@@ -123,10 +123,8 @@ class SpiralSelector(BoxSelectionSubsamplingMethod):
This function moves and scales the topLeft-Points so that all measure boxes lie within the filter limits.
:return list:
"""
assert self.filterHeight == self.filterWidth # elliptical filters are not supportet here..
xCoords: np.array = np.array([float(point[0]) for point in topLefts]) - self.filterWidth / 2
yCoords: np.array = np.array([float(point[1]) for point in topLefts]) - self.filterHeight / 2
xCoords: np.array = np.array([float(point[0]) for point in topLefts]) - self.filterSize / 2
yCoords: np.array = np.array([float(point[1]) for point in topLefts]) - self.filterSize / 2
xCoordsBoxMiddles: np.array = xCoords + self.boxSize/2
yCoordsBoxMiddles: np.array = yCoords + self.boxSize/2
......@@ -142,8 +140,8 @@ class SpiralSelector(BoxSelectionSubsamplingMethod):
xCoordsBoxMiddles *= scaleFactor
yCoordsBoxMiddles *= scaleFactor
xCoords = xCoordsBoxMiddles + (self.filterWidth - self.boxSize)/2
yCoords = yCoordsBoxMiddles + (self.filterHeight - self.boxSize)/2
xCoords = xCoordsBoxMiddles + (self.filterSize - self.boxSize)/2
yCoords = yCoordsBoxMiddles + (self.filterSize - self.boxSize)/2
newTopLefts = zip(np.round(xCoords), np.round(yCoords))
return list(tuple(newTopLefts))
......
......@@ -76,12 +76,4 @@ class MeasureBoxGraphItem(QtWidgets.QGraphicsItem):
def paint(self, painter, option, widget) -> None:
painter.setBrush(QtCore.Qt.green)
painter.setPen(QtCore.Qt.darkGreen)
painter.drawRects(self.rect)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
filterView = FilterView()
filterView.show()
ret = app.exec_()
\ No newline at end of file
painter.drawRects(self.rect)
\ No newline at end of file
......@@ -24,8 +24,8 @@ class CrossBoxMode(MeasureMode):
self.update_measure_viewItems()
def update_measure_viewItems(self) -> None:
self.crossBoxGenerator.filterHeight = self.filterView.filter.height
self.crossBoxGenerator.filterWidth = self.filterView.filter.width
assert self.filterView.filter.height == self.filterView.filter.width
self.crossBoxGenerator.filterSize = self.filterView.filter.height
self.crossBoxGenerator.numBoxesAcross = int(self.uiControls.numBoxesSelector.currentText())
desiredCoverage: int = self.uiControls.coverageSpinbox.value()
......@@ -78,7 +78,7 @@ class CrossBoxesControls(QtWidgets.QGroupBox):
def _config_changed(self):
self.measureModeParent.update_measure_viewItems()
def set_to_max_possible_coverage(self, maxCoverage:int):
def set_to_max_possible_coverage(self, maxCoverage: int):
self.coverageSpinbox.setMaximum(maxCoverage)
if maxCoverage < self.coverageSpinbox.value():
self.coverageSpinbox.valueChanged.disconnect()
......
......@@ -29,6 +29,11 @@ class SubsamplingMethod(object):
class BoxSelectionSubsamplingMethod(SubsamplingMethod):
def __init__(self, *args):
super(BoxSelectionSubsamplingMethod, self).__init__(*args)
self.filterSize: float = 500
@property
def filterArea(self) -> float:
return np.pi * (self.filterSize / 2) ** 2
def apply_subsampling_method(self) -> tuple:
subParticles: list = []
......@@ -44,9 +49,6 @@ class BoxSelectionSubsamplingMethod(SubsamplingMethod):
def get_topLeft_of_boxes(self) -> list:
raise NotImplementedError
def get_parameterCombos_for_fraction(self) -> list:
raise NotImplementedError
class RandomSampling(SubsamplingMethod):
def apply_subsampling_method(self):
......
......@@ -8,7 +8,7 @@ class TestSelectCrossBoxes(unittest.TestCase):
self.crossBoxSelector = CrossBoxSelector(None)
def test_get_topLeft_of_boxes(self):
self.crossBoxSelector.filterWidth = self.crossBoxSelector.filterHeight = 100
self.crossBoxSelector.filterSize = 100
self.crossBoxSelector.fraction = 0.1
self.crossBoxSelector.numBoxesAcross = 3
......@@ -20,9 +20,9 @@ class TestSelectCrossBoxes(unittest.TestCase):
self.assertEqual(len(topLeftCorners), 9)
def test_get_tile_topLefts(self):
self.crossBoxSelector.filterHeight = self.crossBoxSelector.filterWidth = 100
self.crossBoxSelector.filterSize = 100
self.crossBoxSelector.numBoxesAcross = 3
maxBoxSize: float = self.crossBoxSelector.filterWidth/self.crossBoxSelector.numBoxesAcross
maxBoxSize: float = self.crossBoxSelector.filterSize/self.crossBoxSelector.numBoxesAcross
horizontalTileStarts: list = self.crossBoxSelector._get_horizontal_box_starts(maxBoxSize)
verticalTileStarts: list = self.crossBoxSelector._get_vertical_box_starts(maxBoxSize)
self.assertEqual(horizontalTileStarts, [0, 100 / 3, 2 * 100 / 3])
......@@ -36,7 +36,7 @@ class TestSelectCrossBoxes(unittest.TestCase):
self.assertEqual(horizontalTileStarts, verticalTileStarts)
self.crossBoxSelector.numBoxesAcross = 5
maxBoxSize = self.crossBoxSelector.filterWidth / self.crossBoxSelector.numBoxesAcross
maxBoxSize = self.crossBoxSelector.filterSize / self.crossBoxSelector.numBoxesAcross
horizontalTileStarts = self.crossBoxSelector._get_horizontal_box_starts(maxBoxSize)
verticalTileStarts: list = self.crossBoxSelector._get_vertical_box_starts(maxBoxSize)
self.assertEqual(horizontalTileStarts, [0, 100/5, 2*100/5, 3*100/5, 4*100/5])
......@@ -51,11 +51,11 @@ class TestSelectCrossBoxes(unittest.TestCase):
self.assertEqual(horizontalTileStarts, verticalTileStarts)
def test_get_box_size(self) -> None:
self.crossBoxSelector.filterHeight = self.crossBoxSelector.filterWidth = 100 # in pixel
self.crossBoxSelector.filterSize = 100 # in pixel
self.crossBoxSelector.fraction = 0.1
self.crossBoxSelector.numBoxesAcross = 3
filterArea: float = self.crossBoxSelector.filterHeight * self.crossBoxSelector.filterWidth
filterArea: float = np.pi * (self.crossBoxSelector.filterSize/2)**2
totalBoxArea: float = filterArea*self.crossBoxSelector.fraction
numBoxes: int = 2*self.crossBoxSelector.numBoxesAcross - 1
......@@ -71,7 +71,7 @@ class TestSelectSpiralBoxes(unittest.TestCase):
def test_move_and_scale_toplefts(self):
self.spiralBoxSelector.filterHeight = 100
self.spiralBoxSelector.filterWidth = 100
self.spiralBoxSelector.filterSize = 100
self.spiralBoxSelector.boxSize = 10
topLefts = [(45, 45), (0, 45), (90, 45)]
......
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