bool AromaticityMatcher::isNecessary (QueryMolecule &query) { for (int e = query.edgeBegin(); e < query.edgeEnd(); e = query.edgeNext(e)) { if (!query.aromaticity.canBeAromatic(e)) continue; QueryMolecule::Bond &bond = query.getBond(e); // Check if bond isn't aromatic but can be aromatic if (bond.possibleValue(QueryMolecule::BOND_ORDER, BOND_SINGLE)) return true; if (bond.possibleValue(QueryMolecule::BOND_ORDER, BOND_DOUBLE)) return true; } // Check R-groups MoleculeRGroups &rgroups = query.rgroups; int n_rgroups = rgroups.getRGroupCount(); for (int i = 1; i <= n_rgroups; i++) { PtrPool<BaseMolecule> &frags = rgroups.getRGroup(i).fragments; for (int j = frags.begin(); j != frags.end(); j = frags.next(j)) { QueryMolecule &fragment = frags[j]->asQueryMolecule(); if ( AromaticityMatcher::isNecessary(fragment)) return true; } } return false; }
bool QueryMoleculeAromatizer::_aromatizeBondsFuzzy (QueryMolecule &mol, const AromaticityOptions &options) { bool aromatized = false; QueryMoleculeAromatizer aromatizer(mol, options); aromatizer.setMode(QueryMoleculeAromatizer::FUZZY); aromatizer.precalculatePiLabels(); aromatizer.aromatize(); mol.aromaticity.clear(); for (int e_idx = mol.edgeBegin(); e_idx < mol.edgeEnd(); e_idx = mol.edgeNext(e_idx)) { bool aromatic_constraint = mol.getBond(e_idx).possibleValue(QueryMolecule::BOND_ORDER, BOND_AROMATIC); if (aromatic_constraint || aromatizer.isBondAromatic(e_idx)) { mol.aromaticity.setCanBeAromatic(e_idx, true); aromatized = true; } } return aromatized; }
bool QueryMoleculeAromatizer::_aromatizeBonds (QueryMolecule &mol, int additional_atom, const AromaticityOptions &options) { bool aromatized = false; // Mark edges that can be aromatic in some matching aromatized |= _aromatizeBondsFuzzy(mol, options); // Aromatize all aromatic cycles aromatized |= _aromatizeBondsExact(mol, options); MoleculeRGroups &rgroups = mol.rgroups; int n_rgroups = rgroups.getRGroupCount(); // Check if r-groups are attached with single bonds QS_DEF(Array<bool>, rgroups_attached_single); rgroups_attached_single.clear(); for (int v = mol.vertexBegin(); v != mol.vertexEnd(); v = mol.vertexNext(v)) { if (v == additional_atom) continue; if (mol.isRSite(v)) { // Check if neighbor bonds are single const Vertex &vertex = mol.getVertex(v); for (int nei = vertex.neiBegin(); nei != vertex.neiEnd(); nei = vertex.neiNext(nei)) { int edge = vertex.neiEdge(nei); QueryMolecule::Bond &bond = mol.getBond(edge); // DP TODO: implement smth. like Node::possibleOtherValueExcept() ... bool can_be_double = bond.possibleValue(QueryMolecule::BOND_ORDER, BOND_DOUBLE); bool can_be_triple = bond.possibleValue(QueryMolecule::BOND_ORDER, BOND_TRIPLE); bool can_be_arom = bond.possibleValue(QueryMolecule::BOND_ORDER, BOND_AROMATIC); if (can_be_double || can_be_triple || can_be_arom) { QS_DEF(Array<int>, sites); mol.getAllowedRGroups(v, sites); for (int j = 0; j < sites.size(); j++) { rgroups_attached_single.expandFill(sites[j] + 1, true); rgroups_attached_single[sites[j]] = false; } } } } } rgroups_attached_single.expandFill(n_rgroups + 1, true); for (int i = 1; i <= n_rgroups; i++) { PtrPool<BaseMolecule> &frags = rgroups.getRGroup(i).fragments; for (int j = frags.begin(); j != frags.end(); j = frags.next(j)) { QueryMolecule &fragment = frags[j]->asQueryMolecule(); aromatized |= _aromatizeRGroupFragment(fragment, rgroups_attached_single[i], options); } } return aromatized; }
bool MoleculePiSystemsMatcher::_fixBonds (QueryMolecule &query, const int *mapping) { for (int e = query.edgeBegin(); e != query.edgeEnd(); e = query.edgeNext(e)) { const Edge &query_edge = query.getEdge(e); if (mapping[query_edge.beg] < 0 || mapping[query_edge.end] < 0) continue; // Edges connected with ignored vertices int target_edge = Graph::findMappedEdge(query, _target, e, mapping); const Edge &edge = _target.getEdge(target_edge); int p1_idx = _atom_pi_system_idx[edge.beg]; int p2_idx = _atom_pi_system_idx[edge.end]; if (p1_idx == _NOT_IN_PI_SYSTEM || p2_idx == _NOT_IN_PI_SYSTEM || p1_idx != p2_idx) continue; if (!_pi_systems[p1_idx].initialized) throw Error("pi-system must be initialized here"); _Pi_System &pi_system = _pi_systems[p1_idx]; int pi_sys_edge = Graph::findMappedEdge(_target, pi_system.pi_system, target_edge, pi_system.inv_mapping.ptr()); // Get target topology int topology = _target.getBondTopology(target_edge); QueryMolecule::Bond &qbond = query.getBond(e); bool can_be_single = qbond.possibleValuePair( QueryMolecule::BOND_ORDER, BOND_SINGLE, QueryMolecule::BOND_TOPOLOGY, topology); bool can_be_double = qbond.possibleValuePair( QueryMolecule::BOND_ORDER, BOND_DOUBLE, QueryMolecule::BOND_TOPOLOGY, topology); bool can_be_triple = qbond.possibleValuePair( QueryMolecule::BOND_ORDER, BOND_TRIPLE, QueryMolecule::BOND_TOPOLOGY, topology); if (!can_be_single && !can_be_double && !can_be_triple) return false; if (can_be_single && can_be_double && can_be_triple) continue; bool ret = false; // initializing to avoid compiler warning if (can_be_single && can_be_double) // Here can_be_triple = false because of previous check ret = pi_system.localizer->fixBondSingleDouble(pi_sys_edge); else { if (can_be_triple) { if (can_be_single) throw Error("Unsupported bond order specified (can be single or triple)"); else if (can_be_double) throw Error("Unsupported bond order specified (can be double or triple)"); ret = pi_system.localizer->fixBond(pi_sys_edge, BOND_TRIPLE); } if (can_be_single) ret = pi_system.localizer->fixBond(pi_sys_edge, BOND_SINGLE); if (can_be_double) ret = pi_system.localizer->fixBond(pi_sys_edge, BOND_DOUBLE); } if (!ret) return false; } return true; }