Create Veusz charts in Scala. The combination of this API and Vuesz allows to
- quickly create various types of plots in Scala,
- open them in the Veusz editor to try out different layouts and styles and then to
- adjust the settings in the source code according to the UI.
It is useful for the creation of static scientific plots, if render time is not a key requiement (due to the execution of an external program).
-
Install Veusz
To be able to export plots as Image or PDF, the directory of the Veusz binare needs to be in the path variable.
-
Include the dependency requirements into the build.sbt:
libraryDependencies += "de.dreambeam" %% "scalaveusz" % "0.4.8" // version according to Maven Central Badge in the top of this page
Scala 2.12 and 2.13 are currently supported.
-
Create an Example:
import de.dreambeam.veusz._ object Veusztest extends App { // XY Plots use 2 one-dimensional datasets val xData = (1.0 to 10.0 by 0.5).toVector val yLinear = xData.map (_ * 1.25) val ySin = xData.map (2 * Math.sin(_) + 5) // create a linear XY Point Plot with Lines val xyLinearPlot = GraphItems.XY(xData, yLinear) xyLinearPlot.config.plotLine.color = "darkblue" xyLinearPlot.config.markerFill.color = "blue" // create a sinus XY Point Plot with Lines val xySinusPlot = GraphItems.XY(xData, ySin) xySinusPlot.config.plotLine.color = "darkred" xySinusPlot.config.markerFill.color = "red" // put both XY Plots into a Graph val graph = PageItems.Graph(xyLinearPlot, xySinusPlot) graph.axis(0).label = "X Axis" //Axis can also be defined in the Graph constructor graph.axis(1).label = "Y Axis" //More than just two axis is possible graph.openInVeusz("newTest") }
-
This will result in the following Veusz project:
For further examples see scalaveusz-examples
The Veusz API should be accassible through a single import of de.dreambeam.veusz._
. Items can be accessed using the V
shortcut object and the autocomplete features of your prefered IDE.
It is possible to either browse the document structure to find a prefered Item
.. or to access the Items directly
The following figure shows the possible structure of a Veusz document.
Per definition, each chart is in a graph which is in a page (or a grid within a page), which is in a document.
val xy = V.GraphItems.XY(xData, yLinear)
val graph = V.PageItems.Graph(xy) // takes multiples Graphs
val page = V.DocumentItems.Page(graph) // takes a single graph or a grid
val document = V.Document(page) // takes multiple pages
To reduce unnecessary boilerplate code, Scalaveusz offers autowrapping. For example, If you put a chart into a document the plot would then automatically be wrapped with each required parent (graph and page).
val xy = V.GraphItems.XY(xData, yLinear)
val xy2 = V.GraphItems.XY(xData, ySin)
val document = V.Document(xy, xy2) // places each item into a separate page
The following image shows the mapping between the Veusz UI and the API's data objects:
XY Item is created using two Vectors, Axis 'x' and 'y' are used default
val xyLinearPlot = GraphItems.XY(xData, yLinear)
All properties are mutable. Although this is not a good functional style, it allows simple and quick changes. We decided for ease of use over convention since it is still your option to treat each object as if it was immutable. However, the conversion from Vector to the Numerical type must be done manually. (TODO Explain Datatypes)
xyLinearPlot.colorMarkers = Numerical(ySin)
The Item Configuration can be accessed over the config property. This contains a subconfiguration for each Veusz Formatting Tab.
xyLinearPlot.config.main.markerSize = 2 pt() // pt(), cm(), mm(), in() or percent()
xyLinearPlot.config.plotLine.color = "#ff007f"
xyLinearPlot.config.markerFill.color = "darkred"
The colorMarker Configuration is also integrated into the config object.
xyLinearPlot.config.colorConfig.min = 2.5
xyLinearPlot.config.colorConfig.max = 7.5
There are several options:
-
Using java.time.LocalDate
val dates: Vector[LocalDate] = ??? val datesFormatted = DateTimeConstructor.fromLocalDate(dates)
-
Using java.time.LocalDateTime
val dates: Vector[LocalDateTime] = ??? val datesFormatted = DateTimeConstructor.fromLocalDateTime(dates)
-
Using String
val dates = Vector("1/22/2020", "1/23/2020", "1/24/2020") val datesFormatted = DateTimeConstructor.fromString(dates)("M/dd/yyyy")
// Increase all dates by 30 days
val datesFormatted = DateTimeConstructor.fromString(dates)("M/dd/yyyy")(Map("dd"->30))