aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scalam/plotting/Plot.scala
blob: dede53050ffdfc3a3b176a06b8cc5f982f013cd0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package scalam.plotting

import scala.sys.process._
import scalam.m.ast._
import scalax.file.Path
import scalam.plotting.styles._

class Plot(
  val dataSets: Seq[DataSet],
  title: String,
  xLabel: String,
  yLabel: String,
  grid: Boolean = true,
  legend: Boolean = true,
  fontSize: Int = 10,
  styles: Seq[Style[_]] = Seq(),
  name: String = "plot" + Plot.next) {

  private case class RichDataSet(underlying: DataSet, localPath: Path, id: Identifier)
  private val richDataSets = dataSets.zipWithIndex.map {
    case (d, i) => RichDataSet(d, Path("data") / i.toString, Identifier("data" + (i + 1)))
  }

  lazy val roots: List[Root] = {
    def loadData(dataSet: RichDataSet) =
      Assign(dataSet.id, Function(Identifier("load"), StringLiteral(dataSet.localPath.path))) withComment SimpleComment(dataSet.id.m)
    
    val (initial: Seq[Seq[Statement]], styleMaps: Iterable[DataSet => StyleElement]) = styles.map(_.apply(dataSets)).unzip
    
    val figureId = Identifier("fh")
    val on = StringLiteral("on")
    val off = StringLiteral("off")
    def newFigure(figureId: Identifier) = Assign(figureId, Function(Identifier("figure")))
    def hold(b: Boolean) = Function(Identifier("hold"), if (b) on else off)
    def grid(show: Boolean) = Function(Identifier("grid"), if (show) on else off)
    def title(s: String) = Function(Identifier("title"), StringLiteral(s))
    def xLabel(s: String) = Function(Identifier("xlabel"), StringLiteral(s))
    def yLabel(s: String) = Function(Identifier("ylabel"), StringLiteral(s))
    def fontSize(size: Int) = Function(Identifier("set"), Variable(Identifier("gca")), StringLiteral("fontsize"), IntLiteral(size))
    def plot(dataSet: RichDataSet) = {
      val plot = Identifier("plot")
      val styleParams = styleMaps.flatMap(styleMap => {val style = styleMap.apply(dataSet.underlying); Seq(style.name, style.expression)})
      val params = Seq(
          IndexMatrix(dataSet.id, SliceLiteral, IntLiteral(1)),
          IndexMatrix(dataSet.id, SliceLiteral, IntLiteral(2))) ++
          styleParams
     
          Function(plot, params: _*)
    }
    def legend(dataSets: Seq[DataSet]) =
     Function(Identifier("legend"), (for (d <- dataSets) yield StringLiteral(d.label)): _*) :: Nil

    val commands = new scala.collection.mutable.ListBuffer[Root]
    commands ++= (for (d <- richDataSets) yield loadData(d))
    commands ++= initial.flatten
    commands += newFigure(figureId)
    commands += hold(true)
    commands += grid(this.grid)
    commands += fontSize(this.fontSize)
    commands += title(this.title)
    commands += xLabel(this.xLabel)
    commands += yLabel(this.yLabel)
    commands ++= (for (d <- richDataSets) yield plot(d))
    if (this.legend) commands ++= legend(dataSets)
    commands.toList
  }

  private def preamble = {
    val df = new java.text.SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss")
    val now = (new java.util.Date(System.currentTimeMillis()))

    Seq(DoubleComment("Generated by scalam, v1.0-new"), DoubleComment(df.format(now))) 
  }


}

object Plot {
  private[this] var counter = -1
  private def next = { counter += 1; counter }
  
  
   private def randomDataSet(length: Int) = {
    import scala.util.Random
    val data = for (i <- 0 until length) yield (i * 1.0, Random.nextDouble() * 10)
    val name = "a"
    new DataSet(data, name)
  } 
  
  val ds = Seq(
    new DataSet(Seq((0.0, 1.0), (1.0, 1.0), (2.0, 1.0), (3.0, 0.0), (4.0, 1.0), (5.0, 1.0)), "temperature"),
    new DataSet(Seq((0.0, 0.0), (1.0, 1.0), (2.0, 4.0), (3.0, 9.0)), """\alpha""")) ++ (0 to 10).map(_ => randomDataSet(10))
  
  val test = new Plot(ds, "title", "x", "y")
}