*CODで遊ぶ (2016/04/16作成) [#h7f2db8a]
**CODとは [#s11136dc]
-Crystallography Open Database([[COD:http://www.crystallography.net/]])は、結晶構造のオープンデータベースであり、biopolymerを除いた、有機および無機結晶を対象としている。現在(2016/04/14)、36万件超が登録されている。鉱物を扱う者としては、アメリカ鉱物学会等の鉱物構造データベースがCODへ提供されているところが重要な点である。IUCr、ACSの雑誌で出版されたcifデータも自動的に登録されるようになっている。雑誌によってはCODへ構造構造データのデポジットを推奨するところもある。
-CODは個人のPC等に自由にダウンロードすることができるので、それを研究・教育等に利用することができる。例えば、CODサイトで行っている検索は、php, mysqlが使えれば、ローカルPCでも実施することができる。最近、CODで少し遊んでいるので、それらを紹介する。
**CODのダウンロード [#d6805521]
-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
**鉱物名を取り出す [#s004ce3d]
-膨大な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"には鉱物でない場合でも適当な内容が入っていることがあるが、その判定は不可能なので、そのままにしている。そうして出来たのが[[鉱物名リスト:http://www.misasa.okayama-u.ac.jp/~masami/minerals_in_cod.txt]]である。なお、鉱物の場合は温度や圧力を変えたデータや固溶体も多いため、同じ鉱物名でも、たくさんのcifファイルが存在する(たとえばforsterite)。そういう意味では、"_publ_section_title"の情報や組成(_chemical_formula_sum)を一緒に取り出して表示すればいいかもしれない。ここでは"_chemical_name_mineral"タグのみの処理であるが、中央部分を変えれば様々な情報を集めることができそうである。それほど長くはないので、コードをペーストしておく。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する。
**Vestaでオープン [#xcb0ee21]
-上記の[[鉱物名リスト:http://www.misasa.okayama-u.ac.jp/~masami/minerals_in_cod.txt]]をターミナル上ならgrepを使うか、GUIならテキストエディタで開いて、検索すれば鉱物名に対応するcifファイル番号が分かる。次はgrepでの検索の例。
 > grep forsterite minerals_in_cod.txt
 forsterite,9000166.cif
 forsterite,9000167.cif
 forsterite,9000267.cif
 以下省略
-実際にCODをダウンロードしてなくても、そのcifファイルを得ることは簡単にできる。以下のようにウェブブラウザから、cifファイル名を直接指定してやれば、cifファイルがダウンロードされるので、それをVesta等で開けばよい。
 http://www.crystallography.net/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で表示される。もちろんCODデータ以外のcifファイルは対象外。
 > chmod 755 vesta.py
 > ./vesta.py 9000166.cif
**さらに続く(多分) [#y7c3eb64]

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS