Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Организуем поиск молекулярных конструкций с поддержкой Lucene и Chemistry Development Kit

Anna | 5.06.2014 | нет комментариев
Библиотека полнотекстового поиска Lucene предоставляет вероятность организовать поиск по текстовым документам. Существуют так же средства, с поддержкой которых дозволено организовать поиск «схожих» химических конструкций, скажем, OpenBabel. Изредка может появиться надобность объединить эти два вида поиска в цельной «канве». Скажем, если необходимо сделать систему, которая может отвечать на такие запросы: обнаружить вещество, в текстовом изложении которого есть слово «аминокислота», структурно схожее на индол (ожидается, что мы найдём аминокислоту триптофан). В этой статье описано решение данной задачи на основе полнотекстового движка Lucene.

Как вестимо, в основе полнотекстового поиска лежит построение инвертированного индекса. Текст документов разбивается на отдельные слова, для всякого из которых строится список документов, в которых встречается слово. Обыкновенно помимо списка документов для данного слова, индекс содержит позиции слова в всяком документе.Поиск схожих молекул в базах данных может быть основан на «молекулярных отпечатках». Зачастую «молекулярный отпечаток» представляет собой битовую строку, в которой всем биту соответствует наличие определённого свойства либо структурного фрагмента. В роли меры близости применяется показатель Танимото (частный случай показателя Жаккара).

В качестве простого примера молекулярного отпечатка, разглядим такой: Представим, что мы хотим получить молекулярный отпечаток длинны n. Конструкция нарезается на одномерные цепочки атомов длинной не больше чем k. К всякой полученной цепочке используется hash-функция, которая сравнивает цепочке число от 0 до n-1. Это число определяет номер бита, тот, что будет выставлен в 1 в отпечатке.

Для таких манипуляций с химическими конструкциями дозволено применять java-библиотеку Chemistry Development Kit (дальше легко CDK). CDK распространяется под лицензией LGPL и содержит java-классы для представления конструкций, расчёта нескольких типов «молекулярных отпечатков», поддерживает уйма химических форматов файлов. Скажем, нарезка молекулы на фрагменты может быть реализована так:

/Для представления химических конструкций в CDK применяются реализации интерфейса IAtomContainer.
IAtomContainer structure; 
...
for (IAtom startAtom : structure.atoms()) {
    //нам будет увлекателен класс CDK org.openscience.cdk.graph.PathTools, тот, что содержит способ getPathsOfLengthUpto, нарезающий конструкцию на одномерные цепочки.
    List<List<IAtom>> paths = PathTools.getPathsOfLengthUpto(structure, 
                                                     startAtom, 
                                                     searchDepth);
    //Далее делаем что-то с цепочкой атомов
    ...
}

Описанный «молекулярный отпечаток» вычисляется с поддержкой класса CDK org.openscience.cdk.fingerprint.Fingerprinter.

Для того, Дабы применять Lucene для поиска конструкций мы переформулируем поиск конструкций по отпечаткам в своего рода «поиск слов». Конструкция, как и в описанном выше способе построения отпечатка, нарезается на короткие одномерные цепочки, которые и будут аналогами слов в текстовом поиске. Таким образом, если мы предоставим системе иную конструкцию в качестве поискового запроса, то конструкция-запрос так же будет нарезана на цепочки, и итогом будут те конструкции, в которых имеются такие же цепочки атомов. Механизм упорядочивания документов по релевантности будет тяготиться выводить в первые позиции итогов те конструкции, в которых с одной стороны имеют много совпадений, с иной стороны эти совпадения несильно «разбавлены». То есть разумно ждать, что на первом месте будет верно совпадающая конструкция (если, безусловно, она есть среди проиндексированных), дальше схожие конструкции, отличающиеся одним атомом либо группой, дальше ещё крепче отличающиеся конструкции и.т.д.

Стоит подметить, что применяемая в Lucene формула ранжирования по умолчанию (модель векторного пространства TF-IDF) отличается от меры близости Танимото. Дозволено переопределить класс Similarity из Lucene под формулу показателя Танимото, но я не буду на этом останавливаться, тем больше что формула по-умолчанию должна дать «высококачественно верный» итог: конструкции с огромный долей пересечений фрагментов будут на первых местах в итоге.

Данный подход к индексации и поиску молекул дозволено реализовать сделав для Lucene специальный «химический токенизатор». Токенизатором (tokenizer) именуется компонент Lucene, разбивающий текст на отдельные токены (Почаще каждого токенами являются слова). Я теснее привёл выше основную логику работы этого токенизатора. Различие будет заключаться в том, что в токенизаторе Lucene не нужно получать сразу все токены в цикле. Взамен этого необходимо реализовать способ Tokenizer.incrementToken(), тот, что будет выдавать текстовые представления цепочек атомов по одной.

Существует несколько форматов представления молекул в виде текстовой строки. Пока что остановимся на поддержке только на одного из них — формата SMILES. CDK предоставляет парсер SMILES-строки (класс org.openscience.cdk.smiles.SmilesParser). Пользоватья им несложно:

SmilesParser sp = new SmilesParser(DefaultChemObjectBuilder.getInstance());
String smiles = "OCC(O)C(O)C(O)C(O)CO"; //Sorbitol
IAtomContainer structure = sp.parseSmiles( smiles );
//Далее делаем что-то с полученной конструкцией 
...

Логика реформирования SMILES-представления молекул в конструкцию с целью последующего разрезания её на токены-цепочки помещается в класс SmilesTokenizer.

Дозволю себе опустить ряд малозначительных деталей, скажу только, что исходники выложены на GitHub. Перейду сразу к примеру применения этих классов для поиска конструкций. Представим, что поисковые документы содержат три поля: name — имя химического соединения, description — текстовое изложение, и поле smiles — информация о структуре молекулы.

Индексация документов может выглядеть приблизительно так (применяется вспомогательный классSmilesAnalyzer, тот, что легко создаёт SmilesTokenizer):


Map<String,Analyzer> analyzerPerField = new HashMap<String,Analyzer>();

analyzerPerField.put(SMILES_FIELD, new SmilesAnalyzer() );

PerFieldAnalyzerWrapper analyzerWrapper =
       new PerFieldAnalyzerWrapper(new StandardAnalyzer(Version.LUCENE_40), analyzerPerField);

Document doc = new Document();
doc.add( new TextField( "name", "Acetic acid", Field.Store.YES ) );
doc.add( new TextField( "description", "Acetic acid is one of the simplest carboxylic acids. Liquid.", Field.Store.YES ) );
doc.add( new TextField( "smiles", "CC(O)=O", Field.Store.YES ) );

Directory directory = null;
IndexWriter indexWriter = null;
try {
    directory = new RAMDirectory();
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzerWrapper );
    indexWriter = new IndexWriter( directory, config);

    indexWriter.addDocument(doc);
}
...

Поиск же будет выглядеть приблизительно вот так:

reader = IndexReader.open(directory );
IndexSearcher searcher = new IndexSearcher(reader);

String querystr = "smiles:CCC";
Query q = null;
q = new QueryParser(Version.LUCENE_40, FREE_TEXT_FIELD, getAnalyzer()).parse(querystr);

TopScoreDocCollector collector = TopScoreDocCollector.create(5, true);
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;

//Дальше что-то делаем с итогами поиска в hits
...

 

 Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB