merge back in changes from ChemTransforms (r30:51);

the makefile for linux is still missing (I have one, I just need to retrieve it)
but otherwise this is in pretty good shape. 
err, I think so at least.
This commit is contained in:
Greg Landrum
2006-09-15 16:44:38 +00:00
parent 9f5ed2186a
commit a890611a22
26 changed files with 2366 additions and 523 deletions

View File

@@ -82,6 +82,8 @@ namespace RDGeom {
.def(python::self -= python::self)
.def(python::self + python::self)
.def(python::self += python::self)
.def(python::self * double())
.def(python::self / double())
.def("__imul__", &Point3D::operator*=,
python::return_value_policy<python::copy_non_const_reference>(),
"Scalar multiplication")
@@ -120,6 +122,8 @@ namespace RDGeom {
.def(python::self -= python::self)
.def(python::self + python::self)
.def(python::self += python::self)
.def(python::self * double())
.def(python::self / double())
.def("__imul__", &Point2D::operator*=,
python::return_value_policy<python::copy_non_const_reference>(),
"Scalar multiplication")

View File

@@ -366,6 +366,25 @@ void Atom::expandQuery(Atom::QUERYATOM_QUERY *what,
bool Atom::Match(Atom const *what) const {
bool res = getAtomicNum() == what->getAtomicNum();
// special dummy--dummy match case:
// X matches X, Xa, Xb, etc
// Xa only matches X and Xa
if(res && !getAtomicNum()){
std::string l1;
if(this->hasProp("dummyLabel")){
this->getProp("dummyLabel",l1);
} else{
l1="X";
}
if(l1!="X"){
std::string l2;
if(what->hasProp("dummyLabel")) what->getProp("dummyLabel",l2);
else l2="X";
if(l2!="X" && l1!=l2){
res = false;
}
}
}
return res;
}
bool Atom::Match(const Atom::ATOM_SPTR what) const {

View File

@@ -0,0 +1,183 @@
// $Id$
//
// Copyright (C) 2006 Greg Landrum
//
// @@ All Rights Reserved @@
//
#include <RDGeneral/utils.h>
#include <RDGeneral/Invariant.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/Substruct/SubstructMatch.h>
#include <vector>
#include <algorithm>
namespace RDKit{
ROMol *deleteSubstructs(const ROMol &mol, const ROMol &query,
bool onlyFrags) {
RWMol *res = static_cast<RWMol*>(new ROMol(mol,false));
std::vector<MatchVectType> fgpMatches;
std::vector<MatchVectType>::const_iterator mati;
std::pair<int, int> amat;
VECT_INT_VECT matches; // all matches onto the molecule - list of list of atom ids
MatchVectType::const_iterator mi;
// do the substructure matching and get the atoms that match the query
SubstructMatch(*res, query, fgpMatches);
// if didn't find any matches nothing to be done here
// simply return a copy of the molecule
if (fgpMatches.size() == 0) {
return res;
}
for (mati = fgpMatches.begin(); mati != fgpMatches.end(); mati++) {
INT_VECT match; // each match onto the molecule - list of atoms ids
for (mi = mati->begin(); mi != mati->end(); mi++) {
match.push_back(mi->second);
}
matches.push_back(match);
}
// now loop over the list of matches and check if we can delete any of them
INT_VECT delList;
VECT_INT_VECT_I mxi, fi;
if (onlyFrags) {
VECT_INT_VECT frags;
unsigned int nfrags = MolOps::getMolFrags(*res, frags);
for (fi = frags.begin(); fi != frags.end(); fi++) {
std::sort(fi->begin(), fi->end());
for (mxi = matches.begin(); mxi != matches.end(); mxi++) {
std::sort(mxi->begin(), mxi->end());
if ((*fi) == (*mxi) ) {
INT_VECT tmp;
Union((*mxi), delList, tmp);
delList = tmp;
break;
} // end of if we found a matching fragment
} // endof loop over matches
} // end of loop over fragments
} // end of if onlyFrags
else {
// in this case we want to delete any matches we find
// simply loop over the matches and collect the atoms that need to
// be removed
for (mxi = matches.begin(); mxi != matches.end(); mxi++) {
INT_VECT tmp;
Union((*mxi), delList, tmp);
delList = tmp;
}
}
// now loop over the union list and delete the atoms
// Will do this in the decreasing order of the atomIds
// this is so that the AtomIds ids in the "delList" are
// not invalidated by a previous removal (removing atom number i changes
// the atom indices only atoms with indices >i )
std::sort(delList.begin(), delList.end());
INT_VECT_RI dri;
for (dri = delList.rbegin(); dri != delList.rend(); dri++) {
res->removeAtom(*dri);
}
// if we removed any atoms, clear the computed properties:
if(delList.size()){
res->clearComputedProps(true);
// update our properties, but allow unhappiness:
res->updatePropertyCache(false);
}
return res;
}
std::vector<ROMOL_SPTR>
replaceSubstructs(const ROMol &mol, const ROMol &query,const ROMol &replacement,
bool replaceAll) {
std::vector<ROMOL_SPTR> res;
std::vector<MatchVectType> fgpMatches;
// do the substructure matching and get the atoms that match the query
SubstructMatch(mol, query, fgpMatches);
// if we didn't find any matches, there's nothing to be done here
// simply return a list with a copy of the starting molecule
if (fgpMatches.size() == 0) {
res.push_back(ROMOL_SPTR(new ROMol(mol,false)));
return res;
}
INT_VECT delList;
// now loop over the list of matches and replace them:
for (std::vector<MatchVectType>::const_iterator mati = fgpMatches.begin();
mati != fgpMatches.end(); mati++) {
INT_VECT match; // each match onto the molecule - list of atoms ids
for (MatchVectType::const_iterator mi = mati->begin();
mi != mati->end(); mi++) {
match.push_back(mi->second);
}
INT_VECT sortMatch = match;
std::sort(sortMatch.begin(),sortMatch.end());
if( !replaceAll || !res.size() ) {
res.push_back(ROMOL_SPTR(new ROMol(mol,false)));
}
RWMol *newMol = static_cast<RWMol *>(res.rbegin()->get());
// we need a tab to the orig number of atoms because the
// new molecule will start numbered above this:
int numOrigAtoms=newMol->getNumAtoms();
// Add the atoms and bonds from the replacement:
newMol->insertMol(replacement);
// loop over the central atom's (the first atom in match) bonds
// and duplicate any that connect to the remainder of the molecule:
Atom *origAtom=newMol->getAtomWithIdx(match[0]);
ROMol::ADJ_ITER nbrIdx,endNbrs;
boost::tie(nbrIdx,endNbrs) = newMol->getAtomNeighbors(origAtom);
while(nbrIdx!=endNbrs){
// we don't want to duplicate any "intra-match" bonds:
if(!std::binary_search(sortMatch.begin(),sortMatch.end(),int(*nbrIdx))){
Bond *oBond=newMol->getBondBetweenAtoms(match[0],*nbrIdx);
CHECK_INVARIANT(oBond,"required bond not found");
newMol->addBond(numOrigAtoms,*nbrIdx,oBond->getBondType());
}
nbrIdx++;
}
if(replaceAll){
// we'll accumulate a list of atoms to be removed:
INT_VECT tmp;
Union(sortMatch, delList, tmp);
delList = tmp;
} else {
// just delete the atoms now:
for (INT_VECT_RI dri = sortMatch.rbegin(); dri != sortMatch.rend(); dri++) {
newMol->removeAtom(*dri);
}
}
}
if(replaceAll){
// remove the atoms from the delList:
std::sort(delList.begin(),delList.end());
RWMol *newMol = static_cast<RWMol *>(res[0].get());
for (INT_VECT_RI dri = delList.rbegin(); dri != delList.rend(); dri++) {
newMol->removeAtom(*dri);
}
}
// clear computed props and do basic updates on the
// the resulting molecules, but allow unhappiness:
for(std::vector<ROMOL_SPTR>::iterator resI=res.begin();
resI!=res.end();resI++){
(*resI)->clearComputedProps(true);
(*resI)->updatePropertyCache(false);
}
return res;
}
}

View File

@@ -0,0 +1,72 @@
//
// Copyright (C) 2006 Greg Landrum
//
// @@ All Rights Reserved @@
//
#ifndef _RD_CHEMTRANSFORMS_H__
#define _RD_CHEMTRANSFORMS_H__
#include <boost/smart_ptr.hpp>
#include <vector>
namespace RDKit{
class ROMol;
typedef boost::shared_ptr<ROMol> ROMOL_SPTR;
//! \brief Returns a copy of an ROMol with the atoms and bonds that
//! match a pattern removed.
/*!
\param mol the ROMol of interest
\param query the query ROMol
\param onlyFrags if this is set, only matches that correspond to an
entire fragment will be removed. This is useful for
salt removal
\return a copy of \c mol with the matching atoms and bonds (if any)
removed.
*/
ROMol *deleteSubstructs(const ROMol &mol, const ROMol &query,
bool replaceAll=false);
//! \brief Returns a list of copies of an ROMol with the atoms and bonds that
//! match a pattern replaced with the atoms contained in another molecule.
/*!
Bonds are created between the joining atom in the existing molecule
and the atoms in the new molecule. So, using SMILES instead of molecules:
replaceSubstructs('OC(=O)NCCNC(=O)O','C(=O)O','[X]') ->
['[X]NCCNC(=O)O','OC(=O)NCCN[X]']
replaceSubstructs('OC(=O)NCCNC(=O)O','C(=O)O','[X]',true) ->
['[X]NCCN[X]']
Chains should be handled "correctly":
replaceSubstructs('CC(=O)C','C(=O)','[X]') ->
['C[X]C']
As should rings:
replaceSubstructs('C1C(=O)C1','C(=O)','[X]') ->
['C1[X]C1']
And higher order branches:
replaceSubstructs('CC(=O)(C)C','C(=O)','[X]') ->
['C[X](C)C']
Note that the client is responsible for making sure that the
resulting molecule actually makes sense - this function does not
perform sanitization.
\param mol the ROMol of interest
\param query the query ROMol
\param replacement the ROMol to be inserted
\param replaceAll if this is true, only a single result, with all occurances
of the substructure replaced, will be returned.
\return a vector of pointers to copies of \c mol with the matching atoms
and bonds (if any) replaced
*/
std::vector<ROMOL_SPTR> replaceSubstructs(const ROMol &mol, const ROMol &query,
const ROMol &replacement,
bool replaceAll=false);
}
#endif

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="libChemTransforms"
SccProjectName=""
SccLocalPath="">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\Debug"
IntermediateDirectory=".\Debug"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(RDBASE)/Code,$(BOOSTHOME)\include\$(BOOSTBASE),$(RDBASE)/External/vflib-2.0/include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Debug/ChemTransforms.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Debug\ChemTransforms.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="4"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="$(RDBASE)/Code,$(BOOSTHOME)\include\$(BOOSTBASE),$(RDBASE)/External/vflib-2.0/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="TRUE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="2"
PrecompiledHeaderFile=".\Release/ChemTransforms.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\Release\ChemTransforms.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
RelativePath=".\ChemTransforms.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl">
<File
RelativePath="ChemTransforms.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,194 @@
// $Id$
//
// Copyright (C) 2006 Greg Landrum
//
// @@ All Rights Reserved @@
//
#include <RDGeneral/RDLog.h>
#include <GraphMol/RDKitBase.h>
#include <string>
#include <iostream>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/ChemTransforms/ChemTransforms.h>
using namespace RDKit;
void testDeleteSubstruct()
{
int i = 0;
ROMol *mol1=0,*mol2=0,*matcher1=0,*matcher2=0,*matcher3=0;
std::string smi,sma;
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
BOOST_LOG(rdInfoLog) << "Testing deleteSubstruct" << std::endl;
// a lot of the seemingly repetitive stuff is here for Issue96
smi = "CCC(=O).C=O";
mol1 = SmilesToMol(smi);
TEST_ASSERT(mol1);
TEST_ASSERT(mol1->getNumAtoms()==6)
sma = "C=O";
matcher1 = SmartsToMol(sma);
TEST_ASSERT(matcher1);
mol2 = deleteSubstructs(*mol1,*matcher1,0);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==2)
mol2 = deleteSubstructs(*mol2,*matcher1,0);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==2)
delete matcher1;
sma = "[Cl;H1&X1,-]";
matcher1 = SmartsToMol(sma);
sma = "[Na+]";
matcher2 = SmartsToMol(sma);
sma = "[O;H2,H1&-,X0&-2]";
matcher3 = SmartsToMol(sma);
delete mol1;
mol1 = SmilesToMol("CCO.Cl");
TEST_ASSERT(mol1);
TEST_ASSERT(mol1->getNumAtoms()==4);
delete mol2;
mol2 = deleteSubstructs(*mol1,*matcher1,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==3);
mol2 = deleteSubstructs(*mol2,*matcher2,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==3);
mol2 = deleteSubstructs(*mol2,*matcher3,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==3);
delete mol1;
mol1 = SmilesToMol("CC(=O)[O-].[Na+]");
TEST_ASSERT(mol1);
TEST_ASSERT(mol1->getNumAtoms()==5);
delete matcher1;
matcher1 = SmartsToMol("[Cl;H1&X1,-]");
delete matcher2;
matcher2 = SmartsToMol("[Na+]");
mol2 = deleteSubstructs(*mol1,*matcher1,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==5);
mol2 = deleteSubstructs(*mol2,*matcher2,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==4);
mol2 = deleteSubstructs(*mol2,*matcher1,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==4);
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
}
void testReplaceSubstructs()
{
int i = 0;
ROMol *mol1=0,*mol2=0,*matcher1=0,*frag=0;
std::string smi,sma;
std::vector<ROMOL_SPTR> vect;
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
BOOST_LOG(rdInfoLog) << "Testing replaceSubstruct" << std::endl;
smi = "CCCC";
mol1 = SmilesToMol(smi);
TEST_ASSERT(mol1);
sma = "C(=O)O";
matcher1 = SmartsToMol(sma);
TEST_ASSERT(matcher1);
smi = "N";
frag = SmilesToMol(smi);
TEST_ASSERT(frag);
vect = replaceSubstructs(*mol1,*matcher1,*frag);
TEST_ASSERT(vect.size()==1);
TEST_ASSERT(mol1->getNumAtoms()==4);
TEST_ASSERT(vect[0]->getNumAtoms()==4);
delete mol1;
smi = "CCCC(=O)O";
mol1 = SmilesToMol(smi);
TEST_ASSERT(mol1);
vect = replaceSubstructs(*mol1,*matcher1,*frag);
TEST_ASSERT(vect.size()==1);
TEST_ASSERT(mol1->getNumAtoms()==6);
TEST_ASSERT(vect[0]->getNumAtoms()==4);
vect = replaceSubstructs(*mol1,*matcher1,*frag,true);
TEST_ASSERT(vect.size()==1);
TEST_ASSERT(mol1->getNumAtoms()==6);
TEST_ASSERT(vect[0]->getNumAtoms()==4);
delete mol1;
smi = "OC(=O)CCCC(=O)O";
mol1 = SmilesToMol(smi);
TEST_ASSERT(mol1);
vect = replaceSubstructs(*mol1,*matcher1,*frag);
TEST_ASSERT(vect.size()==2);
TEST_ASSERT(mol1->getNumAtoms()==9);
TEST_ASSERT(vect[0]->getNumAtoms()==7);
TEST_ASSERT(vect[1]->getNumAtoms()==7);
// use replaceAll when a single replacement is available:
vect = replaceSubstructs(*mol1,*matcher1,*frag,true);
TEST_ASSERT(vect.size()==1);
TEST_ASSERT(mol1->getNumAtoms()==9);
TEST_ASSERT(vect[0]->getNumAtoms()==5);
delete matcher1;
sma = "C=O";
matcher1 = SmartsToMol(sma);
TEST_ASSERT(matcher1);
delete mol1;
smi = "CC(=O)C";
mol1 = SmilesToMol(smi);
TEST_ASSERT(mol1);
vect = replaceSubstructs(*mol1,*matcher1,*frag);
TEST_ASSERT(vect.size()==1);
TEST_ASSERT(mol1->getNumAtoms()==4);
TEST_ASSERT(vect[0]->getNumAtoms()==3);
delete mol1;
smi = "C1C(=O)C1";
mol1 = SmilesToMol(smi);
TEST_ASSERT(mol1);
vect = replaceSubstructs(*mol1,*matcher1,*frag);
TEST_ASSERT(vect.size()==1);
TEST_ASSERT(mol1->getNumAtoms()==4);
TEST_ASSERT(vect[0]->getNumAtoms()==3);
TEST_ASSERT(vect[0]->getNumBonds()==3);
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
}
int main() {
RDLog::InitLogs();
BOOST_LOG(rdInfoLog) << "********************************************************\n";
BOOST_LOG(rdInfoLog) << "Testing Chemical Transforms \n";
#if 1
testDeleteSubstruct();
testReplaceSubstructs();
#endif
BOOST_LOG(rdInfoLog) << "*******************************************************\n";
return(0);
}

View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="testChemTransforms"
ProjectGUID="{5408B0E6-0B50-4E12-921A-8F1B3E483716}"
SccProjectName=""
SccLocalPath="">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\testExecs"
IntermediateDirectory=".\Debug"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(BOOSTHOME)/include/$(BOOSTBASE),$(RDBASE)/Code"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\Debug/testChemTransforms.pch"
AssemblerListingLocation=".\Debug/"
ObjectFile=".\Debug/"
ProgramDataBaseFileName=".\Debug/"
WarningLevel="3"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="boost_log-vc71-mt-gd-$(BOOSTVERSION).lib"
OutputFile="./testExecs/main.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="$(BOOSTHOME)\lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\Debug/test.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Debug/testChemTransforms.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\testExecs\"
IntermediateDirectory=".\Release"
ConfigurationType="1"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="FALSE"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="$(BOOSTHOME)/include/$(BOOSTBASE),$(RDBASE)/Code"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="TRUE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="TRUE"
PrecompiledHeaderFile=".\Release/testChemTransforms.pch"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="boost_log-vc71-mt-$(BOOSTVERSION).lib"
OutputFile="./testExecs/main.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="$(BOOSTHOME)\lib"
ProgramDatabaseFile=".\Release/test.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"
TypeLibraryName=".\Release/testChemTransforms.tlb"
HeaderFileName=""/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
RelativePath=".\testChemTransforms.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl">
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,14 @@
import sys
tests=[
("testExecs/main.exe","",{}),
]
longTests=[
]
if __name__=='__main__':
import sys
import TestRunner
failed,tests = TestRunner.RunScript('test_list.py',0,1)
sys.exit(len(failed))

View File

@@ -197,7 +197,8 @@ namespace RDKit{
//double pX,pY,pZ;
std::string symb;
int massDiff,chg,hCount;
//int rxnComponentType,rxnComponentNumber,atomMapNumber,inversionFlag,exactChangeFlag;
int stereoCare,totValence;
int atomMapNumber,inversionFlag,exactChangeFlag;
try {
pos.x = stripSpacesAndCast<double>(text.substr(0,10));
@@ -250,6 +251,18 @@ namespace RDKit{
if(symb=="L" || symb=="A" || symb=="Q" || symb=="*" || symb=="LP"
|| (symb>="R0" && symb<="R9") ){
res->setAtomicNum(0);
if(symb=="*") res->setProp("dummyLabel",std::string("X"));
else if(symb=="R0") res->setProp("dummyLabel",std::string("Xa"));
else if(symb=="R1") res->setProp("dummyLabel",std::string("Xb"));
else if(symb=="R2") res->setProp("dummyLabel",std::string("Xc"));
else if(symb=="R3") res->setProp("dummyLabel",std::string("Xd"));
else if(symb=="R4") res->setProp("dummyLabel",std::string("Xe"));
else if(symb=="R5") res->setProp("dummyLabel",std::string("Xf"));
else if(symb=="R6") res->setProp("dummyLabel",std::string("Xg"));
else if(symb=="R7") res->setProp("dummyLabel",std::string("Xh"));
else if(symb=="R8") res->setProp("dummyLabel",std::string("Xi"));
else if(symb=="R9") res->setProp("dummyLabel",std::string("Xj"));
else res->setProp("dummyLabel",symb);
} else {
res->setAtomicNum(PeriodicTable::getTable()->getAtomicNumber(symb));
res->setMass(PeriodicTable::getTable()->getAtomicWeight(res->getAtomicNum()));
@@ -264,7 +277,7 @@ namespace RDKit{
res->setMass(res->getMass()+massDiff);
}
#if 0
#if 1
stereoCare=0;
if(text.size()>=48){
try {
@@ -287,28 +300,6 @@ namespace RDKit{
throw FileParseException(errout.str()) ;
}
}
rxnComponentType=0;
if(text.size()>=57){
try {
rxnComponentType= stripSpacesAndCast<int>(text.substr(54,3));
}
catch (boost::bad_lexical_cast &) {
std::ostringstream errout;
errout << "Cannot convert " << text.substr(54,3) << " to int";
throw FileParseException(errout.str()) ;
}
}
rxnComponentNumber=0;
if(text.size()>=60){
try {
rxnComponentNumber= stripSpacesAndCast<int>(text.substr(57,3));
}
catch (boost::bad_lexical_cast &) {
std::ostringstream errout;
errout << "Cannot convert " << text.substr(57,3) << " to int";
throw FileParseException(errout.str()) ;
}
}
atomMapNumber=0;
if(text.size()>=63){
try {
@@ -345,13 +336,11 @@ namespace RDKit{
// save it for later
res->setProp("stereoCare",stereoCare);
res->setProp("totValence",totValence);
res->setProp("rxnComponentType",rxnComponentType);
res->setProp("rxnComponentNumber",rxnComponentNumber);
res->setProp("atomMapNumber",atomMapNumber);
res->setProp("inversionFlag",inversionFlag);
res->setProp("exactChangeFlag",exactChangeFlag);
res->setProp("molStereoCare",stereoCare);
res->setProp("molTotValence",totValence);
res->setProp("molAtomMapNumber",atomMapNumber);
res->setProp("molInversionFlag",inversionFlag);
res->setProp("molExactChangeFlag",exactChangeFlag);
#endif
return res;
};
@@ -442,19 +431,19 @@ namespace RDKit{
} catch (boost::bad_lexical_cast) {
;
}
#if 0
#if 1
if( text.size() >= 18 )
try {
topology = stripSpacesAndCast<int>(text.substr(15,3));
res->setProp("topology",topology);
int topology = stripSpacesAndCast<int>(text.substr(15,3));
res->setProp("molTopology",topology);
} catch (boost::bad_lexical_cast) {
;
}
if( text.size() >= 21 )
try {
reactStatus = stripSpacesAndCast<int>(text.substr(18,3));
res->setProp("reactStatus",reactStatus);
int reactStatus = stripSpacesAndCast<int>(text.substr(18,3));
res->setProp("molReactStatus",reactStatus);
} catch (boost::bad_lexical_cast) {
;
}

View File

@@ -509,7 +509,8 @@ ATOM_EQUALS_QUERY *makeAtomInRingQuery(){
}
ATOM_EQUALS_QUERY *makeAtomInNRingsQuery(int what){
ATOM_EQUALS_QUERY *res= makeAtomSimpleQuery(what,queryIsAtomInNRings);
ATOM_EQUALS_QUERY *res;
res = makeAtomSimpleQuery(what,queryIsAtomInNRings);
res->setDescription("AtomInNRings");
return res;
}

View File

@@ -79,7 +79,53 @@ namespace RDKit{
//! returns a Query for matching any atom
ATOM_NULL_QUERY *makeAtomNullQuery();
static int queryAtomRingMembership(Atom const *at) {
return static_cast<int>(at->getOwningMol().getRingInfo()->numAtomRings(at->getIdx()));
}
// I'm pretty sure that this typedef shouldn't be necessary,
// but VC++ generates a warning about const Atom const * in
// the definition of Match, then complains about an override
// that differs only by const/volatile (c4301), then generates
// incorrect code if we don't do this... so let's do it.
typedef Atom const *ConstAtomPtr;
class InRingQuery : public Queries::EqualityQuery<int, ConstAtomPtr,true> {
public:
InRingQuery() : Queries::EqualityQuery<int,ConstAtomPtr,true>(-1) {
this->setDescription("AtomInNRings");
this->setDataFunc(queryAtomRingMembership);
};
explicit InRingQuery(int v) : Queries::EqualityQuery<int,ConstAtomPtr,true>(v) {
this->setDescription("AtomInNRings");
this->setDataFunc(queryAtomRingMembership);
};
virtual bool Match(const ConstAtomPtr what) const {
int v = this->TypeConvert(what,Queries::Int2Type<true>());
bool res;
if(this->d_val<0){
res = v!=0;
} else {
res=!Queries::queryCmp(v,this->d_val,this->d_tol);
}
if(this->getNegation()){
res=!res;
}
return res;
}
//! returns a copy of this query
Queries::Query<int,ConstAtomPtr,true> *
copy() const {
InRingQuery *res =
new InRingQuery(this->d_val);
res->setNegation(getNegation());
res->setTol(this->getTol());
res->d_description = this->d_description;
return res;
}
};
//! allows use of recursive structure queries (e.g. recursive SMARTS)
class RecursiveStructureQuery : public Queries::SetQuery<int,Atom const *,true> {
public:

View File

@@ -294,7 +294,7 @@ namespace RDKit{
... atomPtr is a const Atom * ...
ROMol::OEDGE_ITER beg,end;
ROMol::GRAPH_MOL_BOND_PMAP::const_type pMap = molPtr->getBondPMap();
boost::tie(beg,end) = molPtr->getAtomNeighbors(atomPtr);
boost::tie(beg,end) = molPtr->getAtomBonds(atomPtr);
while(beg!=end){
const Bond *bond=pMap[*beg];
... do something with the Bond ...
@@ -307,7 +307,7 @@ namespace RDKit{
... atomPtr is a const Atom * ...
ROMol::OEDGE_ITER beg,end;
ROMol::GRAPH_MOL_BOND_PMAP::type pMap = molPtr->getBondPMap();
boost::tie(beg,end) = molPtr->getAtomNeighbors(atomPtr);
boost::tie(beg,end) = molPtr->getAtomBonds(atomPtr);
while(beg!=end){
Bond *bond=pMap[*beg];
... do something with the Bond ...

View File

@@ -150,7 +150,10 @@ namespace RDKit {
needParen = true;
}
else if (descrip == "AtomInNRings") {
res << "R" << query->getVal();
res << "R";
if(query->getVal()>=0){
res << query->getVal();
}
needParen = true;
}
else if (descrip == "AtomFormalCharge") {

View File

@@ -5,6 +5,7 @@
// @@ All Rights Reserved @@
//
#include <GraphMol/RDKitBase.h>
#include <GraphMol/RDKitQueries.h>
#include "SmilesParse.h"
#include "SmilesParseOps.h"
#include <list>
@@ -28,7 +29,7 @@ namespace SmilesParseOps{
// between the fragment and the molecule
//
void AddFragToMol(RWMol *mol,RWMol *frag,Bond::BondType bondOrder,
Bond::BondDir bondDir,bool closeRings ){
Bond::BondDir bondDir,bool closeRings,bool doingQuery ){
RWMol::GRAPH_NODE_TYPE lastAt = mol->getActiveAtom();
int nOrigAtoms = mol->getNumAtoms();
int nOrigBonds = mol->getNumBonds();
@@ -84,28 +85,56 @@ namespace SmilesParseOps{
leadingBond->setEndAtomIdx(atomIdx1);
mol->addBond(leadingBond,true);
} else {
if(bondOrder == Bond::UNSPECIFIED){
// no bond order provided, figure it out ourselves
if(lastAt->getIsAromatic() && firstAt->getIsAromatic() ){
bo = Bond::AROMATIC;
if(!doingQuery){
if(bondOrder == Bond::UNSPECIFIED){
// no bond order provided, figure it out ourselves
if(lastAt->getIsAromatic() && firstAt->getIsAromatic() ){
bo = Bond::AROMATIC;
}
else{
bo = Bond::SINGLE;
}
}
else{
bo = Bond::SINGLE;
bo = bondOrder;
}
if(bo==Bond::DATIVEL){
int tmp=atomIdx2;
atomIdx2 = atomIdx1;
atomIdx1 = tmp;
bo = Bond::DATIVE;
} else if(bo == Bond::DATIVER){
bo = Bond::DATIVE;
}
int idx = mol->addBond(atomIdx2,atomIdx1,bo)-1;
mol->getBondWithIdx(idx)->setBondDir(bondDir);
} else {
// semantics are different in SMARTS, unspecified bonds can be single or aromatic:
if(bondOrder == Bond::UNSPECIFIED){
QueryBond *newB=new QueryBond(Bond::SINGLE);
newB->expandQuery(makeBondOrderEqualsQuery(Bond::AROMATIC),
Queries::COMPOSITE_OR,
true);
newB->setOwningMol(mol);
newB->setBeginAtomIdx(atomIdx1);
newB->setEndAtomIdx(atomIdx2);
mol->addBond(newB);
delete newB;
}
else{
bo=bondOrder;
if(bo==Bond::DATIVEL){
int tmp=atomIdx2;
atomIdx2 = atomIdx1;
atomIdx1 = tmp;
bo = Bond::DATIVE;
} else if(bo == Bond::DATIVER){
bo = Bond::DATIVE;
}
int idx = mol->addBond(atomIdx2,atomIdx1,bo)-1;
mol->getBondWithIdx(idx)->setBondDir(bondDir);
}
}
else{
bo = bondOrder;
}
if(bo==Bond::DATIVEL){
int tmp=atomIdx2;
atomIdx2 = atomIdx1;
atomIdx1 = tmp;
bo = Bond::DATIVE;
} else if(bo == Bond::DATIVER){
bo = Bond::DATIVE;
}
int idx = mol->addBond(atomIdx2,atomIdx1,bo)-1;
mol->getBondWithIdx(idx)->setBondDir(bondDir);
}
}

View File

@@ -16,7 +16,7 @@ namespace SmilesParseOps {
void AddFragToMol(RDKit::RWMol *mol,RDKit::RWMol *frag,
RDKit::Bond::BondType bondOrder=RDKit::Bond::UNSPECIFIED,
RDKit::Bond::BondDir bondDir=RDKit::Bond::NONE,
bool closeRings=false);
bool closeRings=false,bool doingQuery=false);
RDKit::Bond::BondType GetUnspecifiedBondType(const RDKit::RWMol *mol,
const RDKit::Atom *atom1,
const RDKit::Atom *atom2);

View File

@@ -300,7 +300,9 @@ namespace RDKit{
// decisions and I'm gonna want to smack myself for doing this,
// but we'll try anyway.
std::string MolToSmiles(ROMol &mol,bool doIsomericSmiles,
bool doKekule){
bool doKekule,int rootedAtAtom){
PRECONDITION(rootedAtAtom<0||static_cast<unsigned int>(rootedAtAtom)<mol.getNumAtoms(),
"rootedAtomAtom must be less than the number of atoms");
if(doIsomericSmiles){
mol.setProp("_doIsoSmiles",1);
} else if(mol.hasProp("_doIsoSmiles")){
@@ -315,18 +317,17 @@ namespace RDKit{
#endif
std::string res;
int nAtoms=mol.getNumAtoms();
for(ROMol::AtomIterator atIt=mol.beginAtoms();atIt!=mol.endAtoms();atIt++)
for(ROMol::AtomIterator atIt=mol.beginAtoms();atIt!=mol.endAtoms();atIt++){
(*atIt)->updatePropertyCache();
}
INT_VECT ranks;
ranks.resize(nAtoms);
unsigned int nAtoms=mol.getNumAtoms();
INT_VECT ranks(nAtoms,-1);
// clean up the chirality on any atom that is marked as chiral,
// but that should not be:
if(doIsomericSmiles){
MolOps::assignAtomChiralCodes(mol,true);
//MolOps::assignBondStereoCodes(mol,true);
MolOps::rankAtoms(mol,ranks,ComprehensiveInvariants,
true,0,true);
} else {
@@ -343,14 +344,20 @@ namespace RDKit{
colorIt = colors.begin();
// loop to deal with the possibility that there might be disconnected fragments
while(colorIt != colors.end()){
int i,nextAtomIdx,nextRank;
int nextAtomIdx;
std::string subSmi;
// find the next atom for a traverse
nextRank = nAtoms+1;
for(i=0;i<nAtoms;i++){
if( colors[i] == Canon::WHITE_NODE && ranks[i] < nextRank ){
nextRank = ranks[i];
nextAtomIdx = i;
if(rootedAtAtom>=0){
nextAtomIdx=rootedAtAtom;
rootedAtAtom=-1;
} else {
int nextRank = nAtoms+1;
for(unsigned int i=0;i<nAtoms;i++){
if( colors[i] == Canon::WHITE_NODE && ranks[i] < nextRank ){
nextRank = ranks[i];
nextAtomIdx = i;
}
}
}

View File

@@ -17,6 +17,6 @@ namespace SmilesWrite {
namespace RDKit{
std::string MolToSmiles(ROMol &mol,bool doIsomericSmiles=false,
bool doKekule=false);
bool doKekule=false,int rootedAtAtom=-1);
}
#endif

View File

@@ -160,14 +160,12 @@ using namespace RDKit;
}
<IN_ATOM_STATE>R {
yysmarts_lval.atom = new QueryAtom();
// FIX: this doesn't default properly
yysmarts_lval.atom->setQuery(makeAtomInNRingsQuery(1));
yysmarts_lval.atom->setQuery(new InRingQuery(-1));
return COMPLEX_ATOM_QUERY_TOKEN;
}
<IN_ATOM_STATE>r {
yysmarts_lval.atom = new QueryAtom();
// FIX: this doesn't default properly
yysmarts_lval.atom->setQuery(makeAtomInRingOfSizeQuery(3));
yysmarts_lval.atom->setQuery(makeAtomInRingQuery());
return RINGSIZE_ATOM_QUERY_TOKEN;
}

View File

@@ -61,7 +61,7 @@ static RWMol * curMol_gps = 0;
%left SEMI_TOKEN
%left OR_TOKEN
%left AND_TOKEN
%nonassoc NOT_TOKEN
%right NOT_TOKEN
%%
@@ -190,7 +190,7 @@ mol: atomd {
| mol branch {
RWMol *m1_p = molList_g[$$],*m2_p=molList_g[$2];
// FIX: handle generic bonds here
SmilesParseOps::AddFragToMol(m1_p,m2_p,Bond::UNSPECIFIED,Bond::NONE,false);
SmilesParseOps::AddFragToMol(m1_p,m2_p,Bond::UNSPECIFIED,Bond::NONE,false,true);
delete m2_p;
int sz = molList_g.size();
if ( sz==$2+1) {

View File

@@ -133,6 +133,8 @@ std::vector< MatchVectType > _checkMatches(std::string smarts, std::string smile
matcher = SmartsToMol(smarts);
CHECK_INVARIANT(matcher,smarts);
//std::cerr << "\tSMA: " << smarts << " -> " << MolToSmarts(*matcher) << std::endl;;
mol = SmilesToMol(smiles);
CHECK_INVARIANT(mol,smiles);
@@ -240,17 +242,45 @@ void testMatches3(){
_checkMatches("[CH3][CH]", "C(C)(C)CC(=O)[O-]", 2, 2);
_checkMatches("[!C;R]", "c1ccccc1", 6, 1);
_checkMatches("[!C;R]", "C1COC1", 1, 1);
_checkMatches("[c;H]", "c1ccccc1", 6, 1);
_checkNoMatches("[c;H]", "C1CCCCC1");
_checkMatches("[#6]([#7])[#6]", "c1ncccc1", 2, 3);
_checkMatches("[c;H]", "c1c[c-]ccc1", 5, 1);
_checkMatches("C~O", "C(=O)[O-]", 2, 2);
// -----
// This block is connected to SF-Issue 1538280
// http://sourceforge.net/tracker/index.php?func=detail&aid=1538280&group_id=160139&atid=814650
_checkMatches("[R]", "c1ccccc1", 6, 1);
_checkMatches("[r]", "c1ccccc1", 6, 1);
_checkMatches("[R;!O]", "c1ccccc1", 6, 1);
_checkMatches("[c]", "c1ccccc1", 6, 1);
_checkMatches("[R;c]", "c1ccccc1", 6, 1);
_checkMatches("[c;#6]", "c1ccccc1", 6, 1);
_checkMatches("[R;R]", "c1ccccc1", 6, 1);
_checkMatches("[#6;R]", "c1ccccc1", 6, 1);
_checkMatches("[c;R]", "c1ccccc1", 6, 1);
_checkMatches("[!O;R]", "c1ccccc1", 6, 1);
_checkMatches("[!C;R]", "c1ccccc1", 6, 1);
_checkMatches("[!C;R]", "C1COC1", 1, 1);
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
}
@@ -613,77 +643,6 @@ void testSmartsWrite() {
}
void testDeleteSubstruct()
{
int i = 0;
ROMol *mol1=0,*mol2=0,*matcher1=0,*matcher2=0,*matcher3=0;
std::string smi,sma;
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
BOOST_LOG(rdInfoLog) << "Testing deleteSubstruct" << std::endl;
// a lot of the seemingly repetitive stuff is here for Issue96
smi = "CCC(=O).C=O";
mol1 = SmilesToMol(smi);
TEST_ASSERT(mol1);
sma = "C=O";
matcher1 = SmartsToMol(sma);
TEST_ASSERT(matcher1);
mol2 = deleteSubstructs(*mol1,*matcher1,0);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms(4))
mol2 = deleteSubstructs(*mol2,*matcher1,0);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms(4))
delete matcher1;
sma = "[Cl;H1&X1,-]";
matcher1 = SmartsToMol(sma);
sma = "[Na+]";
matcher2 = SmartsToMol(sma);
sma = "[O;H2,H1&-,X0&-2]";
matcher3 = SmartsToMol(sma);
delete mol1;
mol1 = SmilesToMol("CCO.Cl");
TEST_ASSERT(mol1);
TEST_ASSERT(mol1->getNumAtoms()==4);
delete mol2;
mol2 = deleteSubstructs(*mol1,*matcher1,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==3);
mol2 = deleteSubstructs(*mol2,*matcher2,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==3);
mol2 = deleteSubstructs(*mol2,*matcher3,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==3);
delete mol1;
mol1 = SmilesToMol("CC(=O)[O-].[Na+]");
TEST_ASSERT(mol1);
TEST_ASSERT(mol1->getNumAtoms()==5);
delete matcher1;
matcher1 = SmartsToMol("[Cl;H1&X1,-]");
delete matcher2;
matcher2 = SmartsToMol("[Na+]");
mol2 = deleteSubstructs(*mol1,*matcher1,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==5);
mol2 = deleteSubstructs(*mol2,*matcher2,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==4);
mol2 = deleteSubstructs(*mol2,*matcher1,true);
TEST_ASSERT(mol2);
TEST_ASSERT(mol2->getNumAtoms()==4);
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
}
void testIssue196()
{
@@ -864,7 +823,7 @@ int
main(int argc, char *argv[])
{
RDLog::InitLogs();
#if LOCAL_TEST_ALL
#if 1
testPass();
testFail();
testMatches();
@@ -876,12 +835,12 @@ main(int argc, char *argv[])
testSmartsWrite();
testFrags();
testProblems();
testDeleteSubstruct();
testIssue196();
testIssue254();
testIssue255();
testIssue330();
#endif
testIssue351();
#endif
return 0;
}

View File

@@ -1231,6 +1231,28 @@ void testIssue266(){
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
}
void testRootedAt(){
RWMol *mol;
std::string smi;
int numE=0;
BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
BOOST_LOG(rdInfoLog) << "Testing rootedAtAtom functionality" << std::endl;
smi ="CN(C)C";
mol = SmilesToMol(smi);
TEST_ASSERT(mol);
smi = MolToSmiles(*mol,false,false,-1);
TEST_ASSERT(smi=="CN(C)C");
smi = MolToSmiles(*mol,false,false,1);
TEST_ASSERT(smi=="N(C)(C)C");
smi = MolToSmiles(*mol,false,false,2);
TEST_ASSERT(smi=="CN(C)C");
BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
}
int
main(int argc, char *argv[])
@@ -1257,6 +1279,7 @@ main(int argc, char *argv[])
testIssue184();
testIssue191();
testIssue256();
#endif
testIssue266();
#endif
testRootedAt();
}

View File

@@ -82,6 +82,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testQuery", "Query\QueryTes
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testSmartsParse", "GraphMol\SmilesParse\SmartsParseTest.vcproj", "{1F0176D6-8882-4399-B8AF-E75B8287A591}"
ProjectSection(ProjectDependencies) = postProject
{676E091A-4E6E-429B-91EE-0399C46060C6} = {676E091A-4E6E-429B-91EE-0399C46060C6}
{DDF70921-1F56-4EBF-BE90-0E3A0C8BFACB} = {DDF70921-1F56-4EBF-BE90-0E3A0C8BFACB}
{08AF0B31-BA0F-4C46-A889-4411ADB81D68} = {08AF0B31-BA0F-4C46-A889-4411ADB81D68}
{2E8DFE39-3377-45C0-81D6-D32A2C192F34} = {2E8DFE39-3377-45C0-81D6-D32A2C192F34}
@@ -97,6 +98,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libSmilesParse", "GraphMol\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testSmilesParse", "GraphMol\SmilesParse\SmilesParseTest.vcproj", "{20AFEDA7-3046-41F0-9BEF-425D0398362A}"
ProjectSection(ProjectDependencies) = postProject
{676E091A-4E6E-429B-91EE-0399C46060C6} = {676E091A-4E6E-429B-91EE-0399C46060C6}
{DDF70921-1F56-4EBF-BE90-0E3A0C8BFACB} = {DDF70921-1F56-4EBF-BE90-0E3A0C8BFACB}
{08AF0B31-BA0F-4C46-A889-4411ADB81D68} = {08AF0B31-BA0F-4C46-A889-4411ADB81D68}
{2E8DFE39-3377-45C0-81D6-D32A2C192F34} = {2E8DFE39-3377-45C0-81D6-D32A2C192F34}
@@ -185,6 +187,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wrapGraphMol", "GraphMol\Wr
{33BB4E07-B13A-44EB-931F-E748D22A548D} = {33BB4E07-B13A-44EB-931F-E748D22A548D}
{58DBEB0A-76E7-4029-83DC-0B2AC5AAFA5F} = {58DBEB0A-76E7-4029-83DC-0B2AC5AAFA5F}
{0B51D40C-2E72-42AF-97EE-C7D188E717C0} = {0B51D40C-2E72-42AF-97EE-C7D188E717C0}
{676E091A-4E6E-429B-91EE-0399C46060C6} = {676E091A-4E6E-429B-91EE-0399C46060C6}
{08AF0B31-BA0F-4C46-A889-4411ADB81D68} = {08AF0B31-BA0F-4C46-A889-4411ADB81D68}
{2E8DFE39-3377-45C0-81D6-D32A2C192F34} = {2E8DFE39-3377-45C0-81D6-D32A2C192F34}
{1D9A3F4A-DAFD-498E-9C56-59FAE69194C8} = {1D9A3F4A-DAFD-498E-9C56-59FAE69194C8}
@@ -222,6 +225,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wrapMolOps", "GraphMol\Wrap
{33BB4E07-B13A-44EB-931F-E748D22A548D} = {33BB4E07-B13A-44EB-931F-E748D22A548D}
{58DBEB0A-76E7-4029-83DC-0B2AC5AAFA5F} = {58DBEB0A-76E7-4029-83DC-0B2AC5AAFA5F}
{0B51D40C-2E72-42AF-97EE-C7D188E717C0} = {0B51D40C-2E72-42AF-97EE-C7D188E717C0}
{676E091A-4E6E-429B-91EE-0399C46060C6} = {676E091A-4E6E-429B-91EE-0399C46060C6}
{2E8DFE39-3377-45C0-81D6-D32A2C192F34} = {2E8DFE39-3377-45C0-81D6-D32A2C192F34}
{1D9A3F4A-DAFD-498E-9C56-59FAE69194C8} = {1D9A3F4A-DAFD-498E-9C56-59FAE69194C8}
{8DA7765B-EF8E-45D4-B192-2C950C5C79F5} = {8DA7765B-EF8E-45D4-B192-2C950C5C79F5}
@@ -458,6 +462,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZZZGraphMolRegrs", "GraphMo
{C6555EDD-5666-4CF7-8AE2-1CF49A262636} = {C6555EDD-5666-4CF7-8AE2-1CF49A262636}
{55973DDE-14F0-47A9-9F85-5B387884F136} = {55973DDE-14F0-47A9-9F85-5B387884F136}
{B873A5E6-B25D-425C-8527-C52FB524F607} = {B873A5E6-B25D-425C-8527-C52FB524F607}
{5408B0E6-0B50-4E12-921A-8F1B3E483716} = {5408B0E6-0B50-4E12-921A-8F1B3E483716}
{4D9A72F3-BF82-4B1D-BF0C-580DF04E7429} = {4D9A72F3-BF82-4B1D-BF0C-580DF04E7429}
{BB2B6CF7-385A-4478-8D03-F7BA96F5ABD4} = {BB2B6CF7-385A-4478-8D03-F7BA96F5ABD4}
EndProjectSection
@@ -949,6 +954,22 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testDistGeom", "DistGeom\te
{DD564ACC-9799-4A4F-AA43-C42565165EFD} = {DD564ACC-9799-4A4F-AA43-C42565165EFD}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libChemTransforms", "GraphMol\ChemTransforms\ChemTransforms.vcproj", "{676E091A-4E6E-429B-91EE-0399C46060C6}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testChemTransforms", "GraphMol\ChemTransforms\testChemTransforms.vcproj", "{5408B0E6-0B50-4E12-921A-8F1B3E483716}"
ProjectSection(ProjectDependencies) = postProject
{676E091A-4E6E-429B-91EE-0399C46060C6} = {676E091A-4E6E-429B-91EE-0399C46060C6}
{DDF70921-1F56-4EBF-BE90-0E3A0C8BFACB} = {DDF70921-1F56-4EBF-BE90-0E3A0C8BFACB}
{08AF0B31-BA0F-4C46-A889-4411ADB81D68} = {08AF0B31-BA0F-4C46-A889-4411ADB81D68}
{2E8DFE39-3377-45C0-81D6-D32A2C192F34} = {2E8DFE39-3377-45C0-81D6-D32A2C192F34}
{8DA7765B-EF8E-45D4-B192-2C950C5C79F5} = {8DA7765B-EF8E-45D4-B192-2C950C5C79F5}
{41B2DB92-DBB1-4C73-916C-BD7372F46FD4} = {41B2DB92-DBB1-4C73-916C-BD7372F46FD4}
{8A443D9F-4C81-455C-82AB-AA26C9F9EE1C} = {8A443D9F-4C81-455C-82AB-AA26C9F9EE1C}
{A6FD01DB-2F79-4317-85F8-BA361B8EA095} = {A6FD01DB-2F79-4317-85F8-BA361B8EA095}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@@ -1616,6 +1637,18 @@ Global
{91158915-015A-434B-AE89-CE55709440DC}.DebugPython.Build.0 = Debug|Win32
{91158915-015A-434B-AE89-CE55709440DC}.Release.ActiveCfg = Release|Win32
{91158915-015A-434B-AE89-CE55709440DC}.Release.Build.0 = Release|Win32
{676E091A-4E6E-429B-91EE-0399C46060C6}.Debug.ActiveCfg = Debug|Win32
{676E091A-4E6E-429B-91EE-0399C46060C6}.Debug.Build.0 = Debug|Win32
{676E091A-4E6E-429B-91EE-0399C46060C6}.DebugPython.ActiveCfg = Debug|Win32
{676E091A-4E6E-429B-91EE-0399C46060C6}.DebugPython.Build.0 = Debug|Win32
{676E091A-4E6E-429B-91EE-0399C46060C6}.Release.ActiveCfg = Release|Win32
{676E091A-4E6E-429B-91EE-0399C46060C6}.Release.Build.0 = Release|Win32
{5408B0E6-0B50-4E12-921A-8F1B3E483716}.Debug.ActiveCfg = Debug|Win32
{5408B0E6-0B50-4E12-921A-8F1B3E483716}.Debug.Build.0 = Debug|Win32
{5408B0E6-0B50-4E12-921A-8F1B3E483716}.DebugPython.ActiveCfg = Debug|Win32
{5408B0E6-0B50-4E12-921A-8F1B3E483716}.DebugPython.Build.0 = Debug|Win32
{5408B0E6-0B50-4E12-921A-8F1B3E483716}.Release.ActiveCfg = Release|Win32
{5408B0E6-0B50-4E12-921A-8F1B3E483716}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection