3

matplotlib 1.2.0には新しい実験的な機能があり、数字を選択できることをすでにご存知かもしれません(pickleモジュールで保存できます)。

ただし、ログスケールを使用する場合は機能しません。

import matplotlib.pyplot as plt
import numpy as np
import pickle
ax = plt.subplot(111)
x = np.linspace(0, 10)
y = np.exp(x)
plt.plot(x, y)
ax.set_yscale('log')
pickle.dump(ax, file('myplot.pickle', 'w'))

結果:

PicklingError: Can't pickle <class 'matplotlib.scale.Log10Transform'>: attribute lookup matplotlib.scale.Log10Transform failed

誰かがこれに対する解決策/回避策を知っていますか?

4

1 に答える 1

4

matplotlibのgithub課題追跡システムのバグレポートとしてこれを開きました。matplotlibリポジトリ側で実装するのはかなり簡単な修正です(単にLog10Transformクラス内にLogScaleクラスをネストしないでください)が、それはmpl1.2.0でこれを使用できるようにするのに実際には役立ちません...

これを1.2.0で機能させるための解決策がありますが、警告します-きれいではありません!

ピクルスの質問に対する私の答えに基づいて、ネストされたクラスを(そのままLog10Transformで)ピクルスにすることが可能です。私たちがする必要があるのは、それ自体Log10Transformを「減らす」方法を教えることだけです。

import matplotlib.scale

class _NestedClassGetter(object):
    """
    When called with the containing class as the first argument, 
    the name of the nested class as the second argument,
    and the state of the object as the third argument,
    returns an instance of the nested class.

    """
    def __call__(self, containing_class, class_name, state):
        nested_class = getattr(containing_class, class_name)
        # return an instance of a nested_class. Some more intelligence could be
        # applied for class construction if necessary.
        c = nested_class.__new__(nested_class)
        c.__setstate__(state)
        return c

def _reduce(self):
    # return a class which can return this class when called with the 
    # appropriate tuple of arguments
    cls_name = matplotlib.scale.LogScale.Log10Transform.__name__
    call_args = (matplotlib.scale.LogScale, cls_name, self.__getstate__())
    return (_NestedClassGetter(), call_args)

matplotlib.scale.LogScale.Log10Transform.__reduce__ = _reduce 

他のログベースの変換/クラスに対してもこれを行うことを決定するかもしれませんが、あなたの例では、これであなたの例の図をピクルスにする(そして首尾よくアンピクルする)ことができます:

import matplotlib.pyplot as plt
import numpy as np
import pickle


ax = plt.subplot(111)
x = np.linspace(0, 10)
y = np.exp(x)
plt.plot(x, y)
ax.set_yscale('log')

pickle.dump(ax, file('myplot.pickle', 'w'))
plt.savefig('pickle_log.pre.png')
plt.close()

pickle.load(file('myplot.pickle', 'r'))
plt.savefig('pickle_log.post.png')

mpl 1.3.xでこれを修正して、この厄介な回避策が将来必要にならないようにします:-)。

HTH、

于 2012-11-28T11:14:04.510 に答える