はじめに
ggplotnim, nim-plotly, graph, gnuplot.nim等々、Nimにもグラフ描画ライブラリは複数あります。今回は私が使い慣れているPythonのmatplotlib
をNimで使う方法をまとめます。
matplotnim, nimpyとは
matplotnim
はmatplotlibのNim版ラッパーライブラリです。
nimpy
は、PythonからNim、並びにNimからPythonを呼ぶことを容易にするライブラリです。使用方法はNim初心者が始めるNimとnimpyなどを参考にしてください。
実行環境
Windows11 22H2
nim 1.6.10
matplotnim使用方法(エラー解消方法)
matplotnim自体がnimpyを用いているため、結局Pythonのインストールが必要となります。また、matplotnim公式もnimpyがあるので、自身が冗長であると言っています。 matplotnimを使用するメリットは、import文を使うことでよりPythonしてる感が出る程度です。 nimpyだけを用いる方法も後述します。
まず、nimbleからmatplotnimをダウンロードしましょう。
nimble install matplotnim
なおプログラム例は以下のようになります。
import matplotnim, nimpy # pltからの.呼出でnimpyが要る
let x = @[1, 2, 3, 4]
let y = @[5.5, 7.6, 11.1, 6.5]
discard plt.figure()
discard plt.plot(x, y)
discard plt.show()
さっそく実行すると、以下のエラーが出ました。
Python path configuration:
PYTHONHOME = (not set)
PYTHONPATH = (not set)
program name = 'python'
isolated = 0
environment = 1
user site = 1
import site = 1
sys._base_executable = 'c:\\code\\Nim\\matplotnim_test.exe'
sys.base_prefix = 'C:\\anaconda3'
sys.base_exec_prefix = 'C:\\anaconda3'
sys.platlibdir = 'lib'
sys.executable = 'c:\\code\\Nim\\matplotnim_test.exe'
sys.prefix = 'C:\\anaconda3'
sys.exec_prefix = 'C:\\anaconda3'
sys.path = [
'C:\\anaconda3\\python39.zip',
'.\\DLLs',
'.\\lib',
'c:\\code\\Nim',
]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'
Current thread 0x00006220 (most recent call first):
<no Python frame>
Error: execution of an external program failed: 'c:\code\Nim\matplotnim_test.exe '
同様のエラーから、PYTHONHOME
とPYTHONPATH
の環境変数を設定していないことが原因と知りました。Windows10のAnacondaで仮想環境にインストールしたパッケージがimportできない等を参考にして、PYTHONPATH
には自作のライブラリを格納したパス、PYTHONHOME
には標準の Python libraries のパスを指定します。
PYTHONHOME=C:\anaconda3
PYTHONPATH=C:\anaconda3\Library\bin
私は上記のように設定しましが、Pythonのインストール状況によってまちまちだと思います。また、今回はmatplotlibを呼び出したいだけなのでPYTHONPATH
の設定だけで動作すると思われます。
再起動して実行すると今度はこんなエラーが...
This application failed to start because it could not find or load the Qt platform plugin "windows"
in "".
Reinstalling the application may fix this problem.
Error: execution of an external program failed: 'c:\code\Nim\matplotnim_test.exe '
そもそもPython側で実行すると普通に動きます。
import matplotlib.pyplot as plt
print(plt.__file__) # C:\anaconda3\lib\site-packages\matplotlib\pyplot.py
x = [1, 2, 3, 4]
y = [5.5, 7.6, 11.1, 6.5]
plt.figure()
plt.plot(x, y)
plt.show()
Nim側とPython側では違うmatplotlibを呼び出しているかとも思いましたが、同じでした。
def searchPlace(lib):
return lib.__file__ # アンダーライン始まり・2連続はNimだと多分無理
import matplotnim, nimpy
let place = pyImport("searchPlace").callMethod("searchPlace", plt).to(string)
echo place # C:\anaconda3\lib\site-packages\matplotlib\pyplot.py
調べたところ、同様のエラーを発見したので同じようにQT_PLUGIN_PATH
を設定して再起動。
QT_PLUGIN_PATH=C:\anaconda3\Library\plugins
nimpyで同等の処理をする
ところで、matplotnimの実装は
import nimpy
let plt* = pyImport("matplotlib.pyplot")
以上です。実際matplotnimをインストールする必要はあまり感じません。
先の章でmatplotlibをインストールしていなければ、nimpyをインストールしましょう。
nimble install nimpy
先ほどのプログラムを少し変更して実行します。エラー対応は先の章の通りにしましょう。
import nimpy
let plt = pyImport("matplotlib.pyplot")
let x = @[1, 2, 3, 4]
let y = @[5.5, 7.6, 11.1, 6.5]
discard plt.figure()
discard plt.plot(x, y)
discard plt.show()
seq型が通るのであれば、ArraymancerのTensor型は通るのかと試しましたが、一度seq型にしないとダメなようです。
import nimpy, arraymancer
let plt = pyImport("matplotlib.pyplot")
let x = [1, 2, 3, 4].toTensor
let y = [5.5, 7.6, 11.1, 6.5].toTensor
discard plt.figure()
discard plt.plot(x.toSeq1D(), y.toSeq1D())
discard plt.show()
(更新) Windows起動時に表示されるメッセージへの対処法
QT_PLUGIN_PATH
を設定すると、Windows起動時に以下のエラーメッセージが表示されてしまいます。
そのため、以下のようにプログラム上で環境変数を設定して、プログラム動作時だけ機能するようにしましょう。
import nimpy, arraymancer
let plt = pyImport("matplotlib.pyplot")
let x = [1, 2, 3, 4].toTensor
let y = [5.5, 7.6, 11.1, 6.5].toTensor
# import os # Nim上での設定は反映されないらしい
# putEnv("QT_PLUGIN_PATH", r"C:\anaconda3\Library\plugins")
let os = pyImport("os")
os.environ["QT_PLUGIN_PATH"] = r"C:\anaconda3\Library\plugins"
# discard os.putenv("QT_PLUGIN_PATH", r"C:\anaconda3\Library\plugins") # 若しくは
discard plt.figure()
discard plt.plot(x.toSeq1D(), y.toSeq1D())
discard plt.show()
まとめ
nimpyを使えばPythonのライブラリを簡単に使えることがわかりました。
描画系ライブラリは他にもあるので、自分に合うものを試していきたいです。