rubyistがpycallでpython::Dictデータで苦労した話
PyCall Ruby版
Tipsにほぼ完璧な対応報告がある.
さらに,numpy特有の記法
# 最後の行へのアクセス pythonだと m[-1,:] と書くところ
などと,rubyistにわかりやるいnumpyの解説まで付いている.
という風に簡単にできそうに見える...
複雑なデータ構造だとお手上げ
ところが,複雑なpythonのデータ構造を扱う時には
非常に苦労する.原因はdictのkeyがよくわからないから.
単純な文字を取る時にはいいが,少し複雑な文字ではうまく取れないようだ.
以下の通りにしてpymatgenにあるVasprun::tdosあるいは
Vasprun::compolete_dos などが取れる.
ところが,
p spd_dos = dosrun.complete_dos.get_spd_dos() とすると,
{<OrbitalType.s: 0>: <pymatgen.electronic_structure.dos.Dos
object at 0x102dd4710>, <OrbitalType.p: 1>:
<pymatgen.electronic_structure.dos.Dos object at 0x102dc2dd8>,
<OrbitalType.d: 2>: <pymatgen.electronic_structure.dos.Dos
object at 0x102d962b0>}
と出力される.これはspd_dos('OrbitalType.s')で取れそうに思うが
だめ.そこで,
p s_d = spd_dos.to_a[0][1].densities
として
array([ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
...
])
python::arrayにして,さらに
s_list = PyCall::List.(s_d.to_a[0][1]).to_a
としてhashをarrayにしてvalsを取り出し,さらにそれをto_aでrubyが解釈できるdata構造に変換している.
慣れると同じcodeの繰り返しなんでそれほど苦労しなくなるが,
多分時間が経てば忘れるね.
そこをlibに組み込んで欲しいが,dictを直接読むのは文字だけのよう...
code書いて,pull reqかけてみるか.
densitiesやenergyはnameがわからないとどうしようもなくて,
これは,pymatgenのsource codeを読んで見つける.
どうもpycallを使うには,こういうのを繰り返す必要がありそうだ.
require 'pycall/import'
include PyCall::Import
pyimport :sys
pyimport 'numpy', as: :np
pyfrom 'pymatgen.io.vasp.outputs', import: :Vasprun
# dos
dosrun = Vasprun.("../dos_calc_fine/vasprun.xml")
e_object = (dosrun.tdos.energies - dosrun.efermi)
energy = PyCall::List.(e_object).to_a
spd_dos = dosrun.complete_dos.get_spd_dos()
spd = PyCall::Dict.(spd_dos)
s_d = spd.to_a[0][1].densities
s_list = PyCall::List.(s_d.to_a[0][1]).to_a
p_d = spd.to_a[1][1].densities
p_list = PyCall::List.(p_d.to_a[0][1]).to_a
d_d = spd.to_a[2][1].densities
d_list = PyCall::List.(d_d.to_a[0][1]).to_a
tdos = dosrun.tdos.densities
t_list = PyCall::List.(tdos.to_a[0][1]).to_a
require 'numo/gnuplot'
Numo.gnuplot do
set yrange: '[-10:10]'
plot [s_list, energy, w: :l, title: 's'],
[p_list, energy, w: :l, title: 'p'],
[d_list, energy, w: :l, title: 'd'],
[t_list, energy, w: :l, title: 'total']
end