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