diff --git a/Code/MinimalLib/CMakeLists.txt b/Code/MinimalLib/CMakeLists.txt
index 889c562cf..21cc55d02 100644
--- a/Code/MinimalLib/CMakeLists.txt
+++ b/Code/MinimalLib/CMakeLists.txt
@@ -10,7 +10,9 @@ if(RDK_BUILD_MINIMAL_LIB)
endif()
endif()
add_executable(RDKit_minimal jswrapper.cpp minilib.cpp)
- target_link_libraries(RDKit_minimal MolInterchange_static Abbreviations_static CIPLabeler_static MolDraw2D_static Depictor_static RDInchiLib_static SubstructMatch_static FileParsers_static
+ target_link_libraries(RDKit_minimal MolInterchange_static Abbreviations_static
+ CIPLabeler_static MolDraw2D_static Depictor_static RDInchiLib_static
+ SubstructMatch_static SubstructLibrary_static FileParsers_static
SmilesParse_static GraphMol_static RDGeometryLib_static RDGeneral_static)
set_target_properties(RDKit_minimal PROPERTIES LINK_FLAGS "--bind")
diff --git a/Code/MinimalLib/common.h b/Code/MinimalLib/common.h
index e0da48947..957c8101c 100755
--- a/Code/MinimalLib/common.h
+++ b/Code/MinimalLib/common.h
@@ -68,7 +68,9 @@ static constexpr unsigned int d_defaultHeight = 200;
RWMol *mol_from_input(const std::string &input,
const std::string &details_json = "") {
bool sanitize = true;
+ bool kekulize = true;
bool removeHs = true;
+ bool mergeQueryHs = false;
RWMol *res = nullptr;
boost::property_tree::ptree pt;
if (!details_json.empty()) {
@@ -76,7 +78,9 @@ RWMol *mol_from_input(const std::string &input,
ss.str(details_json);
boost::property_tree::read_json(ss, pt);
LPT_OPT_GET(sanitize);
+ LPT_OPT_GET(kekulize);
LPT_OPT_GET(removeHs);
+ LPT_OPT_GET(mergeQueryHs);
}
try {
if (input.find("M END") != std::string::npos) {
@@ -109,9 +113,17 @@ RWMol *mol_from_input(const std::string &input,
if (res) {
try {
if (sanitize) {
- MolOps::sanitizeMol(*res);
+ unsigned int failedOp;
+ unsigned int sanitizeOps = MolOps::SANITIZE_ALL;
+ if (!kekulize) {
+ sanitizeOps ^= MolOps::SANITIZE_KEKULIZE;
+ }
+ MolOps::sanitizeMol(*res, failedOp, sanitizeOps);
}
MolOps::assignStereochemistry(*res, true, true, true);
+ if (mergeQueryHs) {
+ MolOps::mergeQueryHs(*res);
+ }
} catch (...) {
delete res;
res = nullptr;
@@ -130,7 +142,6 @@ RWMol *mol_from_input(const std::string &input, const char *details_json) {
RWMol *qmol_from_input(const std::string &input,
const std::string &details_json = "") {
RWMol *res = nullptr;
- bool sanitize = false;
bool removeHs = true;
boost::property_tree::ptree pt;
if (!details_json.empty()) {
@@ -138,7 +149,6 @@ RWMol *qmol_from_input(const std::string &input,
std::istringstream ss;
ss.str(details_json);
boost::property_tree::read_json(ss, pt);
- LPT_OPT_GET(sanitize);
LPT_OPT_GET(removeHs);
}
if (input.find("M END") != std::string::npos) {
diff --git a/Code/MinimalLib/docs/GettingStartedInJS.html b/Code/MinimalLib/docs/GettingStartedInJS.html
index 05688b7d2..8bf5511c0 100644
--- a/Code/MinimalLib/docs/GettingStartedInJS.html
+++ b/Code/MinimalLib/docs/GettingStartedInJS.html
@@ -156,6 +156,7 @@ The currently supported options are:
atomLabelDeuteriumTritium,
dummiesAreAttachments,
circleAtoms,
+splitBonds,
continuousHighlight,
fillHighlights,
highlightRadius,
@@ -170,6 +171,7 @@ fontFile,
multipleBondOffset,
padding,
additionalAtomLabelPadding,
+noAtomLabels,
bondLineWidth,
scaleBondWidth,
scaleHighlightBondWidth,
@@ -180,21 +182,24 @@ fixedBondLength,
rotate,
addAtomIndices,
addBondIndices,
+isotopeLabels,
+dummyIsotopeLabels,
addStereoAnnotation,
atomHighlightsAreCircles,
centreMoleculesBeforeDrawing,
explicitMethyl,
includeMetadata,
includeRadicals,
-highlightColour,
-backgroundColour,
-legendColour,
-symbolColour,
-atomLabels
+comicMode,
+variableBondWidthMultiplier,
+variableAtomRadius,
+includeChiralFlagLabel,
+simplifiedStereoGroupLabel,
+singleColourWedgeBonds
-
It's often useful to generate molecule renderings where the coordinates of a core is constrained.
+
It's often useful to generate molecule renderings where the coordinates of a core are constrained.
+
get_mol can be passed a JSON dictionary of boolean options. Currently supported options are:
+
+sanitize,
+kekulize,
+removeHs,
+mergeQueryHs
+
+
+
+
+
The SubstructLibrary functionality is exposed to enable running fast substructure searches
+taking advantage of pre-filtering through pattern fingerprints:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Code/MinimalLib/jswrapper.cpp b/Code/MinimalLib/jswrapper.cpp
index a3738fd8f..59db65bbc 100644
--- a/Code/MinimalLib/jswrapper.cpp
+++ b/Code/MinimalLib/jswrapper.cpp
@@ -88,6 +88,10 @@ std::string draw_to_canvas_with_highlights(JSMol &self, emscripten::val canvas,
return "";
}
+JSMol *get_mol_no_details(const std::string &input) {
+ return get_mol(input, std::string());
+}
+
} // namespace
using namespace emscripten;
@@ -138,6 +142,9 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) {
.function("generate_aligned_coords",
select_overload(
&JSMol::generate_aligned_coords))
+ .function("generate_aligned_coords",
+ select_overload(
+ &JSMol::generate_aligned_coords))
.function("condense_abbreviations",
select_overload(&JSMol::condense_abbreviations))
.function("condense_abbreviations",
@@ -146,9 +153,34 @@ EMSCRIPTEN_BINDINGS(RDKit_minimal) {
.function("add_hs", &JSMol::add_hs)
.function("remove_hs", &JSMol::remove_hs);
+ class_("SubstructLibrary")
+ .constructor<>()
+ .constructor()
+ .function("add_mol", &JSSubstructLibrary::add_mol)
+ .function("add_smiles", &JSSubstructLibrary::add_smiles)
+ .function("add_trusted_smiles", &JSSubstructLibrary::add_trusted_smiles)
+ .function("get_mol", &JSSubstructLibrary::get_mol, allow_raw_pointers())
+ .function(
+ "get_matches",
+ select_overload(
+ &JSSubstructLibrary::get_matches))
+ .function("get_matches",
+ select_overload(
+ &JSSubstructLibrary::get_matches))
+ .function("get_matches",
+ select_overload(
+ &JSSubstructLibrary::get_matches))
+ .function("count_matches",
+ select_overload(
+ &JSSubstructLibrary::count_matches))
+ .function("count_matches",
+ select_overload(
+ &JSSubstructLibrary::count_matches));
+
function("version", &version);
function("prefer_coordgen", &prefer_coordgen);
function("get_inchikey_for_inchi", &get_inchikey_for_inchi);
function("get_mol", &get_mol, allow_raw_pointers());
+ function("get_mol", &get_mol_no_details, allow_raw_pointers());
function("get_qmol", &get_qmol, allow_raw_pointers());
}
diff --git a/Code/MinimalLib/minilib.cpp b/Code/MinimalLib/minilib.cpp
index 3cc4fe6cd..aa29d3856 100644
--- a/Code/MinimalLib/minilib.cpp
+++ b/Code/MinimalLib/minilib.cpp
@@ -17,12 +17,12 @@
#include
#include
#include
-#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -287,7 +287,8 @@ std::string JSMol::condense_abbreviations_from_defs(
std::string JSMol::generate_aligned_coords(const JSMol &templateMol,
bool useCoordGen,
- bool allowRGroups) {
+ bool allowRGroups,
+ bool acceptFailure) {
std::string res;
if (!d_mol || !templateMol.d_mol || !templateMol.d_mol->getNumConformers())
return res;
@@ -297,7 +298,6 @@ std::string JSMol::generate_aligned_coords(const JSMol &templateMol,
RDDepict::preferCoordGen = useCoordGen;
#endif
RDKit::ROMol *refPattern = nullptr;
- bool acceptFailure = true;
int confId = -1;
RDKit::MatchVectType match = RDDepict::generateDepictionMatching2DStructure(
*d_mol, *(templateMol.d_mol), confId, refPattern, acceptFailure, false,
@@ -310,6 +310,8 @@ std::string JSMol::generate_aligned_coords(const JSMol &templateMol,
rj::Writer writer(buffer);
doc.Accept(writer);
res = buffer.GetString();
+ } else {
+ res = "{}";
}
#ifdef RDK_BUILD_COORDGEN_SUPPORT
RDDepict::preferCoordGen = oprefer;
@@ -317,12 +319,86 @@ std::string JSMol::generate_aligned_coords(const JSMol &templateMol,
return res;
};
+JSSubstructLibrary::JSSubstructLibrary(unsigned int num_bits)
+ : d_sslib(new SubstructLibrary(
+ boost::shared_ptr(
+ new CachedTrustedSmilesMolHolder()),
+ boost::shared_ptr(new PatternHolder()))),
+ d_num_bits(num_bits) {
+ d_molHolder = dynamic_cast(
+ d_sslib->getMolHolder().get());
+ d_fpHolder = dynamic_cast(d_sslib->getFpHolder().get());
+}
+
+int JSSubstructLibrary::add_trusted_smiles(const std::string &smi) {
+ std::unique_ptr mol(SmilesToMol(smi, 0, false));
+ if (!mol) {
+ return -1;
+ }
+ mol->updatePropertyCache();
+ ExplicitBitVect *bv = PatternFingerprintMol(*mol, d_num_bits);
+ if (!bv) {
+ return -1;
+ }
+ d_fpHolder->addFingerprint(bv);
+ auto ret = d_molHolder->addSmiles(smi);
+ return ret;
+}
+
+inline int JSSubstructLibrary::add_mol_helper(const ROMol &mol) {
+ std::string smi = MolToSmiles(mol);
+ return add_trusted_smiles(smi);
+}
+
+int JSSubstructLibrary::add_mol(const JSMol &m) {
+ return add_mol_helper(*m.d_mol);
+}
+
+int JSSubstructLibrary::add_smiles(const std::string &smi) {
+ std::unique_ptr mol(SmilesToMol(smi));
+ if (!mol) {
+ return -1;
+ }
+ return add_mol_helper(*mol);
+}
+
+JSMol *JSSubstructLibrary::get_mol(unsigned int i) {
+ return new JSMol(new RWMol(*d_sslib->getMol(i)));
+}
+
+std::string JSSubstructLibrary::get_matches(const JSMol &q, bool useChirality,
+ int numThreads,
+ int maxResults) const {
+ if (!d_sslib->size()) {
+ return "[]";
+ }
+ std::vector indices = d_sslib->getMatches(
+ *q.d_mol, true, useChirality, false, numThreads, maxResults);
+ rj::Document doc;
+ doc.SetArray();
+ auto &alloc = doc.GetAllocator();
+ for (const auto &i : indices) {
+ doc.PushBack(i, alloc);
+ }
+ rj::StringBuffer buffer;
+ rj::Writer writer(buffer);
+ doc.Accept(writer);
+ std::string res = buffer.GetString();
+ return res;
+}
+
+unsigned int JSSubstructLibrary::count_matches(const JSMol &q,
+ bool useChirality,
+ int numThreads) const {
+ return d_sslib->countMatches(*q.d_mol, true, useChirality, false, 1);
+}
+
std::string get_inchikey_for_inchi(const std::string &input) {
return InchiToInchiKey(input);
}
-JSMol *get_mol(const std::string &input) {
- RWMol *mol = MinimalLib::mol_from_input(input);
+JSMol *get_mol(const std::string &input, const std::string &details_json) {
+ RWMol *mol = MinimalLib::mol_from_input(input, details_json);
return new JSMol(mol);
}
diff --git a/Code/MinimalLib/minilib.h b/Code/MinimalLib/minilib.h
index 9ce969e09..30bd77e16 100644
--- a/Code/MinimalLib/minilib.h
+++ b/Code/MinimalLib/minilib.h
@@ -10,6 +10,7 @@
//
#include
#include
+#include
class JSMol {
public:
@@ -38,13 +39,17 @@ class JSMol {
double maxCoverage,
bool areLinkers);
std::string generate_aligned_coords(const JSMol &templateMol,
- bool useCoordGen, bool allowRGroups);
+ bool useCoordGen, bool allowOptionalAttachments, bool acceptFailure);
+ std::string generate_aligned_coords(const JSMol &templateMol,
+ bool useCoordGen, bool allowOptionalAttachments) {
+ return generate_aligned_coords(templateMol, useCoordGen, allowOptionalAttachments, true);
+ };
std::string generate_aligned_coords(const JSMol &templateMol,
bool useCoordGen) {
- return generate_aligned_coords(templateMol, useCoordGen, false);
+ return generate_aligned_coords(templateMol, useCoordGen, false, true);
};
std::string generate_aligned_coords(const JSMol &templateMol) {
- return generate_aligned_coords(templateMol, false, false);
+ return generate_aligned_coords(templateMol, false, false, true);
};
bool is_valid() const { return d_mol.get() != nullptr; };
@@ -63,8 +68,45 @@ class JSMol {
static constexpr unsigned int d_defaultHeight = 200;
};
+class JSSubstructLibrary {
+ public:
+ JSSubstructLibrary(unsigned int num_bits);
+ JSSubstructLibrary() : JSSubstructLibrary(d_defaultNumBits) {}
+ int add_mol(const JSMol &m);
+ int add_smiles(const std::string &smi);
+ int add_trusted_smiles(const std::string &smi);
+ JSMol *get_mol(unsigned int i);
+ std::string get_matches(const JSMol &q, bool useChirality, int numThreads,
+ int maxResults) const;
+ std::string get_matches(const JSMol &q, int maxResults) const {
+ return get_matches(q, d_defaultUseChirality, d_defaultNumThreads,
+ maxResults);
+ }
+ std::string get_matches(const JSMol &q) const {
+ return get_matches(q, d_defaultUseChirality, d_defaultNumThreads,
+ d_defaultMaxResults);
+ }
+ unsigned int count_matches(const JSMol &q, bool useChirality,
+ int numThreads) const;
+ unsigned int count_matches(const JSMol &q) const {
+ return count_matches(q, d_defaultUseChirality, d_defaultNumThreads);
+ }
+
+ std::unique_ptr d_sslib;
+ RDKit::CachedTrustedSmilesMolHolder *d_molHolder;
+ RDKit::PatternHolder *d_fpHolder;
+ unsigned int d_num_bits;
+ static constexpr unsigned int d_defaultNumBits = 2048;
+ static constexpr bool d_defaultUseChirality = true;
+ static constexpr int d_defaultNumThreads = -1;
+ static constexpr int d_defaultMaxResults = 1000;
+
+ private:
+ inline int add_mol_helper(const RDKit::ROMol &mol);
+};
+
std::string get_inchikey_for_inchi(const std::string &input);
-JSMol *get_mol(const std::string &input);
+JSMol *get_mol(const std::string &input, const std::string &details_json);
JSMol *get_qmol(const std::string &input);
std::string version();
void prefer_coordgen(bool prefer);
diff --git a/Code/MinimalLib/tests/tests.js b/Code/MinimalLib/tests/tests.js
index d44476a0a..fc84b4e33 100644
--- a/Code/MinimalLib/tests/tests.js
+++ b/Code/MinimalLib/tests/tests.js
@@ -10,12 +10,17 @@
//
const assert = require('assert');
+const {
+ performance
+ } = require('perf_hooks');
var initRDKitModule = require("../demo/RDKit_minimal.js");
var RDKitModule;
+const fs = require('fs');
+const readline = require('readline');
// the goal here isn't to be comprehensive (the RDKit has tests for that),
// just to make sure that the wrappers are working as expected
-function test_basics(){
+function test_basics() {
var bmol = RDKitModule.get_mol("c1ccccc");
assert.equal(bmol.is_valid(),0);
@@ -58,7 +63,7 @@ function test_basics(){
assert(svg2.search("#FF7F7F")>0);
}
-function test_molblock_nostrict(){
+function test_molblock_nostrict() {
var molblock = `
MJ201100
@@ -99,14 +104,43 @@ M END`;
assert.equal(qmb.includes("M SAP 1 1 8 6"), true);
}
-function test_sketcher_services(){
+function test_molblock_rgp() {
+ var molblock = `
+ MJ190400
+
+ 9 9 0 0 0 0 0 0 0 0999 V2000
+ -6.5623 0.3105 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0
+ -5.8478 -0.1019 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -5.1333 0.3105 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ -4.4188 -0.1019 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ -4.4188 -0.9269 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -5.1333 -1.3394 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -5.8478 -0.9269 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -3.7043 -1.3394 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ -2.9898 -0.9268 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0
+ 3 4 4 0 0 0 0
+ 4 5 4 0 0 0 0
+ 5 6 4 0 0 0 0
+ 6 7 4 0 0 0 0
+ 2 3 4 0 0 0 0
+ 2 7 4 0 0 0 0
+ 5 8 1 0 0 0 0
+ 8 9 1 0 0 0 0
+ 1 2 1 0 0 0 0
+M RGP 2 1 2 9 1
+M END`;
+ var mol = RDKitModule.get_mol(molblock);
+ assert.equal(mol.is_valid(),1);
+}
+
+function test_sketcher_services() {
var mol = RDKitModule.get_mol("C[C@](F)(Cl)/C=C/C(F)Br");
assert.equal(mol.is_valid(),1);
var tags = mol.get_stereo_tags();
assert.equal(tags,'{"CIP_atoms":[[1,"(S)"],[6,"(?)"]],"CIP_bonds":[[4,5,"(E)"]]}');
}
-function test_sketcher_services2(){
+function test_sketcher_services2() {
var mol = RDKitModule.get_mol("c1ccccc1");
assert.equal(mol.is_valid(),1);
var molb = mol.add_hs();
@@ -124,7 +158,7 @@ function test_sketcher_services2(){
}
-function test_abbreviations(){
+function test_abbreviations() {
var bmol = RDKitModule.get_mol("C1CCC1C(F)(F)F");
assert.equal(bmol.is_valid(),1);
bmol.condense_abbreviations();
@@ -133,8 +167,92 @@ function test_abbreviations(){
assert.equal(bmol.get_cxsmiles(),"*C1CCC1 |$CF3;;;;$|");
}
+function test_substruct_library(done) {
+ done.test_substruct_library = false;
+ var smiReader = readline.createInterface({
+ input: fs.createReadStream(__dirname + '/../../GraphMol/test_data/compounds.smi')
+ });
+ var sslib = new RDKitModule.SubstructLibrary();
+ // var t0 = performance.now()
+ // console.log('Started adding trusted SMILES');
+ smiReader.on('line', (smi) => {
+ sslib.add_trusted_smiles(smi);
+ });
+ smiReader.on('close', () => {
+ var query = RDKitModule.get_qmol("N");
+ // var t1 = performance.now();
+ // console.log('Finished adding trusted SMILES took ' + (t1 - t0) / 1000 + ' seconds');
+ assert.equal(sslib.count_matches(query), 52);
+ assert.equal(sslib.get_matches(query), JSON.stringify([
+ 12,13,19,22,24,30,31,32,35,36,39,41,43,44,55,56,58,64,72,80,
+ 85,95,96,101,105,113,124,127,128,131,143,150,151,185,201,202,
+ 203,214,215,223,232,234,238,240,241,246,258,261,263,265,266,284
+ ]));
+ done.test_substruct_library = true;
+ });
+}
-function test_generate_aligned_coords(){
+function test_substruct_library_merge_hs() {
+ var sslib = new RDKitModule.SubstructLibrary();
+ var mol1 = RDKitModule.get_mol("c1ccccc1");
+ var mol2 = RDKitModule.get_mol("Cc1ccccc1");
+ sslib.add_trusted_smiles(mol1.get_smiles());
+ sslib.add_trusted_smiles(mol2.get_smiles());
+ var query = RDKitModule.get_mol(`
+ MJ201100 2D
+
+ 6 6 0 0 0 0 0 0 0 0999 V2000
+ -1.0491 0.7134 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -1.7635 0.3009 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -1.7635 -0.5241 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -1.0491 -0.9366 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -0.3346 -0.5241 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -0.3346 0.3009 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2 3 1 0 0 0 0
+ 5 6 2 0 0 0 0
+ 1 2 2 0 0 0 0
+ 6 1 1 0 0 0 0
+ 3 4 2 0 0 0 0
+ 4 5 1 0 0 0 0
+M END`);
+ assert.equal(sslib.get_matches(query), JSON.stringify([0, 1]));
+ var query_hs = RDKitModule.get_mol(query.add_hs());
+ assert.equal(sslib.get_matches(query_hs), JSON.stringify([]));
+ query_hs = RDKitModule.get_mol(query_hs.get_molblock(), JSON.stringify({ mergeQueryHs: true }));
+ assert.equal(sslib.get_matches(query_hs), JSON.stringify([0]));
+}
+
+function test_substruct_library_empty_mols() {
+ var sslib = new RDKitModule.SubstructLibrary();
+ var mol1 = RDKitModule.get_mol("");
+ var mol2 = RDKitModule.get_mol("");
+ sslib.add_trusted_smiles(mol1.get_smiles());
+ sslib.add_trusted_smiles(mol2.get_smiles());
+ var query = RDKitModule.get_mol("C");
+ assert.equal(sslib.get_matches(query), JSON.stringify([]));
+ var empty_query = RDKitModule.get_mol("");
+ assert.equal(sslib.get_matches(empty_query), JSON.stringify([]));
+}
+
+function test_substruct_library_empty_query() {
+ var sslib = new RDKitModule.SubstructLibrary();
+ var mol1 = RDKitModule.get_mol("C");
+ var mol2 = RDKitModule.get_mol("CC");
+ sslib.add_trusted_smiles(mol1.get_smiles());
+ sslib.add_trusted_smiles(mol2.get_smiles());
+ var query = RDKitModule.get_mol("");
+ assert.equal(sslib.get_matches(query), JSON.stringify([]));
+}
+
+function test_substruct_library_empty_lib() {
+ var sslib = new RDKitModule.SubstructLibrary();
+ var query = RDKitModule.get_mol("C");
+ assert.equal(sslib.get_matches(query), JSON.stringify([]));
+ var empty_query = RDKitModule.get_mol("");
+ assert.equal(sslib.get_matches(empty_query), JSON.stringify([]));
+}
+
+function test_generate_aligned_coords() {
var smiles = "CCC";
var mol = RDKitModule.get_mol(smiles);
var template = "CC";
@@ -143,7 +261,7 @@ function test_generate_aligned_coords(){
}
-function test_isotope_labels(){
+function test_isotope_labels() {
var mol = RDKitModule.get_mol("[1*]c1cc([2*])c([3*])c[14c]1");
assert.equal(mol.is_valid(), 1);
@@ -165,7 +283,8 @@ function test_isotope_labels(){
assert.ok(res.every((resItem, i) => (resItem === resSorted[i])));
}
-function test_generate_aligned_coords_allow_rgroups(){
+
+function test_generate_aligned_coords_allow_rgroups() {
var template_molblock = `
RDKit 2D
@@ -214,16 +333,107 @@ M END`;
}
+function test_accept_failure() {
+ var template_molblock = `
+ RDKit 2D
+
+ 9 9 0 0 0 0 0 0 0 0999 V2000
+ -0.8929 1.0942 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -2.1919 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -2.1919 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -0.8929 -1.9059 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.4060 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.4060 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -3.4910 1.0942 0.0000 R1 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.7051 1.0942 0.0000 R2 0 0 0 0 0 0 0 0 0 0 0 0
+ -3.4910 -1.9059 0.0000 R3 0 0 0 0 0 0 0 0 0 0 0 0
+ 1 2 2 0
+ 2 3 1 0
+ 3 4 2 0
+ 4 5 1 0
+ 5 6 2 0
+ 6 1 1 0
+ 6 8 1 0
+ 3 9 1 0
+ 2 7 1 0
+M RGP 3 7 1 8 2 9 3
+M END
+`;
+ var mol_molblock = `
+ RDKit 2D
+
+ 9 9 0 0 0 0 0 0 0 0999 V2000
+ -0.8929 1.0942 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ -2.1919 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -2.1919 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -0.8929 -1.9059 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.4060 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.4060 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ -3.4910 1.0942 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.7051 1.0942 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0
+ -3.4910 -1.9059 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0
+ 1 2 2 0
+ 2 3 1 0
+ 3 4 2 0
+ 4 5 1 0
+ 5 6 2 0
+ 6 1 1 0
+ 6 8 1 0
+ 3 9 1 0
+ 2 7 1 0
+M END
+`;
+ var template_ref = RDKitModule.get_mol(template_molblock);
+ var mol = RDKitModule.get_mol(mol_molblock);
+ var hasThrown = false;
+ try {
+ mol.generate_aligned_coords(template_ref, false, true, false);
+ } catch (e) {
+ hasThrown = true;
+ }
+ assert(hasThrown);
+ assert.equal(mol.get_molblock(), mol_molblock);
+}
+
+function test_get_mol_no_kekulize() {
+ var mol = RDKitModule.get_mol("c");
+ assert(!mol.is_valid());
+ mol = RDKitModule.get_mol("c", JSON.stringify({kekulize: false}));
+ assert(mol.is_valid());
+}
+
+
initRDKitModule().then(function(instance) {
+ var done = {};
+ const waitAllTestsFinished = () => {
+ const poll = resolve => {
+ if (Object.values(done).every(v => v)) {
+ resolve();
+ } else {
+ setTimeout(() => poll(resolve), 100);
+ }
+ }
+ return new Promise(poll);
+ }
RDKitModule = instance;
console.log(RDKitModule.version());
test_basics();
test_molblock_nostrict();
+ test_molblock_rgp();
test_sketcher_services();
test_sketcher_services2();
test_abbreviations();
+ test_substruct_library(done);
+ test_substruct_library_merge_hs();
+ test_substruct_library_empty_mols();
+ test_substruct_library_empty_lib();
+ test_substruct_library_empty_query();
test_generate_aligned_coords();
test_isotope_labels();
test_generate_aligned_coords_allow_rgroups();
- console.log("Tests finished successfully");
+ test_accept_failure();
+ test_get_mol_no_kekulize();
+ waitAllTestsFinished().then(() =>
+ console.log("Tests finished successfully")
+ );
});