Hello!!
I have created a script that generates a pdf with SVG images taken from a bokeh plot. It was done with the python libraries reportlab
and svglib
. I have followed these basic steps:
- Use the
export_svgs
builtin function in order to get the SVG file - Create a
Flowable
object to add it to the pdf inreportlab
- Creating pdf reports with
reportlab
by theplatypus
methd (building the pdf with a bunch of elements and template).
As export_svgs
can only export one plot at the same time, this may also useful if somebody want to export a grid of plots or a more complex layout.
from reportlab.lib.pagesizes import A4
from reportlab.platypus import Table, TableStyle, SimpleDocTemplate
from reportlab.lib import colors
from reportlab.lib.units import mm
from svglib.svglib import svg2rlg
import numpy as np
from bokeh.plotting import figure
from bokeh.io import curdoc, export_svgs, export_png
from bokeh.models import Button
def get_plot():
N = 3000
x = np.random.random(size=N) * 100
y = np.random.random(size=N) * 100
radii = np.random.random(size=N) * 1.5
p = figure(
x_axis_label='X axis',
y_axis_label='Y axis',
title='Random plot',
tools="crosshair,pan,wheel_zoom,box_zoom,reset,tap,save,lasso_select",
output_backend = "webgl"
)
p.scatter(
x=x,
y=y,
radius=radii,
fill_color='red',
fill_alpha=0.6,
line_color=None
)
print('Exporting plot.svg...')
p.output_backend = "svg"
export_svgs(p, filename="plot.svg")
# create a new SVG or a PDF with the new layout
print('Reading drawing from plot.svg...')
return svg2rlg("plot.svg")
drawing = get_plot()
print('Scaling SVG image...')
sx = sy = 0.3 # scaling factor
drawing.width = drawing.minWidth() * sx
drawing.height = drawing.height * sy
drawing.scale(sx, sy)
data = [
['TABLE HEADER', None], # this works as a leading row
[drawing, drawing],
[drawing, drawing],
[drawing, drawing],
[drawing, drawing],
[drawing, drawing],
[drawing, None]
]
table = Table( # Flowable object
data,
colWidths=200,
rowHeights=[1 * mm] + [drawing.height] * (len(data) - 1),
# hAlign='LEFT',
repeatRows=1
)
table.setStyle(TableStyle([
# LEADING ROW
('LINEBELOW', (0, 0), (1, 0), 0.5, colors.black),
('SPAN', (0, 0), (1, 0)), # colspan
('FONTSIZE', (0, 0), (1, 0), 12),
('LEFTPADDING', (0, 0), (1, 0), 0),
('BOTTOMPADDING', (0, 0), (1, 0), 3),
# REST OF ROWS
('LEFTPADDING', (1, 1), (-1, -1), 0),
('RIGHTPADDING', (1, 1), (-1, -1), 0),
('BOTTOMPADDING', (1, 1), (-1, -1), 0),
('TOPPADDING', (1, 1), (-1, -1), 0),
]))
story = []
story.append(table)
margin = 25 * mm
doc = SimpleDocTemplate(
'minimal_reportlab_table_.pdf', pagesize=A4,
rightMargin=margin, leftMargin=margin,
topMargin=margin, bottomMargin=margin
)
doc.build(story)
If you run this code you may read a warning āUnable to find a suitable font for āfont-family:helveticaāā. But I did not paid attention to it yet.
References:
- Reportlab user guide (80% python, 20% C)
- How to add a SVG file to the pdf in reportlab
- An alternativa can be Wkhtmltopdf (C++). But I did not try it yet library yet, though I do know if it is doable with SVG directly.