1 // Copyright (c) 2015, Novartis Institutes for BioMedical Research Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following
12 // disclaimer in the documentation and/or other materials provided
13 // with the distribution.
14 // * Neither the name of Novartis Institutes for BioMedical Research Inc.
15 // nor the names of its contributors may be used to endorse or promote
16 // products derived from this software without specific prior written
17 // permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 //
31
32 #include "FilterMatchers.h"
33 #include <GraphMol/SmilesParse/SmilesParse.h>
34
35 #include <utility>
36
37 namespace RDKit {
38 const char *DEFAULT_FILTERMATCHERBASE_NAME = "Unnamed FilterMatcherBase";
39 const char *SMARTS_MATCH_NAME_DEFAULT = "Unnamed SmartsMatcher";
40 namespace {
41 const int debugParse = 0;
42 const bool mergeHs = true;
43 } // namespace
SmartsMatcher(const ROMol & pattern,unsigned int minCount,unsigned int maxCount)44 SmartsMatcher::SmartsMatcher(const ROMol &pattern, unsigned int minCount,
45 unsigned int maxCount)
46 : FilterMatcherBase(SMARTS_MATCH_NAME_DEFAULT),
47 d_pattern(new ROMol(pattern)),
48 d_min_count(minCount),
49 d_max_count(maxCount) {}
50
SmartsMatcher(const std::string & name,const ROMol & pattern,unsigned int minCount,unsigned int maxCount)51 SmartsMatcher::SmartsMatcher(const std::string &name, const ROMol &pattern,
52 unsigned int minCount, unsigned int maxCount)
53 : FilterMatcherBase(name),
54 d_pattern(new ROMol(pattern)),
55 d_min_count(minCount),
56 d_max_count(maxCount) {}
57
SmartsMatcher(const std::string & name,const std::string & smarts,unsigned int minCount,unsigned int maxCount)58 SmartsMatcher::SmartsMatcher(const std::string &name, const std::string &smarts,
59 unsigned int minCount, unsigned int maxCount)
60 : FilterMatcherBase(name),
61 d_pattern(SmartsToMol(smarts, debugParse, mergeHs)),
62 d_min_count(minCount),
63 d_max_count(maxCount) {}
64
SmartsMatcher(const std::string & name,ROMOL_SPTR pattern,unsigned int minCount,unsigned int maxCount)65 SmartsMatcher::SmartsMatcher(const std::string &name, ROMOL_SPTR pattern,
66 unsigned int minCount, unsigned int maxCount)
67 : FilterMatcherBase(name),
68 d_pattern(std::move(pattern)),
69 d_min_count(minCount),
70 d_max_count(maxCount) {}
71
setPattern(const std::string & smarts)72 void SmartsMatcher::setPattern(const std::string &smarts) {
73 d_pattern.reset(SmartsToMol(smarts, debugParse, mergeHs));
74 }
75
setPattern(const ROMol & mol)76 void SmartsMatcher::setPattern(const ROMol &mol) {
77 d_pattern.reset(new ROMol(mol));
78 }
79
SmartsMatcher(const SmartsMatcher & rhs)80 SmartsMatcher::SmartsMatcher(const SmartsMatcher &rhs)
81 : FilterMatcherBase(rhs),
82 d_pattern(rhs.d_pattern),
83 d_min_count(rhs.d_min_count),
84 d_max_count(rhs.d_max_count) {}
85
getMatches(const ROMol & mol,std::vector<FilterMatch> & matchVect) const86 bool SmartsMatcher::getMatches(const ROMol &mol,
87 std::vector<FilterMatch> &matchVect) const {
88 PRECONDITION(d_pattern.get(), "bad on pattern");
89
90 bool onPatExists = false;
91 std::vector<RDKit::MatchVectType> matches;
92
93 if (d_min_count == 1 && d_max_count == UINT_MAX) {
94 RDKit::MatchVectType match;
95 onPatExists = RDKit::SubstructMatch(mol, *d_pattern.get(), match);
96 if (onPatExists) {
97 matchVect.emplace_back(copy(), match);
98 }
99 } else { // need to count
100 const bool uniquify = true;
101 unsigned int count =
102 RDKit::SubstructMatch(mol, *d_pattern.get(), matches, uniquify);
103 onPatExists = (count >= d_min_count &&
104 (d_max_count == UINT_MAX || count <= d_max_count));
105 if (onPatExists) {
106 boost::shared_ptr<FilterMatcherBase> clone = copy();
107 for (auto &match : matches) {
108 matchVect.emplace_back(clone, match);
109 }
110 }
111 }
112 return onPatExists;
113 }
114
hasMatch(const ROMol & mol) const115 bool SmartsMatcher::hasMatch(const ROMol &mol) const {
116 PRECONDITION(d_pattern.get(), "bad on pattern");
117
118 if (d_min_count == 1 && d_max_count == UINT_MAX) {
119 RDKit::MatchVectType matches;
120 return SubstructMatch(mol, *d_pattern.get(), matches);
121 } else { // need to count
122 const bool uniquify = true;
123 std::vector<RDKit::MatchVectType> matches;
124 unsigned int count =
125 RDKit::SubstructMatch(mol, *d_pattern.get(), matches, uniquify);
126 return (count >= d_min_count &&
127 (d_max_count == UINT_MAX || count <= d_max_count));
128 }
129 }
130
getMatches(const ROMol & mol,std::vector<FilterMatch> & m) const131 bool FilterHierarchyMatcher::getMatches(const ROMol &mol,
132 std::vector<FilterMatch> &m) const {
133 // a null matcher is root, just goes to the children
134
135 std::vector<FilterMatch> temp;
136 bool result = d_matcher->getMatches(mol, temp);
137
138 if (result) {
139 std::vector<FilterMatch> children;
140
141 for (auto matcher : d_children) {
142 matcher->getMatches(mol, children);
143 }
144
145 if (children.size()) {
146 m.insert(m.end(), children.begin(), children.end());
147 } else {
148 m.insert(m.end(), temp.begin(), temp.end());
149 }
150 }
151
152 return result;
153 }
154 } // namespace RDKit
155