Updatecppdocs (#3039)
* Updated CMakeLists.txx * Updated all examples, extended some. * Added info about highlighting atoms. * Added info about annotation to python getting started. * Minor tweaks. * Minor tweaks. Can only examine the rst in GitHub. * Minor tweaks. Can only examine the rst in GitHub. * get doctests working * update an example image * Include the GettingStartedInC++ doc in the standard docs build * move the C++ docs after the python docs * update backwards incompatible changes doc Co-authored-by: David Cosgrove <david@cozchemix.co.uk> Co-authored-by: greg landrum <greg.landrum@gmail.com>
@@ -8,6 +8,24 @@ generally include changes in results that arise due to bug fixes; we try to call
|
||||
those out in the release notes. The release notes, in general, contain a more
|
||||
comprehensive version of this list.
|
||||
|
||||
## Release 2020.03
|
||||
|
||||
### Use of chirality with `@=` in PostgreSQL cartridge
|
||||
Searches for equal molecules (i.e. `mol1 @= mol2`) in the PostgreSQL cartridge
|
||||
now use the `do_chiral_sss` option. So if `do_chiral_sss` is false (the
|
||||
default), the molecules `CC(F)Cl` and `C[C@H](F)Cl` will be considered to be
|
||||
equal. Previously these molecules were always considered to be different.
|
||||
|
||||
### Handling of empty/invalid files in MolSuppliers
|
||||
Attempting to create a MolSupplier from a filename pointing to an empty file, a
|
||||
file that does not exist or sometihing that is not a standard file (i.e.
|
||||
something like a directory) now generates an exception.
|
||||
|
||||
### Renaming a cmake option
|
||||
The cmake option `RDK_OPTIMIZE_NATIVE` has been renamed to `RDK_OPTIMIZE_POPCNT`
|
||||
|
||||
|
||||
|
||||
## Release 2019.09
|
||||
|
||||
### Updated van der Waals radii
|
||||
|
||||
@@ -2,36 +2,44 @@ cmake_minimum_required( VERSION 2.8.9 )
|
||||
|
||||
project(RDKitSV)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}")
|
||||
set(RDBASE $ENV{RDBASE})
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${RDBASE}/Code/cmake/Modules")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
|
||||
# note that if you haven't installed/built the toolkit with CoordGen, you'll
|
||||
# have problems with this.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -DRDK_BUILD_COORDGEN_SUPPORT=ON" )
|
||||
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_MULTITHREADED OFF)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
find_package( Boost COMPONENTS iostreams filesystem system)
|
||||
|
||||
find_package( Cairo REQUIRED )
|
||||
|
||||
find_package( MyRDKit COMPONENTS ChemReactions FileParsers SmilesParse Depictor RDGeometryLib
|
||||
RDGeneral SubstructMatch Subgraphs MolDraw2D GraphMol DistGeometry DistGeomHelpers
|
||||
MolAlign Optimizer ForceField ForceFieldHelpers Alignment
|
||||
ForceField MolTransforms EigenSolvers )
|
||||
# specify where CMake can find the RDKit libraries
|
||||
include_directories ( ${RDBASE}/Code ${CAIRO_INCLUDE_DIRS} )
|
||||
link_directories ( ${RDBASE}/lib )
|
||||
|
||||
set(RDKit_LIBS RDKitChemReactions RDKitFileParsers RDKitSmilesParse RDKitDepictor
|
||||
RDKitRDGeometryLib RDKitRDGeneral RDKitSubstructMatch RDKitSubgraphs
|
||||
RDKitMolDraw2D RDKitGraphMol RDKitDistGeometry RDKitDistGeomHelpers
|
||||
RDKitMolAlign RDKitOptimizer RDKitForceField RDKitForceFieldHelpers
|
||||
RDKitAlignment RDKitForceField RDKitMolTransforms RDKitEigenSolvers )
|
||||
|
||||
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR})
|
||||
|
||||
find_package (Threads)
|
||||
set(RDKit_THREAD_LIBS Threads::Threads)
|
||||
|
||||
set( LIBS ${RDKIT_LIBRARIES} Boost::iostreams ${RDKit_THREAD_LIBS} z )
|
||||
set( LIBS ${RDKIT_LIBRARIES} Boost::iostreams ${RDKit_THREAD_LIBS}
|
||||
${CAIRO_LIBRARIES} z )
|
||||
|
||||
include_directories(${RDKIT_INCLUDE_DIR})
|
||||
foreach( exnum RANGE 1 16 )
|
||||
foreach( exnum RANGE 1 17 )
|
||||
message( "Example : ${exnum}" )
|
||||
set( exe "example${exnum}" )
|
||||
set( src "${exe}.cpp" )
|
||||
add_executable( ${exe} ${src} )
|
||||
target_link_libraries( ${exe} ${LIBS} )
|
||||
target_link_libraries( ${exe} ${LIBS} ${RDKit_LIBS})
|
||||
endforeach( exnum )
|
||||
|
||||
# add_executable( test_example test_example.cpp )
|
||||
|
||||
@@ -9,22 +9,27 @@
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMol *mol1 = RDKit::SmilesToMol( "Cc1ccccc1" );
|
||||
std::cout << "Number of atoms " << mol1->getNumAtoms() << std::endl;
|
||||
|
||||
using namespace RDKit;
|
||||
auto mol = "C[C@H](F)c1ccc(C#N)cc1"_smiles;
|
||||
std::cout << "Number of atoms : " << mol->getNumAtoms() << std::endl;
|
||||
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
file_root += "/Docs/Book";
|
||||
|
||||
std::string mol_file = file_root + "/data/input.mol";
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::MolFileToMol( mol_file ) );
|
||||
std::shared_ptr<ROMol> mol2( RDKit::MolFileToMol( mol_file ) );
|
||||
|
||||
try {
|
||||
RDKit::ROMOL_SPTR mol3( RDKit::SmilesToMol( "CO(C)C" ) );
|
||||
std::shared_ptr<ROMol> mol3( RDKit::SmilesToMol( "CO(C)C" ) );
|
||||
} catch( RDKit::MolSanitizeException &e ) {
|
||||
// std::cout << e.what() << std::endl;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
try {
|
||||
RDKit::ROMOL_SPTR mol4( RDKit::SmilesToMol( "c1cc1" ) );
|
||||
std::unique_ptr<ROMol> mol4( RDKit::SmilesToMol( "c1cc1" ) );
|
||||
} catch( RDKit::MolSanitizeException &e ) {
|
||||
// std::cout << e.what() << std::endl;
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,27 +9,34 @@
|
||||
#include <GraphMol/Depictor/RDDepictor.h>
|
||||
#include <GraphMol/Substruct/SubstructMatch.h>
|
||||
|
||||
using namespace RDKit;
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::RWMOL_SPTR mol( new RDKit::RWMol( *RDKit::SmilesToMol( "c1nccc2n1ccc2" ) ) );
|
||||
|
||||
auto mol = "c1nccc2n1ccc2"_smiles;
|
||||
RDDepict::compute2DCoords( *mol );
|
||||
|
||||
RDDepict::compute2DCoords( *mol , static_cast<RDGeom::INT_POINT2D_MAP *>( 0 ) ,
|
||||
true );
|
||||
#ifdef RDK_BUILD_COORDGEN_SUPPORT
|
||||
RDDepict::preferCoordGen = true;
|
||||
#else
|
||||
std::cout << "CoordGen support not available" << std::endl;
|
||||
#endif
|
||||
|
||||
RDKit::ROMOL_SPTR templ( RDKit::SmilesToMol( "c1nccc2n1ccc2" ) );
|
||||
RDDepict::compute2DCoords( *mol , nullptr , true );
|
||||
|
||||
std::shared_ptr<RDKit::ROMol> templ( RDKit::SmilesToMol( "c1nccc2n1ccc2" ) );
|
||||
RDDepict::compute2DCoords( *templ );
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "c1cccc2ncn3cccc3c21" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "c1cccc2ncn3cccc3c21" ) );
|
||||
|
||||
RDKit::MatchVectType matchVect;
|
||||
if( RDKit::SubstructMatch( *mol1 , *templ , matchVect ) ) {
|
||||
MatchVectType matchVect;
|
||||
if(SubstructMatch( *mol1 , *templ , matchVect )) {
|
||||
RDKit::Conformer &conf = templ->getConformer();
|
||||
RDGeom::INT_POINT2D_MAP coordMap;
|
||||
for( RDKit::MatchVectType::const_iterator mv = matchVect.begin() ;
|
||||
mv != matchVect.end() ; ++mv ) {
|
||||
RDGeom::Point3D pt3 = conf.getAtomPos( mv->first );
|
||||
for(auto mv: matchVect) {
|
||||
RDGeom::Point3D pt3 = conf.getAtomPos( mv.first );
|
||||
RDGeom::Point2D pt2( pt3.x , pt3.y );
|
||||
coordMap[mv->second] = pt2;
|
||||
coordMap[mv.second] = pt2;
|
||||
}
|
||||
RDDepict::compute2DCoords( *mol1 , &coordMap );
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
#include <GraphMol/SmilesParse/SmilesParse.h>
|
||||
|
||||
int main(int main, char **argv) {
|
||||
RDKit::ROMOL_SPTR mol(RDKit::SmilesToMol("C1CCC1OC"));
|
||||
RDKit::ROMOL_SPTR mol1(RDKit::MolOps::addHs(*mol));
|
||||
RDKit::ROMOL_SPTR mol2(RDKit::MolOps::addHs(*mol));
|
||||
std::shared_ptr<RDKit::ROMol> mol(RDKit::SmilesToMol("C1CCC1OC"));
|
||||
std::shared_ptr<RDKit::ROMol> mol1(RDKit::MolOps::addHs(*mol));
|
||||
std::shared_ptr<RDKit::ROMol> mol2(RDKit::MolOps::addHs(*mol));
|
||||
// Original distance geometry embedding
|
||||
RDKit::DGeomHelpers::EmbedMolecule(*mol1, 0, 1234);
|
||||
RDKit::UFF::UFFOptimizeMolecule(*mol1);
|
||||
@@ -40,7 +40,6 @@ int main(int main, char **argv) {
|
||||
|
||||
std::vector<double> rms_list;
|
||||
std::vector<unsigned int> m2cids(mol2_cids.begin(), mol2_cids.end());
|
||||
RDKit::MolAlign::alignMolConformers(
|
||||
*mol2, static_cast<const std::vector<unsigned int> *>(0), &m2cids,
|
||||
static_cast<const RDNumeric::DoubleVector *>(0), false, 50, &rms_list);
|
||||
RDKit::MolAlign::alignMolConformers( *mol2, nullptr, &m2cids, nullptr,
|
||||
false, 50, &rms_list);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "c1ccncc1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "c1ccncc1" ) );
|
||||
std::string pickle;
|
||||
RDKit::MolPickler::pickleMol( *mol1 , pickle );
|
||||
RDKit::ROMol mol2;
|
||||
@@ -29,8 +29,11 @@ int main( int argc , char **argv ) {
|
||||
std::ofstream pickle_ostream( pkl_name.c_str() , std::ios_base::binary );
|
||||
int write_cnt = 0;
|
||||
while( !suppl.atEnd() ) {
|
||||
RDKit::ROMOL_SPTR mol( suppl.next() );
|
||||
RDKit::MolPickler::pickleMol( *mol , pickle_ostream );
|
||||
std::shared_ptr<RDKit::ROMol> mol( suppl.next() );
|
||||
// write all props (including _Name) to the pickle. Default is not to:
|
||||
// RDKit::MolPickler::pickleMol( *mol , pickle_ostream);
|
||||
// RDKit::MolPickler::pickleMol( *mol , pickle_ostream, RDKit::PicklerOps::NoProps);
|
||||
RDKit::MolPickler::pickleMol( *mol , pickle_ostream, RDKit::PicklerOps::AllProps );
|
||||
++write_cnt;
|
||||
}
|
||||
pickle_ostream.close();
|
||||
@@ -46,6 +49,14 @@ int main( int argc , char **argv ) {
|
||||
} catch( RDKit::MolPicklerException &e ) {
|
||||
break;
|
||||
}
|
||||
if(!read_cnt) {
|
||||
try {
|
||||
std::cout << "Read mol of name : "
|
||||
<< mol3.getProp<std::string>("_Name") << std::endl;
|
||||
} catch(KeyErrorException &e) {
|
||||
std::cerr << "Pickle read error : " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
++read_cnt;
|
||||
}
|
||||
pickle_istream.close();
|
||||
|
||||
@@ -5,32 +5,72 @@
|
||||
#include <GraphMol/GraphMol.h>
|
||||
#include <GraphMol/Depictor/RDDepictor.h>
|
||||
#include <GraphMol/FileParsers/FileParsers.h>
|
||||
#include <GraphMol/SmilesParse/SmilesParse.h>
|
||||
#include <GraphMol/MolDraw2D/MolDraw2DSVG.h>
|
||||
#ifdef RDK_BUILD_CAIRO_SUPPORT
|
||||
#include <GraphMol/MolDraw2D/MolDraw2DCairo.h>
|
||||
#endif
|
||||
|
||||
using namespace RDKit;
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
file_root += "/Docs/Book";
|
||||
|
||||
std::string sdf_file = file_root + "/data/cdk2.sdf";
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::MolFileToMol( sdf_file ) );
|
||||
std::shared_ptr<ROMol> mol1( MolFileToMol( sdf_file ) );
|
||||
RDDepict::compute2DCoords( *mol1 );
|
||||
std::string svg_file = file_root + "/data/cdk_mol1.svg";
|
||||
std::ofstream outs( svg_file.c_str() );
|
||||
RDKit::MolDraw2DSVG svg_drawer(300, 300, outs);
|
||||
MolDraw2DSVG svg_drawer(300, 300, outs);
|
||||
svg_drawer.drawMolecule( *mol1 );
|
||||
svg_drawer.finishDrawing();
|
||||
outs.close();
|
||||
|
||||
#ifdef RDK_BUILD_CAIRO_SUPPORT
|
||||
RDKit::MolDraw2DCairo cairo_drawer(300, 300);
|
||||
MolDraw2DCairo cairo_drawer(300, 300);
|
||||
cairo_drawer.drawMolecule(*mol1);
|
||||
cairo_drawer.finishDrawing();
|
||||
std::string png_file = file_root + "/data/cdk_mol1.png";
|
||||
cairo_drawer.writeDrawingText( png_file );
|
||||
#endif
|
||||
|
||||
|
||||
// drawing multiple molecules to a grid
|
||||
{
|
||||
std::string base_smi("c1ccccc1");
|
||||
std::vector<std::string> extras = {"F", "Cl", "Br", "OC", "C(=O)O"};
|
||||
std::vector<ROMol *> mols;
|
||||
for(auto extra: extras) {
|
||||
mols.push_back(SmilesToMol(base_smi + extra));
|
||||
}
|
||||
MolDraw2DSVG drawer(750, 400, 250, 200);
|
||||
drawer.drawMolecules(mols);
|
||||
drawer.finishDrawing();
|
||||
std::ofstream grids(file_root + "/data/example_13_grid.svg");
|
||||
grids << drawer.getDrawingText();
|
||||
grids.flush();
|
||||
grids.close();
|
||||
|
||||
for(auto mol: mols) {
|
||||
delete mol;
|
||||
}
|
||||
}
|
||||
|
||||
// adding annotation to the molecule
|
||||
{
|
||||
auto m1 = "Cl[C@H](F)NC\\C=C\\C"_smiles;
|
||||
MolDraw2DSVG drawer(250, 200);
|
||||
m1->getAtomWithIdx(2)->setProp(common_properties::atomNote, "foo");
|
||||
m1->getBondWithIdx(0)->setProp(common_properties::bondNote, "bar");
|
||||
drawer.drawOptions().addAtomIndices = true;
|
||||
drawer.drawOptions().addStereoAnnotation = true;
|
||||
drawer.drawMolecule(*m1);
|
||||
drawer.finishDrawing();
|
||||
std::string text = drawer.getDrawingText();
|
||||
std::ofstream outs(file_root + "/images/example_13_note.svg");
|
||||
outs << text;
|
||||
outs.flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "c1ccccc1O" ) );
|
||||
RDKit::RWMOL_SPTR patt( RDKit::SmartsToMol( "ccO" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "c1ccccc1O" ) );
|
||||
std::shared_ptr<RDKit::RWMol> patt( RDKit::SmartsToMol( "ccO" ) );
|
||||
RDKit::MatchVectType res;
|
||||
if( RDKit::SubstructMatch( *mol1 , *patt , res ) ) {
|
||||
std::cout << "Pattern matched molecule : " << std::endl;
|
||||
@@ -39,44 +39,44 @@ int main( int argc , char **argv ) {
|
||||
|
||||
std::string sdf_file = file_root + "/data/actives_5ht3.sdf";
|
||||
RDKit::SDMolSupplier mol_supplier( sdf_file , true );
|
||||
RDKit::RWMOL_SPTR patt1( RDKit::SmartsToMol( "c[NH1]" ) );
|
||||
std::vector<RDKit::ROMOL_SPTR> matches;
|
||||
std::shared_ptr<RDKit::RWMol> patt1( RDKit::SmartsToMol( "c[NH1]" ) );
|
||||
std::vector<std::shared_ptr<RDKit::ROMol>> matches;
|
||||
while( !mol_supplier.atEnd() ) {
|
||||
RDKit::ROMOL_SPTR mol3( mol_supplier.next() );
|
||||
std::shared_ptr<RDKit::ROMol> mol3( mol_supplier.next() );
|
||||
if( mol3 && RDKit::SubstructMatch( *mol3 , *patt1 , res ) ) {
|
||||
matches.push_back( mol3 );
|
||||
}
|
||||
}
|
||||
std::cout << "There were " << matches.size() << " hits in the file." << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol4( RDKit::SmilesToMol( "C1=CC=CC=C1OC" ) );
|
||||
RDKit::RWMOL_SPTR smi_mol1( RDKit::SmilesToMol( "CO" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol4( RDKit::SmilesToMol( "C1=CC=CC=C1OC" ) );
|
||||
std::shared_ptr<RDKit::RWMol> smi_mol1( RDKit::SmilesToMol( "CO" ) );
|
||||
if( RDKit::SubstructMatch( *mol4 , *smi_mol1 , res ) ) {
|
||||
std::cout << "SMILES match" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not SMILES match" << std::endl;
|
||||
}
|
||||
RDKit::RWMOL_SPTR smt_mol1( RDKit::SmartsToMol( "CO" ) );
|
||||
std::shared_ptr<RDKit::RWMol> smt_mol1( RDKit::SmartsToMol( "CO" ) );
|
||||
if( RDKit::SubstructMatch( *mol4 , *smt_mol1 , res ) ) {
|
||||
std::cout << "SMARTS match" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not SMARTS match" << std::endl;
|
||||
}
|
||||
|
||||
RDKit::RWMOL_SPTR smi_mol2( RDKit::SmilesToMol( "COC" ) );
|
||||
std::shared_ptr<RDKit::RWMol> smi_mol2( RDKit::SmilesToMol( "COC" ) );
|
||||
if( RDKit::SubstructMatch( *mol4 , *smi_mol2 , res ) ) {
|
||||
std::cout << "SMILES match" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not SMILES match" << std::endl;
|
||||
}
|
||||
RDKit::RWMOL_SPTR smt_mol2( RDKit::SmartsToMol( "COC" ) );
|
||||
std::shared_ptr<RDKit::RWMol> smt_mol2( RDKit::SmartsToMol( "COC" ) );
|
||||
if( RDKit::SubstructMatch( *mol4 , *smt_mol2 , res ) ) {
|
||||
std::cout << "SMARTS match" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not SMARTS match" << std::endl;
|
||||
}
|
||||
// Needs aromatic C
|
||||
RDKit::RWMOL_SPTR smt_mol3( RDKit::SmartsToMol( "COc" ) );
|
||||
std::shared_ptr<RDKit::RWMol> smt_mol3( RDKit::SmartsToMol( "COc" ) );
|
||||
if( RDKit::SubstructMatch( *mol4 , *smt_mol3 , res ) ) {
|
||||
std::cout << "SMARTS match" << std::endl;
|
||||
} else {
|
||||
|
||||
@@ -8,21 +8,21 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "CC[C@H](F)Cl" ) );
|
||||
RDKit::RWMOL_SPTR patt1( RDKit::SmartsToMol( "C[C@H](F)Cl" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "CC[C@H](F)Cl" ) );
|
||||
std::shared_ptr<RDKit::RWMol> patt1( RDKit::SmartsToMol( "C[C@H](F)Cl" ) );
|
||||
RDKit::MatchVectType res;
|
||||
if( RDKit::SubstructMatch( *mol1 , *patt1 , res ) ) {
|
||||
std::cout << "SMARTS 1 match" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not SMARTS 1 match" << std::endl;
|
||||
}
|
||||
RDKit::RWMOL_SPTR patt2( RDKit::SmartsToMol( "C[C@@H](F)Cl" ) );
|
||||
std::shared_ptr<RDKit::RWMol> patt2( RDKit::SmartsToMol( "C[C@@H](F)Cl" ) );
|
||||
if( RDKit::SubstructMatch( *mol1 , *patt2 , res ) ) {
|
||||
std::cout << "SMARTS 2 match" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not SMARTS 2 match" << std::endl;
|
||||
}
|
||||
RDKit::RWMOL_SPTR patt3( RDKit::SmartsToMol( "CC(F)Cl" ) );
|
||||
std::shared_ptr<RDKit::RWMol> patt3( RDKit::SmartsToMol( "CC(F)Cl" ) );
|
||||
if( RDKit::SubstructMatch( *mol1 , *patt3 , res ) ) {
|
||||
std::cout << "SMARTS 3 match" << std::endl;
|
||||
} else {
|
||||
@@ -45,14 +45,14 @@ int main( int argc , char **argv ) {
|
||||
std::cout << "Not SMARTS 3 chiral match" << std::endl;
|
||||
}
|
||||
|
||||
RDKit::RWMOL_SPTR mol2( RDKit::SmilesToMol( "CC(F)Cl" ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol2( RDKit::SmilesToMol( "CC(F)Cl" ) );
|
||||
if( RDKit::SubstructMatch( *mol1 , *mol2 , res , true , true ) ) {
|
||||
std::cout << "Chiral mol, non-chiral query : match" << std::endl;
|
||||
} else {
|
||||
std::cout << "Chiral mol, non-chiral query : NO match" << std::endl;
|
||||
}
|
||||
|
||||
RDKit::RWMOL_SPTR patt5( RDKit::SmilesToMol( "C[C@H](F)Cl" ) );
|
||||
std::shared_ptr<RDKit::RWMol> patt5( RDKit::SmilesToMol( "C[C@H](F)Cl" ) );
|
||||
if( RDKit::SubstructMatch( *mol2 , *patt5 , res , true , true ) ) {
|
||||
std::cout << "Non-chiral mol, chiral query : match" << std::endl;
|
||||
} else {
|
||||
|
||||
@@ -10,28 +10,24 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::RWMOL_SPTR patt1( RDKit::SmartsToMol( "[cH0:1][c:2]([cH0])!@[CX3!r:3]=[NX2!r:4]" ) );
|
||||
std::shared_ptr<RDKit::RWMol> patt1( RDKit::SmartsToMol( "[cH0:1][c:2]([cH0])!@[CX3!r:3]=[NX2!r:4]" ) );
|
||||
std::map<int,unsigned int> ind_map;
|
||||
RDKit::ROMol::VERTEX_ITER it , end;
|
||||
boost::tie( it , end ) = patt1->getVertices();
|
||||
while( it != end ) {
|
||||
const RDKit::Atom *atom = (*patt1)[*it].get();
|
||||
for(auto atom: patt1->atoms()) {
|
||||
int map_num = atom->getAtomMapNum();
|
||||
if( map_num ) {
|
||||
ind_map[map_num-1] = atom->getIdx();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
std::vector<unsigned int> map_list;
|
||||
for( std::map<int,unsigned int>::iterator i = ind_map.begin() ; i != ind_map.end() ; ++i ) {
|
||||
map_list.push_back( i->second );
|
||||
for(auto im: ind_map) {
|
||||
map_list.push_back(im.second);
|
||||
}
|
||||
for( size_t i = 0 , is = map_list.size() ; i < is ; ++i ) {
|
||||
std::cout << map_list[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "Cc1cccc(C)c1C(C)=NC" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "Cc1cccc(C)c1C(C)=NC" ) );
|
||||
std::vector<RDKit::MatchVectType> hits_vect;
|
||||
if( RDKit::SubstructMatch( *mol1 , *patt1 , hits_vect ) ) {
|
||||
for( size_t i = 0 ; i < hits_vect.size() ; ++i ) {
|
||||
|
||||
126
Docs/Book/C++Examples/example17.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// Depictions with highlights - example17.cpp
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <GraphMol/GraphMol.h>
|
||||
#include <GraphMol/Depictor/RDDepictor.h>
|
||||
#include <GraphMol/FileParsers/FileParsers.h>
|
||||
#include <GraphMol/SmilesParse/SmilesParse.h>
|
||||
#include <GraphMol/MolDraw2D/MolDraw2DSVG.h>
|
||||
|
||||
using namespace RDKit;
|
||||
|
||||
std::vector<int> get_all_hit_atoms(ROMol &mol, const std::string &smt) {
|
||||
std::vector<int> hit_atoms;
|
||||
RWMol *query = SmartsToMol(smt);
|
||||
std::vector<MatchVectType> hits_vect;
|
||||
SubstructMatch(mol, *query, hits_vect);
|
||||
for( size_t i = 0 ; i < hits_vect.size() ; ++i ) {
|
||||
for( size_t j = 0 ; j < hits_vect[i].size() ; ++j ) {
|
||||
hit_atoms.emplace_back(hits_vect[i][j].second);
|
||||
}
|
||||
}
|
||||
delete query;
|
||||
return hit_atoms;
|
||||
}
|
||||
|
||||
std::vector<int> get_all_hit_bonds(ROMol &mol, const std::vector<int> &hit_atoms) {
|
||||
std::vector<int> hit_bonds;
|
||||
for(int i: hit_atoms) {
|
||||
for(int j: hit_atoms) {
|
||||
if(i > j) {
|
||||
Bond *bnd = mol.getBondBetweenAtoms(i, j);
|
||||
if(bnd) {
|
||||
hit_bonds.emplace_back(bnd->getIdx());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hit_bonds;
|
||||
}
|
||||
|
||||
void update_colour_map(const std::vector<int> &ats, DrawColour col,
|
||||
std::map<int, std::vector<DrawColour> > &ha_map) {
|
||||
for(auto h: ats) {
|
||||
auto ex = ha_map.find(h);
|
||||
if(ex == ha_map.end()) {
|
||||
std::vector<DrawColour> cvec(1, col);
|
||||
ha_map.insert(make_pair(h, cvec));
|
||||
} else {
|
||||
if(ex->second.end() == find(ex->second.begin(), ex->second.end(), col)) {
|
||||
ex->second.emplace_back(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
file_root += "/Docs/Book/images/";
|
||||
|
||||
auto mol = "CO[C@@H](O)C1=C(O[C@H](F)Cl)C(C#N)=C1ONNC[NH3+]"_smiles;
|
||||
std::vector<int> hit1_atoms = get_all_hit_atoms(*mol, "CONN");
|
||||
std::vector<int> hit1_bonds = get_all_hit_bonds(*mol, hit1_atoms);
|
||||
{
|
||||
// all atoms and bonds highlighted the same colour
|
||||
std::ofstream outs(file_root + "example_17_1.svg");
|
||||
MolDraw2DSVG drawer(500, 500, outs);
|
||||
drawer.drawMolecule(*mol, &hit1_atoms, &hit1_bonds);
|
||||
drawer.finishDrawing();
|
||||
outs.flush();
|
||||
}
|
||||
{
|
||||
// individual colours for each highlight
|
||||
std::ofstream outs(file_root + "example_17_2.svg");
|
||||
MolDraw2DSVG drawer(500, 500, outs);
|
||||
std::map<int, DrawColour> atom_cols;
|
||||
atom_cols.insert(std::make_pair(13, DrawColour(1.0, 0.0, 0.0)));
|
||||
atom_cols.insert(std::make_pair(14, DrawColour(0.0, 1.0, 0.0)));
|
||||
atom_cols.insert(std::make_pair(15, DrawColour(0.0, 0.0, 1.0)));
|
||||
atom_cols.insert(std::make_pair(16, DrawColour(1.0, 0.55, 0.0)));
|
||||
std::map<int, DrawColour> bond_cols;
|
||||
bond_cols.insert(std::make_pair(13, DrawColour(0.8, 0.8, 0.0)));
|
||||
bond_cols.insert(std::make_pair(14, DrawColour(0.0, 1.0, 1.0)));
|
||||
bond_cols.insert(std::make_pair(15, DrawColour(1.0, 0.0, 1.0)));
|
||||
drawer.drawMolecule(*mol, &hit1_atoms, &hit1_bonds, &atom_cols, &bond_cols);
|
||||
drawer.finishDrawing();
|
||||
outs.flush();
|
||||
}
|
||||
|
||||
std::vector<int> hit2_atoms = get_all_hit_atoms(*mol, "N#CC~CO");
|
||||
std::vector<int> hit2_bonds = get_all_hit_bonds(*mol, hit2_atoms);
|
||||
std::vector<int> hit3_atoms = get_all_hit_atoms(*mol, "C=CON");
|
||||
std::vector<int> hit3_bonds = get_all_hit_bonds(*mol, hit3_atoms);
|
||||
std::vector<int> hit4_atoms = get_all_hit_atoms(*mol, "CONNCN");
|
||||
std::vector<int> hit4_bonds = get_all_hit_bonds(*mol, hit4_atoms);
|
||||
|
||||
std::map<int, std::vector<DrawColour> > ha_map;
|
||||
update_colour_map(hit1_atoms, DrawColour(1.0, 0.0, 0.0), ha_map);
|
||||
update_colour_map(hit2_atoms, DrawColour(0.0, 1.0, 0.0), ha_map);
|
||||
update_colour_map(hit3_atoms, DrawColour(0.0, 0.0, 1.0), ha_map);
|
||||
update_colour_map(hit4_atoms, DrawColour(1.0, 0.55, 0.0), ha_map);
|
||||
std::map<int, std::vector<DrawColour> > hb_map;
|
||||
update_colour_map(hit1_bonds, DrawColour(1.0, 0.0, 0.0), hb_map);
|
||||
update_colour_map(hit2_bonds, DrawColour(0.0, 1.0, 0.0), hb_map);
|
||||
update_colour_map(hit3_bonds, DrawColour(0.0, 0.0, 1.0), hb_map);
|
||||
update_colour_map(hit4_bonds, DrawColour(1.0, 0.55, 0.0), hb_map);
|
||||
std::map<int, double> h_rads;
|
||||
std::map<int, int> h_lw_mult;
|
||||
|
||||
{
|
||||
// atoms and bonds can have multiple highlights
|
||||
std::ofstream outs(file_root + "example_17_3.svg");
|
||||
MolDraw2DSVG drawer(500, 500, outs);
|
||||
drawer.drawOptions().fillHighlights = false;
|
||||
drawer.drawOptions().continuousHighlight = true;
|
||||
drawer.drawOptions().atomHighlightsAreCircles = true;
|
||||
drawer.drawMoleculeWithHighlights(*mol, "Test 1", ha_map,
|
||||
hb_map, h_rads, h_lw_mult);
|
||||
drawer.finishDrawing();
|
||||
outs.flush();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ int main( int argc , char **argv ) {
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
file_root += "/Docs/Book";
|
||||
|
||||
RDKit::ROMOL_SPTR mol;
|
||||
std::unique_ptr<RDKit::ROMol> mol;
|
||||
std::string sdf_file = file_root + "/data/5ht3ligs.sdf";
|
||||
bool takeOwnership = true;
|
||||
RDKit::SDMolSupplier mol_supplier( sdf_file , takeOwnership );
|
||||
@@ -27,7 +27,7 @@ int main( int argc , char **argv ) {
|
||||
}
|
||||
|
||||
for( int i = int( mol_supplier.length() ) - 1 ; i >= 0 ; --i ) {
|
||||
RDKit::ROMOL_SPTR mol( mol_supplier[i] );
|
||||
std::unique_ptr<RDKit::ROMol> mol( mol_supplier[i] );
|
||||
if( mol ) {
|
||||
std::cout << mol->getProp<std::string>( "_Name" ) << " has " << mol->getNumAtoms() << " atoms." << std::endl;
|
||||
}
|
||||
|
||||
@@ -13,21 +13,21 @@ int main(int argc, char **argv) {
|
||||
std::string file_root = getenv("RDBASE");
|
||||
file_root += "/Docs/Book";
|
||||
std::string mol_file = file_root + "/data/chiral.mol";
|
||||
RDKit::ROMOL_SPTR mol(RDKit::MolFileToMol(mol_file));
|
||||
std::shared_ptr<RDKit::ROMol> mol(RDKit::MolFileToMol(mol_file));
|
||||
std::cout << RDKit::MolToSmiles(*mol, true) << std::endl;
|
||||
// 2nd parameter doIsomericSmiles defaults to true
|
||||
std::cout << RDKit::MolToSmiles(*mol, false) << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol1(RDKit::SmilesToMol("C1=CC=CN=C1"));
|
||||
std::shared_ptr<RDKit::ROMol> mol1(RDKit::SmilesToMol("C1=CC=CN=C1"));
|
||||
std::cout << RDKit::MolToSmiles(*mol1) << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol2(RDKit::SmilesToMol("c1cccnc1"));
|
||||
std::shared_ptr<RDKit::ROMol> mol2(RDKit::SmilesToMol("c1cccnc1"));
|
||||
std::cout << RDKit::MolToSmiles(*mol2) << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol3(RDKit::SmilesToMol("n1ccccc1"));
|
||||
std::shared_ptr<RDKit::ROMol> mol3(RDKit::SmilesToMol("n1ccccc1"));
|
||||
std::cout << RDKit::MolToSmiles(*mol3) << std::endl;
|
||||
|
||||
RDKit::RWMOL_SPTR mol4(new RDKit::RWMol(*mol));
|
||||
std::shared_ptr<RDKit::RWMol> mol4(new RDKit::RWMol(*mol));
|
||||
RDKit::MolOps::Kekulize(*mol4);
|
||||
std::cout << RDKit::MolToSmiles(*mol4) << std::endl;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
std::cout << RDKit::MolToMolBlock( *mol1 ) << std::endl;
|
||||
|
||||
mol1->setProp( "_Name" , "cyclobutane" );
|
||||
@@ -24,26 +24,26 @@ int main( int argc , char **argv ) {
|
||||
RDDepict::compute2DCoords( *mol1 );
|
||||
std::cout << RDKit::MolToMolBlock( *mol1 ) << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
mol2->setProp( "_Name" , "cyclobutane3D" );
|
||||
RDKit::DGeomHelpers::EmbedMolecule( *mol2 );
|
||||
RDKit::MMFF::MMFFOptimizeMolecule( *mol2 , 1000 , "MMFF94s" );
|
||||
std::cout << RDKit::MolToMolBlock( *mol2 ) << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol3( RDKit::MolOps::addHs( *mol2 ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol3( RDKit::MolOps::addHs( *mol2 ) );
|
||||
RDKit::MMFF::MMFFOptimizeMolecule( *mol3 , 1000 , "MMFF94s" );
|
||||
std::cout << RDKit::MolToMolBlock( *mol3 ) << std::endl;
|
||||
|
||||
RDKit::RWMOL_SPTR mol4( new RDKit::RWMol( *mol3 ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol4( new RDKit::RWMol( *mol3 ) );
|
||||
RDKit::MolOps::addHs( *mol4 );
|
||||
|
||||
RDKit::ROMOL_SPTR mol3sp( RDKit::MolOps::addHs( *mol2 ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol3sp( RDKit::MolOps::addHs( *mol2 ) );
|
||||
mol3sp->setProp( "_Name" , "cyclobutaneSP" );
|
||||
RDKit::MMFF::MMFFOptimizeMolecule( *mol3sp , 1000 , "MMFF94s" );
|
||||
std::cout << RDKit::MolToMolBlock( *mol3sp ) << std::endl;
|
||||
|
||||
|
||||
RDKit::ROMOL_SPTR mol5( RDKit::MolOps::removeHs( *mol3 ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol5( RDKit::MolOps::removeHs( *mol3 ) );
|
||||
RDKit::MolOps::removeHs( *mol4 );
|
||||
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
|
||||
@@ -24,9 +24,9 @@ int main( int argc , char **argv ) {
|
||||
std::string sdf_file = file_root + "/data/5ht3ligs.sdf";
|
||||
bool takeOwnership = true;
|
||||
RDKit::SDMolSupplier mol_supplier( sdf_file , takeOwnership );
|
||||
std::vector<RDKit::ROMOL_SPTR> mols;
|
||||
std::vector<std::shared_ptr<RDKit::ROMol>> mols;
|
||||
while( !mol_supplier.atEnd() ) {
|
||||
RDKit::ROMOL_SPTR mol( mol_supplier.next() );
|
||||
std::shared_ptr<RDKit::ROMol> mol( mol_supplier.next() );
|
||||
if( mol ) {
|
||||
mols.push_back( mol );
|
||||
}
|
||||
@@ -43,8 +43,8 @@ int main( int argc , char **argv ) {
|
||||
// to delete the std::ostringstream.
|
||||
takeOwnership = false;
|
||||
boost::shared_ptr<RDKit::SDWriter> sdf_writer( new RDKit::SDWriter( &oss , takeOwnership ) );
|
||||
for( std::vector<RDKit::ROMOL_SPTR>::iterator it = mols.begin() ; it != mols.end() ; ++it ) {
|
||||
sdf_writer->write( *(*it) );
|
||||
for( auto mol: mols ) {
|
||||
sdf_writer->write( *mol );
|
||||
}
|
||||
|
||||
std::cout << oss.str() << std::endl;
|
||||
|
||||
@@ -9,34 +9,21 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMOL_SPTR mol( RDKit::SmilesToMol( "C1OC1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::SmilesToMol( "C1OC1" ) );
|
||||
|
||||
RDKit::ROMol::VERTEX_ITER it , end;
|
||||
boost::tie( it , end ) = mol->getVertices();
|
||||
while( it != end ) {
|
||||
const RDKit::Atom *atom = (*mol)[*it].get();
|
||||
for(auto atom: mol->atoms()) {
|
||||
std::cout << atom->getAtomicNum() << " ";
|
||||
++it;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
for( RDKit::ROMol::AtomIterator ai = mol->beginAtoms() ; ai != mol->endAtoms() ; ++ai) {
|
||||
std::cout << (*ai)->getAtomicNum() << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
for( unsigned int i = 0 , is = mol->getNumAtoms() ; i < is ; ++i ) {
|
||||
for( unsigned int i = 0; i < mol->getNumAtoms() ; ++i ) {
|
||||
const RDKit::Atom *atom = mol->getAtomWithIdx( i );
|
||||
std::cout << atom->getAtomicNum() << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
RDKit::ROMol::EDGE_ITER bond_it , bond_end;
|
||||
boost::tie( bond_it , bond_end ) = mol->getEdges();
|
||||
while( bond_it != bond_end ) {
|
||||
const RDKit::Bond *bond = (*mol)[*bond_it].get();
|
||||
for(auto bond: mol->bonds()) {
|
||||
std::cout << bond->getBondType() << " ";
|
||||
++bond_it;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
@@ -46,7 +33,7 @@ int main( int argc , char **argv ) {
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::SmilesToMol( "C1OC1Cl" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::SmilesToMol( "C1OC1Cl" ) );
|
||||
const RDKit::Bond *bond = mol2->getBondBetweenAtoms( 0 , 1 );
|
||||
std::cout << bond->getBeginAtomIdx() << " to "
|
||||
<< bond->getBeginAtomIdx() << " is "
|
||||
@@ -56,12 +43,11 @@ int main( int argc , char **argv ) {
|
||||
}
|
||||
|
||||
const RDKit::Atom *atom = mol2->getAtomWithIdx( 2 );
|
||||
RDKit::ROMol::ADJ_ITER nbr , end_nbr;
|
||||
boost::tie( nbr , end_nbr ) = mol2->getAtomNeighbors( atom );
|
||||
while( nbr != end_nbr ) {
|
||||
const RDKit::Atom *nbr_atom = (*mol2)[*nbr].get();
|
||||
std::cout << nbr_atom->getIdx() << " : " << nbr_atom->getAtomicNum() << std::endl;
|
||||
++nbr;
|
||||
for(const auto &nbri: make_iterator_range(mol->getAtomBonds(atom))) {
|
||||
const RDKit::Bond *bond = (*mol)[nbri];
|
||||
unsigned int nbr_idx = bond->getOtherAtomIdx(atom->getIdx());
|
||||
int nbr_atnum = bond->getOtherAtom(atom)->getAtomicNum();
|
||||
std::cout << nbr_idx << " : " << nbr_atnum << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMOL_SPTR mol( RDKit::SmilesToMol( "OC1C2C1CC2" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::SmilesToMol( "OC1C2C1CC2" ) );
|
||||
|
||||
if( !mol->getRingInfo()->isInitialized() ) {
|
||||
RDKit::MolOps::findSSSR( *mol );
|
||||
}
|
||||
for( unsigned int i = 0 , is = mol->getNumAtoms() ; i < is ; ++i ) {
|
||||
for( unsigned int i = 0; i < mol->getNumAtoms() ; ++i ) {
|
||||
const RDKit::Atom *atom = mol->getAtomWithIdx( i );
|
||||
std::cout << mol->getRingInfo()->numAtomRings( atom->getIdx() ) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
for( unsigned int i = 0 , is = mol->getNumBonds() ; i < is ; ++i ) {
|
||||
for( unsigned int i = 0; i < mol->getNumBonds() ; ++i ) {
|
||||
const RDKit::Bond *bond = mol->getBondWithIdx( i );
|
||||
std::cout << mol->getRingInfo()->numBondRings( bond->getIdx() ) << " ";
|
||||
}
|
||||
@@ -45,9 +45,9 @@ int main( int argc , char **argv ) {
|
||||
RDKit::VECT_INT_VECT rings;
|
||||
RDKit::MolOps::symmetrizeSSSR( *mol , rings );
|
||||
std::cout << "Number of symmetric SSSR rings : " << rings.size() << std::endl;
|
||||
for( RDKit::VECT_INT_VECT::iterator it1 = rings.begin() , it1_end = rings.end() ; it1 != it1_end ; ++it1 ) {
|
||||
for( RDKit::INT_VECT::iterator it2 = it1->begin() , it2_end = it1->end() ; it2 != it2_end ; ++it2 ) {
|
||||
std::cout << *it2 << " ";
|
||||
for( auto ring: rings ) {
|
||||
for( auto ringat: ring ) {
|
||||
std::cout << ringat << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "CCO" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "CCO" ) );
|
||||
std::cout << "Number of atoms : " << mol1->getNumAtoms() << std::endl;
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::MolOps::addHs( *mol1 ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::MolOps::addHs( *mol1 ) );
|
||||
std::cout << "Number of atoms : " << mol2->getNumAtoms() << std::endl;
|
||||
|
||||
RDKit::RWMOL_SPTR mol3( new RDKit::RWMol( *mol2 ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol3( new RDKit::RWMol( *mol2 ) );
|
||||
RDKit::MolOps::removeHs( *mol3 );
|
||||
std::cout << "Number of atoms : " << mol3->getNumAtoms() << std::endl;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
int main( int argc , char **argv ) {
|
||||
|
||||
RDKit::RWMOL_SPTR mol( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::cout << "Order : " << mol->getBondWithIdx( 0 )->getBondType() << std::endl;
|
||||
std::cout << "Aromatic : " << mol->getBondWithIdx( 0 )->getIsAromatic() << std::endl;
|
||||
|
||||
@@ -17,11 +17,11 @@ int main( int argc , char **argv ) {
|
||||
std::cout << "After default Kekulize : Order : " << mol->getBondWithIdx( 0 )->getBondType() << std::endl;
|
||||
std::cout << "After default Kekulize : Aromatic : " << mol->getBondWithIdx( 0 )->getIsAromatic() << std::endl;
|
||||
|
||||
RDKit::RWMOL_SPTR mol1( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol1( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
RDKit::MolOps::Kekulize( *mol1 , false );
|
||||
std::cout << "After Kekulize, markAtomsBonds false : Aromatic : " << mol1->getBondWithIdx( 0 )->getIsAromatic() << std::endl;
|
||||
|
||||
RDKit::RWMOL_SPTR mol2( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol2( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
RDKit::MolOps::Kekulize( *mol2 , true );
|
||||
std::cout << "After Kekulize, markAtomsBonds true : Aromatic : " << mol2->getBondWithIdx( 0 )->getIsAromatic() << std::endl;
|
||||
|
||||
|
||||
@@ -20,14 +20,14 @@ experiment and change settings to get this working. You will
|
||||
need a reasonably modern C++ compiler. On linux systems this will most
|
||||
likely be the GNU compiler gcc, although it could be Clang. On Macs,
|
||||
the opposite is true, and on Windows machines it will probably be
|
||||
Visual C++. At present, RDKit uses a relatively old-fashioned (or, as
|
||||
Greg prefers, "maximally backwards compatible") dialect
|
||||
of C++, so gcc version 3.4 or higher is adequate, but this is due to
|
||||
change within the next year.
|
||||
Visual C++. As of the March 2018 release, RDKit uses modern C++,
|
||||
which currently means up to C++14. You will probably need to tell
|
||||
your compiler that you want to use the new features. On Clang and
|
||||
gcc, use the flag `-std=c++14`.
|
||||
|
||||
C++ programs generally have quite a lot of extra verbiage in them
|
||||
compared to, for example, python scripts, that is similar or identical
|
||||
in all programs. The would produce extraneous clutter in the example
|
||||
in all programs. This would produce extraneous clutter in the example
|
||||
code in this document. Because of this, only the minimum code to
|
||||
exemplify the point being made is shown in the text. Full programs for
|
||||
all the examples (generally with multiple examples in the same
|
||||
@@ -43,7 +43,7 @@ and libraries in all executables this will result in slower compile
|
||||
times, especially
|
||||
if you are doing static linking. When linking to the static (.a)
|
||||
libraries rather than the shared-object (.so) ones, the order the
|
||||
libraries appear in linking list can be important. See the
|
||||
libraries appear in the linking list can be important. See the
|
||||
CMakeLists.txt file in C++Examples directory for a good order. In
|
||||
this case, the same library list is used for all examples, so some
|
||||
will be unnecessary for some of the programs. The first 3 programs
|
||||
@@ -81,7 +81,8 @@ Another consideration is the completeness of the API. A lot of the
|
||||
higher level functionality in RDKit is developed in Python, and
|
||||
back-porting to C++ occurs on a demand-driven basis. There are
|
||||
therefore examples of quite useful functionality, such as computing
|
||||
the RMS differences between conformers that are not available in C++.
|
||||
the RMS differences between conformers (GetConformerRMSMatrix) that
|
||||
are not available in C++.
|
||||
Of course, if this affects you you can always implement the C++ version
|
||||
and submit a Pull Request. Indeed, the RMS calculation is on its way.
|
||||
|
||||
@@ -93,29 +94,32 @@ difficult to track down
|
||||
([Valgrind is your friend!](http://valgrind.org)) and may be a
|
||||
surprise to people used to managed-memory languages like python and
|
||||
java. In RDKit, many of the functions return pointers to molecules
|
||||
and accept such pointers as arguments. The
|
||||
[Boost libraries](http://boost.org) provide tools such as shared
|
||||
(`boost::shared_ptr`) and scoped (`boost::scoped_ptr`) pointers that
|
||||
can be very helpful in preventing memory leaks. If an object is
|
||||
created and a pointer to it is stored in a shared pointer, for
|
||||
example, then when the shared pointer goes out of scope, the object
|
||||
and accept such pointers as arguments. Modern C++ provides tools such
|
||||
as shared
|
||||
(`std::shared_ptr`) and single use (`std::unique_ptr`) (collectively
|
||||
'smart') pointers that can be very helpful in preventing memory leaks.
|
||||
If an object is created and a pointer to it is stored in either of
|
||||
these, then when the smart pointer goes out of scope, the object
|
||||
is automatically deleted. Otherwise, the shared pointer is used
|
||||
exactly as one would use an ordinary pointer. To save some typing,
|
||||
RDKit has a number of typedefs for shared pointers to its objects,
|
||||
defined in the relevant header files. Two particularly useful ones
|
||||
are `RDKit::ROMOL_SPTR` and `RDKit::RWMOL_SPTR`, for `RDKit::ROMol`
|
||||
and `RDKit::RWMol` objects respectively.
|
||||
exactly as one would use an ordinary pointer. The unique_ptr is a bit
|
||||
different in that it cannot be copied (you will get a compiler message
|
||||
such as
|
||||
```
|
||||
/Users/david/Tmp/rdkit-my-fork/Docs/Book/C++Examples/example1.cpp:16:8: error: call to
|
||||
implicitly-deleted copy constructor of 'std::__1::unique_ptr<RDKit::RWMol,
|
||||
std::__1::default_delete<RDKit::RWMol> >'
|
||||
auto m2 = m1;
|
||||
^ ~~
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2494:3: note:
|
||||
copy constructor is implicitly deleted because 'unique_ptr<RDKit::RWMol,
|
||||
std::__1::default_delete<RDKit::RWMol> >' has a user-declared move constructor
|
||||
unique_ptr(unique_ptr&& __u) noexcept
|
||||
```
|
||||
if you try to) although they can be `move`d. There is
|
||||
some anecdotal evidence that VisualStudio doesn't cope with vectors of
|
||||
vectors of `unique_ptr` (`std::vector<std::vector<unique_ptr<RWMol>>>`,
|
||||
for example).
|
||||
|
||||
Something that isn't just relevant to the RDKit, but worth noting
|
||||
generally, is that the new C++
|
||||
standard also has `shared_ptr` and `scoped_ptr` in the standard
|
||||
namespace (essentially, they've adopted the boost libraries). As I
|
||||
discovered the hard way, if you put `using namespace boost` and `using
|
||||
namespace std` at the top of your source file (and let's face it, who
|
||||
doesn't?), and use the unqualified name `shared_ptr` in your
|
||||
code, then, when you start using C++11, you'll have to go all through
|
||||
your code explicitly stating whether you're using `std::shared_ptr` or
|
||||
`boost::shared_ptr`. Worth getting in the habit now!
|
||||
|
||||
## The Molecule Classes
|
||||
|
||||
@@ -141,15 +145,16 @@ to cover most use cases:
|
||||
Individual molecules can be constructed using a variety of approaches [(example1)](./C++Examples/example1.cpp):
|
||||
|
||||
```c++
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
file_root += "/Docs/Book";
|
||||
RDKit::ROMol *mol1 = RDKit::SmilesToMol( "Cc1ccccc1" );
|
||||
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
file_root += "/Docs/Book";
|
||||
|
||||
std::string mol_file = file_root + "/data/input.mol";
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::MolFileToMol( mol_file ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::MolFileToMol( mol_file ) );
|
||||
std::cout << *mol2 << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol3( RDKit::SmilesToMol( "Cc1cccc" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol3( RDKit::SmilesToMol( "Cc1cccc" ) );
|
||||
```
|
||||
|
||||
All these return a pointer to an ROMol on success, or NULL on
|
||||
@@ -159,6 +164,20 @@ document, the molecules, apart from mol1, are wrapped in shared
|
||||
pointers so that the objects are deleted as soon as the shared pointer
|
||||
goes out of scope.
|
||||
|
||||
There is also an overload of `operator""` as a convenient shorthand
|
||||
method of parsing a SMILES string into a molecule
|
||||
[(example1)](./C++Examples/example1.cpp):
|
||||
```
|
||||
using namespace RDKit;
|
||||
auto mol = "C[C@H](F)c1ccc(C#N)cc1"_smiles;"
|
||||
```
|
||||
Normally the keyword `auto` means you don't need to know the return
|
||||
type of the function - the compiler works it out and away you go.
|
||||
However, in this case it is useful to know that you get a
|
||||
`std::unique_ptr<RWMol>`, which tells you it can't be copied, the
|
||||
molecule can be edited, the memory won't leak and you need to use the
|
||||
`->` operator to use functions on the RWMol object.
|
||||
|
||||
If the molecule can't be sanitized after SMILES parsing, an
|
||||
`RDKit::MolSanitizeException` (derived
|
||||
from `std::exception`) is thrown, and an attempt is made to provide
|
||||
@@ -166,7 +185,7 @@ sensible error messages [(example1)](./C++Examples/example1.cpp):
|
||||
|
||||
```c++
|
||||
try {
|
||||
RDKit::ROMOL_SPTR mol( RDKit::SmilesToMol( "CO(C)C" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::SmilesToMol( "CO(C)C" ) );
|
||||
} catch( RDKit::MolSanitizeException &e ) {
|
||||
// empty catch
|
||||
}
|
||||
@@ -177,7 +196,7 @@ is greater than permitted` and [(example1)](./C++Examples/example1.cpp)
|
||||
|
||||
```c++
|
||||
try {
|
||||
RDKit::ROMOL_SPTR mol( RDKit::SmilesToMol( "c1cc1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::SmilesToMol( "c1cc1" ) );
|
||||
} catch( RDKit::MolSanitizeException &e ) {
|
||||
// empty catch
|
||||
}
|
||||
@@ -192,7 +211,7 @@ Groups of molecules are read using a Supplier (for example, an
|
||||
[(example2)](./C++Examples/example2.cpp):
|
||||
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol;
|
||||
std::unqiue_ptr<RDKit::ROMol> mol;
|
||||
std::string file_root = getenv( "RDBASE" );
|
||||
file_root += "/Docs/Book";
|
||||
std::string sdf_file = file_root + "/data/5ht3ligs.sdf";
|
||||
@@ -205,10 +224,10 @@ while( !mol_supplier.atEnd() ) {
|
||||
```
|
||||
gives
|
||||
```
|
||||
20
|
||||
24
|
||||
24
|
||||
26
|
||||
mol-295 has 20 atoms.
|
||||
mol-54 has 24 atoms.
|
||||
mol-15 has 24 atoms.
|
||||
mol-732 has 26 atoms.
|
||||
```
|
||||
|
||||
The supplier can be treated as a random-access object [(example2)](./C++Examples/example2.cpp):
|
||||
@@ -216,7 +235,7 @@ The supplier can be treated as a random-access object [(example2)](./C++Examples
|
||||
```c++
|
||||
RDKit::SDMolSupplier mol_supplier( "data/5ht3ligs.sdf" , takeOwnership );
|
||||
for( int i = int( mol_supplier.length() ) - 1 ; i >= 0 ; --i ) {
|
||||
RDKit::ROMOL_SPTR mol( mol_supplier[i] );
|
||||
unique_ptr<RDKit::ROMol> mol( mol_supplier[i] );
|
||||
if( mol ) {
|
||||
std::cout << mol->getProp<std::string>( "_Name" ) << " has "
|
||||
<< mol->getNumAtoms() << " atoms." << std::endl;
|
||||
@@ -239,7 +258,7 @@ bool takeOwnership = true;
|
||||
RDKit::SDMolSupplier *mol_supplier = new RDKit::SDMolSupplier( "data/5ht3ligs.sdf" , takeOwnership );
|
||||
|
||||
for( int i = int( mol_supplier->length() ) - 1 ; i >= 0 ; --i ) {
|
||||
RDKit::ROMOL_SPTR mol( (*mol_supplier)[i] );
|
||||
std::unique_ptr<RDKit::ROMol> mol( (*mol_supplier)[i] );
|
||||
if( !mol ) {
|
||||
continue;
|
||||
}
|
||||
@@ -292,7 +311,7 @@ For example, for SMILES [(example3)](./C++Examples/example3.cpp):
|
||||
#include <GraphMol/SmilesParse/SmilesWrite.h>
|
||||
.
|
||||
.
|
||||
RDKit::ROMOL_SPTR mol( RDKit::MolFromMolFile( "data/chiral.mol" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::MolFromMolFile( "data/chiral.mol" ) );
|
||||
std::cout << RDKit::MolToSmiles( *mol ) << std::endl;
|
||||
```
|
||||
gives
|
||||
@@ -315,13 +334,13 @@ the same no matter how a particular molecule is input. For example
|
||||
[(example3)](./C++Examples/example3.cpp)
|
||||
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "C1=CC=CN=C1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "C1=CC=CN=C1" ) );
|
||||
std::cout << RDKit::MolToSmiles( *mol1 ) << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::SmilesToMol( "c1cccnc1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::SmilesToMol( "c1cccnc1" ) );
|
||||
std::cout << RDKit::MolToSmiles( *mol2 ) << std::endl;
|
||||
|
||||
RDKit::ROMOL_SPTR mol3( RDKit::SmilesToMol( "n1ccccc1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol3( RDKit::SmilesToMol( "n1ccccc1" ) );
|
||||
std::cout << RDKit::MolToSmiles( *mol3 ) << std::endl;
|
||||
```
|
||||
|
||||
@@ -335,7 +354,7 @@ MolOps.h [(example3)](./C++Examples/example3.cpp):
|
||||
#include <GraphMol/MolOps.h>
|
||||
.
|
||||
.
|
||||
RDKit::RWMOL_SPTR mol4( new RDKit::RWMol( *mol ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol4( new RDKit::RWMol( *mol ) );
|
||||
RDKit::MolOps::Kekulize( *mol4 );
|
||||
std::cout << RDKit::MolToSmiles( *mol4, true, true ) << std::endl;
|
||||
```
|
||||
@@ -351,7 +370,7 @@ SMILES generation, but in the kekulization itself.
|
||||
MDL Mol blocks are also available [(example3)](./C++Examples/example3.cpp):
|
||||
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "C1=CC=CN=C1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "C1=CC=CN=C1" ) );
|
||||
std::cout << RDKit::MolToMolBlock( *mol1 ) << std::endl;
|
||||
```
|
||||
gives
|
||||
@@ -409,7 +428,7 @@ software, it's essential that the mol block have atomic coordinates.
|
||||
It's also convenient for many reasons, such as drawing the molecules.
|
||||
Generating a mol block for a molecule that does not have coordinates will, by
|
||||
default, automatically cause coordinates to be generated. These are not,
|
||||
however, stored with the molecule.
|
||||
however, added to the molecule, but re-generated each time.
|
||||
|
||||
You can either include 2D coordinates (i.e. a depiction), using the
|
||||
function in the RDDepict namespace and declared in RDDepictor.h
|
||||
@@ -419,7 +438,7 @@ function in the RDDepict namespace and declared in RDDepictor.h
|
||||
#include <GraphMol/Depictor/RDDepictor.h>
|
||||
.
|
||||
.
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
RDDepict::compute2DCoords( *mol1 );
|
||||
std::cout << RDKit::MolToMolBlock( *mol1 ) << std::endl;
|
||||
```
|
||||
@@ -447,7 +466,7 @@ Or you can add 3D coordinates by embedding the molecule [(example4)](./C++Exampl
|
||||
#include <GraphMol/ForceFieldHelpers/MMFF/MMFF.h>
|
||||
.
|
||||
.
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::SmilesToMol( "C1CCC1" ) );
|
||||
mol2->setProp( "_Name" , "cyclobutane3D" );
|
||||
RDKit::DGeomHelpers::EmbedMolecule( *mol2 );
|
||||
RDKit::MMFF::MMFFOptimizeMolecule( *mol2 , 1000 , "MMFF94s" );
|
||||
@@ -477,14 +496,14 @@ To get good 3D conformations, it's almost always a good idea to add
|
||||
hydrogens to the molecule first [(example4)](./C++Examples/example4.cpp):
|
||||
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol3( RDKit::MolOps::addHs( *mol2 ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol3( RDKit::MolOps::addHs( *mol2 ) );
|
||||
RDKit::MMFF::MMFFOptimizeMolecule( *mol3 , 1000 , "MMFF94s" );
|
||||
|
||||
RDKit::RWMOL_SPTR mol4( new RDKit::RWMol( *mol3 ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol4( new RDKit::RWMol( *mol3 ) );
|
||||
RDKit::MolOps::addHs( *mol4 );
|
||||
```
|
||||
|
||||
<a name="twoAddHs"></a>Note that there are 2 overloaded versions of
|
||||
Note that there are 2 overloaded versions of
|
||||
addHs. The first takes an
|
||||
ROMol and, because that can't be edited, returns a pointer to a new
|
||||
ROMol with the result. If you use this version be careful not to leak
|
||||
@@ -492,7 +511,7 @@ memory by not deleting mol2 when you are finished with it. The second
|
||||
takes an RWMol which it is able to modify in place. With shared
|
||||
pointers, memory leaks can be avoided [(example4)](./C++Examples/example4.cpp):
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol3sp( RDKit::MolOps::addHs( *mol2 ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol3sp( RDKit::MolOps::addHs( *mol2 ) );
|
||||
mol3sp->setProp( "_Name" , "cyclobutaneSP" );
|
||||
RDKit::MMFF::MMFFOptimizeMolecule( *mol3sp , 1000 , "MMFF94s" );
|
||||
```
|
||||
@@ -501,7 +520,7 @@ Once the optimisation is complete, the hydrogens can be removed
|
||||
again [(example4)](./C++Examples/example4.cpp):
|
||||
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol5( RDKit::MolOps::removeHs( *mol3 );
|
||||
std::shared_ptr<RDKit::ROMol> mol5( RDKit::MolOps::removeHs( *mol3 );
|
||||
RDKit::MolOps::removeHs( *mol4 );
|
||||
```
|
||||
|
||||
@@ -534,9 +553,9 @@ file_root += "/Docs/Book";
|
||||
std::string sdf_file = file_root + "/data/5ht3ligs.sdf";
|
||||
bool takeOwnership = true;
|
||||
RDKit::SDMolSupplier mol_supplier( sdf_file , takeOwnership );
|
||||
std::vector<RDKit::ROMOL_SPTR> mols;
|
||||
std::vector<std::shared_ptr<RDKit::ROMol>> mols;
|
||||
while( !mol_supplier.atEnd() ) {
|
||||
RDKit::ROMOL_SPTR mol( mol_supplier.next() );
|
||||
std::shared_ptr<RDKit::ROMol> mol( mol_supplier.next() );
|
||||
if( mol ) {
|
||||
mols.push_back( mol );
|
||||
}
|
||||
@@ -561,7 +580,7 @@ std::ostringstream oss;
|
||||
// to delete the std::ostringstream.
|
||||
takeOwnership = false;
|
||||
boost::shared_ptr<RDKit::SDWriter> sdf_writer( new RDKit::SDWriter( &oss , takeOwnership ) );
|
||||
for( std::vector<RDKit::ROMOL_SPTR>::iterator it = mols.begin() ; it != mols.end() ; ++it ) {
|
||||
for( auto mol: mols ) {
|
||||
sdf_writer->write( *(*it) );
|
||||
}
|
||||
std::cout << oss.str() << std::endl;
|
||||
@@ -574,59 +593,41 @@ of you with an interest in historical Cheminformatics).
|
||||
|
||||
### Looping over Atoms and Bonds
|
||||
|
||||
Once you have a molecule, it's relatively easy to loop over its atoms
|
||||
and bonds so long as you remember that an atom is a Vertex and a bond
|
||||
is an Edge and accept the odd syntax [(example6)](./C++Examples/example6.cpp):
|
||||
Since the adoption of c++11, looping over atoms and bonds has become
|
||||
extremely simple:
|
||||
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol( RDKit::SmilesToMol( "C1OC1" ) );
|
||||
RDKit::ROMol::VERTEX_ITER it , end;
|
||||
boost::tie( it , end ) = mol->getVertices();
|
||||
while( it != end ) {
|
||||
const RDKit::Atom *atom = (*mol)[*it].get();
|
||||
std::cout << atom->getAtomicNum() << std::endl;
|
||||
++it;
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::SmilesToMol( "C1OC1" ) );
|
||||
for(auto atom: mol->atoms()) {
|
||||
std::cout << atom->getAtomicNum() << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
```
|
||||
gives
|
||||
```
|
||||
6 8 6
|
||||
```
|
||||
As an alternative, there are AtomIterators and
|
||||
BondIterators[(example6)](./C++Examples/example6.cpp):
|
||||
```c++
|
||||
#include <GraphMol/AtomIterators.h>
|
||||
.
|
||||
.
|
||||
for( RDKit::ROMol::AtomIterator ai = mol->beginAtoms() ; ai != mol->endAtoms() ; ++ai) {
|
||||
std::cout << (*ai)->getAtomicNum() << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
```
|
||||
which is functionally equivalent to the above.
|
||||
Finally, there's a method that uses the fact that atoms and bonds
|
||||
As well as this, there are a method that uses the fact that atoms and bonds
|
||||
can be selected by index number
|
||||
[(example6)](./C++Examples/example6.cpp):
|
||||
```c++
|
||||
for( unsigned int i = 0 , is = mol->getNumAtoms() ; i < is ; ++i ) {
|
||||
const RDKit::Atom *atom = mol->getAtomWithIdx( i );
|
||||
std::cout << atom->getAtomicNum() << std::endl;
|
||||
for( unsigned int i = 0; i < mol->getNumAtoms() ; ++i ) {
|
||||
const RDKit::Atom *atom = mol->getAtomWithIdx( i );
|
||||
std::cout << atom->getAtomicNum() << " ";
|
||||
}
|
||||
```
|
||||
Likewise with bonds [(example6)](./C++Examples/example6.cpp):
|
||||
```c++
|
||||
RDKit::ROMol::EDGE_ITER bond_it , bond_end;
|
||||
boost::tie( bond_it , bond_end ) = mol->getEdges();
|
||||
while( bond_it != bond_end ) {
|
||||
const RDKit::Bond *bond = (*mol)[*bond_it].get();
|
||||
std::cout << bond->getBondType() << std::endl;
|
||||
++bond_it;
|
||||
for(auto bond: mol->bonds()) {
|
||||
std::cout << bond->getBondType() << " ";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
for( unsigned int i = 0 , is = mol->getNumBonds() ; i < is ; ++i ) {
|
||||
const RDKit::Bond *bond = mol->getBondWithIdx( i );
|
||||
std::cout << bond->getIsAromatic() << std::endl;
|
||||
const RDKit::Bond *bond = mol->getBondWithIdx( i );
|
||||
std::cout << bond->getIsAromatic() << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
```
|
||||
gives
|
||||
```
|
||||
@@ -637,7 +638,7 @@ gives
|
||||
A bond can be specified by the atoms at its ends, with
|
||||
a NULL pointer being returned if there isn't one [(example6)](./C++Examples/example6.cpp):
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::SmilesToMol( "C1OC1Cl" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::SmilesToMol( "C1OC1Cl" ) );
|
||||
const RDKit::Bond *bond = mol2->getBondBetweenAtoms( 0 , 1 );
|
||||
std::cout << bond->getBeginAtomIdx() << " to "
|
||||
<< bond->getBeginAtomIdx() << " is "
|
||||
@@ -647,17 +648,15 @@ if( !mol2->getBondBetweenAtoms( 0 , 3 ) ) {
|
||||
}
|
||||
```
|
||||
|
||||
The neighbours of an atom can also be extracted, but note that you
|
||||
need an ADJ\_ITER rather than a VERTEX\_ITER [(example6)](./C++Examples/example6.cpp):
|
||||
The neighbours of an atom can also be extracted [(example6)](./C++Examples/example6.cpp):
|
||||
```c++
|
||||
const RDKit::Atom *atom = mol2->getAtomWithIdx( 2 );
|
||||
RDKit::ROMol::ADJ_ITER nbr , end_nbr;
|
||||
boost::tie( nbr , end_nbr ) = mol2->getAtomNeighbors( atom );
|
||||
while( nbr != end_nbr ) {
|
||||
const RDKit::Atom *nbr_atom = (*mol2)[*nbr].get();
|
||||
std::cout << nbr_atom->getIdx() << " : " << nbr_atom->getAtomicNum() << std::endl;
|
||||
++nbr;
|
||||
}
|
||||
const RDKit::Atom *atom = mol2->getAtomWithIdx( 2 );
|
||||
for(const auto &nbri: make_iterator_range(mol->getAtomBonds(atom))) {
|
||||
const RDKit::Bond *bond = (*mol)[nbri];
|
||||
unsigned int nbr_idx = bond->getOtherAtomIdx(atom->getIdx());
|
||||
int nbr_atnum = bond->getOtherAtom(atom)->getAtomicNum();
|
||||
std::cout << nbr_idx << " : " << nbr_atnum << std::endl;
|
||||
}
|
||||
```
|
||||
gives
|
||||
```
|
||||
@@ -665,6 +664,8 @@ gives
|
||||
3 : 17
|
||||
0 : 6
|
||||
```
|
||||
The `auto' keyword here is hiding the fact that `getBondBetweenAtoms`
|
||||
returns the index of the bond, an `unsigned int`.
|
||||
|
||||
### Ring Information
|
||||
|
||||
@@ -674,18 +675,18 @@ It is relatively easy to obtain ring information for atoms and bonds
|
||||
#include <GraphMol/MolOps.h>
|
||||
.
|
||||
.
|
||||
RDKit::ROMOL_SPTR mol( RDKit::SmilesToMol( "OC1C2C1CC2" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::SmilesToMol( "OC1C2C1CC2" ) );
|
||||
|
||||
if( !mol->getRingInfo()->isInitialized() ) {
|
||||
RDKit::MolOps::findSSSR( *mol );
|
||||
}
|
||||
for( unsigned int i = 0 , is = mol->getNumAtoms() ; i < is ; ++i ) {
|
||||
for( unsigned int i = 0; i < mol->getNumAtoms() ; ++i ) {
|
||||
const RDKit::Atom *atom = mol->getAtomWithIdx( i );
|
||||
std::cout << mol->getRingInfo()->numAtomRings( atom->getIdx() ) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
for( unsigned int i = 0 , is = mol->getNumBonds() ; i < is ; ++i ) {
|
||||
for( unsigned int i = 0; i < mol->getNumBonds() ; ++i ) {
|
||||
const RDKit::Bond *bond = mol->getBondWithIdx( i );
|
||||
std::cout << mol->getRingInfo()->numBondRings( bond->getIdx() ) << " ";
|
||||
}
|
||||
@@ -736,9 +737,9 @@ available [(example7)](./C++Examples/example7.cpp):
|
||||
RDKit::VECT_INT_VECT rings;
|
||||
RDKit::MolOps::symmetrizeSSSR( *mol , rings );
|
||||
std::cout << "Number of symmetric SSSR rings : " << rings.size() << std::endl;
|
||||
for( auto it1 = rings.begin() , it1_end = rings.end() ; it1 != it1_end ; ++it1 ) {
|
||||
for( auto it2 = it1->begin() , it2_end = it1->end() ; it2 != it2_end ; ++it2 ) {
|
||||
std::cout << *it2 << " ";
|
||||
for( auto ring: rings ) {
|
||||
for( auto ringat: ring ) {
|
||||
std::cout << ringat << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -772,9 +773,9 @@ when generating or optimizing the 3D geometry, the
|
||||
`RDKit::MolOps::addHs` function can be used
|
||||
[(example8)](./C++Examples/example8.cpp).
|
||||
```c++
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::SmilesToMol( "CCO" ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol1( RDKit::SmilesToMol( "CCO" ) );
|
||||
std::cout << "Number of atoms : " << mol1->getNumAtoms() << std::endl;
|
||||
RDKit::ROMOL_SPTR mol2( RDKit::MolOps::addHs( *mol1 ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol2( RDKit::MolOps::addHs( *mol1 ) );
|
||||
std::cout << "Number of atoms : " << mol2->getNumAtoms() << std::endl;
|
||||
```
|
||||
gives
|
||||
@@ -788,7 +789,7 @@ The Hs can be removed again using the `RDKit::MolOps::RemoveHs`
|
||||
function, which again has two forms
|
||||
[(example8)](./C++Examples/example8.cpp):
|
||||
```c++
|
||||
RDKit::RWMOL_SPTR mol3( new RDKit::RWMol( *mol2 ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol3( new RDKit::RWMol( *mol2 ) );
|
||||
RDKit::MolOps::removeHs( *mol3 );
|
||||
std::cout << "Number of atoms : " << mol3->getNumAtoms() << std::endl;
|
||||
```
|
||||
@@ -799,7 +800,7 @@ having aromatic bond types. This can be changed with the
|
||||
`RDKit::MolOps::Kekulize` function, which must be called with an RWMol
|
||||
[(example9)](./C++Examples/example9.cpp):
|
||||
```c++
|
||||
RDKit::RWMOL_SPTR mol( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::cout << "Order : " << mol->getBondWithIdx( 0 )->getBondType() << std::endl;
|
||||
std::cout << "Aromatic : " << mol->getBondWithIdx( 0 )->getIsAromatic() << std::endl;
|
||||
|
||||
@@ -822,11 +823,11 @@ on the atoms and bonds. **This is in contrast to the Python version of
|
||||
Kekulize, which preserves the flags by default.** The behaviour can be
|
||||
forced explicitly [(example9.cpp)](./C++Examples/example9.cpp):
|
||||
```c++
|
||||
RDKit::RWMOL_SPTR mol1( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol1( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
RDKit::MolOps::Kekulize( *mol1 , false );
|
||||
std::cout << "After Kekulize, markAtomsBonds false : Aromatic : " << mol1->getBondWithIdx( 0 )->getIsAromatic() << std::endl;
|
||||
|
||||
RDKit::RWMOL_SPTR mol2( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
std::shared_ptr<RDKit::RWMol> mol2( new RDKit::RWMol( *RDKit::SmilesToMol( "c1ccccc1" ) ) );
|
||||
RDKit::MolOps::Kekulize( *mol2 , true );
|
||||
std::cout << "After Kekulize, markAtomsBonds true : Aromatic : " << mol2->getBondWithIdx( 0 )->getIsAromatic() << std::endl;
|
||||
```
|
||||
@@ -852,17 +853,32 @@ once more.
|
||||
|
||||
### Working with 2D molecules: Generating Depictions
|
||||
|
||||
The RDKit has a library for generating depictions (sets of 2D
|
||||
coordinates) for molecules. This library, which is part of the
|
||||
The RDKit has 2 different methods for generating depictions (sets of 2D
|
||||
coordinates) for molecules. They are part of the
|
||||
RDDepict namespace, is accessed via the `RDDepict::Compute2DCoords`
|
||||
function [(example10.cpp)](./C++Examples/example10.cpp):
|
||||
```c++
|
||||
#include <GraphMol/Depictor/RDDepictor.h>
|
||||
.
|
||||
.
|
||||
RDKit::RWMOL_SPTR mol( new RDKit::RWMol( *RDKit::SmilesToMol( "c1nccc2n1ccc2" ) ) );
|
||||
std::shared_ptr<RDKit::RWMol>xs mol( new RDKit::RWMol( *RDKit::SmilesToMol( "c1nccc2n1ccc2" ) ) );
|
||||
RDDepict::compute2DCoords( *mol );
|
||||
```
|
||||
The default method is the original RDKit algorithm. The alternative
|
||||
is CoordGen, kindly contributed by Schrodinger. The latter is
|
||||
reckoned to be slower but better at congested structures and
|
||||
macrocycles. CoordGen isn't always built into the RDKit libraries, so
|
||||
it's a reasonable idea to use it conditionally
|
||||
[(example10.cpp)](./C++Examples/example10.cpp):
|
||||
```c++
|
||||
#ifdef RDK_BUILD_COORDGEN_SUPPORT
|
||||
RDDepict::preferCoordGen = true;
|
||||
#else
|
||||
std::cout << "CoordGen support not available" << std::endl;
|
||||
#endif
|
||||
```
|
||||
The [CMakeLists.txt](./C++Examples/CMakeLists.txt) with the examples
|
||||
defines `RDK_BUILD_COORDGEN_SUPPORT`.
|
||||
|
||||
The 2D conformation is constructed to minimize intramolecular clashes,
|
||||
i.e. to maximize the clarity of the drawing. Unlike the Python
|
||||
@@ -870,14 +886,9 @@ equivalent, the depiction is not placed in a canonical orientation by
|
||||
default. This can be forced by passing `true` as the third parameter
|
||||
[(example10.cpp)](./C++Examples/example10.cpp):
|
||||
```c++
|
||||
#include <Geometry/point.h>
|
||||
.
|
||||
.
|
||||
RDDepict::compute2DCoords( *mol , static_cast<RDGeom::INT_POINT2D_MAP *>( 0 ) , true );
|
||||
RDDepict::compute2DCoords( *mol , nullptr , true );
|
||||
```
|
||||
|
||||
The `point.h` must be included for the typedef that defines
|
||||
`INT_POINT2D_MAP`, of which more later.
|
||||
By default, all existing conformations are removed when the 2D
|
||||
coordinates are created. This can be changed by passing false as a
|
||||
4th parameter. The 2D coordinates are added as another conformation
|
||||
@@ -892,6 +903,7 @@ was included in late December 2016. If that is later than the version
|
||||
of RDKit you are using, then the effect can be achieved thus:
|
||||
[(example10.cpp)](./C++Examples/example10.cpp):
|
||||
```c++
|
||||
#include <Geometry/point.h>
|
||||
#include <GraphMol/Substruct/SubstructMatch.h>
|
||||
.
|
||||
.
|
||||
@@ -903,10 +915,10 @@ RDKit::MatchVectType matchVect;
|
||||
if( RDKit::SubstructMatch( *mol1 , *templ , matchVect ) ) {
|
||||
RDKit::Conformer &conf = templ->getConformer();
|
||||
RDGeom::INT_POINT2D_MAP coordMap;
|
||||
for( RDKit::MatchVectType::const_iterator mv = matchVect.begin() ; mv != matchVect.end() ; ++mv ) {
|
||||
RDGeom::Point3D pt3 = conf.getAtomPos( mv->first );
|
||||
for(auto mv: matchVect) {
|
||||
RDGeom::Point3D pt3 = conf.getAtomPos( mv.first );
|
||||
RDGeom::Point2D pt2( pt3.x , pt3.y );
|
||||
coordMap[mv->second] = pt2;
|
||||
coordMap[mv.second] = pt2;
|
||||
}
|
||||
RDDepict::compute2DCoords( *mol1 , &coordMap );
|
||||
}
|
||||
@@ -963,8 +975,8 @@ all the above verbiage makes it sound
|
||||
#include <GraphMol/ForceFieldHelpers/UFF/UFF.h>
|
||||
.
|
||||
.
|
||||
RDKit::ROMOL_SPTR mol( RDKit::SmilesToMol( "C1CCC1OC" ) );
|
||||
RDKit::ROMOL_SPTR mol1( RDKit::MolOps::addHs( *mol ) );
|
||||
std::shared_ptr<RDKit::ROMol> mol( RDKit::SmilesToMol( "C1CCC1OC" ) );
|
||||
std::shared_ptr<RDKit::ROMol>xs mol1( RDKit::MolOps::addHs( *mol ) );
|
||||
// Original distance geometry embedding
|
||||
RDKit::DGeomHelpers::EmbedMolecule( *mol1 , 0 , 1234 );
|
||||
RDKit::UFF::UFFOptimizeMolecule( *mol1 );
|
||||
@@ -1110,7 +1122,7 @@ std::ofstream pickle_ostream( pkl_name , std::ios_base::binary );
|
||||
int write_cnt = 0;
|
||||
while( !suppl.atEnd() ) {
|
||||
RDKit::ROMol *mol = suppl.next();
|
||||
RDKit::MolPickler::pickleMol( *mol , pickle_ostream );
|
||||
RDKit::MolPickler::pickleMol( *mol , pickle_ostream);
|
||||
delete mol;
|
||||
++write_cnt;
|
||||
}
|
||||
@@ -1132,9 +1144,12 @@ while( !pickle_istream.eof() ) {
|
||||
pickle_istream.close();
|
||||
std::cout << "Read " << read_cnt << " molecules." << std::endl;
|
||||
```
|
||||
However, currently the pickling process does not preserve and
|
||||
properties attached to the molecule, which included the molecule name
|
||||
(property "_Name"). This will change in the 2017.03 release.
|
||||
By default, the pickling process does not preserve any
|
||||
properties attached to the molecule, which includes the molecule name
|
||||
(property "_Name"). This can be forced:
|
||||
```c++
|
||||
RDKit::MolPickler::pickleMol( *mol , pickle_ostream, RDKit::PicklerOps::AllProps );
|
||||
```
|
||||
|
||||
### Drawing Molecules
|
||||
The RDKit has some built-in functionality for drawing molecules, found
|
||||
@@ -1144,7 +1159,9 @@ MolDraw2D which defines the interface and does the drawing, with
|
||||
concrete classes for drawing to SVG or PNG files and Qt and wx
|
||||
widgets. Only the SVG output is built by default, Cairo support
|
||||
requires the argument `-DRDK_BUILD_CAIRO_SUPPORT=ON` to cmake, and Qt
|
||||
support `-DRDK_BUILD_QT_SUPPORT=ON`. To create an SVG file:
|
||||
support `-DRDK_BUILD_QT_SUPPORT=ON`. Note that the Qt code hasn't been
|
||||
looked at in years, is not tested as part of the release cycle and so
|
||||
is not known to work. To create an SVG file:
|
||||
[(example13.cpp)](./C++Examples/example13.cpp):
|
||||
```c++
|
||||
#include <GraphMol/MolDraw2D/MolDraw2DSVG.h>
|
||||
@@ -1170,10 +1187,78 @@ cairo_drawer.drawMolecule(*mol1);
|
||||
cairo_drawer.finishDrawing();
|
||||
cairo_drawer.writeDrawingText("cdk_mol1.png");
|
||||
```
|
||||
The Python wrapper includes the function `Chem.MolsToGridImage`.
|
||||
There is, as yet, no equivalent in the C++ version although
|
||||
`test11DrawMolGrid` in `$RDBASE/Code/GraphMol/MolDraw2D/test1.cpp`
|
||||
shows that it can be achieved relatively simply.
|
||||
As in Python, you can draw a set of molecules to a grid
|
||||
[(example13.cpp)](./C++Examples/example13.cpp):
|
||||
```c++
|
||||
std::string base_smi("c1ccccc1");
|
||||
std::vector<std::string> extras = {"F", "Cl", "Br", "OC", "C(=O)O"};
|
||||
std::vector<ROMol *> mols;
|
||||
for(auto extra: extras) {
|
||||
mols.push_back(SmilesToMol(base_smi + extra));
|
||||
}
|
||||
MolDraw2DSVG drawer(750, 400, 250, 200);
|
||||
drawer.drawMolecules(mols);
|
||||
drawer.finishDrawing();
|
||||
std::ofstream grids(file_root + "/data/example_13_grid.svg");
|
||||
grids << drawer.getDrawingText();
|
||||
grids.flush();
|
||||
grids.close();
|
||||
```
|
||||
|
||||
Atoms in a molecule can be highlighted by drawing a coloured solid or
|
||||
open circle around them, and bonds likewise can have a coloured
|
||||
outline applied. An obvious use is to show atoms and bonds that have
|
||||
matched a substructure query
|
||||
[(example17.cpp)](./C++Examples/example17.cpp):
|
||||
```c++
|
||||
drawer.drawMolecule(*mol, &hit1_atoms, &hit1_bonds);
|
||||
```
|
||||
In the example above, `hit1_atoms` and `hit1_bonds` are vectors of
|
||||
ints giving the atoms and bonds to be highlighted. They will all be
|
||||
coloured the same default colour. It is possible to specify the
|
||||
colours for individual atoms and bonds:
|
||||
```c++
|
||||
std::map<int, DrawColour> atom_cols;
|
||||
atom_cols.insert(std::make_pair(13, DrawColour(1.0, 0.0, 0.0)));
|
||||
atom_cols.insert(std::make_pair(14, DrawColour(0.0, 1.0, 0.0)));
|
||||
atom_cols.insert(std::make_pair(15, DrawColour(0.0, 0.0, 1.0)));
|
||||
atom_cols.insert(std::make_pair(16, DrawColour(1.0, 0.55, 0.0)));
|
||||
std::map<int, DrawColour> bond_cols;
|
||||
bond_cols.insert(std::make_pair(13, DrawColour(0.8, 0.8, 0.0)));
|
||||
bond_cols.insert(std::make_pair(14, DrawColour(0.0, 1.0, 1.0)));
|
||||
bond_cols.insert(std::make_pair(15, DrawColour(1.0, 0.0, 1.0)));
|
||||
drawer.drawMolecule(*mol, &hit1_atoms, &hit1_bonds, &atom_cols, &bond_cols);
|
||||
```
|
||||
|
||||
Atoms and bonds can also be highlighted with multiple colours if they
|
||||
fall into multiple sets, for example if they are matched by more
|
||||
than 1 substructure pattern. This is too complicated to show in this
|
||||
simple introduction, but there is an example at the bottom of
|
||||
[example17.cpp](./C++Examples/example17.cpp).
|
||||
|
||||
As of version 2020.03, it is possible to add arbitrary small strings
|
||||
to annotate atoms and bonds in the drawing. The strings are added as
|
||||
properties `common_properties::atomNote` and
|
||||
`common_properties::bondNote` and they will be placed automatically
|
||||
close to the atom or bond in question in a manner intended to minimise
|
||||
their clash with the rest of the drawing. There are 3 flags in
|
||||
`MolDraw2DOptions` that will add stereo information (R/S to atoms, E/Z
|
||||
to bonds) and atom and bond sequence numbers
|
||||
[(example13.cpp)](./C++Examples/example13.cpp):
|
||||
```c++
|
||||
auto m1 = "Cl[C@H](F)NC\\C=C\\C"_smiles;
|
||||
MolDraw2DSVG drawer(250, 200);
|
||||
m1->getAtomWithIdx(2)->setProp(common_properties::atomNote, "foo");
|
||||
m1->getBondWithIdx(0)->setProp(common_properties::bondNote, "bar");
|
||||
drawer.drawOptions().addAtomIndices = true;
|
||||
drawer.drawOptions().addStereoAnnotation = true;
|
||||
drawer.drawMolecule(*m1);
|
||||
drawer.finishDrawing();
|
||||
std::string text = drawer.getDrawingText();
|
||||
std::ofstream outs(file_root + "/data/example_13_note.svg");
|
||||
outs << text;
|
||||
outs.flush();
|
||||
```
|
||||
|
||||
### Substructure Searching
|
||||
|
||||
@@ -1401,19 +1486,15 @@ number property that we can easily extract:
|
||||
```c++
|
||||
RDKit::RWMol *patt1 = RDKit::SmartsToMol( "[cH0:1][c:2]([cH0])!@[CX3!r:3]=[NX2!r:4]" );
|
||||
std::map<int,unsigned int> ind_map;
|
||||
RDKit::ROMol::VERTEX_ITER it , end;
|
||||
boost::tie( it , end ) = patt1->getVertices();
|
||||
while( it != end ) {
|
||||
const RDKit::Atom *atom = (*patt1)[*it].get();
|
||||
for(auto atom: patt1->atoms()) {
|
||||
int map_num = atom->getAtomMapNum();
|
||||
if( map_num ) {
|
||||
ind_map[map_num-1] = atom->getIdx();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
std::vector<unsigned int> map_list;
|
||||
for( std::map<int,unsigned int>::iterator i = ind_map.begin() ; i != ind_map.end() ; ++i ) {
|
||||
map_list.push_back( i->second );
|
||||
for(auto im: ind_map) {
|
||||
map_list.push_back(im.second);
|
||||
}
|
||||
for( size_t i = 0 , is = map_list.size() ; i < is ; ++i ) {
|
||||
std::cout << map_list[i] << " ";
|
||||
|
||||
@@ -834,7 +834,87 @@ The result looks like this:
|
||||
|
||||
.. image:: images/cdk2_molgrid_aligned.png
|
||||
|
||||
Atoms in a molecule can be highlighted by drawing a coloured solid or
|
||||
open circle around them, and bonds likewise can have a coloured
|
||||
outline applied. An obvious use is to show atoms and bonds that have
|
||||
matched a substructure query
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> from rdkit.Chem.Draw import rdMolDraw2D
|
||||
>>> smi = 'c1cc(F)ccc1Cl'
|
||||
>>> mol = Chem.MolFromSmiles(smi)
|
||||
>>> patt = Chem.MolFromSmarts('ClccccF')
|
||||
>>> hit_ats = list(mol.GetSubstructMatch(patt))
|
||||
>>> hit_bonds = []
|
||||
>>> for bond in patt.GetBonds():
|
||||
... aid1 = hit_ats[bond.GetBeginAtomIdx()]
|
||||
... aid2 = hit_ats[bond.GetEndAtomIdx()]
|
||||
... hit_bonds.append(mol.GetBondBetweenAtoms(aid1,aid2).GetIdx())
|
||||
>>> d = rdMolDraw2D.MolDraw2DSVG(500, 500) # or MolDraw2DCairo to get PNGs
|
||||
>>> rdMolDraw2D.PrepareAndDrawMolecule(d, mol, highlightAtoms=hit_ats,
|
||||
... highlightBonds=hit_bonds)
|
||||
|
||||
will produce:
|
||||
|
||||
.. image:: images/atom_highlights_1.png
|
||||
|
||||
It is possible to specify the colours for individual atoms and bonds:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> colours = [(0.8,0.0,0.8),(0.8,0.8,0),(0,0.8,0.8),(0,0,0.8)]
|
||||
>>> atom_cols = {}
|
||||
>>> for i, at in enumerate(hit_ats):
|
||||
... atom_cols[at] = colours[i%4]
|
||||
>>> bond_cols = {}
|
||||
>>> for i, bd in enumerate(hit_bonds):
|
||||
... bond_cols[bd] = colours[3 - i%4]
|
||||
>>>
|
||||
>>> d = rdMolDraw2D.MolDraw2DCairo(500, 500)
|
||||
>>> rdMolDraw2D.PrepareAndDrawMolecule(d, mol, highlightAtoms=hit_ats,
|
||||
... highlightAtomColors=atom_cols,
|
||||
... highlightBonds=hit_bonds,
|
||||
... highlightBondColors=bond_cols)
|
||||
|
||||
to give:
|
||||
|
||||
.. image:: images/atom_highlights_2.png
|
||||
|
||||
Atoms and bonds can also be highlighted with multiple colours if they
|
||||
fall into multiple sets, for example if they are matched by more
|
||||
than 1 substructure pattern. This is too complicated to show in this
|
||||
simple introduction, but there is an example in
|
||||
data/test_multi_colours.py, which produces the somewhat garish
|
||||
|
||||
.. image:: images/atom_highlights_3.png
|
||||
|
||||
As of version 2020.03, it is possible to add arbitrary small strings
|
||||
to annotate atoms and bonds in the drawing. The strings are added as
|
||||
properties 'atomNote' and
|
||||
'bondNote' and they will be placed automatically
|
||||
close to the atom or bond in question in a manner intended to minimise
|
||||
their clash with the rest of the drawing. For convenience, here are 3
|
||||
flags in
|
||||
`MolDraw2DOptions` that will add stereo information (R/S to atoms, E/Z
|
||||
to bonds) and atom and bond sequence numbers.
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> mol = Chem.MolFromSmiles('Cl[C@H](F)NC\C=C\C')
|
||||
>>> d = rdMolDraw2D.MolDraw2DCairo(250, 200) # or MolDraw2DSVG to get SVGs
|
||||
>>> mol.GetAtomWithIdx(2).SetProp('atomNote', 'foo')
|
||||
>>> mol.GetBondWithIdx(0).SetProp('bondNote', 'bar')
|
||||
>>> d.drawOptions().addStereoAnnotation = True
|
||||
>>> d.drawOptions().addAtomIndices = True
|
||||
>>> d.DrawMolecule(mol)
|
||||
>>> d.FinishDrawing()
|
||||
>>> with open('atom_annotation_1.png', 'wb') as f: # doctest: +SKIP
|
||||
... f.write(d.GetDrawingText())
|
||||
|
||||
will produce
|
||||
|
||||
.. image:: images/atom_annotation_1.png
|
||||
|
||||
|
||||
Substructure Searching
|
||||
|
||||
@@ -45,11 +45,14 @@ help:
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
cppexamples:
|
||||
cp -r C++Examples $(BUILDDIR)/html/
|
||||
|
||||
apidocs:
|
||||
mkdir -p $(BUILDDIR)/html/cppapi
|
||||
cp -r $(CPPAPIDOCSHOME)/* $(BUILDDIR)/html/cppapi
|
||||
|
||||
html: $(RSTS_FROM_MD) apidocs
|
||||
html: $(RSTS_FROM_MD) apidocs cppexamples
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
@@ -70,7 +70,7 @@ release = '2020.03.1'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build', 'GettingStartedInC++*', 'C++Examples']
|
||||
exclude_patterns = ['_build', 'C++Examples']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
77
Docs/Book/data/test_multi_colours.py
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from rdkit import Chem, rdBase
|
||||
from rdkit.Chem import rdDepictor
|
||||
from rdkit.Chem import Draw
|
||||
from rdkit.Chem import AllChem
|
||||
from rdkit.Chem.Draw import rdMolDraw2D
|
||||
from json import dumps
|
||||
|
||||
COLS = [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0),
|
||||
(0.0, 0.0, 1.0), (1.0, 0.55, 1.0)]
|
||||
|
||||
|
||||
def get_hit_atoms_and_bonds(mol, smt):
|
||||
alist = []
|
||||
blist = []
|
||||
q = Chem.MolFromSmarts(smt)
|
||||
for match in mol.GetSubstructMatches(q):
|
||||
alist.extend(match)
|
||||
|
||||
for ha1 in alist:
|
||||
for ha2 in alist:
|
||||
if ha1 > ha2:
|
||||
b = mol.GetBondBetweenAtoms(ha1, ha2)
|
||||
if b:
|
||||
blist.append(b.GetIdx())
|
||||
|
||||
return alist, blist
|
||||
|
||||
|
||||
def add_colours_to_map(els, cols, col_num):
|
||||
for el in els:
|
||||
if not el in cols:
|
||||
cols[el] = []
|
||||
if COLS[col_num] not in cols[el]:
|
||||
cols[el].append(COLS[col_num])
|
||||
|
||||
|
||||
def do_a_picture(smi, smarts, filename, label, fmt='svg'):
|
||||
|
||||
rdDepictor.SetPreferCoordGen(True)
|
||||
mol = Chem.MolFromSmiles(smi)
|
||||
mol = Draw.PrepareMolForDrawing(mol)
|
||||
|
||||
acols = {}
|
||||
bcols = {}
|
||||
h_rads = {}
|
||||
h_lw_mult = {}
|
||||
|
||||
for i, smt in enumerate(smarts):
|
||||
alist, blist = get_hit_atoms_and_bonds(mol, smt)
|
||||
col = i % 4
|
||||
add_colours_to_map(alist, acols, col)
|
||||
add_colours_to_map(blist, bcols, col)
|
||||
|
||||
if fmt == 'svg':
|
||||
d = rdMolDraw2D.MolDraw2DSVG(300, 300)
|
||||
mode = 'w'
|
||||
elif fmt == 'png':
|
||||
d = rdMolDraw2D.MolDraw2DCairo(300, 300)
|
||||
mode = 'wb'
|
||||
else:
|
||||
print('unknown format {}'.format(fmt))
|
||||
return
|
||||
|
||||
d.drawOptions().fillHighlights = False
|
||||
d.DrawMoleculeWithHighlights(mol, label, acols, bcols, h_rads, h_lw_mult, -1)
|
||||
d.FinishDrawing()
|
||||
|
||||
with open(filename, mode) as f:
|
||||
f.write(d.GetDrawingText())
|
||||
|
||||
|
||||
smi = 'CO[C@@H](O)C1=C(O[C@H](F)Cl)C(C#N)=C1ONNC[NH3+]'
|
||||
smarts = ['CONN', 'N#CC~CO', 'C=CON', 'CONNCN']
|
||||
do_a_picture(smi, smarts, 'atom_highlights_3.png', '', fmt='png')
|
||||
|
||||
BIN
Docs/Book/images/atom_annotation_1.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
Docs/Book/images/atom_highlights_1.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
Docs/Book/images/atom_highlights_2.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
Docs/Book/images/atom_highlights_3.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Docs/Book/images/stereo_annotation.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 21 KiB |
@@ -17,6 +17,7 @@ The RDKit Documentation
|
||||
Cartridge
|
||||
BackwardsIncompatibleChanges
|
||||
api-docs
|
||||
GettingStartedInC++
|
||||
|
||||
Additional Information
|
||||
======================
|
||||
|
||||