Histograms refactor

This commit is contained in:
Alexander Nozik 2021-02-15 09:32:25 +03:00
parent ce18e85a0a
commit d1b4d1ac11
2 changed files with 24 additions and 28 deletions

View File

@ -8,7 +8,7 @@ import java.util.*
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.sqrt import kotlin.math.sqrt
internal fun <B: ClosedFloatingPointRange<Double>> TreeMap<Double, B>.getBin(value: Double): B? { private fun <B : ClosedFloatingPointRange<Double>> TreeMap<Double, B>.getBin(value: Double): B? {
// check ceiling entry and return it if it is what needed // check ceiling entry and return it if it is what needed
val ceil = ceilingEntry(value)?.value val ceil = ceilingEntry(value)?.value
if (ceil != null && value in ceil) return ceil if (ceil != null && value in ceil) return ceil
@ -29,12 +29,9 @@ public class TreeHistogram(
override val bins: Collection<UnivariateBin> get() = binMap.values override val bins: Collection<UnivariateBin> get() = binMap.values
} }
private class UnivariateBinValue( /**
override val domain: UnivariateDomain, * A space for univariate histograms with variable bin borders based on a tree map
override val value: Double, */
override val standardDeviation: Double,
) : UnivariateBin, ClosedFloatingPointRange<Double> by domain.range
@UnstableKMathAPI @UnstableKMathAPI
public class TreeHistogramSpace( public class TreeHistogramSpace(
public val binFactory: (Double) -> UnivariateDomain, public val binFactory: (Double) -> UnivariateDomain,
@ -73,7 +70,7 @@ public class TreeHistogramSpace(
val resBins = TreeMap<Double, UnivariateBin>() val resBins = TreeMap<Double, UnivariateBin>()
bins.forEach { key, binCounter -> bins.forEach { key, binCounter ->
val count = binCounter.counter.value val count = binCounter.counter.value
resBins[key] = UnivariateBinValue(binCounter.domain, count, sqrt(count)) resBins[key] = UnivariateBin(binCounter.domain, count, sqrt(count))
} }
return TreeHistogram(this, resBins) return TreeHistogram(this, resBins)
} }
@ -86,12 +83,14 @@ public class TreeHistogramSpace(
require(b.context == this) { "Histogram $b does not belong to this context" } require(b.context == this) { "Histogram $b does not belong to this context" }
val bins = TreeMap<Double, UnivariateBin>().apply { val bins = TreeMap<Double, UnivariateBin>().apply {
(a.bins.map { it.domain } union b.bins.map { it.domain }).forEach { def -> (a.bins.map { it.domain } union b.bins.map { it.domain }).forEach { def ->
val newBin = UnivariateBinValue( put(def.center,
UnivariateBin(
def, def,
value = (a[def.center]?.value ?: 0.0) + (b[def.center]?.value ?: 0.0), value = (a[def.center]?.value ?: 0.0) + (b[def.center]?.value ?: 0.0),
standardDeviation = (a[def.center]?.standardDeviation standardDeviation = (a[def.center]?.standardDeviation
?: 0.0) + (b[def.center]?.standardDeviation ?: 0.0) ?: 0.0) + (b[def.center]?.standardDeviation ?: 0.0)
) )
)
} }
} }
return TreeHistogram(this, bins) return TreeHistogram(this, bins)
@ -101,7 +100,7 @@ public class TreeHistogramSpace(
val bins = TreeMap<Double, UnivariateBin>().apply { val bins = TreeMap<Double, UnivariateBin>().apply {
a.bins.forEach { bin -> a.bins.forEach { bin ->
put(bin.domain.center, put(bin.domain.center,
UnivariateBinValue( UnivariateBin(
bin.domain, bin.domain,
value = bin.value * k.toDouble(), value = bin.value * k.toDouble(),
standardDeviation = abs(bin.standardDeviation * k.toDouble()) standardDeviation = abs(bin.standardDeviation * k.toDouble())

View File

@ -10,26 +10,23 @@ import kscience.kmath.structures.asSequence
public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2 public val UnivariateDomain.center: Double get() = (range.endInclusive - range.start) / 2
public interface UnivariateBin : Bin<Double>, ClosedFloatingPointRange<Double> { /**
public val domain: UnivariateDomain * A univariate bin based an a range
* @param value The value of histogram including weighting
/** * @param standardDeviation Standard deviation of the bin value. Zero or negative if not applicable
* The value of histogram including weighting
*/ */
public override val value: Double public class UnivariateBin(
public val domain: UnivariateDomain,
/** override val value: Double,
* Standard deviation of the bin value. Zero if not applicable public val standardDeviation: Double,
*/ ) : Bin<Double>, ClosedFloatingPointRange<Double> by domain.range {
public val standardDeviation: Double
public override val dimension: Int get() = 1 public override val dimension: Int get() = 1
public override fun contains(point: Buffer<Double>): Boolean = point.size == 1 && contains(point[0]) public override fun contains(point: Buffer<Double>): Boolean = point.size == 1 && contains(point[0])
} }
@UnstableKMathAPI @OptIn(UnstableKMathAPI::class)
public interface UnivariateHistogram : Histogram<Double, UnivariateBin>, public interface UnivariateHistogram : Histogram<Double, UnivariateBin>,
SpaceElement<UnivariateHistogram, Space<UnivariateHistogram>> { SpaceElement<UnivariateHistogram, Space<UnivariateHistogram>> {
public operator fun get(value: Double): UnivariateBin? public operator fun get(value: Double): UnivariateBin?