Commit 3fe81bad authored by Mathieu's avatar Mathieu
Browse files

Implements SPLOM graph

parent eab10fb3
......@@ -607,7 +607,7 @@ lazy val clientGUI = OsgiProject(guiClientDir, "org.openmole.gui.client.core") e
libraryDependencies += Libraries.async,
npmDeps in Compile += Dep("ace-builds", "1.2.9", List("mode-scala.js", "theme-github.js", "ext-language_tools.js"), true),
npmDeps in Compile += Dep("sortablejs", "1.7.0", List("Sortable.min.js")),
npmDeps in Compile += Dep("plotly.js", "1.31.0", List("plotly-basic.min.js"))
npmDeps in Compile += Dep("plotly.js", "1.42.0", List("plotly.min.js"))
) settings (defaultSettings: _*)
......
......@@ -12,23 +12,19 @@ import scaladget.bootstrapnative.bsn._
import scaladget.tools._
import org.openmole.gui.ext.api.Api
import org.scalajs.dom.raw.HTMLElement
import rx._
import scalatags.JsDom.all.{ raw, _ }
import scalatags.JsDom.TypedTag
import org.openmole.gui.ext.tool.client._
import org.openmole.gui.client.core._
import org.openmole.gui.ext.tool.client.FileManager
import DataUtils._
import com.definitelyscala.plotlyjs.PlotType
import net.scalapro.sortable._
import org.openmole.gui.client.core.files.TreeNodeTab.{ EditableView, RowFilter }
import org.openmole.gui.client.tool.plot
import org.openmole.gui.client.tool.plot.Plot.{ PlotMode, ScatterMode, XYMode }
import org.openmole.gui.client.tool.plot.Plot.{ PlotMode, ScatterMode, SplomMode, XYMode }
import org.openmole.gui.client.tool.plot._
import org.openmole.gui.client.tool.plot.Tools._
import scaladget.bootstrapnative.DataTable
import rx._
import scala.collection.immutable.HashMap
import scala.scalajs.js.timers._
......@@ -217,7 +213,7 @@ object TreeNodeTab {
view: EditableView = Raw,
initialEditing: Boolean = false,
filter: RowFilter = First100,
axis: (Int, Int) = (0, 1),
axis: Seq[Int] = Seq(0, 1),
plotMode: PlotMode = ScatterMode): TreeNodeTab = new TreeNodeTab {
lazy val safePathTab = Var(safePath)
......@@ -325,9 +321,15 @@ object TreeNodeTab {
def toView(filter: RowFilter) = panels.treeNodeTabs.switchEditableTo(this, sequence.now, view, filter, editing, axis, plotMode)
def toView(newAxis: (Int, Int)) = panels.treeNodeTabs.switchEditableTo(this, sequence.now, view, filter, editing, newAxis, plotMode)
def toView(newAxis: Seq[Int]) = panels.treeNodeTabs.switchEditableTo(this, sequence.now, view, filter, editing, newAxis, plotMode)
def toView(newMode: PlotMode) = panels.treeNodeTabs.switchEditableTo(this, sequence.now, view, filter, editing, axis, newMode)
def toView(newMode: PlotMode) = {
val (seqs, ax) = newMode match {
case SplomMode (initialSequence, axis)
case _ (sequence.now, axis.take(2))
}
panels.treeNodeTabs.switchEditableTo(this, seqs, view, filter, editing, ax, newMode)
}
lazy val switchButton = radios(margin := 20)(
selectableButton("Raw", view == Raw, onclick = () switchView(Raw)),
......@@ -345,13 +347,20 @@ object TreeNodeTab {
(for (
a sequence.now.header.zipWithIndex
) yield {
selectableButton(a._1, axis._1 == a._2 || axis._2 == a._2, onclick = () toView((axis._2, a._2)))
selectableButton(a._1, axis.contains(a._2), onclick = () {
val newAxis = plotMode match {
case SplomMode if (axis.contains(a._2)) axis.filterNot(_ == a._2) else axis :+ a._2
case _ Seq(axis.last, a._2)
}
toView(newAxis)
})
}): _*
)
lazy val plotModeRadios = radios(marginLeft := 40)(
selectableButton("Line", plotMode == XYMode, onclick = () toView(XYMode)),
selectableButton("Scatter", plotMode == ScatterMode, onclick = () toView(ScatterMode))
selectableButton("Scatter", plotMode == ScatterMode, onclick = () toView(ScatterMode)),
selectableButton("SPLOM", plotMode == SplomMode, onclick = () toView(SplomMode))
)
lazy val block: TypedTag[_ <: HTMLElement] = {
......@@ -387,24 +396,19 @@ object TreeNodeTab {
case Raw editorView
case _
if (filteredSequence.size > 0) {
if (filteredSequence.head.length > Math.max(axis._1, axis._2)) {
if (filteredSequence.head.length >= axis.length) {
val dataRow = filteredSequence.map {
scaladget.bootstrapnative.DataTable.DataRow(_)
}.toSeq
val col1 = DataTable.column(axis._1, dataRow)
val col2 = DataTable.column(axis._2, dataRow)
val xyplot = plot.Plot(
plot.Plot(
"",
sequence.now.header(axis._1),
sequence.now.header(axis._2),
Seq(Serie(
x = col1.values.toArray,
y = col2.values.toArray
)),
Serie(axis.length, axis.foldLeft(Array[Dim]()) { (acc, col)
acc :+ Dim(DataTable.column(col, dataRow).values, sequence.now.header.lift(col).getOrElse(""))
}),
false,
plotMode
)
xyplot
}
else div("No plot to display")
}
......@@ -453,7 +457,11 @@ class TreeNodeTabs() {
tab.activate
}
def isActive(safePath: SafePath) = tabs.now.filter { _.safePathTab.now == safePath }.map { _.activity }.headOption.getOrElse(Var(TreeNodeTabs.UnActive))
def isActive(safePath: SafePath) = tabs.now.filter {
_.safePathTab.now == safePath
}.map {
_.activity
}.headOption.getOrElse(Var(TreeNodeTabs.UnActive))
def unActiveAll = tabs.map {
_.foreach { t
......@@ -487,7 +495,7 @@ class TreeNodeTabs() {
}
}
def switchEditableTo(tab: TreeNodeTab, sequence: SequenceData, editableView: EditableView, filter: RowFilter, editing: Boolean, axis: (Int, Int), plotMode: PlotMode) = {
def switchEditableTo(tab: TreeNodeTab, sequence: SequenceData, editableView: EditableView, filter: RowFilter, editing: Boolean, axis: Seq[Int], plotMode: PlotMode) = {
val newTab = TreeNodeTab.editable(tab.safePathTab.now, tab.content, sequence, editableView, editing, filter, axis, plotMode)
switchTab(tab, newTab)
}
......
......@@ -3,29 +3,35 @@ package org.openmole.gui.client.tool.plot
import com.definitelyscala.plotlyjs._
import com.definitelyscala.plotlyjs.all._
import com.definitelyscala.plotlyjs.PlotlyImplicits._
import scala.scalajs.js
import scalatags.JsDom.all._
import Serie._
object ScatterPlot {
def apply(
title: String = "",
xaxisTitle: String = "",
yaxisTitle: String = "",
series: Seq[Serie],
legend: Boolean = false) = {
val plotDiv = div.render
val plotDataArray: scalajs.js.Array[PlotData] = series.map { serie
serie.copy(plotDataBuilder =
title: String = "",
serie: Serie,
legend: Boolean = false) = {
lazy val plotDiv = Plot.baseDiv
val dims = serie.values.take(2)
if (dims.length == 2) {
val plotDataArray: scalajs.js.Array[PlotData] = js.Array(
serie.plotDataBuilder
.x(dims.head.toDimension._result.values.get)
.y(dims(1).toDimension._result.values.get)
.set(plotlymode.markers)
.set(plotlytype.scatter)
)
}
val config = Config.displayModeBar(false)
Plotly.plot(plotDiv, plotDataArray, config = config)
lazy val layout = Plot.baseLayout(title)
.xaxis(plotlyaxis.title(dims.head.label))
.yaxis(plotlyaxis.title(dims(1).label))
.width(800)
Plotly.newPlot(plotDiv, plotDataArray, layout, Plot.baseConfig)
}
div(plotDiv.render).render
}
......
package org.openmole.gui.client.tool.plot
import com.definitelyscala.plotlyjs.all._
import scala.scalajs.js.JSConverters._
import com.definitelyscala.plotlyjs.{ PlotData, PlotDataBuilder, PlotMarkerBuilder }
import com.definitelyscala.plotlyjs._
case class Dim(values: Seq[String], label: String = "") {
def toDimension = Dimension.values(values.toJSArray).label(label)
}
case class Serie(
name: String = "",
x: Array[Double] = Array(),
y: Array[Double] = Array(),
dimensionSize: Int = 0,
values: Seq[Dim] = Seq(),
plotDataBuilder: PlotDataBuilder = PlotData.set(plotlymode.markers.lines),
markerBuilder: PlotMarkerBuilder = plotlymarker.set(plotlysymbol.cross))
object Serie {
implicit def serieToPlotData(serie: Serie): PlotData = serie.plotDataBuilder
.x(serie.x.toJSArray)
.y(serie.y.toJSArray)
.set(serie.markerBuilder)
.name(serie.name)
implicit def seriesToPlotDatas(series: Seq[Serie]): scalajs.js.Array[PlotData] = series.map { serieToPlotData }.toJSArray
}
\ No newline at end of file
markerBuilder: PlotMarkerBuilder = plotlymarker.set(plotlysymbol.cross),
colorScale: ColorScale = ColorScale.hot
)
\ No newline at end of file
package org.openmole.gui.client.tool.plot
import com.definitelyscala.plotlyjs._
import com.definitelyscala.plotlyjs.all._
import com.definitelyscala.plotlyjs.PlotlyImplicits._
import scala.scalajs.js.JSConverters._
import scalatags.JsDom.all._
object SplomPlot {
def apply(
title: String = "",
serie: Serie,
legend: Boolean = false) = {
lazy val plotDiv = Plot.baseDiv
val dims = serie.values
val nbDims = dims.length
if (nbDims > 1) {
val size = nbDims * (if (nbDims < 3) 200 else 150)
lazy val layout = Plot.baseLayout(title)
.width(size)
.height(size)
.dragmode("select")
.xaxis2(Plot.axis)
.yaxis2(Plot.axis)
.xaxis3(Plot.axis)
.yaxis3(Plot.axis)
.xaxis4(Plot.axis)
.yaxis4(Plot.axis)
.xaxis5(Plot.axis)
.yaxis5(Plot.axis)
.xaxis6(Plot.axis)
.yaxis6(Plot.axis)
.xaxis7(Plot.axis)
.yaxis7(Plot.axis)
.xaxis8(Plot.axis)
.yaxis8(Plot.axis)
val dimensions = dims.map {
_.toDimension._result
}.toJSArray
val colorDim = serie.dimensionSize
Plotly.newPlot(
plotDiv,
scalajs.js.Array(serie.plotDataBuilder
.set(dimensions)
.set(plotlytype.splom)
// .set(plotlymarker
// .set(plotlycolor.array((0 to serie.dimensionSize).toJSArray))
// .set(ColorScale.hot)
// )._result
),
layout,
Plot.baseConfig)
}
div(plotDiv.render).render
}
}
......@@ -3,35 +3,39 @@ package org.openmole.gui.client.tool.plot
import com.definitelyscala.plotlyjs._
import com.definitelyscala.plotlyjs.all._
import com.definitelyscala.plotlyjs.PlotlyImplicits._
import scala.scalajs.js.JSConverters._
import scala.scalajs.js
import scalatags.JsDom.all._
import Serie._
object XYPlot {
def apply(
title: String = "",
xaxisTitle: String = "",
yaxisTitle: String = "",
series: Seq[Serie],
legend: Boolean = false) = {
lazy val plotDiv = div.render
lazy val layout = Layout
.title(title)
.showlegend(legend)
.xaxis(plotlyaxis.title(xaxisTitle))
.yaxis(plotlyaxis.title(yaxisTitle))
lazy val config = Config.displayModeBar(false)
val plotDataArray: scalajs.js.Array[PlotData] = series
Plotly.newPlot(
plotDiv,
plotDataArray,
layout,
config)
title: String = "",
serie: Serie,
legend: Boolean = false) = {
lazy val plotDiv = Plot.baseDiv
val dims = serie.values.take(2)
if (dims.length == 2) {
val plotDataArray: scalajs.js.Array[PlotData] = js.Array(
serie.plotDataBuilder
.x(dims.head.toDimension._result.values.get)
.y(dims(1).toDimension._result.values.get)
)
lazy val layout = Plot.baseLayout(title)
.xaxis(plotlyaxis.title(dims.head.label))
.yaxis(plotlyaxis.title(dims(1).label))
.width(800)
Plotly.newPlot(
plotDiv,
plotDataArray,
layout, Plot.baseConfig
)
}
div(plotDiv.render).render
}
......
package org.openmole.gui.client.tool.plot
import com.definitelyscala.plotlyjs._
import com.definitelyscala.plotlyjs.PlotlyImplicits._
import scalatags.JsDom.all._
case class BasePlot(
title: String = "",
xaxisTitle: String = "",
yaxisTitle: String = "",
series: Seq[Serie],
legend: Boolean = false) {
def scatter = ScatterPlot(title, xaxisTitle, yaxisTitle, series, legend)
def line = XYPlot(title, xaxisTitle, yaxisTitle, series, legend)
title: String = "",
serie: Serie,
legend: Boolean = false) {
def scatter = ScatterPlot(title, serie, legend)
def line = XYPlot(title, serie, legend)
def splom = SplomPlot(title, serie, legend)
}
object Plot {
sealed trait PlotMode
object XYMode extends PlotMode
object ScatterMode extends PlotMode
object SplomMode extends PlotMode
def baseDiv = div.render
val baseConfig = Config
.displayModeBar(false)
.responsive(true)
val axis = Axis.zeroline(false).showline(false)
def baseLayout(title: String) = Layout
.title(title)
.showlegend(false)
.autosize(true)
.xaxis(axis)
.yaxis(axis)
.margin(com.definitelyscala.plotlyjs.Margin.t(0)._result)
def apply(
title: String = "",
xaxisTitle: String = "",
yaxisTitle: String = "",
series: Seq[Serie] = Seq(),
legend: Boolean = false,
plotMode: PlotMode) = {
val bpl = BasePlot(title, xaxisTitle, yaxisTitle, series, legend)
title: String = "",
serie: Serie = Serie(),
legend: Boolean = false,
plotMode: PlotMode) = {
val bpl = BasePlot(title, serie, legend)
plotMode match {
case XYMode bpl.line
case ScatterMode bpl.scatter
case SplomMode bpl.splom
}
}
}
\ No newline at end of file
......@@ -43,7 +43,7 @@ object Libraries {
lazy val sourcecodeJS = libraryDependencies += "com.lihaoyi" %%% "sourcecode" % sourcecodeVersion
lazy val scalajsMarked = libraryDependencies += "com.github.karasiq" %%% "scalajs-marked" % "1.0.2"
lazy val htmlparser2 = libraryDependencies += "com.definitelyscala" %%% "scala-js-htmlparser2" % "1.0.2"
lazy val plotlyJS = libraryDependencies += "com.definitelyscala" %%% "scala-js-plotlyjs" % "1.1.4"
lazy val plotlyJS = libraryDependencies += "com.definitelyscala" %%% "scala-js-plotlyjs" % "1.1.7"
lazy val scalatest = "org.scalatest" %% "scalatest" % "3.0.1" % "test"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment