diff --git a/package/AUTHORS b/package/AUTHORS index 0f4dd493ebb..d834aa66f01 100644 --- a/package/AUTHORS +++ b/package/AUTHORS @@ -265,10 +265,7 @@ Chronological list of authors - Raúl Lois-Cuns - Pranay Pelapkar - Shreejan Dolai - - Tanisha Dubey - - Brady Johnston -2026 - - Mohammad Ayaan + - Kushagar garg External code ------------- diff --git a/package/CHANGELOG b/package/CHANGELOG index 2f023d1337a..289409b4de6 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -15,7 +15,7 @@ The rules for this file: ------------------------------------------------------------------------------- ??/??/?? IAlibay, orbeckst, marinegor, tylerjereddy, ljwoods2, marinegor, - spyke7, talagayev, tanii1125, BradyAJohnston + spyke7, talagayev, Dreamstick9 * 2.11.0 @@ -35,6 +35,7 @@ Fixes to version 5.1.0 (Issue #5145, PR #5146) * Fixes incorrect assignment of secondary structure to proline residues in DSSP by porting upstream PyDSSP 0.9.1 fix (Issue #4913) + * MOL2Parser now reads unit cell dimensions from @CRYSIN records (Issue #3341) Enhancements * Enables parallelization for analysis.diffusionmap.DistanceMatrix diff --git a/package/MDAnalysis/coordinates/MOL2.py b/package/MDAnalysis/coordinates/MOL2.py index e3f4c016158..6ec17280138 100644 --- a/package/MDAnalysis/coordinates/MOL2.py +++ b/package/MDAnalysis/coordinates/MOL2.py @@ -69,8 +69,11 @@ * The MDAnalysis :class:`MOL2Reader` and :class:`MOL2Writer` only handle the MOLECULE, SUBSTRUCTURE, ATOM, and BOND record types. Other records are not currently read or preserved on writing. -* As the CRYSIN record type is not parsed / written, MOL2 systems always have - dimensions set to ``None`` and dimensionless MOL2 files are written. +* The MDAnalysis :class:`MOL2Reader` now reads unit cell dimensions from the + @CRYSIN record. The space group and setting information (the 7th + and 8th fields) are currently ignored. The unit cell is interpreted in the + common crystallographic convention with box vector **a** parallel to the x-axis, + **b** in the xy-plane, and **c** having a positive z-component. MOL2 format notes @@ -246,6 +249,10 @@ def _read_frame(self, frame): self.ts.data[sect] = sections[sect] except KeyError: pass + if "crysin" in sections: + line = sections["crysin"][0].strip() + dims = [float(x) for x in line.split()[:6]] + self.ts.dimensions = np.array(dims, dtype=np.float32) self.ts.positions = np.array(coords, dtype=np.float32) diff --git a/testsuite/MDAnalysisTests/coordinates/test_mol2.py b/testsuite/MDAnalysisTests/coordinates/test_mol2.py index 494b2ace2af..fb1ed961f5b 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_mol2.py +++ b/testsuite/MDAnalysisTests/coordinates/test_mol2.py @@ -21,6 +21,7 @@ # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # import pytest +import numpy as np import os from numpy.testing import ( @@ -39,6 +40,7 @@ mol2_comments_header, mol2_ligand, mol2_sodium_ion, + mol2_crysin, ) from MDAnalysis import Universe import MDAnalysis as mda @@ -232,3 +234,11 @@ def test_mol2_universe_write(tmpdir): assert_almost_equal(u.atoms.positions, u2.atoms.positions) # MDA does not current implement @CRYSIN reading assert u2.dimensions is None + + +def test_mol2_crysin_dimensions(): + # test that crysin records are read as dimensions + u = mda.Universe(mol2_crysin) + + expected = np.array([40.0, 50.0, 60.0, 90.0, 90.0, 90.0], dtype=np.float32) + assert_array_almost_equal(u.dimensions, expected, decimal=3) diff --git a/testsuite/MDAnalysisTests/data/mol2/test_crysin.mol2 b/testsuite/MDAnalysisTests/data/mol2/test_crysin.mol2 new file mode 100644 index 00000000000..51959f75a2c --- /dev/null +++ b/testsuite/MDAnalysisTests/data/mol2/test_crysin.mol2 @@ -0,0 +1,10 @@ +@MOLECULE +test_structure + 1 0 0 0 0 +SMALL +USER_CHARGES +@ATOM + 1 C 0.0000 0.0000 0.0000 C.3 1 ALA 0.0000 +@CRYSIN + 40.0000 50.0000 60.0000 90.0000 90.0000 90.0000 1 1 +@END \ No newline at end of file diff --git a/testsuite/MDAnalysisTests/datafiles.py b/testsuite/MDAnalysisTests/datafiles.py index 01336e8aa9a..35f6bf38480 100644 --- a/testsuite/MDAnalysisTests/datafiles.py +++ b/testsuite/MDAnalysisTests/datafiles.py @@ -241,6 +241,7 @@ "mol2_comments_header", "mol2_ligand", "mol2_sodium_ion", + "mol2_crysin", "capping_input", "capping_output", "capping_ace", @@ -735,6 +736,7 @@ mol2_zinc = (_data_ref / "mol2/zinc_856218.mol2").as_posix() # MOL2 file without bonds mol2_sodium_ion = (_data_ref / "mol2/sodium_ion.mol2").as_posix() +mol2_crysin = (_data_ref / "mol2/test_crysin.mol2").as_posix() capping_input = (_data_ref / "capping/aaqaa.gro").as_posix() capping_output = (_data_ref / "capping/maestro_aaqaa_capped.pdb").as_posix()