...

Commits (14)
 ... ... @@ -6,3 +6,11 @@ __pycache__/ *.png *.res cythonModules/build/ *.c *.pyd *.html
 import numpy as np cimport numpy as np cimport cython DTYPE = np.float ctypedef np.int32_t INT32_t def rotate_contour_around_point(np.ndarray[INT32_t, ndim=3] contour, np.ndarray[INT32_t, ndim=1] refPoint, np.float angleDegree): """ Rotates a point around another one... All coordinates in pixel space (integers) :param contour: Array of points to be rotated, [:, 0, 0] = x, [:, 0, 1] = y :param refPoint: The referemce point around which the first point is rotated, tuple of x and y :param angleDegree: The angle in degree to rotate (counter-clockwise) :return: Array of the rotated point, [:, 0, 0] = x, [:, 0, 1] = y """ cdef int i cdef double theta, sin, cos, x, y cdef np.ndarray[INT32_t, ndim=3] newContour theta = np.deg2rad(angleDegree) sin = np.sin(theta) cos = np.cos(theta) newContour = np.zeros_like(contour) for i in range(contour.shape[0]): x = cos * (contour[i, 0, 0]-refPoint[0]) - sin * (contour[i, 0, 1]-refPoint[1]) + refPoint[0] y = sin * (contour[i, 0, 0]-refPoint[0]) + cos * (contour[i, 0, 1]-refPoint[1]) + refPoint[1] newContour[i, 0, 0] = round(x) newContour[i, 0, 1] = round(y) return newContour
 # try: from setuptools import setup from setuptools import Extension from Cython.Build import cythonize import numpy as np import sys if len(sys.argv) == 1: sys.argv.append("build_ext") sys.argv.append("--inplace") ext = Extension("rotateContour", ["rotateContour.pyx"], extra_compile_args=['-O3'],) setup( name="rotate contour around reference point", ext_modules=cythonize([ext], annotate=True), # accepts a glob pattern include_dirs=[np.get_include()] ) \ No newline at end of file
 import copy import numpy as np import sys sys.path.append("C://Users//xbrjos//Desktop//Python") from gepard.analysis.particleContainer import ParticleContainer from cythonModules import rotateContour class ParticleVariations(object): def __init__(self, particleContainer: ParticleContainer, numVariations: int = 10) -> None: super(ParticleVariations, self).__init__() self.origParticleContainer = particleContainer self.numVariations = numVariations def get_particleContainer_variations(self) -> ParticleContainer: if self.numVariations > 0: partContainer: ParticleContainer = self.origParticleContainer contours: list = partContainer.getParticleContours() center: tuple = round(np.mean(contours[:][0][0])),\ round(np.mean(contours[:][0][1])) center: np.ndarray = np.array(center, dtype=np.int32) angles = self._get_angles() for i in range(self.numVariations): if i > 0: partContainer = copy.deepcopy(self.origParticleContainer) for particle in partContainer.particles: contour = np.int32(particle.contour) particle.contour = rotateContour.rotate_contour_around_point(contour, center, np.float(angles[i])) yield partContainer def _get_angles(self) -> np.ndarray: angleIncrement: float = 360 / self.numVariations return np.arange(self.numVariations) * angleIncrement
