Add molecule rendering as service

This commit is contained in:
Saul Johnson
2017-08-06 19:56:44 +01:00
parent cc7af9d541
commit 397cf20ded
2 changed files with 78 additions and 57 deletions
+69
View File
@@ -0,0 +1,69 @@
<?php
namespace Avogadrio;
use Intervention\Image\ImageManagerStatic as Image;
/**
*
*
* @author Saul Johnson <saul.a.johnson@gmail.com>
* @since 06/08/2017
* @package Avogadrio
*/
class MoleculeRenderer
{
private $sourireUrl;
public function __construct($sourireUrl)
{
$this->sourireUrl = $sourireUrl;
// Configure GD as image driver.
Image::configure(array('driver' => 'gd'));
}
public function renderMolecule($color, $smiles)
{
// Proxy into Sourire for molecule render.
$molecule = Image::make($this->sourireUrl . urlencode($smiles));
// Colorize molecule.
list($r, $g, $b) = sscanf($color, "%02x%02x%02x");
$unit = 100 / 255;
$molecule->colorize($unit * $r, $unit * $g, $unit * $b);
return $molecule; // Return molecule image.
}
public function renderScaledMolecule($color, $smiles, $canvasWidth, $canvasHeight, $proportion = 0.6)
{
$molecule = $this->renderMolecule($color, $smiles);
$px = $molecule->getWidth() / $canvasWidth;
$py = $molecule->getHeight() / $canvasHeight;
while ($px > $proportion || $py > $proportion) {
if ($px > $proportion) {
$factor = ($canvasWidth * $proportion) / $molecule->getWidth();
} else {
$factor = ($canvasHeight * $proportion) / $molecule->getHeight();
}
$molecule->resize($molecule->getWidth() * $factor, $molecule->getHeight() * $factor);
$px = $molecule->getWidth() / $canvasWidth;
$py = $molecule->getHeight() / $canvasHeight;
}
return $molecule;
}
public function renderMoleculeWithBackground($fgcolor, $bgcolor, $smiles, $width, $height) {
// Set up background.
$img = Image::canvas($width, $height, "#$bgcolor");
// Render molecule.
$molecule = $this->renderScaledMolecule($fgcolor, $smiles, $width, $height);
// Center on background.
$img->insert($molecule, 'center');
return $img;
}
}
+9 -57
View File
@@ -6,65 +6,28 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Intervention\Image\ImageManagerStatic as Image;
use Condense\Database;
use Avogadrio\SmilesConverter;
// Configure GD as image driver.
Image::configure(array('driver' => 'gd'));
use Avogadrio\MoleculeRenderer;
// Load config.
$config = Spyc::YAMLLoad(__DIR__ . '/../config/config.yaml');
// Caching SMILES converter.
$smilesConverter = new SmilesConverter(new Database('names', __DIR__ . '/../db'));
$app = new Silex\Application();
// Uncomment the line below while debugging your app.
$app['debug'] = true;
// Services.
$smilesConverter = new SmilesConverter(new Database('names', __DIR__ . '/../db'));
$moleculeRenderer = new MoleculeRenderer($config['sourire_service']);
// Twig initialization.
$loader = new Twig_Loader_Filesystem(__DIR__.'/../templates');
$twig = new Twig_Environment($loader, array(
'cache' => false //__DIR__.'/../cache',
));
/*
* Rendering functions.
*/
function renderMolecule($color, $smiles) {
// Proxy into Sourire for molecule render.
$molecule = Image::make('http://localhost:8080/molecule/' . urlencode($smiles));
// Colorize molecule.
list($r, $g, $b) = sscanf($color, "%02x%02x%02x");
$unit = 100 / 255;
$molecule->colorize($unit * $r, $unit * $g, $unit * $b);
return $molecule; // Return molecule image.
}
function renderScaledMolecule($canvasWidth, $canvasHeight, $color, $smiles) {
$molecule = renderMolecule($color, $smiles);
$proportion = 0.6;
$px = $molecule->getWidth() / $canvasWidth;
$py = $molecule->getHeight() / $canvasHeight;
while ($px > $proportion || $py > $proportion) {
if ($px > $proportion) {
$factor = ($canvasWidth * $proportion) / $molecule->getWidth();
} else {
$factor = ($canvasHeight * $proportion) / $molecule->getHeight();
}
$molecule->resize($molecule->getWidth() * $factor, $molecule->getHeight() * $factor);
$px = $molecule->getWidth() / $canvasWidth;
$py = $molecule->getHeight() / $canvasHeight;
}
return $molecule;
}
/*
* Route actions.
*/
@@ -73,20 +36,9 @@ $app->get('/', function () use ($twig, $config) {
return $twig->render('index.html.twig', $config);
});
$app->get('/api/smiles/{width}/{height}/{bgcolor}/{fgcolor}/{smiles}', function ($width, $height, $bgcolor, $fgcolor, $smiles) use ($twig, $config) {
// Set up background.
$img = Image::canvas($width, $height, "#$bgcolor");
// Render molecule.
$molecule = renderScaledMolecule($width, $height, $fgcolor, $smiles);
// Center on background.
$img->insert($molecule, 'center');
// Send image out
$app->get('/api/smiles/{width}/{height}/{bgcolor}/{fgcolor}/{smiles}', function ($width, $height, $bgcolor, $fgcolor, $smiles) use ($twig, $config, $moleculeRenderer) {
return new \Symfony\Component\HttpFoundation\Response(
$img->response('png'),
$moleculeRenderer->renderMoleculeWithBackground($fgcolor, $bgcolor, $smiles, $width, $height)->response('png'),
200,
['Content-Type' => 'image/png']
);
@@ -107,9 +59,9 @@ $app->get('/api/name/{width}/{height}/{bgcolor}/{fgcolor}/{name}', function ($wi
return $app->abort(404, "Chemical name could not be converted to SMILES.");
});
$app->get('/api/smiles/{width}/{height}/{color}/{smiles}', function ($width, $height, $color, $smiles) use ($app, $twig, $config) {
$app->get('/api/smiles/{width}/{height}/{color}/{smiles}', function ($width, $height, $color, $smiles) use ($app, $twig, $config, $moleculeRenderer) {
return new \Symfony\Component\HttpFoundation\Response(
renderScaledMolecule($width, $height, $color, $smiles)->response('png'),
$moleculeRenderer->renderScaledMolecule($width, $height, $color, $smiles)->response('png'),
200,
['Content-Type' => 'image/png']
);