LoginSignup
0
2

More than 1 year has passed since last update.

Pymatgenチュートリアル② Materials Projectのデータを持ってくる

Last updated at Posted at 2021-07-11

はじめに

この記事で書くこと

前回は、一番基本的な使い方ということで、ElementとCompositionについて書いた。

この記事では、Materials Projectからデータを引っ張ってくる方法について学ぶ。この記事を読む人がMaterials Projectについて知らないことはないと思うので、説明は割愛するが、簡単に言えば、計算ベースの無機材料データベースだ。

今回の記事では、このデータベースから、化合物情報を検索し、手元で扱えるように持ってくることを目指す。

使用するバージョン

pymatgen 2022.0.8
2020.x.xくらいのバージョンだと関数の呼び出し方が違っていてエラーが起きるかもしれないので注意。

実際の操作

前準備 -Materials Projectへの登録とAPIキーの入手-

pymatgenを使ってデータを持ってくるには、まず (i) Materials Projectへの登録 を行った後、(ii) APIキーの取得 という手順を踏む。(i)については、特別なことは何もなく、上に示したプロジェクトのページからメールアドレスで登録するか、GoogleやGithubのアカウントでログインする。
(ii)については、少し説明を加える。Mterials Projectにログインすると、上の方に、下図のようなバーがあるのがわかると思う。
スクリーンショット 2021-07-07 19.38.46.png
この中の、'API'と書かれたところをクリックすると、文字だらけのページに遷移する。その中から、'API keys'という見出しの部分に、以下のような文言がある:
To use the MAPI, you need to first have an API key. We have detected that you already have the following API key generated:
この直後に、ランダムなような文字列が、(多分、赤字で)表示されていると思う。これがAPIキーと呼ばれるものだ。pymatgenからデータベースにアクセスするときは、このキーを使うので、どこかにコピって置いておくか、このページをそのままにしておく。

pymatgenを使ったデータの取得

それでは、早速データをとってこよう。ここでは、MPResterというものを使う

#MPRester:Materials Projectからデータを持ってくるためのモジュール
from pymatgen.ext.matproj import MPRester
#APIは自分のやつを持ってくる
API_KEY='さっきメモった文字列'

基本的な考え方は、「検索クエリをかけると、ヒットした結果を返してくる」というものになる。しばらく弄っている感じ、無機化合物を検索する場合に思いつく検索方法は、大体実装されていると考えてよさそう。例えば、組成式で検索をかけるなら、以下のようになる。

#特定の組成式で化合物を検索するパターン
with MPRester(API_KEY) as m:
    mats = m.get_data('BaTiO3')

すると、matsという変数に、検索結果のデータが収納された。要するに、

with MPRester(API_KEY) as m:
    mats = m.get_data(検索文字列)

という書式で、検索することができる。ここでまず気になるのは、このmatsという変数の中に、どのようにデータが格納されていて、どうやってデータを取り出すか、ということだ。まずは型を確認する。

print(type(mats))
#出力結果:<class 'list'>

なるほど、リスト型でデータが格納されたらしい。ということは、中のデータを取り出すには、例えば以下のようにしてやればいい。

display(mats[0])
#出力結果:
#{'energy': -31.02144054,
# 'energy_per_atom': -6.204288108,
# 'volume': 85.16422489125648,
# 'formation_energy_per_atom': -1.6848189356666665,
# 'nsites': 5,
# 'unit_cell_formula': {'Ba': 1.0, 'Ti': 1.0, 'O': 3.0},
# 'pretty_formula': 'BaTiO3',
# 'is_hubbard': False,
# 'elements': ['Ba', 'Ti', 'O'],
# 'nelements': 3,
# 以下略

print(type(mats[0]))
#出力結果:<class 'dict'>

ぱっと見で、これが何がしか1種類の化合物の情報の羅列であることがわかる。さらに、型が辞書型である。つまり、matsというリストには、化合物1つにつき1つの辞書でデータが格納されていることになる。ということは、さらに以下のようにすれば、ある化合物の、特定の特性を読み出すことができる。

print(mats[0]['pretty_formula'])
#出力結果:BaTiO3

さて、実際の使用を考えると、検索結果を一覧して、「今、自分が欲しい化合物」がどれかを調べるには、組成式、晶系、空間群くらいがわかればよいだろう。また、元のmats(リスト)の何番目を指定すれば、そのデータが手に入るか、も気になるところ。というわけで、以下のようなコードを走らせて、ここら辺の情報を一覧する。

for i, mat in enumerate(mats):
    print(i, mat['pretty_formula'], mat['spacegroup']['crystal_system'], mat['spacegroup']['symbol'])
#出力結果:
#0 BaTiO3 tetragonal P4/mmm
#1 BaTiO3 tetragonal P4mm
#2 BaTiO3 orthorhombic Amm2
#3 BaTiO3 orthorhombic Amm2
#4 BaTiO3 cubic Pm-3m
#5 BaTiO3 orthorhombic C222_1
#6 BaTiO3 orthorhombic Amm2
#7 BaTiO3 hexagonal P6_3/mmc
#8 BaTiO3 trigonal R3m
#9 BaTiO3 orthorhombic Amm2
#10 BaTiO3 cubic Pm-3m

これで、matsに格納されているデータを頭から順番に見て、組成式、晶系、空間群を得ることができた。(今のケースでは、組成式は全部同じだけど。)この中から1つピックアップして、情報を取り出してみることにする。せっかくなので、室温強誘電のBaTiO3を選ぶことにする。これは空間群P4mmなので、mats[1]の化合物である。

ferroel_BTO = mats[1]
print(ferroel_BTO['band_gap'])
print(ferroel_BTO['density'])
display(ferroel_BTO['diel'])

#出力結果:
#1.8297999999999996
#5.748582891575844
#{'e_electronic': [[6.267598999999999, 0.0, 0.0],
#  [0.0, 6.267598999999999, 0.0],
#  [0.0, 0.0, 5.163823999999999]],
# 'e_total': [[7.6526499999999995, 0.0, 0.0],
#  [0.0, 7.6526499999999995, 1.3552527156068805e-20],
#  [0.0, 1.3552527156068805e-20, 19.243076999999996]],
# 'n': 2.428924453333203,
# 'poly_electronic': 5.899673999999998,
# 'poly_total': 11.516125666666666}

代表的な物性ということで、バンドギャップ、密度、誘電率テンソルを持ってきてみたが、実測とは結構ズレているので、使い方には注意が必要という印象。さて、ここまで動かしてみて、「Materials Projectのサイトよりもデータ少なくない?DoSは?」という感想を持った。調べてみたら、ちゃんと表示する方法はある、、、が、長くなりそうなので、それは別のチュートリアルに書くことにする。

cifの取得方法

すでに気づいている人は気づいていると思うが、持ってきたデータの中には、cifのデータが入っている。cifを保存できれば、構造の情報は全て持ってこれると言っても過言ではない。

display(ferroel_BTO['cif'])

長いので、出力結果は省略するが、よく見るcifの内容が出力される。これを、保存しておいて使いたいので、以下のようなコードを走らせよう。ここはpymatgenの使い方というより、一般的なPythonの使い方なので、詳しくは省略するが、path_output_dirで指定したフォルダの中に、cifを保存している。(あえて新しいフォルダを作るのは、cifが増えたときに収集がつかなくなるから。)

#フォルダを扱うためのモジュール
import os

#cifを保存する先のフォルダの名前を指定する
path_output_dir = "./cif/"

#その名前のフォルダが存在しなければ新しく作成し、あればそこに保存する。
if not os.path.exists(path_output_dir):
    os.makedirs(path_output_dir)

with open(path_output_dir+ferroel_BTO['material_id']+".cif", mode="w") as f:
    f.write(ferroel_BTO['cif'])

cifから色々とデータを取り出すのは、また次のチュートリアルで書くことにする。

他の検索の仕方

化合物に含まれる元素で検索

「合成してみたら知らないXRDピークが出てきた。これはなんや。」といった場合に、参考データを持ってくるのに使える。こっちの例なら、一覧に組成式を表示している意味も出てくる。

#含まれる元素で化合物を検索するパターン
with MPRester(API_KEY) as m:
    mat_sys_BZO = m.get_data('Ba-Zr-O')

#組成式、晶系、空間群を表示する
for i, mat in enumerate(mat_sys_BZO):
    print(i, mat['pretty_formula'], mat['spacegroup']['crystal_system'], mat['spacegroup']['symbol'])

#出力結果:
#0 Ba6ZrO8 cubic Fm-3m
#1 BaZrO3 cubic Pm-3m
#2 Ba2Zr7O16 trigonal R-3
#3 Ba4ZrO6 trigonal R-3c
#4 Ba2ZrO4 tetragonal I4/mmm
#5 Ba2ZrO6 tetragonal P4/mmm
#6 BaZrO3 tetragonal I4/mcm
#7 Ba3Zr2O7 tetragonal I4/mmm

ワイルドカードを使って検索

例えば、新しく材料を合成する際、候補を探してくる時などに使える。「*」(アスタリスク)がワイルドカードで、以下の例では、一般式ABO3を持つ化合物を検索している。

#ワイルドカードを使って検索するパターン
with MPRester(API_KEY) as m:
    ABO3 = m.get_data('**O3')

#それぞれの化合物のデータがリストに格納される
print(len(ABO3))

for i, mat in enumerate(ABO3[:5]):
    print(i, mat['pretty_formula'], mat['spacegroup']['crystal_system'], mat['spacegroup']['symbol'])

#出力結果:
#2509
#0 AcAlO3 cubic Pm-3m
#1 AcBO3 cubic Pm-3m
#2 AcCrO3 cubic Pm-3m
#3 AcCuO3 cubic Pm-3m
#4 AcFeO3 cubic Pm-3m

格納されたデータの量が多い(len(ABO3)で示した通り、2509件ヒットしてる)ので、最初の5つだけ表示している。ワイルドカードに添字をつけることも可能で、「Fe*2」などとすれば、一般式FeX2を持つ化合物を検索することができる。ちなみに、「化合物に含まれる元素を使って検索」する場合でもワイルドカードを使うことができ、例えば「*-Fe-O」などのようにクエリをかける。

公式ドキュメントによると、さらに高度な検索オプションを使用することができるが、以上のような検索ができれば、データをざっくり持ってくることに支障はない。(それに、そこに手を出すと、この記事が長くなりすぎる。)というわけで、この記事はここまでにする。また必要になったら、別記事として書くかもしれない。

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