✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.

3D Surface plots in Scala

How to create surface plots in Plotly with Scala.


val xs = (-3.0 to 3.0 by 0.1).toVector
val ys = (-3.0 to 3.0 by 0.1).toVector

def gaussian2D(x: Double, y: Double) = Math.exp(-x*x - y*y)
val zs = xs.map { x => ys.map { y => gaussian2D(x, y) } }

val p = ThreeDPlot().withSurface(xs, ys, zs)

draw(p, "gaussian-surfaces")
/*
This example requires the `csv` package. To include it, add the
following lines to your `build.sbt file

libraryDependencies += "com.github.tototoshi" %% "scala-csv" % "1.3.1"
*/

import scala.io.Source
import com.github.tototoshi.csv._
import co.theasi.plotly._

object MountBruno extends App {

  val dataURL = "https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv"
  val reader = CSVReader.open(Source.fromURL(dataURL))

  val firstRow :: dataRows = reader.all

  val data = dataRows.map {
    case index :: values => values
    case _ => throw new IllegalStateException("Empty file")
  }

  val axisOptions = AxisOptions().noGrid.noLine.noZeroLine.noTickLabels.title("")

  val p = ThreeDPlot()
    .withSurface(data, SurfaceOptions().colorscale("Earth").noScale)
    .xAxisOptions(axisOptions)
    .yAxisOptions(axisOptions)
    .zAxisOptions(axisOptions)

  val figure = Figure()
    .plot(p)
    .margins(0, 0, 0, 0)

  val outputFile = draw(figure, "Mt Bruno")
  println(outputFile)
}
// z data
val z1 = Vector(
  Vector(8.83, 8.89, 8.81, 8.87, 8.9, 8.87),
  Vector(8.89, 8.94, 8.85, 8.94, 8.96, 8.92),
  Vector(8.84, 8.9, 8.82, 8.92, 8.93, 8.91),
  Vector(8.79, 8.85, 8.79, 8.9, 8.94, 8.92),
  Vector(8.79, 8.88, 8.81, 8.9, 8.95, 8.92),
  Vector(8.8, 8.82, 8.78, 8.91, 8.94, 8.92),
  Vector(8.75, 8.78, 8.77, 8.91, 8.95, 8.92),
  Vector(8.8, 8.8, 8.77, 8.91, 8.95, 8.94),
  Vector(8.74, 8.81, 8.76, 8.93, 8.98, 8.99),
  Vector(8.89, 8.99, 8.92, 9.1, 9.13, 9.11),
  Vector(8.97, 8.97, 8.91, 9.09, 9.11, 9.11),
  Vector(9.04, 9.08, 9.05, 9.25, 9.28, 9.27),
  Vector(9, 9.01, 9, 9.2, 9.23, 9.2),
  Vector(8.99, 8.99, 8.98, 9.18, 9.2, 9.19),
  Vector(8.93, 8.97, 8.97, 9.18, 9.2, 9.18)
)

val z2 = z1.map { _.map { _ + 1.0 } }
val z3 = z1.map { _.map { _ - 1.0 } }

val p = ThreeDPlot()
  .withSurface(z1)
  .withSurface(z2, SurfaceOptions().opacity(0.9).noScale)
  .withSurface(z3, SurfaceOptions().opacity(0.9).noScale)

draw(p, "multiple-surfaces")