Matplotlib保存情节首选没有数据

时间:2018-11-26 13:55:49

标签: python matplotlib

当前,我正在考虑保存一个未知状态的matplotlib图,因为它正对着用户。我打算执行此操作的方法是将数字放在首位,然后将首选项放入字典中。但是,可以通过将任何基本类型保存到字典中,然后利用json库保存并将该字典加载到文件中来实现。

总体目标是具有操作系统独立性和跨matplotlib版本的兼容性。

我已经原型化了,将绘图的首选项/设置保存到字典中:

import numpy as np
from matplotlib import ticker
import matplotlib.pyplot as plt
import matplotlib.colors
import json

def get_dict_from_fig(fig):
  fig_dict = {}

  axes_list = []
  for ax in fig.axes:
    axes_list.append(get_dict_for_axes(ax))
  fig_dict["Axes"] = axes_list

  fig_dict["Properties"] = get_dict_from_fig_properties(fig)
  return fig_dict

def get_dict_for_axes(ax):
  ax_dict = {}

  # Get the axis properties
  ax_dict["Properties"] = get_dict_from_axes_properties(ax)

  # Get lines from the axes and store it's data
  lines_list = []
  for index, line in enumerate(ax.lines):
    lines_list.append(get_dict_from_line(line, index))
  ax_dict["Lines"] = lines_list

  texts_list = []
  for text in ax.texts:
    texts_list.append(get_dict_from_text(text))
  ax_dict["Texts"] = texts_list

  ax_dict["Title"] = get_dict_from_text(ax.title)
  ax_dict["XAxis Title"] = get_dict_from_text(ax.xaxis.label)
  ax_dict["YAxis Title"] = get_dict_from_text(ax.yaxis.label)

  # Potentially need to handle artists that are Text
  artist_text_dict = {}
  for artist in ax.artists:
    if isinstance(artist, matplotlib.text.Text):
      artist_text_dict = get_dict_from_text(artist)
  ax_dict["Text from artists"] = artist_text_dict

  legend_dict = {}
  legend = ax.get_legend()
  if legend is not None and legend.get_visible():
    legend_dict = get_dict_from_legend(legend)
    legend_dict["Visible"] = True
  ax_dict["Legend"] = legend_dict

  return ax_dict

def get_dict_from_axes_properties(ax):
  prop_dict = {}
  prop_dict["Bounds"] = ax.get_position().bounds
  prop_dict["Dynamic"] = ax.get_navigate()
  prop_dict["Axison"] = ax.axison
  prop_dict["Frame On"] = ax.get_frame_on()
  prop_dict["XAxis Properties"] = get_dict_from_axis_properties(ax.xaxis)
  prop_dict["YAxis Properties"] = get_dict_from_axis_properties(ax.yaxis)

  # XAxis scale and Xlim
  prop_dict["XAxis Scale"] = ax.xaxis.get_scale()
  prop_dict["XLim"] = ax.get_xlim()
  # YAxis scale and Ylim
  prop_dict["YAxis Scale"] = ax.xaxis.get_scale()
  prop_dict["YLim"] = ax.get_ylim()

  return prop_dict

def get_dict_from_axis_properties(ax):
  prop_dict = {}
  label1On = ax._major_tick_kw.get('label1On', True)

  if isinstance(ax, matplotlib.axis.XAxis):
    if label1On:
      prop_dict["Position"] = "Bottom"
    else:
      prop_dict["Position"] = "Top"
  elif isinstance(ax, matplotlib.axis.YAxis):
    if label1On:
      prop_dict["Position"] = "Left"
    else:
      prop_dict["Position"] = "Right"
  else:
    raise ValueError("Value passed is not a valid axis")

  prop_dict["nTicks"] = len(ax.get_major_locator()())
  if isinstance(ax.get_major_locator(), ticker.FixedLocator):
    prop_dict["Tick Values"] = list(ax.get_major_locator())
  else:
    prop_dict["Tick Values"] = None

  formatter = ax.get_major_formatter()
  if isinstance(formatter, ticker.FixedFormatter):
    prop_dict["Tick Format"] = list(formatter.seq)
  else:
    prop_dict["Tick Format"] = ""

  labels = ax.get_ticklabels()
  if labels:
    prop_dict["Font size"] = labels[0].get_fontsize()
  else:
    prop_dict["Font size"] = ""

  prop_dict["Scale"] = ax.get_scale()
  prop_dict["Grid Style"] = get_dict_for_grid_style(ax)
  prop_dict["Visible"] = ax.get_visible()

  return prop_dict

def get_dict_for_grid_style(ax):
  grid_style = {}
  gridlines = ax.get_gridlines()
  if ax._gridOnMajor and len(gridlines) > 0:
    grid_style["Color"] = matplotlib.colors.to_hex(gridlines[0].get_color())
    grid_style["Alpha"] = gridlines[0].get_alpha()
    grid_style["Grid On"] = True
  else:
    grid_style["Grid On"] = False
  return grid_style

def get_dict_from_line(line, index=0):
  line_dict = {}
  line_dict["Line Index"] = index
  line_dict["Label"] = line.get_label()
  line_dict["Alpha"] = line.get_alpha()
  if line_dict["Alpha"] is None:
    line_dict["Alpha"] = 1
  line_dict["Color"] = matplotlib.colors.to_hex(line.get_color())
  line_dict["Linewidth"] = line.get_linewidth()
  line_dict["Line Style"] = line.get_linestyle()
  line_dict["Marker Style"] = get_dict_from_marker_style(line)
  return line_dict

def get_dict_from_marker_style(line):
  style_dict = {}
  style_dict["Face Color"] = matplotlib.colors.to_hex(line.get_markerfacecolor())
  style_dict["Edge Color"] = matplotlib.colors.to_hex(line.get_markeredgecolor())
  style_dict["Edge Width"] = line.get_markeredgewidth()
  style_dict["Marker Type"] = line.get_marker()
  style_dict["Marker Size"] = line.get_markersize()
  style_dict["ZOrder"] = line.get_zorder()
  return style_dict

def get_dict_from_text(text):
  text_dict = {}
  text_dict["Text"] = text.get_text()
  if text_dict["Text"]:
    text_dict["Transform"] = text.get_transform()
    text_dict["Position"] = text.get_position()
    text_dict["Style"] = get_dict_from_text_style(text)
  return text_dict

def get_dict_from_text_style(text):
  style_dict = {}
  style_dict["Alpha"] = text.get_alpha()
  if style_dict["Alpha"] is None:
    style_dict["Alpha"] = 1
  style_dict["Text Size"] = text.get_size()
  style_dict["Color"] = matplotlib.colors.to_hex(text.get_color())
  style_dict["hAlign"] = text.get_horizontalalignment()
  style_dict["vAlign"] = text.get_verticalalignment()
  style_dict["mAlign"] = text._multialignment
  style_dict["Rotation"] = text.get_rotation()
  style_dict["ZOrder"] = text.get_zorder()
  return style_dict

def get_dict_from_legend(legend):
  legend_dict = {}
  legend_elements_list = get_list_of_legend_children(legend)
  legend_elements_list.append(legend.legendPatch)

  text_list = []
  line_list = []
  for child in legend_elements_list:
    try:
      if isinstance(child, matplotlib.text.Text):
        if child.get_text() != None:
          text_list.append(get_dict_from_text(child))
      if isinstance(child, matplotlib.lines.Line2D):
        line_list.append(get_dict_from_line(child))
    except NotImplementedError:
      # Basically do nothing
      pass
      legend_dict["Text"] = text_list
      legend_dict["Line List"] =  line_list
      return legend_dict


def get_list_of_legend_children(legend):
  legend_list = []
  if hasattr(legend, 'get_children') and len(legend.get_children()) > 0:
    for child in legend.get_children():
      legend_list.append(get_list_of_legend_children(child))
  else:
    legend_list.append(legend)
  return legend_list

def get_dict_from_fig_properties(fig):
  fig_dict = {}
  fig_dict["Fig width"] = fig.get_figwidth()
  fig_dict["Fig height"] = fig.get_figheight()
  fig_dict["dpi"] = fig.dpi
  return fig_dict

XVals = np.array([1, 2, 3])
YVals = np.array([1, 2, 3])

plt.plot(XVals, YVals)
dictionary = get_dict_from_fig(plt.gcf())

f = open("./savefile.json", "w+")
f.write(json.dumps(dictionary, indent=4))

我想知道是否已经可以通过维护的库来执行此操作?我试图找到一些办法来做,除了灵感,我找不到任何有用的东西。我已经使用mpld3作为灵感。

我可能早些时候已经提到过这一点,但是在保存时,关键是要加载回已保存的数据,否则保存起来毫无意义。

0 个答案:

没有答案