Reputation: 908
I am using python plotly '5.1.0' for a bubble plot. What I would like to do is to also add some text annotations containing links to web pages. All works fine when I show the figure in jupyter notebook, however I haven't managed to save the plot with working links as a picture (my favorite format would be pdf but I tried basically all the available ones).
Is this possible with plotly? Are there alternatives to achieve that with other libraries?
Edit: the final goal is to insert the picture in a pdf using latex, so solution directly compatible with this usage are preferred :)
Here same toy code to reproduce the behavior:
import plotly.express as px
df = px.data.gapminder()
fig = px.scatter(df.query("year==2007"), x="gdpPercap", y="lifeExp",
size="pop", color="continent",
hover_name="country", log_x=True, size_max=60)
fig.add_annotation(text="""here is my <a href="https://rdcu.be/cB1Ds"><b>paper</b></a>""", x=4, y=50)
fig.show()
The result correctly displays a clickable link:
However, when I save it the link disappears:
fig.write_image("fig1.pdf", engine="kaleido") # I also tried "orca" but doesn't help
Upvotes: 0
Views: 1009
Reputation: 2146
Short answer
Though not elegant, I would suggest to create an image without a link and then use tikz
and hyperref
to add the link to the image manually in latex:
\documentclass{article}
\usepackage{tikz}
\usepackage{hyperref}
\begin{document}
\begin{tikzpicture}
\begin{scope}
\node[anchor=south west,inner sep=0] (image) at (0,0){\includegraphics[width=0.7\textwidth]{scatter_without_link.png}};
\begin{scope}[x={(image.south east)},y={(image.north west)}]
\node [anchor=west] (note) at (0.6,0.70) {\href{https://stackoverflow.com}{Link}};
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}
Long answer
You could create an svg with clickable links. A minimum working example using matplotlib
is
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.scatter([1, 2, 3], [4, 5, 6])
text = ax.annotate("Link", xy=(2,5), xytext=(2.2,5.5),
url='https://stackoverflow.com',
bbox=dict(color='w', alpha=1e-6, url='https://stackoverflow.com'))
fig.savefig('scatter.svg')
Then convert the svg to pdf, e.g. using inkscape and the command line:
inkscape -D --export-type="pdf" scatter.svg --export-latex
This results in a pdf with the scatter plot and a clickable hyperlink.
However: Preserving the hyperlink when embedding the pdf in your latex file (e.g. using the svg package or simply \input{scatter.pdf_tex}
) is a more difficult problem as pdftex seems to drop the annotations from the included file (see this 10-year-old question How to preserve hyperlinks in included PDF?).
Note: If you want to use the svg package, make sure that (1) Inkscape is installed and on the system path and (2) latex runs with shell-escape (--shell-escape
) enabled.
Note 2: For displaying the matplotlib example in jupyter notebook:
%config InlineBackend.figure_formats = ['svg']
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots()
ax.scatter([1, 2, 3], [4, 5, 6])
text = ax.annotate("Link", ... ) # same as above
plt.plot()
Upvotes: 1
Reputation: 727
It seems that the available solutions are not always trusted. That, perhaps, explains why there is no standard one. I was about to suggest @rosa b.'s exact solution, it just did not work for me when I tried to replicate it at my end. Maybe because I used a challenging svg
sample that contained two different types of hyperlinks: one around a shape and another around a text to cover all possibilities as follows:
links.svg
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<!-- A link around a shape -->
<a href="http://www.example.com">
<circle cx="50" cy="40" r="35" stroke="green" fill="red"/>
<text x="50" y="40" text-anchor="middle" font-size="0.5em">
www.example.com
</text>
</a>
<!-- A link around a text -->
<a href="http://www.foo.bar">
<text x="50" y="90" text-anchor="middle">
Foo.Bar
</text>
</a>
</svg>
When I carried out rosa b.
's solution, using the following command under a Windows
environment:
inkscape.com --export-area-drawing --export-type="pdf" --export-filename=links.pdf --export-latex links.svg
It indeed generated a links.tex_pdf
file that, also, did not contain the link to the text hyperlink correctly suggesting adding it manually using \href{}
.
I tried another solution by printing the svg
to a pdf
using Google Chrome since many PDF transformers filter off those hyperlinks as unwanted annotations. The print has to happen without headers or footers and at a 0 margin. This kept the csv
's hyperlinks intact. Now coming to the second challenge to include this good pdf
into LaTeX
since, again, LaTeX inclusion of pdf
do filter off the annotations, again!
I learned about a package called pax
that you can include to better add the pdf
s with links. I followed their recommendation and ended up with the following:
links.tex
\documentclass[a4paper,12pt,landscape]{article}
\usepackage{hyperref}
\usepackage{pdfpages}
% pdfpages loads graphicx
\usepackage{pax}
\iffalse
\usepackage{hyperref}
\hypersetup{
filebordercolor={1 1 0},
}
\fi
\begin{document}
\includepdf[pages=-]{links}
\end{document}
I gave it a shot using the online LaTex editor Overleaf here and now we ended up with a clickable text inside of the circle, but not the outer one.
I hope this one would work for your specific svg
.
Upvotes: 1