Skip to content

Commit d971cfd

Browse files
authored
Merge pull request #171 from OpenBioSim/fix_170
fix_170 - detecting iron as biological
2 parents 4f39c35 + 30eb82a commit d971cfd

File tree

13 files changed

+566
-215
lines changed

13 files changed

+566
-215
lines changed

corelib/src/libs/SireMol/element.h

+16
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,19 @@ namespace SireMol
7979
bool operator==(const Element &other) const;
8080
bool operator!=(const Element &other) const;
8181

82+
bool operator==(const QString &other) const;
83+
bool operator!=(const QString &other) const;
84+
8285
bool operator>(const Element &other) const;
8386
bool operator<(const Element &other) const;
8487
bool operator>=(const Element &other) const;
8588
bool operator<=(const Element &other) const;
8689

90+
bool operator>(const QString &other) const;
91+
bool operator<(const QString &other) const;
92+
bool operator>=(const QString &other) const;
93+
bool operator<=(const QString &other) const;
94+
8795
const Element &operator=(const Element &element);
8896

8997
int nProtons() const;
@@ -122,7 +130,15 @@ namespace SireMol
122130

123131
static Element biologicalElement(const QString &name);
124132

133+
static void setElementIsBiological(const Element &element);
134+
static void setElementIsNotBiological(const Element &element);
135+
static void resetBiologicalElements();
136+
137+
static QList<Element> getBiologicalElements();
138+
125139
private:
140+
bool _locked_biological() const;
141+
126142
/** Pointer to the object containing the data for this element */
127143
ElementData *eldata;
128144
};

corelib/src/libs/SireMol/elementdb.cpp

+136-38
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include <QDataStream>
2929
#include <QRegExp>
30+
#include <QReadWriteLock>
3031
#include <cmath>
3132

3233
#include <limits>
@@ -123,6 +124,111 @@ ElementDB *ElementDB::db = 0;
123124
/////////// Implementation of Element
124125
///////////
125126

127+
Q_GLOBAL_STATIC(QReadWriteLock, globalLock);
128+
Q_GLOBAL_STATIC(QSet<int>, biological_elements);
129+
130+
/** Set that the passed element should be considered to be biological */
131+
void Element::setElementIsBiological(const Element &element)
132+
{
133+
QWriteLocker locker(globalLock());
134+
biological_elements->insert(element.nProtons());
135+
}
136+
137+
/** Set that the passed element should considered to definitely
138+
* not be biological
139+
*/
140+
void Element::setElementIsNotBiological(const Element &element)
141+
{
142+
QWriteLocker locker(globalLock());
143+
biological_elements->remove(element.nProtons());
144+
}
145+
146+
void Element::resetBiologicalElements()
147+
{
148+
QWriteLocker locker(globalLock());
149+
biological_elements->clear();
150+
151+
for (int i = 0; i < 80; ++i)
152+
{
153+
Element el(i);
154+
155+
if ((el.period() <= 3 and not el.nobleGas()) or el.halogen())
156+
biological_elements->insert(i);
157+
}
158+
159+
// also add Fe
160+
biological_elements->insert(26);
161+
}
162+
163+
/** Return a biological element that has been guessed from the passed name.
164+
Note that if no biological element was guessed, then the nearest
165+
non-biological element match is used. A biological element is one that
166+
is in the list of biological elements */
167+
Element Element::biologicalElement(const QString &name)
168+
{
169+
QReadLocker locker(globalLock());
170+
171+
// guess an element with this name...
172+
Element elmnt(name);
173+
174+
// is this a biological element? - if so, return it!
175+
if (elmnt._locked_biological())
176+
return elmnt;
177+
178+
// try to guess the atom from just the first two letters...
179+
Element elmnt2(name.left(2));
180+
181+
if (elmnt2._locked_biological())
182+
return elmnt2;
183+
184+
// try to guess the atom from just the first letter...
185+
Element elmnt3(name.left(1));
186+
187+
if (elmnt3._locked_biological())
188+
return elmnt3;
189+
190+
// we couldn't find anything - return the original, non-biological guess
191+
return elmnt;
192+
}
193+
194+
/** Return whether or not this is biological
195+
(in first three periods and not a noble gas, or a halogen)
196+
(this does preclude iron, potassium and calcium, which are
197+
rather biological... :-) */
198+
bool Element::_locked_biological() const
199+
{
200+
return biological_elements->contains(eldata->protnum);
201+
}
202+
203+
/** Return whether or not this is biological
204+
(in first three periods and not a noble gas, or a halogen)
205+
(this does preclude iron, potassium and calcium, which are
206+
rather biological... :-) */
207+
bool Element::biological() const
208+
{
209+
QReadLocker locker(globalLock());
210+
return this->_locked_biological();
211+
}
212+
213+
/** Return a list of all of the elements that are considered
214+
* to be biological
215+
*/
216+
QList<Element> Element::getBiologicalElements()
217+
{
218+
QReadLocker locker(globalLock());
219+
QList<int> prots = biological_elements->values();
220+
std::sort(prots.begin(), prots.end());
221+
222+
QList<Element> elements;
223+
224+
for (int i = 0; i < prots.size(); ++i)
225+
{
226+
elements.append(Element(prots[i]));
227+
}
228+
229+
return elements;
230+
}
231+
126232
/** Construct a dummy element */
127233
Element::Element()
128234
{
@@ -364,35 +470,6 @@ ElementData *ElementDB::element(const QString &s) const
364470
}
365471
}
366472

367-
/** Return a biological element that has been guessed from the passed name.
368-
Note that if no biological element was guessed, then the nearest
369-
non-biological element match is used. A biological element is one that
370-
is in the first couple of rows (proton number < 18) and is not a noble gas. */
371-
Element Element::biologicalElement(const QString &name)
372-
{
373-
// guess an element with this name...
374-
Element elmnt(name);
375-
376-
// is this a biological element? - if so, return it!
377-
if (elmnt.biological())
378-
return elmnt;
379-
380-
// try to guess the atom from just the first two letters...
381-
Element elmnt2(name.left(2));
382-
383-
if (elmnt2.biological())
384-
return elmnt2;
385-
386-
// try to guess the atom from just the first letter...
387-
Element elmnt3(name.left(1));
388-
389-
if (elmnt3.biological())
390-
return elmnt3;
391-
392-
// we couldn't find anything - return the original, non-biological guess
393-
return elmnt;
394-
}
395-
396473
/** Return whether or not this is a noble gas */
397474
bool Element::nobleGas() const
398475
{
@@ -405,15 +482,6 @@ bool Element::halogen() const
405482
return group() == 17;
406483
}
407484

408-
/** Return whether or not this is biological
409-
(in first three periods and not a noble gas, or a halogen)
410-
(this does preclude iron, potassium and calcium, which are
411-
rather biological... :-) */
412-
bool Element::biological() const
413-
{
414-
return (period() <= 3 and not nobleGas()) or halogen();
415-
}
416-
417485
/** Return whether or not this is an alkali metal (group 1 or 2) */
418486
bool Element::alkaliMetal() const
419487
{
@@ -450,6 +518,36 @@ bool Element::rareEarth() const
450518
return lanthanide() or actinide();
451519
}
452520

521+
bool Element::operator==(const QString &other) const
522+
{
523+
return this->operator==(Element(other));
524+
}
525+
526+
bool Element::operator!=(const QString &other) const
527+
{
528+
return not this->operator==(other);
529+
}
530+
531+
bool Element::operator>(const QString &other) const
532+
{
533+
return this->operator>(Element(other));
534+
}
535+
536+
bool Element::operator<(const QString &other) const
537+
{
538+
return this->operator<(Element(other));
539+
}
540+
541+
bool Element::operator>=(const QString &other) const
542+
{
543+
return this->operator>=(Element(other));
544+
}
545+
546+
bool Element::operator<=(const QString &other) const
547+
{
548+
return this->operator<=(Element(other));
549+
}
550+
453551
/** Sorting operators. Elements are compared based on their
454552
proton numbers, with elements with greater numbers being higher.
455553
The functions are also very quick. */

doc/source/changelog.rst

+4
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ organisation on `GitHub <https://github.com/openbiosim/sire>`__.
155155
when reading Mol2 files. This is more robust than using the atom name.
156156
Fixes issue #166.
157157

158+
* Made it easier to convert from strings to elements. Added the ability to
159+
customise the list of elements that are considered biological. This
160+
fixes issue #170.
161+
158162
* Please add an item to this changelog when you create your PR
159163

160164
`2023.5.1 <https://github.com/openbiosim/sire/compare/2023.5.0...2023.5.1>`__ - January 2024

0 commit comments

Comments
 (0)