I have 12 figures in svg format and I would like to arrange them into 3 columns and 4 rows in the form of 12 panels that would fit into an A4 printed version for publication. What is desired is to maximize the area covering fraction such that the empty space is minimized in order to see all the features in the 12 images.
I am aware that I can use subplots under a big figure in matplotlib. However, in my case, each one of these figures are produced independently from a different function of the same simulation. I cannot embed a large simulation repeatedly into each call as I need to access some of the figures in different places for different purposes. In other words, the less I manipulate the original simulation the less headache I will have to extract different plots from it. I would like to minimize any changes in the original simulation and instead add my additional code to my sole purpose of gathering some of the plots into same place.
Here is what I have come up with in my python code to accomplish this:
import matplotlib.pyplot as plt
import svgutils.transform as sg
from svgutils.compose import *
import os
plt.figure(1, tight_layout=True)
...
plt.savefig('/some_path/first_xy.svg')
plt.figure(2, tight_layout=True)
...
plt.savefig('/some_path/first_xz.svg')
plt.figure(3, tight_layout=True)
...
plt.savefig('/some_path/first_yz.svg')
plt.figure(4, tight_layout=True)
...
plt.savefig('/some_path/second_xy.svg')
plt.figure(5, tight_layout=True)
...
plt.savefig('/some_path/second_xz.svg')
plt.figure(6, tight_layout=True)
...
plt.savefig('/some_path/second_yz.svg')
plt.figure(7, tight_layout=True)
...
plt.savefig('/some_path/third_xy.svg')
plt.figure(8, tight_layout=True)
...
plt.savefig('/some_path/third_xz.svg')
plt.figure(9, tight_layout=True)
...
plt.savefig('/some_path/third_yz.svg')
plt.figure(10, tight_layout=True)
...
plt.savefig('/some_path/fourth_xy.svg')
plt.figure(11, tight_layout=True)
...
plt.savefig('/some_path/fourth_xz.svg')
plt.figure(12, tight_layout=True)
...
plt.savefig('/some_path/fourth_yz.svg')
myfigure = Figure("21cm", "29.7cm",
SVG("/some_path/first_xy.svg"),
SVG("/some_path/first_xz.svg"),
SVG("/some_path/first_yz.svg"),
SVG("/some_path/second_xy.svg"),
SVG("/some_path/second_xz.svg"),
SVG("/some_path/second_yz.svg"),
SVG("/some_path/third_xy.svg"),
SVG("/some_path/third_xz.svg"),
SVG("/some_path/third_yz.svg"),
SVG("/some_path/fourth_xy.svg"),
SVG("/some_path/fourth_xz.svg"),
SVG("/some_path/fourth_yz.svg")
).tile(3, 4)
myfigure.save('/some_path/complete_figure.svg')
os.system('inkscape --export-png=/some_path/complete_figure.png /some_path/complete_figure.svg --export-background=white --export-area-drawing')
However, running this code produces a weird error message related to the function being used, tile()
, to group 12 figures into a single A4 page as below:
Traceback (most recent call last): File "script.py", line 70, in ).tile(3, 4)
File "/usr/local/anaconda3/lib/python3.5/site-packages/svgutils/compose.py", line 287, in tile dx = (self.width/ncols).to('px').value TypeError: unsupported operand type(s) for /: 'Unit' and 'int'
I am running my code on a remote desktop but I can access the content of compose.py
. However I don't know if there is a bug in that routine. What is the fix?
Seems like a bug to me. You should report it at https://github.com/btel/svg_utils/issues
The offending lines are in the tile function:
self.width
andself.height
are typeUnit
, which Python doesn't know how to divide by anint
.In the meantime, I quickly fixed it with a monkey-patch of the tile function:
apply by executing:
EDIT: this is true as of svgutils-0.2.0 freshly installed from pip