3

I've been using plotly a lot for creating graphs and visualizations. I'm working in jupyter notebooks on my local machine (Windows). For a specific use case, I am now required to save these graphics in high resolution .eps files. However, I can't get plotly and poppler to work in my python anaconda environment. Whenever I try to save a graph to eps, it throws the following error (while working fine for all other formats) [example code at end of question]:

ValueError: Transform failed with error code 530: Exporting to EPS format requires the pdftops command which is provided by the poppler library. Please install poppler and make sure the pdftops command is available on the PATH (full error message below)

Now, this appears to be down to a problem of my installation of the poppler library and this is not exactly a new problem. I've tried different solutions from other threads (Poppler in path for pdf2image, How to install Poppler on Windows?, Unable to install Poppler on Windows using Conda),https://chadrick-kwag.net/install-poppler-in-windows/ ) including:

  • Installing it in the conda env using conda install -c conda-forge poppler
  • Downloading the library for windows manually from https://github.com/oschwartz10612/poppler-windows/releases/and putting and putting its directory on the system path
  • Appending the path in the python script as well using sys.path.append(r"C:\poppler-22.04.0\Library\bin")

When I enter pdftops -h into the terminal it works seamlessly, which in my opinion shows it is on the path:

pdftops version 22.04.0
Copyright 2005-2022 The Poppler Developers - http://poppler.freedesktop.org
Copyright 1996-2011, 2022 Glyph & Cog, LLC
Usage: pdftops [options] <PDF-file> [<PS-file>]
  -f <int>                       : first page to print
  -l <int>                       : last page to print
 [...]

Does anyone have any ideas on how to get it to work? Otherwise the conda env/plotly are working perfectly. Below example code and the full error message. I would be extremely grateful - I've been stuck with this for way to long now.

Python: v 3.8, Plotly: v 5.4.0, poppler: v 22.04.0

Example Code:

import plotly.graph_objects as go

fig = go.Figure(data=[go.Sankey(
    node = dict(
      pad = 15,
      thickness = 20,
      line = dict(color = "black", width = 0.5),
      label = ["A 1", "A 2", "A 3", "B 1", "B 2", "B 3", "C 1", "C 2", "C 3"],
      color = ["red", "yellow", "green", "red", "yellow", "green", "red", "yellow", "green"],
      # x = [0,0,0,0.3,0.3,0.3,0.6,0.6,0.6],
      # y = [0.5,0.3,0.1,0.5,0.3,0.1,0.5,0.3,0.1,],
      #groups = [[0,3,6], [1,4,7], [2,5,8]]
    ),
    link = dict(
      source = [0, 0, 0, 1, 1, 1,2,2,2, 3,3,3,4,4,4,5,5,5], # indices correspond to labels, eg A1, A2, A1, B1, ...
      target = [3, 4, 5, 3, 4, 5,3,4,5, 6,7,8,6,7,8,6,7,8],
      value =  [1, 3, 7, 2, 2, 2,2,1,22,1,0,5,0,3,3,3,2,26  ],
      color = ["red", "yellow", "green", "red", "yellow", "green", "red", "yellow", "green", "red", "yellow", "green", "red", "yellow", "green", "red", "yellow", "green"]
  ))])

fig.update_layout(font_size=10)
fig.write_image("Levels_Over_Time.eps", scale = 15)
fig.write_html("Levels_Over_Time.html")
fig.show()

Full Error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_6248/3754478019.py in <module>
     25 
     26 fig.update_layout(autosize=False, width=1000, height=400,  margin=dict(l=65, r=65, b=50, t=50))
---> 27 fig.write_image("Levels_Over_Time.eps", scale = 15)
     28 fig.write_html("Levels_Over_Time.html")
     29 fig.show()

c:\Users\user\anaconda3\envs\Neuro_ML\lib\site-packages\plotly\basedatatypes.py in write_image(self, *args, **kwargs)
   3819         import plotly.io as pio
   3820 
-> 3821         return pio.write_image(self, *args, **kwargs)
   3822 
   3823     # Static helpers