This diff is collapsed.
 from PyQt5 import QtGui, QtWidgets, QtCore import numpy as np import sys sys.path.append("C://Users//xbrjos//Desktop//Python") import gepard from gepard import dataset import helpers import numpy as np from cythonModules import rotateContour as rc class FilterView(QtWidgets.QGraphicsView): ... ... @@ -14,6 +15,7 @@ class FilterView(QtWidgets.QGraphicsView): self.setWindowTitle('FilterView') self.dataset: dataset.DataSet = None self.rotation: int = 0 scene = QtWidgets.QGraphicsScene(self) scene.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex) ... ... @@ -47,6 +49,20 @@ class FilterView(QtWidgets.QGraphicsView): self._update_particle_contours() self._fit_to_window() @helpers.timingDecorator def update_rotation(self, newRotation: int) -> None: if newRotation != self.rotation: angle: float = np.float(newRotation-self.rotation) center: np.ndarray = np.array([self.filter.circleOffset[0] + self.filter.diameter/2, self.filter.circleOffset[1] + self.filter.diameter/2], dtype=np.int32) for particle in self.dataset.particleContainer.particles: particle.contour = rc.rotate_contour_around_point(particle.contour, center, angle) self._update_particle_contours() self.rotation = newRotation @helpers.timingDecorator def _update_particle_contours(self) -> None: self._remove_particle_contours() if self.dataset is not None: ... ...
 ... ... @@ -9,6 +9,7 @@ class MeasureMode(QtCore.QObject): self.filterView: FilterView = relatedFilterView self.uiControls: QtWidgets.QGroupBox = QtWidgets.QGroupBox() self.boxGenerator: BoxSelectionSubsamplingMethod = None self.subParticles: list = [] def get_control_groupBox(self) -> QtWidgets.QGroupBox: return self.uiControls ... ... @@ -16,7 +17,7 @@ class MeasureMode(QtCore.QObject): def update_measure_viewItems(self) -> None: raise NotImplementedError def _send_measuredParticles_to_filterview(self) -> None: def send_measuredParticles_to_filterview(self) -> None: if self.boxGenerator.particleContainer is not None: subParticles = self.boxGenerator.apply_subsampling_method() self.filterView.update_measured_particles(subParticles) ... ... @@ -44,7 +45,7 @@ class CrossBoxMode(MeasureMode): topLefts: list = self.boxGenerator.get_topLeft_of_boxes() boxSize = self.boxGenerator.boxSize self.filterView.update_measure_boxes(topLefts, boxSize) self._send_measuredParticles_to_filterview() self.send_measuredParticles_to_filterview() class CrossBoxesControls(QtWidgets.QGroupBox): ... ... @@ -103,7 +104,7 @@ class SpiralBoxMode(MeasureMode): topLefts: list = self.boxGenerator.get_topLeft_of_boxes() boxSize = self.boxGenerator.boxSize self.filterView.update_measure_boxes(topLefts, boxSize) self._send_measuredParticles_to_filterview() self.send_measuredParticles_to_filterview() class SpiralBoxControls(QtWidgets.QGroupBox): ... ...
 ... ... @@ -3,9 +3,27 @@ import numpy as np import sys sys.path.append("C://Users//xbrjos//Desktop//Python") from gepard import dataset import time def timingDecorator(callingFunction): """ A wrapper function for timing the duration of the given function. :param callingFunction: :return: wrapped function """ def wrapper(*args, **kwargs): t0 = time.time() ret = callingFunction(*args, **kwargs) print(f'{callingFunction.__name__} took {np.round(time.time()-t0, 2)} seconds') return ret return wrapper class ParticleBinSorter(object): def __init__(self): super(ParticleBinSorter, self).__init__() self.bins = [5, 10, 20, 50, 100, 200, 500] ... ... @@ -114,7 +132,7 @@ def get_polygon_area(polygon: QtGui.QPolygonF) -> float: return area def get_filterDimensions_from_dataset(dataset) -> tuple: def get_filterDimensions_from_dataset(dataset: dataset.DataSet) -> tuple: """ Processes the datasets boundary items to calculate diameter and offset (coord system offset of circular filter with respect to actual dataset). This is used to set circular filter dimensions to use in the geometric ... ...
 ... ... @@ -4,6 +4,7 @@ from evaluation import TotalResults def load_results(fname: str) -> TotalResults: # TODO: REMVOE DATASET FROM SAMPLERESULTS, OTHERWISE THE FILESIZE IS GOING TO BE HUGE res: TotalResults = None if os.path.exists(fname): with open(fname, "rb") as fp: ... ...
 ... ... @@ -14,7 +14,7 @@ class SubsamplingMethod(object): def __init__(self, particleConatainer, desiredFraction: float = 0.2): super(SubsamplingMethod, self).__init__() self.particleContainer = particleConatainer self.fraction = desiredFraction self.fraction: float = desiredFraction @property def label(self) -> str: ... ...
 ... ... @@ -10,33 +10,57 @@ SET GEPARD TO EVALUATION BRANCH (WITHOUT THE TILING STUFF), OTHERWISE SOME OF TH """ # results: TotalResults = TotalResults() # pklsInFolders = get_pkls_from_directory(r'C:\Users\xbrjos\Desktop\temp MP\NewDatasets') # # for folder in pklsInFolders.keys(): # for samplePath in pklsInFolders[folder]: # newSampleResult: SampleResult = results.add_sample(samplePath) # for attr in get_attributes_from_foldername(folder): # newSampleResult.set_attribute(attr) # # t0 = time.time() # results.update_all() # print('updating all took', time.time()-t0, 'seconds') # results: TotalResults = TotalResults() pklsInFolders = get_pkls_from_directory(r'C:\Users\xbrjos\Desktop\temp MP\NewDatasets') for folder in pklsInFolders.keys(): for samplePath in pklsInFolders[folder]: newSampleResult: SampleResult = results.add_sample(samplePath) for attr in get_attributes_from_foldername(folder): newSampleResult.set_attribute(attr) t0 = time.time() results.update_all() print('updating all took', time.time()-t0, 'seconds') save_results('results1.res', results) # results: TotalResults = load_results('results1.res') # results.update_all(force=True) # save_results('results1.res', results) results: TotalResults = load_results('results1.res') errorPerFraction: dict = results.get_error_vs_fraction_data(methods=['spiral', 'cross']) plt.clf() errorPerFraction: dict = results.get_error_vs_fraction_data(attributes=['air', 'water'], methods=['chemo', 'sizeBin', 'random']) plt.subplot(121) for methodLabel in errorPerFraction.keys(): fractions: list = list(errorPerFraction[methodLabel].keys()) errors: list = list(errorPerFraction[methodLabel].values()) plt.plot(fractions, errors) plt.scatter(fractions, errors, label=methodLabel) plt.title('Air/Water sample', fontSize=15) plt.xscale('log') plt.xlabel('measured fraction', fontsize=12) plt.ylabel('mpCountError (%)', fontsize=12) plt.ylim([0, 100]) plt.legend() errorPerFraction: dict = results.get_error_vs_fraction_data(attributes=['sediment', 'soil', 'beach', 'slush'], methods=['chemo', 'sizeBin', 'random']) plt.subplot(122) for methodLabel in errorPerFraction.keys(): fractions: list = list(errorPerFraction[methodLabel].keys()) errors: list = list(errorPerFraction[methodLabel].values()) plt.plot(fractions, errors, label=methodLabel) plt.plot(fractions, errors) plt.scatter(fractions, errors, label=methodLabel) plt.title('Spiral or Box Layouts') plt.title('Sediment/Beach/Slush sample', fontSize=15) plt.xscale('log') plt.xlabel('measured fraction') plt.ylabel('mpCountError') plt.xlabel('measured fraction', fontsize=12) plt.ylabel('mpCountError (%)', fontsize=12) plt.ylim([0, 100]) plt.legend() plt.show()
 import numpy as np import sys sys.path.append("C://Users//xbrjos//Desktop//Python") import gepard from gepard.analysis.particleContainer import ParticleContainer def get_default_ParticleContainer() -> ParticleContainer: particleContainer: ParticleContainer = ParticleContainer(None) particleContainer.initializeParticles(4) contours: list = [] for i in range(4): x = 10*i contours.append(np.array([[[x, 0]], [[x+10, 0]], [[x+10, 10]], [[x, 10]]], dtype=np.int32)) particleContainer.setParticleContours(contours) return particleContainer
