xonsh/xontrib/mplhooks.py
Derek Thomas 57d1b3b38e mpl adjusts subplot positions to force no margins
- does not use tight layout anymore
2016-10-03 23:51:27 +09:00

81 lines
2.6 KiB
Python

"""Matplotlib hooks, for what its worth."""
import shutil
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import pickle
from xonsh.tools import print_color, ON_WINDOWS
def figure_to_rgb_array(fig, width, height):
"""Converts figure to a numpy array of rgb values
Forked from http://www.icare.univ-lille1.fr/wiki/index.php/How_to_convert_a_matplotlib_figure_to_a_numpy_array_or_a_PIL_image
"""
# perform a deep copy using pickel because
# Figure is currently not compatible with 'deepcopy'
fig_copy = pickle.loads(pickle.dumps(fig))
w, h = fig_copy.canvas.get_width_height()
dpi = fig_copy.get_dpi()
fig_copy.set_size_inches(width/dpi, height/dpi, forward=True)
width, height = fig_copy.canvas.get_width_height()
for ax in fig_copy.get_axes():
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_xlabel('')
ax.set_ylabel('')
ax.set_title('')
# remove all space between subplots
fig_copy.subplots_adjust(wspace=0, hspace=0)
# move all subplots to take the entirety of space in the figure
# leave only one line for top and bottom
fig_copy.subplots_adjust(bottom=1/height, top=1-1/height, left=0, right=1)
fig_copy.set_frameon(False)
fig_copy.set_facecolor('w')
font_size = matplotlib.rcParams['font.size']
matplotlib.rcParams.update({'font.size': 1})
# Draw the renderer and get the RGB buffer from the figure
fig_copy.canvas.draw()
buf = np.fromstring(fig_copy.canvas.tostring_rgb(), dtype=np.uint8)
buf.shape = (height, width, 3)
# clean up and return
matplotlib.rcParams.update({'font.size': font_size})
# close the figure that was created
plt.close(fig_copy)
return buf
def buf_to_color_str(buf):
"""Converts an RGB array to a xonsh color string."""
space = ' '
pix = '{{bg#{0:02x}{1:02x}{2:02x}}} '
pixels = []
for h in range(buf.shape[0]):
last = None
for w in range(buf.shape[1]):
rgb = buf[h, w]
if last is not None and (last == rgb).all():
pixels.append(space)
else:
pixels.append(pix.format(*rgb))
last = rgb
pixels.append('{NO_COLOR}\n')
pixels[-1] = pixels[-1].rstrip()
return ''.join(pixels)
def show():
fig = plt.gcf()
w, h = shutil.get_terminal_size()
if ON_WINDOWS:
w -= 1 # @melund reports that win terminals are too thin
h -= 1 # leave space for next prompt
buf = figure_to_rgb_array(fig, w, h)
s = buf_to_color_str(buf)
print_color(s)