Skip to content

Commit

Permalink
Size unit implementation for PointGeom and TextGeom (#215)
Browse files Browse the repository at this point in the history
* Size unit implemented for PointGeom and TextGeom

* Add comment for getSizeUnitRatio implementation

* Add comment for getSizeUnitRatio implementation

* Add comment for getSizeUnitRatio implementation

* Add comment for getSizeUnitRatio implementation

* Add size_unit notebook demo

* Modified size_unit example

* Simplify PointGeom.getSizeUnitRatio implementation

* Remove unused constant

* Remove unused constant

* Format rollback

* Return comment

* Edit comment

* Removed unused import

* Comment fix

* Changed comments in size_unit demo

* code cleanup
  • Loading branch information
IKrukov-HORIS committed Oct 27, 2020
1 parent 81b03e8 commit 3b513ea
Show file tree
Hide file tree
Showing 7 changed files with 566 additions and 9 deletions.
492 changes: 492 additions & 0 deletions docs/examples/jupyter-notebooks-dev/size_unit.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ package jetbrains.datalore.plot.base.aes
import jetbrains.datalore.plot.base.DataPointAesthetics

object AesScaling {
const val UNIT_SHAPE_SIZE = 2.2

fun strokeWidth(p: DataPointAesthetics): Double {
// aes Units -> px
return p.size()!! * 2.0
}

fun circleDiameter(p: DataPointAesthetics): Double {
// aes Units -> px
return p.size()!! * 2.2
return p.size()!! * UNIT_SHAPE_SIZE
}

fun circleDiameterSmaller(p: DataPointAesthetics): Double {
Expand All @@ -25,7 +27,7 @@ object AesScaling {

fun sizeFromCircleDiameter(diameter: Double): Double {
// px -> aes Units
return diameter / 2.2
return diameter / UNIT_SHAPE_SIZE
}

fun textSize(p: DataPointAesthetics): Double {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ package jetbrains.datalore.plot.base.geom

import jetbrains.datalore.base.geometry.DoubleVector
import jetbrains.datalore.base.values.Color
import jetbrains.datalore.plot.base.*
import jetbrains.datalore.plot.base.Aesthetics
import jetbrains.datalore.plot.base.CoordinateSystem
import jetbrains.datalore.plot.base.DataPointAesthetics
import jetbrains.datalore.plot.base.GeomContext
import jetbrains.datalore.plot.base.PositionAdjustment
import jetbrains.datalore.plot.base.aes.AesScaling
import jetbrains.datalore.plot.base.aes.AestheticsUtil
import jetbrains.datalore.plot.base.geom.util.GeomHelper
import jetbrains.datalore.plot.base.geom.util.HintColorUtil.fromColorValue
Expand All @@ -24,6 +29,7 @@ import jetbrains.datalore.vis.svg.slim.SvgSlimElements
open class PointGeom : GeomBase() {

var animation: Any? = null
var sizeUnit: String? = null

override val legendKeyElementFactory: LegendKeyElementFactory
get() = PointLegendKeyElementFactory()
Expand All @@ -40,6 +46,8 @@ open class PointGeom : GeomBase() {

val count = aesthetics.dataPointCount()
val slimGroup = SvgSlimElements.g(count)
val sizeUnitRatio = getSizeUnitRatio(ctx)

for (i in 0 until count) {
val p = aesthetics.dataPointAt(i)
val x = p.x()
Expand All @@ -49,16 +57,29 @@ open class PointGeom : GeomBase() {
val location = helper.toClient(DoubleVector(x!!, y!!), p)

val shape = p.shape()!!
targetCollector.addPoint(i, location, shape.size(p) / 2,

targetCollector.addPoint(
i, location, sizeUnitRatio * shape.size(p) / 2,
tooltipParams(p)
)
val o = PointShapeSvg.create(shape, location, p)
val o = PointShapeSvg.create(shape, location, p, sizeUnitRatio)
o.appendTo(slimGroup)
}
}
root.add(wrap(slimGroup))
}

private fun getSizeUnitRatio(ctx: GeomContext): Double {
return if (sizeUnit != null) {
val unitRes = ctx.getUnitResolution(GeomHelper.getSizeUnitAes(sizeUnit!!))
// TODO: Need refactoring: It's better to use NamedShape.FILLED_CIRCLE.size(1.0)
// but Shape.size() can't be used because it takes DataPointAesthetics as param
unitRes / AesScaling.UNIT_SHAPE_SIZE
} else {
1.0
}
}

companion object {
const val HANDLES_GROUPS = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,18 @@ import jetbrains.datalore.plot.common.data.SeriesUtil
class TextGeom : GeomBase() {
var formatter: StringFormat? = null
var naValue = DEF_NA_VALUE
var sizeUnit: String? = null

override val legendKeyElementFactory: LegendKeyElementFactory
get() = TextLegendKeyElementFactory()

override fun buildIntern(root: SvgRoot, aesthetics: Aesthetics, pos: PositionAdjustment, coord: CoordinateSystem, ctx: GeomContext) {
override fun buildIntern(
root: SvgRoot,
aesthetics: Aesthetics,
pos: PositionAdjustment,
coord: CoordinateSystem,
ctx: GeomContext
) {
val helper = GeomHelper(pos, coord, ctx)
val targetCollector = getGeomTargetCollector(ctx)
for (p in aesthetics.dataPoints()) {
Expand All @@ -37,7 +44,7 @@ class TextGeom : GeomBase() {
val text = toString(p.label())
if (SeriesUtil.allFinite(x, y) && !Strings.isNullOrEmpty(text)) {
val label = TextLabel(text)
GeomHelper.decorate(label, p)
GeomHelper.decorate(label, p, getSizeUnitRatio(ctx))

val loc = helper.toClient(x, y, p)
label.moveTo(loc)
Expand All @@ -55,6 +62,19 @@ class TextGeom : GeomBase() {
}
}

// This implementation is oversimplified.
// Current implementation works for label_format ='.2f'
// and values between -1.0 and 1.0.
private fun getSizeUnitRatio(ctx: GeomContext): Double {
return if ( sizeUnit != null) {
val textWidth = 6.0
val unitRes = ctx.getUnitResolution(GeomHelper.getSizeUnitAes(sizeUnit!!))
unitRes / textWidth
} else {
1.0
}
}

private fun toString(label: Any?): String {
return when {
label == null -> naValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package jetbrains.datalore.plot.base.geom.util
import jetbrains.datalore.base.gcommon.base.Strings
import jetbrains.datalore.base.geometry.DoubleRectangle
import jetbrains.datalore.base.geometry.DoubleVector
import jetbrains.datalore.plot.base.Aes
import jetbrains.datalore.plot.base.CoordinateSystem
import jetbrains.datalore.plot.base.DataPointAesthetics
import jetbrains.datalore.plot.base.GeomContext
Expand Down Expand Up @@ -162,11 +163,11 @@ open class GeomHelper(private val myPos: PositionAdjustment, coord: CoordinateSy
"mono" to "monospace"
)

fun decorate(label: TextLabel, p: DataPointAesthetics) {
fun decorate(label: TextLabel, p: DataPointAesthetics, scale: Double = 1.0) {

label.textColor().set(p.color())
label.textOpacity().set(p.alpha())
label.setFontSize(AesScaling.textSize(p))
label.setFontSize(AesScaling.textSize(p) * scale)

// family
var family = p.family()
Expand Down Expand Up @@ -255,5 +256,13 @@ open class GeomHelper(private val myPos: PositionAdjustment, coord: CoordinateSy
shape.setStroke(stroke, strokeAlpha)
shape.setStrokeWidth(AesScaling.strokeWidth(p))
}

fun getSizeUnitAes(sizeUnitName: String): Aes<Double> {
return when (sizeUnitName.toLowerCase()) {
"x" -> Aes.X
"y" -> Aes.Y
else -> error("Size unit value must be either 'x' or 'y', but was $sizeUnitName.")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import jetbrains.datalore.plot.config.Option.Geom.PointRange
import jetbrains.datalore.plot.config.Option.Geom.Segment
import jetbrains.datalore.plot.config.Option.Geom.Step


class GeomProtoClientSide(geomKind: GeomKind) : GeomProto(geomKind) {
private val preferredCoordinateSystem: CoordProvider? = when (geomKind) {
GeomKind.TILE,
Expand Down Expand Up @@ -115,9 +116,12 @@ class GeomProtoClientSide(geomKind: GeomKind) : GeomProto(geomKind) {

GeomKind.POINT -> return GeomProvider.point {
val geom = PointGeom()

if (opts.has(Point.ANIMATION)) {
geom.animation = opts[Point.ANIMATION]
}

geom.sizeUnit = opts.getString(Point.SIZE_UNIT)?.toLowerCase()
geom
}

Expand Down Expand Up @@ -148,6 +152,8 @@ class GeomProtoClientSide(geomKind: GeomKind) : GeomProto(geomKind) {
}
}

geom.sizeUnit = opts.getString(Text.SIZE_UNIT)?.toLowerCase()

geom
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ object Option {

object Point {
const val ANIMATION = "animation"
const val SIZE_UNIT = "size_unit"
}

object Image {
Expand All @@ -148,6 +149,7 @@ object Option {
object Text {
const val LABEL_FORMAT = "label_format"
const val NA_VALUE = "na_value"
const val SIZE_UNIT = "size_unit"
}

object LiveMap {
Expand All @@ -166,6 +168,11 @@ object Option {
const val GEOCODING = "geocoding"
const val DEV_PARAMS = "dev_params"
}

object SizeUnit {
const val X = "x"
const val Y = "y"
}
}

object Scale {
Expand Down

0 comments on commit 3b513ea

Please sign in to comment.