From 876a4de1238b77b3cb74ba6262f3b8ecadcce264 Mon Sep 17 00:00:00 2001 From: Aliaksander Stsepaniuk Date: Sun, 25 Sep 2022 17:11:02 +0300 Subject: [PATCH 1/6] Issue #520 Replace RedBlackMap in MoleculeStereocenters --- api/c/indigo/src/indigo_stereo.cpp | 7 +- .../molecule/molecule_automorphism_search.h | 11 +- .../molecule/molecule_cip_calculator.h | 5 +- .../molecule/molecule_stereocenter_iterator.h | 53 ++++ .../molecule/molecule_stereocenters.h | 47 ++-- .../molecule/src/inchi_wrapper.cpp | 3 +- .../src/molecule_automorphism_search.cpp | 41 +-- .../molecule/src/molecule_cip_calculator.cpp | 13 +- .../src/molecule_stereocenter_iterator.cpp | 35 +++ .../molecule/src/molecule_stereocenters.cpp | 237 +++++++++--------- .../molecule/src/smiles_loader.cpp | 3 +- .../indigo-core/molecule/src/smiles_saver.cpp | 10 +- core/render2d/src/render_internal.cpp | 5 +- 13 files changed, 290 insertions(+), 180 deletions(-) create mode 100644 core/indigo-core/molecule/molecule_stereocenter_iterator.h create mode 100644 core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp diff --git a/api/c/indigo/src/indigo_stereo.cpp b/api/c/indigo/src/indigo_stereo.cpp index 7ce07c4537..87a352d742 100644 --- a/api/c/indigo/src/indigo_stereo.cpp +++ b/api/c/indigo/src/indigo_stereo.cpp @@ -20,6 +20,7 @@ #include "indigo_reaction.h" #include "molecule/molecule_automorphism_search.h" #include "molecule/molecule_exact_matcher.h" +#include "molecule/molecule_stereocenter_iterator.h" #include "reaction/reaction.h" CEXPORT int indigoStereocenterType(int atom) @@ -373,7 +374,7 @@ static int _resetSymmetric(Molecule& mol, bool cistrans, bool stereo) { QS_DEF(Array, to_remove); to_remove.clear(); - for (int i = mol.stereocenters.begin(); i != mol.stereocenters.end(); i = mol.stereocenters.next(i)) + for (auto i = mol.stereocenters.begin(); i != mol.stereocenters.end(); i = mol.stereocenters.next(i)) { int atom_index = mol.stereocenters.getAtomIndex(i); if (am.invalidStereocenter(atom_index)) @@ -530,7 +531,7 @@ static void _indigoValidateMoleculeChirality(Molecule& mol) QS_DEF(Molecule, mirror); mirror.clone(mol, 0, 0); - for (int s = mirror.stereocenters.begin(); s != mirror.stereocenters.end(); s = mirror.stereocenters.next(s)) + for (auto s = mirror.stereocenters.begin(); s != mirror.stereocenters.end(); s = mirror.stereocenters.next(s)) { int atom = mirror.stereocenters.getAtomIndex(s); if (mirror.stereocenters.getType(atom) == MoleculeStereocenters::ATOM_ABS) @@ -544,7 +545,7 @@ static void _indigoValidateMoleculeChirality(Molecule& mol) if (!matcher.find()) return; - for (int s = mol.stereocenters.begin(); s != mol.stereocenters.end(); s = mol.stereocenters.next(s)) + for (auto s = mol.stereocenters.begin(); s != mol.stereocenters.end(); s = mol.stereocenters.next(s)) { int atom = mol.stereocenters.getAtomIndex(s); if (mol.stereocenters.getType(atom) == MoleculeStereocenters::ATOM_ABS) diff --git a/core/indigo-core/molecule/molecule_automorphism_search.h b/core/indigo-core/molecule/molecule_automorphism_search.h index e2c4b3d956..e1795fcaed 100644 --- a/core/indigo-core/molecule/molecule_automorphism_search.h +++ b/core/indigo-core/molecule/molecule_automorphism_search.h @@ -19,13 +19,17 @@ #ifndef __molecule_automorphism_search__ #define __molecule_automorphism_search__ +#include + #include "graph/automorphism_search.h" +#include "molecule/molecule_stereocenter_iterator.h" namespace indigo { class Molecule; class MoleculeStereocenters; + class StereocenterIteratorr; class CancellationHandler; class MoleculeAutomorphismSearch : public AutomorphismSearch @@ -65,7 +69,7 @@ namespace indigo static bool _check_automorphism(Graph& graph, const Array& mapping, const void* context); static bool _isCisTransBondMappedRigid(Molecule& mol, int i, const int* mapping); - static bool _isStereocenterMappedRigid(Molecule& mol, int i, const int* mapping); + static bool _isStereocenterMappedRigid(Molecule& mol, const StereocenterIterator& it, const int* mapping); static int _compare_mapped(Graph& graph, const Array& mapping1, const Array& mapping2, const void* context); @@ -84,7 +88,7 @@ namespace indigo void _getFirstApproximation(Molecule& mol); int _validCisTransBond(int idx, const Array& orbits); - int _validStereocenter(int idx, Array& orbits, int* parity = 0); + int _validStereocenter(const StereocenterIterator& it, Array& orbits, int* parity = 0); int _validStereocenterByAtom(int atom_idx, Array& orbits, int* parity = 0); int _treat_undef_as; @@ -130,7 +134,8 @@ namespace indigo TL_CP_DECL(Array, _cistrans_bond_state); // Target stereocenters and cis-trans bond for checking permutation parity - int _target_stereocenter, _target_bond; + std::unique_ptr _target_stereocenter; // should be replaced with std::optional after switch to C++17 + int _target_bond; bool _target_stereocenter_parity_inv, _target_bond_parity_inv; int _fixed_atom; diff --git a/core/indigo-core/molecule/molecule_cip_calculator.h b/core/indigo-core/molecule/molecule_cip_calculator.h index 2ef433ee7f..919dae87e0 100644 --- a/core/indigo-core/molecule/molecule_cip_calculator.h +++ b/core/indigo-core/molecule/molecule_cip_calculator.h @@ -27,6 +27,7 @@ namespace indigo { class BaseMolecule; class Molecule; + class StereocenterIterator; enum class CIPDesc { @@ -75,8 +76,8 @@ namespace indigo private: void _addCIPStereoDescriptors(BaseMolecule& mol); void _addCIPSgroups(BaseMolecule& mol, Array& atom_cip_desc, Array& bond_cip_desc); - void _calcRSStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, int idx, Array& atom_cip_desc, Array& stereo_passed, - bool use_stereo, Array& equiv_ligands, bool& digraph_cip_used); + void _calcRSStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, const StereocenterIterator& id, Array& atom_cip_desc, + Array& stereo_passed, bool use_stereo, Array& equiv_ligands, bool& digraph_cip_used); void _calcEZStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, int idx, Array& bond_cip_desc); bool _checkLigandsEquivalence(Array& ligands, Array& equiv_ligands, CIPContext& context); static int _getNumberOfStereoDescritors(const Array& atom_cip_desc); diff --git a/core/indigo-core/molecule/molecule_stereocenter_iterator.h b/core/indigo-core/molecule/molecule_stereocenter_iterator.h new file mode 100644 index 0000000000..78346cdd03 --- /dev/null +++ b/core/indigo-core/molecule/molecule_stereocenter_iterator.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * Copyright (C) from 2009 to Present EPAM Systems. + * + * This file is part of Indigo toolkit. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ + +#ifndef __molecule_stereocenter_iterator__ +#define __molecule_stereocenter_iterator__ + +#include "base_c/defs.h" +#include "molecule/molecule_stereocenters.h" + +#ifdef _WIN32 +#pragma warning(push) +#pragma warning(disable : 4251) +#endif + +namespace indigo +{ + + class DLLEXPORT StereocenterIterator + { + StereocenterIterator(MoleculeStereocenters::Container::const_iterator it); + + MoleculeStereocenters::Container::const_iterator _iterator; + + friend class MoleculeStereocenters; + + public: + bool operator==(const StereocenterIterator& rhs) const; + + bool operator!=(const StereocenterIterator& rhs) const; + }; + +} // namespace indigo + +#ifdef _WIN32 +#pragma warning(pop) +#endif + +#endif // __molecule_stereocenter_iterator__ diff --git a/core/indigo-core/molecule/molecule_stereocenters.h b/core/indigo-core/molecule/molecule_stereocenters.h index ebd890839e..7b8f2b4706 100644 --- a/core/indigo-core/molecule/molecule_stereocenters.h +++ b/core/indigo-core/molecule/molecule_stereocenters.h @@ -19,7 +19,9 @@ #ifndef __molecule_stereocenters__ #define __molecule_stereocenters__ -#include "base_cpp/red_black.h" +#include + +#include "base_cpp/array.h" #include "math/algebra.h" #ifdef _WIN32 @@ -31,10 +33,21 @@ namespace indigo { class Filter; class StereocentersOptions; + class StereocenterIterator; class BaseMolecule; class DLLEXPORT MoleculeStereocenters { + struct _Atom + { + int type; // ANY, AND, OR, ABS + int group; // stereogroup index + // [X, Y, Z, W] -- atom indices or -1 for implicit hydrogen + // (X, Y, Z) go counterclockwise when looking from W. + // if there are pure (implicit) hydrogen, it is W + int pyramid[4]; + }; + public: enum { @@ -45,6 +58,11 @@ namespace indigo }; explicit MoleculeStereocenters(); + MoleculeStereocenters(const MoleculeStereocenters&) = delete; // no implicit copy + MoleculeStereocenters(MoleculeStereocenters&&) = default; + + MoleculeStereocenters& operator=(const MoleculeStereocenters&) = delete; // no implicit copy + MoleculeStereocenters& operator=(MoleculeStereocenters&&) = default; void clear(); @@ -69,7 +87,6 @@ namespace indigo void add_ignore(BaseMolecule& baseMolecule, int atom_idx, int type, int group, bool inverse_pyramid); void add_ignore(BaseMolecule& baseMolecule, int atom_idx, int type, int group, const int pyramid[4]); - void get(int i, int& atom_idx, int& type, int& group, int* pyramid) const; void remove(int idx); bool exists(int atom_idx) const; @@ -101,11 +118,12 @@ namespace indigo void flipBond(int atom_parent, int atom_from, int atom_to); - int begin() const; - int end() const; - int next(int i) const; + StereocenterIterator begin() const; + StereocenterIterator end() const; + StereocenterIterator next(const StereocenterIterator& it) const; - int getAtomIndex(int i) const; + void get(const StereocenterIterator& it, int& atom_idx, int& type, int& group, int* pyramid) const; + int getAtomIndex(const StereocenterIterator& it) const; bool isPossibleStereocenter(BaseMolecule& baseMolecule, int atom_idx, bool* possible_implicit_h = 0, bool* possible_lone_pair = 0); @@ -120,7 +138,7 @@ namespace indigo static void moveMinimalToEnd(int pyramid[4]); static void moveElementToEnd(int pyramid[4], int element); - static bool isAutomorphism(BaseMolecule& mol, const Array& mapping, const Filter* filter = NULL); + static bool isAutomorphism(BaseMolecule& mol, const Array& mapping); DECL_ERROR; @@ -129,16 +147,6 @@ namespace indigo static void rotatePyramid(int* pyramid); private: - struct _Atom - { - int type; // ANY, AND, OR, ABS - int group; // stereogroup index - // [X, Y, Z, W] -- atom indices or -1 for implicit hydrogen - // (X, Y, Z) go counterclockwise when looking from W. - // if there are pure (implicit) hydrogen, it is W - int pyramid[4]; - }; - struct _EdgeIndVec { int edge_idx; @@ -156,7 +164,8 @@ namespace indigo int implicit_degree; }; - RedBlackMap _stereocenters; + using Container = std::map; + Container _stereocenters; static int _sign(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3); static int _xyzzy(const Vec3f& v1, const Vec3f& v2, const Vec3f& u); @@ -177,7 +186,7 @@ namespace indigo int _getDirection(BaseMolecule& mol, int atom_from, int atom_to, bool bidirectional_mode); - MoleculeStereocenters(const MoleculeStereocenters&); // no implicit copy + friend class StereocenterIterator; }; } // namespace indigo diff --git a/core/indigo-core/molecule/src/inchi_wrapper.cpp b/core/indigo-core/molecule/src/inchi_wrapper.cpp index 5da196f263..c650b2d20d 100644 --- a/core/indigo-core/molecule/src/inchi_wrapper.cpp +++ b/core/indigo-core/molecule/src/inchi_wrapper.cpp @@ -25,6 +25,7 @@ #include "molecule/elements.h" #include "molecule/molecule.h" #include "molecule/molecule_dearom.h" +#include "molecule/molecule_stereocenter_iterator.h" // #include "mode.h" using namespace indigo; @@ -521,7 +522,7 @@ void InchiWrapper::generateInchiInput(Molecule& mol, inchi_Input& input, Array& orbits, int* parity) +int MoleculeAutomorphismSearch::_validStereocenter(const StereocenterIterator& it, Array& orbits, int* parity) { Molecule& mol = *(Molecule*)_given_graph; - int atom_index = mol.stereocenters.getAtomIndex(idx); + int atom_index = mol.stereocenters.getAtomIndex(it); return _validStereocenterByAtom(atom_index, orbits, parity); } @@ -945,7 +946,7 @@ void MoleculeAutomorphismSearch::_markValidOrInvalidStereo(bool find_valid, Arra } const MoleculeStereocenters& stereocenters = mol.stereocenters; - for (int i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) + for (auto i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) { int validity = _validStereocenter(i, orbits); if (validity == _UNDEF) @@ -979,8 +980,8 @@ void MoleculeAutomorphismSearch::_automorphismCallback(const int* automorphism, MoleculeAutomorphismSearch& self = *(MoleculeAutomorphismSearch*)context; Molecule& mol = *(Molecule*)self._given_graph; - if (self._target_stereocenter != -1) - if (!_isStereocenterMappedRigid(mol, self._target_stereocenter, automorphism)) + if (self._target_stereocenter) + if (!_isStereocenterMappedRigid(mol, *self._target_stereocenter, automorphism)) self._target_stereocenter_parity_inv = true; if (self._target_bond != -1) @@ -988,13 +989,13 @@ void MoleculeAutomorphismSearch::_automorphismCallback(const int* automorphism, self._target_bond_parity_inv = true; } -bool MoleculeAutomorphismSearch::_isStereocenterMappedRigid(Molecule& mol, int i, const int* mapping) +bool MoleculeAutomorphismSearch::_isStereocenterMappedRigid(Molecule& mol, const StereocenterIterator& it, const int* mapping) { int idx, type, group; int pyramid[4]; int j; - mol.stereocenters.get(i, idx, type, group, pyramid); + mol.stereocenters.get(it, idx, type, group, pyramid); if (mapping[idx] == -1) return true; @@ -1072,7 +1073,7 @@ bool MoleculeAutomorphismSearch::_findInvalidStereo(Molecule& mol) invalid_stereo.clear(); _target_bond = -1; MoleculeStereocenters& stereocenters = mol.stereocenters; - for (int i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) + for (auto i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) { int atom_index = stereocenters.getAtomIndex(i); if (ignored_vertices != 0 && ignored_vertices[atom_index]) @@ -1083,7 +1084,15 @@ bool MoleculeAutomorphismSearch::_findInvalidStereo(Molecule& mol) _stereocenter_state[atom_index] = _INVALID; - _target_stereocenter = i; + if (!_target_stereocenter) + { + _target_stereocenter = std::make_unique(std::move(i)); + } + else + { + *_target_stereocenter = i; + } + _fixed_atom = atom_index; _target_stereocenter_parity_inv = false; @@ -1095,7 +1104,7 @@ bool MoleculeAutomorphismSearch::_findInvalidStereo(Molecule& mol) if (type == MoleculeStereocenters::ATOM_AND || type == MoleculeStereocenters::ATOM_OR) { // Mark whole group as absolute - for (int j = stereocenters.begin(); j != stereocenters.end(); j = stereocenters.next(j)) + for (auto j = stereocenters.begin(); j != stereocenters.end(); j = stereocenters.next(j)) { int atom_index2 = stereocenters.getAtomIndex(j); if (atom_index2 == atom_index) @@ -1131,7 +1140,7 @@ bool MoleculeAutomorphismSearch::_findInvalidStereo(Molecule& mol) invalid_found = true; } - _target_stereocenter = -1; + _target_stereocenter = {}; // // Step 2: find valid and invalid cis-trans bonds diff --git a/core/indigo-core/molecule/src/molecule_cip_calculator.cpp b/core/indigo-core/molecule/src/molecule_cip_calculator.cpp index 567ebeff72..217e1a6390 100644 --- a/core/indigo-core/molecule/src/molecule_cip_calculator.cpp +++ b/core/indigo-core/molecule/src/molecule_cip_calculator.cpp @@ -23,6 +23,7 @@ #include "molecule/elements.h" #include "molecule/molecule.h" #include "molecule/molecule_automorphism_search.h" +#include "molecule/molecule_stereocenter_iterator.h" #include "molecule/molecule_stereocenter_options.h" #include "molecule/molecule_stereocenters.h" #include "molecule/molfile_saver.h" @@ -62,7 +63,7 @@ void MoleculeCIPCalculator::_addCIPStereoDescriptors(BaseMolecule& mol) else unfolded_h_mol = std::make_unique(); QS_DEF(Array, markers); - QS_DEF(Array, stereo_passed); + QS_DEF(Array, stereo_passed); QS_DEF(Array, ignored); @@ -241,8 +242,8 @@ void MoleculeCIPCalculator::_addCIPSgroups(BaseMolecule& mol, Array& at } } -void MoleculeCIPCalculator::_calcRSStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, int idx, Array& atom_cip_desc, - Array& stereo_passed, bool use_stereo, Array& equiv_ligands, bool& digraph_cip_used) +void MoleculeCIPCalculator::_calcRSStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, const StereocenterIterator& it, + Array& atom_cip_desc, Array& stereo_passed, bool use_stereo, Array& equiv_ligands, bool& digraph_cip_used) { Array ligands; Array used1; @@ -256,7 +257,7 @@ void MoleculeCIPCalculator::_calcRSStereoDescriptor(BaseMolecule& mol, BaseMolec int parity = 0; int cip_parity = 0; - mol.stereocenters.get(idx, atom_idx, type, group, pyramid); + mol.stereocenters.get(it, atom_idx, type, group, pyramid); if (type <= MoleculeStereocenters::ATOM_ANY) return; @@ -288,7 +289,7 @@ void MoleculeCIPCalculator::_calcRSStereoDescriptor(BaseMolecule& mol, BaseMolec { if (!use_stereo) { - stereo_passed.push(idx); + stereo_passed.push(it); atom_cip_desc[atom_idx] = CIPDesc::UNKNOWN; } else if (mol.vertexInRing(atom_idx)) @@ -443,7 +444,7 @@ CIPDesc MoleculeCIPCalculator::_calcCIPDigraphDescriptor(BaseMolecule& mol, int QS_DEF(Array, atom_cip_desc); QS_DEF(Array, bond_cip_desc); QS_DEF(Array, markers); - QS_DEF(Array, stereo_passed); + QS_DEF(Array, stereo_passed); QS_DEF(Array, ignored); diff --git a/core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp b/core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp new file mode 100644 index 0000000000..97b3228828 --- /dev/null +++ b/core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp @@ -0,0 +1,35 @@ +/**************************************************************************** + * Copyright (C) from 2009 to Present EPAM Systems. + * + * This file is part of Indigo toolkit. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ + +#include "molecule/molecule_stereocenter_iterator.h" + +using namespace indigo; + +StereocenterIterator::StereocenterIterator(MoleculeStereocenters::Container::const_iterator it) : _iterator {it} +{ +} + +bool StereocenterIterator::operator==(const StereocenterIterator& rhs) const +{ + return _iterator == rhs._iterator; +} + +bool StereocenterIterator::operator!=(const StereocenterIterator& rhs) const +{ + return !(*this == rhs); +} diff --git a/core/indigo-core/molecule/src/molecule_stereocenters.cpp b/core/indigo-core/molecule/src/molecule_stereocenters.cpp index 8ac0911db6..d440498615 100644 --- a/core/indigo-core/molecule/src/molecule_stereocenters.cpp +++ b/core/indigo-core/molecule/src/molecule_stereocenters.cpp @@ -23,6 +23,7 @@ #include "molecule/haworth_projection_finder.h" #include "molecule/molecule.h" #include "molecule/molecule_automorphism_search.h" +#include "molecule/molecule_stereocenter_iterator.h" #include "molecule/molecule_stereocenter_options.h" #include #include @@ -358,7 +359,7 @@ bool MoleculeStereocenters::_buildOneCenter(BaseMolecule& baseMolecule, int atom if (getDir(atom_idx, edge_ids[i].nei_idx) > 0) sensible_bonds_out[edge_ids[i].edge_idx] = 1; } - _stereocenters.insert(atom_idx, stereocenter); + _stereocenters.emplace(atom_idx, stereocenter); return true; } @@ -587,7 +588,7 @@ bool MoleculeStereocenters::_buildOneCenter(BaseMolecule& baseMolecule, int atom if (getDir(atom_idx, edge_ids[i].nei_idx) > 0) sensible_bonds_out[edge_ids[i].edge_idx] = 1; - _stereocenters.insert(atom_idx, stereocenter); + _stereocenters.emplace(atom_idx, stereocenter); return true; } @@ -679,12 +680,8 @@ int MoleculeStereocenters::_onPlane(const Vec3f& v1, const Vec3f& v2, const Vec3 int MoleculeStereocenters::getType(int idx) const { - _Atom* atom = _stereocenters.at2(idx); - - if (atom == 0) - return 0; - - return atom->type; + const auto it = _stereocenters.find(idx); + return it != _stereocenters.end() ? it->second.type : 0; } int MoleculeStereocenters::getGroup(int idx) const @@ -715,12 +712,8 @@ const int* MoleculeStereocenters::getPyramid(int idx) const int* MoleculeStereocenters::getPyramid(int idx) { - _Atom* stereo = _stereocenters.at2(idx); - - if (stereo != 0) - return stereo->pyramid; - else - return 0; + const auto it = _stereocenters.find(idx); + return it != _stereocenters.end() ? it->second.pyramid : nullptr; } void MoleculeStereocenters::invertPyramid(int idx) @@ -733,10 +726,10 @@ void MoleculeStereocenters::getAbsAtoms(Array& indices) { indices.clear(); - for (int i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + for(const auto& pair: _stereocenters) { - if (_stereocenters.value(i).type == ATOM_ABS) - indices.push(_stereocenters.key(i)); + if (pair.second.type == ATOM_ABS) + indices.push(pair.first); } } @@ -744,11 +737,11 @@ void MoleculeStereocenters::_getGroups(int type, Array& numbers) { numbers.clear(); - for (int i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + for (const auto& pair : _stereocenters) { - if (_stereocenters.value(i).type == type) + if (pair.second.type == type) { - int group = _stereocenters.value(i).group; + int group = pair.second.group; if (numbers.find(group) == -1) numbers.push(group); @@ -760,12 +753,12 @@ void MoleculeStereocenters::_getGroup(int type, int number, Array& indices) { indices.clear(); - for (int i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + for (const auto& pair : _stereocenters) { - const _Atom& atom = _stereocenters.value(i); + const _Atom& atom = pair.second; if (atom.type == type && atom.group == number) - indices.push(_stereocenters.key(i)); + indices.push(pair.first); } } @@ -791,15 +784,17 @@ void MoleculeStereocenters::getAndGroup(int number, Array& indices) bool MoleculeStereocenters::sameGroup(int idx1, int idx2) { - _Atom* center1 = _stereocenters.at2(idx1); - _Atom* center2 = _stereocenters.at2(idx2); + const auto it1 = _stereocenters.find(idx1); + const auto it2 = _stereocenters.find(idx2); - if (center1 == 0 && center2 == 0) + if (it1 == _stereocenters.end() && it2 == _stereocenters.end()) return true; - if (center1 == 0 || center2 == 0) + if (it1 == _stereocenters.end() || it2 == _stereocenters.end()) return false; + const _Atom* center1 = &(it1->second); + const _Atom* center2 = &(it2->second); if (center1->type == ATOM_ABS) return center2->type == ATOM_ABS; @@ -816,8 +811,8 @@ bool MoleculeStereocenters::haveAllAbs() { int i; - for (i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) - if (_stereocenters.value(i).type != ATOM_ABS) + for(const auto& pair: _stereocenters) + if (pair.second.type != ATOM_ABS) return false; return true; @@ -827,8 +822,8 @@ bool MoleculeStereocenters::haveAbs() { int i; - for (i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) - if (_stereocenters.value(i).type == ATOM_ABS) + for (const auto& pair : _stereocenters) + if (pair.second.type == ATOM_ABS) return true; return false; @@ -838,8 +833,8 @@ bool MoleculeStereocenters::haveAllAbsAny() { int i; - for (i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) - if (_stereocenters.value(i).type != ATOM_ABS && _stereocenters.value(i).type != ATOM_ANY) + for (const auto& pair : _stereocenters) + if (pair.second.type != ATOM_ABS && pair.second.type != ATOM_ANY) return false; return true; @@ -850,15 +845,15 @@ bool MoleculeStereocenters::haveAllAndAny() int i; int groupno = -1; - for (i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + for (const auto& pair : _stereocenters) { - if (_stereocenters.value(i).type == ATOM_ANY) + if (pair.second.type == ATOM_ANY) continue; - if (_stereocenters.value(i).type != ATOM_AND) + if (pair.second.type != ATOM_AND) return false; if (groupno == -1) - groupno = _stereocenters.value(i).group; - else if (groupno != _stereocenters.value(i).group) + groupno = pair.second.group; + else if (groupno != pair.second.group) return false; } @@ -867,22 +862,17 @@ bool MoleculeStereocenters::haveAllAndAny() bool MoleculeStereocenters::checkSub(BaseMolecule& query, BaseMolecule& target, const int* mapping, bool reset_h_isotopes, Filter* stereocenters_vertex_filter) { - QS_DEF(Array, flags); - - flags.clear_resize(query.stereocenters._stereocenters.end()); - flags.zerofill(); - - int i, j; + std::set flags; - for (i = query.stereocenters._stereocenters.begin(); i != query.stereocenters._stereocenters.end(); i = query.stereocenters._stereocenters.next(i)) + for (auto it_i = query.stereocenters._stereocenters.begin(); it_i != query.stereocenters._stereocenters.end(); ++it_i) { - if (flags[i]) + int iq = it_i->first; + if (flags.find(iq) != flags.end()) continue; - flags[i] = 1; + flags.insert(iq); - const _Atom& cq = query.stereocenters._stereocenters.value(i); - int iq = query.stereocenters._stereocenters.key(i); + const _Atom& cq = it_i->second; if (mapping[iq] < 0) continue; // happens only on Exact match (when some query fragments are disabled) @@ -917,10 +907,10 @@ bool MoleculeStereocenters::checkSub(BaseMolecule& query, BaseMolecule& target, } else if (type == ATOM_OR || type == ATOM_AND) { - for (j = i; j != query.stereocenters._stereocenters.end(); j = query.stereocenters._stereocenters.next(j)) + for (auto it_j = it_i; it_j != query.stereocenters._stereocenters.end(); ++it_j) { - int iq2 = query.stereocenters._stereocenters.key(j); - const _Atom& cq2 = query.stereocenters._stereocenters.value(j); + int iq2 = it_j->first; + const _Atom& cq2 = it_j->second; if (cq2.type != type) continue; @@ -928,17 +918,17 @@ bool MoleculeStereocenters::checkSub(BaseMolecule& query, BaseMolecule& target, if (cq2.group != cq.group) continue; - const _Atom* ct2 = target.stereocenters._stereocenters.at2(mapping[iq2]); - - if (ct2 == 0) + const auto& it_ct2 = target.stereocenters._stereocenters.find(mapping[iq2]); + if (it_ct2 == target.stereocenters._stereocenters.end()) return false; - if (ct2->type < type) + const _Atom& ct2 = it_ct2->second; + if (ct2.type < type) return false; - flags[j] = 1; + flags.insert(iq2); - if (ct2->type == ATOM_AND) + if (ct2.type == ATOM_AND) { if (stereo_group_or != -1) return false; @@ -946,11 +936,11 @@ bool MoleculeStereocenters::checkSub(BaseMolecule& query, BaseMolecule& target, return false; if (stereo_group_and == -1) - stereo_group_and = ct2->group; - else if (stereo_group_and != ct2->group) + stereo_group_and = ct2.group; + else if (stereo_group_and != ct2.group) return false; } - else if (ct2->type == ATOM_OR) + else if (ct2.type == ATOM_OR) { if (stereo_group_and != -1) return false; @@ -958,11 +948,11 @@ bool MoleculeStereocenters::checkSub(BaseMolecule& query, BaseMolecule& target, return false; if (stereo_group_or == -1) - stereo_group_or = ct2->group; - else if (stereo_group_or != ct2->group) + stereo_group_or = ct2.group; + else if (stereo_group_or != ct2.group) return false; } - else if (ct2->type == ATOM_ABS) + else if (ct2.type == ATOM_ABS) { if (stereo_group_and != -1) return false; @@ -1142,7 +1132,7 @@ void MoleculeStereocenters::getPyramidMapping(BaseMolecule& query, BaseMolecule& void MoleculeStereocenters::remove(int idx) { - _stereocenters.remove(idx); + _stereocenters.erase(idx); } void MoleculeStereocenters::removeAtoms(BaseMolecule& baseMolecule, const Array& indices) @@ -1150,8 +1140,10 @@ void MoleculeStereocenters::removeAtoms(BaseMolecule& baseMolecule, const Array< for (int i = 0; i < indices.size(); i++) { int idx = indices[i]; - if (_stereocenters.find(idx)) - _stereocenters.remove(idx); + + const auto& it = _stereocenters.find(idx); + if (it != _stereocenters.end()) + _stereocenters.erase(it); else { const Vertex& vertex = baseMolecule.getVertex(idx); @@ -1178,26 +1170,26 @@ void MoleculeStereocenters::removeBonds(BaseMolecule& baseMolecule, const Array< void MoleculeStereocenters::_removeBondDir(BaseMolecule& baseMolecule, int atom_from, int atom_to) { - _Atom* stereo_atom = _stereocenters.at2(atom_to); - if (stereo_atom != 0) + const auto& it = _stereocenters.find(atom_to); + if (it != _stereocenters.end()) { - if (stereo_atom->pyramid[3] == -1) - _stereocenters.remove(atom_to); + if (it->second.pyramid[3] == -1) + _stereocenters.erase(atom_to); else { if (!baseMolecule.isQueryMolecule() || baseMolecule.possibleAtomNumber(atom_from, ELEM_H) || baseMolecule.isRSite(atom_from)) - _convertAtomToImplicitHydrogen(stereo_atom->pyramid, atom_from); + _convertAtomToImplicitHydrogen(it->second.pyramid, atom_from); } } } void MoleculeStereocenters::buildOnSubmolecule(BaseMolecule& baseMolecule, const BaseMolecule& super, int* mapping) { - int i, j; - for (i = super.stereocenters._stereocenters.begin(); i != super.stereocenters._stereocenters.end(); i = super.stereocenters._stereocenters.next(i)) + const auto& super_stereocenters = super.stereocenters._stereocenters; + for (const auto& pair : super_stereocenters) { - int super_idx = super.stereocenters._stereocenters.key(i); - const _Atom& super_stereocenter = super.stereocenters._stereocenters.value(i); + int super_idx = pair.first; + const _Atom& super_stereocenter = pair.second; int sub_idx = mapping[super_idx]; if (sub_idx < 0) @@ -1208,7 +1200,7 @@ void MoleculeStereocenters::buildOnSubmolecule(BaseMolecule& baseMolecule, const new_stereocenter.group = super_stereocenter.group; new_stereocenter.type = super_stereocenter.type; - for (j = 0; j < 4; j++) + for (int j = 0; j < 4; j++) { int idx = super_stereocenter.pyramid[j]; @@ -1228,11 +1220,11 @@ void MoleculeStereocenters::buildOnSubmolecule(BaseMolecule& baseMolecule, const // pyramid is not mapped completely continue; - _stereocenters.insert(sub_idx, new_stereocenter); + _stereocenters.emplace(sub_idx, std::move(new_stereocenter)); const Vertex& super_vertex = super.getVertex(super_idx); - for (j = super_vertex.neiBegin(); j != super_vertex.neiEnd(); j = super_vertex.neiNext(j)) + for (int j = super_vertex.neiBegin(); j != super_vertex.neiEnd(); j = super_vertex.neiNext(j)) { int super_edge = super_vertex.neiEdge(j); if (mapping[super_vertex.neiVertex(j)] == -1) @@ -1270,7 +1262,7 @@ void MoleculeStereocenters::add(BaseMolecule& baseMolecule, int atom_idx, int ty center.group = group; memcpy(center.pyramid, pyramid, 4 * sizeof(int)); - _stereocenters.insert(atom_idx, center); + _stereocenters.emplace(atom_idx, std::move(center)); } void MoleculeStereocenters::add_ignore(BaseMolecule& baseMolecule, int atom_idx, int type, int group, bool inverse_pyramid) @@ -1291,43 +1283,44 @@ void MoleculeStereocenters::add_ignore(BaseMolecule& baseMolecule, int atom_idx, center.group = group; memcpy(center.pyramid, pyramid, 4 * sizeof(int)); - _stereocenters.insert(atom_idx, center); + _stereocenters.emplace(atom_idx, std::move(center)); } -int MoleculeStereocenters::begin() const +StereocenterIterator MoleculeStereocenters::begin() const { - return _stereocenters.begin(); + return {_stereocenters.begin()}; } -int MoleculeStereocenters::end() const +StereocenterIterator MoleculeStereocenters::end() const { - return _stereocenters.end(); + return {_stereocenters.end()}; } -int MoleculeStereocenters::next(int i) const +StereocenterIterator MoleculeStereocenters::next(const StereocenterIterator& it) const { - return _stereocenters.next(i); + auto new_it = it._iterator; + return {++new_it}; } bool MoleculeStereocenters::exists(int atom_idx) const { - return _stereocenters.at2(atom_idx) != 0; + return _stereocenters.find(atom_idx) != _stereocenters.end(); } -void MoleculeStereocenters::get(int i, int& atom_idx, int& type, int& group, int* pyramid) const +void MoleculeStereocenters::get(const StereocenterIterator& it, int& atom_idx, int& type, int& group, int* pyramid) const { - const _Atom& center = _stereocenters.value(i); + const _Atom& center = it._iterator->second; - atom_idx = _stereocenters.key(i); + atom_idx = it._iterator->first; type = center.type; group = center.group; if (pyramid != 0) memcpy(pyramid, center.pyramid, 4 * sizeof(int)); } -int MoleculeStereocenters::getAtomIndex(int i) const +int MoleculeStereocenters::getAtomIndex(const StereocenterIterator& it) const { - return _stereocenters.key(i); + return it._iterator->first; } void MoleculeStereocenters::get(int atom_idx, int& type, int& group, int* pyramid) const @@ -1342,50 +1335,53 @@ void MoleculeStereocenters::get(int atom_idx, int& type, int& group, int* pyrami void MoleculeStereocenters::registerUnfoldedHydrogen(int atom_idx, int added_hydrogen) { - _Atom* center = _stereocenters.at2(atom_idx); - if (center == 0) + auto it = _stereocenters.find(atom_idx); + if (it == _stereocenters.end()) return; - if (center->pyramid[3] != -1) + if (it->second.pyramid[3] != -1) throw Error("cannot unfold hydrogens for stereocenter without implicit hydrogens"); - center->pyramid[3] = added_hydrogen; + it->second.pyramid[3] = added_hydrogen; } void MoleculeStereocenters::flipBond(int atom_parent, int atom_from, int atom_to) { - if (exists(atom_from)) + auto from_it = _stereocenters.find(atom_from); + if (from_it != _stereocenters.end()) { - _Atom* from_center = _stereocenters.at2(atom_from); + _Atom& from_center = from_it->second; - if (from_center->pyramid[3] == -1) + if (from_center.pyramid[3] == -1) remove(atom_from); else { for (int i = 0; i < 4; i++) - if (from_center->pyramid[i] == atom_parent) - from_center->pyramid[i] = -1; - moveMinimalToEnd(from_center->pyramid); + if (from_center.pyramid[i] == atom_parent) + from_center.pyramid[i] = -1; + moveMinimalToEnd(from_center.pyramid); } } - if (exists(atom_to)) + auto to_it = _stereocenters.find(atom_to); + if (to_it != _stereocenters.end()) { - _Atom* to_center = _stereocenters.at2(atom_to); + _Atom& to_center = to_it->second; - if (to_center->pyramid[3] != -1) + if (to_center.pyramid[3] != -1) throw Error("Bad bond flipping. Stereocenter pyramid is already full"); - to_center->pyramid[3] = atom_parent; + to_center.pyramid[3] = atom_parent; } - if (!exists(atom_parent)) + auto parent_it = _stereocenters.find(atom_parent); + if (parent_it == _stereocenters.end()) return; - _Atom* center = _stereocenters.at2(atom_parent); + _Atom& center = parent_it->second; for (int i = 0; i < 4; i++) - if (center->pyramid[i] == atom_from) + if (center.pyramid[i] == atom_from) { - center->pyramid[i] = atom_to; + center.pyramid[i] = atom_to; break; } } @@ -1519,11 +1515,11 @@ void MoleculeStereocenters::_convertAtomToImplicitHydrogen(int pyramid[4], int a void MoleculeStereocenters::markBond(BaseMolecule& baseMolecule, int atom_idx) { - const _Atom* atom_ptr = _stereocenters.at2(atom_idx); - if (atom_ptr == NULL) + const auto atom_it = _stereocenters.find(atom_idx); + if (atom_it == _stereocenters.end()) return; - const _Atom& atom = *atom_ptr; + const _Atom& atom = atom_it->second; int pyramid[4]; int mult = 1; int size = 0; @@ -1654,21 +1650,16 @@ void MoleculeStereocenters::markBond(BaseMolecule& baseMolecule, int atom_idx) void MoleculeStereocenters::markBonds(BaseMolecule& baseMolecule) { - int i; - - for (i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) - markBond(baseMolecule, _stereocenters.key(i)); + for (const auto& pair: _stereocenters) + markBond(baseMolecule, pair.first); } -bool MoleculeStereocenters::isAutomorphism(BaseMolecule& mol, const Array& mapping, const Filter* filter) +bool MoleculeStereocenters::isAutomorphism(BaseMolecule& mol, const Array& mapping) { MoleculeStereocenters& stereocenters = mol.stereocenters; - for (int i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) + for (auto i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) { - if (filter && !filter->valid(i)) - continue; - int idx, type, group; int pyramid[4]; int j; diff --git a/core/indigo-core/molecule/src/smiles_loader.cpp b/core/indigo-core/molecule/src/smiles_loader.cpp index e822949d29..2bd00b808c 100644 --- a/core/indigo-core/molecule/src/smiles_loader.cpp +++ b/core/indigo-core/molecule/src/smiles_loader.cpp @@ -23,6 +23,7 @@ #include "graph/cycle_basis.h" #include "molecule/elements.h" #include "molecule/molecule.h" +#include "molecule/molecule_stereocenter_iterator.h" #include "molecule/molecule_stereocenters.h" #include "molecule/query_molecule.h" #include "molecule/smiles_loader.h" @@ -768,7 +769,7 @@ void SmilesLoader::_readOtherStuff() { // All stereocenters are relative instead of abs MoleculeStereocenters& s = _bmol->stereocenters; - for (int i = s.begin(); i != s.end(); i = s.next(i)) + for (auto i = s.begin(); i != s.end(); i = s.next(i)) { int atom = s.getAtomIndex(i); if (s.getType(atom) == MoleculeStereocenters::ATOM_ABS) diff --git a/core/indigo-core/molecule/src/smiles_saver.cpp b/core/indigo-core/molecule/src/smiles_saver.cpp index c0bf11c06d..2bea3d40de 100644 --- a/core/indigo-core/molecule/src/smiles_saver.cpp +++ b/core/indigo-core/molecule/src/smiles_saver.cpp @@ -28,6 +28,7 @@ #include "molecule/molecule_arom_match.h" #include "molecule/molecule_rgroups.h" #include "molecule/molecule_savers.h" +#include "molecule/molecule_stereocenter_iterator.h" #include "molecule/molecule_stereocenters.h" #include "molecule/query_molecule.h" @@ -256,7 +257,7 @@ void SmilesSaver::_saveMolecule() // detect chiral configurations MoleculeStereocenters& stereocenters = _bmol->stereocenters; - for (i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) + for (auto i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) { int atom_idx, type, group, pyramid[4]; @@ -1464,9 +1465,10 @@ void SmilesSaver::_writeStereogroups() { BaseMolecule& mol = *_bmol; MoleculeStereocenters& stereocenters = mol.stereocenters; - int i, j; + int j; - for (i = stereocenters.begin(); i != stereocenters.end(); i = stereocenters.next(i)) + StereocenterIterator i = stereocenters.begin(); + for (; i != stereocenters.end(); i = stereocenters.next(i)) { int atom, type, group; stereocenters.get(i, atom, type, group, 0); @@ -1486,7 +1488,7 @@ void SmilesSaver::_writeStereogroups() marked.clear_resize(_written_atoms.size()); marked.zerofill(); - for (i = 0; i < _written_atoms.size(); i++) + for (int i = 0; i < _written_atoms.size(); i++) { if (marked[i]) continue; diff --git a/core/render2d/src/render_internal.cpp b/core/render2d/src/render_internal.cpp index 332afb9fac..7d6b916c8c 100644 --- a/core/render2d/src/render_internal.cpp +++ b/core/render2d/src/render_internal.cpp @@ -23,6 +23,7 @@ #include "base_cpp/tree.h" #include "molecule/ket_commons.h" #include "molecule/molecule.h" +#include "molecule/molecule_stereocenter_iterator.h" #include "molecule/query_molecule.h" #include "reaction/query_reaction.h" #include "reaction/reaction.h" @@ -1402,7 +1403,7 @@ void MoleculeRenderInternal::_determineStereoGroupsMode() return; bool allAbs = true, singleAndGroup = true, none = true; int andGid = -1; - for (int i = sc.begin(); i < sc.end(); i = sc.next(i)) + for (auto i = sc.begin(); i != sc.end(); i = sc.next(i)) { int aid, type, gid, pyramid[4]; sc.get(i, aid, type, gid, pyramid); @@ -1441,7 +1442,7 @@ void MoleculeRenderInternal::_determineStereoGroupsMode() _lopt.stereoMode = STEREOGROUPS_SHOW; int aid, type, groupId, pyramid[4]; - for (int i = sc.begin(); i < sc.end(); i = sc.next(i)) + for (auto i = sc.begin(); i != sc.end(); i = sc.next(i)) { sc.get(i, aid, type, groupId, pyramid); AtomDesc& ad = _ad(aid); From 8bec5a128c50e97ae4de35aee3443356a62b45b1 Mon Sep 17 00:00:00 2001 From: Alexander Stepaniuk Date: Sun, 25 Sep 2022 17:27:35 +0300 Subject: [PATCH 2/6] Static analyzer issues fixes --- core/indigo-core/molecule/molecule_cip_calculator.h | 2 +- core/indigo-core/molecule/src/molecule_cip_calculator.cpp | 3 ++- .../molecule/src/molecule_stereocenter_iterator.cpp | 2 +- core/indigo-core/molecule/src/molecule_stereocenters.cpp | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/indigo-core/molecule/molecule_cip_calculator.h b/core/indigo-core/molecule/molecule_cip_calculator.h index 919dae87e0..553e3d7471 100644 --- a/core/indigo-core/molecule/molecule_cip_calculator.h +++ b/core/indigo-core/molecule/molecule_cip_calculator.h @@ -77,7 +77,7 @@ namespace indigo void _addCIPStereoDescriptors(BaseMolecule& mol); void _addCIPSgroups(BaseMolecule& mol, Array& atom_cip_desc, Array& bond_cip_desc); void _calcRSStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, const StereocenterIterator& id, Array& atom_cip_desc, - Array& stereo_passed, bool use_stereo, Array& equiv_ligands, bool& digraph_cip_used); + Array& stereo_passed, bool use_stereo, Array& equiv_ligands, bool& digraph_cip_used); void _calcEZStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, int idx, Array& bond_cip_desc); bool _checkLigandsEquivalence(Array& ligands, Array& equiv_ligands, CIPContext& context); static int _getNumberOfStereoDescritors(const Array& atom_cip_desc); diff --git a/core/indigo-core/molecule/src/molecule_cip_calculator.cpp b/core/indigo-core/molecule/src/molecule_cip_calculator.cpp index 217e1a6390..441ff757ba 100644 --- a/core/indigo-core/molecule/src/molecule_cip_calculator.cpp +++ b/core/indigo-core/molecule/src/molecule_cip_calculator.cpp @@ -243,7 +243,8 @@ void MoleculeCIPCalculator::_addCIPSgroups(BaseMolecule& mol, Array& at } void MoleculeCIPCalculator::_calcRSStereoDescriptor(BaseMolecule& mol, BaseMolecule& unfolded_h_mol, const StereocenterIterator& it, - Array& atom_cip_desc, Array& stereo_passed, bool use_stereo, Array& equiv_ligands, bool& digraph_cip_used) + Array& atom_cip_desc, Array& stereo_passed, bool use_stereo, + Array& equiv_ligands, bool& digraph_cip_used) { Array ligands; Array used1; diff --git a/core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp b/core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp index 97b3228828..383e9eeadd 100644 --- a/core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp +++ b/core/indigo-core/molecule/src/molecule_stereocenter_iterator.cpp @@ -20,7 +20,7 @@ using namespace indigo; -StereocenterIterator::StereocenterIterator(MoleculeStereocenters::Container::const_iterator it) : _iterator {it} +StereocenterIterator::StereocenterIterator(MoleculeStereocenters::Container::const_iterator it) : _iterator{it} { } diff --git a/core/indigo-core/molecule/src/molecule_stereocenters.cpp b/core/indigo-core/molecule/src/molecule_stereocenters.cpp index d440498615..50717c559c 100644 --- a/core/indigo-core/molecule/src/molecule_stereocenters.cpp +++ b/core/indigo-core/molecule/src/molecule_stereocenters.cpp @@ -726,7 +726,7 @@ void MoleculeStereocenters::getAbsAtoms(Array& indices) { indices.clear(); - for(const auto& pair: _stereocenters) + for (const auto& pair : _stereocenters) { if (pair.second.type == ATOM_ABS) indices.push(pair.first); @@ -811,7 +811,7 @@ bool MoleculeStereocenters::haveAllAbs() { int i; - for(const auto& pair: _stereocenters) + for (const auto& pair : _stereocenters) if (pair.second.type != ATOM_ABS) return false; @@ -1650,7 +1650,7 @@ void MoleculeStereocenters::markBond(BaseMolecule& baseMolecule, int atom_idx) void MoleculeStereocenters::markBonds(BaseMolecule& baseMolecule) { - for (const auto& pair: _stereocenters) + for (const auto& pair : _stereocenters) markBond(baseMolecule, pair.first); } From 199a875d50cc7256a1051316338b1c50880c3d30 Mon Sep 17 00:00:00 2001 From: Alexander Stepaniuk Date: Mon, 26 Sep 2022 17:00:25 +0300 Subject: [PATCH 3/6] Fixed segmentation fault issue on *nix platform --- core/indigo-core/molecule/src/molecule_stereocenters.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/indigo-core/molecule/src/molecule_stereocenters.cpp b/core/indigo-core/molecule/src/molecule_stereocenters.cpp index 50717c559c..07920e635f 100644 --- a/core/indigo-core/molecule/src/molecule_stereocenters.cpp +++ b/core/indigo-core/molecule/src/molecule_stereocenters.cpp @@ -864,7 +864,8 @@ bool MoleculeStereocenters::checkSub(BaseMolecule& query, BaseMolecule& target, { std::set flags; - for (auto it_i = query.stereocenters._stereocenters.begin(); it_i != query.stereocenters._stereocenters.end(); ++it_i) + auto& container = query.stereocenters._stereocenters; + for (auto it_i = container.begin(); it_i != container.end(); ++it_i) { int iq = it_i->first; if (flags.find(iq) != flags.end()) From 190dff420bbf791c775f79792787ef4aecc0559e Mon Sep 17 00:00:00 2001 From: Alexander Stepaniuk Date: Thu, 29 Sep 2022 20:03:08 +0300 Subject: [PATCH 4/6] (no branch): Issue 815: Replace ObjList with std::vector for MoleculePkaModel Issue 520: Replace RedBlackMap with std::map for MoleculePkaModel --- core/indigo-core/molecule/molecule_ionize.h | 19 +++-- .../molecule/src/molecule_ionize.cpp | 71 ++++++++++--------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/core/indigo-core/molecule/molecule_ionize.h b/core/indigo-core/molecule/molecule_ionize.h index ff5663ee33..b54e9b6e26 100644 --- a/core/indigo-core/molecule/molecule_ionize.h +++ b/core/indigo-core/molecule/molecule_ionize.h @@ -19,6 +19,11 @@ #ifndef __molecule_ionize_h__ #define __molecule_ionize_h__ +#include +#include +#include +#include + #include "base_cpp/obj_array.h" #include "base_cpp/red_black.h" #include "base_cpp/tlscont.h" @@ -82,16 +87,16 @@ namespace indigo static void _checkCanonicalOrder(Molecule& mol, Molecule& can_mol, Array& order); static void _removeExtraHydrogens(Molecule& mol); - ObjArray acids; - ObjArray basics; - Array a_pkas; - Array b_pkas; + std::vector> acids; // consider replacement to std::vector after QueryMolecule will become movable + std::vector> basics; + std::vector a_pkas; + std::vector b_pkas; bool simple_model_ready = false; - RedBlackStringObjMap> adv_a_pkas; - RedBlackStringObjMap> adv_b_pkas; + std::map, std::less<>> adv_a_pkas; + std::map, std::less<>> adv_b_pkas; int level; - Array max_deviations; + std::vector max_deviations; bool advanced_model_ready = false; }; diff --git a/core/indigo-core/molecule/src/molecule_ionize.cpp b/core/indigo-core/molecule/src/molecule_ionize.cpp index fbc3913355..e7d83af050 100644 --- a/core/indigo-core/molecule/src/molecule_ionize.cpp +++ b/core/indigo-core/molecule/src/molecule_ionize.cpp @@ -249,11 +249,10 @@ int MoleculePkaModel::buildPkaModel(int max_level, float threshold, const char* if (pka_dev > max_deviation) max_deviation = pka_dev; - if (_model.adv_a_pkas.find(fp)) - _model.adv_a_pkas.remove(fp); - _model.adv_a_pkas.insert(fp); - _model.adv_a_pkas.at(fp).push(pka_sum / pkas.size()); - _model.adv_a_pkas.at(fp).push(pka_dev); + const auto it = _model.adv_a_pkas.find(fp); + if (it != _model.adv_a_pkas.end()) + _model.adv_a_pkas.erase(it); + _model.adv_a_pkas.emplace(std::make_pair(fp, std::vector{pka_sum / pkas.size(), pka_dev})); if (pka_dev > threshold) model_ready = false; @@ -285,11 +284,10 @@ int MoleculePkaModel::buildPkaModel(int max_level, float threshold, const char* if (pka_dev > max_deviation) max_deviation = pka_dev; - if (_model.adv_b_pkas.find(fp)) - _model.adv_b_pkas.remove(fp); - _model.adv_b_pkas.insert(fp); - _model.adv_b_pkas.at(fp).push(pka_sum / pkas.size()); - _model.adv_b_pkas.at(fp).push(pka_dev); + const auto it = _model.adv_b_pkas.find(fp); + if (it != _model.adv_b_pkas.end()) + _model.adv_b_pkas.erase(it); + _model.adv_b_pkas.emplace(std::make_pair(fp, std::vector{pka_sum / pkas.size(), pka_dev})); if (pka_dev > threshold) model_ready = false; @@ -309,7 +307,7 @@ int MoleculePkaModel::buildPkaModel(int max_level, float threshold, const char* else { level++; - _model.max_deviations.push(max_deviation); + _model.max_deviations.push_back(max_deviation); } } } @@ -401,22 +399,28 @@ void MoleculePkaModel::_loadSimplePkaModel() _model.a_pkas.clear(); _model.b_pkas.clear(); + _model.acids.reserve(NELEM(simple_pka_model)); + _model.a_pkas.reserve(NELEM(simple_pka_model)); for (auto i = 0; i < NELEM(simple_pka_model); i++) { BufferScanner scanner(simple_pka_model[i].acid); SmilesLoader loader(scanner); - QueryMolecule& acid = _model.acids.push(); + _model.acids.push_back(std::make_unique()); + QueryMolecule& acid = *(_model.acids.back()); loader.loadSMARTS(acid); - _model.a_pkas.push(simple_pka_model[i].pka); + _model.a_pkas.push_back(simple_pka_model[i].pka); } + _model.basics.reserve(NELEM(simple_pka_model)); + _model.b_pkas.reserve(NELEM(simple_pka_model)); for (auto i = 0; i < NELEM(simple_pka_model); i++) { BufferScanner scanner(simple_pka_model[i].basic); SmilesLoader loader(scanner); - QueryMolecule& basic = _model.basics.push(); + _model.basics.push_back(std::make_unique()); + QueryMolecule& basic = *(_model.basics.back()); loader.loadSMARTS(basic); - _model.b_pkas.push(simple_pka_model[i].pka); + _model.b_pkas.push_back(simple_pka_model[i].pka); } _model.simple_model_ready = true; @@ -816,17 +820,16 @@ namespace // data of internal purpose {"7300021320000|64000204210006400020421000|73000213110007300021320000820002220100064000204210008200022201000", 9.69f, 0.00f}, {"82-10023110000|6400020421000|640002042100082-100231100008200022201000", 3.20f, 0.00f}}; - void LoadPkaDefToModel(RedBlackStringObjMap>& adv_model, const AdvancedPkaDef* from, const AdvancedPkaDef* const end) + void LoadPkaDefToModel(std::map, std::less<>>& adv_model, const AdvancedPkaDef* from, const AdvancedPkaDef* const end) { adv_model.clear(); for (; from < end; ++from) { - if (adv_model.find(from->a_fp)) - adv_model.remove(from->a_fp); + const auto it = adv_model.find(from->a_fp); + if (it != adv_model.end()) + adv_model.erase(it); - adv_model.insert(from->a_fp); - adv_model.at(from->a_fp).push(from->pka); - adv_model.at(from->a_fp).push(from->deviation); + adv_model.emplace(std::make_pair(std::string{from->a_fp}, std::vector{from->pka, from->deviation})); } } } // namespace @@ -860,7 +863,7 @@ void MoleculePkaModel::_estimate_pKa_Simple(Molecule& mol, const IonizeOptions& ignore_atoms.clear(); for (auto i = 0; i < _model.acids.size(); ++i) { - matcher.setQuery(_model.acids[i]); + matcher.setQuery(*(_model.acids[i])); for (int j = 0; j < ignore_atoms.size(); ++j) matcher.ignoreTargetAtom(ignore_atoms[j]); @@ -868,7 +871,7 @@ void MoleculePkaModel::_estimate_pKa_Simple(Molecule& mol, const IonizeOptions& for (bool flag = matcher.find(); flag; flag = matcher.findNext()) { mapping.clear(); - mapping.copy(matcher.getQueryMapping(), _model.acids[i].vertexEnd()); + mapping.copy(matcher.getQueryMapping(), _model.acids[i]->vertexEnd()); for (int j = 0; j < mapping.size(); ++j) { if (mapping[j] > -1) @@ -884,7 +887,7 @@ void MoleculePkaModel::_estimate_pKa_Simple(Molecule& mol, const IonizeOptions& ignore_atoms.clear(); for (auto i = 0; i < _model.basics.size(); ++i) { - matcher.setQuery(_model.basics[i]); + matcher.setQuery(*_model.basics[i]); for (int j = 0; j < ignore_atoms.size(); ++j) matcher.ignoreTargetAtom(ignore_atoms[j]); @@ -892,7 +895,7 @@ void MoleculePkaModel::_estimate_pKa_Simple(Molecule& mol, const IonizeOptions& for (bool flag = matcher.find(); flag; flag = matcher.findNext()) { mapping.clear(); - mapping.copy(matcher.getQueryMapping(), _model.basics[i].vertexEnd()); + mapping.copy(matcher.getQueryMapping(), _model.basics[i]->vertexEnd()); for (int j = 0; j < mapping.size(); ++j) { if (mapping[j] > -1) @@ -1229,9 +1232,10 @@ float MoleculePkaModel::getAcidPkaValue(Molecule& mol, int idx, int level, int m getAtomLocalFingerprint(mol, idx, fp, level); // printf("Acid site: atom index = %d, fp = %s\n", idx, fp.ptr()); - if (_model.adv_a_pkas.find(fp.ptr())) + const auto it = _model.adv_a_pkas.find(fp.ptr()); + if (it != _model.adv_a_pkas.end()) { - pka = _model.adv_a_pkas.at(fp.ptr())[0]; + pka = it->second[0]; // printf("Acid site found: fp = %s level = %d pka = %4.2f, dev = %4.2f\n", fp.ptr(), level, pka, // _model.adv_a_pkas.at(fp.ptr())[1]); } @@ -1255,9 +1259,10 @@ float MoleculePkaModel::getAcidPkaValue(Molecule& mol, int idx, int level, int m // printf("Try FP = %s level = %d\n", fp.ptr(), level_pos.size() - i); - if (_model.adv_a_pkas.find(fp.ptr())) + const auto it = _model.adv_a_pkas.find(fp.ptr()); + if (it != _model.adv_a_pkas.end()) { - pka = _model.adv_a_pkas.at(fp.ptr())[0]; + pka = it->second[0]; // printf("Acid site found: fp = %s level = %d pka = %4.2f, dev = %4.2f\n", fp.ptr(), level_pos.size() - i, pka, // _model.adv_a_pkas.at(fp.ptr())[1]); break; @@ -1283,9 +1288,10 @@ float MoleculePkaModel::getBasicPkaValue(Molecule& mol, int idx, int level, int getAtomLocalFingerprint(mol, idx, fp, level); // printf("Basic site: atom index = %d, fp = %s\n", idx, fp.ptr()); - if (_model.adv_b_pkas.find(fp.ptr())) + const auto it = _model.adv_b_pkas.find(fp.ptr()); + if (it != _model.adv_b_pkas.end()) { - pka = (_model.adv_b_pkas.at(fp.ptr())[0]); + pka = it->second[0]; // printf("Basic site found: fp = %s pka = %4.2f, dev = %4.2f\n", fp.ptr(), pka, // _model.adv_b_pkas.at(fp.ptr())[1]); } @@ -1306,7 +1312,8 @@ float MoleculePkaModel::getBasicPkaValue(Molecule& mol, int idx, int level, int break; int next_layer = level_pos[level_pos.size() - i - 1]; fp.remove(next_layer, fp.size() - next_layer - 1); - if (_model.adv_b_pkas.find(fp.ptr())) + const auto it = _model.adv_b_pkas.find(fp.ptr()); + if (it != _model.adv_b_pkas.end()) { pka = _model.adv_b_pkas.at(fp.ptr())[0]; // printf("Basic site found: fp = %s level = %d pka = %4.2f, dev = %4.2f\n", fp.ptr(), level_pos.size() - i, pka, From 8455ebde8b60febacad80f6e21d9784cc5acf141 Mon Sep 17 00:00:00 2001 From: Dmitry Malysh Date: Mon, 24 Jul 2023 12:20:38 +0200 Subject: [PATCH 5/6] Format file. --- core/render2d/src/render_internal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/render2d/src/render_internal.cpp b/core/render2d/src/render_internal.cpp index 54f48aa89d..6830e30d8f 100644 --- a/core/render2d/src/render_internal.cpp +++ b/core/render2d/src/render_internal.cpp @@ -23,8 +23,8 @@ #include "base_cpp/tree.h" #include "molecule/ket_commons.h" #include "molecule/molecule.h" -#include "molecule/molecule_stereocenter_iterator.h" #include "molecule/molecule_sgroups.h" +#include "molecule/molecule_stereocenter_iterator.h" #include "molecule/query_molecule.h" #include "reaction/query_reaction.h" #include "reaction/reaction.h" From af66d77f31a21375f5d7f025da35ccfc39583a4c Mon Sep 17 00:00:00 2001 From: Dmitry Malysh Date: Mon, 31 Jul 2023 11:52:49 +0200 Subject: [PATCH 6/6] Fix build. --- core/indigo-core/molecule/src/molecule_stereocenters.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/indigo-core/molecule/src/molecule_stereocenters.cpp b/core/indigo-core/molecule/src/molecule_stereocenters.cpp index 56ddef9af7..65259e3f4a 100644 --- a/core/indigo-core/molecule/src/molecule_stereocenters.cpp +++ b/core/indigo-core/molecule/src/molecule_stereocenters.cpp @@ -862,9 +862,11 @@ bool MoleculeStereocenters::haveAllAndAny() bool MoleculeStereocenters::haveEnhancedStereocenter() { - for (auto i = _stereocenters.begin(); i != _stereocenters.end(); i = _stereocenters.next(i)) + for (const auto& pair : _stereocenters) { - if (_stereocenters.value(i).type == ATOM_OR || _stereocenters.value(i).type == ATOM_AND) + const _Atom& atom = pair.second; + + if (atom.type == ATOM_OR || atom.type == ATOM_AND) { return true; }