This diff is collapsed.
 import unittest import numpy as np from cythonModules import rotateContour as rc class CythonTester(unittest.TestCase): def test_rotate_contour(self): contour: np.ndarray = np.array([[[0, 5]], [[5, 5]], [[5, 0]]], dtype=np.int32) refPoint: np.ndarray = np.array([0, 0], dtype=np.int32) angle: float = 90.0 newContour: np.ndarray = rc.rotate_contour_around_point(contour, refPoint, angle) self.assertAlmostEqual(newContour[0, 0, 0], -5) self.assertAlmostEqual(newContour[0, 0, 1], 0) self.assertAlmostEqual(newContour[1, 0, 0], -5) self.assertAlmostEqual(newContour[1, 0, 1], 5) self.assertAlmostEqual(newContour[2, 0, 0], 0) self.assertAlmostEqual(newContour[2, 0, 1], 5) angle = 180.0 newContour = rc.rotate_contour_around_point(contour, refPoint, angle) self.assertAlmostEqual(newContour[0, 0, 0], 0) self.assertAlmostEqual(newContour[0, 0, 1], -5) self.assertAlmostEqual(newContour[1, 0, 0], -5) self.assertAlmostEqual(newContour[1, 0, 1], -5) self.assertAlmostEqual(newContour[2, 0, 0], -5) self.assertAlmostEqual(newContour[2, 0, 1], 0) angle = 270.0 newContour = rc.rotate_contour_around_point(contour, refPoint, angle) self.assertAlmostEqual(newContour[0, 0, 0], 5) self.assertAlmostEqual(newContour[0, 0, 1], 0) self.assertAlmostEqual(newContour[1, 0, 0], 5) self.assertAlmostEqual(newContour[1, 0, 1], -5) self.assertAlmostEqual(newContour[2, 0, 0], 0) self.assertAlmostEqual(newContour[2, 0, 1], -5) refPoint = np.array([5, 5], dtype=np.int32) angle: float = 90.0 newContour = rc.rotate_contour_around_point(contour, refPoint, angle) self.assertAlmostEqual(newContour[0, 0, 0], 5) self.assertAlmostEqual(newContour[0, 0, 1], 0) self.assertAlmostEqual(newContour[2, 0, 0], 10) self.assertAlmostEqual(newContour[2, 0, 1], 5) angle = 180.0 newContour = rc.rotate_contour_around_point(contour, refPoint, angle) self.assertAlmostEqual(newContour[0, 0, 0], 10) self.assertAlmostEqual(newContour[0, 0, 1], 5) self.assertAlmostEqual(newContour[2, 0, 0], 5) self.assertAlmostEqual(newContour[2, 0, 1], 10) angle = 270.0 newContour = rc.rotate_contour_around_point(contour, refPoint, angle) self.assertAlmostEqual(newContour[0, 0, 0], 5) self.assertAlmostEqual(newContour[0, 0, 1], 10) self.assertAlmostEqual(newContour[2, 0, 0], 0) self.assertAlmostEqual(newContour[2, 0, 1], 5)
 import unittest import numpy as np import sys sys.path.append("C://Users//xbrjos//Desktop//Python") from gepard.analysis.particleContainer import ParticleContainer from datasetOperations import ParticleVariations from helpers_for_test import get_default_ParticleContainer class TestParticleVariations(unittest.TestCase): def test_get_particleContainer_variations(self): particleContainer: ParticleContainer = get_default_ParticleContainer() contours = particleContainer.getParticleContours() center: tuple = round(np.mean(contours[:][0][0])), \ round(np.mean(contours[:][0][1])) center: np.ndarray = np.array(center, dtype=np.int32) for numVariations in [0, 1, 10, 20]: particleVariations: ParticleVariations = ParticleVariations(particleContainer, numVariations) foundContours: list = [] if numVariations == 0: self.assertEqual(len(list(particleVariations.get_particleContainer_variations())), 0) else: for index, partContainer in enumerate(particleVariations.get_particleContainer_variations()): if index == 0: self.assertTrue(partContainer is particleContainer) else: self.assertFalse(partContainer is particleContainer) contours = [] for particle in partContainer.particles: contours.append(particle.contour) contourHash = hash(particle.contour.tostring()) self.assertTrue(contourHash not in foundContours) foundContours.append(contourHash) self.assertEqual(index, numVariations-1) def test_get_angles(self): particleVariations: ParticleVariations = ParticleVariations(None, 2) angles: list = list(particleVariations._get_angles()) self.assertEqual(angles, [0, 180]) particleVariations.numVariations = 4 angles: list = list(particleVariations._get_angles()) self.assertEqual(angles, [0, 90, 180, 270])
This diff is collapsed.
 ... ... @@ -13,8 +13,9 @@ import numpy as np import gepard from gepard.analysis.particleContainer import ParticleContainer from gepard.analysis.particleAndMeasurement import Particle from methods import RandomSampling, SizeBinFractioning from methods import SubsamplingMethod, RandomSampling, SizeBinFractioning import geometricMethods as gmeth import chemometricMethods as cmeth from helpers import ParticleBinSorter ... ... @@ -24,6 +25,24 @@ def get_default_particle_container(numParticles=1000): return particleContainer class TestAllMethodsGeneric(unittest.TestCase): allMethodClasses : list = [RandomSampling, SizeBinFractioning, gmeth.CrossBoxSubSampling, gmeth.SpiralBoxSubsampling, cmeth.ChemometricSubsampling] def setUp(self) -> None: self.methods = [] for methClass in self.allMethodClasses: self.methods.append(methClass(None, 0.1)) def test_basic_methods(self): for method in self.methods: method: SubsamplingMethod = method label: str = method.label self.assertEqual(type(label), str) class TestRandomParticles(unittest.TestCase): def test_get_number_of_random_particles(self): randomSampling = RandomSampling(None, desiredFraction=0.1) ... ...