mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-03 21:44:30 +08:00
Support using iterators with MolSuppliers (#9230)
* iterators for random-access MolSuppliers add optional caching to SDMolSupplier * add support to SmilesMolSupplier too There is a lot of duplicate code between the random-access suppliers that would be worth trying to remove but at the moment it looks like it would require multiple inheritance, and I think we want to avoid that * add input iterators for ForwardSDMolSupplier() * throw when calling begin() on a used supplier * switch to use the spaceship operator * init() should reset the mol cache * Make SDMolSupplier and SmilesMolSupplier safe for multi-threaded reads * add benchmarking * add TDTMolSupplier support improved testing add benchmarks for parallel iteration optional TBB support * better const handling, add reverse iterators doesn't look like const_iterator is possible since getting data from the underlyng supplier object is non-const * improve docs more usings add reverse iterator to TDTMolSupplier * tests only try execution::par when it is there * fix typo * more testing/demo * remove accidentally added files * review changes * add default ctors * disable a false-positive compiler warning it is stupid to have to do this --------- Co-authored-by: = <=>
This commit is contained in:
@@ -130,6 +130,14 @@ rdkit_catch_test(v2FileParsersCatchTest v2_file_parsers_catch.cpp
|
||||
rdkit_catch_test(atropisomersCatch atropisomers_catch.cpp
|
||||
LINK_LIBRARIES FileParsers)
|
||||
|
||||
find_package(TBB )
|
||||
if(TBB_FOUND)
|
||||
rdkit_catch_test(fileParsersIteratorsTest fileParsersIterTest.cpp
|
||||
LINK_LIBRARIES SmilesParse FileParsers SubstructMatch TBB::tbb)
|
||||
else()
|
||||
rdkit_catch_test(fileParsersIteratorsTest fileParsersIterTest.cpp
|
||||
LINK_LIBRARIES SmilesParse FileParsers SubstructMatch)
|
||||
endif()
|
||||
|
||||
|
||||
if(RDK_TEST_MULTITHREADED AND RDK_BUILD_THREADSAFE_SSS)
|
||||
|
||||
@@ -19,10 +19,14 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <GraphMol/ROMol.h>
|
||||
#include <RDGeneral/BadFileException.h>
|
||||
#include "FileParsers.h"
|
||||
#include <GraphMol/SmilesParse/SmilesParse.h>
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#ifdef RDK_BUILD_MAEPARSER_SUPPORT
|
||||
namespace schrodinger {
|
||||
@@ -38,27 +42,67 @@ RDKIT_FILEPARSERS_EXPORT std::string strip(const std::string &orig);
|
||||
|
||||
namespace v2 {
|
||||
namespace FileParsers {
|
||||
// clang-format off
|
||||
/*!
|
||||
//
|
||||
// Here are a couple of ways one can interact with MolSuppliers:
|
||||
//
|
||||
// 1) Lazy (ForwardIterator):
|
||||
// while(!supplier.atEnd()){
|
||||
// ROMol *mol = supplier.next();
|
||||
// if(mol){
|
||||
// do something;
|
||||
// }
|
||||
// }
|
||||
// 2) Random Access:
|
||||
// for(int i=0;i<supplier.length();i++){
|
||||
// ROMol *mol = supplier[i];
|
||||
// if(mol){
|
||||
// do something;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
|
||||
Here are some of the ways one can interact with MolSuppliers:
|
||||
|
||||
1) Lazy (works with forward and random access suppliers):
|
||||
while(!supplier.atEnd()){
|
||||
auto mol = supplier.next(); // mol is a std::unique_ptr<RWMol>
|
||||
if(mol){
|
||||
do something;
|
||||
}
|
||||
}
|
||||
|
||||
2) Range based for loops (works with forward and random access suppliers):
|
||||
for(auto mol : supplier){
|
||||
if(mol) {
|
||||
do something; // mol is a shared_ptr<RWMol>
|
||||
}
|
||||
}
|
||||
|
||||
3) Random Access:
|
||||
for(int i=0;i<supplier.length();i++){
|
||||
auto mol = supplier[i]; // mol is a std::unique_ptr<RWMol>
|
||||
if(mol){
|
||||
do something;
|
||||
}
|
||||
}
|
||||
|
||||
4) Random access supplier also support caching:
|
||||
supplier.setCaching(true);
|
||||
for(auto mol : supplier){
|
||||
if(mol) {
|
||||
do something; // mol is a shared_ptr<RWMol>
|
||||
}
|
||||
}
|
||||
Subsequent iterations will be much faster as the molecules are cached
|
||||
after the first read.
|
||||
|
||||
It's also possible to access the cached molecules directly using the getShared method:
|
||||
supplier.setCaching(true);
|
||||
for(int i=0;i<supplier.length();i++){
|
||||
auto mol = supplier.getShared(i); // mol is a std::shared_ptr<RWMol>;
|
||||
if(mol){
|
||||
do something;
|
||||
}
|
||||
}
|
||||
|
||||
5) Random access suppliers can also be used with parallel algorithms:
|
||||
supplier.setCaching(true);
|
||||
std::for_each(std::execution::par, supplier.begin(), supplier.end(),
|
||||
[](auto mol) {
|
||||
if (mol) {
|
||||
do something;
|
||||
}
|
||||
});
|
||||
|
||||
Caching is not required here, but if you are planning on working with the
|
||||
molecules multiple times, it can speed things up significantly.
|
||||
|
||||
*/
|
||||
// clang-format on
|
||||
class RDKIT_FILEPARSERS_EXPORT MolSupplier {
|
||||
// this is an abstract base class to supply molecules one at a time
|
||||
public:
|
||||
@@ -118,6 +162,65 @@ class RDKIT_FILEPARSERS_EXPORT MolSupplier {
|
||||
}
|
||||
};
|
||||
|
||||
// g++ 13 generates some spurious warnings from here (they are gone in g++ 14).
|
||||
// disable them
|
||||
#if !defined(__clang__) && defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
// \brief an input iterator for suppliers that only support forward reading
|
||||
template <typename Supplier>
|
||||
struct ForwardSupplierIter {
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = std::shared_ptr<RWMol>;
|
||||
using const_value_type = const std::shared_ptr<RWMol>;
|
||||
|
||||
Supplier *supplier = nullptr;
|
||||
std::optional<value_type> current;
|
||||
ForwardSupplierIter() = default;
|
||||
ForwardSupplierIter(const ForwardSupplierIter &) = default;
|
||||
ForwardSupplierIter &operator=(const ForwardSupplierIter &) = default;
|
||||
ForwardSupplierIter(ForwardSupplierIter &&) = default;
|
||||
ForwardSupplierIter &operator=(ForwardSupplierIter &&) = default;
|
||||
|
||||
explicit ForwardSupplierIter(Supplier *supplier)
|
||||
: supplier(supplier), current(supplier->nextShared()) {}
|
||||
const_value_type operator*() const { return current.value(); }
|
||||
ForwardSupplierIter &operator++() {
|
||||
if (supplier->atEnd()) {
|
||||
current.reset();
|
||||
return *this;
|
||||
}
|
||||
current = supplier->nextShared();
|
||||
// This is the special case where there's a trailing blank line in the SDF.
|
||||
// we were actually at the logical end of the file coming in, but atEnd()
|
||||
// hadn't yet been set.
|
||||
// In this case we want to make sure to reset the iterator to the end state
|
||||
// instead of returning a null molecule.
|
||||
if (!current.value() && supplier->getEOFHitOnRead()) {
|
||||
current.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
ForwardSupplierIter operator++(int) {
|
||||
if (supplier->atEnd()) {
|
||||
current.reset();
|
||||
return *this;
|
||||
}
|
||||
ForwardSupplierIter tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
bool operator==(const ForwardSupplierIter &other) const {
|
||||
return !current.has_value() && !other.current.has_value();
|
||||
}
|
||||
};
|
||||
#if !defined(__clang__) && defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// \brief a supplier from an SD file that only reads forward:
|
||||
class RDKIT_FILEPARSERS_EXPORT ForwardSDMolSupplier : public MolSupplier {
|
||||
/*************************************************************************
|
||||
@@ -126,6 +229,7 @@ class RDKIT_FILEPARSERS_EXPORT ForwardSDMolSupplier : public MolSupplier {
|
||||
*noted.
|
||||
***********************************************************************************/
|
||||
public:
|
||||
using iterator = ForwardSupplierIter<ForwardSDMolSupplier>;
|
||||
ForwardSDMolSupplier() { init(); }
|
||||
|
||||
explicit ForwardSDMolSupplier(
|
||||
@@ -137,6 +241,9 @@ class RDKIT_FILEPARSERS_EXPORT ForwardSDMolSupplier : public MolSupplier {
|
||||
void init() override;
|
||||
void reset() override;
|
||||
std::unique_ptr<RWMol> next() override;
|
||||
std::shared_ptr<RWMol> nextShared() {
|
||||
return std::shared_ptr<RWMol>(this->next());
|
||||
};
|
||||
bool atEnd() override;
|
||||
|
||||
void setProcessPropertyLists(bool val) { df_processPropertyLists = val; }
|
||||
@@ -144,6 +251,16 @@ class RDKIT_FILEPARSERS_EXPORT ForwardSDMolSupplier : public MolSupplier {
|
||||
|
||||
bool getEOFHitOnRead() const { return df_eofHitOnRead; }
|
||||
|
||||
iterator begin() {
|
||||
if (d_line) {
|
||||
throw ValueErrorException(
|
||||
"Cannot create an iterator for a ForwardSDMolSupplier that has already "
|
||||
"been read from.");
|
||||
}
|
||||
return iterator(this);
|
||||
}
|
||||
iterator end() { return iterator(); }
|
||||
|
||||
protected:
|
||||
virtual void checkForEnd();
|
||||
std::unique_ptr<RWMol> _next();
|
||||
@@ -154,21 +271,102 @@ class RDKIT_FILEPARSERS_EXPORT ForwardSDMolSupplier : public MolSupplier {
|
||||
bool df_processPropertyLists = true;
|
||||
bool df_eofHitOnRead = false;
|
||||
};
|
||||
// clang-format off
|
||||
static_assert(
|
||||
std::ranges::input_range<ForwardSDMolSupplier>
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
// \brief a random access iterator for suppliers that support random access
|
||||
template <typename Supplier>
|
||||
struct RandomAccessSupplierIter {
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = std::shared_ptr<RWMol>;
|
||||
using const_value_type = const std::shared_ptr<RWMol>;
|
||||
|
||||
Supplier *supplier = nullptr;
|
||||
size_t current_idx = 0;
|
||||
RandomAccessSupplierIter() = default;
|
||||
RandomAccessSupplierIter(const RandomAccessSupplierIter &) = default;
|
||||
RandomAccessSupplierIter &operator=(const RandomAccessSupplierIter &) =
|
||||
default;
|
||||
RandomAccessSupplierIter(RandomAccessSupplierIter &&) = default;
|
||||
RandomAccessSupplierIter &operator=(RandomAccessSupplierIter &&) = default;
|
||||
explicit RandomAccessSupplierIter(Supplier *supplier)
|
||||
: supplier(supplier), current_idx(0) {}
|
||||
RandomAccessSupplierIter(Supplier *supplier, size_t idx)
|
||||
: supplier(supplier), current_idx(idx) {}
|
||||
const_value_type operator*() const {
|
||||
return supplier->getShared(current_idx);
|
||||
}
|
||||
const_value_type operator[](size_t idx) const {
|
||||
return supplier->getShared(idx);
|
||||
}
|
||||
RandomAccessSupplierIter &operator++() {
|
||||
++current_idx;
|
||||
return *this;
|
||||
}
|
||||
RandomAccessSupplierIter operator++(int) {
|
||||
RandomAccessSupplierIter tmp(this->supplier, current_idx);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
RandomAccessSupplierIter &operator--() {
|
||||
--current_idx;
|
||||
return *this;
|
||||
}
|
||||
RandomAccessSupplierIter operator--(int) {
|
||||
RandomAccessSupplierIter tmp(this->supplier, current_idx);
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
RandomAccessSupplierIter &operator+=(difference_type n) {
|
||||
current_idx += n;
|
||||
return *this;
|
||||
}
|
||||
RandomAccessSupplierIter &operator-=(difference_type n) {
|
||||
current_idx -= n;
|
||||
return *this;
|
||||
}
|
||||
RandomAccessSupplierIter operator+(difference_type n) const {
|
||||
return RandomAccessSupplierIter(this->supplier, current_idx + n);
|
||||
}
|
||||
RandomAccessSupplierIter operator-(difference_type n) const {
|
||||
return RandomAccessSupplierIter(this->supplier, current_idx - n);
|
||||
}
|
||||
difference_type operator-(const RandomAccessSupplierIter &other) const {
|
||||
return static_cast<difference_type>(current_idx) -
|
||||
static_cast<difference_type>(other.current_idx);
|
||||
}
|
||||
friend RandomAccessSupplierIter operator+(
|
||||
difference_type n, const RandomAccessSupplierIter &it) {
|
||||
return RandomAccessSupplierIter(it.supplier, it.current_idx + n);
|
||||
}
|
||||
auto operator<=>(const RandomAccessSupplierIter &other) const {
|
||||
return current_idx <=> other.current_idx;
|
||||
}
|
||||
bool operator==(const RandomAccessSupplierIter &other) const {
|
||||
return this->supplier == other.supplier &&
|
||||
this->current_idx == other.current_idx;
|
||||
}
|
||||
};
|
||||
|
||||
// \brief a lazy supplier from an SD file
|
||||
class RDKIT_FILEPARSERS_EXPORT SDMolSupplier : public ForwardSDMolSupplier {
|
||||
/*************************************************************************
|
||||
* A lazy mol supplier from a SD file.
|
||||
* - When new molecules are read using "next" their positions in the file are
|
||||
*noted.
|
||||
* - A call to the "length" will automatically parse the entire file and
|
||||
*cache all the mol
|
||||
* block positions
|
||||
* - [] operator is used to access a molecule at "idx", calling next
|
||||
*following this will result
|
||||
* in the next molecule after "idx"
|
||||
* - When new molecules are read using "next()" their positions in the file
|
||||
* are stored.
|
||||
* - A call to the "length()" will automatically parse the entire file and
|
||||
* store all the mol block positions
|
||||
* - [] operator is used to access a molecule at "idx", calling next()
|
||||
* after this will result in the next molecule after "idx"
|
||||
***********************************************************************************/
|
||||
|
||||
public:
|
||||
using iterator = RandomAccessSupplierIter<SDMolSupplier>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
|
||||
SDMolSupplier() { init(); }
|
||||
|
||||
/*!
|
||||
@@ -195,6 +393,8 @@ class RDKIT_FILEPARSERS_EXPORT SDMolSupplier : public ForwardSDMolSupplier {
|
||||
bool atEnd() override;
|
||||
void moveTo(unsigned int idx);
|
||||
std::unique_ptr<RWMol> operator[](unsigned int idx);
|
||||
///! \brief returns a shared pointer to the molecule at the given index.
|
||||
std::shared_ptr<RWMol> getShared(unsigned int idx);
|
||||
/*! \brief returns the text block for a particular item
|
||||
*
|
||||
* \param idx - which item to return
|
||||
@@ -218,14 +418,33 @@ class RDKIT_FILEPARSERS_EXPORT SDMolSupplier : public ForwardSDMolSupplier {
|
||||
*/
|
||||
void setStreamIndices(const std::vector<std::streampos> &locs);
|
||||
|
||||
iterator begin() { return RandomAccessSupplierIter(this); }
|
||||
iterator end() { return RandomAccessSupplierIter(this, length()); }
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
|
||||
void setCaching(bool val) { d_cacheMolecules = val; }
|
||||
bool getCaching() const { return d_cacheMolecules; }
|
||||
|
||||
private:
|
||||
void checkForEnd() override;
|
||||
void peekCheckForEnd(char* bufPtr, char* bufEnd, std::streampos molStartPos);
|
||||
void peekCheckForEnd(char *bufPtr, char *bufEnd, std::streampos molStartPos);
|
||||
void buildIndexTo(unsigned int targetIdx);
|
||||
int d_len = 0; // total number of mol blocks in the file (initialized to -1)
|
||||
int d_last = 0; // the molecule we are ready to read
|
||||
std::vector<std::streampos> d_molpos;
|
||||
bool d_cacheMolecules = false;
|
||||
std::vector<std::optional<std::shared_ptr<RWMol>>> d_molCache;
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
std::mutex d_readMutex;
|
||||
std::mutex d_cacheMutex;
|
||||
#endif
|
||||
};
|
||||
// clang-format off
|
||||
static_assert(
|
||||
std::ranges::random_access_range<SDMolSupplier>
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
struct SmilesMolSupplierParams {
|
||||
std::string delimiter = " \t";
|
||||
@@ -249,34 +468,21 @@ class RDKIT_FILEPARSERS_EXPORT SmilesMolSupplier : public MolSupplier {
|
||||
/**************************************************************************
|
||||
* Lazy file parser for Smiles table file, similar to the lazy SD
|
||||
* file parser above
|
||||
* - As an when new molecules are read using "next" their
|
||||
* positions in the file are noted.
|
||||
* - A call to the "length" will automatically parse the entire
|
||||
* file and cache all the mol block positions
|
||||
* - When new molecules are read using "next()" their
|
||||
* positions in the file are stored.
|
||||
* - A call to "length()" will automatically parse the entire
|
||||
* file and store all the mol block positions
|
||||
* - [] operator is used to access a molecule at "idx", calling
|
||||
* next following this will result in the next molecule after
|
||||
* next() following this will result in the next molecule after
|
||||
* "idx"
|
||||
***************************************************************************/
|
||||
public:
|
||||
using iterator = RandomAccessSupplierIter<SmilesMolSupplier>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
/*!
|
||||
* \param fileName - the name of smiles table file
|
||||
* \param delimiter - delimiting characters between records on a each
|
||||
* line NOTE that this is not a string, the tokenizer looks for
|
||||
* the individual characters in delimiter, not the full string
|
||||
* itself. So the default delimiter: " \t", means " " or "\t".
|
||||
* \param smilesColumn - column number for the SMILES string (defaults
|
||||
* to the first column)
|
||||
* \param nameColumn - column number for the molecule name (defaults to
|
||||
* the second column) If set to -1 we assume that no name is
|
||||
* available for the molecule and the name is defaulted to the
|
||||
* smiles string
|
||||
* \param titleLine - if true, the first line is assumed to list the
|
||||
* names of properties in order separated by 'delimiter'. It is
|
||||
* also assume that the 'SMILES' column and the 'name' column
|
||||
* are not specified here if false - no title line is assumed
|
||||
* and the properties are recorded as the "columnX" where "X" is
|
||||
* the column number
|
||||
* \param sanitize - if true sanitize the molecule before returning it
|
||||
* \param params - SmilesMolSupplierParams object controlling how
|
||||
* the file itself and the individual SMILES are parsed.
|
||||
*/
|
||||
explicit SmilesMolSupplier(
|
||||
const std::string &fileName,
|
||||
@@ -295,6 +501,7 @@ class RDKIT_FILEPARSERS_EXPORT SmilesMolSupplier : public MolSupplier {
|
||||
bool atEnd() override;
|
||||
void moveTo(unsigned int idx);
|
||||
std::unique_ptr<RWMol> operator[](unsigned int idx);
|
||||
std::shared_ptr<RWMol> getShared(unsigned int idx);
|
||||
/*! \brief returns the text block for a particular item
|
||||
*
|
||||
* \param idx - which item to return
|
||||
@@ -302,6 +509,14 @@ class RDKIT_FILEPARSERS_EXPORT SmilesMolSupplier : public MolSupplier {
|
||||
std::string getItemText(unsigned int idx);
|
||||
unsigned int length();
|
||||
|
||||
iterator begin() { return iterator(this); }
|
||||
iterator end() { return iterator(this, length()); }
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
|
||||
void setCaching(bool val) { d_cacheMolecules = val; }
|
||||
bool getCaching() const { return d_cacheMolecules; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<RWMol> processLine(std::string inLine);
|
||||
void processTitleLine();
|
||||
@@ -318,6 +533,12 @@ class RDKIT_FILEPARSERS_EXPORT SmilesMolSupplier : public MolSupplier {
|
||||
d_molpos; // vector of positions in the file for molecules
|
||||
std::vector<int> d_lineNums;
|
||||
STR_VECT d_props; // vector of property names
|
||||
bool d_cacheMolecules = false;
|
||||
std::vector<std::optional<std::shared_ptr<RWMol>>> d_molCache;
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
std::mutex d_readMutex;
|
||||
std::mutex d_cacheMutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TDTMolSupplierParams {
|
||||
@@ -341,26 +562,22 @@ class RDKIT_FILEPARSERS_EXPORT TDTMolSupplier : public MolSupplier {
|
||||
/**************************************************************************
|
||||
* Lazy file parser for TDT files, similar to the lazy SD
|
||||
* file parser above
|
||||
* - As an when new molecules are read using "next" their
|
||||
* - When new molecules are read using "next()" their
|
||||
* positions in the file are noted.
|
||||
* - A call to the "length" will automatically parse the entire
|
||||
* file and cache all the mol block positions
|
||||
* - A call to "length()" will automatically parse the entire
|
||||
* file and store all the mol block positions
|
||||
* - [] operator is used to access a molecule at "idx", calling
|
||||
* next following this will result in the next molecule after
|
||||
* next() following this will result in the next molecule after
|
||||
* "idx"
|
||||
***************************************************************************/
|
||||
public:
|
||||
using iterator = RandomAccessSupplierIter<TDTMolSupplier>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
|
||||
/*!
|
||||
* \param fileName - the name of the TDT file
|
||||
* \param nameRecord - property name for the molecule name.
|
||||
* If empty (the default), the name defaults to be empty
|
||||
* \param confId2D - if >=0 and 2D coordinates are provided, the 2D
|
||||
* structure (depiction) in the input will be read into the
|
||||
* corresponding conformer id.
|
||||
* \param confId3D - if >=0 and 3D coordinates are provided, the 3D
|
||||
* structure (depiction) in the input will be read into the
|
||||
* corresponding conformer id.
|
||||
* \param sanitize - if true sanitize the molecule before returning it
|
||||
* \param params - TDTMolSupplierParams object controlling how the file
|
||||
* itself and the individual records are parsed.
|
||||
*/
|
||||
explicit TDTMolSupplier(
|
||||
const std::string &fileName,
|
||||
@@ -378,6 +595,8 @@ class RDKIT_FILEPARSERS_EXPORT TDTMolSupplier : public MolSupplier {
|
||||
bool atEnd() override;
|
||||
void moveTo(unsigned int idx);
|
||||
std::unique_ptr<RWMol> operator[](unsigned int idx);
|
||||
std::shared_ptr<RWMol> getShared(unsigned int idx);
|
||||
|
||||
/*! \brief returns the text block for a particular item
|
||||
*
|
||||
* \param idx - which item to return
|
||||
@@ -385,6 +604,14 @@ class RDKIT_FILEPARSERS_EXPORT TDTMolSupplier : public MolSupplier {
|
||||
std::string getItemText(unsigned int idx);
|
||||
unsigned int length();
|
||||
|
||||
iterator begin() { return iterator(this); }
|
||||
iterator end() { return iterator(this, length()); }
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
|
||||
void setCaching(bool val) { d_cacheMolecules = val; }
|
||||
bool getCaching() const { return d_cacheMolecules; }
|
||||
|
||||
private:
|
||||
bool advanceToNextRecord();
|
||||
void checkForEnd();
|
||||
@@ -397,6 +624,12 @@ class RDKIT_FILEPARSERS_EXPORT TDTMolSupplier : public MolSupplier {
|
||||
std::vector<std::streampos>
|
||||
d_molpos; // vector of positions in the file for molecules
|
||||
TDTMolSupplierParams d_params;
|
||||
bool d_cacheMolecules = false;
|
||||
std::vector<std::optional<std::shared_ptr<RWMol>>> d_molCache;
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
std::mutex d_readMutex;
|
||||
std::mutex d_cacheMutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef RDK_BUILD_MAEPARSER_SUPPORT
|
||||
@@ -435,6 +668,7 @@ class RDKIT_FILEPARSERS_EXPORT MaeMolSupplier : public MolSupplier {
|
||||
bool atEnd() override;
|
||||
void moveTo(unsigned int idx);
|
||||
std::unique_ptr<RWMol> operator[](unsigned int idx);
|
||||
|
||||
unsigned int length();
|
||||
|
||||
void close() override { dp_sInStream.reset(); }
|
||||
|
||||
@@ -62,6 +62,10 @@ void SDMolSupplier::init() {
|
||||
ForwardSDMolSupplier::init();
|
||||
d_len = -1;
|
||||
d_last = 0;
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
d_molCache.clear();
|
||||
}
|
||||
|
||||
void SDMolSupplier::setData(const std::string &text) {
|
||||
@@ -195,6 +199,9 @@ std::unique_ptr<RWMol> SDMolSupplier::next() {
|
||||
|
||||
std::string SDMolSupplier::getItemText(unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
unsigned int holder = d_last;
|
||||
moveTo(idx);
|
||||
std::streampos begP = d_molpos[idx];
|
||||
@@ -218,7 +225,6 @@ std::string SDMolSupplier::getItemText(unsigned int idx) {
|
||||
|
||||
void SDMolSupplier::moveTo(unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
|
||||
// dp_inStream->seekg() is called for all idx values
|
||||
// and earlier calls to next() may have put the stream into a bad state
|
||||
dp_inStream->clear();
|
||||
@@ -256,9 +262,43 @@ void SDMolSupplier::moveTo(unsigned int idx) {
|
||||
|
||||
std::unique_ptr<RWMol> SDMolSupplier::operator[](unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
// std::cerr << "get molecule with index " << idx << std::endl;
|
||||
// get the molecule with index idx
|
||||
moveTo(idx);
|
||||
return next();
|
||||
auto res = next();
|
||||
return res;
|
||||
}
|
||||
|
||||
std::shared_ptr<RWMol> SDMolSupplier::getShared(unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
if (d_cacheMolecules) {
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
if (d_molCache.size() > idx && d_molCache[idx]) {
|
||||
return d_molCache[idx].value();
|
||||
}
|
||||
}
|
||||
std::shared_ptr<RWMol> res;
|
||||
{
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
// get the molecule with index idx
|
||||
moveTo(idx);
|
||||
res.reset(next().release());
|
||||
}
|
||||
if (d_cacheMolecules) {
|
||||
if (d_molCache.size() <= idx) {
|
||||
constexpr unsigned int molCacheAllocChunkSize = 1000;
|
||||
d_molCache.resize(idx + molCacheAllocChunkSize);
|
||||
}
|
||||
d_molCache[idx] = res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int SDMolSupplier::length() {
|
||||
|
||||
@@ -66,6 +66,10 @@ void SmilesMolSupplier::init() {
|
||||
d_line = -1;
|
||||
d_molpos.clear();
|
||||
d_lineNums.clear();
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
d_molCache.clear();
|
||||
}
|
||||
|
||||
void SmilesMolSupplier::setData(const std::string &text,
|
||||
@@ -175,7 +179,7 @@ std::unique_ptr<RWMol> SmilesMolSupplier::processLine(std::string inLine) {
|
||||
if (d_props.size() > col) {
|
||||
pname = d_props[col];
|
||||
}
|
||||
if(pname.empty()){
|
||||
if (pname.empty()) {
|
||||
pname = "Column_";
|
||||
pname += std::to_string(col);
|
||||
}
|
||||
@@ -454,6 +458,9 @@ std::unique_ptr<RWMol> SmilesMolSupplier::next() {
|
||||
std::unique_ptr<RWMol> SmilesMolSupplier::operator[](unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
// ---------
|
||||
// move to the appropriate location in the file:
|
||||
// ---------
|
||||
@@ -466,6 +473,37 @@ std::unique_ptr<RWMol> SmilesMolSupplier::operator[](unsigned int idx) {
|
||||
|
||||
return res;
|
||||
}
|
||||
std::shared_ptr<RWMol> SmilesMolSupplier::getShared(unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
if (d_cacheMolecules) {
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
if (d_molCache.size() > idx && d_molCache[idx]) {
|
||||
return d_molCache[idx].value();
|
||||
}
|
||||
}
|
||||
// get the molecule with index idx
|
||||
std::shared_ptr<RWMol> res;
|
||||
{
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
moveTo(idx);
|
||||
res.reset(next().release());
|
||||
}
|
||||
if (d_cacheMolecules) {
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
if (d_molCache.size() <= idx) {
|
||||
constexpr unsigned int molCacheAllocChunkSize = 1000;
|
||||
d_molCache.resize(idx + molCacheAllocChunkSize);
|
||||
}
|
||||
d_molCache[idx] = res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
//
|
||||
|
||||
@@ -104,6 +104,11 @@ void TDTMolSupplier::init() {
|
||||
d_len = -1;
|
||||
d_last = 0;
|
||||
d_line = 0;
|
||||
d_molpos.clear();
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
d_molCache.clear();
|
||||
}
|
||||
|
||||
void TDTMolSupplier::setData(const std::string &text,
|
||||
@@ -311,6 +316,9 @@ std::unique_ptr<RWMol> TDTMolSupplier::next() {
|
||||
|
||||
std::string TDTMolSupplier::getItemText(unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
unsigned int holder = d_last;
|
||||
moveTo(idx);
|
||||
std::streampos begP = d_molpos[idx];
|
||||
@@ -372,11 +380,43 @@ void TDTMolSupplier::moveTo(unsigned int idx) {
|
||||
|
||||
std::unique_ptr<RWMol> TDTMolSupplier::operator[](unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
// get the molecule with index idx
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
moveTo(idx);
|
||||
return next();
|
||||
}
|
||||
|
||||
std::shared_ptr<RWMol> TDTMolSupplier::getShared(unsigned int idx) {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
if (d_cacheMolecules) {
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
if (d_molCache.size() > idx && d_molCache[idx]) {
|
||||
return d_molCache[idx].value();
|
||||
}
|
||||
}
|
||||
// get the molecule with index idx
|
||||
std::shared_ptr<RWMol> res;
|
||||
{
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_readMutex);
|
||||
#endif
|
||||
moveTo(idx);
|
||||
res.reset(next().release());
|
||||
}
|
||||
if (d_cacheMolecules) {
|
||||
#ifdef RDK_BUILD_THREADSAFE_SSS
|
||||
const std::lock_guard<std::mutex> guard(d_cacheMutex);
|
||||
#endif
|
||||
if (d_molCache.size() <= idx) {
|
||||
constexpr unsigned int molCacheAllocChunkSize = 1000;
|
||||
d_molCache.resize(idx + molCacheAllocChunkSize);
|
||||
}
|
||||
d_molCache[idx] = res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
unsigned int TDTMolSupplier::length() {
|
||||
PRECONDITION(dp_inStream, "no stream");
|
||||
// return the number of mol blocks in the sdfile
|
||||
|
||||
506
Code/GraphMol/FileParsers/fileParsersIterTest.cpp
Normal file
506
Code/GraphMol/FileParsers/fileParsersIterTest.cpp
Normal file
@@ -0,0 +1,506 @@
|
||||
//
|
||||
// Copyright (C) 2026 Greg Landrum and other RDKit contributors
|
||||
//
|
||||
// @@ All Rights Reserved @@
|
||||
// This file is part of the RDKit.
|
||||
// The contents are covered by the terms of the BSD license
|
||||
// which is included in the file license.txt, found at the root
|
||||
// of the RDKit source tree.
|
||||
//
|
||||
#include <catch2/catch_all.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <execution>
|
||||
#include <ranges>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
|
||||
#include <GraphMol/RDKitBase.h>
|
||||
#include "MolSupplier.h"
|
||||
#include <GraphMol/SmilesParse/SmilesWrite.h>
|
||||
#include <GraphMol/SmilesParse/SmilesParse.h>
|
||||
#include <GraphMol/Substruct/SubstructMatch.h>
|
||||
|
||||
static const std::string rdbase = getenv("RDBASE");
|
||||
|
||||
using namespace RDKit;
|
||||
|
||||
namespace {
|
||||
unsigned int countAtoms(const std::shared_ptr<RWMol> &mol) {
|
||||
REQUIRE(mol);
|
||||
return mol->getNumAtoms();
|
||||
}
|
||||
size_t molPtr(const std::shared_ptr<RWMol> &mol) { return (size_t)mol.get(); }
|
||||
} // namespace
|
||||
|
||||
template <typename Supplier>
|
||||
void iterTest(Supplier &reader, size_t len) {
|
||||
CHECK(reader.length() == len);
|
||||
std::vector<unsigned int> expected;
|
||||
expected.reserve(reader.length());
|
||||
for (unsigned int i = 0; i < reader.length(); ++i) {
|
||||
expected.push_back(reader[i]->getNumAtoms());
|
||||
}
|
||||
std::vector<unsigned int> actual;
|
||||
std::ranges::transform(reader, std::back_inserter(actual), countAtoms);
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
|
||||
template <typename Supplier>
|
||||
void forwardIterTest(Supplier &reader, size_t len) {
|
||||
std::vector<unsigned int> actual;
|
||||
std::ranges::transform(reader, std::back_inserter(actual), countAtoms);
|
||||
CHECK(actual.size() == len);
|
||||
}
|
||||
|
||||
template <typename Supplier>
|
||||
void cacheTest(Supplier &reader, size_t len) {
|
||||
reader.setCaching(true);
|
||||
CHECK(reader.length() == len);
|
||||
std::vector<std::shared_ptr<RWMol>> mols(reader.length());
|
||||
std::copy(reader.begin(), reader.end(), mols.begin());
|
||||
REQUIRE(mols.size() == reader.length());
|
||||
std::vector<size_t> expected;
|
||||
std::ranges::transform(mols, std::back_inserter(expected), molPtr);
|
||||
std::vector<size_t> actual;
|
||||
std::ranges::transform(reader, std::back_inserter(actual), molPtr);
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("basic SDMolSupplier iteration") {
|
||||
std::string infile =
|
||||
rdbase + "/Code/GraphMol/FileParsers/test_data/NCI_aids_few.sdf";
|
||||
v2::FileParsers::SDMolSupplier reader(infile);
|
||||
SECTION("basics") { iterTest(reader, 16); }
|
||||
SECTION("with caching") { cacheTest(reader, 16); }
|
||||
SECTION("reverse iteration") {
|
||||
std::vector<unsigned int> expected;
|
||||
std::ranges::transform(std::begin(reader), std::end(reader),
|
||||
std::back_inserter(expected), countAtoms);
|
||||
std::vector<unsigned int> actual;
|
||||
std::ranges::transform(std::rbegin(reader), std::rend(reader),
|
||||
std::back_inserter(actual), countAtoms);
|
||||
std::ranges::reverse(actual);
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ForwardSDMolSupplier iteration") {
|
||||
std::string infile =
|
||||
rdbase + "/Code/GraphMol/FileParsers/test_data/NCI_aids_few.sdf";
|
||||
std::ifstream strm(infile);
|
||||
bool takeOwnership = false;
|
||||
v2::FileParsers::ForwardSDMolSupplier reader(&strm, takeOwnership);
|
||||
SECTION("basics") { forwardIterTest(reader, 16); }
|
||||
SECTION("error handling") {
|
||||
reader.next();
|
||||
CHECK_THROWS_AS(reader.begin(), ValueErrorException);
|
||||
}
|
||||
SECTION("pre-increment") {
|
||||
unsigned int i = 0;
|
||||
auto it = reader.begin();
|
||||
auto end = reader.end();
|
||||
while (it != end) {
|
||||
auto mol = *it;
|
||||
REQUIRE(mol);
|
||||
++it;
|
||||
++i;
|
||||
}
|
||||
CHECK(i == 16);
|
||||
}
|
||||
SECTION("post-increment") {
|
||||
unsigned int i = 0;
|
||||
auto it = reader.begin();
|
||||
auto end = reader.end();
|
||||
while (it != end) {
|
||||
auto mol = *it;
|
||||
REQUIRE(mol);
|
||||
it++;
|
||||
++i;
|
||||
}
|
||||
CHECK(i == 16);
|
||||
}
|
||||
}
|
||||
TEST_CASE("ForwardSDMolSupplier iteration with failing molecules") {
|
||||
std::string infile =
|
||||
rdbase + "/Code/GraphMol/FileParsers/test_data/good_bad_good_good.sdf";
|
||||
std::ifstream strm(infile);
|
||||
bool takeOwnership = false;
|
||||
v2::FileParsers::ForwardSDMolSupplier reader(&strm, takeOwnership);
|
||||
SECTION("basics") {
|
||||
std::vector<unsigned int> expected{6, 0, 6, 6};
|
||||
std::vector<unsigned int> actual;
|
||||
std::ranges::transform(
|
||||
reader, std::back_inserter(actual),
|
||||
[](const auto &mol) { return mol ? mol->getNumAtoms() : 0; });
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
SECTION("pre-increment") {
|
||||
unsigned int i = 0;
|
||||
auto it = reader.begin();
|
||||
auto end = reader.end();
|
||||
while (it != end) {
|
||||
auto mol = *it;
|
||||
if (i == 1) {
|
||||
CHECK(!mol);
|
||||
} else {
|
||||
CHECK(mol);
|
||||
}
|
||||
++it;
|
||||
++i;
|
||||
}
|
||||
CHECK(i == 4);
|
||||
}
|
||||
SECTION("post-increment") {
|
||||
unsigned int i = 0;
|
||||
auto it = reader.begin();
|
||||
auto end = reader.end();
|
||||
while (it != end) {
|
||||
auto mol = *it;
|
||||
if (i == 1) {
|
||||
CHECK(!mol);
|
||||
} else {
|
||||
CHECK(mol);
|
||||
}
|
||||
it++;
|
||||
++i;
|
||||
}
|
||||
CHECK(i == 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ForwardSDMolSupplier iteration with failing molecule at end") {
|
||||
std::string infile =
|
||||
rdbase + "/Code/GraphMol/FileParsers/test_data/good_bad_good_bad.sdf";
|
||||
std::ifstream strm(infile);
|
||||
bool takeOwnership = false;
|
||||
v2::FileParsers::ForwardSDMolSupplier reader(&strm, takeOwnership);
|
||||
SECTION("basics") {
|
||||
std::vector<unsigned int> expected{6, 0, 6, 0};
|
||||
std::vector<unsigned int> actual;
|
||||
std::ranges::transform(
|
||||
reader, std::back_inserter(actual),
|
||||
[](const auto &mol) { return mol ? mol->getNumAtoms() : 0; });
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
SECTION("pre-increment") {
|
||||
unsigned int i = 0;
|
||||
auto it = reader.begin();
|
||||
auto end = reader.end();
|
||||
while (it != end) {
|
||||
auto mol = *it;
|
||||
if (i % 2) {
|
||||
CHECK(!mol);
|
||||
} else {
|
||||
CHECK(mol);
|
||||
}
|
||||
++it;
|
||||
++i;
|
||||
}
|
||||
CHECK(i == 4);
|
||||
}
|
||||
SECTION("post-increment") {
|
||||
unsigned int i = 0;
|
||||
auto it = reader.begin();
|
||||
auto end = reader.end();
|
||||
while (it != end) {
|
||||
auto mol = *it;
|
||||
if (i % 2) {
|
||||
CHECK(!mol);
|
||||
} else {
|
||||
CHECK(mol);
|
||||
}
|
||||
it++;
|
||||
++i;
|
||||
}
|
||||
CHECK(i == 4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("cached SDMolSupplier error handling") {
|
||||
std::string infile =
|
||||
rdbase + "/Code/GraphMol/FileParsers/test_data/good_bad_good_bad.sdf";
|
||||
SECTION("basics") {
|
||||
v2::FileParsers::SDMolSupplier reader(infile);
|
||||
reader.setCaching(true);
|
||||
CHECK(reader.length() == 4);
|
||||
std::vector<std::shared_ptr<RWMol>> mols(reader.length());
|
||||
std::copy(reader.begin(), reader.end(), mols.begin());
|
||||
REQUIRE(mols.size() == reader.length());
|
||||
CHECK(mols[0]);
|
||||
CHECK(!mols[1]);
|
||||
CHECK(mols[2]);
|
||||
CHECK(!mols[3]);
|
||||
std::vector<size_t> expected;
|
||||
std::ranges::transform(mols, std::back_inserter(expected), molPtr);
|
||||
|
||||
// now use the cached versions:
|
||||
std::vector<std::shared_ptr<RWMol>> nmols(reader.length());
|
||||
std::copy(reader.begin(), reader.end(), nmols.begin());
|
||||
REQUIRE(nmols.size() == reader.length());
|
||||
CHECK(nmols[0]);
|
||||
CHECK(!nmols[1]);
|
||||
CHECK(nmols[2]);
|
||||
CHECK(!nmols[3]);
|
||||
// confirm the caching
|
||||
std::vector<size_t> actual;
|
||||
std::ranges::transform(nmols, std::back_inserter(actual), molPtr);
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("basic SmilesMolSupplier iteration") {
|
||||
std::string infile =
|
||||
rdbase + "/Code/GraphMol/FileParsers/test_data/first_200.tpsa.csv";
|
||||
v2::FileParsers::SmilesMolSupplierParams params;
|
||||
params.delimiter = ',';
|
||||
params.smilesColumn = 0;
|
||||
params.nameColumn = -1;
|
||||
v2::FileParsers::SmilesMolSupplier reader(infile, params);
|
||||
SECTION("basics") { iterTest(reader, 200); }
|
||||
SECTION("with caching") { cacheTest(reader, 200); }
|
||||
SECTION("reverse iteration") {
|
||||
std::vector<unsigned int> expected;
|
||||
std::ranges::transform(std::begin(reader), std::end(reader),
|
||||
std::back_inserter(expected), countAtoms);
|
||||
std::vector<unsigned int> actual;
|
||||
std::ranges::transform(std::rbegin(reader), std::rend(reader),
|
||||
std::back_inserter(actual), countAtoms);
|
||||
std::ranges::reverse(actual);
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("cached SmilesMolSupplier error handling") {
|
||||
v2::FileParsers::SmilesMolSupplierParams params;
|
||||
params.delimiter = ',';
|
||||
params.smilesColumn = 0;
|
||||
params.nameColumn = -1;
|
||||
std::string data = R"SMI(smiles,is_valid
|
||||
CCO,1
|
||||
CFC,0
|
||||
CCN,1
|
||||
c1cc1,0
|
||||
c1cc,0
|
||||
)SMI";
|
||||
SECTION("basics") {
|
||||
v2::FileParsers::SmilesMolSupplier reader;
|
||||
reader.setData(data, params);
|
||||
reader.setCaching(true);
|
||||
CHECK(reader.length() == 5);
|
||||
std::vector<std::shared_ptr<RWMol>> mols(reader.length());
|
||||
std::copy(reader.begin(), reader.end(), mols.begin());
|
||||
REQUIRE(mols.size() == reader.length());
|
||||
CHECK(mols[0]);
|
||||
CHECK(!mols[1]);
|
||||
CHECK(mols[2]);
|
||||
CHECK(!mols[3]);
|
||||
CHECK(!mols[4]);
|
||||
std::vector<size_t> expected;
|
||||
std::ranges::transform(mols, std::back_inserter(expected), molPtr);
|
||||
|
||||
// now use the cached versions:
|
||||
std::vector<std::shared_ptr<RWMol>> nmols(reader.length());
|
||||
std::copy(reader.begin(), reader.end(), nmols.begin());
|
||||
REQUIRE(nmols.size() == reader.length());
|
||||
CHECK(nmols[0]);
|
||||
CHECK(!nmols[1]);
|
||||
CHECK(nmols[2]);
|
||||
CHECK(!nmols[3]);
|
||||
CHECK(!nmols[4]);
|
||||
// confirm the caching
|
||||
std::vector<size_t> actual;
|
||||
std::ranges::transform(nmols, std::back_inserter(actual), molPtr);
|
||||
CHECK(actual == expected);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(RDK_BUILD_THREADSAFE_SSS) && defined(__cpp_lib_execution)
|
||||
// NOTE: will only run in parallel on linux if TBB is installed
|
||||
TEST_CASE("parallel reads") {
|
||||
// there's likely no benefit from the parallelization here,
|
||||
// but we want to be sure that the mutexes are working correctly
|
||||
auto *rdbase = std::getenv("RDBASE");
|
||||
REQUIRE(rdbase);
|
||||
SECTION("sdf") {
|
||||
auto path = std::filesystem::path(rdbase) /
|
||||
"Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.sdf";
|
||||
REQUIRE(std::filesystem::exists(path));
|
||||
v2::FileParsers::SDMolSupplier reader1(path.string());
|
||||
std::vector<unsigned int> nAts1(reader1.length());
|
||||
std::transform(reader1.begin(), reader1.end(), nAts1.begin(), countAtoms);
|
||||
// std::sort(nAts1.begin(), nAts1.end());
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
constexpr unsigned int numIters = 20;
|
||||
for (unsigned int iter = 0; iter < numIters; ++iter) {
|
||||
v2::FileParsers::SDMolSupplier reader2(path.string());
|
||||
reader2.setCaching(true);
|
||||
std::vector<unsigned int> nAts2(reader1.length());
|
||||
std::transform(std::execution::par, reader2.begin(), reader2.end(),
|
||||
nAts2.begin(), countAtoms);
|
||||
REQUIRE(nAts1.size() == nAts2.size());
|
||||
REQUIRE(nAts1 == nAts2);
|
||||
}
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
std::cerr << "Read of " << reader1.length() << "x" << numIters
|
||||
<< " molecules took " << duration.count() << " ms" << std::endl;
|
||||
}
|
||||
SECTION("smiles") {
|
||||
auto path = std::filesystem::path(rdbase) /
|
||||
"Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.smi";
|
||||
REQUIRE(std::filesystem::exists(path));
|
||||
v2::FileParsers::SmilesMolSupplierParams params;
|
||||
params.delimiter = '\t';
|
||||
params.smilesColumn = 0;
|
||||
params.nameColumn = 1;
|
||||
params.titleLine = false;
|
||||
|
||||
v2::FileParsers::SmilesMolSupplier reader1(path.string(), params);
|
||||
std::vector<unsigned int> nAts1(reader1.length());
|
||||
std::transform(reader1.begin(), reader1.end(), nAts1.begin(), countAtoms);
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
constexpr unsigned int numIters = 20;
|
||||
for (unsigned int iter = 0; iter < numIters; ++iter) {
|
||||
v2::FileParsers::SmilesMolSupplier reader2(path.string(), params);
|
||||
reader2.setCaching(true);
|
||||
std::vector<unsigned int> nAts2(reader1.length());
|
||||
std::transform(std::execution::par, reader2.begin(), reader2.end(),
|
||||
nAts2.begin(), countAtoms);
|
||||
REQUIRE(nAts1 == nAts2);
|
||||
}
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
std::cerr << "Read of " << reader1.length() << "x" << numIters
|
||||
<< " molecules took " << duration.count() << " ms" << std::endl;
|
||||
}
|
||||
SECTION("TDT") {
|
||||
auto path = std::filesystem::path(rdbase) /
|
||||
"Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.tdt";
|
||||
REQUIRE(std::filesystem::exists(path));
|
||||
|
||||
v2::FileParsers::TDTMolSupplier reader1(path.string());
|
||||
std::vector<unsigned int> nAts1(reader1.length());
|
||||
std::transform(reader1.begin(), reader1.end(), nAts1.begin(), countAtoms);
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
constexpr unsigned int numIters = 20;
|
||||
for (unsigned int iter = 0; iter < numIters; ++iter) {
|
||||
v2::FileParsers::TDTMolSupplier reader2(path.string());
|
||||
reader2.setCaching(true);
|
||||
std::vector<unsigned int> nAts2(reader1.length());
|
||||
std::transform(std::execution::par, reader2.begin(), reader2.end(),
|
||||
nAts2.begin(), countAtoms);
|
||||
REQUIRE(nAts1 == nAts2);
|
||||
}
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
std::cerr << "Read of " << reader1.length() << "x" << numIters
|
||||
<< " molecules took " << duration.count() << " ms" << std::endl;
|
||||
}
|
||||
}
|
||||
TEST_CASE("benchmarking") {
|
||||
auto *rdbase = std::getenv("RDBASE");
|
||||
REQUIRE(rdbase);
|
||||
auto path = std::filesystem::path(rdbase) /
|
||||
"Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.smi";
|
||||
REQUIRE(std::filesystem::exists(path));
|
||||
v2::FileParsers::SmilesMolSupplierParams params;
|
||||
params.delimiter = '\t';
|
||||
params.smilesColumn = 0;
|
||||
params.nameColumn = 1;
|
||||
params.titleLine = false;
|
||||
v2::FileParsers::SmilesMolSupplier reader(path.string(), params);
|
||||
reader.setCaching(true);
|
||||
|
||||
SECTION("transform") {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
// prime the cache:
|
||||
std::vector<unsigned int> nAts1;
|
||||
std::transform(reader.begin(), reader.end(), std::back_inserter(nAts1),
|
||||
countAtoms);
|
||||
|
||||
double accum = 0.0;
|
||||
constexpr unsigned int numIters = 200;
|
||||
for (unsigned int iter = 0; iter < numIters; ++iter) {
|
||||
std::vector<unsigned int> nAts(reader.length());
|
||||
std::transform(std::execution::seq, reader.begin(), reader.end(),
|
||||
nAts.begin(),
|
||||
[](const auto mol) { return MolToSmiles(*mol).size(); });
|
||||
accum += nAts.size();
|
||||
}
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
std::cerr << "Base transform of " << reader.length() << "x" << numIters
|
||||
<< " molecules took " << duration.count() << " ms" << std::endl;
|
||||
CHECK(accum > 0);
|
||||
accum = 0.0;
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
for (unsigned int iter = 0; iter < numIters; ++iter) {
|
||||
std::vector<unsigned int> nAts(reader.length());
|
||||
std::transform(std::execution::par, reader.begin(), reader.end(),
|
||||
nAts.begin(),
|
||||
[](const auto mol) { return MolToSmiles(*mol).size(); });
|
||||
accum += nAts.size();
|
||||
}
|
||||
end = std::chrono::high_resolution_clock::now();
|
||||
duration =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
std::cerr << "Parallel transform of " << reader.length() << "x" << numIters
|
||||
<< " molecules took " << duration.count() << " ms" << std::endl;
|
||||
CHECK(accum > 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("views and filtered reads") {
|
||||
auto *rdbase = std::getenv("RDBASE");
|
||||
REQUIRE(rdbase);
|
||||
auto path = std::filesystem::path(rdbase) /
|
||||
"Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.sdf";
|
||||
REQUIRE(std::filesystem::exists(path));
|
||||
v2::FileParsers::SDMolSupplier reader1(path.string());
|
||||
SECTION("filters") {
|
||||
std::vector<unsigned int> nAts1(reader1.length());
|
||||
std::transform(reader1.begin(), reader1.end(), nAts1.begin(), countAtoms);
|
||||
constexpr unsigned int tgtSize = 15;
|
||||
auto nSmall =
|
||||
std::ranges::count_if(nAts1, [](const auto &v) { return v < tgtSize; });
|
||||
REQUIRE(nSmall > 0);
|
||||
auto filtered = reader1 | std::views::filter([](const auto &mol) {
|
||||
return mol->getNumAtoms() < tgtSize;
|
||||
});
|
||||
CHECK(std::distance(std::begin(filtered), std::end(filtered)) == nSmall);
|
||||
|
||||
// only read until we have a set number of molecules matching our filter:
|
||||
const unsigned int subsetSz = nSmall / 4;
|
||||
auto firstN = reader1 | std::views::filter([](const auto &mol) {
|
||||
return mol->getNumAtoms() < tgtSize;
|
||||
}) |
|
||||
std::views::take(subsetSz);
|
||||
// this doen't work and I don't understand why:
|
||||
// CHECK(std::distance(std::begin(firstN), std::end(firstN)) == subsetSz);
|
||||
std::vector<std::shared_ptr<RWMol>> mols;
|
||||
std::ranges::copy(firstN, std::back_inserter(mols));
|
||||
CHECK(mols.size() == subsetSz);
|
||||
}
|
||||
SECTION("substructure filter") {
|
||||
auto query = "c1ncncn1"_smiles;
|
||||
SubstructMatchParameters params;
|
||||
params.maxMatches = 1;
|
||||
auto firstN = reader1 |
|
||||
std::views::filter([&query, ¶ms](const auto &mol) {
|
||||
return SubstructMatch(*mol, *query, params).empty();
|
||||
}) |
|
||||
std::views::take(5);
|
||||
std::vector<std::shared_ptr<RWMol>> mols;
|
||||
std::ranges::copy(firstN, std::back_inserter(mols));
|
||||
CHECK(mols.size() == 5);
|
||||
}
|
||||
}
|
||||
80
Code/GraphMol/FileParsers/test_data/good_bad_good_bad.sdf
Normal file
80
Code/GraphMol/FileParsers/test_data/good_bad_good_bad.sdf
Normal file
@@ -0,0 +1,80 @@
|
||||
OK
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 5 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
3 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID>
|
||||
good1
|
||||
|
||||
$$$$
|
||||
Sanitization Error
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 5 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
1 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID>
|
||||
bad1
|
||||
|
||||
$$$$
|
||||
OK
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 5 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
3 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID>
|
||||
good2
|
||||
|
||||
$$$$
|
||||
too many bonds
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 6 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
3 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID> (4)
|
||||
Lig2
|
||||
|
||||
$$$$
|
||||
80
Code/GraphMol/FileParsers/test_data/good_bad_good_good.sdf
Normal file
80
Code/GraphMol/FileParsers/test_data/good_bad_good_good.sdf
Normal file
@@ -0,0 +1,80 @@
|
||||
OK
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 5 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
3 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID>
|
||||
good1
|
||||
|
||||
$$$$
|
||||
Sanitization Error
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 5 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
1 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID>
|
||||
bad2
|
||||
|
||||
$$$$
|
||||
OK
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 5 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
3 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID>
|
||||
good3
|
||||
|
||||
$$$$
|
||||
OK
|
||||
csChFnd70/05230312262D
|
||||
|
||||
6 5 0 0 0 0 0 0 0 0999 V2000
|
||||
1.2124 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 0.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
3.6373 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
2.4249 2.1000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0.0000 0.7000 0.0000 Y 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
4.8477 0.6988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 2 1 0 0 0 0
|
||||
2 3 1 0 0 0 0
|
||||
2 4 2 0 0 0 0
|
||||
3 5 1 0 0 0 0
|
||||
3 6 1 0 0 0 0
|
||||
M END
|
||||
> <ID> (4)
|
||||
good4
|
||||
|
||||
$$$$
|
||||
31213
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.mae
Normal file
31213
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.mae
Normal file
File diff suppressed because it is too large
Load Diff
20527
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.sdf
Normal file
20527
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.sdf
Normal file
File diff suppressed because it is too large
Load Diff
500
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.smi
Normal file
500
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.smi
Normal file
@@ -0,0 +1,500 @@
|
||||
C1CCO[C@@H](C1)ON2C(=O)CCC2=O ZINC00403244
|
||||
c1ccc(cc1)Cn2c(c(nn2)c3[nH]c4ccccc4n3)N ZINC00031867
|
||||
C1C(=O)[C@@H]2[C@@H](C=CS2)S(=O)(=O)N1 ZINC30714392
|
||||
C[C@@H]1Cn2c(c(c(=O)[nH]c2=O)c3ccccc3)O1 ZINC02028360
|
||||
C[C@@H](c1nncn1C)NC(=O)Nc2cccc(c2)Cl ZINC32934674
|
||||
C1C[C@@H]([NH2+]C1)n2[nH]c(=S)nn2 ZINC16952145
|
||||
c1cc(ccc1C2=NCC=CCO2)[N+](=O)[O-] ZINC01717366
|
||||
Cc1cc(nc(n1)SC)OCc2n[nH]c(=S)o2 ZINC05537581
|
||||
CCN(CC)C1=Nc2ccccc2-n3ccnc3C1 ZINC13214820
|
||||
C[C@@H]1CCCC[NH+]1Cc2nnnn2Nc3cccc(c3)[N+](=O)[O-] ZINC00804824
|
||||
Cc1cc(nc(n1)n2c3c(cn2)C(=O)CCC3)C ZINC02351349
|
||||
c1cc(oc1)C(=O)Nc2csnn2 ZINC01680566
|
||||
Cn1c(n[nH]c1=S)Cc2c3ccccc3c(=O)n(n2)C ZINC15919724
|
||||
CN(c1ccccc1)/C(=N/NC(=O)[C@H]2CCC(=O)N2)/S ZINC05549721
|
||||
[H]/N=C/1\\CC2(CC[NH+](CC2)C)c3c(nc([nH]3)COC)O1 ZINC20459262
|
||||
c1ccc(cc1)c2c(=S)n(c(=O)[nH]n2)c3ccc(c(c3)Cl)F ZINC03846921
|
||||
c1ccc2c(c1)CN(C(=[NH2+])C23CCOCC3)N ZINC01751973
|
||||
Cc1ccccc1[C@@H]2[C@@H]([C@@]23C(=NN=C3O)N)C#N ZINC06525698
|
||||
c1cc(ccc1c2ccc(o2)C=O)n3cnnn3 ZINC00336354
|
||||
CC(=O)SC ZINC02004049
|
||||
C/C(=N/Oc1cccc(n1)F)/c2ccccc2 ZINC19880407
|
||||
c1ccc(cc1)N/C=C(\\C2=NCCCCC2)/[N+](=O)[O-] ZINC12338436
|
||||
Cc1c(c(n[nH]1)O)n2c3ccccc3c(=O)c4c2cccc4 ZINC05261103
|
||||
C1Cc2c(onc2c3c4c(on3)CCC4)C1 ZINC01588238
|
||||
COC(=O)[C@@H]1CN(C(=O)N1)C(=O)CCc2ccccc2 ZINC05537267
|
||||
c1ccc2c(c1)-c3c4c(cccc4n[nH]3)C2=O ZINC04335977
|
||||
CC1=C(C[S@@](=O)N(C1)c2nc(sn2)SC)C ZINC04290546
|
||||
CCc1c(sc(=[N+](C)C)s1)S ZINC14628732
|
||||
Cc1csc(n1)CCNc2c(cccn2)C#N ZINC40071566
|
||||
CC1([C@@H]2[C@@H](C[NH+]1C)[C@@H](NC(=[NH2+])N2)[NH3+])C ZINC16911528
|
||||
CC1=C[n+]2ccccc2Sc3c1cccc3 ZINC01648649
|
||||
CCn1c(=O)n-2c(n1)COc3c2cccc3 ZINC13362299
|
||||
CC1(CC(=O)/C(=C/[C@@H]2CCN=C2S)/C(=O)N1)C ZINC05734401
|
||||
CC1=CNC(=O)CC(C1)(C)C ZINC01582100
|
||||
Cc1c(nc2ccccc2n1)NCc3[nH]ncn3 ZINC32593071
|
||||
c1ccc2c(c1)C(=O)N(C(=CO2)Cl)CCCCCl ZINC22012349
|
||||
C1CS[S@@](=O)O1 ZINC04692300
|
||||
Cc1c(n2c(=O)n(c(=O)n2c1=O)c3ccccc3)C ZINC01587443
|
||||
c1ccc(cc1)CC(=O)NN2[C@@H]([C@@H](C2=O)Cl)c3ccccc3 ZINC05838349
|
||||
CCc1nc(on1)Cn2c3ccccc3ncc2=O ZINC12985807
|
||||
CC1=C([NH2+]Cc2c1cccc2)/N=C(/NC(=O)c3ccccc3)\\[S-] ZINC00031959
|
||||
C1CSC[C@@]12C(=O)NC(=O)N2 ZINC03434821
|
||||
C[NH+](C)C=C1C=CC=C1 ZINC00967188
|
||||
COc1c(cc2c-3c1COc4c3c(cc(c4)O)CC2)O ZINC31168289
|
||||
c1ccc2c(c1)c(=O)c3=c(c2=O)sc(c(s3)C#N)C#N ZINC01755317
|
||||
Cc1cc([n+]2c(n1)CCN2c3ccccc3)C ZINC03111478
|
||||
C1[C@@H]2C=CC(=O)[C@H](O1)O2 ZINC00078169
|
||||
Cc1[nH]c2c3ccccc3sc2n1 ZINC00241929
|
||||
Cc1cnc(c2[n+]1c(nn2C)[N-]c3ccccc3)C ZINC00387689
|
||||
Cn1c(ncn1)CCc2ccccc2 ZINC01633222
|
||||
CC1([C@@]([N+](=[N+]1[O-])[O-])(c2ccccc2)Br)C ZINC13777563
|
||||
Cc1c2c(con2)c(nn1)c3ccccn3 ZINC01403003
|
||||
c1ccc2c(c1)cc(c(=[NH2+])o2)c3[nH]c4ccccc4n3 ZINC04721566
|
||||
Cc1ccc(cc1)/N=C\\2/CNC(=O)NC2=O ZINC00185656
|
||||
COn1c2ccccc2[n+](=O)c(c1[O-])c3ccco3 ZINC20476957
|
||||
CC1(O[C@@H]2CCC(=O)[C@@H]2O1)C ZINC22014840
|
||||
c1ccn2c(c1)c(c(=S)[nH]c2=O)C#N ZINC08133017
|
||||
c1cc2c(c3c1non3)nns2 ZINC01279110
|
||||
COc1ccc(cc1OC)N2C=NN3C2=NNc4c3[nH]c5c4cccc5 ZINC15226578
|
||||
c1cc2c(cc1N)COCO2 ZINC04272152
|
||||
c1cn(nc1C(=O)N)[C@@H]2[C@H]([C@@H]([C@@H](O2)CO)O)O ZINC05208104
|
||||
Cc1ccc(cc1)/C=C\\2/C(=N[C@@H](C(=O)N2)C)O ZINC02087495
|
||||
Cc1c(c(on1)c2c(nns2)C)C(=O)[O-] ZINC00158954
|
||||
CCCC1=NN([C@@H]2[C@@H]1N=C(NC2=O)Cc3ccc(cc3)N)C ZINC21983240
|
||||
CCOC(=O)c1c([nH]c(n1)[C@@H]2[C@H]([C@@H]([C@@H](O2)CO)O)O)O ZINC17142118
|
||||
CC[C@@](c1ccncc1Br)(C2=NC(CO2)(C)C)O ZINC05010471
|
||||
c1ccc(c(c1)/C=N\\[C@@H]2CONC2=O)O ZINC16980124
|
||||
c1ccc(cc1)C(=O)C[n+]2c(scn2)N ZINC03122070
|
||||
c1ccc(c(c1)/C=N/NC(=O)COC2=CCCC2)Cl ZINC00222804
|
||||
c1cc(c(c(c1)Cl)c2csc(nc2=O)N)Cl ZINC08782861
|
||||
Cc1cc2cc(ccc2[nH]1)O ZINC02571370
|
||||
CC1=[N+]([C@@]2(CCc3c(non3)[C@@]2(C1)O)[NH3+])[O-] ZINC19325434
|
||||
Cn1cc(cn1)c2ccnc(n2)N(C)Cc3nc(on3)C4CCC4 ZINC23506850
|
||||
c1ccc2c(c1)C[C@@H]3C[C@H]2OC(=O)N3 ZINC01589294
|
||||
CC1=C(N=C(C1(C)C)C)C ZINC13281730
|
||||
c1ccc2=[NH+][C@@H]3C(=O)C=CC=C3C=c2c1 ZINC04517670
|
||||
c1cc(sc1)[C@@H]2CC(=O)CS2 ZINC00149349
|
||||
Cc1cc(n2c(n1)ncn2)OS(=O)(=O)c3ccc(cc3)NC(=O)C ZINC02057760
|
||||
c1cc(cc(c1)[N+](=O)[O-])N2CNC=[NH+]N=C2 ZINC28294495
|
||||
CC/N=C(/C(C#N)C#N)\\SCc1ccncc1 ZINC06380277
|
||||
Cc1ccc2c(c1)[C@@H]3[C@@H]4CC[C@@H](C4)[C@@H]3[S@@](=O)N2 ZINC04512174
|
||||
c1cnoc1c2nnc(o2)N ZINC26423850
|
||||
c1cc(c(cc1O)O)/C=N\\Nc2nccs2 ZINC04482795
|
||||
c1ccc(c(c1)N2C(=C([C@@H](C(=C2O)C#N)O)C#N)N)Br ZINC00494677
|
||||
CCOC(=O)Nc1csnn1 ZINC01718899
|
||||
c1ccc(cc1)n2c(nnn2)Cn3nc(nn3)c4ccsc4 ZINC09504077
|
||||
CCOP(=O)(CO[C@@H]1CCCCO1)OCC ZINC16125103
|
||||
CCn1c(nnn1)NC(=O)NCc2[nH+]ccn2Cc3ccccc3 ZINC23158989
|
||||
Cc1nnnn1c2cc3c(s2)CCCC3 ZINC04917484
|
||||
C1[C@@H]([C@@H](CS1(=O)=O)SC(=[NH2+])N)O ZINC04336692
|
||||
C(=O)([C@@]([N+](=O)[O-])(Cl)Br)N ZINC04595350
|
||||
c1ccc(cc1)C2=CN3C=CS[C@@H]3N2CCO ZINC01578471
|
||||
c1cc2c(nc1)sc(=O)o2 ZINC05331463
|
||||
C1CC[NH+]2CSCCC[C@@H]2C1 ZINC01580316
|
||||
C1[NH+]2CN3CN1CP(=S)(C2)C3 ZINC19321765
|
||||
CC(C)[C@H]1C(=N[C@@H](C(=N1)OC)Cc2cc(ccc2F)F)OC ZINC21987106
|
||||
Cc1nnc(o1)CNC(=O)Cc2ccc(cc2)SC ZINC19740639
|
||||
c1c(c([nH]n1)n2cnnn2)C(=O)[O-] ZINC05642230
|
||||
C1C(=C(N2C(=O)CSC2=C1C(=O)N)N)C#N ZINC00201398
|
||||
c1ccc2c(c1)nnn2CN3CC[C@@H](O3)C#N ZINC05520574
|
||||
Cc1ccc(cc1)c2ncc(o2)Sc3[nH]c(=O)cc(n3)C ZINC35681810
|
||||
CN(C)C(F)F ZINC19615840
|
||||
Cc1nc(nn1C(C)C)NC(=O)NCc2coc(n2)c3ccccc3 ZINC20999088
|
||||
COc1cc2c(cc1OC)C[n+]3ccccc3C2 ZINC01596111
|
||||
c1cc(sc1)CCn2cnnc2S ZINC12505079
|
||||
CCOC(=O)c1c(nc(c(n1)C)c2c[nH]c3c2cccc3)NC(=O)C ZINC01424411
|
||||
Cc1nn2cc(nc2s1)Cn3cnc4ccncc4c3=O ZINC32587233
|
||||
CC(=O)N1CCO[C@@H]1c2c(c(c(s2)Cl)Cl)Cl ZINC00523301
|
||||
COP(=O)([C@@H]1C[C@H]2C[C@@H]1C=C2)OC ZINC05051728
|
||||
CC(=O)/N=C\\1/NC(=O)/C(=C/N2CCCCC2)/S1 ZINC30783294
|
||||
CC1([C@@]2(NC(=O)[C@]1(C([C@@H](O2)c3ccccc3)(C#N)C#N)C#N)C)C ZINC35323783
|
||||
c1ccc2c(c1)c(nnn2)OC3CCN(CC3)C(=O)CCC(=O)[O-] ZINC21176605
|
||||
C/N=C/1\\c2ccccc2[C@]3([C@@H]1[NH+]3C)c4ccccc4 ZINC16920394
|
||||
c1cc(cc(c1)c2c3ccoc3ccn2)CO ZINC32590156
|
||||
c1ccc2c(c1)[nH]c(n2)NNC3=C4C=CC[C@@H]4C3 ZINC02646901
|
||||
C[S@@](=O)CC1=NC(=N)N=C1C[S@@](=O)C ZINC05567373
|
||||
C=NC1C=CCC=C1 ZINC01764765
|
||||
CNC1=C[N+](=C(c2cc(ccc2N1)Cl)c3ccccc3)[O-] ZINC13813184
|
||||
C1Cc2c(sc(n2)N)C(=O)NC1 ZINC00243040
|
||||
c1ccc2c(c1)-c3ccccc3S(=O)(=O)N2 ZINC00096040
|
||||
c1ccc(c(c1)[C@@H]2NC(=NO2)CC(=O)N3CCCC3)O ZINC00138607
|
||||
c1ccc(cc1)Cn2c(=O)ccc3c2n[nH]n3 ZINC03852551
|
||||
c1ccc(c(c1)c2nc(on2)Cn3c(nnn3)N)Cl ZINC19223392
|
||||
CC1=C/C(=C/2\\NCC=[NH+]2)/C(=O)[NH+]=N1 ZINC38342386
|
||||
C1N(COCN1[N+](=O)[O-])[N+](=O)[O-] ZINC05002672
|
||||
COCc1cn(nn1)[C@H]2CO[C@H]3[C@@H]2OC[C@H]3O ZINC04260853
|
||||
Cn1/c(=N/C(=S)Nc2ccccc2)/n(nn1)Cc3ccccc3 ZINC17104998
|
||||
c1ccc(cc1)C2=NNC(=[NH2+])SC2 ZINC05773132
|
||||
CN(C)C1C(=O)C(=[N+](C)C)C1=O ZINC16953003
|
||||
C[C@@H]1C=C(C(=O)c2ccccc2N1S(=O)(=O)C)Br ZINC05022953
|
||||
COC1(C=NN=C2N1C=NN2)OC ZINC17176662
|
||||
C/C(=N\\Oc1c2ccccc2ncn1)/SC ZINC15224080
|
||||
CC1=C(/C(=C\\2/C(=NNS2)C)/N=N1)C(=O)OC ZINC13125377
|
||||
Cc1nnc2n1c(=O)/c(=C\\C(=O)OC)/[nH]2 ZINC17949010
|
||||
Cc1c(c(n(n1)Cc2csc(n2)c3ccccc3)C)[N+](=O)[O-] ZINC05797520
|
||||
c1ccc(cc1)n2c(=O)cc3n(c2=O)CCN3 ZINC00398488
|
||||
CCOC(=O)n1c2c([nH][nH]n1C(=O)OCC)n(c(=O)n(c2=O)C)C ZINC01871901
|
||||
C[NH+]1CCC2(CC1)NC(=O)C3CC[NH+](CC3=N2)C ZINC03888336
|
||||
c1ccc2c(c1)cc3n(c2=O)CCCCC3 ZINC15829272
|
||||
Cc1c(ncc(c1c2ccc(c(c2O)OC)OC)C#N)C ZINC13281575
|
||||
CC(C)(C)C1=C([N+](=[NH2+])c2n[nH]c(=S)n2[N-]1)O ZINC26443358
|
||||
CC(=CC[C@@H]1[C@]([C@]2([C@@H](C(=O)CC[C@@]2(CS1)O)OC)O)(C)O)C ZINC31164256
|
||||
Cn1cc(c(c1[C@@H]2CCCO2)C(=O)[O-])c3ccccc3 ZINC15778916
|
||||
c1ccc-2c(c1)C[n+]3c2cccc3 ZINC01870630
|
||||
c1ccc(c(c1)N)SC[C@@H](COc2cccc(n2)C(F)(F)F)O ZINC00117316
|
||||
[H]/N=C\\1/C(=O)C=C(NC1=O)ONCCO ZINC01668471
|
||||
CCOC(=O)c1c([nH]c(=O)[nH]1)Cn2ccnc2 ZINC19925870
|
||||
C1C[NH+]=CC(C=[NH+]1)[N+](=O)[O-] ZINC01734891
|
||||
c1ccc(cc1)/N=c/2\\[nH]n(c(=S)n2c3ccccc3)CCC(=O)[O-] ZINC00234993
|
||||
Cc1c(snn1)c2[nH]c3ccccc3n2 ZINC11535685
|
||||
c1cn[nH]n1 ZINC04807252
|
||||
CC1=C2C(=O)O[C@@H]([C@@]2(CCC1)C)c3ccoc3 ZINC00265495
|
||||
c1cc(cnc1)n2ccnc2 ZINC04227998
|
||||
CC1(CC(=O)C(=C/N=C(/c2ccccc2)\\S)C(=O)C1)C ZINC05734408
|
||||
c1cc2c(nc1)CC(=O)N2 ZINC13283774
|
||||
c1cc2cc(cc(c2nc1)NCn3cnc(n3)[N+](=O)[O-])Br ZINC00032833
|
||||
CC(=O)O[C@@H]1[C@@H]2CC[C@@H](C2)[C@@H]1[N+](=O)[O-] ZINC05081834
|
||||
CCOC(=O)n1cnnn1 ZINC21999832
|
||||
c1ccc(cc1)c2cc(no2)c3ncon3 ZINC01245981
|
||||
CCOC(=O)c1c(n(nn1)CC2(COC2)C)C(=O)Nc3ccccc3 ZINC15767578
|
||||
CC[C@@]1(N=N/C(=N\\c2ccccc2)/O1)C ZINC05337261
|
||||
Cc1c(non1)/[NH+]=C/c2ccccc2[O-] ZINC03088859
|
||||
C1CC=C([C@@H](C1)S(=O)(=O)CC#N)[NH+]2CCOCC2 ZINC05282762
|
||||
COc1ccc2c(c1)CC[C@@H]3[C@@H]2O[C@@H](O3)c4cccnc4 ZINC05487850
|
||||
c1cc2cccc3c2c(c1)C(=O)N3 ZINC00162129
|
||||
c1ccc2c(c1)NS(=O)(=O)N2 ZINC00009186
|
||||
CCOC(=O)c1c([nH]cc1O)C ZINC13465680
|
||||
c1ccc2c(c1)C[C@@H]([C@@H]2Sc3ncccn3)O ZINC05776525
|
||||
c1c(nc([nH]c1=O)SC2=N[C@@H](C[C@@H](C2)O)N)N ZINC17193121
|
||||
C1C=C(O[C@@H]2[C@@H]1OC(=O)N2)C#N ZINC04267562
|
||||
C[C@@]12CCCC[NH+]1CCC3=C2CCC3 ZINC05559913
|
||||
CC(C)(C)C\\1=NN=N/C1=C/Nc2ccc(cc2)F ZINC05293058
|
||||
CN(C)c1ccc(cc1)c2ncnn2c3nc[nH]n3 ZINC22146391
|
||||
C1CCN2[C@@H](C1)C=CC3=C2CCCC3=O ZINC22003183
|
||||
c1(c(non1)Sc2c(non2)[N+](=O)[O-])[N+](=O)[O-] ZINC04343707
|
||||
C=CCC[C@@H](c1ccccc1)/[NH+]=N/C(=O)N ZINC16999204
|
||||
Cc1c(noc1c2ccc(cc2)F)Cn3cnc(n3)C#N ZINC14144321
|
||||
c1ccc2c(c1)C3=C(S2(=O)=O)NCCS3 ZINC20476634
|
||||
Cc1cc(=O)c(c(o1)Nc2nnns2)C(=O)C ZINC27027625
|
||||
Cc1cnc(cn1)C(=O)OCc2nnc(o2)C ZINC28648709
|
||||
CC1=CC(=O)N[C@@H](N1)NN ZINC19168956
|
||||
CC1=C(OP(=O)(O1)n2ccnc2)C ZINC01566125
|
||||
CC(C)Cn1cncc1CNc2c(nccn2)C#N ZINC32598442
|
||||
CC(=O)[C@@H]1C[C@@]2(C(=O)c3ccccc3N2O1)c4ccccc4 ZINC05712628
|
||||
COC(=O)c1c(c(n2c1oc3c2cccc3)Cl)C(=O)OC ZINC00313544
|
||||
CC1=CNNc2c1cccc2 ZINC01683958
|
||||
CC(=O)C1=CCC[C@@H]2CC[C@H]1[NH2+]2 ZINC04098885
|
||||
Cc1nc(on1)COC(=O)C[C@@H]2CCS(=O)(=O)C2 ZINC36692474
|
||||
c1nc2c(c(n1)N)[nH]nc2[C@@H]3C[C@@H]([C@H](O3)CO)O ZINC16953432
|
||||
c1cn2ccnc2cn1 ZINC12356946
|
||||
Cc1ccc(n1c2nc([nH]n2)[S-])C ZINC13110826
|
||||
C[C@@]1(CSC(=[NH+]1)Nc2c([nH]cn2)C(=O)Nc3ccccc3)O ZINC04818365
|
||||
C1CC[NH+](CC1)/C=C/C=C/C=[N+]2CCCCC2 ZINC01623366
|
||||
C(C(=O)OCS(=O)(=O)[O-])Br ZINC05048631
|
||||
C[C@@H]1Sc2c(=S)ssc2S1 ZINC05920112
|
||||
c1ccc(cc1)c2c(cc3ccccc3[o+]2)O ZINC01686405
|
||||
c1ccnc(c1)c2c3c(cc(cn3)C(F)(F)F)no2 ZINC03134964
|
||||
CC1=C([C@@H]2CCO[C@@H]2O1)C(=O)OC ZINC01590962
|
||||
CSc1c(c(c(s1)C#N)N)[n+]2ccccc2 ZINC05037757
|
||||
CC1=Nc2ccccc2NC(=C1c3ccc(c(c3)OC)OC)N ZINC13637103
|
||||
Cc1ccc(cc1)C2=N[N+]3=C(SC2)SCC3=O ZINC26442375
|
||||
c1cnc2c(n1)C(=CC2=O)[O-] ZINC21982657
|
||||
C1=C[C@@H](C(=C1)CCO)S ZINC21991846
|
||||
c1ccc(cc1)SCCS(=O)(=O)OCC(F)(F)F ZINC05446740
|
||||
CC1(OC[C@@H](O1)[C@@H]2CC23SCCCS3)C ZINC01635232
|
||||
Cc1cn2c(nc(nc2n1)c3ccccc3)N ZINC13491993
|
||||
c1ccc(cc1)NC(=O)/C(=N/c2ccc(cc2C(F)(F)F)F)/NN ZINC20523173
|
||||
c1cc[n+](cc1)c2c(cn3c2nc4ccccc4c3[O-])N ZINC36384739
|
||||
CCc1c(sc(c1C(=O)OC)NC(=S)n2cc(cn2)C)C ZINC02859215
|
||||
CC(=O)c1c(c(c(s1)SC)C#N)c2ccco2 ZINC00149475
|
||||
C1CN(CC[NH2+]1)CC/[NH+]=C(/C(=[NH+]/CCN2CCNCC2)/[S-])\\[S-] ZINC19864754
|
||||
C1CCNC(=O)/C(=N/N=C/2\\CCCCNC2=O)/C1 ZINC05566896
|
||||
C[C@@H](/N=N/c1ccccc1)/N=N/c2[n-]nnn2 ZINC17024942
|
||||
CC[C@@H](c1ccoc1)[S@@](=O)c2ccccc2 ZINC05675384
|
||||
C=C1C=C(N2[C@@H](N=C(N=C2N1)N3CCOCC3)c4ccccc4)[O-] ZINC36552956
|
||||
Cc1cc(nc(n1)N2C(=O)C/C(=C/C(=O)OC)/N2)C ZINC02203018
|
||||
Cc1cc(n(n1)C)C(=O)Nn2cnc3ccccc3c2=[NH2+] ZINC06527852
|
||||
C1COC=N1 ZINC01846598
|
||||
CC(=O)O[C@@]1(CC(N[N+]1=O)(C)C)C ZINC17058437
|
||||
C[NH+]1CCc2c(ccs2)[C@@H](OCC1)c3ccccc3 ZINC01607889
|
||||
Cc1csc2n1s/c(=N/[N+](=O)[O-])/[nH+]2 ZINC01608251
|
||||
CCn1nc(nn1)NC2CSCCSC2 ZINC23582035
|
||||
CCSc1nc(s[s+]1)N2CCCC2 ZINC05811622
|
||||
c1ccc-2c(c1)CCc3c2oc(n3)C[NH3+] ZINC40539228
|
||||
C1C[C@@H]2N=Cc3c(c(sc3N2C1)C(=O)N)N ZINC01272559
|
||||
CCCCNC(=O)NCC1=[NH+][C@@H]2C=CC=C[C@@H]2N1 ZINC20030994
|
||||
C1CN=C2[C@@H](N1)C(=O)NC2=O ZINC05386257
|
||||
c1c[n+](cc(c1[N+](=O)[O-])/C=C/N2CCOCC2)[O-] ZINC19313191
|
||||
CC1=NS(=O)(=O)N=C1O ZINC26441933
|
||||
c1cc(ccc1N2C(=O)N3CCCN=C3N2)F ZINC00093512
|
||||
[H]/N=C/1\\[C@@H](C(=C\\2C1=C(C(/C2=N\\[H])C#N)C)C)C#N ZINC05501428
|
||||
CCOP1(OC(=O)[C@@H](S1)C)(OCC)SSC ZINC05618554
|
||||
Cc1c(n2c(ccn2)nn1)C ZINC01705111
|
||||
CC1=C([C@@H](C2=C(N1)c3ccccc3C2=O)c4ccco4)C#N ZINC01407040
|
||||
c1cc(ccc1C=Nn2cnnc2)O ZINC06645782
|
||||
c1ccc(cc1)n2cc(cn2)c3c4ccccc4on3 ZINC13362334
|
||||
CO[P@@](=O)(NS(=O)(=O)C)[O-] ZINC06483334
|
||||
c1ccc2c(c1)-c3ccc(c4c3c(ccc4)C2=O)[S@@](=O)CC(=O)[O-] ZINC04683087
|
||||
Cc1c(nsn1)CSCC(=O)NC ZINC40754381
|
||||
Cc1cc(nc(n1)Nc2[nH]c3ccc(cc3n2)[N+](=O)[O-])C ZINC01301402
|
||||
c1cc(cnc1)C2=C(NON2)/N=C\\N=O ZINC16010710
|
||||
c1ccc2c(c1)C3C[C@@]4(C2c5c3cccc5)C=CS4(=O)=O ZINC16952606
|
||||
COc1ccc(cc1)c2c(c[nH]n2)C=NNC(=O)OC ZINC08721401
|
||||
CCCCC1=N/C(=C\\C#N)/Sc2c1ccc(n2)C ZINC04996816
|
||||
COCCn1cncc1CNc2c(cc(cn2)Cl)F ZINC32593155
|
||||
C/C(=N/N=C(\\C)/c1nnn(n1)C)/c2nnn(n2)C ZINC16136723
|
||||
COC(=O)CSC(=O)N/C=C/c1ccsc1 ZINC02149293
|
||||
CN(C)c1nnc(o1)c2cn[nH]c2N ZINC01395784
|
||||
c1ccc(cc1)N2C(=O)N[C@@H]3c4ccccc4[C@H]5CC[C@@H]3[C@@H]5NC2=O ZINC03852371
|
||||
[H]/N=C(\\CC(=O)c1ccccc1)/c2c(c(c([nH]c2=O)N)C#N)SC ZINC13283266
|
||||
C1C[C@@H](OC1)Cn2c(nnn2)S ZINC04218699
|
||||
Cc1cc(n(n1)[C@H]2C(=C(N=N2)C)[NH3+])C ZINC19737403
|
||||
c1c2c(cc3c1OCCO3)[nH]c(=O)[nH]2 ZINC04983305
|
||||
Cc1ccc(cc1)n2c3c[nH]c(=O)nc3cn2 ZINC32616595
|
||||
c1cc(oc1)[C@@H]2N(C(=O)CS2)c3nccs3 ZINC36649114
|
||||
COC1=C(Cc2c3ccccc3[nH]c2C(=O)N1)C#N ZINC01395241
|
||||
CC(C)(C)N1[C@H]2CS(=O)(=O)C[C@@H]2CO1 ZINC19878364
|
||||
CCc1c(nnc(n1)SCC2=N[C@@H]3C=CC=CN3C(=O)C2)CC ZINC03911024
|
||||
c1cc(ccc1NC(=O)c2cc(=O)[nH+]c(s2)N)F ZINC06058681
|
||||
Cc1nnc(o1)c2ccccc2c3coc4ccccc4c3=O ZINC32537128
|
||||
Cc1c(nnn1c2nc3ccccc3s2)C(=O)N4CCOCC4 ZINC01418428
|
||||
Cc1cc(=O)oc2c1cc[nH+]c2N ZINC01577802
|
||||
CP(C)(Cc1ccc(cc1)[N+](=O)[O-])c2ccccc2 ZINC06485149
|
||||
c1c[n+](c(c[n+]1[O-])c2cnoc2)[O-] ZINC03165159
|
||||
c1ccc2c(c1)nc3n2c(=O)cn[nH]3 ZINC05647467
|
||||
COC(=O)/C=c/1\\c(=O)n2c(=NCC2)s1 ZINC00187658
|
||||
C[C@@]12CCCCC1=[N+](CN2O)[O-] ZINC00370675
|
||||
c1c(nns1)c2nc(no2)CCl ZINC02243855
|
||||
c1cc(oc1)c2nnc3n[nH]c(=S)n3n2 ZINC17059703
|
||||
C1(=C(S(=O)(=O)C(=C1Cl)Cl)Cl)Cl ZINC02570757
|
||||
Cc1nnc(n1c2cccc3c2non3)S ZINC13731070
|
||||
c1ccc(cc1)C2=CSCC(=O)O2 ZINC01692836
|
||||
Cc1cc(n2c(n1)cc(n2)NC[C@@]3(CCOC3)c4ccc(cc4)F)C ZINC20868478
|
||||
CC(C)CC1=N[C@@H](OC1=O)c2ccccc2 ZINC03850379
|
||||
[H]/N=C\\1/C=C[C@@H](S1)C ZINC34925468
|
||||
C[C@@H]1CCCCN1C2=N/C(=C/3\\C=CC=CC3=O)/NC(=C2)C ZINC13121767
|
||||
C/C=C(\\C=c1c(=C)[nH+]c([nH]1)CCC(=O)[O-])/Cl ZINC12362733
|
||||
Cc1ccc(c(c1)C)c2csc(n2)CN3CCOC3=O ZINC30448012
|
||||
C1C/C(=N/O)/CSC1 ZINC00158065
|
||||
Cc1ccc(o1)[C@@H]2Nc3ccccc3C(=N2)O ZINC04108187
|
||||
C1=Nc2c(non2)NN=C1 ZINC03204866
|
||||
c1ccc(cc1)c2[nH]c(=S)c3c(n2)csc3N ZINC06530209
|
||||
c1ccc(cc1)c2nc3cccnc3s2 ZINC12940414
|
||||
COCCCNC1=C(C(=O)N[C@@H](S1)[C@@H]2CCC=CC2)C#N ZINC20414032
|
||||
Cc1ccccc1CNc2cncc(n2)SCC(=O)[O-] ZINC32577550
|
||||
c1ccc(cc1)C2=NO[C@@H]3[C@@H]2C(=O)NC(=O)N3 ZINC05124822
|
||||
Cc1cc(on1)c2cnc(nc2CCNC(=O)C3CC3)C ZINC19123322
|
||||
c1ccc2c(c1)n3cnnc3s2 ZINC00173203
|
||||
C1CC=COC1 ZINC04726938
|
||||
c1ccc2c(c1)cccc2Nc3ncc(o3)N ZINC01637015
|
||||
COc1ccccc1n2n(o2)c3ccccc3OC ZINC01670119
|
||||
c1cc(oc1)Cn2ccnc2S ZINC00024727
|
||||
c12c(non1)C(=O)c3c(non3)C2=O ZINC01017719
|
||||
c1cc(ccc1C(=O)Nc2c(c[nH]c(=O)n2)F)[N+](=O)[O-] ZINC01601271
|
||||
c1ccc2c(c1)C=C[C@@H]3[C@@H]2SC(=C3)C=O ZINC00335881
|
||||
C1CN2C[NH+]3CC=CC[C@@H]3[C@@H]1O2 ZINC05282913
|
||||
CC1=NC2=C(CN1C)CN3C=C(C=CC3=N2)Br ZINC15781046
|
||||
c1ccc(cc1)[C@@H]2[NH2+][C@H]3[C@H](S2)COC3=O ZINC16974985
|
||||
CN1CCC\\2=C1/C(=N\\O)/S/C2=N\\c3ccc(cc3)F ZINC32936437
|
||||
CO/N=C(/c1cc(sc1)Nc2cc(on2)c3ccco3)\\C(=O)[O-] ZINC00097189
|
||||
c1cc(ccc1Nc2nnc(o2)c3c(nc[nH]3)[N+](=O)[O-])Cl ZINC04344036
|
||||
c1ccc(cc1)/N=N/N2CCC(=O)N2 ZINC01395505
|
||||
c1ccc(cc1)n2c(nnn2)Sc3c4c(ccs4)ncn3 ZINC08727358
|
||||
c1ccc2c(c1)CC3[C@@H]2NC3=O ZINC05338825
|
||||
Cc1cc(nc(n1)N/C(=N/S(=O)(=O)N2CCCCCC2)/[O-])C ZINC00186775
|
||||
C[C@@]1([C@@H](N(C(=O)NC1=O)[C@H]2C=C[C@@H](O2)CO)N=[N+]=[N-])Br ZINC17214544
|
||||
c1ccc(cc1)CN2CCC(=N2)/C=C/c3ccco3 ZINC00172696
|
||||
Cc1cs/c(=N\\c2c(nc[nH]2)C(=O)N)/n1c3ccccc3 ZINC08694932
|
||||
C1CSC(=C(SC1)SCC(=O)N)SCC(=O)N ZINC03672036
|
||||
c1cc(oc1)/C=C\\2/C(=O)NC(=N2)[S-] ZINC37866052
|
||||
CC(C)(C)C1=CC=Nn2cnnc2S1 ZINC04753508
|
||||
Cc1ccc(cc1)S(=O)(=O)N/N=C(/C)\\c2c(cc(oc2=O)C)O ZINC17176558
|
||||
CC1([C@@H](N(S1(=O)=O)C(=O)OC)N2CCCC2=O)C ZINC05179691
|
||||
c1cc2n(c1)CCC2 ZINC04914414
|
||||
COC(=O)/C=c/1\\c(=O)n2cnc(c2s1)C(=O)N ZINC01415905
|
||||
CN1C(=O)/C(=C/[n+]2ccccc2N)/SC1=S ZINC01690541
|
||||
COC(=O)C1=CC(=O)/C(=C(/Nc2ccc(cc2Cl)Cl)\\O)/S1 ZINC00480524
|
||||
CCOC(=O)NC(=O)[C@H](/C=N/[C@@H](CO)c1ccccc1)C#N ZINC12859992
|
||||
CC1=C(/C(=C\\2/C(=NNS2)C)/N=N1)C(=O)OC ZINC13125377
|
||||
c1csc2c1[nH]c(=O)cc2O ZINC00080290
|
||||
c1cc(ccc1c2cc3c([n-]nn3)nc2)C(=O)N4CCCC4 ZINC32593203
|
||||
c1ccc2c(c1)c3c(c(=O)o2)SC(=C(C#N)C#N)S3 ZINC00051671
|
||||
COc1ccc(c(c1)O)c2c(cn[nH]2)c3cscn3 ZINC13126788
|
||||
c1cc(ccc1C2=C[N+](=C([CH-]O2)O)c3ccc(cc3)Cl)[N+](=O)[O-] ZINC33384935
|
||||
CCOP(=O)(Cc1cnc(s1)Cl)OCC ZINC04198745
|
||||
c1ccc2c(c1)CCC3=C(C=C2)C(=O)OC3 ZINC19878394
|
||||
COc1ccc2c(c1)[C@@H]3CCCC[C@@H]3SCC2=O ZINC01706546
|
||||
c1ccc2c(c1)c(nc(n2)[O-])C(=O)N[C@@H]3CCSC3 ZINC20907159
|
||||
Cc1cccc(c1)/C=N/NC2=NNC(=Cc3n2ncn3)[NH3+] ZINC06055095
|
||||
CC1(c2ccccc2-[n+]3c1cc(cc3c4ccccc4)c5ccco5)C ZINC03848440
|
||||
Cc1cccc2c1[C@H](C(=O)N2)n3cnc4c(c3=O)cccn4 ZINC32519397
|
||||
CS(=O)(=O)SCc1c[nH]cn1 ZINC06187559
|
||||
c1cc(cc(c1)[N+](=O)[O-])[C@@H]2[C@@](O2)(C#N)C(=C(C#N)C#N)N ZINC35324029
|
||||
c1cc([nH]c1)C(=O)CSC(=S)N2CCCC2 ZINC16927016
|
||||
CCn1c2c[n+](nnc2c(=O)n(c1=O)CC)[O-] ZINC01696288
|
||||
Cc1[c-](n2nc(c([n+]2n1)[N+](=O)[O-])C)C(=O)NCc3ccco3 ZINC04594478
|
||||
c1[nH]c(c(n1)/N=N/SC[C@@H](C(=O)[O-])[NH3+])C(=O)N ZINC05605512
|
||||
C=C(C[NH3+])Br ZINC01684537
|
||||
CC(=O)N[C@@H](C(=O)[O-])OCSC ZINC21986107
|
||||
c1ccc(cc1)C2=NNC(=O)/C(=N/N=c/3\\c4ccccc4nc[nH]3)/C2 ZINC12810418
|
||||
c1cc(cc(c1)[N+](=O)[O-])c2cc(=S)[nH+]c(s2)N ZINC23549979
|
||||
c1ccc(cc1)C2=CCC(=O)O2 ZINC01723799
|
||||
CCOC(=O)CC(=C)NNc1c(=O)[nH]c(=O)[nH]n1 ZINC03196592
|
||||
C/N=C/1\\CC(=O)C1(F)F ZINC05103278
|
||||
COc1ccc(cc1)C2=NC[C@@H](S2)Cn3cnc(n3)C#N ZINC14143714
|
||||
CC1=C(C(=O)C(=C(C1[NH+]=C(C)C)C)C)C ZINC01692804
|
||||
Cc1c2c(on1)[C@@H](C(=C([C@@H]2c3ccccc3)C#N)[NH3+])c4cccc(c4)O ZINC04639687
|
||||
c1ccc(cc1)n2c(=O)n3n(c2=O)-c4cc5ccccc5cc4C3 ZINC01630777
|
||||
CC1=C(CC(=O)N1Cc2ccco2)C(=O)OC ZINC00032157
|
||||
c1cnn(c1)c2ccc(nn2)NN ZINC27704609
|
||||
CN1[C@@H]2[C@@H](NNC(=O)N2)N(C1=O)C ZINC01437219
|
||||
c1ccc(cc1)C/N=c\\2/c(=[NH2+])c(c2O)[O-] ZINC11536078
|
||||
c1ccc(cc1)N2C(=O)[C@H]3[C@H](C2=O)N=NN3 ZINC01635478
|
||||
COc1cc(cc2c1oc(=O)s2)/C=C(/C#N)\\c3[nH]c4ccccc4n3 ZINC15230985
|
||||
CN(C)C=C(C=[N+](C)C)C(F)(F)F ZINC19795288
|
||||
Cc1ccc(cc1)[C@@H]2/C(=N/CCOC)/C(=O)C2=O ZINC06749075
|
||||
Cc1c2c(cn[nH]2)n[nH]1 ZINC13119669
|
||||
c1ccc(cc1)c2cn3c4ccsc4cc3c(=S)n2N ZINC05001335
|
||||
Cc1cc(=O)c(c([nH]1)SC)C#N ZINC12250592
|
||||
CC1=[NH+][C@@H](C(=N[C@@H](C1)c2ccccc2)C#N)C#N ZINC12341202
|
||||
Cc1ccc(o1)/C=N/N=C/2\\C[C@@H](N=N2)c3ccccc3 ZINC04615652
|
||||
CNc1c(cnc2c1c(=[NH2+])nc3n2cccc3)[N+](=O)[O-] ZINC05073549
|
||||
c1ccc2c(c1)c3ccccc3n2/N=C/c4cnc(nc4)N ZINC13957148
|
||||
CCS[C@@H]1C[C@@H](NC(=S)N1)C ZINC00495630
|
||||
COCc1[nH]c2c(n1)-c3c(nc(o3)N)[C@H]2c4ccc(cc4)Cl ZINC04809817
|
||||
C1=C(S/C(=C(\\N)/N=O)/N1)[N+](=O)[O-] ZINC04394414
|
||||
C1C#CCSCC#CCS1 ZINC01579050
|
||||
CNC1=C(C(=O)[C@H](O1)c2ccccc2)c3ccc(cc3)C(F)(F)F ZINC01392875
|
||||
C1CC[C@H]2[C@@H](C1)N[P@@](=O)(S2)C3CCC(CC3)[N+](=O)[O-] ZINC05188068
|
||||
[C@@H]12[C@@H](NS(=O)(=O)N1)[N-]/C(=N\\[N+](=O)[O-])/N2 ZINC27499231
|
||||
c1ccc(cc1)C(=O)/C(=C/2\\C=[N+](ON2)[O-])/N=O ZINC04722296
|
||||
c1ccc(c(c1)/N=N/c2ccc[nH]2)O ZINC05583542
|
||||
c1ccc2c(c1)cc(cn2)O ZINC00191173
|
||||
CC(C)(C)C(=O)[C@@]1([C@@H](c2ccccc2O1)O)n3cncn3 ZINC02338624
|
||||
CC(C)c1nc(on1)[C@@H]2CCCN(C2)c3cc(nc(n3)N)OC ZINC32580949
|
||||
Cc1ccn(n1)CCc2nnc(n2C3CC3)S ZINC02788311
|
||||
CCOC(=O)[C@@H](c1ccccc1)S[P@@](=S)(O)OC ZINC02436012
|
||||
Cn1c2c(cn1)nc3c(c2Cl)CCCC3 ZINC12394906
|
||||
CC(=O)c1cc(cs1)CSC2=NCCN2 ZINC00034674
|
||||
CCS(=O)(=O)NN1CCOCC1 ZINC06048769
|
||||
CC1(CC2=C(C(=O)C1)Sc3c(c(=O)[nH]cn3)N2)C ZINC08773260
|
||||
c1ccc(cc1)c2c3c([nH]n2)nccn3 ZINC05478968
|
||||
CCS(=O)(=O)[C@@]1(CC[C@@]1(C#N)S(=O)(=O)CC)C#N ZINC01626125
|
||||
COc1ccc2c(c1)CCC3=C2CC(=O)N4N3CCCC4 ZINC01585422
|
||||
c1ccc(cc1)CSc2c3c(ncn2)nsn3 ZINC01683976
|
||||
Cc1nn(c(=S)s1)CN2CCCCC2 ZINC20427162
|
||||
CCn\\1ccnc(/c1=N\\c2ccc(cc2)OC)N3CCOCC3 ZINC08654268
|
||||
CCOC(=O)C1=NN[C@@H]2[C@H]1C(=O)NC2=O ZINC04484374
|
||||
c1ccc2c(c1)CP(=O)(C2)CCl ZINC02575553
|
||||
C[C@]12C=C3C(OC(=O)N3CCN1C(=O)OC2(C)C)(C)C ZINC00052076
|
||||
c1ccc(cc1)SC2CN(N(C2)C=O)C=O ZINC01403861
|
||||
CC1=C(NON1)c2c(c(n[nH]2)N=O)N=O ZINC13810301
|
||||
c1ccc(cc1)[C@@H]2CCc3c(nc(nc3O2)S)O ZINC08742562
|
||||
CCOC(=O)c1ccc(cc1)NC=C2C(=O)OC(OC2=O)(C)C ZINC09187082
|
||||
Cc1cc2n(n1)C3(CCCC3)N(NC2=O)C ZINC33950295
|
||||
c1cc(ccc1CSc2nc(n(n2)C(=O)C3CCC3)N)Cl ZINC14162494
|
||||
Cc1c(non1)c2cc3ccccc3[nH]2 ZINC15083870
|
||||
c1ccc2c(c1)ncc(n2)Oc3cnns3 ZINC06943106
|
||||
c1ccc2c(c1)c3c(c(=O)o2)nsn3 ZINC12341338
|
||||
COC(=O)Nc1cc(nc([n+]1[O-])N)N2CCC=CC2 ZINC01590448
|
||||
[H]/N=C\\1/C(=N\\Nc2ccccc2)/c3ncc(n3O1)c4ccc(cc4)Cl ZINC04457953
|
||||
CC1=C([C@@H](N(O1)C)c2ccccc2)S(=O)(=O)c3ccccc3 ZINC01612039
|
||||
CCOC(=O)c1c(sc(n1)N/N=C(\\C#N)/C2=NC(=O)CS2)C ZINC05473952
|
||||
c1ccc(cc1)n2c3c(ccc(=O)o3)cn2 ZINC05477675
|
||||
Cc1cnc(cn1)CNC(=O)CCN2CCCCO2 ZINC20820454
|
||||
CN(Cc1ccccc1)c2c(nsn2)Cl ZINC35232106
|
||||
c1cc2c(cc1O)CCO2 ZINC18557846
|
||||
C[NH+]1CCC(CC1)OC(=O)[C@@](c2ccccc2)(c3ccns3)O ZINC01641834
|
||||
c1ccc(cc1)N2CC=CCO2 ZINC01721075
|
||||
C[C@@H]1C(=O)N/C(=C/C(=S)N)/S1 ZINC08857271
|
||||
C1(=C(SC(=C(S1)C(=O)N)C(=O)N)C(=O)N)C(=O)N ZINC01720125
|
||||
c1cc2c(nc1)-c3c(cccn3)[C@@H]4[C@H]2O4 ZINC18120220
|
||||
c1ccc(cc1)[C@@H]2C(=N[C@@H](C(=N2)C#N)C(=O)N)c3ccccc3 ZINC04377479
|
||||
COC(=O)c1ccoc1CC2CC[NH2+]CC2 ZINC12506134
|
||||
c1cc2c(cc1Nc3nnc(o3)c4ccn[nH]4)OCO2 ZINC04632419
|
||||
C1[C@@H]2[C@@H](CS1)OC(=O)O2 ZINC05574446
|
||||
CS(=O)(=O)OCC[C@@H](C#N)c1cccc(c1)Cl ZINC15442603
|
||||
c1cc2ccc3c(c2nc1)N=C[C@H](C3=O)C(=O)[O-] ZINC18166085
|
||||
c1c(nc(nc1O)N)/N=C/[C@@H](C=O)[N+](=O)[O-] ZINC16893188
|
||||
CC1=C(OP(=O)(O1)[O-])C ZINC01559410
|
||||
CO[C@@]1(CC(=O)N1c2ccccc2)n3c4ccccc4nn3 ZINC06145487
|
||||
c1ccc(cc1)n2nc3ccc4c(c3n2)nc(cn4)N ZINC00189666
|
||||
COC1=C[C@@H]2C[C@@H]([C@]2(C=C1)OC)C#N ZINC17174593
|
||||
CCc1ccc(o1)CC/C(=N/c2nc(ns2)CC(=O)C)/[O-] ZINC09014289
|
||||
CCOC(=O)C1=NNC(=CC(=O)c2cccs2)C(=O)N1 ZINC04301474
|
||||
c1ccc(cc1)n2c(c[nH]c2=S)/C(=N/c3nncs3)/[O-] ZINC21215055
|
||||
Cc1cc(nc2c1c(c(s2)c3c(cco3)C(=O)OC)N)C ZINC12422107
|
||||
CONC(=O)/C=C/c1ccc(s1)c2ccccc2 ZINC32848452
|
||||
COc1cc(ccc1O)C2=N[C@H](C(=O)Nc3c2cc(cc3)Cl)O ZINC00083397
|
||||
c1ccc(cc1)c2nc3c(c(n2)[O-])nc(=O)n(c3N)c4ccccc4 ZINC13470910
|
||||
Cc1nc2c(s1)CCCC2 ZINC39269804
|
||||
c1cc(ccc1c2cc(nc(n2)S)C(=O)Nc3nccs3)N ZINC01617710
|
||||
Cc1c(sc(n1)c2c(c[nH]n2)c3ccccc3F)CC[NH3+] ZINC19560940
|
||||
Cc1c(sc2n1ncn2)c3csc(n3)C ZINC01401913
|
||||
CO[C@@]1(C(=O)N(C(=N1)[O-])c2ccc(cc2)F)C(F)(F)F ZINC13362415
|
||||
c1ccc(cc1)n2c3c(cn2)c(=[NH2+])[nH][nH]3 ZINC08627905
|
||||
CCOC(=O)c1c(c2c(cccc2s1)F)Cn3cnc(n3)C#N ZINC31766246
|
||||
CC(C)(C)/N=C/1\\CC(=O)OC1 ZINC05284069
|
||||
COC(=O)c1ccccc1OC/C(=[NH+]\\Nc2cccc(n2)Cl)/N ZINC05210011
|
||||
CCOC1=CN(NCC(=C1)[N+](=O)[O-])c2ccncn2 ZINC28294498
|
||||
c1ccc(cc1)/C=C/2\\CCNC2=O ZINC01653824
|
||||
C/C(=N/NC(=S)N)/c1cc(ccc1O)Cl ZINC05287757
|
||||
CCCc1[nH]c(nn1)Sc2ncc(c(n2)NC3CC3)[N+](=O)[O-] ZINC12894303
|
||||
CN(C)NC(=S)SNN(C)C ZINC21487034
|
||||
CS(=O)(=O)CSCSSCS(=O)(=O)C ZINC01631876
|
||||
c1cc(c(c(c1)Cl)[C@@H]2[C@@H]([C@@H](SCCS2)N)C#N)F ZINC20086628
|
||||
CC1=NNC(=O)OC1(C)C ZINC04776593
|
||||
Cn1c(=O)n(sc1=O)c2ccccc2 ZINC00102676
|
||||
C1COC(C(O1)(Cl)Cl)(Cl)Cl ZINC04722373
|
||||
c1cc(ccc1C(=O)NC2=[NH+]CCCCCN2)[N+](=O)[O-] ZINC00045438
|
||||
Cc1cc([nH]c1c2nc(no2)C[C@@H]3CCCO3)C ZINC20598117
|
||||
c1ccc2c(c1)C=CC23C(=O)c4ccccc4C3=O ZINC01611935
|
||||
C([C@@H]1[C@@H]([C@@H]([C@@H](O1)OP(=O)([O-])[O-])O)O)O ZINC03870207
|
||||
CC1=C([C@@H](C(=C(S1)N)C#N)c2ccco2)C#N ZINC20568713
|
||||
c1ccc(cc1)n2nc3c([n+]2[O-])-c4ccccc4CC3 ZINC07787398
|
||||
C[NH+]1CCC2=C(C1)C(=NC3(N2)CCCCC3)O ZINC19334663
|
||||
Cc1c(snn1)c2[nH]nc(n2)[S-] ZINC40544346
|
||||
Cc1c(non1)NS(=O)(=O)c2ccccc2 ZINC00134635
|
||||
c1cc(sc1)n2c(=O)[nH]nn2 ZINC04218436
|
||||
c1nc(c2c(n1)snc2Cl)O ZINC16977238
|
||||
C1C[C@H]2C[C@@H]1C3=C2SC([C@@H]3F)(F)F ZINC05600475
|
||||
Cc1nc(on1)c2cnc[nH]c2=O ZINC40351448
|
||||
Cc1c(c(c(o1)C)C(=O)[O-])c2ccc3c(c2)[nH]c(n3)NC(=O)OC ZINC13216433
|
||||
CSCSC ZINC01621620
|
||||
c1nnnn1CC(=O)N[C@@H]2CCS(=O)(=O)C2 ZINC27977392
|
||||
Cc1nn2cc(nc2s1)CNC(=O)Nc3nnc(s3)C4CCC4 ZINC23429667
|
||||
Cc1cccc(c1)NC2=C(C(=O)NC3(S2)CCCC3)C#N ZINC00137148
|
||||
c1ccc(cc1)C#CC(=O)NCCc2cnccn2 ZINC20860959
|
||||
c1cc(ccc1c2nnc(n2C[C@H]3CCCO3)S)O ZINC04993921
|
||||
Cc1cn2ccnc2s1 ZINC33359219
|
||||
CC1(C=C2C(=NN(C(=C2C#N)N)c3ccccc3)CO1)C ZINC00173901
|
||||
CCn\\1c(=O)/c(=C/Nc2ccccc2)/s/c1=C(\\C#N)/C(=O)OCC ZINC12546759
|
||||
Cc1ccc(cc1N/C=C(\\C(=O)OC)/n2cncn2)F ZINC01407155
|
||||
c1nncn1NC(=S)SCC(=O)[O-] ZINC16848052
|
||||
Cc1ccc(cc1)OC/C(=N/OC(=O)c2cc(on2)C)/N ZINC08536224
|
||||
Cc1c(=O)[nH]c2[n+](n1)[C@@H]([C@@H](CS2)Br)c3ccccc3 ZINC00202955
|
||||
c1ccc2c(c1)C(=NCCO2)S ZINC06576028
|
||||
CC(C)(C1c2ccccc2C(=NO)c3c1cccc3)[N+](=O)[O-] ZINC01601553
|
||||
C[C@@]12C[C@@]3(C(NC(=S)N3O)(C)C)ON1C(=S)NC2(C)C ZINC00499273
|
||||
CC1=NC(=C2[C@@H](C1C#N)c3ccccc3NC2=[NH2+])C ZINC08651825
|
||||
c1ccc(cc1)C2=NN(CN(N2)c3ccccc3)c4[n-]nnn4 ZINC05682131
|
||||
c1ccc(cc1)c2nnn(n2)Cc3nc4ccccc4s3 ZINC00416878
|
||||
C1C(=NCC(=N1)S)S ZINC05566537
|
||||
C(#N)S/C(=C(/[N+](=O)[O-])\\Cl)/C(=C(Cl)Cl)Cl ZINC17256958
|
||||
c1ccc(cc1)[C@@H]2CC(=O)C=CO2 ZINC21999070
|
||||
Cc1ccc(nc1)/[NH+]=c\\2/c(c(cc(o2)C)O)C(=O)C ZINC35682746
|
||||
Cn1cccc1c2cc3n(n2)CCCN3 ZINC20864741
|
||||
CCO[P@@]1(=O)CCCCN1Cc2ccccc2 ZINC01849833
|
||||
Cc1nc(on1)c2ccc(cc2)O ZINC04015309
|
||||
Cc1cs/c(=N\\C(C)C)/n1/N=C/c2ccco2 ZINC05833376
|
||||
COC1=CCC=CC1 ZINC01840966
|
||||
CCOC(=O)CNC1=[NH+]N=[S@](=O)(c2c1cccc2)O ZINC17223734
|
||||
Cc1[n+](c2ccc3c(c2s1)C(C(=[N+]3C)C)(C)C)C ZINC27987876
|
||||
Cc1c(c([nH]n1)C(F)(F)F)/N=N\\N(C)C ZINC16924215
|
||||
c1ccc(cc1)c2nc(nc(n2)[n+]3cccc(c3)O)c4ccccc4 ZINC05516865
|
||||
Cc1c(ccc2c1oc(c2[O-])C=[N+]3CCN(CC3)C)O ZINC23127906
|
||||
c1cc2=[NH+]C(=O)CC=c2c(c1)O ZINC16952034
|
||||
c1ccc(cc1)c2c(c3n(n2)-c4ccccc4[C@@H]3CO)O ZINC06007053
|
||||
Cc1cc(nn2c1nnc2)n3c(nc(n3)N)N ZINC06413412
|
||||
C1CCC2=CS(=O)(=O)[C@@H]2C1 ZINC01705812
|
||||
1500
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.tdt
Normal file
1500
Code/GraphMol/FileParsers/test_data/zinc.leads.500.q.tdt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user