mirror of
https://github.com/openbabel/openbabel.git
synced 2025-02-25 18:55:23 -06:00
619 lines
15 KiB
PHP
619 lines
15 KiB
PHP
<?php
|
|
/********************************************************************
|
|
baphpel - PHP interface to OpenBabel
|
|
Copyright (C) 2013 Maciej Wojcikowski <maciek@wojcikowski.pl>
|
|
|
|
This file is part of of the Open Babel project.
|
|
|
|
This file is part of the Open Babel project.
|
|
For more information, see <http://openbabel.org/>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
********************************************************************/
|
|
namespace baphpel;
|
|
|
|
include_once 'openbabel.php';
|
|
|
|
# define global elements
|
|
$_builder = new \OBBuilder;
|
|
$_obconv = new \OBConversion;
|
|
|
|
function vector2array($v) {
|
|
$out = array();
|
|
$num = $v -> size();
|
|
for($i=0;$i<$num;$i++) {
|
|
$out[] = $v -> get($i);
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
function _formatstodict($list) {
|
|
global $_obconv;
|
|
$list = vector2array($_obconv -> $list());
|
|
foreach($list as $f) {
|
|
$fmt = explode(' -- ', preg_replace(array('/\[Read-only\]/'), '/\[Write-only\]/', $f));
|
|
$out[trim($fmt[0])] = trim($fmt[1]);
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
$informats = _formatstodict('GetSupportedInputFormat');
|
|
$outformats = _formatstodict('GetSupportedOutputFormat');
|
|
|
|
function _getplugins($findplugins, $names) {
|
|
$find = explode('::', $findplugins);
|
|
foreach($names as $x) {
|
|
if(in_array($find[0], array('OBDescriptor', 'OBForceField'))) {
|
|
$f = $find[0]::$find[1]($x);
|
|
}
|
|
else {
|
|
$f1 = new $find[0](null);
|
|
$f = $f1 -> $find[1]($x);
|
|
}
|
|
if($f) {
|
|
$plugins[$x] = $f;
|
|
}
|
|
}
|
|
return $plugins;
|
|
}
|
|
|
|
function _getpluginnames($ptype) {
|
|
$plugins = new \vectorString;
|
|
\OBPlugin::ListAsVector($ptype, null, $plugins);
|
|
$plugins = vector2array($plugins);
|
|
foreach($plugins as $p) {
|
|
$out[] = strtolower(explode(' ', trim($p))[0]);
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
|
|
/* A list of supported descriptors */
|
|
$descs = _getpluginnames('descriptors');
|
|
$_descdict = _getplugins('\OBDescriptor::FindType', $descs);
|
|
|
|
/* A list of supported forcefields */
|
|
$forcefields = _getpluginnames('forcefields');
|
|
$_forcefields = _getplugins('\OBForceField::FindForceField', $forcefields);
|
|
|
|
/* A list of supported fingerprint types */
|
|
$fps = _getpluginnames('fingerprints');
|
|
$_fingerprinters = _getplugins('\OBFingerprint::FindType', $fps);
|
|
|
|
/* A list of supported operations */
|
|
$operations = _getpluginnames('ops');
|
|
$_operations = _getplugins('\OBOp::FindType', $operations);
|
|
|
|
function readfile($format, $filename, $opt=array()) {
|
|
# setup converter
|
|
$OBConversion = new \OBConversion;
|
|
$OBConversion -> SetInFormat($format);
|
|
# set options
|
|
if(!empty($opt)) {
|
|
foreach($opt as $k => $v) {
|
|
if(!empty($v)) {
|
|
$OBConversion -> AddOption($k, $OBConversion::INOPTIONS, $v);
|
|
}
|
|
else {
|
|
$OBConversion -> AddOption($k, $OBConversion::INOPTIONS);
|
|
}
|
|
}
|
|
}
|
|
|
|
class filereader implements \Iterator {
|
|
private $position = 0;
|
|
private $notatend = null;
|
|
private $OBMol = null;
|
|
|
|
public function __construct($OBConversion, $filename) {
|
|
$this -> OBConversion = $OBConversion;
|
|
$this -> OBMol = new \OBMol;
|
|
$this -> notatend = $this -> OBConversion -> ReadFile($this -> OBMol, $filename);
|
|
}
|
|
|
|
function rewind() {
|
|
$this->position = 0;
|
|
}
|
|
|
|
function current() {
|
|
return new Molecule($this -> OBMol);
|
|
}
|
|
|
|
function key() {
|
|
return $this->position;
|
|
}
|
|
|
|
function next() {
|
|
$this -> position++;
|
|
$this -> OBMol = new \OBMol;
|
|
$this -> notatend = $this -> OBConversion -> Read($this -> OBMol);
|
|
}
|
|
|
|
function valid() {
|
|
return $this -> notatend;
|
|
}
|
|
}
|
|
|
|
return new filereader($OBConversion, $filename);
|
|
}
|
|
|
|
function readstring($format, $string, $opt=array()) {
|
|
# setup converter
|
|
$OBConversion = new \OBConversion;
|
|
$OBConversion -> SetInFormat($format);
|
|
# set options
|
|
if(!empty($opt)) {
|
|
foreach($opt as $k => $v) {
|
|
if(!empty($v)) {
|
|
$OBConversion -> AddOption($k, $OBConversion::INOPTIONS, $v);
|
|
}
|
|
else {
|
|
$OBConversion -> AddOption($k, $OBConversion::INOPTIONS);
|
|
}
|
|
}
|
|
}
|
|
|
|
$OBMol = new \OBMol;
|
|
$OBConversion->ReadString($OBMol, $string);
|
|
return new Molecule($OBMol);
|
|
}
|
|
|
|
class Outputfile {
|
|
public function __construct($format, $filename, $overwrite=False, $opt=array()) {
|
|
$this -> format = $format;
|
|
$this -> filename = $filename;
|
|
if(!$overwrite && file_exists(self.filename)) {
|
|
throw new \Exception($this -> filename." already exists. Use 'overwrite=True' to overwrite it.");
|
|
}
|
|
$this -> OBConversion = new \OBConversion;
|
|
$formatok = $this -> OBConversion -> SetOutFormat($this -> format);
|
|
if(!$formatok) {
|
|
throw new \Exception($this -> format." is not a recognised Open Babel format");
|
|
}
|
|
foreach($opt as $key => $value) {
|
|
if($v === null) {
|
|
$this -> OBConversion -> AddOption($k, $this -> OBConversion -> OUTOPTIONS);
|
|
}
|
|
else {
|
|
$this -> OBConversion -> AddOption($k, $this -> OBConversion -> OUTOPTIONS, $v);
|
|
}
|
|
}
|
|
$this -> total = 0; # The total number of molecules written to the file
|
|
}
|
|
|
|
public function write($molecule) {
|
|
if(!$this -> filename) {
|
|
throw new \Exception("Outputfile instance is closed.");
|
|
}
|
|
|
|
if($this -> total == 0) {
|
|
$this -> OBConversion -> WriteFile($molecule -> OBMol, $this -> filename);
|
|
}
|
|
else {
|
|
$this -> OBConversion -> Write($molecule -> OBMol);
|
|
}
|
|
$this -> total += 1;
|
|
}
|
|
|
|
public function close() {
|
|
$this -> OBConversion -> CloseOutFile();
|
|
$this -> filename = null;
|
|
}
|
|
}
|
|
|
|
class Molecule implements \Iterator {
|
|
public $OBMol = null;
|
|
private $position = 0;
|
|
private $atoms = array();
|
|
private $residues = array();
|
|
|
|
public function __construct($OBMol) {
|
|
$this -> OBMol = $OBMol;
|
|
}
|
|
|
|
public function __get($name) {
|
|
switch($name) {
|
|
case 'atoms':
|
|
if(empty($this -> atoms)) { # generate atoms only once
|
|
$out = array();
|
|
$num = $this -> OBMol -> NumAtoms();
|
|
for($i=1;$i<=$num;$i++) {
|
|
$atom = $this -> OBMol -> GetAtom($i);
|
|
if(empty($atom)) {
|
|
echo $i.'!!!';
|
|
}
|
|
$out[] = new Atom($this -> OBMol -> GetAtom($i));
|
|
}
|
|
$this -> atoms = $out;
|
|
}
|
|
else {
|
|
$out = $this -> atoms;
|
|
}
|
|
break;
|
|
case 'residues':
|
|
if(empty($this -> residues)) { # generate residues only once
|
|
$out = array();
|
|
$num = $this -> OBMol -> NumResidues();
|
|
for($i=0;$i<$num;$i++) {
|
|
$out[] = new Residue($this -> OBMol -> GetResidue($i));
|
|
}
|
|
$this -> residues = $out;
|
|
}
|
|
else {
|
|
$out = $this -> residues;
|
|
}
|
|
break;
|
|
case 'charge':
|
|
$out = $this -> OBMol -> GetTotalCharge();
|
|
break;
|
|
case 'conformers':
|
|
$out = $this -> OBMol -> GetConformers();
|
|
break;
|
|
case 'data':
|
|
$out = new MoleculeData($this -> OBMol);
|
|
break;
|
|
case 'dim':
|
|
$out = $this -> OBMol -> GetDimension();
|
|
break;
|
|
case 'energy':
|
|
$out = $this -> OBMol -> GetEnergy();
|
|
break;
|
|
case 'exactmass':
|
|
$out = $this -> OBMol -> GetExactMass();
|
|
break;
|
|
case 'formula':
|
|
$out = $this -> OBMol -> GetFormula();
|
|
break;
|
|
case 'molwt':
|
|
$out = $this -> OBMol -> GetMolWt();
|
|
break;
|
|
case 'spin':
|
|
$out = $this -> OBMol -> GetTotalSpinMultiplicity();
|
|
break;
|
|
case 'sssr':
|
|
$out = vector2array($this -> OBMol -> GetSSSR());
|
|
break;
|
|
case 'title':
|
|
$out = $this -> OBMol -> GetTitle();
|
|
break;
|
|
# case 'unitcell':
|
|
#
|
|
# break;
|
|
case '_exchange':
|
|
if($this -> OBMol -> HasNonZeroCoords()) {
|
|
return $this -> write('mol');
|
|
}
|
|
else {
|
|
return preg_split('/[\t\s]+/', trim($this -> write('can')))[0];
|
|
}
|
|
break;
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function __set($name, $value) {
|
|
switch($name) {
|
|
case 'title':
|
|
$out = $this -> OBMol -> SetTitle($value);
|
|
break;
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
# iterator part
|
|
public function rewind() {
|
|
$this->position = 0;
|
|
# generate atoms
|
|
$this-> __get('atoms');
|
|
}
|
|
|
|
public function current() {
|
|
return $this->atoms[$this->position];
|
|
}
|
|
|
|
public function key() {
|
|
return $this->position;
|
|
}
|
|
|
|
public function next() {
|
|
$this->position++;
|
|
}
|
|
|
|
public function valid() {
|
|
return isset($this->atoms[$this->position]);
|
|
}
|
|
# end iterator
|
|
|
|
public function calcdesc($descnames = array()) {
|
|
global $descs, $_descdict;
|
|
if(empty($descnames)) {
|
|
$descnames = $descs;
|
|
}
|
|
foreach($descnames as $descname) {
|
|
if(isset($_descdict[$descname])) {
|
|
$out[$descname] = $_descdict[$descname] -> Predict($this -> OBMol);
|
|
}
|
|
else {
|
|
throw new \Exception($descname.' is not recognised Open Babel descriptor type');
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function calcfp($fptype="FP2") {
|
|
global $_fingerprinters;
|
|
$fp = new \vectorUnsignedInt;
|
|
$fptype = strtolower($fptype);
|
|
if(isset($_fingerprinters[$fptype])) {
|
|
$fingerprinter = $_fingerprinters[$fptype];
|
|
$fingerprinter -> GetFingerprint($this -> OBMol, $fp);
|
|
return new Fingerprint($fp);
|
|
}
|
|
else {
|
|
throw new \Exception($fptype.' is not a recognised Open Babel Fingerprint type');
|
|
}
|
|
}
|
|
|
|
public function __toString() {
|
|
return $this -> write();
|
|
}
|
|
|
|
public function write($format = 'smi', $filename = null, $overwrite = false, $opt = array()) {
|
|
$OBConversion = new \OBConversion;
|
|
$OBConversion -> SetOutFormat($format);
|
|
# set options
|
|
if(!empty($opt)) {
|
|
foreach($opt as $k => $v) {
|
|
if($v === null) {
|
|
$OBConversion -> AddOption($k, $OBConversion::OUTOPTIONS, $v);
|
|
}
|
|
else {
|
|
$OBConversion -> AddOption($k, $OBConversion::OUTOPTIONS);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!empty($filename)) {
|
|
if(!file_exists($filename) || file_exists($filename) && $overwrite) {
|
|
return $OBConversion->WriteFile($this -> OBMol, $filename);
|
|
}
|
|
}
|
|
else {
|
|
return $OBConversion->WriteString($this -> OBMol);
|
|
}
|
|
}
|
|
|
|
public function localopt($forcefield = 'mmff94', $steps = 50) {
|
|
global $_forcefields;
|
|
$forcefield = strtolower($forcefield);
|
|
if($this -> dim != 3) {
|
|
$this -> make3D($forcefield);
|
|
}
|
|
$ff = $_forcefields[$forcefield];
|
|
if(!$ff -> Setup($this -> OBMol)) {
|
|
return false;
|
|
}
|
|
$ff -> SteepestDescent($steps);
|
|
$ff -> GetCoordinates($this -> OBMol);
|
|
}
|
|
|
|
public function make3D($forcefield = 'mmff94', $steps = 50) {
|
|
global $_builder;
|
|
$forcefield = strtolower($forcefield);
|
|
$_builder -> Build($this -> OBMol);
|
|
$this -> addh();
|
|
$this -> localopt($forcefield, $steps);
|
|
}
|
|
|
|
public function addh() {
|
|
$this -> OBMol -> AddHydrogens();
|
|
}
|
|
|
|
public function removeh() {
|
|
$this -> OBMol -> DeleteHydrogens();
|
|
}
|
|
|
|
public function convertdbonds() {
|
|
$this -> OBMol -> ConvertDativeBonds();
|
|
}
|
|
|
|
public function draw() {
|
|
return $this -> write('svg');
|
|
}
|
|
}
|
|
|
|
class Atom {
|
|
public function __construct($OBAtom) {
|
|
$this -> OBAtom = $OBAtom;
|
|
}
|
|
|
|
public function __get($name) {
|
|
switch($name) {
|
|
case 'coords':
|
|
$out = array($this -> OBAtom -> GetX(), $this -> OBAtom -> GetY(), $this -> OBAtom -> GetZ());
|
|
break;
|
|
case 'atomicmass':
|
|
$out = $this -> OBAtom -> GetAtomicMass();
|
|
break;
|
|
case 'atomicnum':
|
|
$out = $this -> OBAtom -> GetAtomicNum();
|
|
break;
|
|
case 'cidx':
|
|
$out = $this -> OBAtom -> GetCIdx();
|
|
break;
|
|
case 'coordidx':
|
|
$out = $this -> OBAtom -> GetCoordinateIdx();
|
|
break;
|
|
case 'exactmass':
|
|
$out = $this -> OBAtom -> GetExactMass();
|
|
break;
|
|
case 'formalcharge':
|
|
$out = $this -> OBAtom -> GetFormalCharge();
|
|
break;
|
|
case 'heavyvalence':
|
|
$out = $this -> OBAtom -> GetHvyValence();
|
|
break;
|
|
case 'heterovalence':
|
|
$out = $this -> OBAtom -> GetHeteroValence();
|
|
break;
|
|
case 'hyb':
|
|
$out = $this -> OBAtom -> GetHyb();
|
|
break;
|
|
case 'idx':
|
|
$out = $this -> OBAtom -> GetIdx();
|
|
break;
|
|
case 'implicitvalence':
|
|
$out = $this -> OBAtom -> GetImplicitValence();
|
|
break;
|
|
case 'isotope':
|
|
$out = $this -> OBAtom -> GetIsotope();
|
|
break;
|
|
case 'partialcharge':
|
|
$out = $this -> OBAtom -> GetPartialCharge();
|
|
break;
|
|
case 'residue':
|
|
$out = new Residue($this -> OBAtom -> GetResidue());
|
|
break;
|
|
case 'spin':
|
|
$out = $this -> OBAtom -> GetSpinMultiplicity();
|
|
break;
|
|
case 'type':
|
|
$out = $this -> OBAtom -> GetType();
|
|
break;
|
|
case 'valence':
|
|
$out = $this -> OBAtom -> GetValence();
|
|
break;
|
|
case 'vector':
|
|
$out = $this -> OBAtom -> GetVector();
|
|
break;
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function __toString() {
|
|
|
|
return 'Atom: '.$this -> atomicnum.' ('.$this -> coords[0] .', '.$this -> coords[1] .', '.$this -> coords[2] .')';
|
|
}
|
|
}
|
|
|
|
class Residue {
|
|
private $atoms = array();
|
|
|
|
public function __construct($OBResidue) {
|
|
$this -> OBResidue = $OBResidue;
|
|
}
|
|
|
|
public function __get($name) {
|
|
switch($name) {
|
|
case 'idx':
|
|
$out = $this -> OBResidue -> GetIdx();
|
|
break;
|
|
case 'num':
|
|
$out = $this -> OBResidue -> GetNum();
|
|
break;
|
|
case 'name':
|
|
$out = $this -> OBResidue -> GetName();
|
|
break;
|
|
case 'atoms':
|
|
if(empty($this -> atoms)) { # generate atoms only once
|
|
$num = $this -> OBResidue -> GetNumAtoms();
|
|
$iter = $this -> OBResidue -> BeginAtoms();
|
|
$out[] = new Atom($this -> OBResidue -> BeginAtom($iter));
|
|
for($i=0;$i<$num-1;$i++) {
|
|
$out[] = new Atom($this -> OBResidue -> NextAtom($iter));
|
|
}
|
|
$this -> atoms = $out;
|
|
}
|
|
else {
|
|
$out = $this -> atoms;
|
|
}
|
|
break;
|
|
}
|
|
return $out;
|
|
}
|
|
}
|
|
|
|
function tanimoto($fp1, $fp2) {
|
|
return \OBFingerprint::Tanimoto($fp1 -> fp, $fp2 -> fp);
|
|
}
|
|
|
|
class Fingerprint {
|
|
public $fp = null;
|
|
|
|
public function __construct($fp) {
|
|
$this -> fp = $fp;
|
|
}
|
|
|
|
public function __toString() {
|
|
return implode(', ', vector2array($this -> fp));
|
|
}
|
|
}
|
|
|
|
class Smarts {
|
|
private $obsmarts = null;
|
|
|
|
public function __construct($smartspattern) {
|
|
$this -> obsmarts = new \OBSmartsPattern;
|
|
if(!$this -> obsmarts -> Init($smartspattern)) {
|
|
throw new Exception('Invalid SMARTS pattern');
|
|
}
|
|
}
|
|
|
|
public function findall($mol) {
|
|
$this -> obsmarts -> Match($mol -> OBMol);
|
|
foreach(vector2array($this -> obsmarts -> GetUMapList()) as $match) {
|
|
$out[] = vector2array($match);
|
|
}
|
|
return $out;
|
|
}
|
|
}
|
|
|
|
class MoleculeData {
|
|
private $_mol = null;
|
|
|
|
public function __construct($obmol) {
|
|
$this -> _mol = $obmol;
|
|
}
|
|
|
|
public function _data() {
|
|
$data = vector2array($this -> _mol -> GetData());
|
|
foreach($data as $d) {
|
|
if(in_array($d -> GetDataType(), array(\openbabel::PairData, \openbabel::CommentData))) {
|
|
$out[] = \openbabel::toPairData($d);
|
|
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function keys() {
|
|
foreach($this -> _data() as $d) {
|
|
$out[] = $d -> GetAttribute();
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function values() {
|
|
foreach($this -> _data() as $d) {
|
|
$out[] = $d -> GetValue();
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function items() {
|
|
foreach($this -> _data() as $d) {
|
|
$out[$d -> GetAttribute()] = $d -> GetValue();
|
|
}
|
|
return $out;
|
|
}
|
|
}
|
|
?>
|