LoginSignup
0
0

More than 3 years have passed since last update.

rubyistがpycallでpython::Dictデータで苦労した話

Posted at

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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0