Example
Defining Layout In Inkscape
First, open inkscape and draw some rectangles with the rectangle
tool (R):
Right click on each rectangle and click Object Properties
Then, change the label to something memorable and click Set
- this will be how you reference each shape from julia. The rectangles in this example are labeled A
B
C
and D
as such:
Now open julia and import figure_second
and either a Makie
library or Plots.jl
:
Loading the Inkscape document in Julia
using figure_second
using CairoMakie
then, create an Updater
object that holds information on where the inkscape file is on disk. If you are ok with mutating the inkscape file in place, you can do
inkscape = updater("./path/to/file.svg")
then, we can find all the ids of the rectangles we just created with ids
:
ids(inkscape)
# outputs: ["A" "B" "C" "D"]
Plotting into Inkscape
now, lets create general plotting function that we can reuse:
function my_plot(x, y, inkscape::Updater, inkscape_id::String)
# manually set a resolution
res = (600, 400)
fig = Figure(resolution = res, dpi = 200)
ax = Axis(fig[1,1], title = inkscape_id)
lines!(ax, x, y, linewidth=4)
return fig
end
and then place some data in the A
rectangle for our figure:
x = range(0, 2pi, 100)
A = my_plot(x, sin.(x), inkscape, "A")
# a dictionary of keys (name of inkscape ID) and values
# (figure objects)
mapping = Dict(
"A" => A
)
# write all these figures into the inkscape svg
plot_figures(inkscape, mapping)
opening inkscape and going File > Revert
, we will force reload inkscape to any changes that have happened in the file. Now the file looks like this:
Lets apply the same process to id C
:
x = range(0, 2pi, 100)
A = my_plot(x, sin.(x), inkscape, "A")
# new figure!
C = my_plot(x, sin.(x), inkscape, "B")
# mapping of inkscape ids to figure objects
mapping = Dict(
"A" => A,
"C" => C,
)
# write all these figures into the inkscape svg
plot_figures(inkscape, mapping)
Sizing plots to inkscape layout
it seems that figure_second
is not respecting the aspect ratios of the inkscape objects which in turn causes the plots to fill the allocated space poorly. To fix this we can use the relative_dimensions
function to calculate a figure resolution that respects the inkscape aspect ratio. Updating our my_plot
function:
function my_plot(x, y, inkscape::Updater, inkscape_id::String)
# every figure will have a height of 500, but the width will
# change to respect the aspect ratio of the output
desired_height = 500.
local res = relative_dimensions(inkscape, inkscape_id, desired_height)
fig = Figure(resolution = res, dpi = 200)
ax = Axis(fig[1,1], title = inkscape_id)
lines!(ax, x, y, linewidth=4)
return fig
end
re-running the code and reloading the inkscape figure we have the following:
then we can adjust our plotting commands for the other boxes:
x = range(0, 2pi, 100)
A = my_plot(x, sin.(x), inkscape, "A")
C = my_plot(x, sin.(x), inkscape, "C")
B = my_plot(x, tan.(x), inkscape, "B")
D = my_plot(x, abs.(cos.(x)), inkscape, "D")
mapping = Dict(
"A"=> A,
"C"=> C,
"B"=> B,
"D" => D
)
The beauty of figure_second
Lets say we want to change all the line plots to scatter plots, and make all background colors different:
function my_plot(x, y, inkscape::Updater, inkscape_id::String)
# manually set a resolution
local res = (600, 400)
desired_height = 500.
local res = relative_dimensions(inkscape, inkscape_id, desired_height)
fig = Figure(resolution = res, dpi = 200)
# now a black background
ax = Axis(fig[1,1], title = inkscape_id, backgroundcolor=:black)
# now a scatter plot
scatter!(ax, x, y, linewidth=4)
return fig
end
our figure now looks like:
Or, what if we moved all the rectangles in our figure:
rerendering in julia: