Commit 0553ff15 authored by Josef Brandt's avatar Josef Brandt

First Stage of Refactoring..

parent 064d26eb
......@@ -2,8 +2,10 @@ import numpy as np
from itertools import combinations
from methods import SubsamplingMethod
import sys
sys.path.append("C://Users//xbrjos//Desktop//Python")
from gepard import dataset
import helpers
class BoxSelectionSubsamplingMethod(SubsamplingMethod):
......@@ -12,6 +14,10 @@ class BoxSelectionSubsamplingMethod(SubsamplingMethod):
self.filterDiameter: float = 500
self.offset: tuple = (0, 0)
@property
def label(self) -> str:
raise NotImplementedError
@property
def filterArea(self) -> float:
return np.pi * (self.filterDiameter / 2) ** 2
......@@ -35,32 +41,63 @@ class BoxSelectionCreator(object):
def __init__(self, dataset: dataset.DataSet):
super(BoxSelectionCreator, self).__init__()
self.dataset: dataset.DataSet = dataset
self.minNumberOfBoxes: int = 10
self.maxNumberOfBoxes: int = 20
def get_crossBoxSelectors_for_fraction(self, desiredFraction: float) -> list:
"""
Creates CrossBoxSelectors that fullfil the desired fraction criterium.
Creates CrossBoxSelectors that fullfill the desired fraction criterium.
:param desiredFraction:
:return:
:return list of CrossBoxSelectors:
"""
crossBoxSelectors = []
offset, diameter, widthHeight = self.get_filterDimensions_from_dataset()
offset, diameter, widthHeight = helpers.get_filterDimensions_from_dataset(self.dataset)
diameter = helpers.convert_length_to_pixels(self.dataset, diameter)
offset = helpers.convert_length_to_pixels(self.dataset, offset[0]), \
helpers.convert_length_to_pixels(self.dataset, offset[1])
for numBoxesAcross in [3, 5]:
newBoxSelector: CrossBoxSelector = CrossBoxSelector(self.dataset.particleContainer, desiredFraction)
newBoxSelector.filterDiameter = diameter
newBoxSelector.offset = offset
newBoxSelector.numBoxesAcross = numBoxesAcross
# for numBoxesAcross in [3, 5]:
# newBoxSelector: CrossBoxSelector = CrossBoxSelector(self.dataset.particleContainer, desiredFraction)
# newBoxSelector.filterDiameter = diameter
# newBoxSelector.offset = offset
# newBoxSelector.numBoxesAcross = numBoxesAcross
#
# crossBoxSelectors.append(newBoxSelector)
crossBoxSelectors.append(newBoxSelector)
return crossBoxSelectors
def get_spiralBoxSelectors_for_fraction(self, desiredFraction: float) -> list:
"""
Creates CrossBoxSelectors that fullfill the desired fraction criterium.
:param desiredFraction:
:return list of SpiralBoxSelectors:
"""
spiralBoxSelectors = []
offset, diameter, widthHeight = helpers.get_filterDimensions_from_dataset(self.dataset)
diameter = helpers.convert_length_to_pixels(self.dataset, diameter)
offset = helpers.convert_length_to_pixels(self.dataset, offset[0]), \
helpers.convert_length_to_pixels(self.dataset, offset[1])
for numBoxes in SpiralSelector.possibleBoxNumbers:
newBoxSelector: SpiralSelector = SpiralSelector(self.dataset.particleContainer, desiredFraction)
newBoxSelector.filterDiameter = diameter
newBoxSelector.offset = offset
newBoxSelector.numBoxes = numBoxes
if newBoxSelector.noBoxOverlap:
spiralBoxSelectors.append(newBoxSelector)
return spiralBoxSelectors
class CrossBoxSelector(BoxSelectionSubsamplingMethod):
def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None:
super(CrossBoxSelector, self).__init__(particleContainer, desiredFraction)
self.numBoxesAcross: int = 3 # either 3 or 5
self.numBoxesAcross: int = 3 # either 3 or 5
@property
def label(self) -> str:
return f'Boxes CrossLayout ({self.numBoxesAcross} boxes across)'
@property
def boxSize(self) -> float:
......@@ -69,20 +106,20 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
self.fraction = maxFraction
totalBoxArea: float = self.filterArea * self.fraction
boxArea: float = totalBoxArea / (2*self.numBoxesAcross - 1)
return boxArea**0.5
boxArea: float = totalBoxArea / (2 * self.numBoxesAcross - 1)
return boxArea ** 0.5
def get_topLeft_of_boxes(self) -> list:
topLeftCorners: list = []
boxSize = self.boxSize
xStartCoordinates: list = self._get_horizontal_box_starts(boxSize)
yStartCoordinates: list = self._get_vertical_box_starts(boxSize)
middleXCoordinate: float = xStartCoordinates[self.numBoxesAcross//2]
middleYCoordinate: float = yStartCoordinates[self.numBoxesAcross//2]
middleXCoordinate: float = xStartCoordinates[self.numBoxesAcross // 2]
middleYCoordinate: float = yStartCoordinates[self.numBoxesAcross // 2]
for i in range(self.numBoxesAcross):
topLeftCorners.append((middleXCoordinate, yStartCoordinates[i]))
if i != self.numBoxesAcross//2:
if i != self.numBoxesAcross // 2:
topLeftCorners.append((xStartCoordinates[i], middleYCoordinate))
return topLeftCorners
......@@ -94,14 +131,14 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
:return float:
"""
alpha: float = np.deg2rad(135)
r: float = self.filterDiameter/2
d: float = (self.numBoxesAcross-1) * r / self.numBoxesAcross # 2/3*r for numAcross = 3, 4/5*r numAcross = 5
r: float = self.filterDiameter / 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 * (maxBoxSize**2)
numBoxes: int = 2 * self.numBoxesAcross - 1
totalBoxArea: float = numBoxes * (maxBoxSize ** 2)
maxFraction: float = totalBoxArea / self.filterArea
return maxFraction
......@@ -133,29 +170,40 @@ class CrossBoxSelector(BoxSelectionSubsamplingMethod):
class SpiralSelector(BoxSelectionSubsamplingMethod):
possibleBoxNumbers: list = [10, 15, 20]
def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None:
super(SpiralSelector, self).__init__(particleContainer, desiredFraction)
self.boxSize: float = 50
self.numBoxes = 20
@property
def label(self) -> str:
return f'Boxes SpiralLayout ({self.numBoxes} boxes)'
@property
def noBoxOverlap(self) -> bool:
return not self._boxes_are_overlapping(self.get_topLeft_of_boxes())
@property
def boxSize(self) -> float:
totalBoxArea: float = self.filterArea * self.fraction
boxArea: float = totalBoxArea / self.numBoxes
return boxArea ** 0.5
@property
def spiralSlope(self) -> float:
return self.armDistance / (2*np.pi)
return self.armDistance / (2 * np.pi)
@property
def armDistance(self) -> float:
return np.sqrt(2) * self.boxSize
@property
def actuallyCoveredFraction(self) -> float:
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.filterDiameter/2 - self.boxSize/2, self.filterDiameter/2 - self.boxSize/2
filterCenter: tuple = self.filterDiameter / 2 - self.boxSize / 2, self.filterDiameter / 2 - self.boxSize / 2
slope = self.spiralSlope
theta: float = 0
boxDistance = self.boxSize * 1.1
......@@ -164,7 +212,7 @@ class SpiralSelector(BoxSelectionSubsamplingMethod):
for i in range(self.numBoxes):
newPoint: tuple = self._get_xy_at_angle(theta, filterCenter)
topLefts.append(newPoint)
theta += boxDistance / (slope * np.sqrt(1 + theta**2))
theta += boxDistance / (slope * np.sqrt(1 + theta ** 2))
boxDistance *= 1.05
topLefts = self._move_and_scale_toplefts(topLefts)
......@@ -176,11 +224,11 @@ class SpiralSelector(BoxSelectionSubsamplingMethod):
This function moves and scales the topLeft-Points so that all measure boxes lie within the filter limits.
:return list:
"""
xCoords: np.ndarray= np.array([float(point[0]) for point in topLefts]) - self.filterDiameter / 2
yCoords: np.ndarray= np.array([float(point[1]) for point in topLefts]) - self.filterDiameter / 2
xCoords: np.ndarray = np.array([float(point[0]) for point in topLefts]) - self.filterDiameter / 2
yCoords: np.ndarray = np.array([float(point[1]) for point in topLefts]) - self.filterDiameter / 2
xCoordsBoxMiddles: np.ndarray= xCoords + self.boxSize/2
yCoordsBoxMiddles: np.ndarray= yCoords + self.boxSize/2
xCoordsBoxMiddles: np.ndarray = xCoords + self.boxSize / 2
yCoordsBoxMiddles: np.ndarray = yCoords + self.boxSize / 2
lastBoxCenter: tuple = (xCoordsBoxMiddles[-1], yCoordsBoxMiddles[-1])
distanceLastCenter: float = np.linalg.norm(lastBoxCenter)
......@@ -193,8 +241,8 @@ class SpiralSelector(BoxSelectionSubsamplingMethod):
xCoordsBoxMiddles *= scaleFactor
yCoordsBoxMiddles *= scaleFactor
xCoords = xCoordsBoxMiddles + (self.filterDiameter - self.boxSize)/2
yCoords = yCoordsBoxMiddles + (self.filterDiameter - self.boxSize)/2
xCoords = xCoordsBoxMiddles + (self.filterDiameter - self.boxSize) / 2
yCoords = yCoordsBoxMiddles + (self.filterDiameter - self.boxSize) / 2
newTopLefts = zip(np.round(xCoords), np.round(yCoords))
return list(tuple(newTopLefts))
......@@ -208,12 +256,12 @@ class SpiralSelector(BoxSelectionSubsamplingMethod):
"""
center = np.array(center)
boxSize = self.boxSize
coords: np.ndarray= np.array([[boxCenter[0] - 0.5*boxSize, boxCenter[1] - 0.5*boxSize],
[boxCenter[0] + 0.5*boxSize, boxCenter[1] - 0.5*boxSize],
[boxCenter[0] - 0.5*boxSize, boxCenter[1] + 0.5*boxSize],
[boxCenter[0] + 0.5*boxSize, boxCenter[1] + 0.5*boxSize]])
coords: np.ndarray = np.array([[boxCenter[0] - 0.5 * boxSize, boxCenter[1] - 0.5 * boxSize],
[boxCenter[0] + 0.5 * boxSize, boxCenter[1] - 0.5 * boxSize],
[boxCenter[0] - 0.5 * boxSize, boxCenter[1] + 0.5 * boxSize],
[boxCenter[0] + 0.5 * boxSize, boxCenter[1] + 0.5 * boxSize]])
distances: np.ndarray= np.linalg.norm(coords - center, axis=1)
distances: np.ndarray = np.linalg.norm(coords - center, axis=1)
return np.max(distances)
def _get_xy_at_angle(self, theta: float, centerXY: tuple = (0, 0)) -> tuple:
......
......@@ -90,13 +90,8 @@ class SpiralBoxMode(MeasureMode):
def update_measure_viewItems(self) -> None:
self.spiralBoxGenerator.filterDiameter = self.filterView.filter.diameter
self.spiralBoxGenerator.boxSize = self.uiControls.boxSizeSpinbox.value()
# minBoxSize: float = self.spiralBoxGenerator.filterDiameter*0.1
# if self.spiralBoxGenerator.boxSize < minBoxSize:
# self.spiralBoxGenerator.boxSize = minBoxSize
# self.uiControls.boxSizeSpinbox.setValue(int(round(minBoxSize)))
self.spiralBoxGenerator.numBoxes = self.uiControls.numBoxesSpinbox.value()
self.spiralBoxGenerator.fraction = self.uiControls.coverageSpinbox.value() / 100
topLefts: list = self.spiralBoxGenerator.get_topLeft_of_boxes()
boxSize = self.spiralBoxGenerator.boxSize
......@@ -115,20 +110,23 @@ class SpiralBoxControls(QtWidgets.QGroupBox):
layout = QtWidgets.QHBoxLayout()
self.setLayout(layout)
layout.addWidget(QtWidgets.QLabel('Box Size:'))
self.boxSizeSpinbox = QtWidgets.QSpinBox()
self.boxSizeSpinbox.setValue(50)
self.boxSizeSpinbox.setMaximum(10000)
self.boxSizeSpinbox.valueChanged.connect(self._config_changed)
layout.addWidget(self.boxSizeSpinbox)
layout.addStretch()
layout.addWidget(QtWidgets.QLabel('Num Boxes:'))
self.numBoxesSpinbox = QtWidgets.QSpinBox()
self.numBoxesSpinbox.setValue(10)
self.numBoxesSpinbox.valueChanged.connect(self._config_changed)
layout.addWidget(self.numBoxesSpinbox)
layout.addStretch()
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):
self.measureModeParent.update_measure_viewItems()
if self.numBoxesSpinbox.value() > 0:
self.measureModeParent.update_measure_viewItems()
......@@ -16,6 +16,14 @@ class SubsamplingMethod(object):
self.particleContainer = particleConatainer
self.fraction = desiredFraction
@property
def label(self) -> str:
"""
A specific label that can be used for plots, for instance.
:return:
"""
raise NotImplementedError
def apply_subsampling_method(self) -> tuple:
"""
Takes all particles from the supplied particle conatiner and returns a new list of particles that
......@@ -27,6 +35,10 @@ class SubsamplingMethod(object):
class RandomSampling(SubsamplingMethod):
@property
def label(self) -> str:
return 'Random Subsampling'
def apply_subsampling_method(self):
numOrigParticles = len(self.particleContainer.particles)
numParticles = self._get_number_of_random_particles(numOrigParticles)
......@@ -43,7 +55,11 @@ class IvlevaSubsampling(SubsamplingMethod):
self.sigma = sigma
self.estimatedMPFraction = mpFraction
self.errorMargin = errorMargin
@property
def label(self) -> str:
return 'Random fraction, Anger et al.'
def apply_subsampling_method(self):
N = self.particleContainer.getNumberOfParticles()
numParticlesMeasured = self._get_ivleva_fraction(N)
......@@ -62,7 +78,11 @@ class SizeBinFractioning(SubsamplingMethod):
def __init__(self, particleConatiner, desiredfraction: float = 0.2):
super(SizeBinFractioning, self).__init__(particleConatiner, desiredfraction)
self.sorter: ParticleBinSorter = ParticleBinSorter()
@property
def label(self) -> str:
return 'SizeBin Random Subsampling'
def apply_subsampling_method(self):
subParticlesPerBin: list = self._get_subParticles_per_bin(self.particleContainer.particles)
subParticles: list = []
......
......@@ -4,26 +4,37 @@ import time
import sys
sys.path.append("C://Users//xbrjos//Desktop//Python")
from gepard import dataset
import gepardevaluation
from methods import IvlevaSubsampling, RandomSampling, SizeBinFractioning
from geometricMethods import BoxSelectionCreator
from helpers import ParticleBinSorter
from evaluation import ResultComparer
fname: str = r'C:\Users\xbrjos\Desktop\temp MP\190313_Soil_5_A_50_5_1_50_1\190313_Soil_5_A_50_5_1_50_1.pkl'
# fname: str = r'C:\Users\xbrjos\Desktop\temp MP\190326_MCII_WWTP_SB_50_2\190326_MCII_WWTP_SB_50_2.pkl'
# fname: str = r'C:\Users\xbrjos\Desktop\temp MP\190326_MCII_WWTP_SB_50_1\190326_MCII_WWTP_SB_50_1.pkl'
# fname: str = r'C:\Users\xbrjos\Desktop\temp MP\KWS_CT_3_ds1_all_10_2\KWS_CT_3_ds1_all_10_2.pkl' #legacy convert not working..
# fname: str = r'C:\Users\xbrjos\Desktop\temp MP\190201_BSB_Stroomi_ds2_R1_R2_50\190201_BSB_Stroomi_ds2_R1_R2_50.pkl' #zvalues image missing, legacy convert fails..
"""
IMPORTANT!!!
SET GEPARD TO EVALUATION BRANCH (WITHOUT THE TILING STUFF), OTHERWISE SOME OF THE LEGACY CONVERTS MIGHT FAIL..
"""
workingFiles: list = []
workingFiles.append(r'C:\Users\xbrjos\Desktop\temp MP\190313_Soil_5_A_50_5_1_50_1\190313_Soil_5_A_50_5_1_50_1.pkl')
workingFiles.append(r'C:\Users\xbrjos\Desktop\temp MP\181018_Microcatch-St.6_50um\181018_Microcatch-St.6_50um.pkl')
workingFiles.append(r'C:\Users\xbrjos\Desktop\temp MP\190326_MCII_WWTP_SB_50_2\190326_MCII_WWTP_SB_50_2.pkl')
workingFiles.append(r'C:\Users\xbrjos\Desktop\temp MP\190326_MCII_WWTP_SB_50_1\190326_MCII_WWTP_SB_50_1.pkl')
workingFiles.append(r'C:\Users\xbrjos\Desktop\temp MP\190201_BSB_Stroomi_ds2_R1_R2_50\190201_BSB_Stroomi_ds2_R1_R2_50.pkl')
dset = dataset.loadData(fname)
print('loaded dataset')
# These do not work, due to no ramanscansortindex??
# fname: str = r'C:\Users\xbrjos\Desktop\temp MP\KWS_CT_3_ds1_all_10_2\KWS_CT_3_ds1_all_10_2.pkl'
# fname: str = r'C:\Users\xbrjos\Desktop\temp MP\KWS_CT_3_ds1_all_10_2\KWS_CT_3_ds1_all_10_2.pkl'
boxCreator = BoxSelectionCreator(dset)
center, size = boxCreator.get_filterDimensions_from_dataset()
print(center, size)
print(dset.mapToPixel(center, force=True))
for index, fname in enumerate(workingFiles):
dset = dataset.loadData(fname)
print('loaded dataset', fname)
# boxCreator = BoxSelectionCreator(dset)
# center, size = boxCreator.get_filterDimensions_from_dataset()
# print(center, size)
# print(dset.mapToPixel(center, force=True))
# pc = dset.particleContainer
# origParticles = pc.particles
......
......@@ -76,7 +76,7 @@ class TestSelectSpiralBoxes(unittest.TestCase):
def test_move_and_scale_toplefts(self):
self.spiralBoxSelector.filterHeight = 100
self.spiralBoxSelector.filterDiameter = 100
self.spiralBoxSelector.boxSize = 10
self._set_boxSelectorFraction_to_reach_boxSize(10)
topLefts = [(45, 45), (0, 45), (90, 45)]
newTopLefts = self.spiralBoxSelector._move_and_scale_toplefts(topLefts)
......@@ -86,26 +86,24 @@ class TestSelectSpiralBoxes(unittest.TestCase):
def test_get_max_distance_of_boxCenter_to_center(self):
boxCenter = 0, 0
self.spiralBoxSelector.boxSize = 1
self._set_boxSelectorFraction_to_reach_boxSize(1)
maxDistance: float = self.spiralBoxSelector._get_max_distance_of_boxCenter_to_center(boxCenter)
self.assertEqual(maxDistance, np.sqrt(0.5**2 + 0.5**2))
self.spiralBoxSelector.boxSize = 2
self._set_boxSelectorFraction_to_reach_boxSize(2)
maxDistance: float = self.spiralBoxSelector._get_max_distance_of_boxCenter_to_center(boxCenter)
self.assertEqual(maxDistance, np.sqrt(2))
boxCenter = 1, 0
self.spiralBoxSelector.boxSize = 2
maxDistance: float = self.spiralBoxSelector._get_max_distance_of_boxCenter_to_center(boxCenter)
self.assertEqual(maxDistance, np.sqrt(2**2 + 1**2))
boxCenter = -1, -3
self.spiralBoxSelector.boxSize = 2
maxDistance: float = self.spiralBoxSelector._get_max_distance_of_boxCenter_to_center(boxCenter)
self.assertEqual(maxDistance, np.sqrt(4**2 + 2**2))
def test_boxes_are_overlapping(self):
self.spiralBoxSelector.boxSize = 10
self._set_boxSelectorFraction_to_reach_boxSize(10)
topLefts: list = [(0, 0), (10, 10), (20, 10)]
overlaps: bool = self.spiralBoxSelector._boxes_are_overlapping(topLefts)
......@@ -123,37 +121,65 @@ class TestSelectSpiralBoxes(unittest.TestCase):
overlaps: bool = self.spiralBoxSelector._boxes_are_overlapping(topLefts)
self.assertEqual(overlaps, True)
def _set_boxSelectorFraction_to_reach_boxSize(self, desiredBoxSize: float) -> None:
"""
For convenience, the SpiralBoxSelector is configured to have the desired box Size by adjusting the fraction.
:param desiredBoxSize:
:return:
"""
areaPerBox: float = desiredBoxSize**2
totalBoxArea: float = areaPerBox * self.spiralBoxSelector.numBoxes
self.spiralBoxSelector.fraction = totalBoxArea / self.spiralBoxSelector.filterArea
assert self.spiralBoxSelector.boxSize == desiredBoxSize
class TestBoxCreator(unittest.TestCase):
def setUp(self) -> None:
self.dataset: dataset.DataSet = dataset.DataSet('test')
self.boxCreator: BoxSelectionCreator = BoxSelectionCreator(self.dataset)
# def test_get_crossBoxSelectors_for_fraction(self):
# def getBoxSize(numBoxes):
# totalBoxArea: float = filterArea * desiredFraction
# areaPerBox: float = totalBoxArea / numBoxes
# boxSize: float = areaPerBox ** 0.5
# return boxSize
#
# self.dataset.lastpos = [0, 0]
# self.dataset.boundary = np.array([[0, 0], [0, 10], [10, 0], [10, 10]])
# self.dataset.imagescanMode = 'df'
# self.dataset.pixelscale_df = 1.0
# self.dataset.imagedim_df = [10, 10]
#
# filterArea: float = np.pi * 5**2
#
# desiredFraction: float = 0.1
# expectedResults: dict = {} # key: numBoxesAcross, value: boxSize
# for numBoxesAcross in [3, 5]:
# expectedResults[numBoxesAcross] = getBoxSize(2*numBoxesAcross - 1)
#
# crossBoxSelectors: list = self.boxCreator.get_crossBoxSelectors_for_fraction(desiredFraction)
# self.assertEqual(len(crossBoxSelectors), 2)
# for boxSelector in crossBoxSelectors:
# self.assertEqual(expectedResults[boxSelector.numBoxesAcross], boxSelector.boxSize)
self.dataset.imagescanMode = 'df'
self.dataset.pixelscale_df = 1.0
imgdim = 1000
minX, maxX, minY, maxY = 0, 1000, 0, 1000 # These are the actual borders!
self.dataset.maxdim = minX + imgdim / 2, maxY - imgdim / 2, maxX - imgdim / 2, minY + imgdim / 2
self.dataset.imagedim_df = [imgdim, imgdim]
self.boxCreator: BoxSelectionCreator = BoxSelectionCreator(self.dataset)
self.filterArea: float = np.pi * 500**2 # the maxDims are 1000 in each direction, so radius is 500
def test_get_crossBoxSelectors_for_fraction(self):
desiredFraction: float = 0.1
crossBoxSelectors: list = self.boxCreator.get_crossBoxSelectors_for_fraction(desiredFraction)
self.assertEqual(len(crossBoxSelectors), 2)
numBoxesAcrossList: list = []
for boxSelector in crossBoxSelectors:
numBoxesAcross = boxSelector.numBoxesAcross
numBoxesAcrossList.append(numBoxesAcross)
numBoxes = 2*numBoxesAcross - 1
self.assertEqual(boxSelector.boxSize, self._getBoxSize(numBoxes, desiredFraction))
self.assertTrue(3 in numBoxesAcrossList)
self.assertTrue(5 in numBoxesAcrossList)
def test_get_spiralBoxSelectors_for_fraction(self):
desiredFraction: float = 0.1
spiralBoxSelectors = self.boxCreator.get_spiralBoxSelectors_for_fraction(desiredFraction)
self.assertTrue(len(spiralBoxSelectors) == len(SpiralSelector.possibleBoxNumbers)) # all boxNumbers work here
for selector in spiralBoxSelectors:
self.assertEqual(selector.boxSize, self._getBoxSize(selector.numBoxes, desiredFraction))
desiredFraction: float = 0.5
spiralBoxSelectors = self.boxCreator.get_spiralBoxSelectors_for_fraction(desiredFraction)
self.assertTrue(len(spiralBoxSelectors) == 0) # no boxNumbers work here
def _getBoxSize(self, numBoxes: int, desiredFraction: float) -> float:
"""
Calculates the size of each box (= width = height), given a certain filter area and number of Boxes
:param numBoxes:
:param desiredFraction:
:return size (i.e. width = height) of each box:
"""
totalBoxArea: float = self.filterArea * desiredFraction
areaPerBox: float = totalBoxArea / numBoxes
boxSize: float = areaPerBox ** 0.5
return boxSize
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