aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2012-11-01 11:46:54 +0100
committerJakob Odersky <jodersky@gmail.com>2012-11-01 11:46:54 +0100
commitcde13945605fb9f543cfb960728c5c7d48d6f3f5 (patch)
tree6bf8055115061ac54cd24083a178abbb63af914a
parent604c0af33343169f9d19e6e3f350c8f10a4d577f (diff)
parent9e226e73e6e145e6a45dc580d3bbba9cee6a3c9e (diff)
downloadscalam-cde13945605fb9f543cfb960728c5c7d48d6f3f5.tar.gz
scalam-cde13945605fb9f543cfb960728c5c7d48d6f3f5.tar.bz2
scalam-cde13945605fb9f543cfb960728c5c7d48d6f3f5.zip
Merge branch 'new-plot'
-rw-r--r--src/main/scala/scalam/plotting/DataSet.scala2
-rw-r--r--src/main/scala/scalam/plotting/Plot.scala148
-rw-r--r--src/main/scala/scalam/plotting/Plotter.scala2
-rw-r--r--src/main/scala/scalam/plotting/styles/styles.scala4
4 files changed, 97 insertions, 59 deletions
diff --git a/src/main/scala/scalam/plotting/DataSet.scala b/src/main/scala/scalam/plotting/DataSet.scala
index 07813ef..768189c 100644
--- a/src/main/scala/scalam/plotting/DataSet.scala
+++ b/src/main/scala/scalam/plotting/DataSet.scala
@@ -4,7 +4,7 @@ import scalax.file.Path
import breeze.linalg.{ Vector, DenseVector }
case class DataSet(points: Seq[(Double, Double)], label: String) {
- val name = label
+ val name = scalam.m.ast.Identifier(label).toValid.name
lazy val (xs, ys) = points.unzip
def save(path: Path) = {
diff --git a/src/main/scala/scalam/plotting/Plot.scala b/src/main/scala/scalam/plotting/Plot.scala
index 5494ace..3c96a22 100644
--- a/src/main/scala/scalam/plotting/Plot.scala
+++ b/src/main/scala/scalam/plotting/Plot.scala
@@ -4,6 +4,8 @@ import scala.sys.process._
import scalam.m.ast._
import scalax.file.Path
import scalam.plotting.styles._
+import scala.collection.mutable.Map
+import scala.collection.mutable.ListBuffer
class Plot(
val dataSets: Seq[DataSet],
@@ -13,66 +15,76 @@ class Plot(
grid: Boolean = true,
legend: Boolean = true,
fontSize: Int = 10,
- styles: Seq[Style[_]] = Seq(),
+ styles: Seq[Style[StyleElement]] = Seq(),
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)))
+ 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-SNAPSHOT"),
+ DoubleComment(df.format(now)))
}
- 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: _*)
+ class RichDataSet(val id: Identifier, val localPath: Path, val underlying: DataSet)
+
+ def richDataSets = {
+ val knownIds = Map[Identifier, Int]()
+ def toRich(dataSet: DataSet) = {
+ val firstId = Identifier(dataSet.name)
+ val finalId = knownIds.get(firstId) match {
+ case None => { //firstId is not already used
+ knownIds += (firstId -> 1)
+ firstId
+ }
+ case Some(prev) => { // firstId is already in use
+ knownIds(firstId) = prev + 1
+ Identifier(firstId.name + "_" + prev)
+ }
+ }
+ new RichDataSet(finalId, Path("data") / finalId.name, dataSet)
}
- 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
+ dataSets.map(toRich(_))
}
- private def preamble = {
- val df = new java.text.SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss")
- val now = (new java.util.Date(System.currentTimeMillis()))
+ def resolveStyles: (Seq[Root], Seq[DataSet => StyleElement]) = {
+ val setupAndStyles = styles.map(_.apply(dataSets))
+ val setup = setupAndStyles.map(_._1).flatten
+ val styleMaps = setupAndStyles.map(_._2)
+ (setup, styleMaps)
+ }
+
+ def roots: Seq[Root] = {
+ import Plot._
+ val richDataSets = this.richDataSets
+
+ val (setup, styleMappings) = resolveStyles
+
+ val loads = richDataSets.map(r =>
+ m.load(r.id, r.localPath) withComment SimpleComment(r.underlying.label))
+
+ val plots = richDataSets.map { r =>
+ val styleElements = styleMappings.map(_.apply(r.underlying))
+ m.plot(r.id, styleElements)
+ }
- Seq(DoubleComment("Generated by scalam, v1.0-new"), DoubleComment(df.format(now)))
+ val roots = new ListBuffer[Root]
+ roots ++= preamble
+ roots ++= loads
+ roots += m.newFigure
+ roots += m.hold(true)
+ roots += m.grid(this.grid)
+ roots += m.title(this.title)
+ roots += m.xLabel(this.xLabel)
+ roots += m.yLabel(this.yLabel)
+ roots += m.fontSize(this.fontSize)
+ roots ++= plots
+ roots += m.legend(dataSets)
+
+ roots.toList
}
def save() = {
@@ -99,18 +111,44 @@ class Plot(
object Plot {
private[this] var counter = -1
private def next = { counter += 1; counter }
-
-
- private def randomDataSet(length: Int) = {
+
+ 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")
+
+ private object m {
+ import scalam.m.ast._
+
+ val On = StringLiteral("on")
+ val Off = StringLiteral("off")
+
+ def newFigure = 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 load(id: Identifier, path: Path) = Assign(id, Function(Identifier("load"), StringLiteral(path.path)))
+ def plot(dataSet: Identifier, styleElements: Seq[StyleElement]) = {
+ val plot = Identifier("plot")
+ val params = Seq(
+ IndexMatrix(dataSet, SliceLiteral, IntLiteral(1)),
+ IndexMatrix(dataSet, SliceLiteral, IntLiteral(2))) ++
+ styleElements.flatMap(e => Seq(e.name, e.expression))
+ Function(plot, params: _*)
+ }
+ def legend(dataSets: Seq[DataSet]) =
+ Function(Identifier("legend"), dataSets.map(d => StringLiteral(d.label)): _*)
+ }
+
} \ No newline at end of file
diff --git a/src/main/scala/scalam/plotting/Plotter.scala b/src/main/scala/scalam/plotting/Plotter.scala
index 341b976..6d240d9 100644
--- a/src/main/scala/scalam/plotting/Plotter.scala
+++ b/src/main/scala/scalam/plotting/Plotter.scala
@@ -13,7 +13,7 @@ trait Plotter {
lazy val interpreter: MInterpreter = new MatlabInterpreter(pwd)
- def plot(dataSets: Seq[DataSet], title: String, x: String, y: String, grid: Boolean = true, legend: Boolean = true)(implicit styles: Seq[Style[_]] = defaultStyles, fontSize: FontSize = defaultFontSize) = {
+ def plot(dataSets: Seq[DataSet], title: String, x: String, y: String, grid: Boolean = true, legend: Boolean = true)(implicit styles: Seq[Style[StyleElement]] = defaultStyles, fontSize: FontSize = defaultFontSize) = {
val p = new Plot(dataSets, title, x, y, grid, legend, styles = styles, fontSize = fontSize.fontSize)
p.save()
val s = Function(Identifier("run"), StringLiteral((p.directory / p.localPlotFile).path))
diff --git a/src/main/scala/scalam/plotting/styles/styles.scala b/src/main/scala/scalam/plotting/styles/styles.scala
index 705b88b..e7d59fc 100644
--- a/src/main/scala/scalam/plotting/styles/styles.scala
+++ b/src/main/scala/scalam/plotting/styles/styles.scala
@@ -6,13 +6,13 @@ import scalam.m.ast._
trait StyleElement {
//command line option
- def name: StringLiteral
+ def name: Expression
//expression
def expression: Expression
}
trait Style[+S <: StyleElement] {
- def apply(dataSets: Seq[DataSet]): Tuple2[Seq[Statement], DataSet => S]
+ def apply(dataSets: Seq[DataSet]): Tuple2[Seq[Root], DataSet => S]
}
case class Uniform[S <: StyleElement](element: S) extends Style[S] {