diff --git a/pom.xml b/pom.xml
index 68457b1..7a70499 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,7 +32,7 @@
1.8
1.8
UTF-8
- 2.11.7
+ 2.12.2
diff --git a/src/main/scala/org/sameersingh/scalaplot/Label.scala b/src/main/scala/org/sameersingh/scalaplot/Label.scala
new file mode 100644
index 0000000..24e3f37
--- /dev/null
+++ b/src/main/scala/org/sameersingh/scalaplot/Label.scala
@@ -0,0 +1,10 @@
+package org.sameersingh.scalaplot
+
+/**
+ * Label class - consists of text and coordinates
+ *
+ * Created by vpatryshev on 6/5/17.
+ */
+case class Label(text: String, x: Double, y: Double) {
+ def gpl = s"$text,$x,$y"
+}
diff --git a/src/main/scala/org/sameersingh/scalaplot/LabelChart.scala b/src/main/scala/org/sameersingh/scalaplot/LabelChart.scala
new file mode 100644
index 0000000..33e716a
--- /dev/null
+++ b/src/main/scala/org/sameersingh/scalaplot/LabelChart.scala
@@ -0,0 +1,13 @@
+package org.sameersingh.scalaplot
+
+/**
+ * A chart consisting of a cloud of labels
+ * Created by vpatryshev on 6/5/17.
+ */
+class LabelChart(chartTitle: Option[String], val data: Iterable[Label],
+ val x: NumericAxis = new NumericAxis,
+ val y: NumericAxis = new NumericAxis) extends Chart {
+
+ def this(title: String, data: Iterable[Label]) = this(Some(title), data)
+}
+
diff --git a/src/main/scala/org/sameersingh/scalaplot/gnuplot/GnuplotPlotter.scala b/src/main/scala/org/sameersingh/scalaplot/gnuplot/GnuplotPlotter.scala
index c807589..c9e9bce 100644
--- a/src/main/scala/org/sameersingh/scalaplot/gnuplot/GnuplotPlotter.scala
+++ b/src/main/scala/org/sameersingh/scalaplot/gnuplot/GnuplotPlotter.scala
@@ -273,13 +273,29 @@ class GnuplotPlotter(chart: Chart) extends Plotter(chart) {
def postPlotFileXYSeries(series: FileXYSeries) {}
+ def plotLabelChart(chart: LabelChart) = {
+ lines +=
+ """# LabelChart settings
+ |set termoption enhanced
+ |set encoding utf8
+ |unset xtics
+ |unset ytics
+ |unset key
+ |set border 0
+ |set size square
+ |set datafile separator ","
+ |plot '-' using 2:3:1 with labels
+ """.stripMargin
+
+ for (label <- chart.data) lines += label.gpl
+ }
+
def writeScriptFile(directory: String, filenamePrefix: String, terminal: String,
filenameSuffix: String, stdout: Boolean = false, defaultTerminal: String = "dumb") {
// write the description
- assert(new File(directory).isDirectory, directory + " should be a directory")
- assert(directory.endsWith("/"), directory + " should end with a /")
+ assert(new File(directory).isDirectory, s"$directory should be a directory - current is ${new File(".").getCanonicalPath}")
reset
- this.directory = directory
+ this.directory = if (directory.endsWith("/")) directory else (directory+"/")
filename = filenamePrefix
plotChart(chart, terminal)
lines += "set terminal %s" format (terminal)
@@ -288,13 +304,14 @@ class GnuplotPlotter(chart: Chart) extends Plotter(chart) {
chart match {
case xyc: XYChart => plotXYChart(xyc)
case bc: BarChart => plotBarChart(bc)
+ case lc: LabelChart => plotLabelChart(lc)
}
lines += "unset output"
lines += "# Wrapup"
lines += "set terminal %s" format (defaultTerminal)
lines += "refresh"
- val scriptFile = directory + filenamePrefix + ".gpl"
+ val scriptFile = this.directory + filenamePrefix + ".gpl"
val writer = new PrintWriter(scriptFile)
for (line <- lines) {
writer.println(line)
@@ -321,7 +338,7 @@ class GnuplotPlotter(chart: Chart) extends Plotter(chart) {
override def svg(directory: String, filenamePrefix: String): String = {
if (chart.monochrome) println("Warning: Monochrome ignored.")
val sizeString = if (chart.size.isDefined) "size %f,%f" format(chart.size.get._1, chart.size.get._2) else ""
- val terminal = "svg enhanced linewidth 3.0 %s" format (sizeString)
+ val terminal = "svg enhanced linewidth 3.0 %s" format sizeString
writeScriptFile(directory, filenamePrefix, terminal, "svg", true, "unknown")
runGnuplot(directory, filenamePrefix)
}
@@ -346,7 +363,7 @@ class GnuplotPlotter(chart: Chart) extends Plotter(chart) {
val terminal = "canvas enhanced name\"%s\"" format (filenamePrefix)
writeScriptFile(directory, filenamePrefix, terminal, "js")
runGnuplot(directory, filenamePrefix)
- htmlWrap(directory, filenamePrefix)
+ htmlWrap(filenamePrefix)
}
def js2(directory: String, filenamePrefix: String): String = {
@@ -372,10 +389,10 @@ class GnuplotPlotter(chart: Chart) extends Plotter(chart) {
}
writer.close()
val str = runGnuplot(directory, filenamePrefix)
- htmlWrap(directory, filenamePrefix)
+ htmlWrap(filenamePrefix)
}
- private def htmlWrap(directory: String, filenamePrefix: String, jsDir: String = "/usr/local/Cellar/gnuplot/4.6.5/share/gnuplot/4.6/js") = {
+ private def htmlWrap(filenamePrefix: String, jsDir: String = "/usr/local/Cellar/gnuplot/4.6.5/share/gnuplot/4.6/js") = {
"""
|
|
@@ -399,12 +416,10 @@ class GnuplotPlotter(chart: Chart) extends Plotter(chart) {
val cmdLine = "gnuplot " + filenamePrefix + ".gpl"
try {
- val p = Runtime.getRuntime().exec(cmdLine, Array.empty[String], new File(directory))
- val input = new BufferedReader(new InputStreamReader(p.getInputStream()))
- while (({
- line = input.readLine();
- line
- }) != null) {
+ println(s"${new File(directory).getCanonicalPath}> $cmdLine")
+ val p = Runtime.getRuntime.exec(cmdLine, Array.empty[String], new File(directory))
+ val input = new BufferedReader(new InputStreamReader(p.getInputStream))
+ while (input.readLine() != null) {
output += (line + '\n')
}
input.close()
diff --git a/src/test/resources/cities.dat b/src/test/resources/cities.dat
new file mode 100644
index 0000000..f56d2c5
--- /dev/null
+++ b/src/test/resources/cities.dat
@@ -0,0 +1,104 @@
+Paris France 2110420 48.86° 2.34°
+Marseille France 820729 43.31° 5.37°
+Lyon France 443859 45.76° 4.83°
+Toulouse France 411768 43.62° 1.45°
+Nice France 331958 43.70° 7.27°
+Nantes France 282251 47.23° -1.57°
+Strasbourg France 272599 48.58° 7.76°
+Montpellier France 230663 43.61° 3.87°
+Bordeaux France 216978 44.84° -0.58°
+Rennes France 212616 48.11° -1.68°
+Le Havre France 189329 49.50° 0.12°
+Reims France 184594 49.25° 4.03°
+Lille France 180547 50.64° 3.07°
+"Saint-Étienne" France 170734 45.43° 4.39°
+Toulon France 161160 43.13° 5.92°
+Grenoble France 155621 45.19° 5.72°
+Angers France 153340 47.48° -0.54°
+Brest France 151526 48.39° -4.50°
+Le Mans France 148654 48.00° 0.20°
+Dijon France 147153 47.33° 5.03°
+Aix-en-Provence France 138060 43.53° 5.44°
+Clermont-Ferrand France 137274 45.78° 3.08°
+"Nîmes" France 136424 43.84° 4.35°
+Amiens France 135768 49.90° 2.30°
+Tours France 133538 47.38° 0.69°
+Limoges France 132299 45.83° 1.25°
+Metz France 125010 49.12° 6.18°
+Villeurbanne France 121852 45.77° 4.88°
+"Besançon" France 118152 47.24° 6.02°
+Caen France 116259 49.19° -0.36°
+"Orléans" France 112327 47.90° 1.90°
+Mulhouse France 111307 47.76° 7.34°
+Perpignan France 110149 42.70° 2.89°
+Boulogne-Billancourt France 108079 48.83° 2.24°
+Rouen France 105310 49.44° 1.08°
+Nancy France 103196 48.69° 6.17°
+Avignon France 86865 43.96° 4.81°
+Nanterre France 85753 48.90° 2.20°
+Poitiers France 85406 46.58° 0.34°
+Versailles France 82101 48.81° 2.14°
+"Créteil" France 80168 48.79° 2.45°
+Pau France 79449 43.30° -0.39°
+La Rochelle France 78854 46.17° -1.18°
+Bourges France 70100 47.08° 2.39°
+Colmar France 65695 48.08° 7.36°
+Valence France 65016 44.94° 4.89°
+Quimper France 64038 47.99° -4.11°
+Troyes France 60353 48.30° 4.08°
+"Chambéry" France 56022 45.58° 5.91°
+Niort France 55868 46.32° -0.47°
+"Charleville-Mézières" France 55343 49.75° 4.73°
+Beauvais France 54116 49.43° 2.09°
+Vannes France 52436 47.66° -2.76°
+Montauban France 51839 44.02° 1.35°
+Laval France 51504 48.07° -0.78°
+"Évreux" France 50882 49.03° 1.14°
+La Roche-sur-Yon France 50608 46.67° -1.44°
+Belfort France 50109 47.65° 6.85°
+Annecy France 49903 45.91° 6.12°
+Blois France 49207 47.59° 1.32°
+"Châteauroux" France 48724 46.81° 1.70°
+Ajaccio France 47914 41.93° 8.73°
+"Évry" France 46928 48.64° 2.44°
+"Châlons-en-Champagne" France 46678 48.97° 4.36°
+Albi France 46540 43.93° 2.15°
+Tarbes France 46048 43.24° 0.08°
+Carcassonne France 44311 43.22° 2.34°
+Saint-Brieuc France 44081 48.52° -2.77°
+"Angoulême" France 42995 45.66° 0.15°
+Bobigny France 42506 48.91° 2.44°
+Bourg-en-Bresse France 41174 46.21° 5.21°
+Bastia France 41160 42.71° 9.46°
+Arras France 40529 50.29° 2.78°
+Nevers France 39648 47.00° 3.15°
+Chartres France 39114 48.46° 1.48°
+Auxerre France 37581 47.81° 3.56°
+Gap France 36131 44.57° 6.08°
+Melun France 35044 48.54° 2.65°
+"Épinal" France 35040 48.18° 6.44°
+"Mâcon" France 33624 46.31° 4.81°
+Mont-de-Marsan France 30684 43.90° -0.51°
+Agen France 30554 44.20° 0.62°
+"Périgueux" France 29980 45.18° 0.71°
+Aurillac France 29402 44.92° 2.43°
+"Alençon" France 28628 48.44° 0.09°
+Pontoise France 26610 49.05° 2.09°
+Laon France 25925 49.58° 3.63°
+Chaumont France 25086 48.11° 5.14°
+Rodez France 23407 44.36° 2.57°
+Auch France 21962 43.65° 0.58°
+Moulins France 21241 46.57° 3.33°
+Le Puy-en-Velay France 20783 45.05° 3.88°
+Cahors France 20645 44.46° 1.44°
+"Saint-Lô" France 19703 49.13° -1.11°
+Lons-le-Saunier France 18169 46.68° 5.53°
+Vesoul France 17128 47.63° 6.15°
+Bar-le-Duc France 16755 48.78° 5.17°
+Digne-les-Bains France 15941 44.10° 6.23°
+Tulle France 15206 45.26° 1.76°
+"Guéret" France 13858 46.17° 1.87°
+Mende France 11915 44.52° 3.48°
+Privas France 9165 44.73° 4.58°
+Foix France 9135 42.97° 1.60°
+
diff --git a/src/test/scala/org/sameersingh/scalaplot/ExampleLabelTest.scala b/src/test/scala/org/sameersingh/scalaplot/ExampleLabelTest.scala
new file mode 100644
index 0000000..e336b97
--- /dev/null
+++ b/src/test/scala/org/sameersingh/scalaplot/ExampleLabelTest.scala
@@ -0,0 +1,69 @@
+package org.sameersingh.scalaplot
+
+import java.io.File
+
+import org.junit._
+import org.sameersingh.scalaplot.Implicits.{output, xyChart}
+import org.sameersingh.scalaplot.Style._
+import org.sameersingh.scalaplot.gnuplot.GnuplotPlotter
+
+import scala.io.Source
+import scala.language.postfixOps
+
+/**
+ * Examples that demonstrate how to use the library. Not really tests.
+ * @author sameer
+ */
+@Test
+class ExampleLabelTest {
+
+ @Test
+ def testLabelsSimple(): Unit = {
+ val cities: Iterable[Label] = readCities
+
+ val chart = new LabelChart("France", cities)
+
+ val folder = java.io.File.createTempFile("labelsample", "pdf")
+ folder.delete()
+ folder.mkdir()
+ val folderpath = folder.getCanonicalPath
+ println(folderpath)
+
+ val gpl = new GnuplotPlotter(chart)
+ println(gpl.string(folderpath, "plot_string"))
+ gpl.js(folderpath, "plot_js")
+ gpl.svg(folderpath, "plot_svg")
+ gpl.html(folderpath, "plot_html")
+ gpl.pdf(folderpath, "plot_pdf")
+ gpl.png(folderpath, "plot_png")
+
+/*
+
+ */
+ }
+
+ @Test
+ def testLabelsPNG(): Unit = {
+ import org.sameersingh.scalaplot.Implicits._
+
+ val cities: Iterable[Label] = readCities
+
+ val chart = new LabelChart("France", cities)
+
+ val folder = java.io.File.createTempFile("labelsample", "pdf")
+ folder.delete()
+ folder.mkdir()
+ val folderpath = folder.getCanonicalPath
+ println(folderpath)
+
+ println(output(PNG(folder.getPath, "cities"), chart))
+ }
+
+ private def readCities: Iterable[Label] = {
+ val Format = "(.+)\\t(\\w+)\\t(\\w+)\\t([^°]+)°\\t([^°]+)°".r
+
+ Source.fromResource("cities.dat").getLines collect {
+ case Format(name, _, size, lat, lon) => Label(name, lat.toDouble, lon.toDouble)
+ } toList
+ }
+}
diff --git a/src/test/scala/org/sameersingh/scalaplot/ExampleXYTest.scala b/src/test/scala/org/sameersingh/scalaplot/ExampleXYTest.scala
index 071dba3..6769fac 100644
--- a/src/test/scala/org/sameersingh/scalaplot/ExampleXYTest.scala
+++ b/src/test/scala/org/sameersingh/scalaplot/ExampleXYTest.scala
@@ -1,5 +1,8 @@
package org.sameersingh.scalaplot
+import java.io.File
+
+import language.postfixOps
import gnuplot.GnuplotPlotter
import jfreegraph.JFGraphPlotter
import org.junit._
@@ -151,6 +154,8 @@ class ExampleXYTest {
import org.sameersingh.scalaplot.Implicits._
val x = 0.0 until 10.0 by 0.01
val rnd = new scala.util.Random(0)
- println(output(PNG("docs/img/", "scatter"), xyChart(x -> Seq(Y(x, style = XYPlotStyle.Lines), Y(x.map(_ + rnd.nextDouble - 0.5), style = XYPlotStyle.Dots)))))
+ val folder = new File("doc/img/")
+ folder.mkdirs()
+ println(output(PNG(folder.getPath, "scatter"), xyChart(x -> Seq(Y(x, style = XYPlotStyle.Lines), Y(x.map(_ + rnd.nextDouble - 0.5), style = XYPlotStyle.Dots)))))
}
}