BH11.11/山本作業記録
提供:TogoWiki
「BH11.11/ヒト・環境メタゲノムメタデータのオントロジー整備とRDF化」関連の作業記録
目次 |
文字列マッチ
今回の処理対象データの特徴として、数値が意味をなさない場合が多く、アルファベット部分の類似度に重きを置くことが有効であった。 そこで、Apache Commonsライブラリに含まれているDoubleMetaphoneアルゴリズムを利用している。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Iterator; import java.util.TreeSet; import java.util.regex.Pattern; import org.apache.commons.codec.language.DoubleMetaphone; public class getDoubleMetaphone { public static void main(String[] args) { DoubleMetaphone dmp = new DoubleMetaphone(); try{ BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String str; while ((str = in.readLine()) != null) { String[] parts = str.split("\t"); System.out.println(str+'\t'+dmp.doubleMetaphone(parts[1],false)); } } catch (IOException e){ System.exit(0); } } }
オントロジーマッチ
関連オントロジーを、所与の文字列にマッチさせる。
オントロジー
マッチさせるオントロジーは以下の通り
- EnvO (Environment Ontology) - http://environmentontology.org/
- FMA (Foundational Model of Anatomy) - http://sig.biostr.washington.edu/projects/fm/AboutFM.html
- Plant Ontology - http://www.plantontology.org/
- OGR (Ontology of Geographical Region) - http://bioportal.bioontology.org/ontologies/1087
- OBIS (Ocean Biogeographic Information System) - http://www.iobis.org/
- Gazetteer - http://bioportal.bioontology.org/ontologies/1397
ID-ターム対応ファイル生成
OBISはダウンロードが単純ではなく、取得は見送り。残りの5つについて、それぞれのファイル形式は下記の通りなので、各形式について対応。
オントロジー | ファイル形式 |
---|---|
EnvO | obo |
FMA | MySQLダンプ |
Plant Ontology | obo |
OGR | owl |
Gazetteer | obo |
OBO形式
EnvO、Plant Ontology、GazetteerはOBOフォーマットが取得出来るので、PerlプログラムでTermとIDの組を取得。
use warnings; use strict; my $skipflag = 0; my $termid = ""; while(<>){ chomp; if(/^$/){ $skipflag = 0; next; } next if $skipflag; if(index($_, "[") == 0){ $termid = ""; my ($cat) = $_ =~ m/^\[(\w+)\]/; if($cat ne "Term"){ $skipflag = 1; next; } } if(index($_, "id: ") == 0){ substr($_, 0, 4, ""); $termid = $_; } next unless index($_, "name: ") == 0; substr($_, 0, 6, ""); print join("\t", ($termid, $_)), "\n"; }
MySQLダンプ形式
FMAはMySQLのダンプが取得出来るので、これをそのままロードする。
+-------------+----------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+----------------+------+-----+---------+-------+ | frame | varbinary(500) | NO | MUL | NULL | | | frame_type | smallint(6) | NO | | NULL | | | slot | varbinary(500) | NO | MUL | NULL | | | facet | varbinary(500) | NO | | NULL | | | is_template | bit(1) | NO | | NULL | | | value_index | int(11) | NO | | NULL | | | value_type | smallint(6) | NO | | NULL | | | short_value | varchar(500) | YES | MUL | NULL | | | long_value | mediumtext | YES | | NULL | | +-------------+----------------+------+-----+---------+-------+
'SELECT frame,slot,short_value FROM fma WHERE slot="name" OR slot="FMAID"'
`frame`をキーとした構造になっているので、上記のクエリを発行して取得し、PerlスクリプトでTermとIDの組を生成。 一部のターム (3字未満、数値のみ、数値の後にアルファベット一文字、大文字一文字に続いて数値) は予めフィルタして出力。
use warnings; use strict; my (%fmaids, %terms); while(<>){ chomp; my ($frame, $slot, $short) = split /\t/; if($slot eq 'FMAID'){ $fmaids{$frame} = $short; }elsif($slot eq 'name'){ $terms{$frame} = $short; } } while(my ($frame, $fmid) = each %fmaids){ next unless $terms{$frame}; my $term = $terms{$frame}; next if length($term) < 3 || $term =~ /\d+$/ || $term =~ /\d+[A-Za-z]$/ || $term =~ /^[A-Z]+\d+ /; print join("\t", ($fmid, $term)), "\n"; }
その他
OGRはowl形式のみ取得可能だが、rdfs:label属性が無く、文字列そのものをIDとし、rdfs:comment属性値にMeSHの地理情報に関する(Z01木)IDが書かれているのみなので、これとは別に予めDBCLSで取得しているMeSH2011 (mtrees2011.bin) を対象としてZ01部分を抽出。
grep ';Z0' mtrees2011.bin | perl -pe 's/;/\t/'
文字列マッチ
上記の処理を行うことで、全てIDと実際のタームがタブ区切りで一行一エントリの形式になる。 つづいて、文字列マッチを行うため、ACアルゴリズムに基づくマッチを行うPerlモジュールText::Scanを利用したプログラムを用意。
辞書生成プログラム
use warnings; use strict; use Text::Scan; my %files = ( 'OGR', 'GeographicRegion.txt', 'EnvO', 'envo.txt', 'FMA', 'fma_terms.txt', 'Gaz', 'gaz.txt', 'PO', 'plant_ontology.txt', ); my $dict = new Text::Scan; $dict->ignorecase(); $dict->squeezeblanks; $dict->ignore("\n\r<>()[]"); for my $dname ( qw/OGR EnvO FMA Gaz PO/ ){ open(my $fh1, $files{$dname}) or die "$files{$dname}:$!\n"; while(<$fh1>){ chomp; my ($id, $term) = split /\t/; if($dname eq 'OGR'){ my $tmp = $id; $id = $term; $term = $tmp; } $term =~ s|[-,.:;/]| |g; my $dcname = ; if($dname eq 'EnvO' || $dname eq 'Gaz' || $dname eq 'PO'){ }else{ $dcname = $dname.':'; } $dict->insert($term, $dcname.$id); print join("\t", ($term, $dcname.$id)), "\n"; } close($fh1); } $dict->serialize("bh11jpDict");
文字列マッチプログラム
use warnings; use strict; use Text::Scan; my $dict = new Text::Scan; $dict->restore("bh11jpDict"); $dict->squeezeblanks; $dict->charclass("[]<>().:;,?"); $dict->boundary("'\"[]<>():;,/-.? "); open(my $fh, "merged.txt") or die $!; while(<$fh>){ chomp; my @result = $dict->multiscan(' '.$_.' '); for my $r ( @result ){ print join("\t", ($_, $r->[0], $r->[2])), "\n"; } } close($fh);