CODで遊ぶ (2016/04/16作成)(2017/05/25追加、訂正など)

  • (2017/08/07) cod_list.txtを最新にupdateした。
  • (2017/05/26) Xojoで簡単なGUI検索プログラムを作ってみた(Mac, Win)。そちらは結晶構造の検索GUI版を参照

CODとは

  • Crystallography Open Database(COD)は、結晶構造のオープンデータベースであり、biopolymerを除いた、有機および無機結晶を対象としている。現在(2017/01/24)、37.1万件が登録されている。無料で結晶構造データベースを使うことができる。鉱物を扱う者としては、アメリカ鉱物学会等の鉱物構造データベースがCODへ提供されているところが重要な点である。IUCr、ACSの雑誌で出版されたcifデータは自動的に登録されるようになっている。雑誌によってはCODへ結晶構造データのデポジットを推奨するところもある。
  • CODは個人のPC等に自由にダウンロードすることができるので、それを研究・教育等に利用することができる。例えば、CODサイトで行っている検索は、php, mysqlが使えれば、ローカルPCでも実施することができる。最近、CODで遊んでいるので、いくつか紹介する。下で述べるようにCOD自体をダウンロードしなくても遊べることが色々とあります。

CODのダウンロード

  • CODのwikiにダウンロード方法が書かれているのでそれを参考にする。UNIX系(Mac OS Xも)であれば、Subversionを使って、以下のようにすればよい。なお、現在データ量は膨大なので(40GB弱、2016/04/14)、ハードディスク容量に注意しよう。最初のダウンロードには長時間かかる。 次のコマンドで、CODをダウンロードする。
    > svn co svn://www.crystallography.net/cod
    CODは常に更新しているので、時々アップデートする必要がある。まずcodディレクトリーに移動してから、
    > cd cod
    > svn update
    もしアップデートで怒られたら、指示通りにclean upを実行する
    > svn cleanup
    アップデートしようとしたら、アップグレードするように言われる時がある。その場合は、
    > svn upgrade

