Altair: Error saving to SVG

Created on 20 Mar 2017  Â·  15Comments  Â·  Source: altair-viz/altair

Hi. Using the first example in the docs

from altair import Chart, load_dataset

# load built-in dataset as a pandas DataFrame
cars = load_dataset('cars')

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

the following attempt to save to SVG fails

chart.savechart('cars.jpg','jpg')
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2881, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-14-b070806b7bcc>", line 1, in <module>
    chart.savechart('cars.jpg','jpg')
  File "/usr/local/lib/python2.7/site-packages/altair/api.py", line 182, in savechart
    supported = _node.SUPPORTED_FILETYPES + ['json', 'html']
NameError: global name '_node' is not defined

and attempting to use vl2svg directly gives the error

vl2svg cars.json cars.jpg
/usr/local/lib/node_modules/vega/build/vega.js:686
  throw Error(message);
  ^

Error: Missing required "filter" parameter: "expr"
    at error (/usr/local/lib/node_modules/vega/build/vega.js:686:9)
    at parseParameter$1 (/usr/local/lib/node_modules/vega/build/vega.js:28796:9)
    at parseParameters (/usr/local/lib/node_modules/vega/build/vega.js:28775:25)
    at parseTransform (/usr/local/lib/node_modules/vega/build/vega.js:28763:35)
    at /usr/local/lib/node_modules/vega/build/vega.js:29639:23
    at Array.forEach (native)
    at parseData$1 (/usr/local/lib/node_modules/vega/build/vega.js:29638:20)
    at /usr/local/lib/node_modules/vega/build/vega.js:30045:5
    at Array.forEach (native)
    at parseSpec (/usr/local/lib/node_modules/vega/build/vega.js:30044:22)

I have installed canvas, vega and vega-lite and altair is the pypi version.

needs-info question

All 15 comments

You'll have to install a bit more for saving the figure through the altair module. See for more information this link: https://altair-viz.github.io/documentation/displaying.html#saving-figures-as-png-and-svg

If you would like to save an Altair visualization as PNG or SVG from a script, Altair does provide an interface that allows this, though it requires some extra setup.

The Vega-Lite javascript library provides a NodeJS command-line tool to generate png and svg outputs from Altair/Vega-Lite specifications. The Chart.savechart() method provides an interface that will use these command-line tools to output PNG or SVG outputs of a chart.

The extra requirements here are straightforward, but the manual installation process is admittedly a bit clunky. We hope to find a way to streamline this in the future, but creating transparent interactions between Python packages and NodeJS packages remains a challenging area in general. If you have ideas on how to improve this aspect of Altair’s user experience, please send comments or contributions via Altair’s GitHub Issue Tracker.

I think the issue is a version mismatch between the vega-lite version used by the current Altair master, and the vega-lite version used by your node installation. As of the Altair 1.0 release, the Altair version number is pegged to the vega-lite version number:

>>> from altair import schema
>>> print(schema.vegalite_version)
1.2.1

If this doesn't match the version of vega-lite you installed with nodejs (particularly if you installed the 2.0 pre-release, which is not backward compatible), then the conversion will not work.

As Altair and Vega-Lite become more mature, I think these sorts of things will be a bit more seamless.

@tahnoonpasha have we answered your questions sufficiently?

Hi @jakevdp and @ellisonbg - thank you for your response. I will try and reinstall the 1.x vegalite and check. Not sure how to check which version I have with node. Appreciate your help

@jakevdp and @ellisonbg, I think there is still a problem saving to SVG file after follow these steps. The error I got is related to this Stack Overflow post. Here I paste part of the error.

/Users/titipata/anaconda3/lib/python3.6/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session)
   1324                             else:
   1325                                 err_msg += ': ' + repr(orig_executable)
-> 1326                     raise child_exception_type(errno_num, err_msg)
   1327                 raise child_exception_type(err_msg)
   1328 

FileNotFoundError: [Errno 2] No such file or directory: 'vl2svg'

print(schema.vegalite_version) is 1.2.1, Python version 3.6.

The issue is that the vl2svg command is not available in the environment in which Python is running. You'll have to make sure you've installed that tool, and adjust your system path so that the command works when executed from Python.

Sorry it's not easier, but currently there's no good way to automatically interface between Python and NodeJS. If you know of one, please let us know!

@titipata I was able to get it working on both ubuntu and mac os x with anaconda 3.6. At first, I also got an error like your on mac. On mac I have to reinstall npm by following this : https://gist.github.com/DanHerbert/9520689 .

