8

How can I get matplotlib plots as emf or wmf files that are usable as vector graphics in MS Office (Word and PowerPoint)?

I've tried exporting to svg and converting to emf using both Inkscape and LibreOffice Draw, but both of those options seem to cause image quality loss resulting in raster images.

I've also tried exporting to pdf and converting to emf/wmf, but that has the same issue.

user1292456
  • 778
  • 4
  • 12
iamchoosinganame
  • 1,090
  • 6
  • 15
  • 2
    Since matplotlib does not provide any option to export to those formats, you will need to use some external conversion. Using inkscape for the conversion seems reasonable. I did not encounter any quality loss. – ImportanceOfBeingErnest Nov 07 '18 at 18:49
  • I also made a simple solution for saving to EMF [here](https://stackoverflow.com/a/59149291/7390266) – Gilly Gumption Dec 03 '19 at 16:28

2 Answers2

2

To save figures as .emf file in matplotlib using Linux, try the following:

  1. Install Inkscape (I have installed Inkscape 0.92.4 in Ubuntu 16.04. Other versions should work alike)
  2. In matplotlib, save the figure as .svg and then convert it to .emf via an Inkscape subprocess call. For example:
    import numpy as np
    import subprocess
    import matplotlib.pyplot as plt
    
    x = np.arange(2,50,step=2)
    y = x**2
    plt.plot(x,y)
    plt.savefig('y_is_x^2.svg', format='svg', bbox_inches='tight')
    subprocess.call('inkscape y_is_x^2.svg -M y_is_x^2.emf',shell=True)

You can then insert the .emf figure as a picture in MS Word or PowerPoint. The quality is near .svg. Be warned though, large .svg files may not work.

Sam Macharia
  • 803
  • 10
  • 18
1

Here is my solution to create WMF and SVG. You can install Inkscape and use the following class, 'SaveAndClosePlot' creates SVG and then by using the Inkscape it converted to WMF. TestPlot function can be customized for your need.

import os
from pathlib import Path
from ConfigParserM import logging
import subprocess
from matplotlib import pyplot as plt


class SVG_WMF_Plot:

    def __init__(self):
        self.__folderNameGraph = 'Graphs'
        self.__WMF_SVGSaving = True
        self.__inkScapePath = "C://Program Files//inkscape//inkscape.exe"
        self.__figureDPI = 500

    def getRootDirectory(self):
        try:
            return Path(os.path.dirname(os.path.realpath('__file__')))

        except Exception as e:
            logging.exception(e)
            raise

    def getAddressTo(self, Main=None, FolderName=None, FileName=None, Extension=None):
        try:
            if Main is None:
                Main = self.getRootDirectory()
            if FolderName:
                Path1 = Path(Main) / Path(FolderName)
            else:
                Path1 = Path(Main)

            if not os.path.exists(Path1):
                os.makedirs(Path1)
            if FileName:
                if Extension:
                    File_Address = Path1 / Path(FileName + "." + Extension)
                else:
                    File_Address = Path1 / Path(FileName)
            else:
                File_Address = Path1
            return File_Address

        except Exception as e:
            logging.exception(e)
            raise

    def TestPlot(self):
        try:

            fig, ax1 = plt.subplots()
            x = [1, 2]
            y = [1, 2]
            F1 = 'test'
            ax1.plot(x, y)
            self.SaveAndClosePlot(folderName=self.__folderNameGraph, fileName=F1)


        except Exception as e:
            logging.exception(e)
            raise

    def SaveAndClosePlot(self, folderName, fileName):
        try:
            Address = self.getAddressTo(FolderName=self.__folderNameGraph + f"\{folderName}", FileName=fileName, Extension="jpg")
            plt.savefig(Address, format='jpg', dpi=self.__figureDPI, bbox_inches='tight')

            if self.__WMF_SVGSaving:
                Address = self.getAddressTo(FolderName=self.__folderNameGraph + f"\{folderName}", FileName=fileName, Extension="svg")
                plt.savefig(Address, format='svg', dpi=self.__figureDPI, bbox_inches='tight')
                # add removing SVG if needed

                AddressWMF = self.getAddressTo(FolderName=self.__folderNameGraph + f"\{folderName}", FileName=fileName, Extension="wmf")
                subprocess.call([self.__inkScapePath, str(Address.resolve()), '--export-wmf', str(AddressWMF.resolve())])

            plt.clf()
            plt.close()
        except Exception as e:
            logging.exception(e)
            raise
Kayhan
  • 26
  • 4