Skip to content

Commit fbc6844

Browse files
authored
MacroMol core (rdkit#9373)
1 parent cfa1451 commit fbc6844

13 files changed

Lines changed: 731 additions & 4 deletions

File tree

Code/GraphMol/Atom.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ void Atom::initFromOther(const Atom &other) {
217217
} else {
218218
dp_monomerInfo = nullptr;
219219
}
220+
dp_macroAtomInfo =
221+
other.dp_macroAtomInfo ? other.dp_macroAtomInfo->copy() : nullptr;
220222
d_flags = other.d_flags;
221223
}
222224

@@ -633,6 +635,10 @@ void Atom::setMonomerInfo(AtomMonomerInfo *info) {
633635
dp_monomerInfo = info;
634636
}
635637

638+
void Atom::setMacroAtomInfo(MacroAtomInfo *info) {
639+
dp_macroAtomInfo.reset(info);
640+
}
641+
636642
void Atom::setIsotope(unsigned int what) { d_isotope = what; }
637643

638644
double Atom::getMass() const {

Code/GraphMol/Atom.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
#define _RD_ATOM_H
1818

1919
#include <limits>
20+
#include <memory>
2021

2122
// ours
2223
#include <RDGeneral/Invariant.h>
2324
#include <Query/QueryObjects.h>
2425
#include <RDGeneral/types.h>
2526
#include <RDGeneral/RDProps.h>
2627
#include <GraphMol/details.h>
28+
#include <GraphMol/MacroAtomInfo.h>
2729

2830
namespace RDKit {
2931
class Atom;
@@ -36,7 +38,6 @@ namespace RDKit {
3638
class ROMol;
3739
class RWMol;
3840
class AtomMonomerInfo;
39-
4041
//! The class for representing atoms
4142
/*!
4243
@@ -370,6 +371,13 @@ class RDKIT_GRAPHMOL_EXPORT Atom : public RDProps {
370371
//! takes ownership of the pointer
371372
void setMonomerInfo(AtomMonomerInfo *info);
372373

374+
MacroAtomInfo *getMacroAtomInfo() { return dp_macroAtomInfo.get(); }
375+
const MacroAtomInfo *getMacroAtomInfo() const {
376+
return dp_macroAtomInfo.get();
377+
}
378+
//! takes ownership of the pointer
379+
void setMacroAtomInfo(MacroAtomInfo *info);
380+
373381
//! Set the atom map Number of the atom
374382
void setAtomMapNum(int mapno, bool strict = true) {
375383
PRECONDITION(
@@ -422,6 +430,7 @@ class RDKIT_GRAPHMOL_EXPORT Atom : public RDProps {
422430

423431
ROMol *dp_mol;
424432
AtomMonomerInfo *dp_monomerInfo;
433+
std::unique_ptr<MacroAtomInfo> dp_macroAtomInfo;
425434
void initAtom();
426435
void initFromOther(const Atom &other);
427436
};

Code/GraphMol/Bond.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Bond::Bond(const Bond &other) : RDProps(other) {
3535
} else {
3636
dp_stereoAtoms = nullptr;
3737
}
38+
dp_macroBondInfo =
39+
other.dp_macroBondInfo ? other.dp_macroBondInfo->copy() : nullptr;
3840
df_isAromatic = other.df_isAromatic;
3941
df_isConjugated = other.df_isConjugated;
4042
d_index = other.d_index;
@@ -58,6 +60,8 @@ Bond &Bond::operator=(const Bond &other) {
5860
} else {
5961
dp_stereoAtoms = nullptr;
6062
}
63+
dp_macroBondInfo =
64+
other.dp_macroBondInfo ? other.dp_macroBondInfo->copy() : nullptr;
6165
df_isAromatic = other.df_isAromatic;
6266
df_isConjugated = other.df_isConjugated;
6367
d_index = other.d_index;
@@ -77,6 +81,10 @@ void Bond::setOwningMol(ROMol *other) {
7781
dp_mol = other;
7882
}
7983

84+
void Bond::setMacroBondInfo(MacroBondInfo *info) {
85+
dp_macroBondInfo.reset(info);
86+
}
87+
8088
unsigned int Bond::getOtherAtomIdx(const unsigned int thisIdx) const {
8189
if (d_beginAtomIdx == thisIdx) {
8290
return d_endAtomIdx;

Code/GraphMol/Bond.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define RD_BOND_H
1313

1414
// std stuff
15+
#include <memory>
1516
#include <utility>
1617

1718
// Ours
@@ -20,6 +21,7 @@
2021
#include <RDGeneral/types.h>
2122
#include <RDGeneral/RDProps.h>
2223
#include <GraphMol/details.h>
24+
#include <GraphMol/MacroBondInfo.h>
2325

2426
namespace RDKit {
2527
class ROMol;
@@ -124,6 +126,7 @@ class RDKIT_GRAPHMOL_EXPORT Bond : public RDProps {
124126
// the molecule will still be pointing to the original object
125127
dp_mol = std::exchange(o.dp_mol, nullptr);
126128
dp_stereoAtoms = std::exchange(o.dp_stereoAtoms, nullptr);
129+
dp_macroBondInfo = std::move(o.dp_macroBondInfo);
127130
d_flags = std::exchange(o.d_flags, 0);
128131
}
129132
Bond &operator=(Bond &&o) noexcept {
@@ -144,6 +147,7 @@ class RDKIT_GRAPHMOL_EXPORT Bond : public RDProps {
144147
delete dp_stereoAtoms;
145148
dp_mol = std::exchange(o.dp_mol, nullptr);
146149
dp_stereoAtoms = std::exchange(o.dp_stereoAtoms, nullptr);
150+
dp_macroBondInfo = std::move(o.dp_macroBondInfo);
147151
d_flags = std::exchange(o.d_flags, 0);
148152
return *this;
149153
}
@@ -362,6 +366,13 @@ class RDKIT_GRAPHMOL_EXPORT Bond : public RDProps {
362366
return *dp_stereoAtoms;
363367
}
364368

369+
MacroBondInfo *getMacroBondInfo() { return dp_macroBondInfo.get(); }
370+
const MacroBondInfo *getMacroBondInfo() const {
371+
return dp_macroBondInfo.get();
372+
}
373+
//! takes ownership of the pointer
374+
void setMacroBondInfo(MacroBondInfo *info);
375+
365376
//! calculates any of our lazy \c properties
366377
/*!
367378
<b>Notes:</b>
@@ -384,6 +395,7 @@ class RDKIT_GRAPHMOL_EXPORT Bond : public RDProps {
384395
/// void setOwningMol(ROMol &other) { setOwningMol(&other); }
385396
ROMol *dp_mol;
386397
INT_VECT *dp_stereoAtoms;
398+
std::unique_ptr<MacroBondInfo> dp_macroBondInfo;
387399
atomindex_t d_index;
388400
atomindex_t d_beginAtomIdx, d_endAtomIdx;
389401
bool df_isAromatic;

Code/GraphMol/CMakeLists.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
rdkit_library(GraphMol
22
Atom.cpp QueryAtom.cpp QueryBond.cpp Bond.cpp
3-
MolOps.cpp FindRings.cpp ROMol.cpp RWMol.cpp PeriodicTable.cpp
3+
MolOps.cpp FindRings.cpp ROMol.cpp RWMol.cpp
4+
MacroAtomInfo.cpp
5+
MacroMol.cpp
6+
PeriodicTable.cpp
47
atomic_data.cpp QueryOps.cpp MolPickler.cpp Canon.cpp
58
AtomIterators.cpp BondIterators.cpp Aromaticity.cpp Kekulize.cpp
69
ConjugHybrid.cpp AddHs.cpp
@@ -42,6 +45,9 @@ rdkit_headers(Atom.h
4245
Rings.h
4346
ROMol.h
4447
RWMol.h
48+
MacroAtomInfo.h
49+
MacroBondInfo.h
50+
MacroMol.h
4551
SanitException.h
4652
SubstanceGroup.h
4753
StereoGroup.h
@@ -208,4 +214,7 @@ rdkit_catch_test(tableTestsCatch catch_periodictable.cpp
208214
rdkit_catch_test(molopsTestsCatch catch_molops.cpp
209215
LINK_LIBRARIES FileParsers SmilesParse GraphMol)
210216

211-
rdkit_catch_test(ringSystemsTest ring_systems_test.cpp LINK_LIBRARIES SmilesParse GraphMol RDStreams)
217+
rdkit_catch_test(testMacroMol testMacroMol.cpp
218+
LINK_LIBRARIES SmilesParse GraphMol)
219+
220+
rdkit_catch_test(ringSystemsTest ring_systems_test.cpp LINK_LIBRARIES SmilesParse GraphMol RDStreams)

Code/GraphMol/MacroAtomInfo.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//
2+
// Copyright (C) 2026 Schrödinger and other RDKit contributors
3+
//
4+
// @@ All Rights Reserved @@
5+
// This file is part of the RDKit.
6+
// The contents are covered by the terms of the BSD license
7+
// which is included in the file license.txt, found at the root
8+
// of the RDKit source tree.
9+
//
10+
#include "MacroAtomInfo.h"
11+
12+
#include <RDGeneral/Invariant.h>
13+
#include <RDGeneral/RDLog.h>
14+
15+
#include <array>
16+
#include <utility>
17+
18+
namespace RDKit {
19+
namespace {
20+
const std::array<std::pair<MonomerClass, const char *>, 4> monomerClassNames = {
21+
{
22+
{MonomerClass::AminoAcid, "AminoAcid"},
23+
{MonomerClass::NucleicAcid, "NucleicAcid"},
24+
{MonomerClass::Chemical, "Chemical"},
25+
{MonomerClass::Other, "Other"},
26+
}};
27+
} // namespace
28+
29+
const char *monomerClassToString(MonomerClass monomerClass) {
30+
for (const auto &[value, name] : monomerClassNames) {
31+
if (value == monomerClass) {
32+
return name;
33+
}
34+
}
35+
POSTCONDITION(false, "unknown monomer class");
36+
return "";
37+
}
38+
39+
MonomerClass monomerClassFromString(const std::string &monomerClass) {
40+
for (const auto &[value, name] : monomerClassNames) {
41+
if (monomerClass == name) {
42+
return value;
43+
}
44+
}
45+
BOOST_LOG(rdWarningLog) << "unrecognized monomer class '" << monomerClass
46+
<< "'; treating it as Other" << std::endl;
47+
return MonomerClass::Other;
48+
}
49+
50+
} // namespace RDKit

Code/GraphMol/MacroAtomInfo.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//
2+
// Copyright (C) 2026 Schrödinger and other RDKit contributors
3+
//
4+
// @@ All Rights Reserved @@
5+
// This file is part of the RDKit.
6+
// The contents are covered by the terms of the BSD license
7+
// which is included in the file license.txt, found at the root
8+
// of the RDKit source tree.
9+
//
10+
/*! \file MacroAtomInfo.h
11+
12+
\brief Defines atom-level macro atom information
13+
14+
*/
15+
#ifndef RD_MACROATOMINFO_H
16+
#define RD_MACROATOMINFO_H
17+
18+
#include <RDGeneral/export.h>
19+
20+
#include <memory>
21+
#include <string>
22+
#include <utility>
23+
24+
namespace RDKit {
25+
26+
//! Classes of monomer that a macro atom can represent.
27+
/*!
28+
Supported monomer classes for macro atoms.
29+
30+
A regular enum is used here because MonomerClass appears in public MacroMol
31+
method signatures. RDKit's BETTER_ENUM macro can expand to different C++
32+
types depending on per-source-file preprocessor settings, which can cause
33+
link errors in shared-library and unity builds.
34+
*/
35+
enum MonomerClass : int {
36+
AminoAcid,
37+
NucleicAcid,
38+
Chemical,
39+
Other
40+
};
41+
42+
//! Converts a macro atom monomer class enum value to its recognized name.
43+
RDKIT_GRAPHMOL_EXPORT const char *monomerClassToString(
44+
MonomerClass monomerClass);
45+
46+
//! Converts a recognized macro atom monomer class name to its enum value.
47+
RDKIT_GRAPHMOL_EXPORT MonomerClass
48+
monomerClassFromString(const std::string &monomerClass);
49+
50+
//! Captures atom-level information for macro atoms.
51+
/*!
52+
Macro atom information is owned by an Atom and stores the macro atom's
53+
display symbol and monomer class.
54+
*/
55+
class RDKIT_GRAPHMOL_EXPORT MacroAtomInfo {
56+
public:
57+
virtual ~MacroAtomInfo() = default;
58+
59+
MacroAtomInfo() = default;
60+
61+
//! Construct macro atom information.
62+
/*!
63+
\param symbol the symbol used to identify the monomer
64+
\param monomerClass the class of monomer the macro atom represents
65+
*/
66+
MacroAtomInfo(std::string symbol,
67+
MonomerClass monomerClass = MonomerClass::Other)
68+
: d_symbol(std::move(symbol)), d_monomerClass(monomerClass) {}
69+
MacroAtomInfo(const MacroAtomInfo &other) = default;
70+
71+
//! Returns the macro atom symbol.
72+
const std::string &getSymbol() const { return d_symbol; }
73+
74+
//! Sets the macro atom symbol.
75+
/*!
76+
\param symbol the symbol used to identify the monomer
77+
*/
78+
void setSymbol(const std::string &symbol) { d_symbol = symbol; }
79+
80+
//! Returns the macro atom monomer class.
81+
MonomerClass getMonomerClass() const { return d_monomerClass; }
82+
83+
//! Sets the macro atom monomer class.
84+
/*!
85+
\param monomerClass the class of monomer the macro atom represents
86+
*/
87+
void setMonomerClass(MonomerClass monomerClass) {
88+
d_monomerClass = monomerClass;
89+
}
90+
91+
//! Returns a copy of this macro atom information.
92+
virtual std::unique_ptr<MacroAtomInfo> copy() const {
93+
return std::make_unique<MacroAtomInfo>(*this);
94+
}
95+
96+
private:
97+
std::string d_symbol{""};
98+
MonomerClass d_monomerClass{MonomerClass::Other};
99+
};
100+
} // namespace RDKit
101+
102+
#endif

0 commit comments

Comments
 (0)