RRUFF(https://rruff.net)はアリゾナ大学のDowns教授らが作成している鉱物のラマンスペクトルのオープンデータベースで、試料の組成分析、IRスペクトルや粉末XRDパターンも公開されています。最近リニューアルされました。このサイトでは鉱物名や化学組成で検索して、出てきた試料のラマンスペクトル等を見ることができますが、手持ちの観察スペクトルデータやピーク位置(ラマンシフト)を使っての検索機能はありません。ラマンスペクトルのデータベース検索については、別途CrystalSleuthというプログラムが同じサイトで古くから公開されています(現在はOther databasesのSoftwareのところ)。ただしCrystalSleuthはWindows専用で、また2008年で更新が止まっていて、付属データベース自体はそのころの古いままのようです。さらに私はMacユーザーなので利用しづらい問題もあります。そのため簡易に検索できるようなプログラムを自作することを以前から考えてはいたのですが、このリニューアルの機会に作ってみることにしました。また最終的には自分の持っているスペクトルデータも追加して、合わせて利用できるようにと思ってます。
RRUFFのラマンデータ集はRRUFFのサイトから自由にダウンロードすることができます。いくつかのデータセットがありますが、私は最もサイズの大きいexcellent_unoriented.zipをダウンロードしました。解凍してみると2025/12/03の時点で11,413点のファイル(テキストファイル)がありました。excellent_unorientedのファイルを詳しく見ると、測定したデータ(Raman_Data_RAW)と処理したデータ(Raman_Data_Processed)があるので、実際に検索に使うスペクトルとしてはその約半分となります。このデータセットの相対波数範囲は100くらいから1300 cm-1くらい(ダイヤモンドなどはもう少し高い波数まで)のものになります。4000 cm-1くらいまでの広い波数範囲が欲しい場合はLR-Raman.zipの方をダウンロードしてください。
ファイルをいくらか読んでみると、フォーマットは大体は整ってはいるのですが、全く同じではないので、読み込む時に注意が必要なので、以下に特徴をまとめました。
pythonでGUIにはTkinter使うのですが、以下の方針で作ることにしました。
最初にRRUFFのラマンデータファイルを開いてプロットして、平滑化処理やピーク検出を試すテストプログラムを作成しました。それを使っていくらかのファイルを処理して分かったことは、find_peaks()関数によるピーク検出はバックグラウンド(傾き)があるスペクトルではあまりうまくいきません。そういう意味でもバックグラウンド処理済みのProcessedを使うことになります。
Savitzky-Golay法で平滑化した方がより正しいピーク検出が行われるようでした。しかし平滑化は場合によっては元のスペクトルを大きく変化させてしまうことがあります。そのために大きく変化した場合(最大ピーク強度が半分以下になる)はパラメータを変えて再度計算しなおすようにしてます。ピーク検出では検出感度のパラメータを自動で調整して、8個ピークが得られるようにしてます。本当のピークではないものを拾ったり、元々ピーク数が8個もない鉱物もあるため、indexの一部は正確でない場合もありますが、そこはあまり大事にはならないだろうと考えてます。この辺りをもう少しrefineするには自分でピーク検出部分を書く必要がありそうです。
強度情報は入れてませんが、強度の順番にindexファイルに入れているので、それを定性的強度として利用してます。
Processedを全部処理するプログラムを作成して、それを実行しました。結構速くて1分以内で終了します。index.txtのファイルサイズは815 kb程度となりました。見ると5765行あります。RAWデータを無視しているので、ファイル数のほぼ半数ですが、対応するRAW自体がないものもあるので、半数よりは少し多くなってます。indexファイルは先頭8つがピーク位置を高いものから低いものの順番で並べて、最後にそのファイル名を入れてあります。ファイル名は後でオリジナルのファイルにアクセスするためと、ファイル名から鉱物名を拾うためです。なおピーク位置はピーク関数でフィットはしてなく、find_peaks()関数で得られたものをそのまま使ってます。ピーク位置は校正の方法などに依存するので実際的には使った装置が違えばある程度のずれが存在すること、鉱物の場合は固溶体が多く、ピーク位置は組成でかなり変わりうるので、同定目的では非常に正確なピーク位置を求める必要性はないと考えるからです(その分、検索時には幅を広げて検索する必要があります)。
検索するプログラムを作成しました。同定したいスペクトルを読んでプロットし、平滑化、(必要なら)バックグラウンドを引く処理、8個ピーク検出してそれをlistbox1に入れます。そのリストとindex.txtを比較して、一致度がいいものをlistbox2にリストアップします。それらを実行するにはプログラムのwinodwで、ボタンを上から順番にクリックすることで達成できます。最終的にリストアップされたものを選択して、スペクトルとして表示して、同定したいスペクトルと一致しているかをユーザー自身が判断することで同定を行います。
実測スペクトルによってはピークが1つ(ダイヤモンド)とか2つ(グラファイト)しかない場合があります。そういう場合には無理矢理8個拾ってきた位置で検索すると余分なものまで候補として拾ってきます。また宇宙線由来のピークやレイリー散乱線を拾ってくる場合もあります。そこでlistbox1の8個のピークから検索で使わないピークをユーザーが選択できるようにしました(複数選択可)。そうやって検索するとより正しい候補が得られます。
今の所、一致度(gof)には単純な指標を使ってます。toleranceで指定した値の範囲内にあるindex.txtにあるピークを一致したとして、強度の高い順に8から1点のポイントを与えて、その合計ポイントを計算しているだけです。ラマンの強度は方位にもよるので強度の強弱は必ずしも一定ではありませんが、意外にもこの単純な指標で正しい候補が得られてます。ただし正解ではない候補のスペクトルと比べてみると全然似てないスペクトルの場合が多いので、逆に候補側の強度高いものが存在するかどうかも調べて一致度に加えるように直しました。これがあると候補の精度が上がります。
バックグラウンド除去には移動平均を利用する方法を使いました。これはS.Bruckner (J.Appl.Cryst.33,977-979,2000)で提案されている方法で、こちらで紹介されていてpythonのサンプルコードも公開されてます。これを実行しておくとピークの検出がより正確になります。
自分で測定したデータ数十個でテストしてみましたが、ほとんどの場合は出てきた候補の中に正解が含まれていて同定できてます。うまくいかないケースも数件ありましたが、それはデータベースにない、データベースにあるスペクトルがあまりよくない、測定スペクトルがブロードなどが理由でした。
面白いことに石英の測定スペクトルを使って検索したところ、石英が候補リストに出てくるのは当然なのですが、それ以外でredmonditeも候補リストに出てきました。そこでRRUFFのredmonditeのスペクトルを見てみたところ、石英のスペクトルと完全に一致しました。これはRRUFFに対応を報告済みです。さらにもう1件、おかしいものを見つけました。
今後については、候補スペクトルに対してコサイン類似度を計算することで候補を絞れないかを試してみる予定です(実は強度リストに対してコサイン類似度とユークリッド距離を試しましたが、あまり有効でないようです)。また自分の持っているラマンデータも検索に使えるようにしたいのですが、その前に使うスペクトルの吟味や情報追加などが必要でちょっと時間がかかりそうです。
まずはプログラムのGUI window。全然洗練されてませんが、基本的には上からボタンをクリックしていけば処理が進みます。結果はプロットされるので、あまりうまくない時はパラメータを変えて、再度ボタンをクリックすると改善されるはずです。
まずはLoadボタンをクリックして、データを読み込みます。例は天然ダイアスポアのスペクトルです。読み込むとMatPlotLibを使ってスペクトルを表示します。
次にSmoothボタンをクリックすると平滑化したスペクトルが表示されます。あまりスペクトルの変形がひどい時はwindowの値を少し小さくして再度ボタンをクリックします。
バックグラウンドがある場合はbackgroundボタンをクリックすると、バックグラウンドを引いたスペクトルが表示されます。この例では必要ないかもしれません。
次にピーク検出を行います。パラメータは普通はそのままで問題ないはずですが、近接する2つのピークで片側が検出できてない場合はDistanceを小さくしてください。find peaksボタンをクリックすると、スペクトルとピークを検出した位置が示されます。また、1つ下のリストボックスに検出したピークのリストが表示されます。
リストボックスのピークリストを吟味して、本来のピークでないものがあった場合(例えば宇宙線由来ピーク)はリストボックスのその行をクリックすると選択されます。選択されたものは検索で使いません。下の例では2つを除外してます。それでSearch indexボタンをクリックすると検索が始まって、一致のよい候補を一番下のリストボックスに表示します。より多くの候補を見たい場合はthresholdを小さくしてください。波数校正してない場合はtoleranceを少し大きくした方がいいかもしれません。
このリストボックスから見たいものを選んでPlotボタンをクリックするとそのスペクトルと測定されたスペクトルが同時に表示されるので、2つが一致しているかどうかを判断できます。また隣のOpenボタンをクリックするとデータファイルが開きます(なおこれ直近で付けたので上の図にはまだありません)。その試料の細かい情報がデータファイルのヘッダ部分にあります。この例の場合は候補にはダイアスポアだけが出てきて、スペクトルをプロットすると天然ダイアスポア測定スペクトルとよく一致していることが分かりますので、ダイアスポアと同定できます。
参考のためにコードを公開してます。実際に使うためにはpythonライブラリの追加、ファイルのディレクトリをユーザーに合わせて変更するなどが必要になります。