鉱物名を取り出す

  • 膨大なcifファイルがあるが、そこから情報を取り出してみよう。以下はMac上での処理だが、Linuxでもほぼ同じ。私の場合、鉱物を扱うことが多いので、鉱物名で検索できれば便利である。鉱物名はcifファイル中では、"_chemical_name_mineral"というタグで入っているので(入ってないcifも多数存在する)、それを読めばよい。そうして得た鉱物名をそのcifファイル名とともにテキストファイルに書き出しておけば、後でそのファイルを使って、ローカルで鉱物名で検索することや、鉱物のみを対象とする処理等で利用できる。そこで簡単なPythonのコードを書いて試してみた。cifファイルが3層のディレクトリ下に分配されているので、まずディレクトリのリストを得て、一段降りて、それを3回繰り返して、最後にcifファイルが実際に入っているディレクトリへ到着する。そこでcifファイルのリストを得て、それらを1つづつ処理する。Macの場合は、.DS_Storeというファイルが自動的にディレクトリ内にできるので、それをリストから除外する処理も必要となる。私のMacbook AirだとCOD全部処理するのに8分くらいかかったが、SSDを使っているので、これは速い方だった。HDD内臓のMac miniで試すと1時間以上かかった。"_chemical_name_mineral"には鉱物でない場合でも適当な内容が入っていることがあるが、その判定は不可能なので、そのままにしている。そうして出来たのが鉱物名リストである。なお、鉱物の場合は温度や圧力を変えたデータや固溶体も多いため、同じ鉱物名でも、たくさんのcifファイルが存在する(たとえばforsterite)。そういう意味では、"_publ_section_title"の情報や組成(_chemical_formula_sum)を一緒に取り出して表示すればいいかもしれない(それは既に実行中。下を参照)。ここでは"_chemical_name_mineral"タグのみの処理であるが、中央部分を変えれば様々な情報を集めることができそうである。それほど長くはないので、コードをペーストしておく。4行目のbaseは自分の環境に合わせて直す必要がある。
    #!/usr/bin/python
    import os,sys
    
    base = '/Users/masami/cod/cif/' # cif base directory, change here!
    list_basedir = ['1','2','3','4','5','6','7','8','9']
    #list_basedir = ['1'] # for test purpose, use limited list...
    for i in range(0,len(list_basedir)):
    	dir1 = base + list_basedir[i] + '/' # first-level directory
    	os.chdir(dir1) # move to second-level directory
    	list_1 = os.listdir('.') # 
    	if '.DS_Store' in list_1: # .DS_Store exists?
    		list_1.remove('.DS_Store') # remove .DS_Store
    	for j in range(0,len(list_1)):
    		dir2 = dir1 + list_1[j] + '/'
    		os.chdir(dir2) # move to 3rd-level directory
    		list_2 = os.listdir('.') 
    		if '.DS_Store' in list_2: # .DS_Store exists?
    			list_2.remove('.DS_Store') # remove .DS_Store
    		for k in range(0,len(list_2)):
    			dir3 = dir2 + list_2[k] + '/'
    			os.chdir(dir3) # move to 4th-level directory
    			list_3 = os.listdir('.')
    			if '.DS_Store' in list_3: # .DS_Store exists?
    				list_3.remove('.DS_Store') # remove .DS_Store
    			# list_3 contains cif file name list in this directory
    			for l in range(0,len(list_3)):  # process cif file
    				fin = open(list_3[l],'r') # open cif file
    				contents = fin.readlines() # read all contents in memory
    				fin.close() # close cif file
    				for line in contents: # for each line of cif  file (in memory)
    					try:
    						if '_chemical_name_mineral' in  line: # Does this tag exist?
    							tmp = line.strip() # strip \n
    							t = len(tmp) # length of tmp string
    							mineral_name = tmp[33:t] # get mineral name
    							if len(mineral_name) == 0: # if empty, break
    								break
    							else: # next line, remove ' and spaces
    								mineral_name = mineral_name.replace("'","").strip()
    								# make first letter to lower case
    								mineral_name = mineral_name[0].lower() + mineral_name[1:]
    								print mineral_name + ',' + list_3[l] #list_3[l] = cif filename
    								break
    					except: # tag not available in this cif
    						break	
  • これを使っている時に問題があって、途中で止めるには、control-cを押す。バックグラウンドで実行中なら、psコマンドでpid番号を見つけて、killする。
  • (2016/05/13) COD内のファイルを眺めていたら、同じ様に抽出したテキストファイルが存在していた。これはmysql directoryにあるので、mysqlでの検索にこれを使っているのだろう。data.txtという名前で、私が作ったのよりははるかに情報が入っているが、その分でかい(300 MB)。

Vestaでオープン

  • 上記の鉱物名リストをターミナル上ならgrepを使うか、GUIならテキストエディタで開いて、検索すれば鉱物名に対応するcifファイル番号がすぐ分かる。次はgrepでの検索の例。
    > grep forsterite minerals_in_cod.txt
    forsterite,9000166.cif
    forsterite,9000167.cif
    forsterite,9000267.cif
    以下省略
  • 実際にCOD全部をダウンロードしてなくても、その特定のcifファイルだけを得ることは簡単にできる。以下のようにウェブブラウザから、cifファイル名を直接指定してやれば、cifファイルがダウンロードされるので、それをVesta等で開けばよい。さらに後で示すようにcurlコマンドを使えば、ダウンロードを自動化することができる。以前は/cod/の部分が不要だったが、最近はないとダメなようだ
    http://www.crystallography.net/cod/9000166.cif
  • COD自体をダウンロードしている場合には、cifファイル本体はcodディレクトリから数えて5層下にあるので、GUI操作だとファイル名からファイルまでたどり着くのは結構面倒である(MacならSpotlightで検索した方が早いだろう)。cifファイル名からそれがあるディレクトリは一意に決まるので、cifファイル名を引数に与えると、ファイルを探して、Vestaで開いてくれる簡単なPythonコードも作った。これくらいならUnixのshellでできなくもないが。コードは短いので下に直接ペーストしておく。もちろんbase部分はそれぞれの環境に応じて変えないといけない。
    #!/usr/bin/python
    import sys,subprocess
    base = '/Users/masami/cod/cif/' # cif base directory, change here
    fname = sys.argv[1]
    dir = base + fname[0] + '/' + fname[1:3] + '/' + fname[3:5] + '/' + fname
    cmd = "open -a VESTA " + dir
    subprocess.call(cmd.split(" "))
    たとえばこれをvesta.pyとして保存し、実行権限をつけて以下のように実行すると、cifファイルの内容が結晶構造としてVesta上に表示される。
    > chmod 755 vesta.py
    > ./vesta.py 9000166.cif

