pymatgenで結晶構造情報フォーマットcifを扱う

#Cifについて
Cif:Crystallographic Information Fileは
結晶学情報共通データ・フォーマット:結晶構造についての情報を詰め込んだ、国際結晶学連盟が推奨しているフォーマットです。
詳細はここ[表面分析研究会　無料記事vol.21](http://www.sasj.jp/JSA/CONTENTS/vol.21_2/Vol.21%20No.2/Vol.21%20No.2_04_Matsushita.pdf)にかなり詳しい記載があります。


例えば、NaCl（塩化ナトリウム）のCifはこんな感じです。

~~~

# generated using pymatgen
data_NaCl
_symmetry_space_group_name_H-M   'P 1'
_cell_length_a   3.50218997
_cell_length_b   3.50218997
_cell_length_c   3.50218997
_cell_angle_alpha   90.00000000
_cell_angle_beta   90.00000000
_cell_angle_gamma   90.00000000
_symmetry_Int_Tables_number   1
_chemical_formula_structural   NaCl
_chemical_formula_sum   'Na1 Cl1'
_cell_volume   42.95553177
_cell_formula_units_Z   1
loop_
 _symmetry_equiv_pos_site_id
 _symmetry_equiv_pos_as_xyz
  1  'x, y, z'
loop_
 _atom_site_type_symbol
 _atom_site_label
 _atom_site_symmetry_multiplicity
 _atom_site_fract_x
 _atom_site_fract_y
 _atom_site_fract_z
 _atom_site_occupancy
  Na  Na0  1  0.000000  0.000000  0.000000  1
  Cl  Cl1  1  0.500000  0.500000  0.500000  1


~~~

このままではただの文字列で分かりにくいので、pymatgenで読み込み数値データを利用しやすくします。

まずはMaterial Projectから上記の塩化ナトリウムのCifを取得します。

~~~~python3
#material projectから塩化ナトリウムのデータを取得する
import pandas as pd
from pymatgen.ext.matproj import MPRester

API_KEY = 'Your API' # Materials Project の API キー

with MPRester(API_KEY) as m:
    # m.get_data(chemsys_formula_id)は Material Projectから指定化合物のデータを取得
　  #chemsys_formula_id は、元素の組み合わせ(e.g.,Li-Fe-O)、化合物名(e.g.,Fe2O3)、
　　# またはMaterial Projectの材料id (e.g., mp-1234)のどれかを入れる.
    NaCl_df = pd.DataFrame(m.get_data('NaCl',data_type='vasp'))
~~~
NaClのデータは2個あるらしい。

~~~python3
NaCl_df['cif']
>>>
0    # generated using pymatgen\ndata_NaCl\n_symmet...
1    # generated using pymatgen\ndata_NaCl\n_symmet...
Name: cif, dtype: object

~~~

両方のNaClをpymatgenのStructureオブジェクトで取得します。

~~~python3
import pymatgen.io.cif as pycif 
from pymatgen.io.cif import CifParser

#cifを取り出す
NaCl_cif_1 = CifParser.from_string(NaCl_df['cif'][0])
NaCl_cif_2 = CifParser.from_string(NaCl_df['cif'][1])

#CifParser.get_structure　メソッドは　cifのデータを入力するとStructureの部分をリスト型に整形して返す
NaCl_1 =CifParser.get_structures(NaCl_cif_1)
NaCl_2 =CifParser.get_structures(NaCl_cif_2)

NaCl_1,NaCl_2
~~~

Cifの名データがだいぶ見やすい形で出力されました。

~~~
([Structure Summary
  Lattice
      abc : 4.02463512 4.02463511817503 4.024635115608324
   angles : 59.99999991890345 59.99999987171031 60.000000015
   volume : 46.09613775346724
        A : -3.4854362538293855 0.0 -2.0123175618249705
        B : -3.4854362538293855 0.0 2.0123175581750297
        C : -2.323624174916067 3.286100806051642 -3.78335363038218e-09
  PeriodicSite: Na (0.0000, 0.0000, 0.0000) [0.0000, 0.0000, 0.0000]
  PeriodicSite: Cl (-4.6472, 1.6431, -0.0000) [0.5000, 0.5000, 0.5000]],
~~~
~~~
 [Structure Summary
  Lattice
      abc : 3.50218997 3.50218997 3.50218997
   angles : 90.0 90.0 90.0
   volume : 42.95553176567333
        A : 3.50218997 0.0 2.1444728683832323e-16
        B : -2.1444728683832323e-16 3.50218997 2.1444728683832323e-16
        C : 0.0 0.0 3.50218997
  PeriodicSite: Na (0.0000, 0.0000, 0.0000) [0.0000, 0.0000, 0.0000]
  PeriodicSite: Cl (1.7511, 1.7511, 1.7511) [0.5000, 0.5000, 0.5000]])
~~~

この２つを見比べると'angles'の値が60-60-60と90-90-90とあるので、結晶構造違いのようです。
塩化ナトリウムの結晶構造は立方格子（ccp)のものが普通なので、60-60-60のものは高圧下での構造ですかね？

![81306024014311.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270149/ef47d4a6-4c95-316b-49d0-9e76148d0738.jpeg)

現状のNaCl_1はリスト型ですが、その中にはStructure型というpymatgenで広く使うオブジェクトが入っています。

~~~python3
type(NaCl_1)
>>>list

type(NaCl_1[0])
>>>pymatgen.core.structure.Structure
~~~

たとえば、latticeメソッド（lattice:格子)を使うと,
格子に関するデータを表示できます。

~~~python3
NaCl_1_Lattice = NaCl_1[0].lattice

NaCl_1_Lattice
>>>
Lattice
    abc : 4.02463512 4.02463511817503 4.024635115608324
 angles : 59.99999991890345 59.99999987171031 60.000000015
 volume : 46.09613775346724
      A : -3.4854362538293855 0.0 -2.0123175618249705
      B : -3.4854362538293855 0.0 2.0123175581750297
      C : -2.323624174916067 3.286100806051642 -3.78335363038218e-09
~~~

さらにvolumeメソッドでは体積の値を取得できます。

~~~python3
NaCl_1_Lattice.volume
>>>
46.09613775346724
~~~

これで扱いにくいcifから数値データを取得できたので、機械学習に使う素材データとして扱えそうです。