Altair: chart.save does not support pdf as shown in docs

Created on 3 Apr 2020  路  11Comments  路  Source: altair-viz/altair

The docs for saving charts show chart.save('chart.pdf') as one of the options, but running that results in ValueError: unrecognized format: 'pdf', even though altair_saver is installed and from altair_saver import save; save(chart, "chart.pdf") works.

By contrast, chart.save("chart.svg") works fine.

Looking at the docstring of Chart.save, it looks like pdf isn't even supposed to work: "Supported formats are json, html, png, svg". But maybe it's just a matter of wiring it up?

If the issue is more complicated than that (maybe because Chart.save is currently hardwired to use the Selenium backend, which doesn't offer pdf export?), then I would suggest just removing chart.save('chart.pdf') from the code example and refer users who are interested in pdf export functionality to altair_saver's docs :)

bug

All 11 comments

This requires altair version 4.1 or later. Check what version you are using with

import altair
print(altair.__version__)

4.1.0, I've just installed it... But maybe I've misconfigured it then?

Ah, yeah, you're right. the mimebundle code has been updated, but we neglected to thread through the save method for pdf. This is a bug.

What error do you get when trying to save a png? I'm surprised that doesn't work, because (unlike PDF) it's covered in the test suite in several places.

Thanks for resolving this so quickly!

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr  4 22:40:59 2020

