NuriKit v0.1.0b2
Loading...
Searching...
No Matches
molecule.h
Go to the documentation of this file.
1//
2// Project NuriKit - Copyright 2023 SNU Compbio Lab.
3// SPDX-License-Identifier: Apache-2.0
4//
5#ifndef NURI_CORE_MOLECULE_H_
6#define NURI_CORE_MOLECULE_H_
7
9#include <algorithm>
10#include <cmath>
11#include <cstdint>
12#include <ostream>
13#include <string>
14#include <string_view>
15#include <type_traits>
16#include <utility>
17#include <vector>
18
19#include <absl/algorithm/container.h>
20#include <absl/base/attributes.h>
21#include <absl/base/optimization.h>
22#include <absl/container/fixed_array.h>
23#include <absl/container/flat_hash_map.h>
24#include <absl/log/absl_check.h>
25#include <boost/container/flat_map.hpp>
26#include <Eigen/Dense>
28
29#include "nuri/eigen_config.h"
32#include "nuri/core/element.h"
35#include "nuri/meta.h"
36#include "nuri/utils.h"
37
38namespace nuri {
39namespace constants {
43 enum Hybridization : int {
44 kUnbound = 0, // Unbound
45 kTerminal = 1, // Terminal
46 kSP = 2,
47 kSP2 = 3,
48 kSP3 = 4,
49 kSP3D = 5,
50 kSP3D2 = 6,
51 kOtherHyb = 7, // Unknown/other
52 };
53
54 inline std::ostream &operator<<(std::ostream &os, Hybridization hyb) {
55 switch (hyb) {
56 case kUnbound:
57 return os << "unbound";
58 case kTerminal:
59 return os << "terminal";
60 case kSP:
61 return os << "sp";
62 case kSP2:
63 return os << "sp2";
64 case kSP3:
65 return os << "sp3";
66 case kSP3D:
67 return os << "sp3d";
68 case kSP3D2:
69 return os << "sp3d2";
70 case kOtherHyb:
71 break;
72 }
73
74 return os << "other";
75 }
76
88
89 inline std::ostream &operator<<(std::ostream &os, BondOrder bo) {
90 switch (bo) {
91 case kOtherBond:
92 break;
93 case kSingleBond:
94 return os << "single";
95 case kDoubleBond:
96 return os << "double";
97 case kTripleBond:
98 return os << "triple";
99 case kQuadrupleBond:
100 return os << "quadruple";
101 case kAromaticBond:
102 return os << "aromatic";
103 }
104
105 return os << "other";
106 }
107
108 constexpr double kBondOrderToDouble[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 1.5 };
109} // namespace constants
110
115
120
121enum class AtomFlags : std::uint32_t {
124 kRing = 0x4,
125 kChiral = 0x8,
127};
128
129class AtomData {
130public:
134 AtomData(): AtomData(kPt[0]) { }
135
137 int formal_charge = 0,
139 double partial_charge = 0.0, int mass_number = -1,
140 bool is_aromatic = false, bool is_in_ring = false,
141 bool is_chiral = false, bool is_clockwise = false);
142
149 int atomic_number() const { return element().atomic_number(); }
150
157 double atomic_weight() const { return element().atomic_weight(); }
158
165 std::string_view element_symbol() const { return element().symbol(); }
166
173 std::string_view element_name() const { return element().name(); }
174
182 element_ = &element;
183 return *this;
184 }
185
196 return *this;
197 }
198
203 const Element &element() const noexcept {
204 // GCOV_EXCL_START
205 ABSL_ASSUME(element_ != nullptr);
206 // GCOV_EXCL_STOP
207 return *element_;
208 }
209
217 const Isotope &isotope() const {
218 return ABSL_PREDICT_TRUE(isotope_ == nullptr) ? element().major_isotope()
219 : *isotope_;
220 }
221
232 isotope_ = &isotope;
233 return *this;
234 }
235
245 AtomData &set_isotope(int mass_number) {
246 isotope_ = element().find_isotope(mass_number);
247 return *this;
248 }
249
258 internal::Nullable<const Isotope *> explicit_isotope() const {
259 return isotope_;
260 }
261
263 hyb_ = hyb;
264 return *this;
265 }
266
268
279 ABSL_DCHECK(implicit_hydrogens >= 0);
280 implicit_hydrogens_ = implicit_hydrogens;
281 return *this;
282 }
283
290 int implicit_hydrogens() const { return implicit_hydrogens_; }
291
293 internal::update_flag(flags_, is_aromatic, AtomFlags::kAromatic);
294 return *this;
295 }
296
297 bool is_aromatic() const {
298 return internal::check_flag(flags_, AtomFlags::kAromatic);
299 }
300
302 internal::update_flag(flags_, is_conjugated, AtomFlags::kConjugated);
303 return *this;
304 }
305
306 bool is_conjugated() const {
307 return internal::check_flag(flags_, AtomFlags::kConjugated);
308 }
309
311 internal::update_flag(flags_, is_ring_atom, AtomFlags::kRing);
312 return *this;
313 }
314
315 bool is_ring_atom() const {
316 return internal::check_flag(flags_, AtomFlags::kRing);
317 }
318
320 internal::update_flag(flags_, is_chiral, AtomFlags::kChiral);
321 return *this;
322 }
323
324 bool is_chiral() const {
325 return internal::check_flag(flags_, AtomFlags::kChiral);
326 }
327
329 internal::update_flag(flags_, is_clockwise, AtomFlags::kClockWise);
330 return *this;
331 }
332
343 bool is_clockwise() const {
344 return internal::check_flag(flags_, AtomFlags::kClockWise);
345 }
346
347 AtomFlags flags() const { return flags_; }
348
350 flags_ |= flags;
351 return *this;
352 }
353
355 flags_ &= ~flags;
356 return *this;
357 }
358
360 flags_ = static_cast<AtomFlags>(0);
361 return *this;
362 }
363
364 AtomData &set_partial_charge(double charge) {
365 partial_charge_ = charge;
366 return *this;
367 }
368
369 double partial_charge() const { return partial_charge_; }
370
372 formal_charge_ = charge;
373 return *this;
374 }
375
376 int formal_charge() const { return formal_charge_; }
377
378 std::string_view get_name() const { return internal::get_name(props_); }
379
380 template <class ST>
381 AtomData &set_name(ST &&name) {
382 internal::set_name(props_, std::forward<ST>(name));
383 return *this;
384 }
385
386 template <class KT, class VT>
387 AtomData &add_prop(KT &&key, VT &&val) {
388 internal::set_key(props_, std::forward<KT>(key), std::forward<VT>(val));
389 return *this;
390 }
391
392 internal::PropertyMap &props() { return props_; }
393
394 const internal::PropertyMap &props() const { return props_; }
395
396private:
397 friend bool operator==(const AtomData &lhs, const AtomData &rhs) noexcept;
398
399 const Element *element_;
400 int implicit_hydrogens_;
401 int formal_charge_;
403 AtomFlags flags_;
404 double partial_charge_;
405 const Isotope *isotope_;
406 internal::PropertyMap props_;
407};
408
409inline bool operator==(const AtomData &lhs, const AtomData &rhs) noexcept {
410 return lhs.element() == rhs.element()
411 && lhs.hybridization() == rhs.hybridization()
412 && lhs.flags_ == rhs.flags_
413 && lhs.formal_charge() == rhs.formal_charge();
414}
415
416enum class BondFlags : std::uint32_t {
417 kRing = 0x1,
422};
423
424class BondData {
425public:
426 BondData(): BondData(constants::kOtherBond) { }
427
429 : order_(order), flags_(static_cast<BondFlags>(0)) { }
430
434 constants::BondOrder order() const { return order_; }
435
440 double approx_order() const { return constants::kBondOrderToDouble[order_]; }
441
445 constants::BondOrder &order() { return order_; }
446
448 order_ = order;
449 return *this;
450 }
451
458 bool is_rotatable() const {
459 return order_ <= constants::kSingleBond
460 && !internal::check_flag(flags_,
462 }
463
464 bool is_ring_bond() const {
465 return internal::check_flag(flags_, BondFlags::kRing);
466 }
467
469 internal::update_flag(flags_, ring, BondFlags::kRing);
470 return *this;
471 }
472
473 bool is_aromatic() const {
474 return internal::check_flag(flags_, BondFlags::kAromatic);
475 }
476
477 BondData &set_aromatic(bool aromatic) {
478 internal::update_flag(flags_, aromatic, BondFlags::kAromatic);
479 return *this;
480 }
481
482 bool is_conjugated() const {
483 return internal::check_flag(flags_, BondFlags::kConjugated);
484 }
485
487 internal::update_flag(flags_, conj, BondFlags::kConjugated);
488 return *this;
489 }
490
494 bool has_config() const {
495 return internal::check_flag(flags_, BondFlags::kConfigSpecified);
496 }
497
501 BondData &set_config(bool config) {
502 internal::update_flag(flags_, config, BondFlags::kConfigSpecified);
503 return *this;
504 }
505
529 bool is_trans() const {
530 return internal::check_flag(flags_, BondFlags::kTransConfig);
531 }
532
538 BondData &set_trans(bool trans) {
539 internal::update_flag(flags_, trans, BondFlags::kTransConfig);
540 return *this;
541 }
542
543 BondFlags flags() const { return flags_; }
544
546 flags_ |= flags;
547 return *this;
548 }
549
551 flags_ &= ~flags;
552 return *this;
553 }
554
556 flags_ = static_cast<BondFlags>(0);
557 return *this;
558 }
559
560 std::string_view get_name() const { return internal::get_name(props_); }
561
562 template <class ST>
563 BondData &set_name(ST &&name) {
564 internal::set_name(props_, std::forward<ST>(name));
565 return *this;
566 }
567
568 template <class KT, class VT>
569 BondData &add_prop(KT &&key, VT &&val) {
570 internal::set_key(props_, std::forward<KT>(key), std::forward<VT>(val));
571 return *this;
572 }
573
574 internal::PropertyMap &props() { return props_; }
575
576 const internal::PropertyMap &props() const { return props_; }
577
578private:
580 BondFlags flags_;
581 internal::PropertyMap props_;
582};
583
584class Molecule;
585class MoleculeMutator;
586
592
593namespace internal {
594 template <bool is_const = false>
595 class Substructure {
596 public:
597 using GraphType = const_if_t<is_const, Graph<AtomData, BondData>>;
598
599 // Should use SubgraphOf<GraphType> here, but Subgraph was used directly for
600 // better clangd autocompletion.
601 using SubgraphType = Subgraph<AtomData, BondData, is_const>;
602
603 using MutableAtom = typename SubgraphType::NodeRef;
604 using Atom = typename SubgraphType::ConstNodeRef;
605
606 using iterator = typename SubgraphType::iterator;
607 using const_iterator = typename SubgraphType::const_iterator;
608 using atom_iterator = iterator;
609 using const_atom_iterator = const_iterator;
610
611 using bond_iterator = typename SubgraphType::edge_iterator;
612 using const_bond_iterator = typename SubgraphType::const_edge_iterator;
613 using MutableBond = typename SubgraphType::EdgeRef;
614 using Bond = typename SubgraphType::ConstEdgeRef;
615
616 using BondsWrapper = typename SubgraphType::EdgesWrapper;
617 using ConstBondsWrapper = typename SubgraphType::ConstEdgesWrapper;
618
619 using MutableNeighbor = typename SubgraphType::AdjRef;
620 using Neighbor = typename SubgraphType::ConstAdjRef;
621 using neighbor_iterator = typename SubgraphType::adjacency_iterator;
622 using const_neighbor_iterator =
624
625 Substructure(const SubgraphType &sub,
627 : graph_(sub), cat_(cat) { }
628
629 Substructure(SubgraphType &&sub,
631 : graph_(std::move(sub)), cat_(cat) { }
632
633 Substructure(const SubgraphType &sub, const std::string &name,
635 : graph_(sub), name_(name), cat_(cat) { }
636
637 Substructure(SubgraphType &&sub, std::string &&name,
639 : graph_(std::move(sub)), name_(std::move(name)), cat_(cat) { }
640
641 template <bool other_const,
642 std::enable_if_t<is_const && !other_const, int> = 0>
644 : graph_(other.graph_), name_(other.name_), id_(other.id_),
645 cat_(other.cat_), props_(other.props_) { }
646
647 template <bool other_const,
648 std::enable_if_t<is_const && !other_const, int> = 0>
650 : graph_(std::move(other.graph_)), name_(std::move(other.name_)),
651 id_(other.id_), cat_(other.cat_), props_(std::move(other.props_)) { }
652
653 template <bool other_const,
654 std::enable_if_t<is_const && !other_const, int> = 0>
655 Substructure &operator=(const Substructure<other_const> &other) {
656 graph_ = other.graph_;
657 name_ = other.name_;
658 id_ = other.id_;
659 cat_ = other.cat_;
660 props_ = other.props_;
661 return *this;
662 }
663
664 template <bool other_const,
665 std::enable_if_t<is_const && !other_const, int> = 0>
666 Substructure &operator=(Substructure<other_const> &&other) noexcept {
667 graph_ = std::move(other.graph_);
668 name_ = std::move(other.name_);
669 id_ = other.id_;
670 cat_ = other.cat_;
671 props_ = std::move(other.props_);
672 return *this;
673 }
674
675 bool empty() const { return graph_.empty(); }
676 int size() const { return graph_.size(); }
677 int num_atoms() const { return graph_.num_nodes(); }
678 int num_bonds() const { return graph_.num_edges(); }
679 int count_heavy_atoms() const {
680 return absl::c_count_if(graph_, [](Substructure::Atom atom) {
681 return atom.data().atomic_number() != 1;
682 });
683 }
684
685 void clear() noexcept {
686 graph_.clear();
687 name_.clear();
688 id_ = 0;
690 props_.clear();
691 }
692
693 void clear_atoms() noexcept { graph_.clear(); }
694
695 void update(IndexSet &&atoms, IndexSet &&bonds) {
696 graph_.update(std::move(atoms), std::move(bonds));
697 }
698
699 void update_atoms(IndexSet &&atoms) noexcept {
700 graph_.update_nodes(std::move(atoms));
701 }
702
703 void reserve_atoms(int n) { graph_.reserve_nodes(n); }
704
705 void add_atom(int id) { graph_.add_node(id); }
706
707 void add_atoms(const IndexSet &atoms, bool bonds = false) {
708 if (bonds) {
709 graph_.add_nodes_with_edges(atoms);
710 } else {
711 graph_.add_nodes(atoms);
712 }
713 }
714
715 bool contains_atom(int id) const { return graph_.contains_node(id); }
716 bool contains_atom(typename GraphType::ConstNodeRef atom) const {
717 return graph_.contains_node(atom);
718 }
719
720 MutableAtom operator[](int idx) { return graph_[idx]; }
721 Atom operator[](int idx) const { return graph_[idx]; }
722
723 MutableAtom atom(int idx) { return graph_.node(idx); }
724 Atom atom(int idx) const { return graph_.node(idx); }
725
726 iterator find_atom(int id) { return graph_.find_node(id); }
727 iterator find_atom(typename GraphType::ConstNodeRef atom) {
728 return graph_.find_node(atom);
729 }
730
731 const_iterator find_atom(int id) const { return graph_.find_node(id); }
732 const_iterator find_atom(typename GraphType::ConstNodeRef atom) const {
733 return graph_.find_node(atom);
734 }
735
736 void erase_atom(int idx) { graph_.erase_node(idx); }
737 void erase_atom(Atom atom) { graph_.erase_node(atom); }
738
739 void erase_atoms(const_iterator begin, const_iterator end) {
740 graph_.erase_nodes(begin, end);
741 }
742
743 void erase_atom_of(int id) { graph_.erase_node_of(id); }
744
745 void erase_atom_of(typename GraphType::ConstNodeRef atom) {
746 graph_.erase_node_of(atom);
747 }
748
749 template <class UnaryPred>
750 void erase_atoms_if(UnaryPred &&pred) {
751 graph_.erase_nodes_if(std::forward<UnaryPred>(pred));
752 }
753
754 iterator begin() { return graph_.begin(); }
755 iterator end() { return graph_.end(); }
756
757 const_iterator begin() const { return cbegin(); }
758 const_iterator end() const { return cend(); }
759
760 const_iterator cbegin() const { return graph_.cbegin(); }
761 const_iterator cend() const { return graph_.cend(); }
762
763 atom_iterator atom_begin() { return graph_.node_begin(); }
764 atom_iterator atom_end() { return graph_.node_end(); }
765
766 const_atom_iterator atom_begin() const { return atom_cbegin(); }
767 const_atom_iterator atom_end() const { return atom_cend(); }
768
769 const_atom_iterator atom_cbegin() const { return graph_.node_cbegin(); }
770 const_atom_iterator atom_cend() const { return graph_.node_cend(); }
771
772 const std::vector<int> &atom_ids() const { return graph_.node_ids(); }
773
774 BondsWrapper bonds() { return graph_.edges(); }
775 ConstBondsWrapper bonds() const { return graph_.edges(); }
776
777 void clear_bonds() noexcept { graph_.clear_edges(); }
778
779 void update_bonds(IndexSet &&bonds) noexcept {
780 graph_.update_edges(std::move(bonds));
781 }
782
783 void refresh_bonds() { graph_.refresh_edges(); }
784
785 void reserve_bonds(int n) { graph_.reserve_edges(n); }
786
787 void add_bond(int id) { graph_.add_edge(id); }
788
789 void add_bonds(const IndexSet &bonds) { graph_.add_edges(bonds); }
790
791 bool contains_bond(int id) const { return graph_.contains_edge(id); }
792 bool contains_bond(typename GraphType::ConstEdgeRef bond) const {
793 return graph_.contains_edge(bond);
794 }
795
796 MutableBond bond(int idx) { return graph_.edge(idx); }
797 Bond bond(int idx) const { return graph_.edge(idx); }
798
799 bond_iterator find_bond(int id) { return graph_.find_edge(id); }
800 bond_iterator find_bond(typename GraphType::ConstEdgeRef bond) {
801 return graph_.find_edge(bond);
802 }
803
804 const_bond_iterator find_bond(int id) const { return graph_.find_edge(id); }
805 const_bond_iterator find_bond(typename GraphType::ConstEdgeRef bond) const {
806 return graph_.find_edge(bond);
807 }
808
809 void erase_bond(int idx) { graph_.erase_edge(idx); }
810 void erase_bond(Bond bond) { graph_.erase_edge(bond); }
811
812 void erase_bonds(const_bond_iterator begin, const_bond_iterator end) {
813 graph_.erase_edges(begin, end);
814 }
815
816 void erase_bond_of(int id) { graph_.erase_edge_of(id); }
817
818 void erase_bond_of(typename GraphType::ConstEdgeRef bond) {
819 graph_.erase_edge_of(bond);
820 }
821
822 template <class UnaryPred>
823 void erase_bonds_if(UnaryPred &&pred) {
824 graph_.erase_edges_if(std::forward<UnaryPred>(pred));
825 }
826
827 bond_iterator bond_begin() { return graph_.edge_begin(); }
828 bond_iterator bond_end() { return graph_.edge_end(); }
829
830 const_bond_iterator bond_begin() const { return bond_cbegin(); }
831 const_bond_iterator bond_end() const { return bond_cend(); }
832
833 const_bond_iterator bond_cbegin() const { return graph_.edge_cbegin(); }
834 const_bond_iterator bond_cend() const { return graph_.edge_cend(); }
835
836 const std::vector<int> &bond_ids() const { return graph_.edge_ids(); }
837
838 int degree(int id) const { return graph_.degree(id); }
839
840 bond_iterator find_bond(Atom src, Atom dst) {
841 return graph_.find_edge(src, dst);
842 }
843
844 const_bond_iterator find_bond(Atom src, Atom dst) const {
845 return graph_.find_edge(src, dst);
846 }
847
848 bond_iterator find_bond(typename GraphType::ConstNodeRef src,
849 typename GraphType::ConstNodeRef dst) {
850 return graph_.find_edge(src, dst);
851 }
852
853 const_bond_iterator find_bond(typename GraphType::ConstNodeRef src,
854 typename GraphType::ConstNodeRef dst) const {
855 return graph_.find_edge(src, dst);
856 }
857
858 neighbor_iterator find_neighbor(Atom src, Atom dst) {
859 return graph_.find_adjacent(src, dst);
860 }
861
862 const_neighbor_iterator find_neighbor(Atom src, Atom dst) const {
863 return graph_.find_adjacent(src, dst);
864 }
865
866 neighbor_iterator neighbor_begin(int id) { return graph_.adj_begin(id); }
867 neighbor_iterator neighbor_end(int id) { return graph_.adj_end(id); }
868
869 const_neighbor_iterator neighbor_begin(int id) const {
870 return graph_.adj_begin(id);
871 }
872 const_neighbor_iterator neighbor_end(int id) const {
873 return graph_.adj_end(id);
874 }
875
876 const_neighbor_iterator neighbor_cbegin(int id) const {
877 return graph_.adj_cbegin(id);
878 }
879 const_neighbor_iterator neighbor_cend(int id) const {
880 return graph_.adj_cend(id);
881 }
882
883 std::string &name() { return name_; }
884
885 const std::string &name() const { return name_; }
886
887 void set_id(int id) { id_ = id; }
888
889 int id() const { return id_; }
890
891 SubstructCategory &category() { return cat_; }
892
893 SubstructCategory category() const { return cat_; }
894
895 template <class KT, class VT>
896 void add_prop(KT &&key, VT &&val) {
897 internal::set_key(props_, std::forward<KT>(key), std::forward<VT>(val));
898 }
899
900 internal::PropertyMap &props() { return props_; }
901
902 const internal::PropertyMap &props() const { return props_; }
903
904 private:
905 friend Molecule;
906 friend MoleculeMutator;
907
908 void rebind(typename SubgraphType::parent_type &parent) {
909 graph_.rebind(parent);
910 }
911
912 SubgraphType graph_;
913
914 std::string name_;
915 int id_ = 0;
917 internal::PropertyMap props_;
918 };
919
920 extern std::pair<std::vector<int>, bool>
921 place_trailing_hydrogens_initial(const Molecule &mol, Matrix3Xd &conf,
922 int h_begin);
923
924 extern bool optimize_free_hydrogens(const Molecule &mol, Matrix3Xd &conf,
925 const std::vector<int> &free_hs);
926} // namespace internal
927
928using Substructure = internal::Substructure<false>;
929using ConstSubstructure = internal::Substructure<true>;
930
943class Molecule {
944public:
946
953
958
963
965
969 Molecule() noexcept = default;
970 ~Molecule() noexcept = default;
971
972 Molecule(const Molecule &other) noexcept;
973 Molecule(Molecule &&other) noexcept;
974 Molecule &operator=(const Molecule &other) noexcept;
975 Molecule &operator=(Molecule &&other) noexcept;
976
984 template <class Iterator,
985 class = internal::enable_if_compatible_iter_t<Iterator, AtomData>>
986 Molecule(Iterator begin, Iterator end);
987
988 std::string &name() { return name_; }
989
990 const std::string &name() const { return name_; }
991
992 void reserve(int num_atoms) { graph_.reserve(num_atoms); }
993
994 void reserve_bonds(int num_bonds) { graph_.reserve_edges(num_bonds); }
995
999 bool empty() const { return graph_.empty(); }
1000
1005 int size() const { return graph_.size(); }
1006
1011 int num_atoms() const { return graph_.num_nodes(); }
1012
1019 int count_heavy_atoms() const {
1020 return absl::c_count_if(graph_, [](Molecule::Atom a) {
1021 return a.data().atomic_number() != 1;
1022 });
1023 }
1024
1032 MutableAtom atom(int atom_idx) { return graph_.node(atom_idx); }
1033
1041 Atom atom(int atom_idx) const { return graph_.node(atom_idx); }
1042
1050 MutableAtom operator[](int atom_idx) { return graph_[atom_idx]; }
1051
1059 Atom operator[](int atom_idx) const { return graph_[atom_idx]; }
1060
1065 iterator begin() { return graph_.begin(); }
1070 const_iterator begin() const { return graph_.begin(); }
1071
1076 iterator atom_begin() { return begin(); }
1081 const_iterator atom_begin() const { return begin(); }
1082
1086 iterator end() { return graph_.end(); }
1090 const_iterator end() const { return graph_.end(); }
1091
1095 iterator atom_end() { return end(); }
1099 const_iterator atom_end() const { return end(); }
1100
1104 bool bond_empty() const { return graph_.edge_empty(); }
1105
1109 int num_bonds() const { return graph_.num_edges(); }
1110
1118 MutableBond bond(int bond_idx) { return graph_.edge(bond_idx); }
1119
1127 Bond bond(int bond_idx) const { return graph_.edge(bond_idx); }
1128
1137 bond_iterator find_bond(int src, int dst) {
1138 return graph_.find_edge(src, dst);
1139 }
1140
1149 const_bond_iterator find_bond(int src, int dst) const {
1150 return graph_.find_edge(src, dst);
1151 }
1152
1162 return graph_.find_edge(src, dst);
1163 }
1164
1174 return graph_.find_edge(src, dst);
1175 }
1176
1180 auto bonds() { return graph_.edges(); }
1181
1185 auto bonds() const { return graph_.edges(); }
1186
1190 auto cbonds() const { return graph_.edges(); }
1191
1195 bond_iterator bond_begin() { return graph_.edge_begin(); }
1199 const_bond_iterator bond_begin() const { return graph_.edge_begin(); }
1203 bond_iterator bond_end() { return graph_.edge_end(); }
1207 const_bond_iterator bond_end() const { return graph_.edge_end(); }
1208
1214 int count_heavy_bonds() const {
1215 return absl::c_count_if(bonds(), [](Molecule::Bond bond) {
1216 return bond.src().data().atomic_number() != 1
1217 && bond.dst().data().atomic_number() != 1;
1218 });
1219 }
1220
1228 int num_neighbors(int atom) const { return graph_.degree(atom); }
1229
1239 return graph_.find_adjacent(src, dst);
1240 }
1241
1250 const_neighbor_iterator find_neighbor(int src, int dst) const {
1251 return graph_.find_adjacent(src, dst);
1252 }
1253
1263 return graph_.find_adjacent(src, dst);
1264 }
1265
1275 return graph_.find_adjacent(src, dst);
1276 }
1277
1282 return graph_.adj_begin(atom_idx);
1283 }
1284
1288 return graph_.adj_begin(atom_idx);
1289 }
1290
1294 return graph_.adj_end(atom_idx);
1295 }
1296
1300 return graph_.adj_end(atom_idx);
1301 }
1302
1309
1319 void clear() noexcept;
1320
1329 void clear_atoms() noexcept;
1330
1338 void clear_bonds() noexcept;
1339
1345 const GraphType &raw_graph() const { return graph_; }
1346
1360 ABSL_MUST_USE_RESULT bool add_hydrogens(bool update_confs = true,
1361 bool optimize = true);
1362
1374
1379 bool is_3d() const { return !conformers_.empty(); }
1380
1387 std::vector<Matrix3Xd> &confs() { return conformers_; }
1388
1393 const std::vector<Matrix3Xd> &confs() const { return conformers_; }
1394
1399 void transform(const Eigen::Isometry3d &trans) {
1400 for (Matrix3Xd &m: conformers_)
1401 m = trans * m;
1402 }
1403
1411 void transform(int i, const Eigen::Isometry3d &trans) {
1412 Matrix3Xd &m = conformers_[i];
1413 m = trans * m;
1414 }
1415
1424 double distsq(int src, int dst, int conf = 0) const;
1425
1434 double distsq(Bond bond, int conf = 0) const {
1435 return distsq(bond.src().id(), bond.dst().id(), conf);
1436 }
1437
1446 double distance(int src, int dst, int conf = 0) const {
1447 return std::sqrt(distsq(src, dst, conf));
1448 }
1449
1458 double distance(Bond bond, int conf = 0) const {
1459 return distance(bond.src().id(), bond.dst().id(), conf);
1460 }
1461
1469 ArrayXd bond_lengths(int conf = 0) const;
1470
1490 bool rotate_bond(int ref_atom, int pivot_atom, double angle);
1491
1509 bool rotate_bond(int bid, double angle);
1510
1529 bool rotate_bond_conf(int i, int ref_atom, int pivot_atom, double angle);
1530
1547 bool rotate_bond_conf(int i, int bid, double angle);
1548
1557 return { make_subgraph(graph_), cat };
1558 }
1559
1569 substructure(internal::IndexSet &&atoms, internal::IndexSet &&bonds,
1571 return { make_subgraph(graph_, std::move(atoms), std::move(bonds)), cat };
1572 }
1573
1581 atom_substructure(internal::IndexSet &&atoms,
1583 return { subgraph_from_nodes(graph_, std::move(atoms)), cat };
1584 }
1585
1593 internal::IndexSet &&bonds,
1595 return { subgraph_from_edges(graph_, std::move(bonds)), cat };
1596 }
1597
1606 return { Subgraph(graph_), cat };
1607 }
1608
1618 substructure(internal::IndexSet &&atoms, internal::IndexSet &&bonds,
1620 return { make_subgraph(graph_, std::move(atoms), std::move(bonds)), cat };
1621 }
1622
1630 atom_substructure(internal::IndexSet &&atoms,
1632 return { subgraph_from_nodes(graph_, std::move(atoms)), cat };
1633 }
1634
1642 bond_substructure(internal::IndexSet &&bonds,
1644 return { subgraph_from_edges(graph_, std::move(bonds)), cat };
1645 }
1646
1652 std::vector<Substructure> &substructures() { return substructs_; }
1653
1659 const std::vector<Substructure> &substructures() const { return substructs_; }
1660
1675
1680 int num_sssr() const { return num_bonds() - num_atoms() + num_fragments(); }
1681
1688 const std::vector<std::vector<int>> &ring_groups() const {
1689 return ring_groups_;
1690 }
1691
1696 int num_fragments() const { return num_fragments_; }
1697
1709 template <class MoleculeLike>
1710 void merge(const MoleculeLike &other) {
1711 graph_.merge(other.graph_);
1713
1714 for (Matrix3Xd &conf: conformers_)
1715 conf.conservativeResize(Eigen::NoChange, size());
1716 }
1717
1718 template <class KT, class VT>
1719 void add_prop(KT &&key, VT &&val) {
1720 internal::set_key(props_, std::forward<KT>(key), std::forward<VT>(val));
1721 }
1722
1723 internal::PropertyMap &props() { return props_; }
1724
1725 const internal::PropertyMap &props() const { return props_; }
1726
1727private:
1728 Molecule(GraphType &&graph, std::vector<Matrix3Xd> &&conformers) noexcept
1729 : graph_(std::move(graph)), conformers_(std::move(conformers)) { }
1730
1731 void rebind_substructs() noexcept;
1732
1733 bool rotate_bond_common(int i, int ref_atom, int pivot_atom, double angle);
1734
1735 GraphType graph_;
1736 std::vector<Matrix3Xd> conformers_;
1737 std::string name_;
1738 internal::PropertyMap props_;
1739
1740 std::vector<Substructure> substructs_;
1741
1742 std::vector<std::vector<int>> ring_groups_;
1743 int num_fragments_ = 0;
1744};
1745
1773public:
1780 : mol_(&mol), prev_num_atoms_(mol.num_atoms()) { }
1781
1785 MoleculeMutator(MoleculeMutator &&) noexcept = default;
1786 MoleculeMutator &operator=(MoleculeMutator &&) noexcept = default;
1787
1788 ~MoleculeMutator() noexcept { finalize(); }
1789
1795 int add_atom(const AtomData &atom) { return mol().graph_.add_node(atom); }
1796
1802 int add_atom(AtomData &&atom) noexcept {
1803 return mol().graph_.add_node(std::move(atom));
1804 }
1805
1811 int add_atom(const Molecule::Atom &atom) { return add_atom(atom.data()); }
1812
1819 void mark_atom_erase(int atom_idx) { erased_atoms_.push_back(atom_idx); }
1820
1828
1832 void clear_atoms() noexcept;
1833
1846 std::pair<int, bool> register_bond(int src, int dst, const BondData &bond);
1847
1860 std::pair<int, bool> register_bond(int src, int dst,
1861 BondData &&bond) noexcept;
1862
1875 std::pair<int, bool> register_bond(int src, int dst, Molecule::Bond bond) {
1876 return register_bond(src, dst, bond.data());
1877 }
1878
1884 void mark_bond_erase(int bid) { erased_bonds_.push_back(bid); }
1885
1893 void mark_bond_erase(int src, int dst);
1894
1903 mark_bond_erase(src.id(), dst.id());
1904 }
1905
1909 void clear_bonds() noexcept;
1910
1914 void clear() noexcept;
1915
1925 void finalize() noexcept;
1926
1927 // GCOV_EXCL_START
1928 Molecule &mol() noexcept {
1929 ABSL_ASSUME(mol_ != nullptr);
1930 return *mol_;
1931 }
1932
1933 const Molecule &mol() const noexcept {
1934 ABSL_ASSUME(mol_ != nullptr);
1935 return *mol_;
1936 }
1937 // GCOV_EXCL_STOP
1938
1939private:
1940 void discard_bonds() noexcept;
1941
1942 void discard() noexcept;
1943
1944 Molecule *mol_;
1945 int prev_num_atoms_;
1946
1947 std::vector<Molecule::GraphType::StoredEdge> bond_registry_;
1948 absl::flat_hash_map<int, std::vector<std::pair<int, int>>> delta_adj_;
1949
1950 std::vector<int> erased_atoms_;
1951 std::vector<int> erased_bonds_;
1952};
1953
1955public:
1961 explicit MoleculeSanitizer(Molecule &molecule);
1962
1963 MoleculeSanitizer(MoleculeSanitizer &&) noexcept = default;
1964 ~MoleculeSanitizer() noexcept = default;
1965
1968 MoleculeSanitizer &operator=(const MoleculeSanitizer &) = delete;
1969 MoleculeSanitizer &operator=(MoleculeSanitizer &&) noexcept = delete;
1970
1975 ABSL_MUST_USE_RESULT bool sanitize_conjugated();
1976
1983 ABSL_MUST_USE_RESULT bool sanitize_aromaticity();
1984
1991 ABSL_MUST_USE_RESULT bool sanitize_hybridization();
1992
1999 ABSL_MUST_USE_RESULT bool sanitize_valence();
2000
2015 ABSL_MUST_USE_RESULT bool sanitize_all() {
2018 }
2019
2020 Molecule &mol() noexcept {
2021 ABSL_ASSUME(mol_ != nullptr);
2022 return *mol_;
2023 }
2024
2025 const Molecule &mol() const noexcept {
2026 ABSL_ASSUME(mol_ != nullptr);
2027 return *mol_;
2028 }
2029
2030private:
2031 Molecule *mol_;
2032 absl::FixedArray<int> valences_;
2033};
2034
2035/* Out-of-line definitions for molecule */
2036
2037template <class Iterator, class>
2038Molecule::Molecule(Iterator begin, Iterator end): Molecule() {
2040 for (auto it = begin; it != end; ++it) {
2041 m.add_atom(*it);
2042 }
2043}
2044
2046 return MoleculeMutator(*this);
2047}
2048
2049/* Utility functions */
2050
2051namespace internal {
2052 inline int common_valence(const Element &effective) {
2053 const int val_electrons = effective.valence_electrons(),
2054 common_valence = val_electrons <= 4 ? val_electrons
2055 : 8 - val_electrons;
2056 return common_valence;
2057 }
2058
2059 extern const Element &
2060 effective_element_or_element(const AtomData &data) noexcept;
2061
2062 inline const Element &
2063 effective_element_or_element(Molecule::Atom atom) noexcept {
2064 return effective_element_or_element(atom.data());
2065 }
2066
2067 extern int sum_bond_order_raw(Molecule::Atom atom, int implicit_hydrogens,
2068 bool aromatic_correct);
2069
2070 inline int sum_bond_order(Molecule::Atom atom, bool aromatic_correct) {
2071 return sum_bond_order_raw(atom, atom.data().implicit_hydrogens(),
2072 aromatic_correct);
2073 }
2074
2075 extern int steric_number(int total_degree, int nb_electrons);
2076
2077 extern constants::Hybridization from_degree(int total_degree,
2078 int nb_electrons);
2079
2080 extern int nonbonding_electrons(const AtomData &data, int total_valence);
2081
2082 extern int count_pi_e(Molecule::Atom atom, int total_valence);
2083
2084 extern int aromatic_pi_e(Molecule::Atom atom, int total_valence);
2085} // namespace internal
2086
2093 return atom.degree() + atom.data().implicit_hydrogens();
2094}
2095
2103
2111
2119 return internal::sum_bond_order(atom, true);
2120}
2121
2130 return internal::nonbonding_electrons(atom.data(), sum_bond_order(atom));
2131}
2132
2142 int nbe = nonbonding_electrons(atom);
2143 if (nbe < 0)
2144 return nbe;
2145
2146 return internal::steric_number(all_neighbors(atom), nbe);
2147}
2148
2156inline const Element *effective_element(const AtomData &data) {
2157 const int effective_z = data.atomic_number() - data.formal_charge();
2158 return kPt.find_element(effective_z);
2159}
2160
2169 return effective_element(atom.data());
2170}
2171
2178extern std::vector<std::vector<int>> fragments(const Molecule &mol);
2179} // namespace nuri
2180
2181#endif /* NURI_CORE_MOLECULE_H_ */
Definition molecule.h:129
AtomData(const Element &element, int implicit_hydrogens=0, int formal_charge=0, constants::Hybridization hyb=constants::kOtherHyb, double partial_charge=0.0, int mass_number=-1, bool is_aromatic=false, bool is_in_ring=false, bool is_chiral=false, bool is_clockwise=false)
AtomData & set_element(int atomic_number)
Set the element of the atom by atomic number.
Definition molecule.h:194
bool is_aromatic() const
Definition molecule.h:297
AtomData()
Creates a dummy atom with unknown hybridization.
Definition molecule.h:134
AtomData & reset_flags()
Definition molecule.h:359
AtomData & set_chiral(bool is_chiral)
Definition molecule.h:319
AtomData & set_ring_atom(bool is_ring_atom)
Definition molecule.h:310
AtomData & set_partial_charge(double charge)
Definition molecule.h:364
constants::Hybridization hybridization() const
Definition molecule.h:267
AtomFlags flags() const
Definition molecule.h:347
std::string_view get_name() const
Definition molecule.h:378
friend bool operator==(const AtomData &lhs, const AtomData &rhs) noexcept
Definition molecule.h:409
const Element & element() const noexcept
Get the element data of the atom.
Definition molecule.h:203
AtomData & set_formal_charge(int charge)
Definition molecule.h:371
AtomData & set_name(ST &&name)
Definition molecule.h:381
const internal::PropertyMap & props() const
Definition molecule.h:394
AtomData & set_element(const Element &element)
Change the element of the atom.
Definition molecule.h:181
AtomData & add_flags(AtomFlags flags)
Definition molecule.h:349
std::string_view element_symbol() const
Get the element symbol of the atom.
Definition molecule.h:165
AtomData & set_implicit_hydrogens(int implicit_hydrogens)
Set the number of implicit hydrogen atoms.
Definition molecule.h:278
AtomData & set_isotope(int mass_number)
Set explicit isotope of the atom by mass number.
Definition molecule.h:245
bool is_chiral() const
Definition molecule.h:324
bool is_clockwise() const
Get handedness of a chiral atom.
Definition molecule.h:343
AtomData & set_isotope(const Isotope &isotope)
Set explicit isotope of the atom.
Definition molecule.h:231
std::string_view element_name() const
Get the element name of the atom.
Definition molecule.h:173
AtomData & set_aromatic(bool is_aromatic)
Definition molecule.h:292
const Isotope & isotope() const
Get the isotope of the atom.
Definition molecule.h:217
AtomData & set_clockwise(bool is_clockwise)
Definition molecule.h:328
int formal_charge() const
Definition molecule.h:376
internal::Nullable< const Isotope * > explicit_isotope() const
Get the explicitly set isotope of the atom.
Definition molecule.h:258
AtomData & add_prop(KT &&key, VT &&val)
Definition molecule.h:387
double atomic_weight() const
Get the atomic weight of the atom.
Definition molecule.h:157
AtomData & set_conjugated(bool is_conjugated)
Definition molecule.h:301
internal::PropertyMap & props()
Definition molecule.h:392
int implicit_hydrogens() const
Get the number of implicit hydrogen atoms.
Definition molecule.h:290
bool is_conjugated() const
Definition molecule.h:306
int atomic_number() const
Get the atomic number of the atom.
Definition molecule.h:149
AtomData & del_flags(AtomFlags flags)
Definition molecule.h:354
double partial_charge() const
Definition molecule.h:369
AtomData & set_hybridization(constants::Hybridization hyb)
Definition molecule.h:262
bool is_ring_atom() const
Definition molecule.h:315
Definition molecule.h:424
bool is_ring_bond() const
Definition molecule.h:464
constants::BondOrder & order()
Get the read-write reference to bond order.
Definition molecule.h:445
bool is_trans() const
Get the cis-trans configuration of the bond.
Definition molecule.h:529
BondData & set_order(constants::BondOrder order)
Definition molecule.h:447
bool is_rotatable() const
Test if this bond is rotatable.
Definition molecule.h:458
BondData & set_ring_bond(bool ring)
Definition molecule.h:468
BondData & reset_flags()
Definition molecule.h:555
BondData & del_flags(BondFlags flags)
Definition molecule.h:550
BondData(constants::BondOrder order)
Definition molecule.h:428
BondData & set_conjugated(bool conj)
Definition molecule.h:486
BondFlags flags() const
Definition molecule.h:543
internal::PropertyMap & props()
Definition molecule.h:574
BondData & set_config(bool config)
Set whether the bond configuration is explicitly specified.
Definition molecule.h:501
BondData & add_flags(BondFlags flags)
Definition molecule.h:545
bool is_conjugated() const
Definition molecule.h:482
BondData & add_prop(KT &&key, VT &&val)
Definition molecule.h:569
double approx_order() const
Get the approximate bond order of the bond.
Definition molecule.h:440
std::string_view get_name() const
Definition molecule.h:560
BondData()
Definition molecule.h:426
BondData & set_trans(bool trans)
Set cis-trans configuration of the bond.
Definition molecule.h:538
constants::BondOrder order() const
Get the bond order of the bond.
Definition molecule.h:434
bool has_config() const
Test if the bond configuration is explicitly specified.
Definition molecule.h:494
bool is_aromatic() const
Definition molecule.h:473
const internal::PropertyMap & props() const
Definition molecule.h:576
BondData & set_aromatic(bool aromatic)
Definition molecule.h:477
BondData & set_name(ST &&name)
Definition molecule.h:563
The class for element data.
Definition element.h:157
constexpr std::string_view name() const noexcept
Get the IUPAC Name of the atom.
Definition element.h:258
constexpr std::string_view symbol() const noexcept
Get the IUPAC Symbol of the atom.
Definition element.h:252
const Isotope * find_isotope(int mass_number) const noexcept
Find an element with the given mass number.
Definition element.h:305
constexpr const Isotope & major_isotope() const noexcept
Get the representative isotope of the element.
Definition element.h:296
constexpr int atomic_number() const noexcept
Get the atomic number of the atom.
Definition element.h:180
constexpr double atomic_weight() const noexcept
Get the atomic weight of the atom.
Definition element.h:265
constexpr std::int16_t valence_electrons() const noexcept
Get the number of valence electrons of the atom.
Definition element.h:186
Class for very sparse graphs, especially designed for the molecular graphs.
Definition graph.h:475
internal::NodeWrapper< Graph, true > ConstNodeRef
Definition graph.h:497
internal::EdgeIterator< Graph, false > edge_iterator
Definition graph.h:499
internal::NodeIterator< Graph, true > const_iterator
Definition graph.h:494
internal::AdjWrapper< Graph, true > ConstAdjRef
Definition graph.h:507
internal::EdgeIterator< Graph, true > const_edge_iterator
Definition graph.h:500
internal::NodeWrapper< Graph, false > NodeRef
Definition graph.h:496
internal::EdgeWrapper< Graph, false > EdgeRef
Definition graph.h:501
internal::AdjIterator< Graph, false > adjacency_iterator
Definition graph.h:504
internal::EdgeWrapper< Graph, true > ConstEdgeRef
Definition graph.h:502
internal::AdjWrapper< Graph, false > AdjRef
Definition graph.h:506
internal::AdjIterator< Graph, true > const_adjacency_iterator
Definition graph.h:505
internal::NodeIterator< Graph, false > iterator
Definition graph.h:492
A class to mutate a molecule.
Definition molecule.h:1772
std::pair< int, bool > register_bond(int src, int dst, const BondData &bond)
Register a bond to be added to the molecule.
MoleculeMutator(MoleculeMutator &&) noexcept=default
void mark_atom_erase(Molecule::Atom atom)
Mark an atom to be erased.
Definition molecule.h:1827
void finalize() noexcept
Finalize the mutation.
int add_atom(const AtomData &atom)
Add an atom to the molecule.
Definition molecule.h:1795
void clear_atoms() noexcept
Clear all atoms and bonds of the molecule.
const Molecule & mol() const noexcept
Definition molecule.h:1933
void mark_bond_erase(int bid)
Mark a bond to be erased.
Definition molecule.h:1884
int add_atom(const Molecule::Atom &atom)
Add an atom to the molecule.
Definition molecule.h:1811
Molecule & mol() noexcept
Definition molecule.h:1928
int add_atom(AtomData &&atom) noexcept
Add an atom to the molecule.
Definition molecule.h:1802
void mark_bond_erase(Molecule::Atom src, Molecule::Atom dst)
Mark a bond to be erased.
Definition molecule.h:1902
void clear_bonds() noexcept
Clear all bonds of the molecule.
MoleculeMutator(Molecule &mol)
Construct a new MoleculeMutator object.
Definition molecule.h:1779
MoleculeMutator(const MoleculeMutator &)=delete
MoleculeMutator & operator=(const MoleculeMutator &)=delete
void mark_bond_erase(int src, int dst)
Mark a bond to be erased.
void clear() noexcept
Clear the molecule.
void mark_atom_erase(int atom_idx)
Mark an atom to be erased.
Definition molecule.h:1819
ABSL_MUST_USE_RESULT bool sanitize_conjugated()
Sanitize conjugated bonds.
const Molecule & mol() const noexcept
Definition molecule.h:2025
ABSL_MUST_USE_RESULT bool sanitize_hybridization()
Sanitize hybridization.
ABSL_MUST_USE_RESULT bool sanitize_all()
Sanitize all.
Definition molecule.h:2015
ABSL_MUST_USE_RESULT bool sanitize_aromaticity()
Sanitize aromaticity.
ABSL_MUST_USE_RESULT bool sanitize_valence()
Sanitize valences.
MoleculeSanitizer(Molecule &molecule)
Construct a new MoleculeSanitizer object.
Molecule & mol() noexcept
Definition molecule.h:2020
MoleculeSanitizer(MoleculeSanitizer &&) noexcept=default
Read-only molecule class.
Definition molecule.h:943
GraphType::adjacency_iterator neighbor_iterator
Definition molecule.h:961
MutableBond bond(int bond_idx)
Get a mutable bond of the molecule.
Definition molecule.h:1118
int num_neighbors(int atom) const
Get the explicitly connected neighbor atoms of the atom.
Definition molecule.h:1228
const_iterator end() const
The past-the-end iterator of the molecule over atoms.
Definition molecule.h:1090
void erase_hydrogens()
Erase all trivial hydrogens from the molecule.
void clear_atoms() noexcept
Clear all atoms and bonds of the molecule.
void clear() noexcept
Reset the molecule to an empty state.
ConstSubstructure substructure(SubstructCategory cat=SubstructCategory::kUnknown) const
Create and return a substurcture of the molecule.
Definition molecule.h:1605
Substructure atom_substructure(internal::IndexSet &&atoms, SubstructCategory cat=SubstructCategory::kUnknown)
Create and return a substurcture of the molecule.
Definition molecule.h:1581
int num_atoms() const
Get the number of atoms in the molecule.
Definition molecule.h:1011
GraphType::ConstAdjRef Neighbor
Definition molecule.h:960
GraphType::const_adjacency_iterator const_neighbor_iterator
Definition molecule.h:962
double distance(int src, int dst, int conf=0) const
Calculate the distance between two atoms.
Definition molecule.h:1446
int count_heavy_bonds() const
Get the number of bonds between heavy atoms in the molecule.
Definition molecule.h:1214
ConstSubstructure atom_substructure(internal::IndexSet &&atoms, SubstructCategory cat=SubstructCategory::kUnknown) const
Create and return a substurcture of the molecule.
Definition molecule.h:1630
double distsq(int src, int dst, int conf=0) const
Calculate the squared distance between two atoms.
bool empty() const
Check if the molecule has any atoms.
Definition molecule.h:999
const_bond_iterator find_bond(int src, int dst) const
Get a bond of the molecule.
Definition molecule.h:1149
bool rotate_bond(int ref_atom, int pivot_atom, double angle)
Rotate a bond.
void update_topology()
Update topology of the molecule.
Substructure bond_substructure(internal::IndexSet &&bonds, SubstructCategory cat=SubstructCategory::kUnknown) noexcept
Create and return a substurcture of the molecule.
Definition molecule.h:1592
auto bonds()
Get an iterable, modifiable view over bonds of the molecule.
Definition molecule.h:1180
const_iterator const_atom_iterator
Definition molecule.h:952
const_bond_iterator bond_end() const
The past-the-end iterator of the molecule over bonds.
Definition molecule.h:1207
void merge(const MoleculeLike &other)
Merge other molecule-like object into this molecule.
Definition molecule.h:1710
const_neighbor_iterator find_neighbor(Atom src, Atom dst) const
Find a neighbor of the atom.
Definition molecule.h:1274
GraphType::iterator iterator
Definition molecule.h:949
iterator end()
The past-the-end iterator of the molecule over atoms.
Definition molecule.h:1086
const_neighbor_iterator neighbor_begin(int atom_idx) const
The begin iterator of an atom over its neighbors.
Definition molecule.h:1287
void clear_bonds() noexcept
Clear all bonds of the molecule.
MoleculeMutator mutator()
Get a MoleculeMutator object associated with the molecule.
Definition molecule.h:2045
auto bonds() const
Get an iterable, non-modifiable view over bonds of the molecule.
Definition molecule.h:1185
int num_sssr() const
Get size of SSSR.
Definition molecule.h:1680
bool rotate_bond(int bid, double angle)
Rotate a bond.
GraphType::NodeRef MutableAtom
Definition molecule.h:947
const std::vector< std::vector< int > > & ring_groups() const
Get the ring groups of the molecule, i.e. all rings of a molecule, merged into groups of rings that s...
Definition molecule.h:1688
MutableAtom atom(int atom_idx)
Get a mutable atom of the molecule.
Definition molecule.h:1032
const_iterator begin() const
The begin iterator of the molecule over atoms.
Definition molecule.h:1070
const std::vector< Matrix3Xd > & confs() const
Get all atomic coordinates of the conformers.
Definition molecule.h:1393
GraphType::const_edge_iterator const_bond_iterator
Definition molecule.h:957
bond_iterator bond_begin()
The begin iterator of the molecule over bonds.
Definition molecule.h:1195
GraphType::ConstEdgeRef Bond
Definition molecule.h:955
GraphType::edge_iterator bond_iterator
Definition molecule.h:956
ConstSubstructure bond_substructure(internal::IndexSet &&bonds, SubstructCategory cat=SubstructCategory::kUnknown) const
Create and return a substurcture of the molecule.
Definition molecule.h:1642
const GraphType & raw_graph() const
Get the underlying graph of the molecule.
Definition molecule.h:1345
const_bond_iterator bond_begin() const
The begin iterator of the molecule over bonds.
Definition molecule.h:1199
iterator begin()
The begin iterator of the molecule over atoms.
Definition molecule.h:1065
bond_iterator find_bond(Atom src, Atom dst)
Get a bond of the molecule.
Definition molecule.h:1161
std::vector< Matrix3Xd > & confs()
Get all atomic coordinates of the conformers.
Definition molecule.h:1387
const std::string & name() const
Definition molecule.h:990
bool bond_empty() const
Check if the molecule has any bonds.
Definition molecule.h:1104
bool rotate_bond_conf(int i, int bid, double angle)
Rotate a bond of a conformer.
bond_iterator find_bond(int src, int dst)
Get a bond of the molecule.
Definition molecule.h:1137
MutableAtom operator[](int atom_idx)
Get a mutable atom of the molecule.
Definition molecule.h:1050
neighbor_iterator find_neighbor(Atom src, Atom dst)
Find a neighbor of the atom.
Definition molecule.h:1262
void reserve_bonds(int num_bonds)
Definition molecule.h:994
void transform(const Eigen::Isometry3d &trans)
Transform the molecule with the given affine transformation.
Definition molecule.h:1399
std::vector< Substructure > & substructures()
Get the substructures.
Definition molecule.h:1652
const_iterator atom_begin() const
The begin iterator of the molecule over atoms.
Definition molecule.h:1081
GraphType::AdjRef MutableNeighbor
Definition molecule.h:959
iterator atom_end()
The past-the-end iterator of the molecule over atoms.
Definition molecule.h:1095
int count_heavy_atoms() const
Get the number of heavy atoms in the molecule (i.e., non-hydrogen atoms).
Definition molecule.h:1019
iterator atom_begin()
The begin iterator of the molecule over atoms.
Definition molecule.h:1076
Atom operator[](int atom_idx) const
Get an atom of the molecule.
Definition molecule.h:1059
const internal::PropertyMap & props() const
Definition molecule.h:1725
const_bond_iterator find_bond(Atom src, Atom dst) const
Get a bond of the molecule.
Definition molecule.h:1173
bool is_3d() const
Check if the molecule has any 3D conformations.
Definition molecule.h:1379
GraphType::EdgeRef MutableBond
Definition molecule.h:954
Graph< AtomData, BondData > GraphType
Definition molecule.h:945
friend MoleculeMutator
Definition molecule.h:964
Substructure substructure(SubstructCategory cat=SubstructCategory::kUnknown)
Create and return a substurcture of the molecule.
Definition molecule.h:1556
void reserve(int num_atoms)
Definition molecule.h:992
const_neighbor_iterator find_neighbor(int src, int dst) const
Find a neighbor of the atom.
Definition molecule.h:1250
ABSL_MUST_USE_RESULT bool add_hydrogens(bool update_confs=true, bool optimize=true)
Make all implicit hydrogens explicit.
ConstSubstructure substructure(internal::IndexSet &&atoms, internal::IndexSet &&bonds, SubstructCategory cat=SubstructCategory::kUnknown) const
Create and return a substurcture of the molecule.
Definition molecule.h:1618
GraphType::ConstNodeRef Atom
Definition molecule.h:948
double distsq(Bond bond, int conf=0) const
Calculate the squared distance between two bonded atoms.
Definition molecule.h:1434
double distance(Bond bond, int conf=0) const
Calculate the distance between two bonded atoms.
Definition molecule.h:1458
ArrayXd bond_lengths(int conf=0) const
Calculate the bond lengths of the molecule.
Molecule() noexcept=default
Construct an empty Molecule object.
iterator atom_iterator
Definition molecule.h:951
void add_prop(KT &&key, VT &&val)
Definition molecule.h:1719
auto cbonds() const
Get an iterable, non-modifiable view over bonds of the molecule.
Definition molecule.h:1190
const std::vector< Substructure > & substructures() const
Get the substructures.
Definition molecule.h:1659
std::string & name()
Definition molecule.h:988
internal::PropertyMap & props()
Definition molecule.h:1723
neighbor_iterator find_neighbor(int src, int dst)
Find a neighbor of the atom.
Definition molecule.h:1238
int num_bonds() const
Get the number of bonds in the molecule.
Definition molecule.h:1109
neighbor_iterator neighbor_begin(int atom_idx)
The begin iterator of an atom over its neighbors.
Definition molecule.h:1281
const_neighbor_iterator neighbor_end(int atom_idx) const
The past-the-end iterator of an atom over its neighbors.
Definition molecule.h:1299
int num_fragments() const
Get number of fragments (aka connected components).
Definition molecule.h:1696
const_iterator atom_end() const
The past-the-end iterator of the molecule over atoms.
Definition molecule.h:1099
Bond bond(int bond_idx) const
Get a bond of the molecule.
Definition molecule.h:1127
bond_iterator bond_end()
The past-the-end iterator of the molecule over bonds.
Definition molecule.h:1203
int size() const
Get the number of atoms in the molecule.
Definition molecule.h:1005
Substructure substructure(internal::IndexSet &&atoms, internal::IndexSet &&bonds, SubstructCategory cat=SubstructCategory::kUnknown)
Create and return a substurcture of the molecule.
Definition molecule.h:1569
Atom atom(int atom_idx) const
Get an atom of the molecule.
Definition molecule.h:1041
neighbor_iterator neighbor_end(int atom_idx)
The past-the-end iterator of an atom over its neighbors.
Definition molecule.h:1293
bool rotate_bond_conf(int i, int ref_atom, int pivot_atom, double angle)
Rotate a bond of a conformer.
GraphType::const_iterator const_iterator
Definition molecule.h:950
void transform(int i, const Eigen::Isometry3d &trans)
Transform a conformer of the molecule with the given affine transformation.
Definition molecule.h:1411
internal::SubEdgeWrapper< Subgraph, is_const > EdgeRef
Definition subgraph.h:592
internal::SubNodeIterator< Subgraph, is_const > iterator
Definition subgraph.h:583
internal::EdgesWrapper< Subgraph, true > ConstEdgesWrapper
Definition subgraph.h:595
internal::SubEdgeIterator< Subgraph, is_const > edge_iterator
Definition subgraph.h:590
internal::SubNodeWrapper< Subgraph, true > ConstNodeRef
Definition subgraph.h:588
internal::const_if_t< is_const, graph_type > parent_type
Definition subgraph.h:578
internal::SubAdjIterator< Subgraph, true > const_adjacency_iterator
Definition subgraph.h:598
internal::EdgesWrapper< Subgraph, is_const > EdgesWrapper
Definition subgraph.h:594
internal::SubEdgeIterator< Subgraph, true > const_edge_iterator
Definition subgraph.h:591
internal::SubNodeWrapper< Subgraph, is_const > NodeRef
Definition subgraph.h:587
internal::SubEdgeWrapper< Subgraph, true > ConstEdgeRef
Definition subgraph.h:593
internal::SubAdjIterator< Subgraph, is_const > adjacency_iterator
Definition subgraph.h:597
internal::SubNodeIterator< Subgraph, true > const_iterator
Definition subgraph.h:585
internal::SubAdjWrapper< Subgraph, true > ConstAdjRef
Definition subgraph.h:600
internal::SubAdjWrapper< Subgraph, is_const > AdjRef
Definition subgraph.h:599
Definition geometry.h:259
Hybridization
The hybridization state of an atom object.
Definition molecule.h:43
@ kSP3D2
Definition molecule.h:50
@ kSP
Definition molecule.h:46
@ kOtherHyb
Definition molecule.h:51
@ kSP3D
Definition molecule.h:49
@ kSP2
Definition molecule.h:47
@ kTerminal
Definition molecule.h:45
@ kUnbound
Definition molecule.h:44
@ kSP3
Definition molecule.h:48
std::ostream & operator<<(std::ostream &os, Hybridization hyb)
Definition molecule.h:54
constexpr double kBondOrderToDouble[]
Definition molecule.h:108
BondOrder
The bond order of a bond object.
Definition molecule.h:80
@ kDoubleBond
Definition molecule.h:83
@ kAromaticBond
Definition molecule.h:86
@ kSingleBond
Definition molecule.h:82
@ kQuadrupleBond
Definition molecule.h:85
@ kTripleBond
Definition molecule.h:84
@ kOtherBond
Definition molecule.h:81
Definition crdgen.h:16
constants::BondOrder clamp_ord(int ord)
Definition molecule.h:116
SubgraphOf< GT > subgraph_from_nodes(GT &&graph, internal::IndexSet &&nodes)
Make a subgraph from list of nodes.
Definition subgraph.h:1730
constexpr T clamp(T v, T l, T h)
Definition utils.h:87
AtomFlags
Definition molecule.h:121
@ kConjugated
Definition molecule.h:123
@ kClockWise
Definition molecule.h:126
@ kChiral
Definition molecule.h:125
@ kRing
Definition molecule.h:124
@ kAromatic
Definition molecule.h:122
SubgraphOf< GT > make_subgraph(GT &&graph)
Make an empty subgraph from a graph.
Definition subgraph.h:1696
BondFlags
Definition molecule.h:416
@ kConjugated
Definition molecule.h:419
@ kRing
Definition molecule.h:417
@ kTransConfig
Definition molecule.h:421
@ kAromatic
Definition molecule.h:418
@ kConfigSpecified
Definition molecule.h:420
SubstructCategory
Definition molecule.h:587
@ kUnknown
Definition molecule.h:588
@ kResidue
Definition molecule.h:589
@ kChain
Definition molecule.h:590
int count_heavy(Molecule::Atom atom)
Get the number of heavy atoms bonded to an atom.
int all_neighbors(Molecule::Atom atom)
Get the number of all neighbors of an atom.
Definition molecule.h:2092
int count_hydrogens(Molecule::Atom atom)
Count the number of hydrogens of the atom.
SubgraphOf< GT > subgraph_from_edges(GT &&graph, internal::IndexSet &&edges)
Make a subgraph from list of edges.
Definition subgraph.h:1745
int steric_number(Molecule::Atom atom)
Get the predicted steric number of the atom.
Definition molecule.h:2141
int nonbonding_electrons(Molecule::Atom atom)
Get the predicted non-bonding electron count of the atom.
Definition molecule.h:2129
constexpr bool operator==(const Isotope &lhs, const Isotope &rhs) noexcept
Definition element.h:34
Subgraph(Graph< NT, ET > &graph) -> Subgraph< NT, ET, false >
internal::Substructure< false > Substructure
Definition molecule.h:928
int sum_bond_order(Molecule::Atom atom)
Get the approximate total bond order of the atom.
Definition molecule.h:2118
std::vector< std::vector< int > > fragments(const Molecule &mol)
Get fragments of the molecule.
const Element * effective_element(const AtomData &data)
Get "effective" element of the atom.
Definition molecule.h:2156
internal::Substructure< true > ConstSubstructure
Definition molecule.h:929
constants::Hybridization clamp_hyb(int hyb)
Definition molecule.h:111
Definition element.h:27