commonMain.jetbrains.datalore.plot.builder.MarginalLayerUtil.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plot-builder-portable-js Show documentation
Show all versions of plot-builder-portable-js Show documentation
The Let-Plot Kotlin API depends on this artifact.
The newest version!
/*
* Copyright (c) 2022. 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.builder
import jetbrains.datalore.base.interval.DoubleSpan
import jetbrains.datalore.plot.base.Aes
import jetbrains.datalore.plot.base.Scale
import jetbrains.datalore.plot.base.scale.Scales
import jetbrains.datalore.plot.base.scale.transform.Transforms
import jetbrains.datalore.plot.builder.assemble.PlotFacets
import jetbrains.datalore.plot.builder.assemble.PositionalScalesUtil
object MarginalLayerUtil {
private val MARGINAL_SCALE = Scales.continuousDomain("marginal", true)
private val MARGINAL_SCALE_REVERSED = MARGINAL_SCALE.with().continuousTransform(Transforms.REVERSE).build()
private val MARGINAL_SCALES = mapOf(
MarginSide.LEFT to MARGINAL_SCALE_REVERSED,
MarginSide.TOP to MARGINAL_SCALE,
MarginSide.RIGHT to MARGINAL_SCALE,
MarginSide.BOTTOM to MARGINAL_SCALE_REVERSED,
)
fun marginalLayersByMargin(marginalLayers: List): Map> {
return marginalLayers
.fold(LinkedHashMap>()) { map, layer ->
map.getOrPut(layer.marginalSide, ::ArrayList).add(layer)
map
}
}
fun marginalDomainByMargin(
marginalLayers: List,
scaleXProto: Scale,
scaleYProto: Scale,
): Map {
val scaleXYByMargin = scaleXYByMargin(scaleXProto, scaleYProto)
val layersByMargin = marginalLayersByMargin(marginalLayers)
return layersByMargin.mapValues { (side, layers) ->
val (marginScaleXProto, marginScaleYProto) = scaleXYByMargin.getValue(side)
val layersByTile = listOf(layers)
val domainXYByTile = PositionalScalesUtil.computePlotXYTransformedDomains(
layersByTile,
marginScaleXProto,
marginScaleYProto,
PlotFacets.undefined()
)
// All tiles share the same domain.
val (xDomain, yDomain) = domainXYByTile.first()
when (side) {
MarginSide.LEFT, MarginSide.RIGHT -> xDomain
MarginSide.TOP, MarginSide.BOTTOM -> yDomain
}
}
}
private fun scaleXYByMargin(
scaleXProto: Scale,
scaleYProto: Scale,
): Map> {
return mapOf(
MarginSide.LEFT to Pair(MARGINAL_SCALE_REVERSED, scaleYProto),
MarginSide.RIGHT to Pair(MARGINAL_SCALE, scaleYProto),
MarginSide.TOP to Pair(scaleXProto, MARGINAL_SCALE),
MarginSide.BOTTOM to Pair(scaleXProto, MARGINAL_SCALE_REVERSED)
)
}
fun toMarginalScaleMap(
scaleMap: Map, Scale>,
margin: MarginSide,
flipOrientation: Boolean
): Map, Scale> {
fun isXAxis(aes: Aes<*>): Boolean {
return when (flipOrientation) {
true -> Aes.isPositionalY(aes)
false -> Aes.isPositionalX(aes)
}
}
fun isYAxis(aes: Aes<*>): Boolean {
return when (flipOrientation) {
true -> Aes.isPositionalX(aes)
false -> Aes.isPositionalY(aes)
}
}
return scaleMap.mapValues { (aes, scale) ->
when (margin) {
MarginSide.LEFT, MarginSide.RIGHT -> if (isXAxis(aes)) MARGINAL_SCALES.getValue(margin) else scale
MarginSide.TOP, MarginSide.BOTTOM -> if (isYAxis(aes)) MARGINAL_SCALES.getValue(margin) else scale
}
}
}
}