<reponame>stkterry/collatzpy<filename>collatzpy/plot/helpers/size_fix.py
from matplotlib.image import imread
from tempfile import NamedTemporaryFile


def __get_size(fig, dpi=100):
  """Helper to set_size.  Tests the size of a temp file in mpl."""
  with NamedTemporaryFile(suffix='.png') as f:
    fig.savefig(f.name, bbox_inches='tight', dpi=dpi)
    height, width, _channels = imread(f.name).shape
    return width / dpi, height / dpi


def set_size(fig, size, dpi=100, eps=1e-2, give_up=2, min_size_px=10):
  """Adjusts the given figure to perfectly match the given size.

  This is just a hack/fix for matplotlib.  When saving images
  mpl rarely saves the figure as the exact size specified.
  This ensures it does.
  """
  target_width, target_height = size
  set_width, set_height = target_width, target_height
  deltas = []
  while True:
    fig.set_size_inches([set_width, set_height])
    actual_width, actual_height = __get_size(fig, dpi=dpi)
    set_width *= target_width / actual_width
    set_height *= target_height / actual_height
    deltas.append(
        abs(actual_width - target_width) + abs(actual_height - target_height))
    if deltas[-1] < eps:
      return True
    if (len(deltas) > give_up
            and sorted(deltas[-give_up:]) == deltas[-give_up:]):
      return False
    if set_width * dpi < min_size_px or set_height * dpi < min_size_px:
      return False

from matplotlib.image import imread
from tempfile import NamedTemporaryFile


def __get_size(fig, dpi=100):
  """Helper to set_size.  Tests the size of a temp file in mpl."""
  with NamedTemporaryFile(suffix='.png') as f:
    fig.savefig(f.name, bbox_inches='tight', dpi=dpi)
    height, width, _channels = imread(f.name).shape
    return width / dpi, height / dpi


def set_size(fig, size, dpi=100, eps=1e-2, give_up=2, min_size_px=10):
  """Adjusts the given figure to perfectly match the given size.

  This is just a hack/fix for matplotlib.  When saving images
  mpl rarely saves the figure as the exact size specified.
  This ensures it does.
  """
  target_width, target_height = size
  set_width, set_height = target_width, target_height
  deltas = []
  while True:
    fig.set_size_inches([set_width, set_height])
    actual_width, actual_height = __get_size(fig, dpi=dpi)
    set_width *= target_width / actual_width
    set_height *= target_height / actual_height
    deltas.append(
        abs(actual_width - target_width) + abs(actual_height - target_height))
    if deltas[-1] < eps:
      return True
    if (len(deltas) > give_up
            and sorted(deltas[-give_up:]) == deltas[-give_up:]):
      return False
    if set_width * dpi < min_size_px or set_height * dpi < min_size_px:
      return False
Helper to set_size.  Tests the size of a temp file in mpl. Adjusts the given figure to perfectly match the given size.    This is just a hack/fix for matplotlib.  When saving images   mpl rarely saves the figure as the exact size specified.   This ensures it does.