c:\Users\user\anaconda3\envs\Neuro_ML\lib\site-packages\plotly\io\_kaleido.py in write_image(fig, file, format, scale, width, height, validate, engine)
    266     # -------------
    267     # Do this first so we don't create a file if image conversion fails
--> 268     img_data = to_image(
    269         fig,
    270         format=format,

c:\Users\user\anaconda3\envs\Neuro_ML\lib\site-packages\plotly\io\_kaleido.py in to_image(fig, format, width, height, scale, validate, engine)
    143     # ---------------
    144     fig_dict = validate_coerce_fig_to_dict(fig, validate)
--> 145     img_bytes = scope.transform(
    146         fig_dict, format=format, width=width, height=height, scale=scale
    147     )

c:\Users\user\anaconda3\envs\Neuro_ML\lib\site-packages\kaleido\scopes\plotly.py in transform(self, figure, format, width, height, scale)
    159         if code != 0:
    160             message = response.get("message", None)
--> 161             raise ValueError(
    162                 "Transform failed with error code {code}: {message}".format(
    163                     code=code, message=message

ValueError: Transform failed with error code 530: Exporting to EPS format requires the pdftops command which is provided by the poppler library. Please install poppler and make sure the pdftops command is available on the PATH
Jason Aller
  • 3,541
  • 28
  • 38
  • 38

3 Answers3

1

This took care of it for me on WSL2 Ubuntu 20.04 (the native poppler-utils wouldn't). Since this is conda, I think it should work for you too.

conda install -c conda-forge poppler

from here.

Mahomet
  • 373
  • 2
  • 4
  • Running it on WSL2 actually worked. However, there is a poppler version compiled for Windows (although I did not get it to run) – Entspannter Sep 30 '22 at 17:32
1

I got stuck with this as well. The script not finding the pdftops command is generally a PATH issue.

On Windows

From what I can tell, it seems that you're not running the sys.path.append() at the start of your script every time. You will need to either permanently add Poppler to your PATH (i.e export PATH=/path/to/poppler/bin:${PATH} in your terminal), or append it at the beginning of the script every time.


On Linux / MacOS

Using pip install poppler has no changes to the environment's PATH. Either brew install poppler or sudo apt-get install poppler-utils (Linux) will make your life easier. This should properly add all the relative links and make pdftops accessible within your scripts.


Note: If you're running your script on IPython, you'll need to restart your kernel for any PATH changes to take effect.

ThunderStruct
  • 1,504
  • 6
  • 23
  • 32
  • Thanks for your comment, Manually adding it didn't work, probably because I was using conda. I ended up us solving it two ways: - in the short term, I circumvented the problem on windows by converting the image types and thus not using poppler - later, I ended up running the script on WSL2 Ubuntu – Entspannter Sep 30 '22 at 17:30
  • That's unfortunate :/ Seems to be a niche issue that some of us lucky ones encounter! Good job being so detailed with your question and self-answer, though... Hope whoever comes across it can get it to work out with one of the many suggestions on here. – ThunderStruct Oct 01 '22 at 18:16
1

The long-term solution was to run the code in WSL2 Ubuntu for very complicated graphs because there poppler and its installation is not an issue. While I did not get poppler to run on Windows as intended, I found a quick short-term workaround that produced reasonable quality tiffs for many graphics. This involves using the PIL's package functions to convert images, which works well for many standard graphs and can save much time compared with setting up WSL2 when necessary.

Here is some example code:

import plotly.io as pio
import plotly.express as px
from PIL import Image
import os
    
fig = px.bar(
            x=your_x_values,
            y=your_y_values,
        )
pio.write_image(fig, "your_plot_name.png", scale=3)
image = Image.open("your_plot_name.png")
image.save(
            "your_plot_name.tiff",
            dpi=(300, 300),
            compression=None,
            artist="Your_Name_Here",
        )
os.remove(f"{file_name}.png")
    

THis also works with other file types often demanded for scientific journals like .eps. I hope this can help someone!

Best regards