さらに簡単にVestaでオープン(2016/04/26)

  • 上記ファイルを使ってみると、鉱物構造をちょっと調べるのに便利なので、さらにVestaでオープンするコードを改良した。COD自体をダウンロードしてない方の場合、上記のままだと、検索後に見たいファイルをCODサイトからダウンロードする必要がある。検索、ダウンロード、Vestaでオープンと3ステップも必要なのは面倒である。そこで、それらを1つのPythonコード内で行うようにした。ダウンロードにはcurlコマンドを利用している。このコードでは、検索する鉱物名を引数として渡すと、検索して、存在しない場合は即終了。1つのみ存在の場合は、直ちにダウンロードして表示する。複数ある場合は、番号付きリストが出てくるので、その番号を選んでやると、ダウンロードされて、Vestaで表示される。当然インターネットにつながってないとダメ。また、上記の鉱物名リストが必要である(現在は下記の化学組成を含む方をダウンロードしてください)。このコードもそれほど長くないので、ペーストしておく。鉱物リストファイルの場所を(mineral_file)、自分の環境に合わせて変える必要がある。Linuxの場合、Vestaを呼び出すところを変える必要がある。文字だけでは便利さが伝わらないかもしれないので、使っているところのmovieを置いておきます。(2016/09/09追記)しばしば同じ鉱物でも沢山あって何が違うかよくわからない場合が多いので、JeditXで自動的にcifファイルをオープンする部分を追加した(とりあえずコメントアウトしているが)。
#!/usr/bin/python
import sys,subprocess
# curl version
list = ['' for i in range(500)]
min_name = sys.argv[1]
mineral_file = '/Users/masami/minerals_in_cod.txt' # mineral-list, change here
try: # text file open
	 fin = open(mineral_file,'r')
except IOError, (errno, msg): # file not found
	print 'minerals_in_cod.txt is missing.'
	exit()
contents = fin.readlines() # read all lines in cif file to contents
fin.close() # close file
find = 0
for line in contents:
	if min_name in line: # mineral name in a line?
		find = find + 1
		list[find] = line.strip() # strip \n
		print str(find) + ": " + list[find] 
if find == 0:
	print "No such mineral in the list."
	exit()
elif find == 1: # just one, no selection
	input_no = 1
else: # select by number
	print "Select by number? (0 to stop)."
	input_no = input('>>> ')
if (input_no <= 0) or (input_no > find):
	exit()
s = list[input_no].index(",")
t = len(list[input_no])
fname = list[input_no][s+1:t] # get file name
cmd = "curl -s -o" + " " + fname + " " + "http://www.crystallography.net/cod/" + fname
subprocess.call(cmd.split(" ")) # Get specified cif file from the COD site by curl   
cmd = "open -a VESTA" + " " + fname
subprocess.call(cmd.split(" ")) # open VESTA using a downloaded cif file  
#cmd = "open -a Jedit\ X" + " " + fname
#subprocess.call(cmd,shell=True) # open cif file by JeditX			 
exit()
# end of the code, mkanzaki@me.com

使い方は、terminal上では次のような感じ。moganiteを検索すると、3つ存在したので、2番目を選んでいる。9005115.cifがCODサイトからダウンロードされ、Vestaに表示される。なお、そのcifファイルはカレントディレクトリに保存されているので、後で再利用できる。

> ./vesta_curl.py moganite
1: moganite,9002648.cif
2: moganite,9002649.cif
3: moganite,9005115.cif
Select by number? (0 to stop).
>>> 2

