mirror of
https://github.com/bckelley/avogadrio.git
synced 2026-08-24 10:14:10 -05:00
Add Wikipedia fallback for SMILES lookup
This commit is contained in:
+2
-1
@@ -15,7 +15,8 @@
|
|||||||
"mustangostang/spyc": "^0.5.1",
|
"mustangostang/spyc": "^0.5.1",
|
||||||
"intervention/image": "^2.4",
|
"intervention/image": "^2.4",
|
||||||
"guzzlehttp/guzzle": "^6.3",
|
"guzzlehttp/guzzle": "^6.3",
|
||||||
"lambdacasserole/condense": "^1.1"
|
"lambdacasserole/condense": "^1.1",
|
||||||
|
"tburry/pquery": "^1.1"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|||||||
Generated
+53
-1
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "414181a9b439757b16b4938d109a80bd",
|
"content-hash": "18fab38459b21165a1075c73d836e92c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "defuse/php-encryption",
|
"name": "defuse/php-encryption",
|
||||||
@@ -1056,6 +1056,58 @@
|
|||||||
],
|
],
|
||||||
"time": "2016-06-29T05:41:56+00:00"
|
"time": "2016-06-29T05:41:56+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "tburry/pquery",
|
||||||
|
"version": "v1.1.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/tburry/pquery.git",
|
||||||
|
"reference": "872339ffd38d261c4417ea1855428b1b4ff9abf1"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/tburry/pquery/zipball/872339ffd38d261c4417ea1855428b1b4ff9abf1",
|
||||||
|
"reference": "872339ffd38d261c4417ea1855428b1b4ff9abf1",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"htmlawed/htmlawed": "dev-master"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"IQuery.php",
|
||||||
|
"gan_formatter.php",
|
||||||
|
"gan_node_html.php",
|
||||||
|
"gan_parser_html.php",
|
||||||
|
"gan_selector_html.php",
|
||||||
|
"gan_tokenizer.php",
|
||||||
|
"gan_xml2array.php",
|
||||||
|
"pQuery.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-2.1"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Todd Burry",
|
||||||
|
"email": "todd@vanillaforums.com",
|
||||||
|
"role": "developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A jQuery like html dom parser written in php.",
|
||||||
|
"keywords": [
|
||||||
|
"dom",
|
||||||
|
"ganon",
|
||||||
|
"php"
|
||||||
|
],
|
||||||
|
"time": "2016-01-14T20:55:00+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
"version": "v1.24.1",
|
"version": "v1.24.1",
|
||||||
|
|||||||
@@ -6,55 +6,26 @@ use Condense\Database;
|
|||||||
use \GuzzleHttp\Client;
|
use \GuzzleHttp\Client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a conversion service between compound names and SMILES strings.
|
* Provides a conversion service between compound names and SMILES strings that uses a dedicated lookup service.
|
||||||
*
|
*
|
||||||
* @author Saul Johnson <saul.a.johnson@gmail.com>
|
* @author Saul Johnson <saul.a.johnson@gmail.com>
|
||||||
* @since 06/08/2017
|
* @since 06/08/2017
|
||||||
* @package Avogadrio
|
* @package Avogadrio
|
||||||
*/
|
*/
|
||||||
class CactusSmilesConverter
|
class CactusSmilesConverter extends SmilesConverter
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* The compound name/SMILES cache database.
|
|
||||||
*
|
|
||||||
* @var Database
|
|
||||||
*/
|
|
||||||
private $db;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of a conversion service between compound names and SMILES strings.
|
* Initializes a new instance of a conversion service between compound names and SMILES strings.
|
||||||
*
|
*
|
||||||
* @param Database $db the database in which to cache lookup results
|
* @param Database $db the database in which to cache lookup results
|
||||||
|
* @param SmilesConverter $fallback the conversion service to fall back to in case of error
|
||||||
*/
|
*/
|
||||||
public function __construct($db = null) {
|
public function __construct($db = null, $fallback = null) {
|
||||||
$this->db = $db;
|
parent::__construct($db, $fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether or not the API result cache is enabled.
|
* @inheritdoc
|
||||||
*
|
|
||||||
* @return bool true if the cache is enabled, otherwise false
|
|
||||||
*/
|
|
||||||
public function isCacheEnabled() {
|
|
||||||
return $this->db !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to fix any errors in a SMILES string and returns the result.
|
|
||||||
*
|
|
||||||
* @param string $smiles the SMILES string to fix
|
|
||||||
* @return string the fixed SMILES string
|
|
||||||
*/
|
|
||||||
private static function fixSmiles($smiles) {
|
|
||||||
$output = str_replace('|', '', $smiles); // Zap vertical bars.
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a compound name to SMILES notation.
|
|
||||||
*
|
|
||||||
* @param string $name the name of the compound
|
|
||||||
* @return null|string the SMILES notation for the named compound or null if not found
|
|
||||||
*/
|
*/
|
||||||
public function nameToSmiles($name)
|
public function nameToSmiles($name)
|
||||||
{
|
{
|
||||||
@@ -62,11 +33,9 @@ class CactusSmilesConverter
|
|||||||
$encoded = rawurlencode($name);
|
$encoded = rawurlencode($name);
|
||||||
|
|
||||||
// Check if we've got the name cached already.
|
// Check if we've got the name cached already.
|
||||||
if ($this->isCacheEnabled()) {
|
$cached = $this->getIfCachedAndValid($encoded);
|
||||||
$cachedSmiles = $this->db->get('smiles', 'name', $encoded);
|
if ($cached !== null) {
|
||||||
if ($cachedSmiles !== null) {
|
return $cached;
|
||||||
return self::fixSmiles($cachedSmiles);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert chemical name to SMILES if we can using API.
|
// Convert chemical name to SMILES if we can using API.
|
||||||
@@ -76,13 +45,12 @@ class CactusSmilesConverter
|
|||||||
// If request was successful.
|
// If request was successful.
|
||||||
if ($response->getStatusCode() === 200) {
|
if ($response->getStatusCode() === 200) {
|
||||||
$smiles = $response->getBody()->getContents();
|
$smiles = $response->getBody()->getContents();
|
||||||
if ($this->isCacheEnabled()) {
|
if (self::isValidSmiles($smiles)) {
|
||||||
$this->db->insert(['name' => $encoded, 'smiles' => $smiles]); // Cache name for future.
|
$this->cache($encoded, $smiles);
|
||||||
|
return $smiles;
|
||||||
}
|
}
|
||||||
return self::fixSmiles($smiles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request failed.
|
return $this->fallback($name); // Fall back.
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Avogadrio;
|
||||||
|
|
||||||
|
use Condense\Database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a conversion service between compound names and SMILES strings.
|
||||||
|
*
|
||||||
|
* @author Saul Johnson <saul.a.johnson@gmail.com>
|
||||||
|
* @since 27/08/2017
|
||||||
|
* @package Avogadrio
|
||||||
|
*/
|
||||||
|
abstract class SmilesConverter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The compound name/SMILES cache database.
|
||||||
|
*
|
||||||
|
* @var Database
|
||||||
|
*/
|
||||||
|
private $db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The conversion service to fall back to in case of error.
|
||||||
|
*
|
||||||
|
* @var SmilesConverter
|
||||||
|
*/
|
||||||
|
private $fallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new instance of a conversion service between compound names and SMILES strings.
|
||||||
|
*
|
||||||
|
* @param Database $db the database in which to cache lookup results
|
||||||
|
* @param SmilesConverter $fallback the conversion service to fall back to in case of error
|
||||||
|
*/
|
||||||
|
protected function __construct($db, $fallback) {
|
||||||
|
$this->db = $db;
|
||||||
|
$this->fallback = $fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether or not the API result cache is enabled.
|
||||||
|
*
|
||||||
|
* @return bool true if the cache is enabled, otherwise false
|
||||||
|
*/
|
||||||
|
public function isCacheEnabled() {
|
||||||
|
return $this->db !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to fix any errors in a SMILES string and returns the result.
|
||||||
|
*
|
||||||
|
* @param string $smiles the SMILES string to fix
|
||||||
|
* @return string the fixed SMILES string
|
||||||
|
*/
|
||||||
|
protected static function fixSmiles($smiles) {
|
||||||
|
$output = str_replace('|', '', $smiles); // Zap vertical bars.
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given SMILES string is valid, otherwise returns false.
|
||||||
|
*
|
||||||
|
* @param string $smiles the SMILES string to check
|
||||||
|
* @return bool true if the string was valid, otherwise false
|
||||||
|
*/
|
||||||
|
protected static function isValidSmiles($smiles) {
|
||||||
|
return preg_match('/^[a-zA-Z0-9@%=\\\\\/\[\]\.\+\-\_\*\(\)]+$/', $smiles) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getIfCachedAndValid($name) {
|
||||||
|
if ($this->isCacheEnabled()) {
|
||||||
|
$cachedSmiles = $this->db->get('smiles', 'name', $name);
|
||||||
|
if ($cachedSmiles !== null && self::isValidSmiles($cachedSmiles)) {
|
||||||
|
return $cachedSmiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cache($name, $smiles) {
|
||||||
|
if ($this->isCacheEnabled()) {
|
||||||
|
$this->db->insert(['name' => $name, 'smiles' => $smiles]); // Cache name for future.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls back to another SMILES conversion service.
|
||||||
|
*
|
||||||
|
* @param string $name the compound name to convert
|
||||||
|
* @return null|string the converted compound name or null if not found
|
||||||
|
*/
|
||||||
|
protected function fallback($name) {
|
||||||
|
if ($this->fallback === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return $this->fallback->nameToSmiles($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a compound name to SMILES notation.
|
||||||
|
*
|
||||||
|
* @param string $name the name of the compound
|
||||||
|
* @return null|string the SMILES notation for the named compound or null if not found
|
||||||
|
*/
|
||||||
|
public abstract function nameToSmiles($name);
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Avogadrio;
|
||||||
|
|
||||||
|
use Condense\Database;
|
||||||
|
use \GuzzleHttp\Client;
|
||||||
|
use pQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a conversion service between compound names and SMILES strings that scrapes SMILES strings from Wikipedia.
|
||||||
|
*
|
||||||
|
* @author Saul Johnson <saul.a.johnson@gmail.com>
|
||||||
|
* @since 27/08/2017
|
||||||
|
* @package Avogadrio
|
||||||
|
*/
|
||||||
|
class WikipediaSmilesConverter extends SmilesConverter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Initializes a new instance of a conversion service between compound names and SMILES strings.
|
||||||
|
*
|
||||||
|
* @param Database $db the database in which to cache lookup results
|
||||||
|
* @param SmilesConverter $fallback the conversion service to fall back to in case of error
|
||||||
|
*/
|
||||||
|
public function __construct($db = null, $fallback = null) {
|
||||||
|
parent::__construct($db, $fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function nameToSmiles($name)
|
||||||
|
{
|
||||||
|
// Sanitize name for URLs.
|
||||||
|
$encoded = str_replace(' ', '_', $name);
|
||||||
|
|
||||||
|
// Check if we've got the name cached already.
|
||||||
|
$cached = $this->getIfCachedAndValid($encoded);
|
||||||
|
if ($cached !== null) {
|
||||||
|
return $cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Wikipedia page for compound.
|
||||||
|
$client = new Client();
|
||||||
|
$response = $client->request('GET', "https://en.wikipedia.org/wiki/$encoded");
|
||||||
|
|
||||||
|
// If there is a page.
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
|
||||||
|
// Parse page into DOM.
|
||||||
|
$page = $response->getBody()->getContents();
|
||||||
|
$dom = pQuery::parseStr($page);
|
||||||
|
|
||||||
|
// Get all hyperlinks.
|
||||||
|
$links = $dom->select('a');
|
||||||
|
|
||||||
|
// Look for the SMILES hyperlink.
|
||||||
|
foreach ($links as $link) {
|
||||||
|
if (strstr($link->text(), 'SMILES')) {
|
||||||
|
$smiles = trim($link->parent->getNextSibling()->text()); // Get actual SMILES string.
|
||||||
|
if (self::isValidSmiles($smiles)) {
|
||||||
|
$this->cache($encoded, $smiles);
|
||||||
|
return $smiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fallback($name); // Fall back.
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -9,6 +9,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
|
|||||||
|
|
||||||
use Condense\Database;
|
use Condense\Database;
|
||||||
use Avogadrio\CactusSmilesConverter;
|
use Avogadrio\CactusSmilesConverter;
|
||||||
|
use Avogadrio\WikipediaSmilesConverter;
|
||||||
use Avogadrio\MoleculeRenderer;
|
use Avogadrio\MoleculeRenderer;
|
||||||
|
|
||||||
$app = new Silex\Application();
|
$app = new Silex\Application();
|
||||||
@@ -20,7 +21,7 @@ $app = new Silex\Application();
|
|||||||
$config = Spyc::YAMLLoad(__DIR__ . '/../config/config.yaml');
|
$config = Spyc::YAMLLoad(__DIR__ . '/../config/config.yaml');
|
||||||
|
|
||||||
// Services.
|
// Services.
|
||||||
$smilesConverter = new CactusSmilesConverter(new Database('names', __DIR__ . '/../db'));
|
$smilesConverter = new CactusSmilesConverter(new Database('names', __DIR__ . '/../db'), new WikipediaSmilesConverter());
|
||||||
$moleculeRenderer = new MoleculeRenderer($config['sourire_service']);
|
$moleculeRenderer = new MoleculeRenderer($config['sourire_service']);
|
||||||
|
|
||||||
$moleculeRenderer->setRenderChiralLabels(false); // Disable chiral labels.
|
$moleculeRenderer->setRenderChiralLabels(false); // Disable chiral labels.
|
||||||
|
|||||||
Reference in New Issue
Block a user