SciProgCentre / plotly.kt

An interactive Kotlin wrapper for plotly visualization tools
https://sciprogcentre.github.io/plotly.kt/
Apache License 2.0
150 stars 21 forks source link

Updating multiple traces `textsList` in the live server does not update for each value #53

Closed zakhenry closed 3 years ago

zakhenry commented 3 years ago

Hi me again with another bug I'm afraid

0.3.0 fixes the issue raised in #51 however there remains a very similar issue, this time it is the textsList property that is not updated correctly, however I suspect the source of the issue is different as the data going through the websocket appears correct.

Repro based on the example one

import hep.dataforge.meta.invoke
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kscience.plotly.Plotly
import kscience.plotly.models.Bar
import kscience.plotly.plot
import kscience.plotly.server.close
import kscience.plotly.server.pushUpdates
import kscience.plotly.server.serve
import kscience.plotly.server.show
import kotlin.random.Random

fun main() {
    val initialValue = (1..10).toList()

    val traces = (0..2).associate { i ->
        val name = "Series $i"

        name to Bar {
            x.strings = initialValue.map { "Column: $it" }
            y.numbers = initialValue
            textsList = initialValue.map { "Initial value of this datapoint is: ${it}"} // <-- LINE ADDED
            this.name = name
        }
    }

    val server = Plotly.serve(port = 3872) {

        //root level plots go to default page
        page { plotly ->
            plot(renderer = plotly) {
                traces(traces.values)
                layout {
                    title = "Other dynamic plot"
                    xaxis.title = "x axis name"
                    yaxis.title = "y axis name"
                }
            }
        }

        pushUpdates(100)       // start sending updates via websocket to the front-end
    }

    server.show()

    //Start pushing updates
    GlobalScope.launch {
        delay(1000)
        while (isActive) {
            repeat(10) { columnIndex ->
                repeat(3) { seriesIndex ->
                    delay(200)
                    traces["Series $seriesIndex"]?.let {bar->
                        println("Updating ${bar.name}, Column $columnIndex")
                        //TODO replace with dynamic data API
                        val yValues = bar.y.doubles
                        yValues[columnIndex] = Random.nextInt(0,100).toDouble()
                        bar.y.doubles = yValues
                        bar.textsList = yValues.map { "Updated value of this datapoint is: ${it}"} // <-- LINE ADDED
                    }
                }
            }
        }
    }

    println("Press Enter to close server")
    readLine()

    server.close()
}

See my two // <-- LINE ADDED comments for the diff.

When running this example you would expect the hover label to contain the text "Updated value of this datapoint is: ${it}" where it is the y value of that bar, however the value appears to be being set to the value of the first bar in that series always.

zakhenry commented 3 years ago

Ok this was an easier fix, raised #54 to fix this