JetBrains / lets-plot

Multiplatform plotting library based on the Grammar of Graphics
https://lets-plot.org
MIT License
1.57k stars 51 forks source link

Option to save plots to PDF format using `ggsave()` #710

Closed erdirstats closed 1 year ago

erdirstats commented 1 year ago

Would it be possible to directly save PDF output from ggsave()? It would be nice to be able to save a plot mosaic (made using gggrid()) in PDF output, with option to specify dimensions. Maybe there is some straightforward way for going from SVG to PDF but somehow it's a bit difficult to manage fonts sometimes? I am new at using lets-plot for python, so I might be missing something obvious...

alshan commented 1 year ago

Sure, that would be a good featue.

Meanwhile, you can try using CairoSVG for SVG --> PDF conversion:

p = ggplot() ...

pathname = ggsave(p, "plot.svg")

import cairosvg

cairosvg.svg2pdf(url=pathname, write_to='plot.pdf')

AFAIK, there should be no issues with fonts as long as the font you needed is installed in your system.

erdirstats commented 1 year ago

Thanks. I am not being able yo get cairosvg working into windows... It's a known issue apparently. I tried using svglib, based on answers here but it just doesn't recognise the font. It would be nice to have all this taken care by ggsave, although it might not be top priority for now.

VDovidaytis-HORIS commented 1 year ago

I am not being able yo get cairosvg working into windows...

Could you describe this problem, please? What environment are you using and what errors do you get?

erdirstats commented 1 year ago

Sure. I am creating the first plot described in the documentations here.

import numpy as np
import pandas as pd
from lets_plot import *

LetsPlot.setup_html()

data = pd.read_csv('https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/mpg2.csv')

p = (ggplot(data, aes(x="engine horsepower", y="miles per gallon")) + \
     geom_point(aes(color="origin of car")) + \
     ggsize(800, 350))

pathname = ggsave(p, "plot.svg")

import cairosvg

cairosvg.svg2pdf(url=pathname, write_to='plot.pdf')

svg plot is created correctly but when import cairosvg is run, the following error shows up:

Traceback (most recent call last):
  File "c:\Users\Admin\letsplotpdf\file.py", line 16, in <module>
    import cairosvg
  File "C:\Users\Admin\AppData\Local\pypoetry\Cache\virtualenvs\letsplotpdf-p-kfgU1k-py3.10\lib\site-packages\cairosvg\__init__.py", line 26, in <module>
    from . import surface  # noqa isort:skip
  File "C:\Users\Admin\AppData\Local\pypoetry\Cache\virtualenvs\letsplotpdf-p-kfgU1k-py3.10\lib\site-packages\cairosvg\surface.py", line 9, in <module>
    import cairocffi as cairo
  File "C:\Users\Admin\AppData\Local\pypoetry\Cache\virtualenvs\letsplotpdf-p-kfgU1k-py3.10\lib\site-packages\cairocffi\__init__.py", line 47, in <module>
    cairo = dlopen(
  File "C:\Users\Admin\AppData\Local\pypoetry\Cache\virtualenvs\letsplotpdf-p-kfgU1k-py3.10\lib\site-packages\cairocffi\__init__.py", line 44, in dlopen
    raise OSError(error_message)  # pragma: no cover
OSError: no library called "cairo-2" was found
no library called "cairo" was found
no library called "libcairo-2" was found
cannot load library 'libcairo.so.2': error 0x7e
cannot load library 'libcairo.2.dylib': error 0x7e
cannot load library 'libcairo-2.dll': error 0x7e
(letsplotpdf-py3.10) PS C:\Users\Admin\letsplotpdf> & C:/Users/Admin/AppData/Local/pypoeotpdf-p-kfgU1k-py3.10\lib\site-packages\cairocffi\__init__.py", line 47, in <module>        cairo = dlopen(
  File "C:\Users\Admin\AppData\Local\pypoetry\Cache\virtualenvs\letsplotpdf-p-kfgU1k-py3.10\lib\site-packages\cairocffi\__init__.py", line 44, in dlopen
    raise OSError(error_message)  # pragma: no coverOSError: no library called "cairo-2" was found
no library called "cairo" was foundno library called "libcairo-2" was foundcannot load library 'libcairo.so.2': error 0x7e
cannot load library 'libcairo.2.dylib': error 0x7ecannot load library 'libcairo-2.dll': error 0x7e

I am on Windows and using VS Code as an editor. I have created a poetry environment and the content of the pyproject.toml file is:

[tool.poetry]
name = "letsplotpdf"
version = "0.1.0"
description = ""
authors = ["erdirstats <erdi.eng@gmail.com>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.10"
pandas = "^1.5.3"
numpy = "^1.24.2"
lets-plot = "^3.1.0"
ipython = "^8.11.0"
cairosvg = "^2.7.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
VDovidaytis-HORIS commented 1 year ago
OSError: no library called "cairo-2" was found
no library called "cairo" was found
no library called "libcairo-2" was found
cannot load library 'libcairo.so.2': error 0x7e
cannot load library 'libcairo.2.dylib': error 0x7e
cannot load library 'libcairo-2.dll': error 0x7e

You can resolve this problem by installing the missing dependencies on your Windows. In my case the GTK3 Runtime for Windows package helped. You can try this solution or find a better one for you.

ASmirnov-HORIS commented 1 year ago

I tried to save plots through svglib on my Windows 11.

It shows warnings like

Unable to find a suitable font for 'font-family:Lucida Console', weight:normal, style:normal

about some fonts, and lost plot titles. But still save PDF somehow.

Here comparison of an original plot with different fonts and its PDF-version:

alshan commented 1 year ago

Option added in v4.1.0