JetBrains / lets-plot-kotlin

Grammar of Graphics for Kotlin
https://lets-plot.org/kotlin/
MIT License
418 stars 36 forks source link

Working with new types of data. #184

Open AndreiKingsley opened 1 year ago

AndreiKingsley commented 1 year ago

Suppose we use a non-typical data type for plotting, for example our own data class.

public data class A(val a: Int)
public fun main() {
    (letsPlot {
    } + geomPoint {
        x = listOf(A(1), A(2))
        y = listOf(1, 2)
        color = listOf(A(1), A(2))
    }).also {
        ggsave(it, "plot.png")
    }
}

When trying to create a plot with this type of data with png rendering everything works as we assume - data of this type are casted to String.

image

However, when we try to save to html or use notebook rendering, we get an exception:

public data class A(val a: Int)
public fun main() {
    println(A(5))
    (letsPlot {
    } + geomPoint {
        x = listOf(A(1), A(2))
        y = listOf(1, 2)
        color = listOf(A(1), A(2))
    }).also {
        ggsave(it, "plot.html")
    }
}
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Exception in thread "main" java.lang.IllegalArgumentException: Can't serialize object A(a=1)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:49)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:40)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleList$1.invoke(JsObjectSupport.kt:20)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleList$1.invoke(JsObjectSupport.kt:15)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:47)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:40)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleMap$1.invoke(JsObjectSupport.kt:35)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleMap$1.invoke(JsObjectSupport.kt:25)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:48)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:40)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleMap$1.invoke(JsObjectSupport.kt:35)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleMap$1.invoke(JsObjectSupport.kt:25)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:48)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:40)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleList$1.invoke(JsObjectSupport.kt:20)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleList$1.invoke(JsObjectSupport.kt:15)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:47)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$1.invoke(JsObjectSupport.kt:40)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleMap$1.invoke(JsObjectSupport.kt:35)
    at jetbrains.datalore.base.jsObject.JsObjectSupport$mapToJsObjectInitializer$handleMap$1.invoke(JsObjectSupport.kt:25)
    at jetbrains.datalore.base.jsObject.JsObjectSupport.mapToJsObjectInitializer(JsObjectSupport.kt:53)
    at jetbrains.datalore.plot.PlotHtmlHelper.getStaticDisplayHtmlForRawSpec(PlotHtmlHelper.kt:123)
    at jetbrains.datalore.plot.PlotHtmlExport.buildHtmlFromRawSpecs(PlotHtmlExport.kt:30)
    at jetbrains.datalore.plot.PlotHtmlExport.buildHtmlFromRawSpecs$default(PlotHtmlExport.kt:22)
    at org.jetbrains.letsPlot.export.GgsaveKt.ggsave(ggsave.kt:77)
    at org.jetbrains.letsPlot.export.GgsaveKt.ggsave$default(ggsave.kt:44)
    at org.jetbrains.kotlinx.kandy.letsplot.MainKt.main(main.kt:16)
    at org.jetbrains.kotlinx.kandy.letsplot.MainKt.main(main.kt)

Indeed, the new type is not among the recognizable. The question is: why? I believe that the behavior with "png" should be repeated - just add toString() for unknown types.

AndreiKingsley commented 1 year ago

Perhaps we should do this at the stage of transforming into a spec?