Skip to content

Commit 762f244

Browse files
authored
Merge pull request #211 from OpenBioSim/fix_ion_merge
Fix AtomMapping::alignTo when mapping an ion to a molecule
2 parents 8a74d0c + f23acd3 commit 762f244

File tree

3 files changed

+76
-14
lines changed

3 files changed

+76
-14
lines changed

corelib/src/libs/SireMol/atommapping.cpp

+55-14
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "SireMaths/align.h"
3232

3333
#include "SireMol/core.h"
34+
#include "SireMol/moleditor.h"
3435

3536
#include "SireStream/datastream.h"
3637
#include "SireStream/shareddatastream.h"
@@ -723,20 +724,40 @@ AtomMapping AtomMapping::alignTo0() const
723724
QVector<Vector> coords0 = this->atms0.property<Vector>(map0["coordinates"]).toVector();
724725
QVector<Vector> coords1 = this->atms1.property<Vector>(map1["coordinates"]).toVector();
725726

726-
// calculate the transform to do a RMSD aligment of the two sets of coordinates
727-
auto transform = SireMaths::getAlignment(coords0, coords1, true);
728-
729-
auto mols1 = this->orig_atms1.molecules();
730-
731727
AtomMapping ret(*this);
732728

733-
for (int i = 0; i < mols1.count(); ++i)
729+
if ((this->count() == 1) and ((coords0.count() == 1) or (coords1.count() == 1)))
734730
{
735-
auto mol = mols1[i].move().transform(transform, map1).commit();
731+
// if we've only mapped a single atom and one molecule is a monatomic ion,
732+
// then simply replace the coordinates of the mapped atom.
733+
734+
auto atom0 = this->atms0[0];
735+
auto atom1 = this->atms1[0];
736+
737+
auto mol = this->orig_atms1.molecules()[0];
738+
739+
mol = mol.edit().atom(atom1.index())
740+
.setProperty(map1["coordinates"].source(), coords0[0])
741+
.molecule().commit();
736742

737743
ret.atms1.update(mol);
738744
ret.orig_atms1.update(mol);
739745
}
746+
else
747+
{
748+
// calculate the transform to do a RMSD aligment of the two sets of coordinates
749+
auto transform = SireMaths::getAlignment(coords0, coords1, true);
750+
751+
auto mols1 = this->orig_atms1.molecules();
752+
753+
for (int i = 0; i < mols1.count(); ++i)
754+
{
755+
auto mol = mols1[i].move().transform(transform, map1).commit();
756+
757+
ret.atms1.update(mol);
758+
ret.orig_atms1.update(mol);
759+
}
760+
}
740761

741762
return ret;
742763
}
@@ -754,20 +775,40 @@ AtomMapping AtomMapping::alignTo1() const
754775
QVector<Vector> coords0 = this->atms0.property<Vector>(map0["coordinates"]).toVector();
755776
QVector<Vector> coords1 = this->atms1.property<Vector>(map1["coordinates"]).toVector();
756777

757-
// calculate the transform to do a RMSD aligment of the two sets of coordinates
758-
auto transform = SireMaths::getAlignment(coords1, coords0, true);
759-
760-
auto mols0 = this->orig_atms0.molecules();
761-
762778
AtomMapping ret(*this);
763779

764-
for (int i = 0; i < mols0.count(); ++i)
780+
if ((this->count() == 1) and ((coords0.count() == 1) or (coords1.count() == 1)))
765781
{
766-
auto mol = mols0[i].move().transform(transform, map0).commit();
782+
// if we've only mapped a single atom and one molecule is a monatomic ion,
783+
// then simply replace the coordinates of the mapped atom.
784+
785+
auto atom0 = this->atms0[0];
786+
auto atom1 = this->atms1[0];
787+
788+
auto mol = this->orig_atms0.molecules()[0];
789+
790+
mol = mol.edit().atom(atom0.index())
791+
.setProperty(map0["coordinates"].source(), coords0[0])
792+
.molecule().commit();
767793

768794
ret.atms0.update(mol);
769795
ret.orig_atms0.update(mol);
770796
}
797+
else
798+
{
799+
// calculate the transform to do a RMSD aligment of the two sets of coordinates
800+
auto transform = SireMaths::getAlignment(coords1, coords0, true);
801+
802+
auto mols0 = this->orig_atms0.molecules();
803+
804+
for (int i = 0; i < mols0.count(); ++i)
805+
{
806+
auto mol = mols0[i].move().transform(transform, map0).commit();
807+
808+
ret.atms0.update(mol);
809+
ret.orig_atms0.update(mol);
810+
}
811+
}
771812

772813
return ret;
773814
}

doc/source/changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ organisation on `GitHub <https://github.com/openbiosim/sire>`__.
1818
* Please add an item to this changelog when you create your PR
1919
* Print residue indices of perturbed water molecules to SOMD1 log.
2020
* Add support for creating Na+ and Cl- ions.
21+
* Fix ``sire.morph.merge`` function when one molecule is a monatomic ion.
2122

2223
`2024.2.0 <https://github.com/openbiosim/sire/compare/2024.1.0...2024.2.0>`__ - June 2024
2324
-----------------------------------------------------------------------------------------

tests/morph/test_merge.py

+20
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,23 @@ def test_merge_neopentane_methane(neopentane_methane, openmm_platform):
202202
# These energies aren't correct - extra ghost atom internals?
203203
assert nrg_neo.value() == pytest.approx(nrg_merged_0.value(), abs=1e-3)
204204
# assert nrg_met.value() == pytest.approx(nrg_merged_1.value(), abs=1e-3)
205+
206+
207+
@pytest.mark.skipif(sys.platform == "win32", reason="Not supported on Windows")
208+
def test_ion_merge(ala_mols):
209+
water = ala_mols[-1]
210+
ion = sr.legacy.IO.createSodiumIon(water.atoms()[-1].coordinates(), "tip3p")
211+
212+
merged = sr.morph.merge(water, ion)
213+
214+
coords0 = merged.property("coordinates0").to_vector()[0]
215+
coords1 = merged.property("coordinates1").to_vector()[0]
216+
217+
assert coords0 == coords1
218+
219+
merged = sr.morph.merge(ion, water)
220+
221+
coords0 = merged.property("coordinates0").to_vector()[0]
222+
coords1 = merged.property("coordinates1").to_vector()[0]
223+
224+
assert coords0 == coords1

0 commit comments

Comments
 (0)