27

Does anyone know how to save a Matplotlib figure as *.tiff? It seems that this format is not supported in Python, while the journals are quite often ask for that format.

I am adding some minimal code:

# -*- coding: utf-8 -*-

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

# fig setup
fig = plt.figure(figsize=(5,5), dpi=300)
ax = fig.gca(projection='3d')
ax.set_xlim([-1,1])
ax.set_ylim([-1,1])
ax.set_zlim([-1,1])
ax.axes.xaxis.set_ticklabels([])
ax.axes.yaxis.set_ticklabels([])
ax.axes.zaxis.set_ticklabels([])

# draw a surface
xx, yy = np.meshgrid(range(-1,2), range(-1,2))
zz = np.zeros(shape=(3,3))
ax.plot_surface(xx, yy, zz, color='#c8c8c8', alpha=0.3)
ax.plot_surface(xx, zz, yy, color='#b6b6ff', alpha=0.2)

# draw a point
ax.scatter([0],[0],[0], color='b', s=200)

This works:

fig.savefig('3dPlot.pdf')

But this does not:

fig.savefig('3dPlot.tif')
Georgy
  • 12,464
  • 7
  • 65
  • 73
striatum
  • 1,428
  • 3
  • 14
  • 31
  • Possible duplicate of [Save raw data as tif](http://stackoverflow.com/questions/19673619/save-raw-data-as-tif) – Essex Jun 21 '16 at 14:14
  • Unfortunately, they do ask for tiff-s. I know it's weird. Also, I did not work with it. – striatum Jun 21 '16 at 14:58
  • 2
    If you don't need accurate colour reproduction you could simply save as png and convert the png file to tiff. I've done that before. – Åsmund Jun 21 '16 at 17:58
  • 2
    I don't think this is a duplicate. Not every plot is a raw image. For example, if we start with a simple `plot(x, y)`, it is not clear at all how one could save that as `tif` with PIL/Pillow. – gerrit Jun 22 '16 at 18:58

4 Answers4

19

As a workaround, there would be nothing to stop you using the Python PIL package to save your image in TIFF format:

# -*- coding: utf-8 -*-

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

from PIL import Image
import io

# fig setup
fig = plt.figure(figsize=(5,5), dpi=300)
ax = fig.gca(projection='3d')
ax.set_xlim([-1,1])
ax.set_ylim([-1,1])
ax.set_zlim([-1,1])
ax.axes.xaxis.set_ticklabels([])
ax.axes.yaxis.set_ticklabels([])
ax.axes.zaxis.set_ticklabels([])

# draw a surface
xx, yy = np.meshgrid(range(-1,2), range(-1,2))
zz = np.zeros(shape=(3,3))
ax.plot_surface(xx, yy, zz, color='#c8c8c8', alpha=0.3)
ax.plot_surface(xx, zz, yy, color='#b6b6ff', alpha=0.2)

# draw a point
ax.scatter([0],[0],[0], color='b', s=200)

#fig.savefig('3dPlot.pdf')

# Save the image in memory in PNG format
png1 = io.BytesIO()
fig.savefig(png1, format="png")

# Load this image into PIL
png2 = Image.open(png1)

# Save as TIFF
png2.save("3dPlot.tiff")
png1.close()

If Python 2.x is being used, use cStringIO instead of BytesIO as follows:

import cStringIO

# Replace the BytesIO() call with
png1 = cStringIO.StringIO()
Martin Evans
  • 45,791
  • 17
  • 81
  • 97
10

This is great! Thanks ot Martin Evans. However, for those who would like to make it happen in Python3.x, small fixes (since cStringIO module is not available; and I would rather use BytesIO)

# -*- coding: utf-8 -*-

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

from PIL import Image
from io import BytesIO

# fig setup
fig = plt.figure(figsize=(5,5), dpi=300)
ax = fig.gca(projection='3d')
ax.set_xlim([-1,1])
ax.set_ylim([-1,1])
ax.set_zlim([-1,1])
ax.axes.xaxis.set_ticklabels([])
ax.axes.yaxis.set_ticklabels([])
ax.axes.zaxis.set_ticklabels([])

# draw a point
ax.scatter([0],[0],[0], color='b', s=200)

# save figure
# (1) save the image in memory in PNG format
png1 = BytesIO()
fig.savefig(png1, format='png')

# (2) load this image into PIL
png2 = Image.open(png1)

# (3) save as TIFF
png2.save('3dPlot.tiff')
png1.close()
Community
  • 1
  • 1
striatum
  • 1,428
  • 3
  • 14
  • 31
8

Matplotlib does support tif since version 1.1 but the support is optional and not obvious. As long as you have pillow installed, you can save to tif like you can save to any other format. Thus your example would simply be:

# -*- coding: utf-8 -*-

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import PIL # not necessary but mustn't fail

# fig setup
fig = plt.figure(figsize=(5,5), dpi=300)
ax = fig.gca(projection='3d')
ax.set_xlim([-1,1])
ax.set_ylim([-1,1])
ax.set_zlim([-1,1])
ax.axes.xaxis.set_ticklabels([])
ax.axes.yaxis.set_ticklabels([])
ax.axes.zaxis.set_ticklabels([])

# draw a surface
xx, yy = np.meshgrid(range(-1,2), range(-1,2))
zz = np.zeros(shape=(3,3))
ax.plot_surface(xx, yy, zz, color='#c8c8c8', alpha=0.3)
ax.plot_surface(xx, zz, yy, color='#b6b6ff', alpha=0.2)

# draw a point
ax.scatter([0],[0],[0], color='b', s=200)

fig.savefig('3dPlot.tif')
Tim Tröndle
  • 465
  • 5
  • 12
7

All you have to do is install Pillow . Then you can use just this:

fig.savefig('3dPlot.tiff')
Pratik Joshi
  • 389
  • 4
  • 13