diff --git a/docs/examples/jupyter-notebooks-dev/livemap/pie_bar_on_livemap.ipynb b/docs/examples/jupyter-notebooks-dev/livemap/pie_bar_on_livemap.ipynb
index 9ec2decd6bf..a68428ae423 100644
--- a/docs/examples/jupyter-notebooks-dev/livemap/pie_bar_on_livemap.ipynb
+++ b/docs/examples/jupyter-notebooks-dev/livemap/pie_bar_on_livemap.ipynb
@@ -2,274 +2,97 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "from lets_plot import *"
+ "from lets_plot import *\n",
+ "import lets_plot.mapping as pm"
]
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- " \n",
- " \n",
- " "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"LetsPlot.setup_html()"
]
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "LetsPlot.set(maptiles_zxy(url='https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png'))"
+ "from lets_plot.settings_utils import maptiles_lets_plot\n",
+ "LetsPlot.set(maptiles_lets_plot(url='ws://10.0.0.127:3933'))"
]
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "data = {'val': [3000, 0, -2000, 1500, 1000, 2500], \\\n",
- " 'order': [1, 2, 3, 1, 2, 3], \\\n",
- " 'lat': [31, 31, 31, 42, 42, 42],\\\n",
- " 'lng': [-100, -100, -100, -93, -93, -93],\\\n",
- " 'lnglat': [\"-100,31\",\"-100,31\",\"-100,31\",\"-93,42\",\"-93,42\",\"-93,42\"]}"
+ "data = {\n",
+ " 'val': [1500, 1000, 1000, 500, 600, 700, 500, 600, 700, 700],\n",
+ " 'order': [1, 1, 2, 2, 3, 3, 4, 4 , 5, 5],\n",
+ " 'lon': [-82, -100, -82, -100, -82, -100, -82, -100, -82, -100],\n",
+ " 'lat': [28, 31, 28, 31, 28, 31, 28, 31, 28, 31]\n",
+ "}"
]
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": null,
"metadata": {
"scrolled": false
},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
- "ggplot(data) + geom_livemap(aes(map_id='lnglat', x = 'order', y='val', fill = 'order'), symbol='bar', size = 30)"
+ "ggplot(data) + geom_livemap(aes(x='lon', y='lat', sym_y='val', fill='val'), symbol='bar', size = 30)"
]
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"ggplot(data) \\\n",
- " + geom_livemap(aes(map_id='lnglat', x='order', y= 'val', fill='order'), symbol='pie', size=30) \\\n",
- " + scale_fill_hue(h = [0.,120.], name = 'order')"
+ " + geom_livemap(aes(x='lon', y='lat', sym_x='order', sym_y= 'val', fill='val'), symbol='bar', size=50) \\\n",
+ " + scale_fill_gradient(low='yellow', high='red')"
]
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"ggplot(data) \\\n",
- " + geom_livemap(aes(map_id='lnglat', x='order', y= 'val', fill='order'), symbol='bar', size=50) \\\n",
- " + scale_fill_hue(h = [0.,120.], name = 'order')"
+ " + geom_livemap(aes(x='lon', y='lat', sym_x='order', sym_y='val', fill='val'), symbol='pie', size=32, color='orange') \\\n",
+ " + scale_fill_gradient(low='yellow', high='red') + ggsize(600,200)"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ggplot(data) \\\n",
+ " + geom_livemap(aes(x='lon', y='lat', sym_y='val', fill='val'), symbol='pie', size=32, color='orange') \\\n",
+ " + scale_fill_gradient(low='yellow', high='red') + ggsize(600,200)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
}
],
"metadata": {
diff --git a/livemap-demo/src/commonMain/kotlin/jetbrains/livemap/plotDemo/LiveMap.kt b/livemap-demo/src/commonMain/kotlin/jetbrains/livemap/plotDemo/LiveMap.kt
index 47c51aba9ab..5bb6cd9f644 100644
--- a/livemap-demo/src/commonMain/kotlin/jetbrains/livemap/plotDemo/LiveMap.kt
+++ b/livemap-demo/src/commonMain/kotlin/jetbrains/livemap/plotDemo/LiveMap.kt
@@ -249,7 +249,8 @@ class LiveMap : PlotConfigDemoBase() {
{
"geom":"livemap",
"mapping":{
- "map_id":"lonlat",
+ "x":"x",
+ "y":"y",
"color":"label"
},
"display_mode":"point",
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/Aes.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/Aes.kt
index 3dd0c1e12b5..fd257953113 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/Aes.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/Aes.kt
@@ -34,10 +34,8 @@ class Aes private constructor(val name: String, val isNumeric: Boolean = true
val COLOR: Aes = Aes("color", false)
val FILL: Aes = Aes("fill", false)
val ALPHA: Aes = Aes("alpha")
- val SHAPE: Aes =
- Aes("shape", false)
- val LINETYPE: Aes =
- Aes("linetype", false)
+ val SHAPE: Aes = Aes("shape", false)
+ val LINETYPE: Aes = Aes("linetype", false)
val SIZE: Aes = Aes("size")
val WIDTH: Aes = Aes("width")
@@ -58,7 +56,6 @@ class Aes private constructor(val name: String, val isNumeric: Boolean = true
val XEND: Aes = Aes("xend")
val YEND: Aes = Aes("yend")
- val MAP_ID: Aes = Aes("map_id", false)
val FRAME: Aes = Aes("frame", false)
val SPEED: Aes = Aes("speed")
@@ -76,6 +73,9 @@ class Aes private constructor(val name: String, val isNumeric: Boolean = true
val ANGLE: Aes = Aes("angle")
+ val SYM_X: Aes = Aes("sym_x")
+ val SYM_Y: Aes = Aes("sym_y")
+
fun numeric(unfiltered: Iterable>): Iterable> {
// safe to cast all 'numeric' aesthetics are 'Double'
@@ -135,8 +135,7 @@ class Aes private constructor(val name: String, val isNumeric: Boolean = true
}
fun noGuideNeeded(aes: Aes<*>): Boolean {
- return aes == MAP_ID ||
- aes == FRAME ||
+ return aes == FRAME ||
aes == SPEED ||
aes == FLOW ||
aes == LABEL ||
@@ -148,6 +147,8 @@ class Aes private constructor(val name: String, val isNumeric: Boolean = true
aes == ANGLE ||
aes == FAMILY ||
aes == FONTFACE ||
+ aes == SYM_X ||
+ aes == SYM_Y ||
isPositional(aes)
}
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/DataPointAesthetics.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/DataPointAesthetics.kt
index 67f45478078..af601d75bf5 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/DataPointAesthetics.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/DataPointAesthetics.kt
@@ -54,8 +54,6 @@ interface DataPointAesthetics {
fun upper(): Double?
- fun mapId(): Any
-
fun frame(): String
fun speed(): Double?
@@ -82,6 +80,10 @@ interface DataPointAesthetics {
fun angle(): Double?
+ fun symX(): Double?
+
+ fun symY(): Double?
+
fun group(): Int?
fun numeric(aes: Aes): Double?
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/GeomMeta.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/GeomMeta.kt
index a4bb321d881..a6bed4564ef 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/GeomMeta.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/GeomMeta.kt
@@ -29,8 +29,7 @@ object GeomMeta {
Aes.COLOR,
Aes.FILL,
Aes.ALPHA,
- Aes.SHAPE,
- Aes.MAP_ID
+ Aes.SHAPE
// strokeWidth
)
@@ -40,7 +39,6 @@ object GeomMeta {
Aes.LINETYPE,
Aes.COLOR,
Aes.ALPHA,
- Aes.MAP_ID,
Aes.SPEED,
Aes.FLOW
)
@@ -51,8 +49,7 @@ object GeomMeta {
Aes.LINETYPE,
Aes.COLOR,
Aes.FILL,
- Aes.ALPHA,
- Aes.MAP_ID
+ Aes.ALPHA
)
private val AREA = listOf(
@@ -167,8 +164,7 @@ object GeomMeta {
Aes.LINETYPE,
Aes.COLOR,
Aes.FILL,
- Aes.ALPHA,
- Aes.MAP_ID
+ Aes.ALPHA
)
GeomKind.AB_LINE -> listOf(
@@ -237,8 +233,7 @@ object GeomMeta {
Aes.LINETYPE,
Aes.COLOR,
Aes.FILL,
- Aes.ALPHA,
- Aes.MAP_ID
+ Aes.ALPHA
)
GeomKind.SEGMENT -> listOf(
@@ -262,12 +257,10 @@ object GeomMeta {
Aes.FONTFACE,
Aes.HJUST,
Aes.VJUST,
- Aes.ANGLE,
- Aes.MAP_ID
+ Aes.ANGLE
)
GeomKind.LIVE_MAP -> listOf( // ToDo: not static - depends on 'display mode'
- Aes.MAP_ID,
Aes.ALPHA,
Aes.COLOR,
Aes.FILL,
@@ -275,7 +268,9 @@ object GeomMeta {
Aes.SHAPE,
Aes.FRAME,
Aes.X,
- Aes.Y
+ Aes.Y,
+ Aes.SYM_X,
+ Aes.SYM_Y
)
GeomKind.RASTER -> listOf(
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesInitValue.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesInitValue.kt
index 5e0bf60c989..49dae5e8cf8 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesInitValue.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesInitValue.kt
@@ -23,12 +23,13 @@ import jetbrains.datalore.plot.base.Aes.Companion.INTERCEPT
import jetbrains.datalore.plot.base.Aes.Companion.LABEL
import jetbrains.datalore.plot.base.Aes.Companion.LINETYPE
import jetbrains.datalore.plot.base.Aes.Companion.LOWER
-import jetbrains.datalore.plot.base.Aes.Companion.MAP_ID
import jetbrains.datalore.plot.base.Aes.Companion.MIDDLE
import jetbrains.datalore.plot.base.Aes.Companion.SHAPE
import jetbrains.datalore.plot.base.Aes.Companion.SIZE
import jetbrains.datalore.plot.base.Aes.Companion.SLOPE
import jetbrains.datalore.plot.base.Aes.Companion.SPEED
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_X
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_Y
import jetbrains.datalore.plot.base.Aes.Companion.UPPER
import jetbrains.datalore.plot.base.Aes.Companion.VJUST
import jetbrains.datalore.plot.base.Aes.Companion.WEIGHT
@@ -73,7 +74,6 @@ object AesInitValue {
VALUE_MAP[LOWER] = Double.NaN
VALUE_MAP[MIDDLE] = Double.NaN
VALUE_MAP[UPPER] = Double.NaN
- VALUE_MAP[MAP_ID] = "empty map_id"
VALUE_MAP[FRAME] = "empty frame"
VALUE_MAP[SPEED] = 10.0
VALUE_MAP[FLOW] = 0.1
@@ -87,6 +87,8 @@ object AesInitValue {
VALUE_MAP[HJUST] = 0.5 // 'middle'
VALUE_MAP[VJUST] = 0.5 // 'middle'
VALUE_MAP[ANGLE] = 0.0
+ VALUE_MAP[SYM_X] = 0.0
+ VALUE_MAP[SYM_Y] = 0.0
}
/**
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesVisitor.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesVisitor.kt
index 3cc7b74c7ea..ae3f007d981 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesVisitor.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AesVisitor.kt
@@ -20,12 +20,13 @@ import jetbrains.datalore.plot.base.Aes.Companion.INTERCEPT
import jetbrains.datalore.plot.base.Aes.Companion.LABEL
import jetbrains.datalore.plot.base.Aes.Companion.LINETYPE
import jetbrains.datalore.plot.base.Aes.Companion.LOWER
-import jetbrains.datalore.plot.base.Aes.Companion.MAP_ID
import jetbrains.datalore.plot.base.Aes.Companion.MIDDLE
import jetbrains.datalore.plot.base.Aes.Companion.SHAPE
import jetbrains.datalore.plot.base.Aes.Companion.SIZE
import jetbrains.datalore.plot.base.Aes.Companion.SLOPE
import jetbrains.datalore.plot.base.Aes.Companion.SPEED
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_X
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_Y
import jetbrains.datalore.plot.base.Aes.Companion.UPPER
import jetbrains.datalore.plot.base.Aes.Companion.VJUST
import jetbrains.datalore.plot.base.Aes.Companion.WEIGHT
@@ -125,9 +126,6 @@ abstract class AesVisitor {
if (aes == UPPER) {
return upper()
}
- if (aes == MAP_ID) {
- return mapId()
- }
if (aes == FRAME) {
return frame()
}
@@ -168,6 +166,14 @@ abstract class AesVisitor {
return angle()
}
+ if (aes == SYM_X) {
+ return symX()
+ }
+
+ if (aes == SYM_Y) {
+ return symY()
+ }
+
throw IllegalArgumentException("Unexpected aes: $aes")
}
@@ -213,8 +219,6 @@ abstract class AesVisitor {
protected abstract fun upper(): T
- protected abstract fun mapId(): T
-
protected abstract fun frame(): T
protected abstract fun speed(): T
@@ -240,4 +244,8 @@ abstract class AesVisitor {
protected abstract fun vjust(): T
protected abstract fun angle(): T
+
+ protected abstract fun symX(): T
+
+ protected abstract fun symY(): T
}
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsBuilder.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsBuilder.kt
index 2744bc8e0d8..b5d5e510867 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsBuilder.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsBuilder.kt
@@ -26,12 +26,13 @@ import jetbrains.datalore.plot.base.Aes.Companion.INTERCEPT
import jetbrains.datalore.plot.base.Aes.Companion.LABEL
import jetbrains.datalore.plot.base.Aes.Companion.LINETYPE
import jetbrains.datalore.plot.base.Aes.Companion.LOWER
-import jetbrains.datalore.plot.base.Aes.Companion.MAP_ID
import jetbrains.datalore.plot.base.Aes.Companion.MIDDLE
import jetbrains.datalore.plot.base.Aes.Companion.SHAPE
import jetbrains.datalore.plot.base.Aes.Companion.SIZE
import jetbrains.datalore.plot.base.Aes.Companion.SLOPE
import jetbrains.datalore.plot.base.Aes.Companion.SPEED
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_X
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_Y
import jetbrains.datalore.plot.base.Aes.Companion.UPPER
import jetbrains.datalore.plot.base.Aes.Companion.VJUST
import jetbrains.datalore.plot.base.Aes.Companion.WEIGHT
@@ -123,10 +124,6 @@ class AestheticsBuilder @JvmOverloads constructor(private var myDataPointCount:
return aes(WEIGHT, v)
}
- fun mapId(v: (Int) -> Any?): AestheticsBuilder {
- return aes(MAP_ID, v)
- }
-
fun frame(v: (Int) -> String?): AestheticsBuilder {
return aes(FRAME, v)
}
@@ -184,6 +181,14 @@ class AestheticsBuilder @JvmOverloads constructor(private var myDataPointCount:
return aes(YMAX, v)
}
+ fun symX(v: (Int) -> Double?): AestheticsBuilder {
+ return aes(SYM_X, v)
+ }
+
+ fun symY(v: (Int) -> Double?): AestheticsBuilder {
+ return aes(SYM_Y, v)
+ }
+
fun constantAes(aes: Aes, v: T): AestheticsBuilder {
myConstantAes.add(aes)
myIndexFunctionMap[aes] = constant(v)
@@ -438,10 +443,6 @@ class AestheticsBuilder @JvmOverloads constructor(private var myDataPointCount:
return get(UPPER)
}
- override fun mapId(): Any {
- return get(MAP_ID)
- }
-
override fun frame(): String {
return get(FRAME)
}
@@ -494,6 +495,14 @@ class AestheticsBuilder @JvmOverloads constructor(private var myDataPointCount:
return get(ANGLE)
}
+ override fun symX(): Double? {
+ return get(SYM_X)
+ }
+
+ override fun symY(): Double? {
+ return get(SYM_Y)
+ }
+
override fun group(): Int? {
return myAesthetics.group(myIndex!!)
}
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsDefaults.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsDefaults.kt
index e4d47f362de..948ac025168 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsDefaults.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/aes/AestheticsDefaults.kt
@@ -152,9 +152,8 @@ open class AestheticsDefaults {
return crossBar()
}
- fun livemap(displayMode: LivemapConstants.DisplayMode, scaled: Boolean): AestheticsDefaults {
+ fun livemap(displayMode: LivemapConstants.DisplayMode): AestheticsDefaults {
return when (displayMode) {
- LivemapConstants.DisplayMode.POLYGON -> polygon()
LivemapConstants.DisplayMode.POINT -> point()
.updateInLegend(Aes.SIZE, 5.0)
LivemapConstants.DisplayMode.BAR -> base()
@@ -164,7 +163,6 @@ open class AestheticsDefaults {
.update(Aes.SIZE, 20.0)
.update(Aes.COLOR, Color.TRANSPARENT)
.updateInLegend(Aes.SIZE, 5.0)
- LivemapConstants.DisplayMode.HEATMAP -> base().update(Aes.SIZE, if (scaled) 0.01 else 10.0)
}
}
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/DataFrameUtil.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/DataFrameUtil.kt
index d79d5b236a0..934d949de55 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/DataFrameUtil.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/DataFrameUtil.kt
@@ -98,7 +98,7 @@ object DataFrameUtil {
}
fun variables(df: DataFrame): Map {
- return df.variables().associateBy { it.name }
+ return df.variables().associateBy(DataFrame.Variable::name)
}
fun appendReplace(df0: DataFrame, df1: DataFrame): DataFrame {
@@ -169,3 +169,5 @@ object DataFrameUtil {
return b.build()
}
}
+
+
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/TransformVar.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/TransformVar.kt
index 7f1926bb14a..aac66464658 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/TransformVar.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/data/TransformVar.kt
@@ -33,7 +33,6 @@ object TransformVar {
val LOWER = DataFrame.Variable("transform.LOWER", TRANSFORM)
val MIDDLE = DataFrame.Variable("transform.MIDDLE", TRANSFORM)
val UPPER = DataFrame.Variable("transform.UPPER", TRANSFORM)
- val MAP_ID = DataFrame.Variable("transform.MAP_ID", TRANSFORM)
val FRAME = DataFrame.Variable("transform.FRAME", TRANSFORM)
val SPEED = DataFrame.Variable("transform.SPEED", TRANSFORM)
val FLOW = DataFrame.Variable("transform.FLOW", TRANSFORM)
@@ -47,6 +46,8 @@ object TransformVar {
val HJUST = DataFrame.Variable("transform.HJUST", TRANSFORM)
val VJUST = DataFrame.Variable("transform.VJUST", TRANSFORM)
val ANGLE = DataFrame.Variable("transform.ANGLE", TRANSFORM)
+ val SYM_X = DataFrame.Variable("transform.SYM_X", TRANSFORM)
+ val SYM_Y = DataFrame.Variable("transform.SYM_Y", TRANSFORM)
private val VAR_BY_AES = TransformVarByAes()
private val VARS: Map
@@ -160,11 +161,6 @@ object TransformVar {
return UPPER
}
-
- override fun mapId(): DataFrame.Variable {
- return MAP_ID
- }
-
override fun frame(): DataFrame.Variable {
return FRAME
}
@@ -216,5 +212,13 @@ object TransformVar {
override fun angle(): DataFrame.Variable {
return ANGLE
}
+
+ override fun symX(): DataFrame.Variable {
+ return SYM_X
+ }
+
+ override fun symY(): DataFrame.Variable {
+ return SYM_Y
+ }
}
}
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/LiveMapGeom.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/LiveMapGeom.kt
index 205f9d71e87..2cb7da21c24 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/LiveMapGeom.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/LiveMapGeom.kt
@@ -5,8 +5,6 @@
package jetbrains.datalore.plot.base.geom
-import jetbrains.datalore.base.geometry.DoubleVector
-import jetbrains.datalore.base.values.SomeFig
import jetbrains.datalore.base.geometry.DoubleRectangle
import jetbrains.datalore.plot.base.*
import jetbrains.datalore.plot.base.geom.legend.GenericLegendKeyElementFactory
@@ -49,7 +47,6 @@ class LiveMapGeom(private val myDisplayMode: DisplayMode) : Geom {
// ToDo: not static, depends on 'display mode'
// val RENDERS = listOf(
-// Aes.MAP_ID,
// Aes.ALPHA,
// Aes.COLOR,
// Aes.FILL,
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/MapGeom.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/MapGeom.kt
index 99f05304679..733bb8d9dc2 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/MapGeom.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/MapGeom.kt
@@ -18,8 +18,6 @@ class MapGeom : PolygonGeom() {
// Aes.COLOR,
// Aes.FILL,
// Aes.ALPHA,
-//
-// Aes.MAP_ID
// )
const val HANDLES_GROUPS = true
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/RectGeom.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/RectGeom.kt
index 808e5830600..1831c699a49 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/RectGeom.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/RectGeom.kt
@@ -40,7 +40,6 @@ class RectGeom : GeomBase() {
// Aes.COLOR,
// Aes.FILL,
// Aes.ALPHA,
-// Aes.MAP_ID
// )
//rectangle groups are used in geom_livemap
const val HANDLES_GROUPS = true
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/util/DataPointAestheticsDelegate.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/util/DataPointAestheticsDelegate.kt
index 6e59201b96b..e59a07d8dd3 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/util/DataPointAestheticsDelegate.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/geom/util/DataPointAestheticsDelegate.kt
@@ -102,10 +102,6 @@ open class DataPointAestheticsDelegate(private val p: DataPointAesthetics) :
return p.upper()
}
- override fun mapId(): Any {
- return p.mapId()
- }
-
override fun frame(): String {
return p.frame()
}
@@ -158,6 +154,14 @@ open class DataPointAestheticsDelegate(private val p: DataPointAesthetics) :
return p.angle()
}
+ override fun symX(): Double? {
+ return p.symX()
+ }
+
+ override fun symY(): Double? {
+ return p.symY()
+ }
+
override fun group(): Int? {
return p.group()
}
diff --git a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/livemap/LiveMapConstants.kt b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/livemap/LiveMapConstants.kt
index 88eb1cefe96..18c35becea6 100644
--- a/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/livemap/LiveMapConstants.kt
+++ b/plot-base-portable/src/commonMain/kotlin/jetbrains/datalore/plot/base/livemap/LiveMapConstants.kt
@@ -7,10 +7,8 @@ package jetbrains.datalore.plot.base.livemap
interface LivemapConstants {
enum class DisplayMode {
- POLYGON,
POINT,
PIE,
- HEATMAP,
BAR
}
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/GeomLayerBuilder.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/GeomLayerBuilder.kt
index dec25e0ff9e..b19466e3992 100644
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/GeomLayerBuilder.kt
+++ b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/GeomLayerBuilder.kt
@@ -36,6 +36,7 @@ class GeomLayerBuilder {
private lateinit var myPosProvider: PosProvider
private lateinit var myGeomProvider: GeomProvider
private var myGroupingVarName: String? = null
+ private var myPathIdVarName: String? = null
private val myScaleProviderByAes = HashMap, ScaleProvider<*>>()
private var myDataPreprocessor: ((DataFrame) -> DataFrame)? = null
@@ -74,6 +75,11 @@ class GeomLayerBuilder {
return this
}
+ fun pathIdVarName(v: String): GeomLayerBuilder {
+ myPathIdVarName = v
+ return this
+ }
+
fun addConstantAes(aes: Aes, v: T): GeomLayerBuilder {
myConstantByAes.put(aes, v)
return this
@@ -148,7 +154,7 @@ class GeomLayerBuilder {
myPosProvider,
// handledAes(),
myGeomProvider.renders(),
- GroupingContext(data, myBindings, myGroupingVarName, handlesGroups()).groupMapper,
+ GroupingContext(data, myBindings, myGroupingVarName, myPathIdVarName, handlesGroups()).groupMapper,
replacementBindings.values,
myConstantByAes,
dataAccess,
@@ -276,6 +282,7 @@ class GeomLayerBuilder {
transformedData,
builder.myBindings,
builder.myGroupingVarName,
+ builder.myPathIdVarName,
true
)
val dataAndGroupingContext = DataProcessing.buildStatData(
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/geom/GeomProvider.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/geom/GeomProvider.kt
index 20d3f16b5a5..d16e1799997 100644
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/geom/GeomProvider.kt
+++ b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/assemble/geom/GeomProvider.kt
@@ -233,7 +233,7 @@ abstract class GeomProvider private constructor(val geomKind: GeomKind) {
): GeomProvider {
return GeomProviderBuilder(
GeomKind.LIVE_MAP,
- AestheticsDefaults.livemap(options.displayMode, options.scaled),
+ AestheticsDefaults.livemap(options.displayMode),
LiveMapGeom.HANDLES_GROUPS,
myGeomSupplier = { LiveMapGeom(options.displayMode) }
).build()
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/DataProcessing.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/DataProcessing.kt
index 32fa9e8265d..238667674db 100644
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/DataProcessing.kt
+++ b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/DataProcessing.kt
@@ -304,8 +304,8 @@ object DataProcessing {
return inverseTransformedStatSeries
}
- internal fun computeGroups(data: DataFrame, bindings: List, groupingVar: Variable?): (Int) -> Int {
- val groupingVariables = getGroupingVariables(data, bindings, groupingVar)
+ internal fun computeGroups(data: DataFrame, bindings: List, groupingVar: Variable?, pathIdVar: Variable?): (Int) -> Int {
+ val groupingVariables = getGroupingVariables(data, bindings, groupingVar) + listOfNotNull(pathIdVar)
var currentGroups: List? = null
if (groupingVar != null) {
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/GroupingContext.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/GroupingContext.kt
index ecea85ae4f3..344e5303128 100644
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/GroupingContext.kt
+++ b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/GroupingContext.kt
@@ -15,11 +15,13 @@ class GroupingContext(
private val myData: DataFrame,
bindings: List,
groupingVarName: String?,
+ pathIdVarName: String?,
private val myExpectMultiple: Boolean
) {
- private val myBindings: List
- internal val optionalGroupingVar: Variable?
+ private val myBindings: List = ArrayList(bindings)
+ internal val optionalGroupingVar: Variable? = findOptionalVariable(myData, groupingVarName)
+ private val pathIdVar: Variable? = findOptionalVariable(myData, pathIdVarName)
private var myGroupSizeList: List? = null
private var myGroupMapper: ((Int) -> Int)? = null
@@ -33,11 +35,6 @@ class GroupingContext(
myGroupMapper!!(index)
}
- init {
- myBindings = ArrayList(bindings)
- optionalGroupingVar = findOptionalVariable(myData, groupingVarName)
- }
-
private fun computeGroups(): (Int) -> Int {
if (myData.has(Stats.GROUP)) {
val list = myData.getNumeric(Stats.GROUP)
@@ -54,7 +51,8 @@ class GroupingContext(
return DataProcessing.computeGroups(
myData,
myBindings,
- optionalGroupingVar
+ optionalGroupingVar,
+ pathIdVar
)
}
return GroupUtil.SINGLE_GROUP
@@ -62,7 +60,7 @@ class GroupingContext(
companion object {
internal fun withOrderedGroups(data: DataFrame, groupSizeList: List): GroupingContext {
- val groupingContext = GroupingContext(data, emptyList(), null, false)
+ val groupingContext = GroupingContext(data, emptyList(), null, null, false)
groupingContext.myGroupSizeList = ArrayList(groupSizeList)
return groupingContext
}
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/map/GeoPositionField.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/map/GeoPositionField.kt
deleted file mode 100644
index ca1c5349351..00000000000
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/map/GeoPositionField.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.builder.map
-
-
-// column names in data-frames provided by geocoding
-object GeoPositionField {
-
- // fixed columns in 'boundaries' of 'centroids' data frames
- const val POINT_X = "lon"
- const val POINT_X1 = "longitude"
- const val POINT_X2 = "long"
- const val POINT_Y = "lat"
- const val POINT_Y1 = "latitude"
-
- // fixed columns in 'limits'
- const val RECT_XMIN = "lonmin"
- const val RECT_XMAX = "lonmax"
- const val RECT_YMIN = "latmin"
- const val RECT_YMAX = "latmax"
-}
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultMapperProvider.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultMapperProvider.kt
index e509e7bc51b..0db96aa7431 100644
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultMapperProvider.kt
+++ b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultMapperProvider.kt
@@ -20,12 +20,13 @@ import jetbrains.datalore.plot.base.Aes.Companion.INTERCEPT
import jetbrains.datalore.plot.base.Aes.Companion.LABEL
import jetbrains.datalore.plot.base.Aes.Companion.LINETYPE
import jetbrains.datalore.plot.base.Aes.Companion.LOWER
-import jetbrains.datalore.plot.base.Aes.Companion.MAP_ID
import jetbrains.datalore.plot.base.Aes.Companion.MIDDLE
import jetbrains.datalore.plot.base.Aes.Companion.SHAPE
import jetbrains.datalore.plot.base.Aes.Companion.SIZE
import jetbrains.datalore.plot.base.Aes.Companion.SLOPE
import jetbrains.datalore.plot.base.Aes.Companion.SPEED
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_X
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_Y
import jetbrains.datalore.plot.base.Aes.Companion.UPPER
import jetbrains.datalore.plot.base.Aes.Companion.VJUST
import jetbrains.datalore.plot.base.Aes.Companion.WEIGHT
@@ -74,17 +75,13 @@ object DefaultMapperProvider {
init {
for (aes in Aes.allPositional()) {
- put(aes,
- NUMERIC_UNDEFINED
- )
+ put(aes, NUMERIC_UNDEFINED)
}
this.put(X, NUMERIC_IDENTITY)
this.put(Y, NUMERIC_IDENTITY)
- this.put(Z,
- NUMERIC_IDENTITY
- )
+ this.put(Z, NUMERIC_IDENTITY)
this.put(YMIN, NUMERIC_IDENTITY)
this.put(YMAX, NUMERIC_IDENTITY)
this.put(COLOR, createColor())
@@ -94,15 +91,9 @@ object DefaultMapperProvider {
this.put(LINETYPE, createWithDiscreteOutput(LineTypeMapper.allLineTypes(), LineTypeMapper.NA_VALUE))
this.put(SIZE, SizeMapperProvider.DEFAULT)
- this.put(WIDTH,
- NUMERIC_IDENTITY
- )
- this.put(HEIGHT,
- NUMERIC_IDENTITY
- )
- this.put(WEIGHT,
- NUMERIC_IDENTITY
- )
+ this.put(WIDTH, NUMERIC_IDENTITY)
+ this.put(HEIGHT, NUMERIC_IDENTITY)
+ this.put(WEIGHT, NUMERIC_IDENTITY)
this.put(INTERCEPT, NUMERIC_IDENTITY)
this.put(SLOPE, NUMERIC_IDENTITY)
this.put(XINTERCEPT, NUMERIC_IDENTITY)
@@ -111,15 +102,10 @@ object DefaultMapperProvider {
this.put(MIDDLE, NUMERIC_IDENTITY)
this.put(UPPER, NUMERIC_IDENTITY)
- this.put(MAP_ID, createObjectIdentityDiscrete(MAP_ID))
this.put(FRAME, createStringIdentity(FRAME))
- this.put(SPEED,
- NUMERIC_IDENTITY
- )
- this.put(FLOW,
- NUMERIC_IDENTITY
- )
+ this.put(SPEED, NUMERIC_IDENTITY)
+ this.put(FLOW, NUMERIC_IDENTITY)
this.put(XMIN, NUMERIC_IDENTITY)
this.put(XMAX, NUMERIC_IDENTITY)
@@ -135,9 +121,10 @@ object DefaultMapperProvider {
// text vertical justification (numbers [0..1] or predefined strings, not positional)
this.put(VJUST, createObjectIdentityDiscrete(VJUST))
- this.put(ANGLE,
- NUMERIC_IDENTITY
- )
+ this.put(ANGLE, NUMERIC_IDENTITY)
+
+ this.put(SYM_X, NUMERIC_IDENTITY)
+ this.put(SYM_Y, NUMERIC_IDENTITY)
}
internal operator fun get(aes: Aes): MapperProvider {
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultNaValue.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultNaValue.kt
index 1e93843759e..e1fe60ae2a1 100644
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultNaValue.kt
+++ b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/scale/DefaultNaValue.kt
@@ -23,12 +23,13 @@ import jetbrains.datalore.plot.base.Aes.Companion.INTERCEPT
import jetbrains.datalore.plot.base.Aes.Companion.LABEL
import jetbrains.datalore.plot.base.Aes.Companion.LINETYPE
import jetbrains.datalore.plot.base.Aes.Companion.LOWER
-import jetbrains.datalore.plot.base.Aes.Companion.MAP_ID
import jetbrains.datalore.plot.base.Aes.Companion.MIDDLE
import jetbrains.datalore.plot.base.Aes.Companion.SHAPE
import jetbrains.datalore.plot.base.Aes.Companion.SIZE
import jetbrains.datalore.plot.base.Aes.Companion.SLOPE
import jetbrains.datalore.plot.base.Aes.Companion.SPEED
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_X
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_Y
import jetbrains.datalore.plot.base.Aes.Companion.UPPER
import jetbrains.datalore.plot.base.Aes.Companion.VJUST
import jetbrains.datalore.plot.base.Aes.Companion.WEIGHT
@@ -73,7 +74,6 @@ object DefaultNaValue {
VALUE_MAP.put(LOWER, 0.0)
VALUE_MAP.put(MIDDLE, 0.0)
VALUE_MAP.put(UPPER, 0.0)
- VALUE_MAP.put(MAP_ID, "empty map_id")
VALUE_MAP.put(FRAME, "empty frame")
VALUE_MAP.put(SPEED, 10.0)
VALUE_MAP.put(FLOW, 0.1)
@@ -87,6 +87,8 @@ object DefaultNaValue {
VALUE_MAP.put(HJUST, 0.5) // 'middle'
VALUE_MAP.put(VJUST, 0.5) // 'middle'
VALUE_MAP.put(ANGLE, 0.0)
+ VALUE_MAP.put(SYM_X, 0.0)
+ VALUE_MAP.put(SYM_Y, 0.0)
}
/**
diff --git a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/tooltip/MappedAes.kt b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/tooltip/MappedAes.kt
index ad476f55dcc..902a8fb337c 100644
--- a/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/tooltip/MappedAes.kt
+++ b/plot-builder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/tooltip/MappedAes.kt
@@ -10,7 +10,6 @@ import jetbrains.datalore.plot.base.interact.DataContext
import jetbrains.datalore.plot.base.interact.MappedDataAccess
import jetbrains.datalore.plot.base.interact.ValueSource
import jetbrains.datalore.plot.base.interact.ValueSource.DataPoint
-import jetbrains.datalore.plot.builder.map.GeoPositionField
open class MappedAes(
protected val aes: Aes<*>,
@@ -28,7 +27,7 @@ open class MappedAes(
val mappedDataPoint = getMappedDataPoint(index) ?: return null
val label2value: Pair = when {
- isAxis && !isAxisTooltipAllowed(mappedDataPoint) -> null
+ isAxis && !mappedDataPoint.isContinuous -> null
isAxis -> "" to mappedDataPoint.value
else -> createLabeledValue(
index = index,
@@ -62,13 +61,6 @@ open class MappedAes(
)
}
- private fun isAxisTooltipAllowed(sourceDataPoint: DataPoint): Boolean {
- return when {
- MAP_COORDINATE_NAMES.contains(sourceDataPoint.label) -> false
- else -> sourceDataPoint.isContinuous
- }
- }
-
private fun createLabeledValue(
index: Int,
value: String,
@@ -85,7 +77,6 @@ open class MappedAes(
}
fun shortText() = "" to value
-
fun fullText() = label to value
return when {
@@ -101,13 +92,6 @@ open class MappedAes(
}
companion object {
- private val MAP_COORDINATE_NAMES = setOf(
- GeoPositionField.POINT_X,
- GeoPositionField.POINT_X1,
- GeoPositionField.POINT_Y,
- GeoPositionField.POINT_Y1
- )
-
fun createMappedAxis(aes: Aes<*>, dataContext: DataContext): ValueSource =
MappedAes(aes, isOutlier = true, isAxis = true).also { it.setDataPointProvider(dataContext) }
diff --git a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecAxisTooltipTest.kt b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecAxisTooltipTest.kt
index 46cf28d83dd..d3499f13056 100644
--- a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecAxisTooltipTest.kt
+++ b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecAxisTooltipTest.kt
@@ -65,19 +65,4 @@ class TooltipSpecAxisTooltipTest : jetbrains.datalore.plot.builder.interact.Tool
assertLines(0, fillMapping.shortTooltipText())
assertLines(1, yMapping.shortTooltipText())
}
-
- @Test
- fun mapVarsShouldNotBeAddedToAxisTooltip() {
- val namesToIgnore = listOf("lon", "longitude", "lat", "latitude")
-
- for (name in namesToIgnore) {
- val var1 = variable().name(name).value("0").isContinuous(true)
-
- addMappedData(var1.mapping(Aes.X))
-
- buildTooltipSpecs()
-
- assertTooltipsCount(0)
- }
- }
}
diff --git a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecFactorySkippedAesTest.kt b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecFactorySkippedAesTest.kt
index 0ccdee463d7..c345460d534 100644
--- a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecFactorySkippedAesTest.kt
+++ b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/interact/TooltipSpecFactorySkippedAesTest.kt
@@ -34,15 +34,4 @@ class TooltipSpecFactorySkippedAesTest : jetbrains.datalore.plot.builder.interac
assertTooltipsCount(1)
assertLines(0, widthMapping.longTooltipText())
}
-
- @Test
- fun shouldNotSkipMapIdMappingVar_whenOtherMappingWithSameVarExists() {
- val commonLabel = "foo"
- addMappedData(variable().name(commonLabel).mapping(Aes.MAP_ID))
- addMappedData(variable().name(commonLabel).mapping(Aes.FILL))
-
- buildTooltipSpecs()
-
- assertTooltipsCount(1)
- }
}
diff --git a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/DefaultMapperProviderTest.kt b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/DefaultMapperProviderTest.kt
index d9c1755d29a..7477fdc33b8 100644
--- a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/DefaultMapperProviderTest.kt
+++ b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/DefaultMapperProviderTest.kt
@@ -6,27 +6,10 @@
package jetbrains.datalore.plot.builder.scale
import jetbrains.datalore.plot.base.Aes
-import jetbrains.datalore.plot.base.data.DataFrameUtil
import kotlin.test.Test
-import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DefaultMapperProviderTest {
- @Test
- fun mapId() {
- val serie = listOf("a", "a", "b", "c")
- val d = mapOf("var" to serie)
- val df = DataFrameUtil.fromMap(d)
-
- val variable = df.variables().iterator().next()
-
- val mapperProvider = DefaultMapperProvider[Aes.MAP_ID]
- val mapper = mapperProvider.createDiscreteMapper(df, variable)
-
- val mapped = arrayOf(0.0, 0.0, 1.0, 2.0).map { v -> mapper.apply(v) as String }
- assertEquals(serie, mapped)
- }
-
@Test
fun everyAesHasMapperProvider() {
for (aes in Aes.values()) {
diff --git a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/ScaleProviderHelperTest.kt b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/ScaleProviderHelperTest.kt
index 9d02ba89c6e..5677d9a153b 100644
--- a/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/ScaleProviderHelperTest.kt
+++ b/plot-builder-portable/src/jvmTest/kotlin/plot/builder/scale/ScaleProviderHelperTest.kt
@@ -7,7 +7,6 @@ package jetbrains.datalore.plot.builder.scale
import jetbrains.datalore.plot.base.Aes
import jetbrains.datalore.plot.base.DataFrame
-import org.junit.Ignore
import kotlin.test.Test
class ScaleProviderHelperTest {
@@ -19,6 +18,6 @@ class ScaleProviderHelperTest {
.put(region, listOf("Europe", "Asia", null, "Australia"))
.build()
- ScaleProviderHelper.createDefault(Aes.MAP_ID).createScale(df, region)
+ ScaleProviderHelper.createDefault(Aes.HJUST).createScale(df, region)
}
}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/GeoConfig.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/GeoConfig.kt
new file mode 100644
index 00000000000..0dfde4caef9
--- /dev/null
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/GeoConfig.kt
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2020. 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.config
+
+import jetbrains.datalore.base.spatial.*
+import jetbrains.datalore.base.typedGeometry.*
+import jetbrains.datalore.plot.base.Aes
+import jetbrains.datalore.plot.base.DataFrame
+import jetbrains.datalore.plot.base.DataFrame.Variable
+import jetbrains.datalore.plot.base.GeomKind
+import jetbrains.datalore.plot.base.GeomKind.*
+import jetbrains.datalore.plot.base.data.DataFrameUtil.findVariableOrFail
+import jetbrains.datalore.plot.base.data.DataFrameUtil.variables
+import jetbrains.datalore.plot.config.ConfigUtil.createAesMapping
+import jetbrains.datalore.plot.config.ConfigUtil.createDataFrame
+import jetbrains.datalore.plot.config.ConfigUtil.rightJoin
+import jetbrains.datalore.plot.config.CoordinatesCollector.*
+import jetbrains.datalore.plot.config.Option.Geom.Choropleth.GEO_POSITIONS
+import jetbrains.datalore.plot.config.Option.Layer.MAP_JOIN
+import jetbrains.datalore.plot.config.Option.Meta.DATA_META
+import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame.GDF
+import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame.GEOMETRY
+import jetbrains.datalore.plot.config.Option.Meta.MAP_DATA_META
+import jetbrains.datalore.plot.config.Option.PlotBase.DATA
+
+class GeoConfig(
+ geomKind: GeomKind,
+ data: DataFrame,
+ layerOptions: Map<*, *>,
+ mappingOptions: Map<*, *>
+) {
+ val dataAndCoordinates: DataFrame
+ val mappings: Map, Variable>
+
+ init {
+ fun getGeoJson(gdfLocation: String, keys: Collection): Map {
+ val geoColumn: String
+ val geoDataFrame: Map
+ when(gdfLocation) {
+ GEO_POSITIONS -> {
+ geoDataFrame = layerOptions.getMap(GEO_POSITIONS) ?: error("require 'map' parameter")
+ geoColumn = layerOptions.getString(MAP_DATA_META, GDF, GEOMETRY) ?: error("Geometry column not set")
+ }
+ DATA -> {
+ geoDataFrame = layerOptions.getMap(DATA) ?: error("require 'data' parameter")
+ geoColumn = layerOptions.getString(DATA_META, GDF, GEOMETRY) ?: error("Geometry column not set")
+ }
+ else -> error("Unknown gdf location: $gdfLocation")
+ }
+ val geoJsons = geoDataFrame.getList(geoColumn)?.map { it as String } ?: error("$geoColumn not found in $gdfLocation")
+ return keys.zip(geoJsons).toMap()
+ }
+
+ val dataKeyColumn: String
+ val geoKeyColumn: String
+ val geometries: Map
+ val dataFrame: DataFrame
+
+ when {
+ // (aes(color='cyl'), data=data, map=gdf) - how to join without `map_join`?
+ with(layerOptions) { has(MAP_DATA_META, GDF, GEOMETRY) && !has(MAP_JOIN) && !data.isEmpty && mappingOptions.isNotEmpty() } -> {
+ require(layerOptions.has(GEO_POSITIONS)) { "'map' parameter is mandatory with MAP_DATA_META" }
+ error(MAP_JOIN_REQUIRED_MESSAGE)
+ }
+
+ // (data=data, map=gdf, map_join=('id', 'city'))
+ with(layerOptions) { has(MAP_DATA_META, GDF, GEOMETRY) && has(MAP_JOIN) } -> {
+ require(layerOptions.has(GEO_POSITIONS)) { "'map' parameter is mandatory with MAP_DATA_META" }
+
+ dataFrame = data
+ val mapJoin = layerOptions.getList(MAP_JOIN) ?: error("require map_join parameter")
+ geoKeyColumn = mapJoin[1] as String
+ dataKeyColumn = mapJoin[0] as String
+ val mapKeys = layerOptions
+ .getMap(GEO_POSITIONS)
+ ?.getList(geoKeyColumn)
+ ?.requireNoNulls()
+ ?.toSet()
+ ?: error("'$geoKeyColumn' is not found in map")
+
+ val dataKeys = dataFrame.getOrFail(dataKeyColumn).requireNoNulls().toSet()
+
+ // All data keys should be present in map
+ (dataKeys - mapKeys).firstOrNull() ?.let { error("'$it' not found in map") }
+
+ geometries = getGeoJson(gdfLocation = GEO_POSITIONS, keys = mapKeys)
+ .filterKeys { it in dataKeys } // if not in data rightJoin adds null values and cause NPE when compute groups
+ }
+
+ // (map=gdf) - simple geometry
+ with(layerOptions) { has(MAP_DATA_META, GDF, GEOMETRY) && !has(MAP_JOIN) } -> {
+ require(layerOptions.has(GEO_POSITIONS)) { "'map' parameter is mandatory with MAP_DATA_META" }
+ dataKeyColumn = AUTO_ID
+ geoKeyColumn = AUTO_ID
+ geometries = run {
+ val indicies = layerOptions.getMap(GEO_POSITIONS)?.indicies?.map(Int::toString) ?: emptyList()
+ getGeoJson(gdfLocation = GEO_POSITIONS, keys = indicies)
+ }
+
+ dataFrame = DataFrame.Builder(data).put(Variable(dataKeyColumn), geometries.keys.toList()).build()
+ }
+
+ // (data=gdf)
+ with(layerOptions) { has(DATA_META, GDF, GEOMETRY) && !has(GEO_POSITIONS) && !has(MAP_JOIN) } -> {
+ require(layerOptions.has(DATA)) { "'data' parameter is mandatory with DATA_META" }
+ dataKeyColumn = AUTO_ID
+ geoKeyColumn = "__geo_id__"
+ geometries = run {
+ val indicies = layerOptions.getMap(DATA)?.indicies?.map(Int::toString) ?: emptyList()
+ getGeoJson(gdfLocation = DATA, keys = indicies)
+ }
+
+ dataFrame = DataFrame.Builder(data).put(Variable(dataKeyColumn), geometries.keys.toList()).build()
+ }
+
+ else -> error("GeoDataFrame not found in data or map")
+ }
+
+ val coordinatesCollector = when(geomKind) {
+ MAP, POLYGON -> BoundaryCoordinatesCollector()
+ POINT, TEXT -> PointCoordinatesCollector()
+ RECT -> BboxCoordinatesCollector()
+ PATH -> PathCoordinatesCollector()
+ else -> error("Unsupported geom: $geomKind")
+ }
+
+ val geoFrame = coordinatesCollector
+ .append(geometries)
+ .setKeyColumn(geoKeyColumn)
+ .buildCoordinatesMap()
+ .let(::createDataFrame)
+
+ dataAndCoordinates = rightJoin(
+ left = dataFrame,
+ leftKey = dataKeyColumn,
+ right = geoFrame,
+ rightKey = geoKeyColumn
+ )
+
+ val coordinatesAutoMapping = coordinatesCollector.mappings
+ .filterValues { coordName -> coordName in variables(dataAndCoordinates) }
+ .map { (aes, coordName) -> aes to variables(dataAndCoordinates).getValue(coordName) }
+ .toMap()
+ mappings = createAesMapping(dataAndCoordinates, mappingOptions) + coordinatesAutoMapping
+ }
+
+ companion object {
+ const val MAP_JOIN_REQUIRED_MESSAGE = "map_join is required when both data and map parameters used"
+
+ fun isApplicable(layerOptions: Map<*, *>): Boolean {
+ return layerOptions.has(MAP_DATA_META, GDF, GEOMETRY) ||
+ layerOptions.has(DATA_META, GDF, GEOMETRY)
+ }
+ }
+}
+
+const val AUTO_ID = "__id__"
+const val POINT_X = "__x__"
+const val POINT_Y = "__y__"
+const val RECT_XMIN = "__xmin__"
+const val RECT_YMIN = "__ymin__"
+const val RECT_XMAX = "__xmax__"
+const val RECT_YMAX = "__ymax__"
+
+internal abstract class CoordinatesCollector(
+ val mappings: Map, String>
+) {
+ private lateinit var keyColumnName: String
+ private val groupKeys = mutableListOf()
+ private val groupLengths = mutableListOf()
+ protected val coordinates: Map> = mappings.values.associateBy({ it }) { mutableListOf() }
+ protected abstract val geoJsonConsumer: SimpleFeature.Consumer
+ protected abstract val supportedFeatures: List
+
+ fun append(rows: Map): CoordinatesCollector {
+ rows.forEach { (key, geoJson) ->
+ val oldRowCount = coordinates.rowCount
+ GeoJson.parse(geoJson, geoJsonConsumer)
+ groupLengths += coordinates.rowCount - oldRowCount
+ groupKeys += key
+ }
+
+ if (coordinates.rowCount == 0) {
+ error("Geometries are empty or no matching types. Expected: " + supportedFeatures)
+ }
+
+ return this
+ }
+
+ fun setKeyColumn(columnName: String): CoordinatesCollector {
+ keyColumnName = columnName
+ return this
+ }
+
+ fun buildCoordinatesMap(): Map> {
+ require(groupLengths.size == groupKeys.size) { "Groups and ids should have same size" }
+
+ // (['a', 'b'], [2, 3]) => ['a', 'a', 'b', 'b', 'b']
+ fun copies(values: Collection, count: Collection) =
+ values.asSequence().zip(count.asSequence())
+ .fold(mutableListOf()) { acc, (value, count) -> repeat(count) { acc += value }; acc }
+
+ return coordinates + (keyColumnName to copies(groupKeys, groupLengths))
+ }
+
+ internal fun defaultConsumer(config: SimpleFeature.Consumer.() -> Unit) =
+ SimpleFeature.Consumer(
+ onPoint = {},
+ onMultiPoint = {},
+ onLineString = {},
+ onMultiLineString = {},
+ onPolygon = {},
+ onMultiPolygon = {}
+ ).apply(config)
+
+ private val > Map.rowCount get() = values.firstOrNull()?.size ?: 0
+
+ class PointCoordinatesCollector : CoordinatesCollector(POINT_COLUMNS) {
+ override val supportedFeatures = listOf("Point, MultiPoint")
+ override val geoJsonConsumer: SimpleFeature.Consumer = defaultConsumer {
+ onPoint = { p -> coordinates.append(p) }
+ onMultiPoint = { it.forEach { p -> coordinates.append(p) } }
+ }
+ }
+
+ class PathCoordinatesCollector : CoordinatesCollector(POINT_COLUMNS) {
+ override val supportedFeatures = listOf("LineString, MultiLineString")
+ override val geoJsonConsumer: SimpleFeature.Consumer = defaultConsumer {
+ onLineString = { it.forEach { p -> coordinates.append(p) } }
+ onMultiLineString = { it.asSequence().flatten().forEach { p -> coordinates.append(p) } }
+ }
+ }
+
+ class BoundaryCoordinatesCollector : CoordinatesCollector(POINT_COLUMNS) {
+ override val supportedFeatures = listOf("Polygon, MultiPolygon")
+ override val geoJsonConsumer: SimpleFeature.Consumer = defaultConsumer {
+ onPolygon = { it.asSequence().flatten().forEach { p -> coordinates.append(p) } }
+ onMultiPolygon = { it.asSequence().flatten().flatten().forEach { p -> coordinates.append(p) } }
+ }
+ }
+
+ class BboxCoordinatesCollector : CoordinatesCollector(RECT_MAPPINGS) {
+ override val supportedFeatures = listOf("MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon")
+ override val geoJsonConsumer: SimpleFeature.Consumer = defaultConsumer {
+ fun insert(bboxes: List>) =
+ bboxes
+ .run(BBOX_CALCULATOR::union)
+ .run(::convertToGeoRectangle)
+ .run(GeoRectangle::splitByAntiMeridian)
+ .forEach{ r -> coordinates.append(r) }
+
+ fun insert(bbox: Rect) = insert(listOf(bbox))
+
+ onMultiPoint = { insert(it.boundingBox()) }
+ onLineString = { insert(it.boundingBox()) }
+ onMultiLineString = { insert(it.flatten().boundingBox()) }
+ onPolygon = { insert(it.limit()) }
+ onMultiPolygon = { insert(it.limit()) }
+ }
+ }
+
+ companion object {
+
+ val POINT_COLUMNS = mapOf, String>(
+ Aes.X to POINT_X,
+ Aes.Y to POINT_Y
+ )
+
+ val RECT_MAPPINGS = mapOf, String>(
+ Aes.XMIN to RECT_XMIN,
+ Aes.YMIN to RECT_YMIN,
+ Aes.XMAX to RECT_XMAX,
+ Aes.YMAX to RECT_YMAX
+ )
+
+ internal fun Map>.append(p: Vec) {
+ append(POINT_X, p.x)
+ append(POINT_Y, p.y)
+ }
+
+ internal fun Map>.append(rect: Rect) {
+ append(RECT_XMIN, rect.left)
+ append(RECT_XMAX, rect.right)
+ append(RECT_YMIN, rect.top)
+ append(RECT_YMAX, rect.bottom)
+ }
+
+ private fun Map>.append(key: String, value: Double) {
+ get(key)?.add(value) ?: error("$key is not found")
+ }
+ }
+}
+
+
+fun Map<*, *>.dataJoinVariable() = getList(MAP_JOIN)?.get(0) as? String
+private fun DataFrame.getOrFail(varName: String) = this.get(findVariableOrFail(this, varName))
+private val Map.indicies get() = (values.firstOrNull() as? List<*>)?.indices
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/GeoPositionsDataUtil.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/GeoPositionsDataUtil.kt
deleted file mode 100644
index 577b67fe067..00000000000
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/GeoPositionsDataUtil.kt
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.config
-
-import jetbrains.datalore.base.gcommon.base.Preconditions.checkState
-import jetbrains.datalore.base.values.Pair
-import jetbrains.datalore.plot.base.Aes
-import jetbrains.datalore.plot.base.DataFrame
-import jetbrains.datalore.plot.base.DataFrame.Variable
-import jetbrains.datalore.plot.base.GeomKind
-import jetbrains.datalore.plot.base.data.DataFrameUtil
-import jetbrains.datalore.plot.builder.map.GeoPositionField
-import jetbrains.datalore.plot.config.Option.Geom.Choropleth
-import jetbrains.datalore.plot.config.Option.Meta.MapJoin
-
-object GeoPositionsDataUtil {
- // Provided by regions object
- const val MAP_REGION_COLUMN = "region"
-
- const val MAP_OSM_ID_COLUMN = "__geoid__"
-
- private val GEOMS_SUPPORT = mapOf(
- GeomKind.MAP to GeoDataSupport.boundary(),
- GeomKind.POLYGON to GeoDataSupport.boundary(),
- GeomKind.POINT to GeoDataSupport.point(),
- GeomKind.RECT to GeoDataSupport.bbox(),
- GeomKind.PATH to GeoDataSupport.path(),
- GeomKind.TEXT to GeoDataSupport.point()
- )
-
- fun isGeomSupported(geomKind: GeomKind): Boolean {
- return GEOMS_SUPPORT.containsKey(geomKind)
- }
-
- fun getGeoDataKind(geomKind: GeomKind): GeoDataKind {
- return GEOMS_SUPPORT[geomKind]!!.geoDataKind
- }
-
- internal fun hasGeoPositionsData(layerConfig: LayerConfig): Boolean {
- return layerConfig.has(Choropleth.GEO_POSITIONS)
- }
-
- internal fun getGeoPositionsData(layerConfig: LayerConfig): DataFrame {
- val mapOptions = layerConfig.getMap(Choropleth.GEO_POSITIONS)
- return ConfigUtil.createDataFrame(mapOptions)
- }
-
- internal fun initDataAndMappingForGeoPositions(
- geomKind: GeomKind, layerData: DataFrame, mapOptions: DataFrame, mappingOptions: Map<*, *>): Pair, Variable>> {
- @Suppress("NAME_SHADOWING")
- var layerData = layerData
-
- val leftMapId = mappingOptions[Option.Mapping.MAP_ID]
- checkState(leftMapId != null || mappingOptions.isEmpty(), "'map_join' parameter is required if 'map' parameter is used")
-
- return when {
- leftMapId != null -> {
- val rightMapId = getGeoPositionsIdVar(mapOptions).name
- layerData = ConfigUtil.rightJoin(
- layerData,
- leftMapId.toString(),
- mapOptions,
- rightMapId
- )
-
- val aesMapping = HashMap(
- ConfigUtil.createAesMapping(
- layerData,
- mappingOptions
- )
- )
- aesMapping.putAll(
- generateMappings(
- geomKind,
- layerData
- )
- )
- Pair(layerData, aesMapping)
- }
- else -> // just show a blank map
- Pair(mapOptions,
- generateMappings(geomKind, mapOptions)
- )
- }
- }
-
- private fun generateMappings(geomKind: GeomKind, layerData: DataFrame): Map, Variable> {
- return if (isGeomSupported(geomKind)) {
- GEOMS_SUPPORT[geomKind]!!.generateMapping(layerData)
- } else {
- emptyMap()
- }
- }
-
- private fun getGeoPositionsIdVar(mapOptions: DataFrame): Variable {
- val variable = findFirstVariable(mapOptions, listOf(MapJoin.ID, MAP_REGION_COLUMN))
- if (variable != null) {
- return variable
- }
-
- throw IllegalArgumentException(
- geoPositionsColumnNotFoundError(
- "region id",
- listOf(MapJoin.ID, MAP_REGION_COLUMN)
- )
- )
- }
-
- private fun findMapping(aes: Aes<*>, names: List, dataFrame: DataFrame): Map, Variable> {
- val variable = findFirstVariable(dataFrame, names)
- ?: throw IllegalArgumentException(
- geoPositionsColumnNotFoundError(
- aes.name + "-column",
- names
- )
- )
- return mapOf(aes to variable)
- }
-
- private fun findFirstVariable(data: DataFrame, names: Iterable): Variable? {
- val variableMap = DataFrameUtil.variables(data)
- for (name in names) {
- if (variableMap.containsKey(name)) {
- return variableMap[name]
- }
- }
- return null
- }
-
- private fun geoPositionsColumnNotFoundError(what: String, names: List): String {
- return "Can't draw map: " + what + " not found. Geo position data must contain column " +
- names.joinToString(" or ") { s -> "'$s'" }
- }
-
- enum class GeoDataKind {
- POINT,
- PATH,
- BBOX,
- BOUNDARY
- }
-
- internal class GeoDataSupport(val geoDataKind: GeoDataKind, private val mappingsGenerator: (DataFrame) -> Map, Variable>) {
-
- fun generateMapping(df: DataFrame): Map, Variable> {
- return mappingsGenerator(df)
- }
-
- companion object {
- fun boundary(): GeoDataSupport {
- return GeoDataSupport(GeoDataKind.BOUNDARY, ::createPointMapping)
- }
-
- fun point(): GeoDataSupport {
- return GeoDataSupport(GeoDataKind.POINT, ::createPointMapping)
- }
-
- fun path(): GeoDataSupport {
- return GeoDataSupport(GeoDataKind.PATH, ::createPointMapping)
- }
-
- fun bbox(): GeoDataSupport {
- return GeoDataSupport(GeoDataKind.BBOX, ::createRectMapping)
- }
-
- private fun createRectMapping(dataFrame: DataFrame): Map, Variable> {
- val mapping = HashMap, Variable>()
- mapping.putAll(
- findMapping(
- Aes.XMIN,
- listOf(GeoPositionField.RECT_XMIN),
- dataFrame
- )
- )
- mapping.putAll(
- findMapping(
- Aes.XMAX,
- listOf(GeoPositionField.RECT_XMAX),
- dataFrame
- )
- )
- mapping.putAll(
- findMapping(
- Aes.YMIN,
- listOf(GeoPositionField.RECT_YMIN),
- dataFrame
- )
- )
- mapping.putAll(
- findMapping(
- Aes.YMAX,
- listOf(GeoPositionField.RECT_YMAX),
- dataFrame
- )
- )
- return mapping
- }
-
- private fun createPointMapping(dataFrame: DataFrame): Map, Variable> {
- val mapping = HashMap, Variable>()
- mapping.putAll(
- findMapping(
- Aes.X,
- listOf(
- GeoPositionField.POINT_X,
- "x",
- GeoPositionField.POINT_X2
- ),
- dataFrame
- )
- )
- mapping.putAll(
- findMapping(
- Aes.Y,
- listOf(GeoPositionField.POINT_Y, "y"),
- dataFrame
- )
- )
-
- return mapping
- }
- }
- }
-}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LayerConfig.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LayerConfig.kt
index e7ec3fa5e16..13f5f53ccff 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LayerConfig.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LayerConfig.kt
@@ -18,7 +18,9 @@ import jetbrains.datalore.plot.builder.assemble.PosProvider
import jetbrains.datalore.plot.builder.assemble.TypedScaleProviderMap
import jetbrains.datalore.plot.builder.sampling.Sampling
import jetbrains.datalore.plot.builder.tooltip.TooltipLineSpecification
+import jetbrains.datalore.plot.config.ConfigUtil.createAesMapping
import jetbrains.datalore.plot.config.DataMetaUtil.createDataFrame
+import jetbrains.datalore.plot.config.Option.Geom.Choropleth.GEO_POSITIONS
import jetbrains.datalore.plot.config.Option.Layer.GEOM
import jetbrains.datalore.plot.config.Option.Layer.SHOW_LEGEND
import jetbrains.datalore.plot.config.Option.Layer.STAT
@@ -96,28 +98,23 @@ class LayerConfig(
var aesMappings: Map, DataFrame.Variable>?
- if (GeoPositionsDataUtil.hasGeoPositionsData(this) && myClientSide) {
- // join dataset and geo-positions data
- val dataAndMapping = GeoPositionsDataUtil.initDataAndMappingForGeoPositions(
+ if (myClientSide && GeoConfig.isApplicable(layerOptions)) {
+ val geoConfig = GeoConfig(
geomProto.geomKind,
combinedData,
- GeoPositionsDataUtil.getGeoPositionsData(this),
+ layerOptions,
combinedMappings
)
- combinedData = dataAndMapping.first
- aesMappings = dataAndMapping.second
+ combinedData = geoConfig.dataAndCoordinates
+ aesMappings = geoConfig.mappings
+
} else {
- aesMappings = ConfigUtil.createAesMapping(combinedData, combinedMappings)
+ aesMappings = createAesMapping(combinedData, combinedMappings)
}
// exclude constant aes from mapping
- val constants = LayerConfigUtil.initConstants(this)
- if (constants.isNotEmpty()) {
- aesMappings = HashMap(aesMappings)
- for (aes in constants.keys) {
- aesMappings.remove(aes)
- }
- }
+ constantsMap = LayerConfigUtil.initConstants(this)
+ aesMappings = aesMappings - constantsMap.keys
// grouping
explicitGroupingVarName = initGroupingVarName(combinedData, combinedMappings)
@@ -128,7 +125,6 @@ class LayerConfig(
this,
geomProto.preferredPositionAdjustments(this)
)
- constantsMap = constants
val consumedAesSet = HashSet(geomProto.renders())
if (!myClientSide) {
@@ -166,7 +162,7 @@ class LayerConfig(
else
null
- if (fieldName == null && GeoPositionsDataUtil.hasGeoPositionsData(this)) {
+ if (fieldName == null && has(GEO_POSITIONS)) {
// 'default' group is important for 'geom_map'
val groupVar = variables(data)["group"]
if (groupVar != null) {
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LiveMapOptionsParser.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LiveMapOptionsParser.kt
index 9e0a7f45588..576dcc488c3 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LiveMapOptionsParser.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/LiveMapOptionsParser.kt
@@ -34,7 +34,7 @@ class LiveMapOptionsParser {
location = opts.get(LiveMap.LOCATION),
stroke = opts.getDouble(LiveMap.STROKE),
interactive = opts.getBoolean(LiveMap.INTERACTIVE, true),
- displayMode = opts.getString(LiveMap.DISPLAY_MODE)?.let(::parseDisplayMode) ?: DisplayMode.POLYGON,
+ displayMode = opts.getString(LiveMap.DISPLAY_MODE)?.let(::parseDisplayMode) ?: DisplayMode.POINT,
scaled = opts.getBoolean(LiveMap.SCALED, false),
clustering = opts.getBoolean(LiveMap.CLUSTERING, false),
labels = opts.getBoolean(LiveMap.LABELS, true),
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/Option.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/Option.kt
index dccf746b106..20d281b9cfc 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/Option.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/Option.kt
@@ -29,30 +29,14 @@ object Option {
}
object GeoDataFrame {
- const val TAG = "geodataframe"
- const val GEOMETRY_COLUMN_NAME = "geometry"
-
- // Column with geometries extracted from GeoDataFrame. Can be used either in DATA and MAP
- const val GEOMETRIES = "__geometry__"
- }
-
- object GeoReference {
- const val TAG = "georeference"
- const val REQUEST = "request"
- const val MAP_REGION_COLUMN = "region"
- const val OSM_ID = "id"
+ const val GDF = "geodataframe"
+ const val GEOMETRY = "geometry"
}
object GeoDict {
const val TAG = "geodict"
}
- object MapJoin {
- // Column with keys used for join
- const val ID = "__id__"
- const val MAP_JOIN_COLUMN = "__map_join_column__"
- }
-
object MappingAnnotation {
const val TAG = "mapping_annotations"
const val AES = "aes"
@@ -236,7 +220,6 @@ object Option {
object Mapping {
const val GROUP = "group"
- val MAP_ID = toOption(Aes.MAP_ID) // map_id is 'aes' but also used as option in geom_map()
private val AES_BY_OPTION = HashMap>()
val REAL_AES_OPTION_NAMES: Iterable = AES_BY_OPTION.keys
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSide.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSide.kt
index 138f5a70f09..9cdda006d38 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSide.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSide.kt
@@ -14,7 +14,6 @@ import jetbrains.datalore.plot.builder.theme.Theme
import jetbrains.datalore.plot.config.Option.Plot.COORD
import jetbrains.datalore.plot.config.Option.Plot.THEME
import jetbrains.datalore.plot.config.PlotConfigClientSideUtil.createGuideOptionsMap
-import jetbrains.datalore.plot.config.geo.GeometryFromGeoDataFrameChange
import jetbrains.datalore.plot.config.theme.ThemeConfig
import jetbrains.datalore.plot.config.transform.PlotSpecTransform
import jetbrains.datalore.plot.config.transform.migration.MoveGeomPropertiesToLayerMigration
@@ -73,7 +72,6 @@ class PlotConfigClientSide private constructor(opts: Map) : PlotCon
val isGGBunch = isGGBunchSpec(plotSpec)
plotSpec = PlotSpecTransform.builderForRawSpec()
- .change(GeometryFromGeoDataFrameChange.specSelector(isGGBunch), GeometryFromGeoDataFrameChange())
.build()
.apply(plotSpec)
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSideUtil.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSideUtil.kt
index 8332f84f2ec..49651c2a362 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSideUtil.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/PlotConfigClientSideUtil.kt
@@ -21,7 +21,6 @@ import jetbrains.datalore.plot.builder.interact.GeomInteractionBuilder.Companion
import jetbrains.datalore.plot.builder.interact.GeomInteractionBuilder.Companion.NON_AREA_GEOM
import jetbrains.datalore.plot.builder.theme.Theme
import jetbrains.datalore.plot.builder.tooltip.CompositeValue
-import jetbrains.datalore.plot.config.Option.Meta.MapJoin
import jetbrains.datalore.plot.builder.tooltip.TooltipLineSpecification
object PlotConfigClientSideUtil {
@@ -133,6 +132,10 @@ object PlotConfigClientSideUtil {
layerBuilder.groupingVarName(layerConfig.explicitGroupingVarName!!)
}
+ layerConfig.mergedOptions.dataJoinVariable()?.let {
+ layerBuilder.pathIdVarName(it)
+ }
+
// variable bindings
val bindings = layerConfig.varBindings
for (binding in bindings) {
@@ -251,10 +254,8 @@ object PlotConfigClientSideUtil {
}
// remove auto generated mappings
- aesListForTooltip.removeAll { layerConfig.getScaleForAes(it)?.name == MapJoin.ID }
-
- // remove map_id mapping
- aesListForTooltip.removeAll { it === Aes.MAP_ID }
+ val autoGenerated = listOf()
+ aesListForTooltip.removeAll { layerConfig.getScaleForAes(it)?.name in autoGenerated }
return aesListForTooltip
}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/aes/TypedOptionConverterMap.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/aes/TypedOptionConverterMap.kt
index 329360bd8f2..1a0c7635204 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/aes/TypedOptionConverterMap.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/aes/TypedOptionConverterMap.kt
@@ -20,12 +20,13 @@ import jetbrains.datalore.plot.base.Aes.Companion.INTERCEPT
import jetbrains.datalore.plot.base.Aes.Companion.LABEL
import jetbrains.datalore.plot.base.Aes.Companion.LINETYPE
import jetbrains.datalore.plot.base.Aes.Companion.LOWER
-import jetbrains.datalore.plot.base.Aes.Companion.MAP_ID
import jetbrains.datalore.plot.base.Aes.Companion.MIDDLE
import jetbrains.datalore.plot.base.Aes.Companion.SHAPE
import jetbrains.datalore.plot.base.Aes.Companion.SIZE
import jetbrains.datalore.plot.base.Aes.Companion.SLOPE
import jetbrains.datalore.plot.base.Aes.Companion.SPEED
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_X
+import jetbrains.datalore.plot.base.Aes.Companion.SYM_Y
import jetbrains.datalore.plot.base.Aes.Companion.UPPER
import jetbrains.datalore.plot.base.Aes.Companion.VJUST
import jetbrains.datalore.plot.base.Aes.Companion.WEIGHT
@@ -71,7 +72,6 @@ internal class TypedOptionConverterMap {
this.put(MIDDLE, DOUBLE_CVT)
this.put(UPPER, DOUBLE_CVT)
- this.put(MAP_ID, IDENTITY_O_CVT)
this.put(FRAME, IDENTITY_S_CVT)
this.put(SPEED, DOUBLE_CVT)
@@ -88,6 +88,9 @@ internal class TypedOptionConverterMap {
this.put(HJUST, IDENTITY_O_CVT) // text horizontal justification (numbers [0..1] or predefined strings, DOUBLE_CVT; not positional)
this.put(VJUST, IDENTITY_O_CVT) // text vertical justification (numbers [0..1] or predefined strings, not positional)
this.put(ANGLE, DOUBLE_CVT)
+
+ this.put(SYM_X, DOUBLE_CVT)
+ this.put(SYM_Y, DOUBLE_CVT)
}
private fun put(aes: Aes, value: (Any?) -> T?) {
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeometryFromGeoDataFrameChange.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeometryFromGeoDataFrameChange.kt
deleted file mode 100644
index 71fdf64f76d..00000000000
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeometryFromGeoDataFrameChange.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2020. 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.config.geo
-
-import jetbrains.datalore.base.spatial.*
-import jetbrains.datalore.base.typedGeometry.*
-import jetbrains.datalore.plot.builder.map.GeoPositionField.POINT_X
-import jetbrains.datalore.plot.builder.map.GeoPositionField.POINT_Y
-import jetbrains.datalore.plot.builder.map.GeoPositionField.RECT_XMAX
-import jetbrains.datalore.plot.builder.map.GeoPositionField.RECT_XMIN
-import jetbrains.datalore.plot.builder.map.GeoPositionField.RECT_YMAX
-import jetbrains.datalore.plot.builder.map.GeoPositionField.RECT_YMIN
-import jetbrains.datalore.plot.config.GeoPositionsDataUtil.GeoDataKind
-import jetbrains.datalore.plot.config.Option
-import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame
-import jetbrains.datalore.plot.config.Option.Meta.MapJoin
-import jetbrains.datalore.plot.config.getList
-import jetbrains.datalore.plot.config.transform.SpecSelector
-
-
-class GeometryFromGeoDataFrameChange : GeometryFromGeoPositionsChange() {
- override val geoPositionsKeys: Set
- get() = GEO_DATA_FRAME_KEYS
-
- override fun changeGeoPositions(mapSpec: MutableMap, geoDataKind: GeoDataKind) {
- val geometryTables = mapSpec.getList(GeoDataFrame.GEOMETRIES)!!.map { parseGeometry(it as String, geoDataKind) }
-
- if (geometryTables.sumBy { it.rowCount } == 0) {
- error(
- "Geometries are empty or no matching types. Expected: " +
- when (geoDataKind) {
- GeoDataKind.POINT -> "Point, MultiPoint"
- GeoDataKind.PATH -> "LineString, MultiLineString"
- GeoDataKind.BOUNDARY -> "Polygon, MultiPolygon"
- GeoDataKind.BBOX -> "MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon"
- }
- )
- }
-
- val dataTable = mapSpec.getList(MapJoin.ID)
- ?.zip(geometryTables)
- ?.fold(mutableMapOf>(), { dataFrame, (id, geometryTable) ->
- dataFrame
- .concat(geometryTable)
- .concat(MapJoin.ID, MutableList(geometryTable.rowCount) { id!! })
- })
- ?: geometryTables.fold(mutableMapOf>(), { dataFrame, geometryTable ->
- dataFrame.concat(geometryTable)
- })
-
- mapSpec.clear()
- mapSpec.putAll(dataTable)
- }
-
- private fun parseGeometry(geoJson: String, geoDataKind: GeoDataKind): MutableMap> {
- val geometryTable = mutableMapOf>()
-
- when (geoDataKind) {
- GeoDataKind.POINT -> defaultConsumer {
- onPoint = geometryTable::append
- onMultiPoint = { it.forEach(geometryTable::append) }
- }
- GeoDataKind.PATH -> defaultConsumer {
- onLineString = { it.forEach(geometryTable::append) }
- onMultiLineString = { it.flatten().forEach(geometryTable::append) }
- }
- GeoDataKind.BOUNDARY -> defaultConsumer {
- onPolygon = { it.flatten().forEach(geometryTable::append) }
- onMultiPolygon = { it.flatten().flatten().forEach(geometryTable::append) }
- }
- GeoDataKind.BBOX -> {
- fun insert(bboxes: List>) =
- bboxes
- .run(BBOX_CALCULATOR::union)
- .run(::convertToGeoRectangle)
- .run(GeoRectangle::splitByAntiMeridian)
- .forEach(geometryTable::append)
-
- fun insert(bbox: Rect) = insert(listOf(bbox))
-
- defaultConsumer {
- onMultiPoint = { insert(it.boundingBox()) }
- onLineString = { insert(it.boundingBox()) }
- onMultiLineString = { insert(it.flatten().boundingBox()) }
- onPolygon = { insert(it.limit()) }
- onMultiPolygon = { insert(it.limit()) }
- }
-
- }
- }.let { GeoJson.parse(geoJson, it) }
-
- return geometryTable
- }
-
- companion object {
- fun specSelector(isGGBunch: Boolean) = SpecSelector.from(
- if (isGGBunch) {
- listOf(Option.GGBunch.ITEMS, Option.GGBunch.Item.FEATURE_SPEC, Option.Plot.LAYERS);
- } else {
- listOf(Option.Plot.LAYERS);
- }
- )
-
- private val GEO_DATA_FRAME_KEYS: Set = setOf(GeoDataFrame.GEOMETRIES)
-
- internal fun defaultConsumer(config: SimpleFeature.Consumer.() -> Unit) =
- SimpleFeature.Consumer(
- onPoint = {},
- onMultiPoint = {},
- onLineString = {},
- onMultiLineString = {},
- onPolygon = {},
- onMultiPolygon = {}
- ).apply(config)
- }
-}
-
-private val > Map.rowCount get() = values.firstOrNull()?.size ?: 0
-
-private fun MutableMap>.concat(other: Map>) = apply {
- other.forEach { (key, value) -> getOrPut(key, { ArrayList() }).addAll(value) }
-}
-
-private fun MutableMap>.concat(column: String, values: List) = apply {
- concat(mutableMapOf(column to values))
-}
-
-private fun MutableMap>.append(key: String, value: Double) {
- getOrPut(key, { mutableListOf() }).add(value)
-}
-
-private fun MutableMap>.append(p: Vec) {
- append(POINT_X, p.x)
- append(POINT_Y, p.y)
-}
-
-private fun MutableMap>.append(rect: Rect) {
- append(RECT_XMIN, rect.left)
- append(RECT_XMAX, rect.right)
- append(RECT_YMIN, rect.top)
- append(RECT_YMAX, rect.bottom)
-}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeometryFromGeoPositionsChange.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeometryFromGeoPositionsChange.kt
deleted file mode 100644
index 536b57d0a90..00000000000
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeometryFromGeoPositionsChange.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2020. 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.config.geo
-
-import jetbrains.datalore.plot.base.GeomKind
-import jetbrains.datalore.plot.config.GeoPositionsDataUtil
-import jetbrains.datalore.plot.config.GeoPositionsDataUtil.getGeoDataKind
-import jetbrains.datalore.plot.config.GeoPositionsDataUtil.isGeomSupported
-import jetbrains.datalore.plot.config.Option
-import jetbrains.datalore.plot.config.Option.Geom.Choropleth.GEO_POSITIONS
-import jetbrains.datalore.plot.config.Option.Layer.GEOM
-import jetbrains.datalore.plot.config.asMutable
-import jetbrains.datalore.plot.config.getMap
-import jetbrains.datalore.plot.config.transform.SpecChange
-import jetbrains.datalore.plot.config.transform.SpecChangeContext
-
-
-abstract class GeometryFromGeoPositionsChange : SpecChange {
- override fun isApplicable(spec: Map): Boolean {
- if (spec[GEO_POSITIONS] !is MutableMap<*, *>) {
- return false
- }
- if (!(spec[GEO_POSITIONS] as MutableMap<*, *>?)!!.keys.containsAll(geoPositionsKeys)) {
- return false
- }
- return isGeomSupported(getGeomKind(spec))
- }
-
- override fun apply(spec: MutableMap, ctx: SpecChangeContext) {
- changeGeoPositions(
- mapSpec = spec.getMap(GEO_POSITIONS)!!.asMutable(),
- geoDataKind = getGeoDataKind(getGeomKind(spec))
- )
- }
-
- abstract val geoPositionsKeys: Set
- abstract fun changeGeoPositions(mapSpec: MutableMap, geoDataKind: GeoPositionsDataUtil.GeoDataKind)
-
- companion object {
- private fun getGeomKind(layerSpec: Map): GeomKind {
- val name = layerSpec[GEOM] as String
- return Option.GeomName.toGeomKind(name)
- }
- }
-}
\ No newline at end of file
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/PlotConfigServerSide.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/PlotConfigServerSide.kt
index f0c429b2f26..e4dae3f6870 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/PlotConfigServerSide.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/PlotConfigServerSide.kt
@@ -16,6 +16,10 @@ import jetbrains.datalore.plot.builder.data.GroupingContext
import jetbrains.datalore.plot.builder.tooltip.TooltipLineSpecification
import jetbrains.datalore.plot.builder.tooltip.VariableValue
import jetbrains.datalore.plot.config.*
+import jetbrains.datalore.plot.config.Option.Layer.MAP_JOIN
+import jetbrains.datalore.plot.config.Option.Meta.DATA_META
+import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame.GDF
+import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame.GEOMETRY
import jetbrains.datalore.plot.server.config.transform.PlotConfigServerSideTransforms.entryTransform
import jetbrains.datalore.plot.server.config.transform.PlotConfigServerSideTransforms.migrationTransform
@@ -115,12 +119,10 @@ open class PlotConfigServerSide(opts: Map) : PlotConfig(opts) {
if (!DataFrameUtil.variables(layerData!!).containsKey(varName)) {
dropPlotVar = when {
- // don't drop if used in mapping
- layerConfig.hasVarBinding(varName) -> false
+ layerConfig.hasVarBinding(varName) -> false // don't drop if used in mapping
layerConfig.isExplicitGrouping(varName) -> false
- // don't drop if used for facets
- varName == facets.xVar -> false
- varName == facets.yVar -> false
+ varName == facets.xVar -> false // don't drop if used for facets
+ varName == facets.yVar -> false // don't drop if used for facets
else -> true
}
if (!dropPlotVar) {
@@ -185,17 +187,12 @@ open class PlotConfigServerSide(opts: Map) : PlotConfig(opts) {
varsToKeep.removeAll(notRenderedVars)
varsToKeep.addAll(renderedVars)
- val varNamesToKeep = HashSet()
- for (`var` in varsToKeep) {
- varNamesToKeep.add(`var`.name)
- }
- varNamesToKeep.add(Stats.GROUP.name)
- facets.xVar?.let(varNamesToKeep::add)
- facets.yVar?.let(varNamesToKeep::add)
-
- if (layerConfig.hasExplicitGrouping()) {
- varNamesToKeep.add(layerConfig.explicitGroupingVarName!!)
- }
+ val varNamesToKeep = HashSet() +
+ varsToKeep.map(Variable::name) +
+ Stats.GROUP.name +
+ listOfNotNull(layerConfig.mergedOptions.getString(DATA_META, GDF, GEOMETRY)) +
+ listOfNotNull(layerConfig.mergedOptions.getList(MAP_JOIN)?.get(0) as? String) +
+ listOfNotNull(facets.xVar, facets.yVar, layerConfig.explicitGroupingVarName)
layerData = DataFrameUtil.removeAllExcept(layerData!!, varNamesToKeep)
layerConfig.replaceOwnData(layerData)
@@ -231,8 +228,11 @@ open class PlotConfigServerSide(opts: Map) : PlotConfig(opts) {
val tileLayerInputData = inputDataByTileByLayer[tileIndex][layerIndex]
val varBindings = layerConfig.varBindings
val groupingContext = GroupingContext(
- tileLayerInputData,
- varBindings, layerConfig.explicitGroupingVarName, true
+ myData = tileLayerInputData,
+ bindings = varBindings,
+ groupingVarName = layerConfig.explicitGroupingVarName,
+ pathIdVarName = null, // only on client side
+ myExpectMultiple = true
)
val groupingContextAfterStat: GroupingContext
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/GeoDataFrameMappingChange.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/GeoDataFrameMappingChange.kt
deleted file mode 100644
index 41e2709e5d9..00000000000
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/GeoDataFrameMappingChange.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.server.config.transform
-
-import jetbrains.datalore.plot.config.*
-import jetbrains.datalore.plot.config.Option.Geom.Choropleth.GEO_POSITIONS
-import jetbrains.datalore.plot.config.Option.Mapping.MAP_ID
-import jetbrains.datalore.plot.config.Option.Meta.DATA_META
-import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame
-import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame.GEOMETRY_COLUMN_NAME
-import jetbrains.datalore.plot.config.Option.Meta.MapJoin
-import jetbrains.datalore.plot.config.Option.Plot
-import jetbrains.datalore.plot.config.Option.PlotBase.DATA
-import jetbrains.datalore.plot.config.Option.PlotBase.MAPPING
-import jetbrains.datalore.plot.config.transform.SpecChange
-import jetbrains.datalore.plot.config.transform.SpecChangeContext
-import jetbrains.datalore.plot.config.transform.SpecSelector
-
-class GeoDataFrameMappingChange : SpecChange {
-
- override fun apply(spec: MutableMap, ctx: SpecChangeContext) {
- val geometryColumnName = spec.read(DATA_META, GeoDataFrame.TAG, GEOMETRY_COLUMN_NAME) as String
- val geometries = spec.getList(DATA, geometryColumnName)!!
- val ids = geometries.indices.map(Int::toString)
-
- spec.remove(DATA, geometryColumnName)
- spec.write(DATA, MapJoin.ID) { ids }
- spec.write(GEO_POSITIONS, MapJoin.ID) { ids }
- spec.write(GEO_POSITIONS, GeoDataFrame.GEOMETRIES) { geometries}
- spec.write(MAPPING, MAP_ID) { MapJoin.ID }
- }
-
- override fun isApplicable(spec: Map): Boolean {
- return (!spec.has(GEO_POSITIONS)
- && spec.has(DATA_META, GeoDataFrame.TAG))
- }
-
- companion object {
- internal fun specSelector() = SpecSelector.of(Plot.LAYERS)
- }
-}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/GeoPositionMappingChange.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/GeoPositionMappingChange.kt
deleted file mode 100644
index 76d0ff0f98e..00000000000
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/GeoPositionMappingChange.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.server.config.transform
-
-import jetbrains.datalore.plot.config.*
-import jetbrains.datalore.plot.config.GeoPositionsDataUtil.MAP_OSM_ID_COLUMN
-import jetbrains.datalore.plot.config.GeoPositionsDataUtil.MAP_REGION_COLUMN
-import jetbrains.datalore.plot.config.Option.Geom.Choropleth.GEO_POSITIONS
-import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame
-import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame.GEOMETRY_COLUMN_NAME
-import jetbrains.datalore.plot.config.Option.Meta.GeoDict
-import jetbrains.datalore.plot.config.Option.Meta.GeoReference
-import jetbrains.datalore.plot.config.Option.Meta.MAP_DATA_META
-import jetbrains.datalore.plot.config.Option.Meta.MapJoin
-import jetbrains.datalore.plot.config.Option.Plot
-import jetbrains.datalore.plot.config.transform.SpecChange
-import jetbrains.datalore.plot.config.transform.SpecChangeContext
-import jetbrains.datalore.plot.config.transform.SpecSelector
-
-class GeoPositionMappingChange : SpecChange {
-
- override fun apply(spec: MutableMap, ctx: SpecChangeContext) {
- val mapSpec = spec.getMap(GEO_POSITIONS)!!
- val mapJoinIds = spec.read(MapJoin.MAP_JOIN_COLUMN)?.let { mapSpec.read(it as String) }
-
- if (spec.has(MAP_DATA_META, GeoDataFrame.TAG)) {
- // Select column applicable for join
- listOfNotNull(
- mapJoinIds, // user defined column via parameter `map_join`
- mapSpec.read(GeoReference.REQUEST), // Regions object from our geocoding
- mapSpec.read(MAP_REGION_COLUMN) // ???
- ).firstOrNull()?.let { mapSpec.write(MapJoin.ID) { it } }
-
- spec.read(MAP_DATA_META, GeoDataFrame.TAG, GEOMETRY_COLUMN_NAME)
- ?.let { geometryColumnName -> mapSpec.read(geometryColumnName as String)!! }
- ?.let { geometries -> mapSpec.write(GeoDataFrame.GEOMETRIES) { geometries } }
- }
-
- if (spec.has(MAP_DATA_META, GeoReference.TAG)) {
- mapSpec.write(MapJoin.ID) { mapSpec.read(GeoReference.REQUEST)!! }
- mapSpec.write(MAP_OSM_ID_COLUMN) { mapSpec.read(GeoReference.OSM_ID)!! }
- }
-
- if (spec.has(MAP_DATA_META, GeoDict.TAG)) {
- mapJoinIds?.let { mapSpec.write(MapJoin.ID) { it } }
- }
- }
-
- override fun isApplicable(spec: Map): Boolean {
- return spec.has(MAP_DATA_META, GeoDataFrame.TAG) ||
- spec.has(MAP_DATA_META, GeoReference.TAG) ||
- spec.has(MAP_DATA_META, GeoDict.TAG)
- }
-
- companion object {
- internal fun specSelector() = SpecSelector.of(Plot.LAYERS)
- }
-}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/LonLatSpecInMappingSpecChange.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/LonLatSpecInMappingSpecChange.kt
deleted file mode 100644
index 4737952c4bb..00000000000
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/LonLatSpecInMappingSpecChange.kt
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.server.config.transform
-
-import jetbrains.datalore.base.gcommon.base.Preconditions.checkArgument
-import jetbrains.datalore.base.spatial.MercatorUtils.checkLat
-import jetbrains.datalore.base.spatial.MercatorUtils.checkLon
-import jetbrains.datalore.plot.config.Option.GeomName
-import jetbrains.datalore.plot.config.Option.Layer.GEOM
-import jetbrains.datalore.plot.config.Option.Mapping
-import jetbrains.datalore.plot.config.Option.Plot
-import jetbrains.datalore.plot.config.Option.PlotBase.DATA
-import jetbrains.datalore.plot.config.Option.PlotBase.MAPPING
-import jetbrains.datalore.plot.config.transform.SpecChange
-import jetbrains.datalore.plot.config.transform.SpecChangeContext
-import jetbrains.datalore.plot.config.transform.SpecFinder
-import jetbrains.datalore.plot.config.transform.SpecSelector
-
-class LonLatSpecInMappingSpecChange : SpecChange {
-
- override fun isApplicable(spec: Map): Boolean {
- return GeomName.LIVE_MAP == spec[GEOM] &&
- spec.containsKey(MAPPING) &&
- spec[MAPPING] is Map<*, *>
- }
-
- override fun apply(spec: MutableMap, ctx: SpecChangeContext) {
- //System.out.println("Finding mapping.....");
- // find: aes(... , map_id = lon_lat(lon = 'x', lat = 'y') )
- val finder = SpecFinder(MAPPING, Mapping.MAP_ID)
- val specs = finder.findSpecs(spec)
- if (specs.isEmpty()) {
- //System.out.println("Not found");
- return
- }
-
- val mapIdMapping = specs[0]
- //System.out.println("Found " + mapIdMapping);
-
- // check if the value is: lon_lat(lon = 'x', lat = 'y')
- if (mapIdMapping.containsKey(LONLAT_SPEC_KEY)
- && LONLAT_SPEC_VALUE == mapIdMapping[LONLAT_SPEC_KEY]
- && mapIdMapping.containsKey(LON_KEY)
- && mapIdMapping.containsKey(LAT_KEY)
- ) {
-
- val lonDataKey = mapIdMapping[LON_KEY].toString()
- val latDataKey = mapIdMapping[LAT_KEY].toString()
- val keys = listOf(lonDataKey, latDataKey)
-
- // Find data spec containing both: lon and lat data keys
- var dataSpec: MutableMap? = null
- if (spec[DATA] is Map<*, *>) {
- val layerDataSpec = spec[DATA] as Map<*, *>
- if (layerDataSpec.keys.containsAll(keys)) {
- @Suppress("UNCHECKED_CAST")
- dataSpec = layerDataSpec as MutableMap
- }
- }
-
- if (dataSpec == null) {
- val list = ctx.getSpecsAbsolute(DATA)
- if (list.isNotEmpty() && list[0].keys.containsAll(keys)) {
- dataSpec = list[0] as MutableMap
- }
- }
-
- //System.out.println("data found: " + dataSpec);
- if (dataSpec == null) {
- throw IllegalArgumentException("Can not find data containing keys: $lonDataKey and $latDataKey")
- }
-
- val coords =
- concatColumns(
- dataSpec[lonDataKey] as List<*>,
- dataSpec[latDataKey] as List<*>
- )
-
- // add 'lon/lat' data vector
- dataSpec[GENERATED_LONLAT_COLUMN_NAME] = coords
- // update map_id mapping
- @Suppress("UNCHECKED_CAST")
- val aesSpec = spec[MAPPING] as MutableMap
- aesSpec[Mapping.MAP_ID] =
- GENERATED_LONLAT_COLUMN_NAME
- }
- }
-
- companion object {
- const val LON_KEY = "lon"
- const val LAT_KEY = "lat"
- const val LONLAT_SPEC_KEY = "name"
- const val LONLAT_SPEC_VALUE = "lon_lat"
- const val GENERATED_LONLAT_COLUMN_NAME = "generated_lonlat"
-
- fun specSelector(): SpecSelector {
- return SpecSelector.of(Plot.LAYERS)
- }
-
- private fun concatColumns(lon: List<*>, lat: List<*>): List {
- checkArgument(lon.isNotEmpty(), "Empty longitude data.")
- checkArgument(lat.isNotEmpty(), "Empty latitude data.")
- checkArgument(lon.size == lat.size, "Longitude and latitude have different size")
-
- val coordinates = ArrayList()
- var i = 0
- val n = lon.size
- while (i < n) {
- coordinates.add(
- concatCoordinates(
- lon[i],
- lat[i]
- )
- )
- ++i
- }
-
- return coordinates
- }
-
- private fun concatCoordinates(lonObj: Any?, latObj: Any?): String {
- val lon =
- toDouble(lonObj)
- val lat =
- toDouble(latObj)
-
- checkArgument(checkLon(lon), "Invalid longitude: $lon")
- checkArgument(checkLat(lat), "Invalid latitude: $lat")
-
- return "$lon, $lat"
- }
-
- private fun toDouble(v: Any?): Double {
- val errorMessage = "Invalid coordinate data format"
- checkArgument(v is String || v is Number, errorMessage)
-
- if (v is String) {
- try {
- return v.toDouble()
- } catch (e: NumberFormatException) {
- throw IllegalArgumentException(errorMessage, e)
- }
-
- }
-
- return (v as Number).toDouble()
- }
- }
-}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/MapJoinChange.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/MapJoinChange.kt
deleted file mode 100644
index 0decd1dcd2b..00000000000
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/MapJoinChange.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2020. 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.server.config.transform
-
-import jetbrains.datalore.plot.config.Option
-import jetbrains.datalore.plot.config.Option.Layer.MAP_JOIN
-import jetbrains.datalore.plot.config.Option.Mapping.MAP_ID
-import jetbrains.datalore.plot.config.Option.Meta.MAP_DATA_META
-import jetbrains.datalore.plot.config.Option.Meta.MapJoin
-import jetbrains.datalore.plot.config.Option.PlotBase.MAPPING
-import jetbrains.datalore.plot.config.getList
-import jetbrains.datalore.plot.config.transform.SpecChange
-import jetbrains.datalore.plot.config.transform.SpecChangeContext
-import jetbrains.datalore.plot.config.transform.SpecSelector
-import jetbrains.datalore.plot.config.write
-
-class MapJoinChange: SpecChange {
- override fun apply(spec: MutableMap, ctx: SpecChangeContext) {
- val (dataJoinColumn, mapJoinColumn) = spec.getList(MAP_JOIN)!!
- dataJoinColumn?.let { spec.write(MAPPING, MAP_ID) { it } }
- mapJoinColumn?.let { spec.write(MapJoin.MAP_JOIN_COLUMN) { it } }
- }
-
- override fun isApplicable(spec: Map): Boolean {
- return spec.contains(MAP_JOIN)
- && spec.contains(MAP_DATA_META)
- }
-
- companion object {
- internal fun specSelector(): SpecSelector {
- return SpecSelector.of(Option.Plot.LAYERS)
- }
- }
-}
diff --git a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/PlotConfigServerSideTransforms.kt b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/PlotConfigServerSideTransforms.kt
index 1ba4ae31cd8..e5debc46a56 100644
--- a/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/PlotConfigServerSideTransforms.kt
+++ b/plot-config-portable/src/commonMain/kotlin/jetbrains/datalore/plot/server/config/transform/PlotConfigServerSideTransforms.kt
@@ -41,22 +41,6 @@ object PlotConfigServerSideTransforms {
ReplaceDataVectorsInAesMappingChange.specSelector(),
ReplaceDataVectorsInAesMappingChange()
)
- .change(
- MapJoinChange.specSelector(),
- MapJoinChange()
- )
- .change(
- LonLatSpecInMappingSpecChange.specSelector(),
- LonLatSpecInMappingSpecChange()
- )
- .change(
- GeoDataFrameMappingChange.specSelector(),
- GeoDataFrameMappingChange()
- )
- .change(
- GeoPositionMappingChange.specSelector(),
- GeoPositionMappingChange()
- )
.build()
}
}
diff --git a/plot-config-portable/src/commonTest/kotlin/plot/config/GeomInteractionBuilderCreationTest.kt b/plot-config-portable/src/commonTest/kotlin/plot/config/GeomInteractionBuilderCreationTest.kt
index 48faf1d4a96..58c5958151e 100644
--- a/plot-config-portable/src/commonTest/kotlin/plot/config/GeomInteractionBuilderCreationTest.kt
+++ b/plot-config-portable/src/commonTest/kotlin/plot/config/GeomInteractionBuilderCreationTest.kt
@@ -6,17 +6,20 @@
package plot.config
import jetbrains.datalore.plot.base.Aes
-import jetbrains.datalore.plot.config.LayerConfig
-import jetbrains.datalore.plot.config.Option
-import jetbrains.datalore.plot.config.Option.Meta.MapJoin
+import jetbrains.datalore.plot.config.*
+import jetbrains.datalore.plot.config.Option.GeomName.POINT
+import jetbrains.datalore.plot.config.Option.Layer.GEOM
+import jetbrains.datalore.plot.config.Option.Meta.DATA_META
+import jetbrains.datalore.plot.config.Option.Meta.GeoDataFrame
+import jetbrains.datalore.plot.config.Option.Meta.KIND
+import jetbrains.datalore.plot.config.Option.Meta.Kind.PLOT
+import jetbrains.datalore.plot.config.Option.Plot.LAYERS
import jetbrains.datalore.plot.config.Option.PlotBase.DATA
import jetbrains.datalore.plot.config.Option.PlotBase.MAPPING
-import jetbrains.datalore.plot.config.PlotConfigClientSideUtil
import jetbrains.datalore.plot.server.config.PlotConfigServerSide
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
-import kotlin.test.assertNotNull
class GeomInteractionBuilderCreationTest {
@@ -32,9 +35,9 @@ class GeomInteractionBuilderCreationTest {
)
val plotOpts = mutableMapOf(
MAPPING to mappedData,
- Option.Plot.LAYERS to listOf(
+ LAYERS to listOf(
mapOf(
- Option.Layer.GEOM to Option.GeomName.HISTOGRAM
+ GEOM to Option.GeomName.HISTOGRAM
)
)
)
@@ -53,72 +56,6 @@ class GeomInteractionBuilderCreationTest {
assertAesListCount(expectedAesListCount, builder.aesListForTooltip)
}
-
- @Test
- fun shouldSkipMapIdMapping() {
- val mappedData = data + mapOf(
- Aes.MAP_ID.name to listOf('a')
- )
- val plotOpts = mutableMapOf(
- MAPPING to mappedData,
- Option.Plot.LAYERS to listOf(
- mapOf(
- Option.Layer.GEOM to Option.GeomName.POINT
- )
- )
- )
- val layerConfig = createLayerConfig(plotOpts)
-
- val builder = PlotConfigClientSideUtil.createGeomInteractionBuilder(
- layerConfig,
- emptyList(),
- false
- )
-
- assertFalse { builder.aesListForTooltip.contains(Aes.MAP_ID) }
-
- val expectedAxisList = listOf(Aes.X, Aes.Y)
- // without Aes.MAP_ID:
- val expectedAesListCount = (layerConfig.geomProto.renders() - expectedAxisList).size - 1
-
- assertAesListCount(expectedAxisList.size, builder.axisAesListForTooltip)
- assertAesListCount(expectedAesListCount, builder.aesListForTooltip)
- }
-
- @Test
- fun shouldSkipMapIdMappingAndAxisVisibilityIsFalse() {
- val mappedData = data + mapOf(
- Aes.MAP_ID.name to listOf('a')
- )
-
- val plotOpts = mutableMapOf(
- MAPPING to mappedData,
- Option.Plot.LAYERS to listOf(
- mapOf(
- Option.Layer.GEOM to Option.GeomName.POLYGON
- )
- )
- )
- val layerConfig = createLayerConfig(plotOpts)
-
- val builder = PlotConfigClientSideUtil.createGeomInteractionBuilder(
- layerConfig,
- emptyList(),
- false
- )
-
- assertFalse { builder.aesListForTooltip.contains(Aes.MAP_ID) }
-
- // builder's axis tooltip visibility is false:
- val expectedAxisCount = 0
- // without Aes.MAP_ID:
- val expectedAesListCount = (layerConfig.geomProto.renders() - listOf(Aes.X, Aes.Y)).size - 1
-
- assertAesListCount(expectedAxisCount, builder.axisAesListForTooltip)
- assertAesListCount(expectedAesListCount, builder.aesListForTooltip)
-
- }
-
@Test
fun shouldNotDuplicateVarToAxisAndGenericTooltip() {
val mappedData = mapOf(
@@ -128,9 +65,9 @@ class GeomInteractionBuilderCreationTest {
val plotOpts = mutableMapOf(
MAPPING to mappedData,
- Option.Plot.LAYERS to listOf(
+ LAYERS to listOf(
mapOf(
- Option.Layer.GEOM to Option.GeomName.HISTOGRAM
+ GEOM to Option.GeomName.HISTOGRAM
)
)
)
@@ -156,9 +93,9 @@ class GeomInteractionBuilderCreationTest {
fun shouldSkipAutoGeneratedMappings() {
val GEOMETRIES = listOf(
- "{\"type: \"Point\", \"coordinates\":[-10, -20]}",
- "{\"type: \"Point\", \"coordinates\":[-30, -40]}",
- "{\"type: \"Point\", \"coordinates\":[-50, -60]}"
+ "{\"type\": \"Point\", \"coordinates\":[-10, -20]}",
+ "{\"type\": \"Point\", \"coordinates\":[-30, -40]}",
+ "{\"type\": \"Point\", \"coordinates\":[-50, -60]}"
)
val geomData = mapOf(
"name" to listOf("a", "b", "c"),
@@ -166,25 +103,28 @@ class GeomInteractionBuilderCreationTest {
"coord" to GEOMETRIES
)
val GEO_DATA_FRAME_META = mapOf(
- Option.Meta.GeoDataFrame.TAG to mapOf(
- Option.Meta.GeoDataFrame.GEOMETRY_COLUMN_NAME to "coord"
+ GeoDataFrame.GDF to mapOf(
+ GeoDataFrame.GEOMETRY to "coord"
)
)
val plotOpts = mutableMapOf(
- Option.Meta.KIND to Option.Meta.Kind.PLOT,
- Option.Plot.LAYERS to listOf(
+ KIND to PLOT,
+ LAYERS to listOf(
mutableMapOf(
- Option.Layer.GEOM to Option.GeomName.POLYGON,
+ GEOM to POINT,
DATA to geomData,
- Option.Meta.DATA_META to GEO_DATA_FRAME_META,
+ DATA_META to GEO_DATA_FRAME_META,
MAPPING to mapOf(Aes.FILL.name to "name")
)
)
)
- val layerConfig = createLayerConfig(plotOpts)
- val binding = layerConfig.varBindings.find { it.variable.name == MapJoin.ID }
- assertNotNull(binding)
+
+ val opts = PlotConfigServerSide.processTransform(plotOpts)
+ val layerConfig = PlotConfigClientSide.create(opts).layerConfigs.first()
+
+ val pointX = layerConfig.varBindings.find { it.variable.name == POINT_X }
+ val pointY = layerConfig.varBindings.find { it.variable.name == POINT_Y }
val builder = PlotConfigClientSideUtil.createGeomInteractionBuilder(
layerConfig,
@@ -192,7 +132,8 @@ class GeomInteractionBuilderCreationTest {
false
)
- assertFalse { builder.aesListForTooltip.contains(binding.aes) }
+ assertFalse { builder.aesListForTooltip.contains(pointX!!.aes) }
+ assertFalse { builder.aesListForTooltip.contains(pointY!!.aes) }
}
private fun createLayerConfig(plotOpts: MutableMap): LayerConfig {
@@ -200,7 +141,7 @@ class GeomInteractionBuilderCreationTest {
return PlotConfigServerSide(plotSpec).layerConfigs.first()
}
- internal fun assertAesListCount(expectedCount: Int, aesList: List>) {
+ private fun assertAesListCount(expectedCount: Int, aesList: List>) {
assertEquals(expectedCount, aesList.size)
}
}
\ No newline at end of file
diff --git a/plot-config/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeoPositionResolver.kt b/plot-config/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeoPositionResolver.kt
deleted file mode 100644
index 9d2be246423..00000000000
--- a/plot-config/src/commonMain/kotlin/jetbrains/datalore/plot/config/geo/GeoPositionResolver.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.config.geo
-
-import jetbrains.datalore.base.async.Async
-import jetbrains.datalore.base.async.Asyncs
-import jetbrains.datalore.plot.config.Option.GGBunch.ITEMS
-import jetbrains.datalore.plot.config.Option.GGBunch.Item.FEATURE_SPEC
-import jetbrains.datalore.plot.config.Option.GeomName.LIVE_MAP
-import jetbrains.datalore.plot.config.Option.Layer.GEOM
-import jetbrains.datalore.plot.config.Option.Plot.LAYERS
-import jetbrains.datalore.plot.config.PlotConfig
-import jetbrains.datalore.plot.config.transform.PlotSpecTransform
-import jetbrains.datalore.plot.config.transform.SpecFinder
-import jetbrains.datalore.plot.config.transform.SpecSelector.Companion.of
-
-object GeoPositionsResolver {
-
- public fun fetchAndReplace(
- plotSpec: Map
- ) : Async