9

I am looking for a way to save a matplotlib figure as an EMF file. Matplotlib allows me to save as either a PDF or SVG vector file but not as EMF.

After a long search I still cannot seem to find a way to do this with python. Hopefully anyone has an idea.

My workaround is to call inkscape using subprocess but this is far from ideal as I would like to avoid the use of external programs.

I'm running python 2.7.5 and matplotlib 1.3.0 using the wx backend.

JustMe
  • 237
  • 4
  • 7
  • Looks like EMF support was removed in [`matplotlib v1.3`](http://matplotlib.org/api/api_changes.html#changes-in-1-3) – tmdavison Feb 12 '16 at 16:44
  • I'm thinking about using pyEMF and an svg parser to write a little library to convert from svg to emf - somebody be my better judgement and stop me! – Shmack Aug 27 '22 at 22:24

2 Answers2

10
  • For anyone who still needs this, I wrote a basic function that can let you save a file as an emf from matplotlib, as long as you have inkscape installed.

I know the op didn't want inkscape, but people who find this post later just want to make it work.

import matplotlib.pyplot as plt
import subprocess
import os
inkscapePath = r"path\to\inkscape.exe"
savePath= r"path\to\images\folder"

def exportEmf(savePath, plotName, fig=None, keepSVG=False):
    """Save a figure as an emf file

    Parameters
    ----------
    savePath : str, the path to the directory you want the image saved in
    plotName : str, the name of the image 
    fig : matplotlib figure, (optional, default uses gca)
    keepSVG : bool, whether to keep the interim svg file
    """

    figFolder = savePath + r"\{}.{}"
    svgFile = figFolder.format(plotName,"svg")
    emfFile = figFolder.format(plotName,"emf")
    if fig:
        use=fig
    else:
        use=plt
    use.savefig(svgFile)
    subprocess.run([inkscapePath, svgFile, '-M', emfFile])
 
    if not keepSVG:
        os.system('del "{}"'.format(svgFile))

#Example Usage

import numpy as np
tt = np.linspace(0, 2*3.14159)
plt.plot(tt, np.sin(tt))
exportEmf(r"C:\Users\userName", 'FileName')
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Gilly Gumption
  • 111
  • 1
  • 7
  • I get a `PermissionError: [Errno 13] Permission denied: '\\filename.svg'` – Stücke Mar 24 '20 at 15:50
  • Got it. It works with `figFolder = savePath + r"{}.{}"` – Stücke Mar 24 '20 at 16:09
  • 1
    What does `-M` do? – Stücke Dec 08 '20 at 07:12
  • For Ubuntu, try https://stackoverflow.com/a/66450399/7842910 – Sam Macharia Mar 03 '21 at 05:20
  • I had a lot of trouble getting this solution to work. I had to modify the script to replace the `subprocess.run` line with `proc = subprocess.Popen([inkscapePath, svgFile, '--export-type=emf'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)` and `print(proc.communicate()[0])`. In addition to successfully exporting the emf format, these lines also pipe errors to the command line so that issues can be troubleshot. – nrp1000 Apr 28 '23 at 16:11
3

I think the function is cool but inkscape syntax seems not working in my case. I search in other post and find it as:

inkscape filename.svg --export-filename filename.emf 

So if I replace -M by --export-filename within the subprocess argument, everything works fine.

S.B
  • 13,077
  • 10
  • 22
  • 49
Chenyao
  • 29
  • 1
  • This ("--export-filename") worked for me. Any idea why the emf output fills the empty circles with a black back ground? – banbar Jun 26 '21 at 05:33
  • Sorry, I have no clue about it. But on another issue, I think it is better to specify the fig="fig" as default so that the "if loop" inside the function can work. This is to avoid specifying "fig" argument every time you apply the function. – Chenyao Jul 15 '21 at 21:48