化学組成なども取り出したリストで検索(2016/05/06)

  • 上記は鉱物名だけだったが、化学組成、空間群、化学物質名、鉱物名を取り出したリストを最近作った。実は鉱物名が付いているcifファイルは多くなく、全体の3%くらいにすぎない。こちらは全cifファイルから抽出しているので、16 MBと巨大になっている。ダウンロードはここから。それ用の検索用codeも作った。そちらはここ。それらについては、結晶構造の検索にまとめてある。
  • なお、CODをダウンロードしている場合は、ローカルディスク上を探すために、少しコードを変えるが、それはこちらからダウンロードできる。これの6行目を実際にCODを置いている場所に応じて直す必要がある。
  • このPythonプログラムはGUIでないので、多くの方には使いずらいかもしれない。Xojoで簡単なGUIの検索アプリを作ろうとしていて、どうすればXojoからOS Xのコマンド(curlなど)を実行できるか勉強中。以下のようにshell.Excecuteを使えばいいようだ。ボタンを追加して、それのAction eventで以下のコードを書いておく。実行して、ボタンをクリックすると、9000166.cifをダウンロードして、Vesta, Jeditで表示された。
    Dim Sh As New Shell
    Sh.Execute( "curl -s -o ~/test.cif http://www.crystallography.net/cod/9000166.cif" )
    Sh.Execute( "open -a VESTA ~/test.cif" )
    Sh.Execute( "open -a Jedit\ X ~/test.cif" )
  • 下図のような簡単なGUI検索プログラムを何とか作った。テスト中。
    COD_search.png

cifファイルから粉末回折パターンを計算する(2016/05/06)

  • これらの結晶構造データ(cifファイル)から、粉末X線回折パターンを作成することができる。もっとも簡単な方法は(VestaとRIETAN-FPのユーザーの場合は)、Vestaでcifを読んで、そこから粉末回折パターンをRIETAN-FPで計算させる方法である。ただ、CODの膨大な数のファイルをマニュアルで処理するのは困難なので、cifファイルからRIETAN-FPの入力ファイル(.ins)を自動作成するコードが必要となる。最近、そのようなPythonコードを開発中である。現在、数千のcifファイルを処理して、テストを行っているが、どうしても空間群指定のかなり特殊なケース等が数件出てしまう。非標準な場合の対応はその場しのぎの汚い処理なので、コードの公開は難しい。もう少しrefineして、全cifファイルを処理する予定。この計算は1日近くかかりそう。lstファイルを処理して、各ピークの強度を抽出してやればよいが、パターン自体も計算されているので、パターン自体で検索することも可能になる(検索時間はかかりそうだが)。検索するソフトの方がまだ手付かずだが。

実測と計算回折パターンの比較

  • まだ検索ソフトには取り掛かってないが、ちょうど測定データを同定する必要があったので、応急処置で上記等を組み合わせて、候補の計算パターンと測定パターンが比較ができるようにした。以下はそのやり方。
    • 回折装置、私の場合はリガクの測定データ(.asc)をPlot2(Macのアプリ)で読める様に変換する
    • 検索コード(上記)で見つけたcifファイルを、これも上記のcifからRIETAN-FPの入力ファイル.insを作るコードで処理する
    • insファイルから粉末パターンのシミュレーションをRIETAN-FPで実行。
    • 強度データ(gpd)をPlot2で読める様に変換(これもPythonコード)
    • Plot2でそれらを読み込んで比較する
  • Plot2に自動で読み込ませる部分がうまくいかなかった。Appstoreからではなく、Plot2のHPから直接ダウンロードしたバージョンだと、コマンドラインから、ASCIIファイルでも読み込めるようになる。ただし1つのファイルだけ。1つのファイルに全部詰め込んでおけばいいのだろうが。
    cmd = "/Applications/Plot2.1.1/Plot2x.app/Contents/MacOS/Plot2x -i " + dir3 + " &" 
    subprocess.call(cmd,shell=True)
  • Jeditは実行ファイル名やディレクトリー名にスペースを使うのをやめてほしい。Pythonから実行させる時にsubprocess.call(cmd.split(" "))を使うと、Jedit\ Xのスペースが問題になる。そのため、subprocess.call(cmd.split(" "))をやめて、subprocess.call(cmd,shell=True)を使っている。
    cmd = "open -a Jedit\ X" + " " + filename
    subprocess.call(cmd,shell=True)				 
  • Xojoで簡単なGUIの検索プログラム(構造の方の)を作成した。そちらは結晶構造の検索GUI版を参照。

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-10-03 (月) 08:56:53 (414d)