RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
Pairlist.h
Go to the documentation of this file.
1//
2//
3// Copyright (C) 2020 Schrödinger, LLC
4//
5// @@ All Rights Reserved @@
6// This file is part of the RDKit.
7// The contents are covered by the terms of the BSD license
8// which is included in the file license.txt, found at the root
9// of the RDKit source tree.
10//
11#pragma once
12
13#include <cstdint>
14#include <sstream>
15#include <string>
16#include <vector>
17
18#include "../Descriptor.h"
19
20namespace RDKit {
21namespace CIPLabeler {
22
23/**
24 * Implementation of a descriptor list that allows descriptors to be added and
25 * ignored. The list maintains an integer value throughout which stores the
26 * pairing of descriptors and allows easy comparison between descriptor lists in
27 * that higher priority descriptor pairing will always have a higher integer
28 * value. The integer value can be access via the {@link #getPairing()} method.
29 *
30 * @see Descriptor
31 */
32class PairList {
33 public:
34 using pairing_t = std::uint64_t;
35 static constexpr int numPairingBits = sizeof(pairing_t) * 8;
36
37 static Descriptor ref(Descriptor descriptor) {
38 switch (descriptor) {
39 case Descriptor::R:
40 case Descriptor::M:
42 return Descriptor::R;
43 case Descriptor::S:
44 case Descriptor::P:
46 return Descriptor::S;
47 default:
48 return Descriptor::NONE;
49 }
50 }
51
52 PairList() = default;
53
55
56 /**
57 * Creates a new list from a provided head and tail. The head and tail
58 * ignored descriptors are first transferred and then their descriptors. In
59 * either list, descriptors that are ignored by the other will be not be
60 * added to the new instance.
61 *
62 * @param head the head of the list (prefix)
63 * @param tail the tail of the list (suffix)
64 */
66 // add descriptors to the new instance (ignored descriptors not added)
67 addAll(head.d_descriptors);
68 addAll(tail.d_descriptors);
69 }
70
71 Descriptor getRefDescriptor() const { return ref(d_descriptors[0]); }
72
73 /**
74 * Adds a descriptor to the descriptor list. If the provided descriptor is
75 * present in the ignore set the descriptor will not be added.
76 *
77 * @param descriptor the descriptor to add.
78 * @return whether the descriptor was added to the list
79 */
80
81 bool add(Descriptor descriptor) {
82 switch (descriptor) {
83 case Descriptor::R:
84 case Descriptor::S:
85 case Descriptor::M:
86 case Descriptor::P:
89 addAndPair(descriptor);
90 return true;
91 default:
92 return false;
93 }
94 }
95
96 /**
97 * Adds multiple descriptors to the descriptor list. If the descriptor is
98 * present in the ignore set it will not be added to the list.
99 *
100 * @param descriptors a collection of descriptors to be added
101 */
102 template <typename T>
103 void addAll(const T &descriptors) {
104 for (const auto &descriptor : descriptors) {
105 add(descriptor);
106 }
107 }
108
109 /**
110 * Access a positive integer that represents the like/unlike pairings of
111 * this descriptor list. The like/unlike is represented by set bits in an
112 * integer value and means larger integer values indicates a higher
113 * descriptor pairing preference.
114 *
115 * @return an integer representing the descriptor pairings
116 */
117 pairing_t getPairing() const { return d_pairing; }
118
119 int compareTo(const PairList &that) const {
120 if (d_descriptors.size() != that.d_descriptors.size()) {
121 throw std::runtime_error("Descriptor lists should be the same length!");
122 }
123 Descriptor thisRef = d_descriptors[0];
124 Descriptor thatRef = that.d_descriptors[0];
125 for (auto i = 1u; i < d_descriptors.size(); ++i) {
126 if (thisRef == d_descriptors[i] && thatRef != that.d_descriptors[i]) {
127 return +1;
128 }
129 if (thisRef != d_descriptors[i] && thatRef == that.d_descriptors[i]) {
130 return -1;
131 }
132 }
133 return 0;
134 }
135
136 bool operator<(const PairList &that) const { return compareTo(that) == -1; }
137
138 std::string toString() const {
139 // handles cases that would break the toString method
140 if (d_descriptors.empty() || d_descriptors[0] == Descriptor::NONE) {
141 return "";
142 }
143
144 std::stringstream ss;
145 auto basis = d_descriptors[0];
146 ss << to_string(basis) << ':';
147
148 basis = ref(basis);
149
150 // build like (l) / unlike (u) descriptor pairing
151 for (auto it = d_descriptors.begin() + 1; it != d_descriptors.end(); ++it) {
152 ss << (basis == ref(*it) ? "l" : "u");
153 }
154
155 return ss.str();
156 }
157
158 private:
159 std::vector<Descriptor> d_descriptors;
160
161 pairing_t d_pairing = 0;
162
163 /**
164 * Adds the descriptor to the descriptor list and stores the pair in an set
165 * bit (64-bit integer).
166 *
167 * @param descriptor the descriptor to add an pair
168 * @return whether the descriptor was added
169 */
170 void addAndPair(Descriptor descriptor) {
171 // if this isn't the first descriptor - check the pairing
172 if (!d_descriptors.empty() && d_descriptors[0] == descriptor) {
173 // set the bit to indicate a pair
174 d_pairing |= static_cast<pairing_t>(1)
175 << (numPairingBits - 1 - d_descriptors.size());
176 }
177 d_descriptors.push_back(ref(descriptor));
178 }
179};
180
181} // namespace CIPLabeler
182} // namespace RDKit
std::uint64_t pairing_t
Definition Pairlist.h:34
bool operator<(const PairList &that) const
Definition Pairlist.h:136
std::string toString() const
Definition Pairlist.h:138
PairList(Descriptor ref)
Definition Pairlist.h:54
static constexpr int numPairingBits
Definition Pairlist.h:35
static Descriptor ref(Descriptor descriptor)
Definition Pairlist.h:37
int compareTo(const PairList &that) const
Definition Pairlist.h:119
bool add(Descriptor descriptor)
Definition Pairlist.h:81
PairList(const PairList &head, const PairList &tail)
Definition Pairlist.h:65
void addAll(const T &descriptors)
Definition Pairlist.h:103
pairing_t getPairing() const
Definition Pairlist.h:117
Descriptor getRefDescriptor() const
Definition Pairlist.h:71
static std::string to_string(const Descriptor &desc)
Definition Descriptor.h:54
Std stuff.
bool rdvalue_is(const RDValue_cast_t)