Xenonpyによる記述子の作成
本記事の概要
本記事では、Xenonpyを用いた記述子の作成方法を紹介する。
Pythonの基礎は習得していることを前提に話を進めていく。
目次:
Xenonpyとは
XenonPyは、統計数理研究所ものづくりデータ科学研究センターのチーム (Chang Liu 特任助教、野口瑶 特任研究員、Stephen Wu 助教、山田寛尚 特任研究員、吉田亮 同センター長) が物質・材料研究機構と共同開発しているマテリアルズインフォマティクス (MI) のオープンソースプラットフォーム。XenonPyには、様々なマテリアルインフォマティクスのアプリケーションのためのツールが豊富に用意されている。記述子生成クラスでは、組成、構造から数種類の数値記述子を計算することができる。
以下、公式ドキュメント
xenonpy.readthedocs.io
早速、実装
Xenonpyのインストール方法は、以下のサイトを参考にしてください。
xenonpy.readthedocs.io
Xenonpyを使用するために、以下のrdkitをインストールしておく必要がある。
! conda install --yes -c rdkit rdkit #最初にinstallしてください。
ライブラリのインポート
import pandas as pd import numpy as np import os, sys,warnings warnings.filterwarnings('ignore') from pymatgen.io.cif import CifParser from pymatgen.core.composition import Composition from xenonpy.descriptor import Compositions,Structures
組成記述子の作成
与えられた化学組成に対して290種類の組成特性を計算することができるらしい。
全ての記述子を確認したい方は、以下のURLをご確認ください。
xenonpy.readthedocs.io
XenonpyのCompositionsクラスでは、辞書形式に変換された組成から記述子を計算することができる。
注意)Compositionsは、Xenonpyの記述子を計算するためのクラス、CompositionはPymatgenの組成を辞書形式に変換してくれるクラス。自分で組成を辞書形式にするのが面倒であるため、PymatgenのCompositionクラスを使用している。 そして、Compositionsクラスに”composition”という列名があるデータフレームを渡すと組成情報から組成記述子を作成することができる。
def comp_descriptors(comp_holder): comp_holder = [Composition(x) for x in comp_holder] #Change strings(compositions) into dictionary df = pd.DataFrame({'composition':comp_holder}) cal_comp = Compositions() descriptor_comp = cal_comp.transform(df) #Make descriptors return descriptor_comp comp_holder = [ 'Li2O', 'MgO', 'LiCoO2', 'MgCo2O4', 'Fe' ] df = comp_descriptors(comp_holder) df
>(出力)
構造記述子の作成
構造記述子は、RDF(radial distribution function) OFM (orbital field matrix)2) を使用している。
参考)Pham et al. Machine learning reveals orbital interaction in materials, Sci Technol Adv Mater. 18(1): 756-765, 2017.
私が作成したプログラムではcifファイルが入っているディレクトリで、以下の関数を実行する必要がある。 そのためcifファイルが入っているディレクトリへのパスを引数で渡している。
Xenonpyでは、cifではなくPOSCARを読み取り構造記述子を作成する。この変換のプログラムなどは作成するのが面倒なのでPymatgenを使用している。そして、POSCAR形式の情報をデータフレームに格納し、その列名を"structure"にしておくことで、Structureクラスが読み取ることができ、構造記述子を計算することができる。
def getciflist(path_to_cif): ls = os.listdir(path_to_cif) calclist = [] for i in ls: if '.cif' in i: calclist.append(i.rstrip()) return calclist def str_descript(path_to_cif): #strはstructureの略 cif_list = getciflist(path_to_cif) str_holder = [] cif_holder = [] for cif in tqdm(cif_list): #時間がかかる場合があるので、tqmdでprogressバーを表示している cif_p = CifParser(cif)#cifの読み込み str_holder.append(cif_p.get_structures())#cifをPOSCARに変換している。 df = pd.DataFrame({'structure':str_holder}) cal_str = Structures() descriptor_str = cal_str.transform(df)#Make descriptors return descriptor_str cwd='./' df = str_descript(cwd) df
>(出力)
今回は、3つのcifファイルを用意したので、3つの結晶構造について記述子を獲得できている。
構造記述子は、合計で約1200個程度であることがわかる。
おまけ 組成記述子と構造記述子を同時に作成
実は、cifファイルがあれば、組成情報もcifファイルに書かれているので cifファイルから、組成記述子・構造記述子両方を作成することが可能である。 それが以下の関数になっている。
def getdescripts(path_to_cif): cif_list = getciflist(path_to_cif) str_holder = [] comp_holder =[] cif_holder = [] for cif in tqdm(cif_list):#時間がかかる場合があるので、tqmdでprogressバーを表示している with open(cif) as r: for i in r: if '_chemical_formula_sum' in i: comp_str = '' for j in i.split("\'")[1].split(): comp_str += j comp_holder.append(Composition(comp_str)) cif_p = CifParser(cif) str_holder.append(cif_p.get_structures()) cif_holder.append(cif) df = pd.DataFrame({'cif':cif_holder,'structure':str_holder,'composition':comp_holder}) df = df.set_index('cif') cal_comp = Compositions() cal_str = Structures() descriptor_comp = cal_comp.transform(df) descriptor_str = cal_str.transform(df) descriptor_comp_str = pd.merge(descriptor_comp,descriptor_str,left_index=True, right_index=True) return descriptor_comp_str cwd='./' df = getdescripts(cwd) df
>(出力)
組成記述子と構造記述子両方欲しい場合には、こんな感じにプログラムをかくと便利。
#コードが読みにくくて、大変申し訳ない。。。