methods.py 3.53 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Nov 26 17:42:33 2019

@author: brandt
"""
import random
import numpy as np
from helpers import ParticleBinSorter

Josef Brandt's avatar
Josef Brandt committed
12

13 14 15 16 17 18
class SubsamplingMethod(object):
    def __init__(self, particleConatainer, desiredFraction: float = 0.2):
        super(SubsamplingMethod, self).__init__()
        self.particleContainer = particleConatainer
        self.fraction = desiredFraction

Josef Brandt's avatar
Josef Brandt committed
19 20 21 22 23 24 25
    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:
        """
26 27 28
        raise NotImplementedError


Josef Brandt's avatar
Josef Brandt committed
29
class RandomSampling(SubsamplingMethod):
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    def apply_subsampling_method(self):
        numOrigParticles = len(self.particleContainer.particles)
        numParticles = self._get_number_of_random_particles(numOrigParticles)
        subParticles = random.sample(self.particleContainer.particles, numParticles)
        return self.fraction, subParticles
    
    def _get_number_of_random_particles(self, numTotalParticles):
        return np.int(np.ceil(numTotalParticles * self.fraction))

        
class IvlevaSubsampling(SubsamplingMethod):
    def __init__(self, particleContainer, sigma=1.65, mpFraction=0.01, errorMargin=0.1):
        super(IvlevaSubsampling, self).__init__(particleContainer)
        self.sigma = sigma
        self.estimatedMPFraction = mpFraction
        self.errorMargin = errorMargin
    
    def apply_subsampling_method(self):
        N = self.particleContainer.getNumberOfParticles()
        numParticlesMeasured = self._get_ivleva_fraction(N)
        subParticles = random.sample(self.particleContainer.particles, numParticlesMeasured)
        fractionMeasured = numParticlesMeasured/N
        return fractionMeasured, subParticles
        
    def _get_ivleva_fraction(self, N):
        P = self.estimatedMPFraction
        e = P * self.errorMargin            
        numParticlesMeasured = np.ceil(P*(1 - P) / (e**2/self.sigma**2 + P*(1-P)/N))
        return np.int(numParticlesMeasured)
    

class SizeBinFractioning(SubsamplingMethod):
    def __init__(self, particleConatiner, desiredfraction: float = 0.2):
        super(SizeBinFractioning, self).__init__(particleConatiner, desiredfraction)
        self.sorter: ParticleBinSorter = ParticleBinSorter()
        
    def apply_subsampling_method(self):
        subParticlesPerBin: list = self._get_subParticles_per_bin(self.particleContainer.particles)
        subParticles: list = []
        for subParticleList in subParticlesPerBin:
            for particle in subParticleList:
                subParticles.append(particle)
        return self.fraction, subParticles
    
    def _get_subParticles_per_bin(self, particleList: list):
        particlesInBins: list = self.sorter.sort_particles_into_bins(particleList)
        subParticlesPerBin: list = []
        for particles in particlesInBins:
            numParticlesInBin: int = len(particles)
Josef Brandt's avatar
Josef Brandt committed
79
            numSubParticlesPerBin: int = np.int(np.round(numParticlesInBin * self.fraction))
80 81 82 83 84 85 86
            if numSubParticlesPerBin == 0 and numParticlesInBin > 0:
                numSubParticlesPerBin = 1

            subParticlesInBin: list = random.sample(particles, numSubParticlesPerBin)
            subParticlesPerBin.append(subParticlesInBin)
            
        return subParticlesPerBin