commonMain.jetbrains.datalore.plot.base.scale.AbstractScale.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lets-plot-common Show documentation
Show all versions of lets-plot-common Show documentation
Lets-Plot JVM package without rendering part
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
package jetbrains.datalore.plot.base.scale
import jetbrains.datalore.plot.base.ContinuousTransform
import jetbrains.datalore.plot.base.Scale
internal abstract class AbstractScale : Scale {
private val definedBreaks: List?
private val definedLabels: List?
final override val name: String
final override val mapper: ((Double?) -> T?)
final override var multiplicativeExpand = 0.0
protected set
final override var additiveExpand = 0.0
protected set
final override val labelFormatter: ((Any) -> String)?
override val isContinuous: Boolean
get() = false
override val isContinuousDomain: Boolean
get() = false
protected constructor(name: String, mapper: ((Double?) -> T?), breaks: List? = null) {
this.name = name
this.mapper = mapper
this.definedBreaks = breaks
definedLabels = null
labelFormatter = null
}
protected constructor(b: AbstractBuilder) {
name = b.myName
definedBreaks = b.myBreaks
definedLabels = b.myLabels
labelFormatter = b.myLabelFormatter
mapper = b.myMapper
multiplicativeExpand = b.myMultiplicativeExpand
additiveExpand = b.myAdditiveExpand
}
override fun hasBreaks(): Boolean {
return definedBreaks != null
}
protected open fun getBreaksIntern(): List {
check(hasBreaks()) { "No breaks defined for scale $name" }
@Suppress("UNCHECKED_CAST")
return definedBreaks as List
}
protected open fun getLabelsIntern(): List {
check(definedLabels != null) { "No labels defined for scale $name" }
return definedLabels
}
override fun applyTransform(source: List<*>, checkLimits: Boolean): List {
@Suppress("NAME_SHADOWING")
var source: List = source
// Replace values outside 'scale limits' with null-s.
if (checkLimits && hasDomainLimits()) {
source = source.map { if (it == null || isInDomainLimits(it)) it else null }
}
// Replace values outside of domain of 'continuous transform' with null-s.
if (transform is ContinuousTransform) {
val continuousTransform = transform as ContinuousTransform
if (continuousTransform.hasDomainLimits()) {
source = source.map { if (continuousTransform.isInDomain(it as Double?)) it else null }
}
}
return transform.apply(source)
}
override fun getScaleBreaks(): ScaleBreaks {
if (!hasBreaks()) {
return ScaleBreaks.EMPTY
}
val breakValuesIntern = getBreaksIntern()
val labels = getLabels(breakValuesIntern)
val transformed = applyTransform(breakValuesIntern, checkLimits = false)
// drop NULLs which can occure after transform.
val keepIndices: Set = transformed
.mapIndexed { i, v -> if (v == null) null else i }
.filterNotNull()
.toSet()
return ScaleBreaks(
domainValues = breakValuesIntern.filterIndexed { i, _ -> i in keepIndices },
transformedValues = transformed.filterNotNull(),
labels = labels.filterIndexed { i, _ -> i in keepIndices }
)
}
private fun getLabels(breaks: List): List {
if (definedLabels != null) {
val labels = getLabelsIntern()
return when {
labels.isEmpty() -> List(breaks.size) { "" }
breaks.size <= labels.size -> labels.subList(0, breaks.size)
else -> List(breaks.size) { i -> labels[i % labels.size] }
}
}
// generate labels
val formatter: (Any) -> String = labelFormatter ?: { v: Any -> v.toString() }
return breaks.map { formatter(it) }
}
protected abstract class AbstractBuilder(scale: AbstractScale) : Scale.Builder {
internal val myName: String = scale.name
internal var myBreaks: List? = scale.definedBreaks
internal var myLabels: List? = scale.definedLabels
internal var myLabelFormatter: ((Any) -> String)? = scale.labelFormatter
internal var myMapper: (Double?) -> T? = scale.mapper
internal var myMultiplicativeExpand: Double = scale.multiplicativeExpand
internal var myAdditiveExpand: Double = scale.additiveExpand
override fun breaks(l: List): Scale.Builder {
myBreaks = l.map {
@Suppress("UNCHECKED_CAST")
it as DomainT
}
return this
}
override fun labels(l: List): Scale.Builder {
myLabels = l
return this
}
override fun labelFormatter(v: (Any) -> String): Scale.Builder {
myLabelFormatter = v
return this
}
override fun mapper(m: (Double?) -> T?): Scale.Builder {
myMapper = m
return this
}
override fun multiplicativeExpand(v: Double): Scale.Builder {
myMultiplicativeExpand = v
return this
}
override fun additiveExpand(v: Double): Scale.Builder {
myAdditiveExpand = v
return this
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy