aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scalam/plotting/Plot.scala
blob: 1a92f79d404a58b9ef968a117c5c188351de3c69 (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
96
97
98
99
100
101
102
103
104
105
106
107
package scalam.plotting

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

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

  val directory = Path(name)
  val localPlotFile = Path("results.m")

  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)))
  }

  private val colors = colorScheme(dataSets)

  lazy val statements: List[Statement] = {
    def loadData(dataSet: RichDataSet) = Assign(dataSet.id, Function(Identifier("load"), StringLiteral(dataSet.localPath.path)))
    def initialColor(ds: Seq[DataSet]) = colorScheme match {
      case predefined: MColorScheme => predefined.initial(ds) :: Nil
      case _ => Nil
    }
    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) = Evaluate(Function(Identifier("hold"), if (b) on else off))
    def grid(show: Boolean) = Evaluate(Function(Identifier("grid"), if (show) on else off))
    def title(s: String) = Evaluate(Function(Identifier("title"), StringLiteral(s)))
    def xLabel(s: String) = Evaluate(Function(Identifier("xlabel"), StringLiteral(s)))
    def yLabel(s: String) = Evaluate(Function(Identifier("ylabel"), StringLiteral(s)))
    def fontSize(size: Int) = Evaluate(Function(Identifier("set"), Variable(Identifier("gca")), StringLiteral("fontsize"), IntLiteral(size)))
    def plot(dataSet: RichDataSet) =
      Evaluate(
        Function(
          Identifier("plot"),
          IndexMatrix(dataSet.id, SliceLiteral, IntLiteral(1)),
          IndexMatrix(dataSet.id, SliceLiteral, IntLiteral(2)),
          StringLiteral("color"),
          colors(dataSet.underlying).expression))
    def legend(dataSets: Seq[DataSet]) =
      Evaluate(Function(Identifier("legend"), (for (d <- dataSets) yield StringLiteral(d.name)): _*)) :: Nil
    def wait(figureId: Identifier) = List(Evaluate(Function(Identifier("waitfor"), Variable(figureId))))

    val commands = new scala.collection.mutable.ListBuffer[Statement]
    commands ++= (for (d <- richDataSets) yield loadData(d))
    commands ++= initialColor(richDataSets.map(_.underlying))
    commands += newFigure(figureId)
    commands += hold(true)
    commands += grid(this.grid)
    commands += title(this.title)
    commands += xLabel(this.xLabel)
    commands += yLabel(this.yLabel)
    commands += fontSize(this.fontSize)
    commands ++= (for (d <- richDataSets) yield plot(d))
    if (this.legend) commands ++= legend(dataSets)
    commands ++= wait(figureId)
    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()))

    "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" +
      "% Generated by scalam, v1.0 %\n" +
      "% " + df.format(now) + "  %\n" +
      "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
  }

  def save() = {
    for (d <- richDataSets) d.underlying.save(directory / d.localPath)

    val plotFile = (directory / localPlotFile)
    plotFile.createFile(createParents = true, failIfExists = false)
    for (processor <- plotFile.outputProcessor; out = processor.asOutput) {
      out.write(preamble)
      for (s <- statements) out.write(s.m + "\n")
    }

  }

  def run() = {
    Process(
      "matlab -nodesktop -nosplash -r " + localPlotFile.path.takeWhile(_ != '.'),
      directory.fileOption,
      "" -> "") #> (directory / "log.txt").fileOption.get run
  }

}

object Plot {
  private[this] var counter = -1
  private def next = { counter += 1; counter }
}