@author: a
"""


import altair as alt
print(alt.__version__)
alt.renderers.enable('altair_viewer')
#alt.renderers.enable('html')
# load a simple dataset as a pandas DataFrame
from vega_datasets import data
cars = data.cars()

chart = alt.Chart(cars).mark_point().encode(
    x='Horsepower',
    y='Miles_per_Gallon',
    color='Origin',
).interactive()

#chart.show()
chart.save('filename.html')
chart.save('filename.pdf')
#chart.save("TESTS_/charty4_1.pdf")

This results in the error messages:

runfile('/home/a/ADR/SPYDER_CODE/example.py', wdir='/home/a/ADR/SPYDER_CODE')
4.1.0
Traceback (most recent call last):

  File "/home/a/ADR/SPYDER_CODE/example.py", line 26, in <module>
    chart.save('filename.pdf')

  File "/home/a/anaconda3/lib/python3.7/site-packages/altair/vegalite/v4/api.py", line 476, in save
    result = save(**kwds)

  File "/home/a/anaconda3/lib/python3.7/site-packages/altair/utils/save.py", line 128, in save
    raise ValueError("unrecognized format: '{}'".format(format))

ValueError: unrecognized format: 'pdf'`

Is something still wrong with the pdf save?

Yes, pdf save is still broken in version 4.1. The fix above is only a few hours old and has not made it into a release yet.

Thank you kindly Jake.

I would like to sincerely congratulate you on the 4.0 - 4.1 releases.
Excellent improvements.

Hi,

I installed both Altair and Altair_saver last dev versions using the following commands

pip3 install git+https://github.com/altair-viz/altair       
# Successfully installed altair-4.2.0.dev0
pip3 install git+https://github.com/altair-viz/altair_saver
#Successfully installed altair-saver-0.6.0.dev0

But I didn't succeed to export as PDF

4.2.0.dev0
Traceback (most recent call last):
  File "stacked_bar_example_pd.py", line 56, in <module>
    chart.save('chart.pdf')
  File "/home/aitsaidn/.local/lib/python3.6/site-packages/altair/vegalite/v4/api.py", line 477, in save
    result = save(**kwds)
  File "/home/aitsaidn/.local/lib/python3.6/site-packages/altair/utils/save.py", line 121, in save
    **kwargs,
  File "/home/aitsaidn/.local/lib/python3.6/site-packages/altair/utils/mimebundle.py", line 60, in spec_to_mimebundle
    return altair_saver.render(spec, format, mode=mode, **kwargs)
  File "/home/aitsaidn/.local/lib/python3.6/site-packages/altair_saver/_core.py", line 255, in render
    Saver = _select_saver(method, mode=mode, fmt=fmt)
  File "/home/aitsaidn/.local/lib/python3.6/site-packages/altair_saver/_core.py", line 69, in _select_saver
    raise ValueError(f"No enabled saver found that supports format={fmt!r}")
ValueError: No enabled saver found that supports format='pdf'

Here is the Example I'm using

import pandas as pd
import numpy as np
import altair as alt

# Generate Random Data

df1=pd.DataFrame(10*np.random.rand(4,3),index=["A","B","C","D"],columns=["I","J","K"])
df2=pd.DataFrame(10*np.random.rand(4,3),index=["A","B","C","D"],columns=["I","J","K"])
df3=pd.DataFrame(10*np.random.rand(4,3),index=["A","B","C","D"],columns=["I","J","K"])

def prep_df(df, name):
    df = df.stack().reset_index()
    df.columns = ['c1', 'c2', 'values']
    df['DF'] = name
    return df

df1 = prep_df(df1, 'DF1')
df2 = prep_df(df2, 'DF2')
df3 = prep_df(df3, 'DF3')

df = pd.concat([df1, df2, df3])


# Plotting
chart = alt.Chart(df).mark_bar().encode(

    # tell Altair which field to group columns on
    x=alt.X('c2:N', title=None),

    # tell Altair which field to use as Y values and how to calculate
    y=alt.Y('sum(values):Q',
        axis=alt.Axis(
            grid=False,
            title=None)),

    # tell Altair which field to use to use as the set of columns to be  represented in each group
    column=alt.Column('c1:N', title=None),

    # tell Altair which field to use for color segmentation 
    color=alt.Color('DF:N',
            scale=alt.Scale(
                # make it look pretty with an enjoyable color pallet
                range=['#96ceb4', '#ffcc5c','#ff6f69'],
            ),
        ))\
    .configure_view(
        # remove grid lines around column clusters
        strokeOpacity=0    
    )

print(alt.__version__)
chart.save('chart.pdf')

Any ideas to resolve that?

Thanks in advance.
Best regards.

To save as PDF, you need the vega-cli tools installed and correctly configured, as described in the documentation

(base) a@a-HP-EliteBook-820-G1:~$ sudo -s
[sudo] password for a:
(base) root@a-HP-EliteBook-820-G1:~# npm install vega-lite vega-cli canvas

[email protected] install /home/a/node_modules/canvas
node-pre-gyp install --fallback-to-build

node-pre-gyp WARN Using needle for node-pre-gyp https download
node-pre-gyp WARN Pre-built binaries not installable for [email protected] and [email protected] (node-v64 ABI, glibc) (falling back to source compile with node-gyp)
node-pre-gyp WARN Hit error EACCES: permission denied, mkdir '/home/a/node_modules/canvas/build'
gyp ERR! configure error
gyp ERR! stack Error: EACCES: permission denied, mkdir '/home/a/node_modules/canvas/build'
gyp ERR! System Linux 5.3.0-42-generic
gyp ERR! command "/home/a/anaconda3/bin/node" "/home/a/anaconda3/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "configure" "--fallback-to-build" "--module=/home/a/node_modules/canvas/build/Release/canvas.node" "--module_name=canvas" "--module_path=/home/a/node_modules/canvas/build/Release" "--napi_version=3" "--node_abi_napi=napi" "--napi_build_version=0" "--node_napi_label=node-v64"
gyp ERR! cwd /home/a/node_modules/canvas
gyp ERR! node -v v10.13.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
node-pre-gyp ERR! build error
node-pre-gyp ERR! stack Error: Failed to execute '/home/a/anaconda3/bin/node /home/a/anaconda3/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/home/a/node_modules/canvas/build/Release/canvas.node --module_name=canvas --module_path=/home/a/node_modules/canvas/build/Release --napi_version=3 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v64' (1)
node-pre-gyp ERR! stack at ChildProcess. (/home/a/node_modules/node-pre-gyp/lib/util/compile.js:83:29)
node-pre-gyp ERR! stack at ChildProcess.emit (events.js:182:13)
node-pre-gyp ERR! stack at maybeClose (internal/child_process.js:962:16)
node-pre-gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:251:5)
node-pre-gyp ERR! System Linux 5.3.0-42-generic
node-pre-gyp ERR! command "/home/a/anaconda3/bin/node" "/home/a/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd /home/a/node_modules/canvas
node-pre-gyp ERR! node -v v10.13.0
node-pre-gyp ERR! node-pre-gyp -v v0.11.0
node-pre-gyp ERR! not ok
Failed to execute '/home/a/anaconda3/bin/node /home/a/anaconda3/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/home/a/node_modules/canvas/build/Release/canvas.node --module_name=canvas --module_path=/home/a/node_modules/canvas/build/Release --napi_version=3 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v64' (1)
npm WARN enoent ENOENT: no such file or directory, open '/home/a/package.json'
npm WARN [email protected] requires a peer of vega@^5.12.1 but none is installed. You must install peer dependencies yourself.
npm WARN a No description
npm WARN a No repository field.
npm WARN a No README data
npm WARN a No license field.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: node-pre-gyp install --fallback-to-build
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /home/a/.npm/_logs/2020-05-24T11_51_59_632Z-debug.log

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zanarmstrong picture zanarmstrong  路  4Comments

Juan-132 picture Juan-132  路  3Comments

floringogianu picture floringogianu  路  3Comments

mroswell picture mroswell  路  4Comments

LukeMathWalker picture LukeMathWalker  路  3Comments