For Ubuntu, I have to install both nodejs and nodejs-legacy due to anaconda.

sudo apt-get install nodejs -y
sudo apt-get install npm -y
sudo apt-get install nodejs-legacy -y
sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++
sudo npm install -g --save canvas vega vega-lite

@titipata did you get this figured out?

hi @ellisonbg, I still didn't figure out the solution (note that I'm on macOS). It seems like problem is from nodejs as @thoo commented. I'm reinstalling nodejs right now. I will update the comment shortly.

thanks for the update

On Wed, Sep 27, 2017 at 11:36 AM, Titipat Achakulvisut <
[email protected]> wrote:

hi @ellisonbg https://github.com/ellisonbg, I still didn't figure out
the solution (note that I'm on macOS). It seems like problem is from
nodejs as @thoo https://github.com/thoo commented. I'm reinstalling
nodejs right now. I will update the comment shortly.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/altair-viz/altair/issues/310#issuecomment-332615895,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABr0LqdiVySJo7CkvdGn_z8WyacadsIks5smpWWgaJpZM4MiHBA
.

--
Brian E. Granger
Associate Professor of Physics and Data Science
Cal Poly State University, San Luis Obispo
@ellisonbg on Twitter and GitHub
[email protected] and [email protected]

For what it's worth, I can no longer get this to work on any of my machines. I think the NodeJS+shell dependency is something we're going to have to figure out how to move away from (Bokeh has an interesting approach that we may adopt)

Running into this myself, but not these errors. Using the same example as in the first post, except I changed the file to a .png (no good reason, and I get the same error with .svg).

---------------------------------------------------------------------------
CalledProcessError                        Traceback (most recent call last)
<ipython-input-1-557fcfee05a8> in <module>()
      9     color='Origin',
     10 )
---> 11 chart.savechart('cars.png','png')

~/.local/lib/python3.6/site-packages/altair/v1/api.py in savechart(self, outfile, filetype)
    224 
    225         if filetype in node.SUPPORTED_FILETYPES:
--> 226             node.savechart(self, outfile, filetype)
    227         elif filetype == 'json':
    228             if hasattr(outfile, 'write'):

~/.local/lib/python3.6/site-packages/altair/utils/node.py in savechart(chart, filename, filetype, verbose)
    138                                'vl2' + filetype,
    139                                outfile=filename,
--> 140                                verbose=verbose)

~/.local/lib/python3.6/site-packages/altair/utils/node.py in _convert_vegalite_spec(spec, cmd, outfile, verbose)
     84     if p.returncode:
     85         combined_output = out + b'\nError:\n' + err
---> 86         raise CalledProcessError(p.returncode, cmd, output=combined_output)
     87 
     88     if outfile is not None:

CalledProcessError: Command 'vl2png' returned non-zero exit status 127.
>>> print(schema.vegalite_version)
v1.2.1

$ npm list
[email protected]
[email protected]

$ which vl2png
/home/jwhendy/node_modules/.bin/vl2png

$ pip freeze
altair==1.2.1
vega==0.4.4

# arch linux
$ pacman -Q
cairo 1.15.8-2
nodejs 8.8.1-1

tl;dr: try:

$ npm install [email protected]
$ npm install [email protected]

Ha! On a fluke, I tried running vl2png directly as that's what the docs mention. I figured maybe I could feed it something by hand and figure out what the deal was.

$ vl2png --help
/home/jwhendy/node_modules/.bin/vl2png: line 8: vg2png: command not found

Whoa! A quick google reveals that vg2png comes from vega, not vega-lite. After a quick npm install vega, my error changed from exit status 127 to exit status 1. I suspected a version issue from the comment above, but vega isn't matched to vega-lite.

Some sleuthing reveals that vega-lite 1.2.1 was released in Oct 2016, so going back in version histories shows that vega 2.6.0 was the last release at that time, just before they pushed out 3.0.0 beta in Nov 2016.

Installing [email protected] brings back the goodness; I can now save out both .png and .svg (though I now need to figure out how to specify the .png resolution, which is awful).

This is no longer relevant, because Altair 2 uses selenium rather than node for programmatic export.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fischcheng picture fischcheng  Â·  4Comments

Juan-132 picture Juan-132  Â·  3Comments

SuperShinyEyes picture SuperShinyEyes  Â·  3Comments

galloramiro picture galloramiro  Â·  3Comments

firasm picture firasm  Â·  3Comments