diff --git a/corelib/src/libs/SireMol/element.h b/corelib/src/libs/SireMol/element.h index e6dc6b209..66f95d1c1 100644 --- a/corelib/src/libs/SireMol/element.h +++ b/corelib/src/libs/SireMol/element.h @@ -79,11 +79,19 @@ namespace SireMol bool operator==(const Element &other) const; bool operator!=(const Element &other) const; + bool operator==(const QString &other) const; + bool operator!=(const QString &other) const; + bool operator>(const Element &other) const; bool operator<(const Element &other) const; bool operator>=(const Element &other) const; bool operator<=(const Element &other) const; + bool operator>(const QString &other) const; + bool operator<(const QString &other) const; + bool operator>=(const QString &other) const; + bool operator<=(const QString &other) const; + const Element &operator=(const Element &element); int nProtons() const; @@ -122,7 +130,15 @@ namespace SireMol static Element biologicalElement(const QString &name); + static void setElementIsBiological(const Element &element); + static void setElementIsNotBiological(const Element &element); + static void resetBiologicalElements(); + + static QList getBiologicalElements(); + private: + bool _locked_biological() const; + /** Pointer to the object containing the data for this element */ ElementData *eldata; }; diff --git a/corelib/src/libs/SireMol/elementdb.cpp b/corelib/src/libs/SireMol/elementdb.cpp index a02c103f9..c9f168176 100644 --- a/corelib/src/libs/SireMol/elementdb.cpp +++ b/corelib/src/libs/SireMol/elementdb.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -123,6 +124,111 @@ ElementDB *ElementDB::db = 0; /////////// Implementation of Element /////////// +Q_GLOBAL_STATIC(QReadWriteLock, globalLock); +Q_GLOBAL_STATIC(QSet, biological_elements); + +/** Set that the passed element should be considered to be biological */ +void Element::setElementIsBiological(const Element &element) +{ + QWriteLocker locker(globalLock()); + biological_elements->insert(element.nProtons()); +} + +/** Set that the passed element should considered to definitely + * not be biological + */ +void Element::setElementIsNotBiological(const Element &element) +{ + QWriteLocker locker(globalLock()); + biological_elements->remove(element.nProtons()); +} + +void Element::resetBiologicalElements() +{ + QWriteLocker locker(globalLock()); + biological_elements->clear(); + + for (int i = 0; i < 80; ++i) + { + Element el(i); + + if ((el.period() <= 3 and not el.nobleGas()) or el.halogen()) + biological_elements->insert(i); + } + + // also add Fe + biological_elements->insert(26); +} + +/** Return a biological element that has been guessed from the passed name. + Note that if no biological element was guessed, then the nearest + non-biological element match is used. A biological element is one that + is in the list of biological elements */ +Element Element::biologicalElement(const QString &name) +{ + QReadLocker locker(globalLock()); + + // guess an element with this name... + Element elmnt(name); + + // is this a biological element? - if so, return it! + if (elmnt._locked_biological()) + return elmnt; + + // try to guess the atom from just the first two letters... + Element elmnt2(name.left(2)); + + if (elmnt2._locked_biological()) + return elmnt2; + + // try to guess the atom from just the first letter... + Element elmnt3(name.left(1)); + + if (elmnt3._locked_biological()) + return elmnt3; + + // we couldn't find anything - return the original, non-biological guess + return elmnt; +} + +/** Return whether or not this is biological + (in first three periods and not a noble gas, or a halogen) + (this does preclude iron, potassium and calcium, which are + rather biological... :-) */ +bool Element::_locked_biological() const +{ + return biological_elements->contains(eldata->protnum); +} + +/** Return whether or not this is biological + (in first three periods and not a noble gas, or a halogen) + (this does preclude iron, potassium and calcium, which are + rather biological... :-) */ +bool Element::biological() const +{ + QReadLocker locker(globalLock()); + return this->_locked_biological(); +} + +/** Return a list of all of the elements that are considered + * to be biological + */ +QList Element::getBiologicalElements() +{ + QReadLocker locker(globalLock()); + QList prots = biological_elements->values(); + std::sort(prots.begin(), prots.end()); + + QList elements; + + for (int i = 0; i < prots.size(); ++i) + { + elements.append(Element(prots[i])); + } + + return elements; +} + /** Construct a dummy element */ Element::Element() { @@ -364,35 +470,6 @@ ElementData *ElementDB::element(const QString &s) const } } -/** Return a biological element that has been guessed from the passed name. - Note that if no biological element was guessed, then the nearest - non-biological element match is used. A biological element is one that - is in the first couple of rows (proton number < 18) and is not a noble gas. */ -Element Element::biologicalElement(const QString &name) -{ - // guess an element with this name... - Element elmnt(name); - - // is this a biological element? - if so, return it! - if (elmnt.biological()) - return elmnt; - - // try to guess the atom from just the first two letters... - Element elmnt2(name.left(2)); - - if (elmnt2.biological()) - return elmnt2; - - // try to guess the atom from just the first letter... - Element elmnt3(name.left(1)); - - if (elmnt3.biological()) - return elmnt3; - - // we couldn't find anything - return the original, non-biological guess - return elmnt; -} - /** Return whether or not this is a noble gas */ bool Element::nobleGas() const { @@ -405,15 +482,6 @@ bool Element::halogen() const return group() == 17; } -/** Return whether or not this is biological - (in first three periods and not a noble gas, or a halogen) - (this does preclude iron, potassium and calcium, which are - rather biological... :-) */ -bool Element::biological() const -{ - return (period() <= 3 and not nobleGas()) or halogen(); -} - /** Return whether or not this is an alkali metal (group 1 or 2) */ bool Element::alkaliMetal() const { @@ -450,6 +518,36 @@ bool Element::rareEarth() const return lanthanide() or actinide(); } +bool Element::operator==(const QString &other) const +{ + return this->operator==(Element(other)); +} + +bool Element::operator!=(const QString &other) const +{ + return not this->operator==(other); +} + +bool Element::operator>(const QString &other) const +{ + return this->operator>(Element(other)); +} + +bool Element::operator<(const QString &other) const +{ + return this->operator<(Element(other)); +} + +bool Element::operator>=(const QString &other) const +{ + return this->operator>=(Element(other)); +} + +bool Element::operator<=(const QString &other) const +{ + return this->operator<=(Element(other)); +} + /** Sorting operators. Elements are compared based on their proton numbers, with elements with greater numbers being higher. The functions are also very quick. */ diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 89affedcf..e273aa297 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -155,6 +155,10 @@ organisation on `GitHub `__. when reading Mol2 files. This is more robust than using the atom name. Fixes issue #166. +* Made it easier to convert from strings to elements. Added the ability to + customise the list of elements that are considered biological. This + fixes issue #170. + * Please add an item to this changelog when you create your PR `2023.5.1 `__ - January 2024 diff --git a/src/sire/mm/__init__.py b/src/sire/mm/__init__.py index ff2af81a2..2255fd1ac 100644 --- a/src/sire/mm/__init__.py +++ b/src/sire/mm/__init__.py @@ -25,23 +25,6 @@ from ..legacy import MM as _MM -from ..mol import ( - __fix_getitem, - _add_evals, - _add_property_func, - _add_apply_func, - _cursor, - _cursors, - _cursorsm, - _dynamics, - _minimisation, - _selector_to_smiles, - _selector_to_smarts, - _selector_view2d, - _trajectory, - _viewfunc, -) - from .. import use_new_api as _use_new_api _use_new_api() @@ -101,74 +84,108 @@ except AttributeError: Improper.__len__ = Improper.num_atoms -for C in [ - Bond, - SelectorBond, - SelectorMBond, - Angle, - SelectorAngle, - SelectorMAngle, - Dihedral, - SelectorDihedral, - SelectorMDihedral, - Improper, - SelectorImproper, - SelectorMImproper, -]: - __fix_getitem(C) - _add_evals(C) - _add_property_func(C) - _add_apply_func(C) - -Bond.cursor = _cursor -SelectorBond.cursor = _cursors -Angle.cursor = _cursor -SelectorAngle.cursor = _cursors -Dihedral.cursor = _cursor -SelectorDihedral.cursor = _cursors -Improper.cursor = _cursor -SelectorImproper.cursor = _cursors - -SelectorMBond.cursor = _cursorsm -SelectorMAngle.cursor = _cursorsm -SelectorMDihedral.cursor = _cursorsm -SelectorMImproper.cursor = _cursorsm - -SelectorMBond.dynamics = _dynamics -SelectorMAngle.dynamics = _dynamics -SelectorMDihedral.dynamics = _dynamics -SelectorMImproper.dynamics = _dynamics - -SelectorMBond.minimisation = _minimisation -SelectorMAngle.minimisation = _minimisation -SelectorMDihedral.minimisation = _minimisation -SelectorMImproper.minimisation = _minimisation - -SelectorMBond.smiles = _selector_to_smiles -SelectorMAngle.smiles = _selector_to_smiles -SelectorMDihedral.smiles = _selector_to_smiles -SelectorMImproper.smiles = _selector_to_smiles -SelectorMBond.smarts = _selector_to_smarts -SelectorMAngle.smarts = _selector_to_smarts -SelectorMDihedral.smarts = _selector_to_smarts -SelectorMImproper.smarts = _selector_to_smarts - -SelectorMBond.trajectory = _trajectory -SelectorMAngle.trajectory = _trajectory -SelectorMDihedral.trajectory = _trajectory -SelectorMImproper.trajectory = _trajectory - -SelectorBond.view = _viewfunc -SelectorAngle.view = _viewfunc -SelectorDihedral.view = _viewfunc -SelectorImproper.view = _viewfunc - -SelectorMBond.view = _viewfunc -SelectorMAngle.view = _viewfunc -SelectorMDihedral.view = _viewfunc -SelectorMImproper.view = _viewfunc - -SelectorMBond.view2d = _selector_view2d -SelectorMAngle.view2d = _selector_view2d -SelectorMDihedral.view2d = _selector_view2d -SelectorMImproper.view2d = _selector_view2d + +_have_fixed_siremm = False + + +def _fix_siremm(): + global _have_fixed_siremm + if _have_fixed_siremm: + return + + from ..mol import ( + __fix_getitem, + _add_evals, + _add_property_func, + _add_apply_func, + _cursor, + _cursors, + _cursorsm, + _dynamics, + _minimisation, + _selector_to_smiles, + _selector_to_smarts, + _selector_view2d, + _trajectory, + _viewfunc, + ) + + _have_fixed_siremm = True + + for C in [ + Bond, + SelectorBond, + SelectorMBond, + Angle, + SelectorAngle, + SelectorMAngle, + Dihedral, + SelectorDihedral, + SelectorMDihedral, + Improper, + SelectorImproper, + SelectorMImproper, + ]: + __fix_getitem(C) + _add_evals(C) + _add_property_func(C) + _add_apply_func(C) + + Bond.cursor = _cursor + SelectorBond.cursor = _cursors + Angle.cursor = _cursor + SelectorAngle.cursor = _cursors + Dihedral.cursor = _cursor + SelectorDihedral.cursor = _cursors + Improper.cursor = _cursor + SelectorImproper.cursor = _cursors + + SelectorMBond.cursor = _cursorsm + SelectorMAngle.cursor = _cursorsm + SelectorMDihedral.cursor = _cursorsm + SelectorMImproper.cursor = _cursorsm + + SelectorMBond.dynamics = _dynamics + SelectorMAngle.dynamics = _dynamics + SelectorMDihedral.dynamics = _dynamics + SelectorMImproper.dynamics = _dynamics + + SelectorMBond.minimisation = _minimisation + SelectorMAngle.minimisation = _minimisation + SelectorMDihedral.minimisation = _minimisation + SelectorMImproper.minimisation = _minimisation + + SelectorMBond.smiles = _selector_to_smiles + SelectorMAngle.smiles = _selector_to_smiles + SelectorMDihedral.smiles = _selector_to_smiles + SelectorMImproper.smiles = _selector_to_smiles + SelectorMBond.smarts = _selector_to_smarts + SelectorMAngle.smarts = _selector_to_smarts + SelectorMDihedral.smarts = _selector_to_smarts + SelectorMImproper.smarts = _selector_to_smarts + + SelectorMBond.trajectory = _trajectory + SelectorMAngle.trajectory = _trajectory + SelectorMDihedral.trajectory = _trajectory + SelectorMImproper.trajectory = _trajectory + + SelectorBond.view = _viewfunc + SelectorAngle.view = _viewfunc + SelectorDihedral.view = _viewfunc + SelectorImproper.view = _viewfunc + + SelectorMBond.view = _viewfunc + SelectorMAngle.view = _viewfunc + SelectorMDihedral.view = _viewfunc + SelectorMImproper.view = _viewfunc + + SelectorMBond.view2d = _selector_view2d + SelectorMAngle.view2d = _selector_view2d + SelectorMDihedral.view2d = _selector_view2d + SelectorMImproper.view2d = _selector_view2d + + +try: + _fix_siremm() +except ImportError: + pass diff --git a/src/sire/mol/__init__.py b/src/sire/mol/__init__.py index 2511b5045..fba3e2f7c 100644 --- a/src/sire/mol/__init__.py +++ b/src/sire/mol/__init__.py @@ -2590,3 +2590,9 @@ def __molecule_is_perturbable(mol): # Remove some temporary variables del C + +# also initialise sire.mm (it can sometimes be uninitialised if +# sire.mol is loaded first) +from ..mm import _fix_siremm + +_fix_siremm() diff --git a/tests/convert/test_openmm_constraints.py b/tests/convert/test_openmm_constraints.py index 8eecc15ed..ee64d6f5c 100644 --- a/tests/convert/test_openmm_constraints.py +++ b/tests/convert/test_openmm_constraints.py @@ -212,3 +212,69 @@ def test_neo_constraints(neopentane_methane, openmm_platform): # check that there is only one perturbable constraint p = mols_fwds[0].perturbation().to_openmm(constraint="h-bonds-not-heavy-perturbed") assert (len(p.changed_constraints(to_pandas=False))) == 1 + + +@pytest.mark.skipif( + "openmm" not in sr.convert.supported_formats(), + reason="openmm support is not available", +) +def test_dynamic_constraints(merged_ethane_methanol, openmm_platform): + mols = sr.morph.link_to_reference(merged_ethane_methanol) + + d = mols[0].dynamics( + constraint="h-bonds", + dynamic_constraints=True, + platform=openmm_platform, + lambda_value=0.0, + ) + + constraints = d.get_constraints() + + nrg = d.current_potential_energy().value() + + assert nrg == pytest.approx(1.65783, abs=0.001) + + # there are 6 bonds involving hydrogen - they should all be the same + assert len(constraints) == 6 + + for constraint in constraints: + assert constraint[1].value() == pytest.approx(1.0969) + + d = mols[0].dynamics( + constraint="h-bonds", + dynamic_constraints=True, + platform=openmm_platform, + lambda_value=1.0, + ) + + constraints = d.get_constraints() + + # there are 6 bonds involving hydrogen - they should all be the same + assert len(constraints) == 6 + + # one of the constraints should be 0.973 A + cons = {} + + for constraint in constraints: + dist = constraint[1].value() + + if dist not in cons: + cons[dist] = 0 + + cons[dist] += 1 + + assert len(cons) == 2 + + for key, value in cons.items(): + if value == 1: + assert key == pytest.approx(0.973) + elif value == 5: + assert key == pytest.approx(1.0969) + else: + assert False + + # make sure that the bond parameters are correct - can only do this + # via potential energy + nrg = d.current_potential_energy() + + assert nrg.value() == pytest.approx(13.8969, abs=0.001) diff --git a/tests/mol/test_element.py b/tests/mol/test_element.py new file mode 100644 index 000000000..42f245cb5 --- /dev/null +++ b/tests/mol/test_element.py @@ -0,0 +1,51 @@ +import pytest +import sire as sr + + +def test_element(): + # Create an element + el = sr.mol.Element("C") + assert el.symbol() == "C" + assert el.num_protons() == 6 + assert el.mass().to("g mol-1") == pytest.approx(12.01, abs=0.01) + + # Create an element from atomic number + el = sr.mol.Element(6) + assert el.symbol() == "C" + + # Create an element from name + el = sr.mol.Element("Carbon") + assert el.symbol() == "C" + + # Create an element from mass + el = sr.mol.Element.element_with_mass(sr.u("12 g mol-1")) + assert el.symbol() == "C" + + # Create a biological Iron + el = sr.mol.Element.biological_element("Fe") + + assert el.symbol() == "Fe" + assert el.num_protons() == 26 + assert el.mass().to("g mol-1") == pytest.approx(55.845) + assert el.name() == "Iron" + + # remove this as a biological element + sr.mol.Element.set_element_is_not_biological("Fe") + + el = sr.mol.Element.biological_element("Fe") + + assert el.symbol() != "Fe" + assert el.num_protons() != 26 + + # Add this back + sr.mol.Element.set_element_is_biological("Fe") + + el = sr.mol.Element.biological_element("Fe") + + assert el.symbol() == "Fe" + assert el.num_protons() == 26 + + # get the list of biological elements + elements = sr.mol.Element.get_biological_elements() + + assert sr.mol.Element("Fe") in elements diff --git a/wrapper/Convert/SireOpenMM/lambdalever.cpp b/wrapper/Convert/SireOpenMM/lambdalever.cpp index 204fa3b1f..59ccd848a 100644 --- a/wrapper/Convert/SireOpenMM/lambdalever.cpp +++ b/wrapper/Convert/SireOpenMM/lambdalever.cpp @@ -71,12 +71,18 @@ MolLambdaCache &MolLambdaCache::operator=(const MolLambdaCache &other) const QVector &MolLambdaCache::morph(const LambdaSchedule &schedule, const QString &force, const QString &key, + const QString &subkey, const QVector &initial, const QVector &final) const { auto nonconst_this = const_cast(this); - QString force_key = force + "::" + key; + QString cache_key = key; + + if (not subkey.isEmpty()) + cache_key += ("::" + subkey); + + QString force_key = force + "::" + cache_key; QReadLocker lkr(&(nonconst_this->lock)); @@ -108,16 +114,16 @@ const QVector &MolLambdaCache::morph(const LambdaSchedule &schedule, { // all forces use the same equation for this lever // Look for the common equation - it = cache.constFind(key); + it = cache.constFind(cache_key); if (it == cache.constEnd()) { // we're the first - create the values and cache them - nonconst_this->cache.insert(key, + nonconst_this->cache.insert(cache_key, schedule.morph("*", key, initial, final, lam_val)); - it = cache.constFind(key); + it = cache.constFind(cache_key); } // save this equation for this force for this lever @@ -127,6 +133,15 @@ const QVector &MolLambdaCache::morph(const LambdaSchedule &schedule, return cache.constFind(force_key).value(); } +const QVector &MolLambdaCache::morph(const LambdaSchedule &schedule, + const QString &force, + const QString &key, + const QVector &initial, + const QVector &final) const +{ + return this->morph(schedule, force, key, QString(), initial, final); +} + ////// ////// Implementation of LeverCache ////// @@ -783,7 +798,7 @@ double LambdaLever::setLambda(OpenMM::Context &context, { const auto morphed_constraint_length = cache.morph( schedule, - "bond", "bond_length", + "bond", "bond_length", "constraint", r0_0, r0_1); for (int j = 0; j < idxs.count(); ++j) diff --git a/wrapper/Convert/SireOpenMM/lambdalever.h b/wrapper/Convert/SireOpenMM/lambdalever.h index 8521972d1..13b8e3d0c 100644 --- a/wrapper/Convert/SireOpenMM/lambdalever.h +++ b/wrapper/Convert/SireOpenMM/lambdalever.h @@ -58,6 +58,12 @@ namespace SireOpenMM const QVector &initial, const QVector &final) const; + const QVector &morph(const SireCAS::LambdaSchedule &schedule, + const QString &force, const QString &key, + const QString &subkey, + const QVector &initial, + const QVector &final) const; + private: QHash> cache; QReadWriteLock lock; diff --git a/wrapper/Mol/Element.pypp.cpp b/wrapper/Mol/Element.pypp.cpp index e8ab4d2b5..20e8fc4c7 100644 --- a/wrapper/Mol/Element.pypp.cpp +++ b/wrapper/Mol/Element.pypp.cpp @@ -139,6 +139,18 @@ void register_Element_class(){ , bp::release_gil_policy() , "Return an element which has the closest mass to mass (in atomic\nmass units, g mol-1)" ); + } + { //::SireMol::Element::getBiologicalElements + + typedef ::QList< SireMol::Element > ( *getBiologicalElements_function_type )( ); + getBiologicalElements_function_type getBiologicalElements_function_value( &::SireMol::Element::getBiologicalElements ); + + Element_exposer.def( + "getBiologicalElements" + , getBiologicalElements_function_value + , bp::release_gil_policy() + , "" ); + } { //::SireMol::Element::green @@ -249,8 +261,11 @@ void register_Element_class(){ } Element_exposer.def( bp::self != bp::self ); + Element_exposer.def( bp::self != bp::other< QString >() ); Element_exposer.def( bp::self < bp::self ); + Element_exposer.def( bp::self < bp::other< QString >() ); Element_exposer.def( bp::self <= bp::self ); + Element_exposer.def( bp::self <= bp::other< QString >() ); { //::SireMol::Element::operator= typedef ::SireMol::Element const & ( ::SireMol::Element::*assign_function_type)( ::SireMol::Element const & ) ; @@ -265,8 +280,11 @@ void register_Element_class(){ } Element_exposer.def( bp::self == bp::self ); + Element_exposer.def( bp::self == bp::other< QString >() ); Element_exposer.def( bp::self > bp::self ); + Element_exposer.def( bp::self > bp::other< QString >() ); Element_exposer.def( bp::self >= bp::self ); + Element_exposer.def( bp::self >= bp::other< QString >() ); { //::SireMol::Element::period typedef int ( ::SireMol::Element::*period_function_type)( ) const; @@ -302,6 +320,44 @@ void register_Element_class(){ , bp::release_gil_policy() , "Return the red colour components (0.0->1.0) for\nthe colour of this element" ); + } + { //::SireMol::Element::resetBiologicalElements + + typedef void ( *resetBiologicalElements_function_type )( ); + resetBiologicalElements_function_type resetBiologicalElements_function_value( &::SireMol::Element::resetBiologicalElements ); + + Element_exposer.def( + "resetBiologicalElements" + , resetBiologicalElements_function_value + , bp::release_gil_policy() + , "" ); + + } + { //::SireMol::Element::setElementIsBiological + + typedef void ( *setElementIsBiological_function_type )( ::SireMol::Element const & ); + setElementIsBiological_function_type setElementIsBiological_function_value( &::SireMol::Element::setElementIsBiological ); + + Element_exposer.def( + "setElementIsBiological" + , setElementIsBiological_function_value + , ( bp::arg("element") ) + , bp::release_gil_policy() + , "" ); + + } + { //::SireMol::Element::setElementIsNotBiological + + typedef void ( *setElementIsNotBiological_function_type )( ::SireMol::Element const & ); + setElementIsNotBiological_function_type setElementIsNotBiological_function_value( &::SireMol::Element::setElementIsNotBiological ); + + Element_exposer.def( + "setElementIsNotBiological" + , setElementIsNotBiological_function_value + , ( bp::arg("element") ) + , bp::release_gil_policy() + , "" ); + } { //::SireMol::Element::symbol @@ -377,6 +433,10 @@ void register_Element_class(){ } Element_exposer.staticmethod( "biologicalElement" ); Element_exposer.staticmethod( "elementWithMass" ); + Element_exposer.staticmethod( "getBiologicalElements" ); + Element_exposer.staticmethod( "resetBiologicalElements" ); + Element_exposer.staticmethod( "setElementIsBiological" ); + Element_exposer.staticmethod( "setElementIsNotBiological" ); Element_exposer.staticmethod( "typeName" ); Element_exposer.def( "__copy__", &__copy__); Element_exposer.def( "__deepcopy__", &__copy__); diff --git a/wrapper/Mol/SireMol_containers.cpp b/wrapper/Mol/SireMol_containers.cpp index 07634129f..8b72cee54 100644 --- a/wrapper/Mol/SireMol_containers.cpp +++ b/wrapper/Mol/SireMol_containers.cpp @@ -46,6 +46,7 @@ #include "SireMol/cutgroup.h" #include "SireMol/residue.h" #include "SireMol/chain.h" +#include "SireMol/element.h" #include "SireMol/segment.h" #include "SireMol/molecule.h" #include "SireMol/atomselection.h" @@ -85,121 +86,122 @@ using boost::python::register_tuple; void register_SireMol_containers() { - register_viewsofmol_list(); + register_viewsofmol_list(); - register_list>(); - register_list>>(); - register_list>(); + register_list>(); + register_list>>(); + register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); + register_list>(); - register_list>(); + register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); - register_list>>(); - register_list>>(); + register_list>>(); + register_list>>(); - register_list>>(); + register_list>>(); - register_list>>(); + register_list>>(); - register_list>(); - register_list>>(); + register_list>(); + register_list>>(); - register_list>(); + register_list>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); - register_list>>(); + register_list>>(); - register_list>(); - register_list>(); + register_list>(); + register_list>(); - register_list>(); + register_list>(); - register_tuple>(); - register_tuple>(); - register_tuple>(); + register_tuple>(); + register_tuple>(); + register_tuple>(); - register_tuple>(); - register_tuple>(); + register_tuple>(); + register_tuple>(); - register_tuple>(); + register_tuple>(); - register_tuple>(); + register_tuple>(); - register_tuple>(); + register_tuple>(); - register_tuple>(); + register_tuple>(); - register_tuple>(); - register_tuple>(); - register_tuple, SireBase::PropertyMap>>(); - register_tuple, SireBase::PropertyMap>>(); + register_tuple>(); + register_tuple>(); + register_tuple, SireBase::PropertyMap>>(); + register_tuple, SireBase::PropertyMap>>(); - register_PackedArray>(); - register_PackedArray>(); + register_PackedArray>(); + register_PackedArray>(); - register_dict>(); + register_dict>(); - register_dict>(); - register_dict>(); + register_dict>(); + register_dict>(); - register_dict>>(); + register_dict>>(); - register_dict>>(); - register_dict>>(); - register_dict>>(); - register_dict>>(); - register_dict>>(); - register_dict>(); - register_dict>(); - register_dict>(); + register_dict>>(); + register_dict>>(); + register_dict>>(); + register_dict>>(); + register_dict>>(); + register_dict>(); + register_dict>(); + register_dict>(); - register_set>(); - register_set>(); + register_set>(); + register_set>(); - register_set>(); - register_set>(); + register_set>(); + register_set>(); } diff --git a/wrapper/Mol/_Mol.main.cpp b/wrapper/Mol/_Mol.main.cpp index e2cb30d3c..346070212 100644 --- a/wrapper/Mol/_Mol.main.cpp +++ b/wrapper/Mol/_Mol.main.cpp @@ -585,6 +585,8 @@ namespace bp = boost::python; #include "SireMol/selectorm.hpp" +#include "SireMol/element.h" + BOOST_PYTHON_MODULE(_Mol){ register_SireMol_objects(); @@ -1144,6 +1146,8 @@ BOOST_PYTHON_MODULE(_Mol){ register_SireMol_properties(); + bp::implicitly_convertible< QString, SireMol::Element >(); + bp::implicitly_convertible< SireMol::AtomID, SireMol::AtomIdentifier >(); bp::implicitly_convertible< SireMol::CGID, SireMol::CGIdentifier >(); diff --git a/wrapper/Mol/__init__.py b/wrapper/Mol/__init__.py index dcfaee737..c93f6f5cf 100644 --- a/wrapper/Mol/__init__.py +++ b/wrapper/Mol/__init__.py @@ -16,6 +16,12 @@ _install_search_parser() +# initialise the list of biological elements +try: + _Mol.Element.resetBiologicalElements() +except AttributeError: + _Mol.Element.reset_biological_elements() + def __get_property__(molview, key): if hasattr(molview, "property_type"):