3x3 grid multiplot

import io.data2viz.charts.* import io.data2viz.charts.dimension.* import io.data2viz.charts.chart.* import io.data2viz.charts.chart.mark.* import io.data2viz.charts.viz.* import io.data2viz.charts.layout.* import io.data2viz.charts.core.* import io.data2viz.charts.core.Padding import io.data2viz.geom.* import io.data2viz.color.* import io.data2viz.random.RandomDistribution import kotlinx.datetime.Instant import kotlinx.browser.document import org.w3c.dom.* val width = 900.0 val height = 480.0 fun main() { // setting up the different accessors val accessors: List<Datum<Sample>.() -> Double> = listOf( { domain.temperature }, { domain.pressure }, { domain.random } ) // set a style for placing the CANVAS val style = document.createElement("style") style.innerHTML = "canvas{display:inline !important;}" document.head!!.appendChild(style) // creating the DIVs, then placing VizContainer inside val charts = (0 until 3).map { xi -> val div = document.createElement("div") document.body!!.appendChild(div) val chartrow = (0 until 3).map { yi -> val vc = (div as HTMLDivElement).newVizContainer() vc.apply { size = Size(width / 3.0, height / 3.0) } vc.createChart(samples, accessors[yi], accessors[xi]) } div.setAttribute("style", "height: ${height / 3.0}px;width: ${width}px") chartrow } var current = 0 charts.forEachIndexed { xi, chartrow -> chartrow.forEachIndexed { yi, chart -> // "unlight" all chart.onHighlight { _ -> charts[0][0].highlight(listOf<Sample>()) charts[1][0].highlight(listOf<Sample>()) charts[2][0].highlight(listOf<Sample>()) charts[0][1].highlight(listOf<Sample>()) charts[1][1].highlight(listOf<Sample>()) charts[2][1].highlight(listOf<Sample>()) charts[0][2].highlight(listOf<Sample>()) charts[1][2].highlight(listOf<Sample>()) charts[2][2].highlight(listOf<Sample>()) } // then highlight the expected one (0 until 3).forEach { index -> chart.onHighlight { evt -> charts[xi][index].highlight(evt.data) } chart.onHighlight { evt -> charts[index][yi].highlight(evt.data) } } // also synchronize all "panning" (0 until 9).forEach { index -> if (index != current) { chart.onPan { evt -> charts[index%3][index/3].pan(evt.panX, evt.panY) } } } current++ } } } private fun VizContainer.createChart(dataset:List<Sample>, xAcc: Datum<Sample>.() -> Double, yAcc: Datum<Sample>.() -> Double): Chart<Sample> { return chart(dataset) { config { padding = Padding(2.0, 2.0, 2.0, 2.0) events { zoomMode = ZoomMode.None panMode = PanMode.XY } cursor { show = true } } series = discrete( { domain.batchCode } ) val ts = quantitative( xAcc ) val tp = quantitative( yAcc ) plot(ts, tp) { x { enableTicksLabels = false enableTicks = false } y { enableTicksLabels = false enableTicks = false } } } } val randomGenerator = RandomDistribution(42).normal(100.0, 18.0) data class Sample( val sampleIndex: Int, val batchCode: String, val timestamp: Instant, val temperature: Double, val pressure: Double, val random: Double, ) val samples = generateSamples(200) fun generateSamples(numSamples: Int) = (0 until numSamples).map { val batchIndex = 1 + (it % 4) val pressure: Double = randomGenerator() * 1000 val temp: Double = randomGenerator() * batchIndex * pressure / 100000 val ts = Instant.fromEpochMilliseconds(1611150127144L + (it * 8632L)) val random = randomGenerator() / temp Sample(it, "Batch #$batchIndex", ts, temp, pressure, random) }
pierre avatar

Sketch created by

pierre

A 3x3 synchronized multiplot grid.

comments

Gaetan Zoritchak