diff --git a/.github/actions/setup-deps/action.yaml b/.github/actions/setup-deps/action.yaml index 2473c32df34..53b8374daef 100644 --- a/.github/actions/setup-deps/action.yaml +++ b/.github/actions/setup-deps/action.yaml @@ -28,7 +28,7 @@ inputs: griddataformats: default: 'griddataformats' gsd: - default: 'gsd' + default: 'gsd>3.0.0' hypothesis: default: 'hypothesis' matplotlib: @@ -107,7 +107,6 @@ runs: ${{ inputs.cython }} ${{ inputs.fasteners }} ${{ inputs.griddataformats }} - ${{ inputs.gsd }} ${{ inputs.hypothesis }} ${{ inputs.matplotlib }} ${{ inputs.mmtf-python }} @@ -123,6 +122,7 @@ runs: ${{ inputs.chemfiles-python }} ${{ inputs.clustalw }} ${{ inputs.distopia }} + ${{ inputs.gsd }} ${{ inputs.h5py }} ${{ inputs.hole2 }} ${{ inputs.joblib }} diff --git a/.github/workflows/darkerbot.yaml b/.github/workflows/darkerbot.yaml index 3a564a49e89..3f7d7169a0e 100644 --- a/.github/workflows/darkerbot.yaml +++ b/.github/workflows/darkerbot.yaml @@ -19,6 +19,7 @@ jobs: darker_bot: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 6b4d0306f00..4085ef96c38 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -32,6 +32,7 @@ jobs: if: "github.repository == 'MDAnalysis/mdanalysis'" name: Build wheels runs-on: ${{ matrix.buildplat[0] }} + timeout-minutes: 15 strategy: fail-fast: false matrix: @@ -69,6 +70,7 @@ jobs: if: "github.repository == 'MDAnalysis/mdanalysis'" name: build package source distribution runs-on: ubuntu-latest + timeout-minutes: 10 defaults: run: working-directory: ./package @@ -93,6 +95,7 @@ jobs: if: "github.repository == 'MDAnalysis/mdanalysis'" name: build test source distribution runs-on: ubuntu-latest + timeout-minutes: 10 defaults: run: working-directory: ./testsuite @@ -187,6 +190,7 @@ jobs: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/package')) name: testpypi check runs-on: ${{ matrix.os }} + timeout-minutes: 60 needs: upload_testpypi strategy: fail-fast: false diff --git a/.github/workflows/gh-ci-cron.yaml b/.github/workflows/gh-ci-cron.yaml index 8eea28f988f..8bbc6ac6505 100644 --- a/.github/workflows/gh-ci-cron.yaml +++ b/.github/workflows/gh-ci-cron.yaml @@ -23,6 +23,7 @@ jobs: numpy_and_scipy_dev: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 60 steps: - uses: actions/checkout@v3 @@ -51,7 +52,7 @@ jobs: # overwrite installs by picking up nightly wheels - name: nightly_wheels run: | - pip install --pre -U -i https://pypi.anaconda.org/scipy-wheels-nightly/simple scipy numpy h5py matplotlib + pip install --pre -U -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple scipy numpy networkx matplotlib - name: list_deps run: | @@ -74,6 +75,7 @@ jobs: native_march: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 60 steps: - uses: actions/checkout@v3 @@ -117,6 +119,7 @@ jobs: old_ubuntu_macos: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -158,9 +161,10 @@ jobs: # Issue 1727 - pip-only: + pip-only-develop: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -192,3 +196,71 @@ jobs: - name: run_tests run: | pytest -n $numprocs testsuite/MDAnalysisTests --disable-pytest-warnings --durations=50 + + # Issue 4208 + conda-latest-release: + # A set of runner to check that the latest conda release works as expected + if: "github.repository == 'MDAnalysis/mdanalysis'" + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + python-version: ["3.9", "3.10", "3.11"] + steps: + - uses: actions/checkout@v3 + + - name: setup_micromamba + uses: mamba-org/setup-micromamba@v1 + with: + environment-name: mda + create-args: >- + python=${{ matrix.python-version }} + pip + # using jaime's shim to avoid pulling down the cudatoolkit + condarc: | + channels: + - jaimergp/label/unsupported-cudatoolkit-shim + - conda-forge + - bioconda + + - name: install_deps + uses: ./.github/actions/setup-deps + with: + micromamba: true + full-deps: true + gsd: "gsd<3.0" + + - name: install_mdanalysis + run: | + micromamba install mdanalysis mdanalysistests + + - name: run_tests + run: | + pytest -n auto --pyargs MDAnalysisTests + + pypi-latest-release: + # A set of runner to check that the latest conda release works as expected + if: "github.repository == 'MDAnalysis/mdanalysis'" + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ["3.9", "3.10", "3.11"] + steps: + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: install_mdanalysis + shell: bash + run: | + pip install mdanalysis mdanalysistests pytest-xdist "gsd<3.0" + + - name: run_tests + shell: bash + run: | + pytest -n auto --pyargs MDAnalysisTests diff --git a/.github/workflows/gh-ci.yaml b/.github/workflows/gh-ci.yaml index f3bf821adc7..ef29d222052 100644 --- a/.github/workflows/gh-ci.yaml +++ b/.github/workflows/gh-ci.yaml @@ -22,6 +22,7 @@ jobs: main_tests: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -40,7 +41,7 @@ jobs: python-version: 3.9 full-deps: false codecov: true - numpy: numpy=1.21.0 + numpy: numpy=1.22.3 - name: asv_check os: ubuntu-latest python-version: 3.9 @@ -113,6 +114,7 @@ jobs: build_docs: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 15 env: CYTHON_TRACE_NOGIL: 1 MPLBACKEND: agg @@ -135,7 +137,7 @@ jobs: with: micromamba: true full-deps: true - extra-pip-deps: "sphinx sphinx-sitemap sphinx_rtd_theme msmb_theme==1.2.0 sphinxcontrib-bibtex pybtex pybtex-docutils" + extra-pip-deps: "docutils<0.18 sphinx<7.0 sphinx-sitemap sphinx_rtd_theme msmb_theme==1.2.0 sphinxcontrib-bibtex pybtex pybtex-docutils" - name: build_srcs uses: ./.github/actions/build-src @@ -207,6 +209,7 @@ jobs: sdist_check_and_build: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/greetings.yaml b/.github/workflows/greetings.yaml index 7670b0ce1d6..aa7a6ff9b6f 100644 --- a/.github/workflows/greetings.yaml +++ b/.github/workflows/greetings.yaml @@ -10,6 +10,7 @@ jobs: greeting: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 10 permissions: pull-requests: write steps: diff --git a/.github/workflows/labels.yaml b/.github/workflows/labels.yaml index 338a735438b..2cac7d8e087 100644 --- a/.github/workflows/labels.yaml +++ b/.github/workflows/labels.yaml @@ -8,6 +8,7 @@ on: jobs: triage-on-file-paths: runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/labeler@v3 with: diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml index dc32d56dadc..fc97ec7ad44 100644 --- a/.github/workflows/linters.yaml +++ b/.github/workflows/linters.yaml @@ -19,6 +19,7 @@ jobs: darker_lint: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 10 permissions: pull-requests: write defaults: @@ -99,6 +100,7 @@ jobs: pylint_check: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v3 @@ -120,6 +122,7 @@ jobs: mypy : if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v3 @@ -138,7 +141,7 @@ jobs: with: micromamba: true full-deps: true - numpy: numpy=1.21.0 + numpy: numpy=1.22.3 - name: install run: | diff --git a/.github/workflows/rtd.yaml b/.github/workflows/rtd.yaml index 64f73f873a8..e48d8f08b22 100644 --- a/.github/workflows/rtd.yaml +++ b/.github/workflows/rtd.yaml @@ -10,6 +10,7 @@ jobs: rtdpreview: if: "github.repository == 'MDAnalysis/mdanalysis'" runs-on: ubuntu-latest + timeout-minutes: 5 permissions: pull-requests: write steps: diff --git a/README.rst b/README.rst index 381fee95c35..d7a8a15ef4e 100644 --- a/README.rst +++ b/README.rst @@ -25,7 +25,7 @@ This project is bound by a `Code of Conduct`_. |powered_by_MDA| -If you use MDAnalysis_ in your project consider lettting your users and the world know about it by displaying the MDAnalysis_ badge! `Embedding code`_ is available for different markups. +If you use MDAnalysis_ in your project consider letting your users and the world know about it by displaying the MDAnalysis_ badge! `Embedding code`_ is available for different markups. Example analysis script ======================= diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 29673c14bb4..2e6e0802eed 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,12 +21,6 @@ jobs: MPLBACKEND: agg strategy: matrix: - Win-Python39-32bit-full: - PYTHON_VERSION: '3.9' - PYTHON_ARCH: 'x86' - BUILD_TYPE: 'normal' - NUMPY_MIN: '1.21.0' - imageName: 'windows-2019' Win-Python39-64bit-full: PYTHON_VERSION: '3.9' PYTHON_ARCH: 'x64' @@ -47,7 +41,7 @@ jobs: PYTHON_VERSION: '3.9' PYTHON_ARCH: 'x64' BUILD_TYPE: 'wheel' - NUMPY_MIN: '1.21.0' + NUMPY_MIN: '1.22.3' imageName: 'windows-2019' Linux-Python311-64bit-full-wheel: PYTHON_VERSION: '3.11' @@ -59,7 +53,7 @@ jobs: PYTHON_VERSION: '3.9' PYTHON_ARCH: 'x64' BUILD_TYPE: 'wheel' - NUMPY_MIN: '1.21.0' + NUMPY_MIN: '1.22.3' imageName: 'ubuntu-latest' pool: vmImage: $(imageName) @@ -82,9 +76,10 @@ jobs: - script: python -m pip install --upgrade pip setuptools wheel displayName: 'Install tools' - script: >- - python -m pip install --only-binary=scipy + python -m pip install --only-binary=scipy,h5py cython hypothesis + h5py>=2.10 matplotlib numpy packaging @@ -96,27 +91,20 @@ jobs: threadpoolctl fasteners displayName: 'Install dependencies' - # H5PY wheels are problematic on 32bit py3.9, so we don't install - # it in that specific case. Note: prefer binary because building - # h5py is difficult on azure. - - script: >- - pip install --prefer-binary h5py>=2.10 - displayName: 'Install non 32bit dependencies' - condition: and(succeeded(), ne(variables['PYTHON_ARCH'], 'x86')) # for wheel install testing, we pin to an # older NumPy, the oldest version we support and that # supports the Python version in use # to check the ABI compatibility of our wheels - script: >- python -m pip install numpy==$(NUMPY_MIN) - displayName: 'pin to older NumPy (wheel test and 32bit)' + displayName: 'pin to older NumPy (wheel test)' condition: and(succeeded(), ne(variables['NUMPY_MIN'], '')) - script: >- python -m pip install biopython "chemfiles>=0.10,<0.10.4" duecredit - gsd + "gsd>3.0.0" joblib GridDataFormats mmtf-python diff --git a/maintainer/conda/environment.yml b/maintainer/conda/environment.yml index 4e03cc7a609..f01499f4cfe 100644 --- a/maintainer/conda/environment.yml +++ b/maintainer/conda/environment.yml @@ -6,6 +6,7 @@ dependencies: - chemfiles>=0.10 - codecov - cython + - docutils <0.18 - fasteners - griddataformats - gsd @@ -16,14 +17,14 @@ dependencies: - mmtf-python - mock - networkx - - numpy>=1.21 + - numpy>=1.22.3 - pytest - python==3.9 - pytng>=0.2.3 - scikit-learn - scipy - pip - - sphinx + - sphinx <7.0 - tidynamics>=1.0.0 - tqdm>=4.43.0 - sphinxcontrib-bibtex diff --git a/package/AUTHORS b/package/AUTHORS index 0279ba7dde5..033461c17a6 100644 --- a/package/AUTHORS +++ b/package/AUTHORS @@ -217,6 +217,8 @@ Chronological list of authors - Egor Marin - Shaivi Malik - Daniel J. Evans + - Mohit Kumar + - Shubham Kumar External code ------------- diff --git a/package/CHANGELOG b/package/CHANGELOG index 93ca9323533..e3301b754a4 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -13,17 +13,40 @@ The rules for this file: * release numbers follow "Semantic Versioning" http://semver.org ------------------------------------------------------------------------------ -??/??/?? IAlibay +??/??/?? IAlibay, jaclark5, MohitKumar020291, orionarcher, xhgchen * 2.6.0 Fixes + * Fix Boltzmann typo in `units.py` (PR #4214, Issue #4213) + * Fix deletion of bond/angle/dihedral types (PR #4003, Issue #4001) + * CRD, PQR, and PDBQT writers now write BZ2 and GZ files if requested + (PR #4163, Issue #4159) Enhancements + * Added a `exclude_same` kwarg to InterRDF (PR #4161) + * LAMMPSDump Reader use of `continuous` option to stitch trajectories + (Issue #3546) Changes + * Support for GSD is now limited to version 3.0.1 and above. Alongside this + change, support for schema 1.3 files has been dropped (PR #4153) + * Add definition of ts.data['time'] in LAMMPSDump Reader (Issue #3546) + * As per NEP29 the minimum supported version has been raised to 1.22. We + have opted to pin to a minimum of 1.22.3 to avoid known issues on some + platforms. + * GSD is no longer a core dependency of MDAnalysis. It must be installed + independently if you wish to read HOOMD trajectory files. + (PR #4174, Issue #3819) Deprecations + * The hole2 module is deprecated in favour of the the MDAKit: + https://github.com/MDAnalysis/hole2-mdakit (Issue #4179, PR #4200) + * MDAnalysis no longer officially supports 32 bit installations (they are + no longer tested in our continuous integration pipelines). Note: whilst + no code changes have been made to disable 32 bit, although it is known that + new versions of most MDAnalysis core dependencies no longer release + 32 bit compatible versions. (Issue #3858, PR #4176) 05/28/23 IAlibay, pgbarletta, mglagolev, hmacdope, manuel.nuno.melo, chrispfae, @@ -35,6 +58,7 @@ Deprecations * 2.5.0 Fixes + * Fixed using 'rb' mode inside GSDReader to avoid FutureWarning from GSDFile (Issue #4152) * Fixed ChainReader performing transformations correctly across boundaries in the individual trajectories (Issue #3657 #4008 PR #3906) * Fix the `heavy` distance_type for water bridge analysis where distance diff --git a/package/MDAnalysis/analysis/align.py b/package/MDAnalysis/analysis/align.py index 9bb9f4798e2..acb3943c576 100644 --- a/package/MDAnalysis/analysis/align.py +++ b/package/MDAnalysis/analysis/align.py @@ -74,7 +74,7 @@ two structures, using :func:`rmsd`:: >>> ref = mda.Universe(PDB_small) - >>> mobile = mda.Universe(PSF,DCD) + >>> mobile = mda.Universe(PSF, DCD) >>> rmsd(mobile.select_atoms('name CA').positions, ref.select_atoms('name CA').positions) 28.20178579474479 @@ -89,8 +89,8 @@ rotational superposition use the superposition keyword. This will calculate a minimized RMSD between the reference and mobile structure. - >>> rmsd(mobile.select_atoms('name CA').positions, ref.select_atoms('name CA').positions, - >>> superposition=True) + >>> rmsd(mobile.select_atoms('name CA').positions, ref.select_atoms('name CA').positions, + ... superposition=True) 6.809396586471815 The rotation matrix that superimposes *mobile* on *ref* while @@ -100,18 +100,21 @@ >>> mobile0 = mobile.select_atoms('name CA').positions - mobile.select_atoms('name CA').center_of_mass() >>> ref0 = ref.select_atoms('name CA').positions - ref.select_atoms('name CA').center_of_mass() >>> R, rmsd = align.rotation_matrix(mobile0, ref0) - >>> print rmsd + >>> rmsd 6.809396586471805 - >>> print R - [[ 0.14514539 -0.27259113 0.95111876] - [ 0.88652593 0.46267112 -0.00268642] - [-0.43932289 0.84358136 0.30881368]] + >>> R + array([[ 0.14514539, -0.27259113, 0.95111876], + ... [ 0.88652593, 0.46267112, -0.00268642], + ... [-0.43932289, 0.84358136, 0.30881368]]) Putting all this together one can superimpose all of *mobile* onto *ref*:: >>> mobile.atoms.translate(-mobile.select_atoms('name CA').center_of_mass()) + >>> mobile.atoms.rotate(R) + >>> mobile.atoms.translate(ref.select_atoms('name CA').center_of_mass()) + >>> mobile.atoms.write("mobile_on_ref.pdb") @@ -123,6 +126,7 @@ >>> ref = mda.Universe(PSF, PDB_small) >>> mobile = mda.Universe(PSF, DCD) # we use the first frame >>> align.alignto(mobile, ref, select="protein and name CA", weights="mass") + (21.892591663632704, 6.809396586471809) This will change *all* coordinates in *mobile* so that the protein C-alpha atoms are optimally superimposed (translation and rotation). @@ -134,6 +138,7 @@ >>> trj = mda.Universe(PSF, DCD) # trajectory of change 1AKE->4AKE >>> alignment = align.AlignTraj(trj, ref, filename='rmsfit.dcd') >>> alignment.run() + It is also possible to align two arbitrary structures by providing a mapping between atoms based on a sequence alignment. This allows @@ -143,9 +148,9 @@ the appropriate MDAnalysis selections with the :func:`fasta2select` function and then feed the resulting dictionary to :class:`AlignTraj`:: - >>> seldict = align.fasta2select('sequences.aln') - >>> alignment = align.AlignTraj(trj, ref, filename='rmsfit.dcd', select=seldict) - >>> alignment.run() + >>> seldict = align.fasta2select('sequences.aln') # doctest: +SKIP + >>> alignment = align.AlignTraj(trj, ref, filename='rmsfit.dcd', select=seldict) # doctest: +SKIP + >>> alignment.run() # doctest: +SKIP (See the documentation of the functions for this advanced usage.) @@ -222,15 +227,15 @@ def rotation_matrix(a, b, weights=None): Parameters ---------- a : array_like - coordinates that are to be rotated ("mobile set"); array of N atoms - of shape N*3 as generated by, e.g., - :attr:`MDAnalysis.core.groups.AtomGroup.positions`. + coordinates that are to be rotated ("mobile set"); array of N atoms + of shape N*3 as generated by, e.g., + :attr:`MDAnalysis.core.groups.AtomGroup.positions`. b : array_like - reference coordinates; array of N atoms of shape N*3 as generated by, - e.g., :attr:`MDAnalysis.core.groups.AtomGroup.positions`. + reference coordinates; array of N atoms of shape N*3 as generated by, + e.g., :attr:`MDAnalysis.core.groups.AtomGroup.positions`. weights : array_like (optional) - array of floats of size N for doing weighted RMSD fitting (e.g. the - masses of the atoms) + array of floats of size N for doing weighted RMSD fitting (e.g. the + masses of the atoms) Returns ------- @@ -246,10 +251,15 @@ def rotation_matrix(a, b, weights=None): :meth:`MDAnalysis.core.groups.AtomGroup.rotate` to generate a rotated selection, e.g. :: - >>> R = rotation_matrix(A.select_atoms('backbone').positions, - >>> B.select_atoms('backbone').positions)[0] - >>> A.atoms.rotate(R) - >>> A.atoms.write("rotated.pdb") + >>> from MDAnalysisTests.datafiles import TPR, TRR + >>> from MDAnalysis.analysis import align + >>> A = mda.Universe(TPR,TRR) + >>> B = A.copy() + >>> R = rotation_matrix(A.select_atoms('backbone').positions, + ... B.select_atoms('backbone').positions)[0] + >>> A.atoms.rotate(R) + + >>> A.atoms.write("rotated.pdb") Notes ----- @@ -263,6 +273,7 @@ def rotation_matrix(a, b, weights=None): AlignTraj: Fit a whole trajectory. """ + a = np.asarray(a, dtype=np.float64) b = np.asarray(b, dtype=np.float64) diff --git a/package/MDAnalysis/analysis/dielectric.py b/package/MDAnalysis/analysis/dielectric.py index 0497aac60d0..5bf5d1d6f4f 100644 --- a/package/MDAnalysis/analysis/dielectric.py +++ b/package/MDAnalysis/analysis/dielectric.py @@ -159,7 +159,7 @@ def _conclude(self): self.results.fluct = self.results.M2 - self.results.M * self.results.M self.results.eps = self.results.fluct / ( - convert(constants["Boltzman_constant"], "kJ/mol", "eV") * + convert(constants["Boltzmann_constant"], "kJ/mol", "eV") * self.temperature * self.volume * constants["electric_constant"]) self.results.eps_mean = self.results.eps.mean() diff --git a/package/MDAnalysis/analysis/hole2/hole.py b/package/MDAnalysis/analysis/hole2/hole.py index 4e012d33745..6570f1ab952 100644 --- a/package/MDAnalysis/analysis/hole2/hole.py +++ b/package/MDAnalysis/analysis/hole2/hole.py @@ -33,6 +33,7 @@ import matplotlib.pyplot as plt from collections import OrderedDict +from MDAnalysis.lib.util import deprecate from ...exceptions import ApplicationError from ..base import AnalysisBase from ...lib import util @@ -46,6 +47,9 @@ logger = logging.getLogger(__name__) +@deprecate(release="2.6.0", remove="3.0.0", + message=("This method has been moved to the MDAKit hole2-mdakit: " + "https://github.com/MDAnalysis/hole2-mdakit")) def hole(pdbfile, infile_text=None, infile=None, @@ -429,6 +433,11 @@ class HoleAnalysis(AnalysisBase): are now stored in a :class:`MDAnalysis.analysis.base.Results` instance. + .. deprecated:: 2.6.0 + This class has been moved to the MDAKit + `hole2-mdakit `_ and will + be removed for the core MDAnalysis library in version 3.0 + """ input_file = '{prefix}hole{i:03d}.inp' @@ -478,6 +487,12 @@ def __init__(self, universe, write_input_files=False): super(HoleAnalysis, self).__init__(universe.universe.trajectory, verbose=verbose) + + wmsg = ("This class has been moved to the MDAKit `hole2-mdakit` " + "(https://github.com/MDAnalysis/hole2-mdakit) and will be " + "removed in version 3.0.") + warnings.warn(wmsg, DeprecationWarning) + if output_level > 3: msg = 'output_level ({}) needs to be < 3 in order to extract a HOLE profile!' warnings.warn(msg.format(output_level)) diff --git a/package/MDAnalysis/analysis/rdf.py b/package/MDAnalysis/analysis/rdf.py index 452f0a74189..0480c2adf13 100644 --- a/package/MDAnalysis/analysis/rdf.py +++ b/package/MDAnalysis/analysis/rdf.py @@ -125,6 +125,10 @@ class InterRDF(AnalysisBase): exclusion_block : tuple A tuple representing the tile to exclude from the distance array. + exclude_same : str + Will exclude pairs of atoms that share the same "residue", "segment", or "chain". + Those are the only valid values. This is intended to remove atoms that are + spatially correlated due to direct bonded connections. verbose : bool Show detailed progress of the calculation if set to `True` @@ -220,6 +224,7 @@ def __init__(self, range=(0.0, 15.0), norm="rdf", exclusion_block=None, + exclude_same=None, **kwargs): super(InterRDF, self).__init__(g1.universe.trajectory, **kwargs) self.g1 = g1 @@ -229,6 +234,17 @@ def __init__(self, self.rdf_settings = {'bins': nbins, 'range': range} self._exclusion_block = exclusion_block + if exclude_same is not None and exclude_same not in ['residue', 'segment', 'chain']: + raise ValueError( + "The exclude_same argument to InterRDF must be None, 'residue', 'segment' " + "or 'chain'." + ) + if exclude_same is not None and exclusion_block is not None: + raise ValueError( + "The exclude_same argument to InterRDF cannot be used with exclusion_block." + ) + name_to_attr = {'residue': 'resindices', 'segment': 'segindices', 'chain': 'chainIDs'} + self.exclude_same = name_to_attr.get(exclude_same) if self.norm not in ['rdf', 'density', 'none']: raise ValueError(f"'{self.norm}' is an invalid norm. " @@ -261,6 +277,13 @@ def _single_frame(self): mask = np.where(idxA != idxB)[0] dist = dist[mask] + if self.exclude_same is not None: + # Ignore distances between atoms in the same attribute + attr_ix_a = getattr(self.g1, self.exclude_same)[pairs[:, 0]] + attr_ix_b = getattr(self.g2, self.exclude_same)[pairs[:, 1]] + mask = np.where(attr_ix_a != attr_ix_b)[0] + dist = dist[mask] + count, _ = np.histogram(dist, **self.rdf_settings) self.results.count += count diff --git a/package/MDAnalysis/coordinates/CRD.py b/package/MDAnalysis/coordinates/CRD.py index 79f88634971..89322ed771c 100644 --- a/package/MDAnalysis/coordinates/CRD.py +++ b/package/MDAnalysis/coordinates/CRD.py @@ -128,6 +128,9 @@ class CRDWriter(base.WriterBase): .. versionchanged:: 2.2.0 CRD extended format can now be explicitly requested with the `extended` keyword + .. versionchanged:: 2.6.0 + Files are now written in `wt` mode, and keep extensions, allowing + for files to be written under compressed formats """ format = 'CRD' units = {'time': None, 'length': 'Angstrom'} @@ -165,7 +168,7 @@ def __init__(self, filename, **kwargs): .. versionadded:: 2.2.0 """ - self.filename = util.filename(filename, ext='crd') + self.filename = util.filename(filename, ext='crd', keep=True) self.crd = None # account for explicit crd format, if requested @@ -247,7 +250,7 @@ def write(self, selection, frame=None): "{miss}. These will be written with default values. " "".format(miss=', '.join(missing_topology))) - with util.openany(self.filename, 'w') as crd: + with util.openany(self.filename, 'wt') as crd: # Write Title crd.write(self.fmt['TITLE'].format( frame=frame, where=u.trajectory.filename)) diff --git a/package/MDAnalysis/coordinates/GSD.py b/package/MDAnalysis/coordinates/GSD.py index 738c0d9aa72..2dcdf9bac78 100644 --- a/package/MDAnalysis/coordinates/GSD.py +++ b/package/MDAnalysis/coordinates/GSD.py @@ -51,9 +51,21 @@ """ import numpy as np -import gsd -import gsd.fl -import gsd.hoomd +try: + import gsd + import gsd.fl +except ImportError: + HAS_GSD = False + import types + + class MockHOOMDTrajectory: + pass + + gsd = types.ModuleType("gsd") + gsd.hoomd = types.ModuleType("hoomd") + gsd.hoomd.HOOMDTrajectory = MockHOOMDTrajectory +else: + HAS_GSD = True from . import base from MDAnalysis.lib.util import store_init_arguments @@ -81,8 +93,14 @@ def __init__(self, filename, **kwargs): .. versionchanged:: 2.0.0 Now use a picklable :class:`gsd.hoomd.HOOMDTrajectory`-- :class:`GSDPicklable` - + .. versionchanged:: 2.6.0 + Support for GSD versions below 3.0.1 have been dropped. This + includes support for schema 1.3. """ + if not HAS_GSD: + errmsg = "GSDReader: To read GSD files, please install gsd" + raise ImportError(errmsg) + super(GSDReader, self).__init__(filename, **kwargs) self.filename = filename self.open_trajectory() @@ -93,7 +111,7 @@ def __init__(self, filename, **kwargs): def open_trajectory(self): """opens the trajectory file using gsd.hoomd module""" self._frame = -1 - self._file = gsd_pickle_open(self.filename, mode='rb') + self._file = gsd_pickle_open(self.filename, mode='r') def close(self): """close reader""" @@ -170,8 +188,8 @@ class GSDPicklable(gsd.hoomd.HOOMDTrajectory): :: gsdfileobj = gsd.fl.open(name=filename, - mode='rb', - application='gsd.hoomd '+gsd.__version__, + mode='r', + application='gsd.hoomd '+ gsd.version.version, schema='hoomd', schema_version=[1, 3]) file = GSDPicklable(gsdfileobj) @@ -192,8 +210,8 @@ def __getstate__(self): return self.file.name, self.file.mode def __setstate__(self, args): - gsd_version = gsd.__version__ - schema_version = [1, 4] if gsd_version >= '1.9.0' else [1, 3] + gsd_version = gsd.version.version + schema_version = [1, 4] gsdfileobj = gsd.fl.open(name=args[0], mode=args[1], application='gsd.hoomd ' + gsd_version, @@ -202,7 +220,7 @@ def __setstate__(self, args): self.__init__(gsdfileobj) -def gsd_pickle_open(name, mode='rb'): +def gsd_pickle_open(name: str, mode: str='r'): """Open hoomd schema GSD file with pickle function implemented. This function returns a GSDPicklable object. It can be used as a @@ -219,8 +237,8 @@ def gsd_pickle_open(name, mode='rb'): ---------- name : str a filename given a text or byte string. - mode: {'r', 'rb'} (optional) - 'r', 'rb': open for reading; + mode: str, optional + 'r': open for reading. Returns ------- @@ -254,11 +272,14 @@ def gsd_pickle_open(name, mode='rb'): .. versionadded:: 2.0.0 + .. versionchanged:: 2.6.0 + Only GSD versions 3.0.1+ are supported. 'rb' mode support + has been replaced with 'r' mode. """ - gsd_version = gsd.__version__ - schema_version = [1, 4] if gsd_version >= '1.9.0' else [1, 3] - if mode not in {'r', 'rb'}: - raise ValueError("Only read mode ('r', 'rb') " + gsd_version = gsd.version.version + schema_version = [1, 4] + if mode != 'r': + raise ValueError("Only read mode 'r' " "files can be pickled.") gsdfileobj = gsd.fl.open(name=name, mode=mode, diff --git a/package/MDAnalysis/coordinates/LAMMPS.py b/package/MDAnalysis/coordinates/LAMMPS.py index 746d24497ee..0cd3874997b 100644 --- a/package/MDAnalysis/coordinates/LAMMPS.py +++ b/package/MDAnalysis/coordinates/LAMMPS.py @@ -263,7 +263,7 @@ def __init__(self, filename, convert_units=True, **kwargs): convert_units : bool, optional units are converted to the MDAnalysis base format; [``True``] """ - self.filename = util.filename(filename, ext='data') + self.filename = util.filename(filename, ext='data', keep=True) self.convert_units = convert_units @@ -419,7 +419,7 @@ def write(self, selection, frame=None): has_velocities = True features = {} - with util.openany(self.filename, 'w') as self.f: + with util.openany(self.filename, 'wt') as self.f: self.f.write('LAMMPS data file via MDAnalysis\n') self.f.write('\n') self.f.write('{:>12d} atoms\n'.format(len(atoms))) @@ -595,6 +595,7 @@ def _read_next_timestep(self): f.readline() # ITEM TIMESTEP step_num = int(f.readline()) ts.data['step'] = step_num + ts.data['time'] = step_num * ts.dt f.readline() # ITEM NUMBER OF ATOMS n_atoms = int(f.readline()) diff --git a/package/MDAnalysis/coordinates/NAMDBIN.py b/package/MDAnalysis/coordinates/NAMDBIN.py index 2400a34fd77..01587967963 100644 --- a/package/MDAnalysis/coordinates/NAMDBIN.py +++ b/package/MDAnalysis/coordinates/NAMDBIN.py @@ -94,7 +94,12 @@ def Writer(self, filename, **kwargs): class NAMDBINWriter(base.WriterBase): """Writer for NAMD binary coordinate files. - + + Note + ---- + * Does not handle writing to bz2 or gz compressed file types. + + .. versionadded:: 1.0.0 """ format = ['COOR', 'NAMDBIN'] diff --git a/package/MDAnalysis/coordinates/PDBQT.py b/package/MDAnalysis/coordinates/PDBQT.py index 0e07008d984..a941e65fa22 100644 --- a/package/MDAnalysis/coordinates/PDBQT.py +++ b/package/MDAnalysis/coordinates/PDBQT.py @@ -195,6 +195,11 @@ class PDBQTWriter(base.WriterBase): .. _PDB: http://www.wwpdb.org/documentation/file-format-content/format32/v3.2.html .. _PDBQT: http://autodock.scripps.edu/faqs-help/faq/what-is-the-format-of-a-pdbqt-file + + + .. versionchanged:: 2.6.0 + Files are now written in `wt` mode, and keep extensions, allowing + for files to be written under compressed formats """ fmt = { @@ -213,8 +218,8 @@ class PDBQTWriter(base.WriterBase): pdb_coor_limits = {"min": -999.9995, "max": 9999.9995} def __init__(self, filename, **kwargs): - self.filename = util.filename(filename, ext='pdbqt') - self.pdb = util.anyopen(self.filename, 'w') + self.filename = util.filename(filename, ext='pdbqt', keep=True) + self.pdb = util.anyopen(self.filename, 'wt') def close(self): self.pdb.close() diff --git a/package/MDAnalysis/coordinates/PQR.py b/package/MDAnalysis/coordinates/PQR.py index 1fd971b4d37..8ae92622e46 100644 --- a/package/MDAnalysis/coordinates/PQR.py +++ b/package/MDAnalysis/coordinates/PQR.py @@ -186,7 +186,11 @@ class PQRWriter(base.WriterBase): The output format is similar to ``pdb2pqr --whitespace``. + .. versionadded:: 0.9.0 + .. versionchanged:: 2.6.0 + Files are now written in `wt` mode, and keep extensions, allowing + for files to be written under compressed formats """ format = 'PQR' units = {'time': None, 'length': 'Angstrom'} @@ -210,7 +214,7 @@ def __init__(self, filename, convert_units=True, **kwargs): remark lines (list of strings) or single string to be added to the top of the PQR file """ - self.filename = util.filename(filename, ext='pqr') + self.filename = util.filename(filename, ext='pqr', keep=True) self.convert_units = convert_units # convert length and time to base units self.remarks = kwargs.pop('remarks', "PQR file written by MDAnalysis") @@ -299,7 +303,7 @@ def write(self, selection, frame=None): "{miss}. These will be written with default values. " "".format(miss=', '.join(missing_topology))) - with util.openany(self.filename, 'w') as pqrfile: + with util.openany(self.filename, 'wt') as pqrfile: # Header / Remarks # The *remarknumber* is typically 1 but :program:`pdb2pgr` # also uses 6 for the total charge and 5 for warnings. diff --git a/package/MDAnalysis/coordinates/chain.py b/package/MDAnalysis/coordinates/chain.py index 54fe5da7cd1..33f5a80b642 100644 --- a/package/MDAnalysis/coordinates/chain.py +++ b/package/MDAnalysis/coordinates/chain.py @@ -191,7 +191,7 @@ class ChainReader(base.ReaderBase): what frames are used with the continuous option. The default chainreader will read all frames. The continuous option is - currently only supported for XTC and TRR files. + currently only supported for XTC, TRR, and LAMMPSDUMP files. Notes ----- @@ -299,7 +299,7 @@ def __init__(self, filenames, skip=1, dt=None, continuous=False, # calculate new start_frames to have a time continuous trajectory. if continuous: - check_allowed_filetypes(self.readers, ['XTC', 'TRR']) + check_allowed_filetypes(self.readers, ['XTC', 'TRR', "LAMMPSDUMP"]) if np.any(np.array(n_frames) == 1): raise RuntimeError("ChainReader: Need at least two frames in " "every trajectory with continuous=True") diff --git a/package/MDAnalysis/core/topologyobjects.py b/package/MDAnalysis/core/topologyobjects.py index 8dcd96dc580..c620902d81d 100644 --- a/package/MDAnalysis/core/topologyobjects.py +++ b/package/MDAnalysis/core/topologyobjects.py @@ -445,7 +445,15 @@ def __init__(self, topologygroup): except KeyError: self.dict[btype] = [b] - self._removeDupes() + # Some force field types define bonds with a type + # (Ex. 1: 12 or 21), while others define with a tuple of atom types + # (Ex. 2: ("H", "O") or ("O", "H")). If the bond type is a tuple + # then the bond types in our second example are equivalent and one + # should be removed. If the bonds are defined as an integer then + # our first example would also be combined if `_removeDupes()` + # is run. + if self.dict and isinstance(list(self.dict.keys())[0], tuple): + self._removeDupes() def _removeDupes(self): """Sorts through contents and makes sure that there are diff --git a/package/MDAnalysis/lib/mdamath.py b/package/MDAnalysis/lib/mdamath.py index 260bf0b87d5..93285ad2df7 100644 --- a/package/MDAnalysis/lib/mdamath.py +++ b/package/MDAnalysis/lib/mdamath.py @@ -104,7 +104,8 @@ def normal(vec1: npt.ArrayLike, vec2: npt.ArrayLike) -> npt.NDArray: .. versionchanged:: 0.11.0 Moved into lib.mdamath """ - normal: npt.NDArray = np.cross(vec1, vec2) + # TODO: enable typing when https://github.com/python/mypy/issues/11347 done + normal: npt.NDArray = np.cross(vec1, vec2) # type: ignore n = norm(normal) if n == 0.0: return normal # returns [0,0,0] instead of [nan,nan,nan] @@ -171,7 +172,8 @@ def stp(vec1: npt.ArrayLike, vec2: npt.ArrayLike, vec3: npt.ArrayLike) -> float: .. versionchanged:: 0.11.0 Moved into lib.mdamath """ - return np.dot(vec3, np.cross(vec1, vec2)) + # TODO: enable typing when https://github.com/python/mypy/issues/11347 done + return np.dot(vec3, np.cross(vec1, vec2)) # type: ignore def dihedral(ab: npt.ArrayLike, bc: npt.ArrayLike, cd: npt.ArrayLike) -> float: @@ -292,9 +294,10 @@ def triclinic_box(x: npt.ArrayLike, y: npt.ArrayLike, z: npt.ArrayLike) -> npt.N lx = norm(x) ly = norm(y) lz = norm(z) - alpha = np.rad2deg(np.arccos(np.dot(y, z) / (ly * lz))) - beta = np.rad2deg(np.arccos(np.dot(x, z) / (lx * lz))) - gamma = np.rad2deg(np.arccos(np.dot(x, y) / (lx * ly))) + with np.errstate(invalid="ignore"): + alpha = np.rad2deg(np.arccos(np.dot(y, z) / (ly * lz))) + beta = np.rad2deg(np.arccos(np.dot(x, z) / (lx * lz))) + gamma = np.rad2deg(np.arccos(np.dot(x, y) / (lx * ly))) box = np.array([lx, ly, lz, alpha, beta, gamma], dtype=np.float32) # Only positive edge lengths and angles in (0, 180) are allowed: if np.all(box > 0.0) and alpha < 180.0 and beta < 180.0 and gamma < 180.0: diff --git a/package/MDAnalysis/lib/src/transformations/transformations.c b/package/MDAnalysis/lib/src/transformations/transformations.c index d9fdda72be7..4536b301d32 100644 --- a/package/MDAnalysis/lib/src/transformations/transformations.c +++ b/package/MDAnalysis/lib/src/transformations/transformations.c @@ -786,7 +786,7 @@ PyConverter_AnyDoubleArray( PyObject **address) { PyArrayObject *obj = (PyArrayObject *)object; - if (PyArray_Check(object) && obj->descr->type_num == PyArray_DOUBLE) { + if (PyArray_Check(object) && obj->descr->type_num == NPY_DOUBLE) { *address = object; Py_INCREF(object); return NPY_SUCCEED; @@ -965,7 +965,7 @@ PyOutputConverter_AnyDoubleArrayOrNone( *address = NULL; return NPY_SUCCEED; } - if (PyArray_Check(object) && (obj->descr->type_num == PyArray_DOUBLE)) { + if (PyArray_Check(object) && (obj->descr->type_num == NPY_DOUBLE)) { Py_INCREF(object); *address = (PyArrayObject *)object; return NPY_SUCCEED; diff --git a/package/MDAnalysis/lib/util.py b/package/MDAnalysis/lib/util.py index 4bf21361a45..fbbb9679340 100644 --- a/package/MDAnalysis/lib/util.py +++ b/package/MDAnalysis/lib/util.py @@ -338,9 +338,10 @@ def anyopen(datasource, mode='rt', reset=True): a file (from :class:`file` or :func:`open`) or a stream (e.g. from :func:`urllib2.urlopen` or :class:`io.StringIO`) mode: {'r', 'w', 'a'} (optional) - Open in r(ead), w(rite) or a(ppen) mode. More complicated - modes ('r+', 'w+', ...) are not supported; only the first letter of - `mode` is used and thus any additional modifiers are silently ignored. + Open in r(ead), w(rite) or a(ppend) mode. This string is directly + passed to the file opening handler (either Python's openfe, bz2, or + gzip). More complex modes are supported if the file opening handler + supports it. reset: bool (optional) try to read (`mode` 'r') the stream from the start diff --git a/package/MDAnalysis/topology/GSDParser.py b/package/MDAnalysis/topology/GSDParser.py index c093c73cec4..f1ae72d287d 100644 --- a/package/MDAnalysis/topology/GSDParser.py +++ b/package/MDAnalysis/topology/GSDParser.py @@ -52,7 +52,6 @@ """ import os -import gsd.hoomd import numpy as np from . import guessers @@ -75,6 +74,13 @@ Segids, ) +try: + import gsd.hoomd +except ImportError: + HAS_GSD = False +else: + HAS_GSD = True + class GSDParser(TopologyReaderBase): """Parses a Hoomd GSD file to create a Topology @@ -101,6 +107,14 @@ class GSDParser(TopologyReaderBase): """ format = 'GSD' + def __init__(self, filename): + + if not HAS_GSD: + errmsg = ("GSDParser: To read a Topology from a Hoomd GSD " + "file, please install gsd") + raise ImportError(errmsg) + super(GSDParser, self).__init__(filename) + def parse(self, **kwargs): """Parse Hoomd GSD file @@ -108,7 +122,7 @@ def parse(self, **kwargs): """ attrs = {} - with gsd.hoomd.open(self.filename,mode='rb') as t : + with gsd.hoomd.open(self.filename, mode='r') as t : # Here it is assumed that the particle data does not change in the # trajectory. snap = t[0] diff --git a/package/MDAnalysis/units.py b/package/MDAnalysis/units.py index eb36d4a7908..951416d02ce 100644 --- a/package/MDAnalysis/units.py +++ b/package/MDAnalysis/units.py @@ -193,7 +193,7 @@ 'N_Avogadro': 6.02214129e+23, # mol**-1 'elementary_charge': 1.602176565e-19, # As 'calorie': 4.184, # J - 'Boltzman_constant': 8.314462159e-3, # KJ (mol K)**-1 + 'Boltzmann_constant': 8.314462159e-3, # KJ (mol K)**-1 'electric_constant': 5.526350e-3, # As (Angstroms Volts)**-1 } diff --git a/package/pyproject.toml b/package/pyproject.toml index 43b9a0577d7..af034be83e1 100644 --- a/package/pyproject.toml +++ b/package/pyproject.toml @@ -8,12 +8,11 @@ requires = [ # except for more exotic platform (Mac Arm flavors) # aarch64, AIX, s390x, and arm64 all support 1.21 so we can safely pin to this # Note: MDA does not build with PyPy so we do not support it in the build system - "numpy==1.21.0; python_version=='3.9' and platform_python_implementation != 'PyPy'", # Scipy: On windows avoid 1.21.6, 1.22.0, and 1.22.1 because they were built on vc142 - "numpy==1.22.3; python_version=='3.10' and platform_system=='Windows' and platform_python_implementation != 'PyPy'", - # As per https://github.com/scipy/oldest-supported-numpy/blob/main/setup.cfg - # safest to build at 1.21.6 for all other platforms - "numpy==1.21.6; python_version=='3.10' and platform_system !='Windows'and platform_python_implementation != 'PyPy'", + # Let's set everything to this version to make things clean, also avoids other issues + # on other archs + "numpy==1.22.3; python_version=='3.9' and platform_python_implementation != 'PyPy'", + "numpy==1.22.3; python_version=='3.10' and platform_python_implementation != 'PyPy'", "numpy==1.23.2; python_version=='3.11' and platform_python_implementation != 'PyPy'", # For unreleased versions of Python there is currently no known supported # NumPy version. In that case we just let it be a bare NumPy install @@ -47,7 +46,6 @@ dependencies = [ 'threadpoolctl', 'packaging', 'fasteners', - 'gsd>=1.9.3', ] keywords = [ "python", "science", "chemistry", "biophysics", "molecular-dynamics", @@ -78,8 +76,11 @@ extra_formats = [ "netCDF4>=1.0", "h5py>=2.10", "chemfiles>=0.10", + "parmed", "pyedr>=0.7.0", "pytng>=0.2.3", + "gsd>3.0.0", + "rdkit>=2020.03.1", ] analysis = [ "seaborn", diff --git a/package/requirements.txt b/package/requirements.txt index a9daf1375ff..ba896936372 100644 --- a/package/requirements.txt +++ b/package/requirements.txt @@ -11,7 +11,7 @@ mmtf-python msmb_theme==1.2.0 netcdf4 networkx -numpy>=1.21.0 +numpy>=1.22.3 packaging parmed pytest diff --git a/package/setup.py b/package/setup.py index cea781c732b..e72247b32c1 100755 --- a/package/setup.py +++ b/package/setup.py @@ -592,7 +592,7 @@ def long_description(readme): exts, cythonfiles = extensions(config) install_requires = [ - 'numpy>=1.21.0', + 'numpy>=1.22.3', 'biopython>=1.80', 'networkx>=2.0', 'GridDataFormats>=0.4.0', @@ -604,7 +604,6 @@ def long_description(readme): 'threadpoolctl', 'packaging', 'fasteners', - 'gsd>=1.9.3', ] setup(name='MDAnalysis', @@ -654,6 +653,9 @@ def long_description(readme): 'pytng>=0.2.3', # TNG 'chemfiles>=0.10', # multiple formats supported by chemfiles 'pyedr>=0.7.0', # EDR files for the EDR AuxReader + 'gsd>3.0.0', # GSD + 'rdkit>=2020.03.1', # RDKit converter + 'parmed', # ParmEd converter ], 'analysis': [ 'seaborn', # for annotated heat map and nearest neighbor diff --git a/testsuite/MDAnalysisTests/analysis/test_hole2.py b/testsuite/MDAnalysisTests/analysis/test_hole2.py index 98bdb24a412..694b5560d3e 100644 --- a/testsuite/MDAnalysisTests/analysis/test_hole2.py +++ b/testsuite/MDAnalysisTests/analysis/test_hole2.py @@ -110,8 +110,9 @@ class TestHole(object): def test_correct_input(self, tmpdir): with tmpdir.as_cwd(): - hole2.hole(self.filename, random_seed=self.random_seed, - infile='hole.inp') + with pytest.warns(DeprecationWarning, match="to the MDAKit"): + hole2.hole(self.filename, random_seed=self.random_seed, + infile='hole.inp') infile = str(tmpdir.join('hole.inp')) with open(infile, 'r') as f: @@ -135,9 +136,10 @@ def test_input_options(self, tmpdir): cog = u.select_atoms('protein').center_of_geometry() with tmpdir.as_cwd(): - hole2.hole(self.filename, random_seed=self.random_seed, - infile='hole.inp', cpoint=cog, - ignore_residues=[]) + with pytest.warns(DeprecationWarning, match="to the MDAKit"): + hole2.hole(self.filename, random_seed=self.random_seed, + infile='hole.inp', cpoint=cog, + ignore_residues=[]) infile = str(tmpdir.join('hole.inp')) with open(infile, 'r') as f: @@ -159,7 +161,9 @@ def test_input_options(self, tmpdir): def test_correct_profile_values(self, tmpdir): with tmpdir.as_cwd(): - profiles = hole2.hole(self.filename, random_seed=self.random_seed) + with pytest.warns(DeprecationWarning, match="to the MDAKit"): + profiles = hole2.hole(self.filename, + random_seed=self.random_seed) values = list(profiles.values()) assert_equal(len(values), 1, @@ -195,11 +199,13 @@ def test_correct_profile_values(self, tmpdir): # assert_equal(len(profiles), int(keep_frames/step)) + @pytest.mark.filterwarnings("ignore: `hole` is deprecated") def test_application_error(self, tmpdir): with tmpdir.as_cwd(): with pytest.raises(ApplicationError): hole2.hole(self.filename, dcd=DCD) + @pytest.mark.filterwarnings("ignore: `hole` is deprecated") def test_output_level(self, tmpdir): with tmpdir.as_cwd(): with pytest.warns(UserWarning, match="needs to be < 3"): @@ -210,9 +216,10 @@ def test_output_level(self, tmpdir): def test_keep_files(self, tmpdir): with tmpdir.as_cwd(): - hole2.hole(self.filename, random_seed=self.random_seed, - infile='hole.inp', - keep_files=False) + with pytest.warns(DeprecationWarning, match="to the MDAKit"): + hole2.hole(self.filename, random_seed=self.random_seed, + infile='hole.inp', + keep_files=False) sphpdbs = tmpdir.join('*.sph') assert len(glob.glob(str(sphpdbs))) == 0 outfiles = tmpdir.join('*.out') @@ -243,7 +250,8 @@ def universe(self): @pytest.fixture() def hole(self, universe, tmpdir): with tmpdir.as_cwd(): - h = hole2.HoleAnalysis(universe) + with pytest.warns(DeprecationWarning, match='This class has been'): + h = hole2.HoleAnalysis(universe) h.run(start=self.start, stop=self.stop, random_seed=self.random_seed) return h @@ -274,21 +282,25 @@ class TestOSError: def universe(self): return mda.Universe(MULTIPDB_HOLE) + @pytest.mark.filterwarnings("ignore: `hole` is deprecated") def test_hole_method_oserror(self): errmsg = exe_err.format(name='dummy_path', kw='executable') with pytest.raises(OSError, match=errmsg): h = hole2.hole(PDB_HOLE, executable='dummy_path') + @pytest.mark.filterwarnings("ignore: This class has been moved") def test_hole_oserror(self, universe): errmsg = exe_err.format(name='dummy_path', kw='executable') with pytest.raises(OSError, match=errmsg): h = hole2.HoleAnalysis(universe, executable='dummy_path') + @pytest.mark.filterwarnings("ignore: This class has been moved") def test_sos_triangle_oserror(self, universe): errmsg = exe_err.format(name='dummy_path', kw='sos_triangle') with pytest.raises(OSError, match=errmsg): h = hole2.HoleAnalysis(universe, sos_triangle='dummy_path') + @pytest.mark.filterwarnings("ignore: This class has been moved") def test_sph_process_oserror(self, universe): errmsg = exe_err.format(name='dummy_path', kw='sph_process') with pytest.raises(OSError, match=errmsg): @@ -316,6 +328,7 @@ def test_min_radius(self, hole): assert_almost_equal(hole.min_radius(), values, err_msg="min_radius() array not correct") + @pytest.mark.filterwarnings("ignore: This class has been moved") def test_context_manager(self, universe, tmpdir): with tmpdir.as_cwd(): with hole2.HoleAnalysis(universe) as h: @@ -336,6 +349,7 @@ def test_context_manager(self, universe, tmpdir): vmd_file = tmpdir.join('hole.vmd') assert len(glob.glob(str(vmd_file))) == 1 + @pytest.mark.filterwarnings("ignore: This class has been moved") @pytest.mark.parametrize("start,stop,step", [ (1, 9, 2), (1, None, 3), (5, -2, None)]) def test_nonzero_start_surface(self, universe, tmpdir, @@ -343,7 +357,8 @@ def test_nonzero_start_surface(self, universe, tmpdir, surface="hole.vmd"): # Issue 3476 with tmpdir.as_cwd(): - h = hole2.HoleAnalysis(universe) + with pytest.warns(DeprecationWarning, match='This class has been'): + h = hole2.HoleAnalysis(universe) h.run(start=start, stop=stop, step=step) h.create_vmd_surface(filename=surface) @@ -358,6 +373,7 @@ def test_nonzero_start_surface(self, universe, tmpdir, np.arange(len(universe.trajectory[start:stop:step])), err_msg="wrong frame indices in VMD surface file") + @pytest.mark.filterwarnings("ignore: This class has been moved") def test_output_level(self, tmpdir, universe): with tmpdir.as_cwd(): with pytest.warns(UserWarning, match='needs to be < 3'): @@ -373,10 +389,11 @@ def test_cpoint_geometry(self, tmpdir, universe): protein = universe.select_atoms('protein') cogs = [protein.center_of_geometry() for ts in universe.trajectory] with tmpdir.as_cwd(): - h = hole2.HoleAnalysis(universe, - select='protein', - cpoint='center_of_geometry', - write_input_files=True) + with pytest.warns(DeprecationWarning, match='This class has been'): + h = hole2.HoleAnalysis(universe, + select='protein', + cpoint='center_of_geometry', + write_input_files=True) h.run(start=self.start, stop=self.stop, random_seed=self.random_seed) @@ -469,6 +486,7 @@ def test_plot3D_rmax(self, hole, frames, profiles): assert_almost_equal(z, radius) assert line.get_label() == str(frame) + @pytest.mark.filterwarnings("ignore: This class has been moved") def test_none_filename(self, tmpdir): universe_none_filename = mda.Universe(PDB_HOLE, in_memory=True) universe_none_filename.trajectory.filename = None @@ -722,6 +740,7 @@ def universe(): @pytest.mark.skipif(rlimits_missing, reason="Test skipped because platform does not allow setting rlimits") + @pytest.mark.filterwarnings("ignore: This class has been moved") def test_hole_module_fd_closure(self, universe, tmpdir): """test open file descriptors are closed (MDAnalysisTests.analysis.test_hole.TestHoleModule): Issue 129""" # If Issue 129 isn't resolved, this function will produce an OSError on diff --git a/testsuite/MDAnalysisTests/analysis/test_rdf.py b/testsuite/MDAnalysisTests/analysis/test_rdf.py index 3717ea1898b..bc121666488 100644 --- a/testsuite/MDAnalysisTests/analysis/test_rdf.py +++ b/testsuite/MDAnalysisTests/analysis/test_rdf.py @@ -32,7 +32,9 @@ @pytest.fixture() def u(): - return mda.Universe(two_water_gro, in_memory=True) + u = mda.Universe(two_water_gro, in_memory=True) + u.add_TopologyAttr('chainIDs', u.atoms.resids) + return u @pytest.fixture() @@ -94,6 +96,27 @@ def test_exclusion(sels): assert rdf.results.count.sum() == 4 +@pytest.mark.parametrize("attr, count", [ + ("residue", 8), + ("segment", 0), + ("chain", 8)]) +def test_ignore_same_residues(sels, attr, count): + # should see two distances with 4 counts each + s1, s2 = sels + rdf = InterRDF(s2, s2, exclude_same=attr).run() + assert rdf.rdf[0] == 0 + assert rdf.results.count.sum() == count + + +def test_ignore_same_residues_fails(sels): + s1, s2 = sels + with pytest.raises(ValueError, match="The exclude_same argument to InterRDF must be"): + InterRDF(s2, s2, exclude_same="unsupported").run() + + with pytest.raises(ValueError, match="The exclude_same argument to InterRDF cannot be used with"): + InterRDF(s2, s2, exclude_same="residue", exclusion_block=tuple()).run() + + @pytest.mark.parametrize("attr", ("rdf", "bins", "edges", "count")) def test_rdf_attr_warning(sels, attr): s1, s2 = sels diff --git a/testsuite/MDAnalysisTests/coordinates/test_chainreader.py b/testsuite/MDAnalysisTests/coordinates/test_chainreader.py index a869039d8b2..ba0687ffd76 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_chainreader.py +++ b/testsuite/MDAnalysisTests/coordinates/test_chainreader.py @@ -33,7 +33,9 @@ import MDAnalysis as mda from MDAnalysis.transformations import translate from MDAnalysisTests.datafiles import (PDB, PSF, CRD, DCD, - GRO, XTC, TRR, PDB_small, PDB_closed) + GRO, XTC, TRR, PDB_small, PDB_closed, + LAMMPS_chain, LAMMPSDUMP_chain1, + LAMMPSDUMP_chain2,) from MDAnalysisTests.util import no_warning @@ -206,6 +208,18 @@ def test_set_all_format_tuples(self): assert universe.trajectory.n_frames == 21 assert_equal(universe.trajectory.filenames, [PDB, XTC, TRR]) + def test_set_all_format_lammps(self): + universe = mda.Universe( + LAMMPS_chain, [LAMMPSDUMP_chain1, LAMMPSDUMP_chain2], + format="LAMMPSDUMP", continuous=True) + assert universe.trajectory.n_frames == 11 + + # Test whether the amount of time between frames is consistently = 1 + time_values = np.array([ts.time for ts in universe.trajectory]) + dt_array = time_values[1:]-time_values[:-1] + assert np.unique(dt_array) == 1 + assert_equal(time_values, np.arange(11)) + def test_set_format_tuples_and_format(self): universe = mda.Universe(GRO, [(PDB, 'pdb'), GRO, GRO, (XTC, 'xtc'), (TRR, 'trr')], format='gro') diff --git a/testsuite/MDAnalysisTests/coordinates/test_copying.py b/testsuite/MDAnalysisTests/coordinates/test_copying.py index 8536c3086c3..b6f42e7aff0 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_copying.py +++ b/testsuite/MDAnalysisTests/coordinates/test_copying.py @@ -60,6 +60,7 @@ XYZ_mini, ) from MDAnalysis.coordinates.core import get_reader_for +from MDAnalysis.coordinates.GSD import HAS_GSD from MDAnalysis.auxiliary.EDR import HAS_PYEDR @@ -89,7 +90,10 @@ ('memory', np.arange(60).reshape(2, 10, 3).astype(np.float64), dict()), ('CHAIN', [GRO, GRO, GRO], dict()), ('FHIAIMS', FHIAIMS, dict()), - ('GSD', GSD, dict()), + pytest.param( + ('GSD', GSD, dict()), + marks=pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') + ), ('NAMDBIN', NAMDBIN, dict()), ('TXYZ', TXYZ, dict()), ]) @@ -130,7 +134,10 @@ def ref_reader(request): ('memory', np.arange(60).reshape(2, 10, 3).astype(np.float64), dict()), ('CHAIN', [GRO, GRO, GRO], dict()), ('FHIAIMS', FHIAIMS, dict()), - ('GSD', GSD, dict()), + pytest.param( + ('GSD', GSD, dict()), + marks=pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') + ), ('NAMDBIN', NAMDBIN, dict()), ('TXYZ', TXYZ, dict()), ]) diff --git a/testsuite/MDAnalysisTests/coordinates/test_crd.py b/testsuite/MDAnalysisTests/coordinates/test_crd.py index 623524a8a98..2b964d9c67e 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_crd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_crd.py @@ -43,14 +43,17 @@ def u(self): def outfile(self, tmpdir): return os.path.join(str(tmpdir), 'test.crd') - def test_write_atoms(self, u, outfile): + @pytest.mark.parametrize('testfile', + ['test.crd', 'test.crd.bz2', 'test.crd.gz']) + def test_write_atoms(self, u, testfile, tmpdir): # Test that written file when read gives same coordinates - u.atoms.write(outfile) + with tmpdir.as_cwd(): + u.atoms.write(testfile) - u2 = mda.Universe(outfile) + u2 = mda.Universe(testfile) - assert_equal(u.atoms.positions, - u2.atoms.positions) + assert_equal(u.atoms.positions, + u2.atoms.positions) def test_roundtrip(self, u, outfile): # Write out a copy of the Universe, and compare this against the original diff --git a/testsuite/MDAnalysisTests/coordinates/test_gsd.py b/testsuite/MDAnalysisTests/coordinates/test_gsd.py index 9c11208bd36..7cf38209fb1 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gsd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gsd.py @@ -26,36 +26,48 @@ from numpy.testing import assert_almost_equal import MDAnalysis as mda -from MDAnalysis.coordinates.GSD import GSDReader +from MDAnalysis.coordinates.GSD import GSDReader, HAS_GSD from MDAnalysisTests.datafiles import GSD -@pytest.fixture -def GSD_U(): - return mda.Universe(GSD) +@pytest.mark.skipif(HAS_GSD, reason='gsd is installed') +def test_no_gsd_u_raises(): + with pytest.raises(ImportError, match='please install gsd'): + _ = mda.Universe(GSD) -def test_gsd_positions(GSD_U): - # first frame first particle - ts = GSD_U.trajectory[0] - assert_almost_equal(GSD_U.atoms.positions[0], - [ -5.4000001 , -10.19999981, -10.19999981]) - # second frame first particle - ts = GSD_U.trajectory[1] - assert_almost_equal(GSD_U.atoms.positions[0], - [ -5.58348083, -9.98546982, -10.17657185]) +@pytest.mark.skipif(HAS_GSD, reason='gsd is installed') +def test_gsd_reader_raises(): + with pytest.raises(ImportError, match='please install gsd'): + _ = GSDReader('foo') -def test_gsd_n_frames(GSD_U): - assert len(GSD_U.trajectory) == 2 +@pytest.mark.skipif(not HAS_GSD, reason='gsd is not installed') +class TestGSDReader: + @pytest.fixture(scope='class') + def GSD_U(self): + return mda.Universe(GSD) + def test_gsd_positions(self, GSD_U): + # first frame first particle + GSD_U.trajectory[0] + assert_almost_equal(GSD_U.atoms.positions[0], + [-5.4000001 , -10.19999981, -10.19999981]) + # second frame first particle + GSD_U.trajectory[1] + assert_almost_equal(GSD_U.atoms.positions[0], + [-5.58348083, -9.98546982, -10.17657185]) + + def test_gsd_n_frames(self, GSD_U): + assert len(GSD_U.trajectory) == 2 -def test_gsd_dimensions(GSD_U): - ts = GSD_U.trajectory[0] - assert_almost_equal(ts.dimensions, - [ 21.60000038,21.60000038,21.60000038,90.,90.,90.]) + def test_gsd_dimensions(self, GSD_U): + ts = GSD_U.trajectory[0] + assert_almost_equal( + ts.dimensions, + [21.60000038, 21.60000038, 21.60000038, 90., 90., 90.] + ) - -def test_gsd_data_step(GSD_U): - assert GSD_U.trajectory[0].data['step'] == 0 - assert GSD_U.trajectory[1].data['step'] == 500 + def test_gsd_data_step(self, GSD_U): + assert GSD_U.trajectory[0].data['step'] == 0 + assert GSD_U.trajectory[1].data['step'] == 500 diff --git a/testsuite/MDAnalysisTests/coordinates/test_lammps.py b/testsuite/MDAnalysisTests/coordinates/test_lammps.py index f3a9e53ab93..c8afb286fb7 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_lammps.py +++ b/testsuite/MDAnalysisTests/coordinates/test_lammps.py @@ -220,8 +220,13 @@ def test_molecule_tag(self, LAMMPSDATAWriter_molecule_tag): err_msg="resids different after writing",) -def test_datawriter_universe(tmpdir): - fn = str(tmpdir.join('out.data')) +@pytest.mark.parametrize('filename', ['out.data', 'out.data.bz2', 'out.data.gz']) +def test_datawriter_universe(filename, tmpdir): + """ + Test roundtrip on datawriter, and also checks compressed files + can be written (see #4159). + """ + fn = str(tmpdir.join(filename)) u = mda.Universe(LAMMPSdata_mini) diff --git a/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py b/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py index 667ed61aa36..2c169da9889 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py @@ -89,13 +89,17 @@ class TestPDBQTWriter(object): def outfile(self, tmpdir): return str(tmpdir) + 'out.pdbqt' - def test_roundtrip_writing_coords(self, outfile): - u = mda.Universe(PDBQT_input) - u.atoms.write(outfile) - u2 = mda.Universe(outfile) + @pytest.mark.parametrize('filename', + ['test.pdbqt', 'test.pdbqt.bz2', 'test.pdbqt.gz']) + def test_roundtrip_writing_coords(self, filename, tmpdir): + + with tmpdir.as_cwd(): + u = mda.Universe(PDBQT_input) + u.atoms.write(filename) + u2 = mda.Universe(filename) - assert_equal(u2.atoms.positions, u.atoms.positions, - "Round trip does not preserve coordinates") + assert_equal(u2.atoms.positions, u.atoms.positions, + "Round trip does not preserve coordinates") def test_roundtrip_formatting(self, outfile): # Compare formatting of first line diff --git a/testsuite/MDAnalysisTests/coordinates/test_pqr.py b/testsuite/MDAnalysisTests/coordinates/test_pqr.py index 96eeea34099..9f1fe2f89b1 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pqr.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pqr.py @@ -80,6 +80,15 @@ def universe(): prec = 3 + @pytest.mark.parametrize('filename', + ['test.pqr', 'test.pqr.bz2', 'test.pqr.gz']) + def test_simple_writer_roundtrip(self, universe, filename, tmpdir): + with tmpdir.as_cwd(): + universe.atoms.write(filename) + u2 = mda.Universe(filename) + assert_equal(universe.atoms.positions, + u2.atoms.positions) + def test_writer_noChainID(self, universe, tmpdir): outfile = str(tmpdir.join('pqr-test.pqr')) diff --git a/testsuite/MDAnalysisTests/core/test_topologyobjects.py b/testsuite/MDAnalysisTests/core/test_topologyobjects.py index ec31d743e34..380a73b8afe 100644 --- a/testsuite/MDAnalysisTests/core/test_topologyobjects.py +++ b/testsuite/MDAnalysisTests/core/test_topologyobjects.py @@ -29,6 +29,7 @@ import MDAnalysis as mda from MDAnalysis.lib.distances import calc_bonds, calc_angles, calc_dihedrals +from MDAnalysisTests.datafiles import LAMMPSdata_many_bonds from MDAnalysis.core.topologyobjects import ( TopologyGroup, TopologyObject, TopologyDict, # TODO: the following items are not used @@ -300,6 +301,15 @@ def test_bond_reversal(self, PSFDCD, b_td): tg2 = b_td[b[::-1]] assert tg1 == tg2 + # This test will pass as long as `TopologyDict._removeDupes()` is + # not run. Otherwise bond type 12 and 21 will be seen as duplicates + # and combined. + def test_bond_no_reversal(self): + universe = mda.Universe(LAMMPSdata_many_bonds, format="DATA") + nbonds = 22 + bondtypes = universe.atoms.bonds.types() + assert len(bondtypes) == nbonds + def test_angles_types(self, PSFDCD): """TopologyDict for angles""" assert len(PSFDCD.atoms.angles.types()) == 130 diff --git a/testsuite/MDAnalysisTests/data/lammps/a_lot_of_bond_types.data b/testsuite/MDAnalysisTests/data/lammps/a_lot_of_bond_types.data new file mode 100644 index 00000000000..1da933ba3e5 --- /dev/null +++ b/testsuite/MDAnalysisTests/data/lammps/a_lot_of_bond_types.data @@ -0,0 +1,204 @@ +LAMMPS data file generated by OpenBabel +28 atoms +27 bonds +44 angles +61 dihedrals +0 impropers +9 atom types +22 bond types +36 angle types +49 dihedral types +0 improper types + -6.91004 5.99665 xlo xhi + -6.91004 5.99665 ylo yhi + -6.91004 5.99665 zlo zhi + + + +Masses + +1 79.904 # Br +2 12.0107 # C +3 35.453 # Cl +4 18.9984 # F +5 1.00794 # H +6 14.0067 # N +7 15.9994 # O +8 30.9738 # P +9 32.065 # S + + +Atoms + +1 1 2 0.00000 -1.23707 1.11411 -0.08956 # C +2 1 2 0.00000 -2.12077 -0.27264 0.08817 # C +3 1 2 0.00000 -1.74311 -1.09893 1.38852 # C +4 1 5 0.41000 -2.18526 -0.62143 2.28556 # H +5 1 4 0.00000 -2.25633 -2.37277 1.29938 # F +6 1 1 0.00000 0.09936 -1.55412 1.81908 # Br +7 1 9 0.00000 -4.07565 -0.30488 0.00221 # S +8 1 7 -0.82000 -5.81365 -0.48635 -0.01704 # O +9 1 1 0.00000 -6.41004 -0.99147 -1.70511 # Br +10 1 7 -0.82000 -3.96870 1.41535 0.18342 # O +11 1 6 0.00000 -4.98376 1.90832 -0.59681 # N +12 1 5 0.41000 -5.81819 2.06218 0.01623 # H +13 1 8 0.00000 -4.57772 3.50859 -1.33780 # P +14 1 5 0.41000 -5.78917 3.47542 -2.14332 # H +15 1 5 0.41000 -4.80980 4.20632 -0.08001 # H +16 1 1 0.00000 -4.02071 5.49665 -2.30091 # Br +17 1 7 -0.82000 -4.22298 -2.03748 -0.17558 # O +18 1 3 0.00000 -4.91536 -2.74247 1.23284 # Cl +19 1 3 0.00000 -1.67757 -1.28048 -1.34036 # Cl +20 1 8 0.00000 -1.35687 2.50643 1.21376 # P +21 1 4 0.00000 -2.70153 3.42513 0.73504 # F +22 1 7 -0.82000 -0.30576 3.58278 0.31747 # O +23 1 4 0.00000 0.91763 3.37723 0.77456 # F +24 1 7 -0.82000 -1.47682 1.68843 -1.35335 # O +25 1 5 0.41000 -2.39092 1.46822 -1.65330 # H +26 1 6 0.00000 0.21540 0.84629 -0.04018 # N +27 1 5 0.41000 0.62043 0.77000 0.92091 # H +28 1 4 0.00000 0.67813 -0.11355 -0.86675 # F + + +Bonds + +1 6 2 1 # N: C +2 8 3 1 # O: C +3 9 3 4 # O: H +4 4 5 2 # F: N +5 7 2 6 # N: H +6 11 7 1 # P: C +7 15 7 8 # P: O +8 12 7 9 # P: F +9 5 10 8 # F: O +10 1 1 11 # C: C +11 21 12 11 # Cl: C +12 16 13 11 # S: C +13 17 13 14 # S: O +14 17 13 15 # S: O +15 17 13 16 # S: O +16 19 17 16 # Br: O +17 1 11 18 # C: C +18 18 19 18 # Br: C +19 3 20 18 # F: C +20 2 18 21 # C: H +21 10 15 22 # O: N +22 22 23 14 # Cl: O +23 14 24 22 # P: N +24 7 22 25 # N: H +25 20 26 24 # Br: P +26 13 24 27 # P: H +27 13 24 28 # P: H + + +Angles + +1 15 3 1 2 # O: C: N +2 21 7 1 2 # P: C: N +3 12 2 1 11 # N: C: C +4 22 7 1 3 # P: C: O +5 14 3 1 11 # O: C: C +6 20 7 1 11 # P: C: C +7 7 5 2 1 # F: N: C +8 3 1 2 6 # C: N: H +9 8 5 2 6 # F: N: H +10 4 1 3 4 # C: O: H +11 17 8 7 1 # O: P: C +12 9 9 7 1 # F: P: C +13 10 9 7 8 # F: P: O +14 25 7 8 10 # P: O: F +15 34 12 11 1 # Cl: C: C +16 26 13 11 1 # S: C: C +17 1 18 11 1 # C: C: C +18 35 12 11 13 # Cl: C: S +19 34 12 11 18 # Cl: C: C +20 26 13 11 18 # S: C: C +21 18 14 13 11 # O: S: C +22 18 15 13 11 # O: S: C +23 18 16 13 11 # O: S: C +24 19 15 13 14 # O: S: O +25 19 16 13 14 # O: S: O +26 19 16 13 15 # O: S: O +27 36 23 14 13 # Cl: O: S +28 27 13 15 22 # S: O: N +29 31 17 16 13 # Br: O: S +30 28 19 18 11 # Br: C: C +31 5 20 18 11 # F: C: C +32 2 11 18 21 # C: C: H +33 29 19 18 20 # Br: C: F +34 30 19 18 21 # Br: C: H +35 6 20 18 21 # F: C: H +36 24 24 22 15 # P: N: O +37 16 15 22 25 # O: N: H +38 23 24 22 25 # P: N: H +39 33 26 24 22 # Br: P: N +40 13 22 24 27 # N: P: H +41 13 22 24 28 # N: P: H +42 32 26 24 27 # Br: P: H +43 32 26 24 28 # Br: P: H +44 11 28 24 27 # H: P: H + + +Dihedrals + +1 6 5 1 2 3 # F: C: N: O +2 17 3 1 2 6 # O: C: N: H +3 25 7 1 2 5 # P: C: N: F +4 26 7 1 2 6 # P: C: N: H +5 5 5 1 2 11 # F: C: N: C +6 2 11 1 2 6 # C: C: N: H +7 14 2 1 3 4 # N: C: O: H +8 27 7 1 3 4 # P: C: O: H +9 3 11 1 3 4 # C: C: O: H +10 19 8 1 7 2 # O: C: P: N +11 8 9 1 7 2 # F: C: P: N +12 20 8 1 7 3 # O: C: P: O +13 9 9 1 7 3 # F: C: P: O +14 18 8 1 7 11 # O: C: P: C +15 7 9 1 7 11 # F: C: P: C +16 10 10 7 8 1 # F: P: O: C +17 11 10 7 8 9 # F: P: O: F +18 44 12 1 11 2 # Cl: C: C: N +19 30 13 1 11 2 # S: C: C: N +20 13 2 1 11 18 # N: C: C: C +21 45 12 1 11 3 # Cl: C: C: O +22 31 13 1 11 3 # S: C: C: O +23 16 3 1 11 18 # O: C: C: C +24 46 12 1 11 7 # Cl: C: C: P +25 32 13 1 11 7 # S: C: C: P +26 24 7 1 11 18 # P: C: C: C +27 21 14 11 13 1 # O: C: S: C +28 21 15 11 13 1 # O: C: S: C +29 21 16 11 13 1 # O: C: S: C +30 47 12 11 13 14 # Cl: C: S: O +31 47 12 11 13 15 # Cl: C: S: O +32 47 12 11 13 16 # Cl: C: S: O +33 21 14 11 13 18 # O: C: S: C +34 21 15 11 13 18 # O: C: S: C +35 21 16 11 13 18 # O: C: S: C +36 48 23 13 14 11 # Cl: S: O: C +37 49 23 13 14 15 # Cl: S: O: O +38 49 23 13 14 16 # Cl: S: O: O +39 15 22 13 15 11 # N: S: O: C +40 23 14 13 15 22 # O: S: O: N +41 23 16 13 15 22 # O: S: O: N +42 40 17 13 16 11 # Br: S: O: C +43 41 17 13 16 14 # Br: S: O: O +44 41 17 13 16 15 # Br: S: O: O +45 35 19 11 18 1 # Br: C: C: C +46 4 20 11 18 1 # F: C: C: C +47 1 1 11 18 21 # C: C: C: H +48 37 19 11 18 12 # Br: C: C:Cl +49 42 12 11 18 20 # Cl: C: C: F +50 43 12 11 18 21 # Cl: C: C: H +51 36 19 11 18 13 # Br: C: C: S +52 28 13 11 18 20 # S: C: C: F +53 29 13 11 18 21 # S: C: C: H +54 34 13 15 22 24 # S: O: N: P +55 33 13 15 22 25 # S: O: N: H +56 39 26 22 24 15 # Br: N: P: O +57 22 15 22 24 27 # O: N: P: H +58 22 15 22 24 28 # O: N: P: H +59 38 26 22 24 25 # Br: N: P: H +60 12 27 22 24 25 # H: N: P: H +61 12 28 22 24 25 # H: N: P: H diff --git a/testsuite/MDAnalysisTests/data/lammps/chain_dump_1.lammpstrj b/testsuite/MDAnalysisTests/data/lammps/chain_dump_1.lammpstrj new file mode 100644 index 00000000000..300909054c0 --- /dev/null +++ b/testsuite/MDAnalysisTests/data/lammps/chain_dump_1.lammpstrj @@ -0,0 +1,186 @@ +ITEM: TIMESTEP +0 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.88374 3.41791 0.249243 +10 0 2 0 5.19702 4.14267 2.35373 +13 0 2 0 3.42556 5.80345 1.03172 +16 0 2 0 0.0624761 8.72482 0.313035 +22 0 2 0 1.59082 3.31475 4.97774 +11 0 2 0 3.42477 4.70658 3.66179 +1 0 1 0 5.19899 5.00015 5.48947 +2 0 1 0 4.97794 4.97944 4.51567 +14 0 2 0 6.62547 4.95874 6.02809 +19 0 2 0 7.08926 4.30542 5.23948 +20 0 2 0 7.0361 5.90606 5.4861 +15 0 2 0 4.22366 9.62949 5.40626 +21 0 2 0 4.17191 8.57808 5.01616 +6 0 2 0 8.27587 8.45465 4.67567 +18 0 2 0 1.26168 1.6929 8.0355 +3 0 2 0 3.45325 5.51395 8.67997 +9 0 2 0 5.19513 5.29517 8.55806 +5 0 2 0 6.55796 3.99289 9.54127 +7 0 2 0 7.62242 6.3979 9.73197 +8 0 2 0 6.88523 4.51143 6.98553 +17 0 2 0 9.17665 6.50396 7.07893 +12 0 2 0 7.07863 9.62566 7.36101 +ITEM: TIMESTEP +1 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.87099 3.41767 0.251237 +10 0 2 0 5.17103 4.14373 2.36815 +13 0 2 0 3.43361 5.81743 1.05571 +16 0 2 0 0.0513171 8.713 0.28804 +22 0 2 0 1.5998 3.31559 4.97326 +11 0 2 0 3.42282 4.70176 3.65073 +1 0 1 0 5.20676 4.99743 5.47086 +2 0 1 0 4.9757 4.97824 4.51385 +14 0 2 0 6.6219 4.99337 6.05337 +19 0 2 0 7.12985 4.31467 5.24475 +20 0 2 0 7.03647 5.90326 5.48498 +15 0 2 0 4.22247 9.64286 5.3867 +21 0 2 0 4.17371 8.58414 5.00718 +6 0 2 0 8.25895 8.45456 4.65529 +18 0 2 0 1.24399 1.69158 8.02878 +3 0 2 0 3.44983 5.48966 8.7051 +9 0 2 0 5.18181 5.2815 8.56656 +5 0 2 0 6.56395 3.97275 9.5395 +7 0 2 0 7.61969 6.40413 9.72323 +8 0 2 0 6.88059 4.52138 6.98398 +17 0 2 0 9.19784 6.49329 7.08897 +12 0 2 0 7.1015 9.62409 7.37619 +ITEM: TIMESTEP +2 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.85828 3.41747 0.253186 +10 0 2 0 5.14503 4.14478 2.38259 +13 0 2 0 3.44167 5.83141 1.07969 +16 0 2 0 0.0401567 8.70118 0.263043 +22 0 2 0 1.60879 3.31643 4.96878 +11 0 2 0 3.4209 4.69695 3.63969 +1 0 1 0 5.21537 4.99476 5.45525 +2 0 1 0 4.97272 4.97698 4.50903 +14 0 2 0 6.61824 5.02819 6.07806 +19 0 2 0 7.17033 4.32411 5.2502 +20 0 2 0 7.03677 5.90027 5.48392 +15 0 2 0 4.22129 9.65621 5.36713 +21 0 2 0 4.17552 8.59021 4.9982 +6 0 2 0 8.24203 8.45447 4.63492 +18 0 2 0 1.2263 1.69026 8.02205 +3 0 2 0 3.44645 5.46536 8.73023 +9 0 2 0 5.16846 5.26782 8.57506 +5 0 2 0 6.56988 3.95258 9.53777 +7 0 2 0 7.61696 6.41036 9.71449 +8 0 2 0 6.87604 4.53115 6.98274 +17 0 2 0 9.21902 6.48262 7.09901 +12 0 2 0 7.12436 9.62251 7.39137 +ITEM: TIMESTEP +3 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.84563 3.41731 0.255081 +10 0 2 0 5.11902 4.14585 2.39703 +13 0 2 0 3.44973 5.8454 1.10368 +16 0 2 0 0.0289914 8.68935 0.238036 +22 0 2 0 1.61778 3.31727 4.9643 +11 0 2 0 3.41903 4.69215 3.62866 +1 0 1 0 5.22524 4.99218 5.44415 +2 0 1 0 4.96857 4.97562 4.49975 +14 0 2 0 6.61446 5.06321 6.10201 +19 0 2 0 7.21069 4.33378 5.25586 +20 0 2 0 7.03704 5.89714 5.48289 +15 0 2 0 4.2201 9.66953 5.34754 +21 0 2 0 4.17732 8.59631 4.98923 +6 0 2 0 8.2251 8.45438 4.61454 +18 0 2 0 1.2086 1.68893 8.01533 +3 0 2 0 3.44311 5.44105 8.75537 +9 0 2 0 5.15508 5.25413 8.58357 +5 0 2 0 6.57575 3.93237 9.53609 +7 0 2 0 7.61422 6.41659 9.70575 +8 0 2 0 6.87164 4.54066 6.98195 +17 0 2 0 9.24021 6.47194 7.10905 +12 0 2 0 7.14724 9.62094 7.40656 +ITEM: TIMESTEP +4 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.83303 3.41722 0.256909 +10 0 2 0 5.09298 4.14692 2.4115 +13 0 2 0 3.4578 5.85939 1.12768 +16 0 2 0 0.0178158 8.67751 0.213006 +22 0 2 0 1.62678 3.31812 4.95981 +11 0 2 0 3.4172 4.68734 3.61764 +1 0 1 0 5.23636 4.98968 5.43716 +2 0 1 0 4.9633 4.97418 4.48634 +14 0 2 0 6.61052 5.09848 6.12517 +19 0 2 0 7.25094 4.34369 5.26174 +20 0 2 0 7.0373 5.89391 5.48185 +15 0 2 0 4.21891 9.68281 5.32792 +21 0 2 0 4.17913 8.60247 4.98027 +6 0 2 0 8.20816 8.45428 4.59414 +18 0 2 0 1.19088 1.68761 8.0086 +3 0 2 0 3.43982 5.41671 8.78054 +9 0 2 0 5.14164 5.24043 8.59209 +5 0 2 0 6.58155 3.9121 9.53447 +7 0 2 0 7.61148 6.42282 9.69699 +8 0 2 0 6.86741 4.54983 6.98173 +17 0 2 0 9.26141 6.46124 7.1191 +12 0 2 0 7.17014 9.61936 7.42176 +ITEM: TIMESTEP +5 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.82049 3.41718 0.258662 +10 0 2 0 5.06689 4.148 2.42599 +13 0 2 0 3.46588 5.87339 1.15172 +16 0 2 0 0.00662379 8.66565 0.187939 +22 0 2 0 1.63579 3.31896 4.95531 +11 0 2 0 3.41541 4.68252 3.60661 +1 0 1 0 5.2482 4.98721 5.43226 +2 0 1 0 4.9574 4.9727 4.47085 +14 0 2 0 6.60634 5.13405 6.14753 +19 0 2 0 7.29111 4.35383 5.26782 +20 0 2 0 7.03759 5.89064 5.48076 +15 0 2 0 4.21772 9.69606 5.30825 +21 0 2 0 4.18095 8.6087 4.97131 +6 0 2 0 8.19119 8.45419 4.57372 +18 0 2 0 1.17314 1.68628 8.00186 +3 0 2 0 3.43657 5.39233 8.80574 +9 0 2 0 5.12815 5.2267 8.60064 +5 0 2 0 6.58727 3.89175 9.53293 +7 0 2 0 7.60873 6.42905 9.68822 +8 0 2 0 6.86339 4.55856 6.98215 +17 0 2 0 9.28264 6.45054 7.12917 +12 0 2 0 7.19307 9.61778 7.43698 diff --git a/testsuite/MDAnalysisTests/data/lammps/chain_dump_2.lammpstrj b/testsuite/MDAnalysisTests/data/lammps/chain_dump_2.lammpstrj new file mode 100644 index 00000000000..d6f905e7ab5 --- /dev/null +++ b/testsuite/MDAnalysisTests/data/lammps/chain_dump_2.lammpstrj @@ -0,0 +1,186 @@ +ITEM: TIMESTEP +5 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.82049 3.41718 0.258662 +10 0 2 0 5.06689 4.148 2.42599 +13 0 2 0 3.46588 5.87339 1.15172 +16 0 2 0 0.00662379 8.66565 0.187939 +22 0 2 0 1.63579 3.31896 4.95531 +11 0 2 0 3.41541 4.68252 3.60661 +1 0 1 0 5.2482 4.98721 5.43226 +2 0 1 0 4.9574 4.9727 4.47085 +14 0 2 0 6.60634 5.13405 6.14753 +19 0 2 0 7.29111 4.35383 5.26782 +20 0 2 0 7.03759 5.89064 5.48076 +15 0 2 0 4.21772 9.69606 5.30825 +21 0 2 0 4.18095 8.6087 4.97131 +6 0 2 0 8.19119 8.45419 4.57372 +18 0 2 0 1.17314 1.68628 8.00186 +3 0 2 0 3.43657 5.39233 8.80574 +9 0 2 0 5.12815 5.2267 8.60064 +5 0 2 0 6.58727 3.89175 9.53293 +7 0 2 0 7.60873 6.42905 9.68822 +8 0 2 0 6.86339 4.55856 6.98215 +17 0 2 0 9.28264 6.45054 7.12917 +12 0 2 0 7.19307 9.61778 7.43698 +ITEM: TIMESTEP +6 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.80802 3.41721 0.26033 +10 0 2 0 5.04074 4.14908 2.44053 +13 0 2 0 3.47398 5.88743 1.1758 +16 0 2 0 -0.00459111 8.65377 0.162823 +22 0 2 0 1.64483 3.31981 4.95081 +11 0 2 0 3.41365 4.6777 3.59557 +1 0 1 0 5.25992 4.98474 5.42653 +2 0 1 0 4.95174 4.97122 4.45619 +14 0 2 0 6.60185 5.16996 6.16913 +19 0 2 0 7.33123 4.3642 5.27408 +20 0 2 0 7.03795 5.88738 5.47956 +15 0 2 0 4.21652 9.70925 5.28851 +21 0 2 0 4.18277 8.61502 4.96236 +6 0 2 0 8.17419 8.45409 4.55326 +18 0 2 0 1.15536 1.68495 7.9951 +3 0 2 0 3.43337 5.3679 8.83099 +9 0 2 0 5.11459 5.21294 8.60921 +5 0 2 0 6.59289 3.87132 9.53146 +7 0 2 0 7.60598 6.4353 9.67943 +8 0 2 0 6.8596 4.56681 6.98327 +17 0 2 0 9.3039 6.43981 7.13925 +12 0 2 0 7.21605 9.61619 7.45223 +ITEM: TIMESTEP +7 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.79562 3.4173 0.261903 +10 0 2 0 5.0145 4.15018 2.45512 +13 0 2 0 3.48211 5.90149 1.19995 +16 0 2 0 -0.0158389 8.64186 0.137633 +22 0 2 0 1.65389 3.32066 4.94629 +11 0 2 0 3.41194 4.67287 3.58451 +1 0 1 0 5.27068 4.98223 5.41736 +2 0 1 0 4.94714 4.96978 4.44493 +14 0 2 0 6.597 5.20621 6.1901 +19 0 2 0 7.37133 4.37478 5.28052 +20 0 2 0 7.03842 5.8842 5.47816 +15 0 2 0 4.21532 9.72238 5.26869 +21 0 2 0 4.18461 8.62145 4.95342 +6 0 2 0 8.15714 8.45399 4.53274 +18 0 2 0 1.13753 1.68362 7.98832 +3 0 2 0 3.43021 5.34339 8.85631 +9 0 2 0 5.10096 5.19914 8.61781 +5 0 2 0 6.59842 3.85077 9.53009 +7 0 2 0 7.60322 6.44156 9.67061 +8 0 2 0 6.85602 4.57456 6.98507 +17 0 2 0 9.32523 6.42905 7.14936 +12 0 2 0 7.23909 9.6146 7.46752 +ITEM: TIMESTEP +8 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.78328 3.41747 0.263374 +10 0 2 0 4.98814 4.1513 2.46979 +13 0 2 0 3.49028 5.91562 1.2242 +16 0 2 0 -0.0271356 8.62989 0.112334 +22 0 2 0 1.663 3.32152 4.94174 +11 0 2 0 3.41027 4.66802 3.57342 +1 0 1 0 5.28003 4.97967 5.40346 +2 0 1 0 4.94408 4.96838 4.43834 +14 0 2 0 6.59174 5.24281 6.21061 +19 0 2 0 7.4115 4.38559 5.28712 +20 0 2 0 7.03906 5.88115 5.4765 +15 0 2 0 4.21411 9.73547 5.24876 +21 0 2 0 4.18645 8.628 4.94446 +6 0 2 0 8.14001 8.45389 4.51213 +18 0 2 0 1.11963 1.68228 7.98152 +3 0 2 0 3.4271 5.31878 8.88174 +9 0 2 0 5.08722 5.18528 8.62647 +5 0 2 0 6.60384 3.83008 9.52881 +7 0 2 0 7.60044 6.44784 9.66175 +8 0 2 0 6.85265 4.58182 6.98749 +17 0 2 0 9.34664 6.41824 7.15951 +12 0 2 0 7.26224 9.613 7.48288 +ITEM: TIMESTEP +9 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.771 3.4177 0.264737 +10 0 2 0 4.9616 4.15243 2.48456 +13 0 2 0 3.49849 5.92982 1.2486 +16 0 2 0 -0.0385029 8.61785 0.086878 +22 0 2 0 1.67216 3.32239 4.93717 +11 0 2 0 3.40863 4.66314 3.56226 +1 0 1 0 5.28808 4.97706 5.38536 +2 0 1 0 4.94242 4.96701 4.43585 +14 0 2 0 6.58603 5.27977 6.23089 +19 0 2 0 7.4518 4.39662 5.29387 +20 0 2 0 7.03991 5.87825 5.47449 +15 0 2 0 4.21289 9.74853 5.22867 +21 0 2 0 4.18831 8.63472 4.93548 +6 0 2 0 8.12277 8.45379 4.49139 +18 0 2 0 1.10161 1.68093 7.97467 +3 0 2 0 3.42402 5.29401 8.90732 +9 0 2 0 5.07335 5.17132 8.63518 +5 0 2 0 6.60916 3.8092 9.52764 +7 0 2 0 7.59765 6.45417 9.65284 +8 0 2 0 6.84947 4.58864 6.99047 +17 0 2 0 9.36818 6.40736 7.16973 +12 0 2 0 7.28552 9.61139 7.49833 +ITEM: TIMESTEP +10 +ITEM: NUMBER OF ATOMS +22 +ITEM: BOX BOUNDS pp pp pp +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +0.0000000000000000e+00 1.0000000000000000e+01 +ITEM: ATOMS id mol type q xu yu zu +4 0 2 0 5.75876 3.41802 0.265988 +10 0 2 0 4.93482 4.15358 2.49947 +13 0 2 0 3.50678 5.94414 1.2732 +16 0 2 0 -0.0499635 8.60572 0.0612139 +22 0 2 0 1.68141 3.32326 4.93257 +11 0 2 0 3.40704 4.65822 3.55103 +1 0 1 0 5.29558 4.97443 5.36518 +2 0 1 0 4.94144 4.96564 4.4353 +14 0 2 0 6.57985 5.31706 6.25115 +19 0 2 0 7.49234 4.4079 5.30078 +20 0 2 0 7.041 5.87553 5.47208 +15 0 2 0 4.21165 9.76157 5.20839 +21 0 2 0 4.19018 8.64161 4.92646 +6 0 2 0 8.1054 8.45368 4.47049 +18 0 2 0 1.08345 1.67958 7.96777 +3 0 2 0 3.42098 5.26903 8.93311 +9 0 2 0 5.05932 5.15725 8.64398 +5 0 2 0 6.61438 3.78809 9.52658 +7 0 2 0 7.59483 6.46054 9.64385 +8 0 2 0 6.84642 4.59509 6.99388 +17 0 2 0 9.3899 6.39639 7.18003 +12 0 2 0 7.309 9.60977 7.51391 diff --git a/testsuite/MDAnalysisTests/data/lammps/chain_initial.data b/testsuite/MDAnalysisTests/data/lammps/chain_initial.data new file mode 100644 index 00000000000..f5fc04e7cac --- /dev/null +++ b/testsuite/MDAnalysisTests/data/lammps/chain_initial.data @@ -0,0 +1,78 @@ +LAMMPS data file via write_data, version 30 Jul 2021, timestep = 0 + +22 atoms +2 atom types +1 bonds +1 bond types + +0 10 xlo xhi +0 10 ylo yhi +0 10 zlo zhi + +Masses + +1 1 +2 1 + +Pair Coeffs # lj/cut + +1 1 1 +2 1 1 + +Bond Coeffs # harmonic + +1 1000 1 + +Atoms # full + +4 0 2 0 5.883740014805435 3.4179109354590804 0.24924286058641165 0 0 0 +10 0 2 0 5.197015196461036 4.142670556288421 2.353726151705203 0 0 0 +13 0 2 0 3.4255611285133267 5.803452070538761 1.031722991669274 0 0 0 +16 0 2 0 0.062476149254058554 8.724819406439591 0.31303480449240967 0 0 0 +22 0 2 0 1.5908211403175816 3.314754844382107 4.977739896776302 0 0 0 +11 0 2 0 3.424765092918008 4.706577781408797 3.661788275287658 0 0 0 +1 0 1 0 5.198991972049708 5.000151164651573 5.489469948645906 0 0 0 +2 0 1 0 4.977944755383636 4.979439231068392 4.515671261808374 0 0 0 +14 0 2 0 6.625473870892448 4.958741001742174 6.028090349925399 0 0 0 +19 0 2 0 7.0892589199131 4.3054178493503095 5.239481480901857 0 0 0 +20 0 2 0 7.036104530790973 5.906057579268762 5.486102918822923 0 0 0 +15 0 2 0 4.223656722003392 9.629493461794167 5.406260861415652 0 0 0 +21 0 2 0 4.171908135414807 8.578083005413488 5.016164227356318 0 0 0 +6 0 2 0 8.275867208937644 8.454650609100012 4.6756651150995525 0 0 0 +18 0 2 0 1.2616827540211895 1.6929043853399965 8.035498383807296 0 0 0 +3 0 2 0 3.4532547038183803 5.513947457637427 8.679969313168533 0 0 0 +9 0 2 0 5.195132811898448 5.29516718448986 8.55806411296179 0 0 0 +5 0 2 0 6.557959186170065 3.9928856347618593 9.541271333406879 0 0 0 +7 0 2 0 7.622424406139167 6.397902195984017 9.731973643509342 0 0 0 +8 0 2 0 6.885234927302157 4.511429989177588 6.9855314363826535 0 0 0 +17 0 2 0 9.17665431960683 6.503964175144789 7.078934920317938 0 0 0 +12 0 2 0 7.07862885024416 9.625664231829576 7.361010319462491 0 0 0 + +Velocities + +4 -1.276660702504741 -0.026070411269423915 0.20108568802782487 +10 -2.5983566504504765 0.10526434391058373 1.442584513910767 +13 0.8050400413759953 1.398345394013117 2.398536219936858 +16 -1.1158865606286625 -1.1821133354613182 -2.499434382708754 +22 0.8980591872307232 0.08370783310298346 -0.44786472491418416 +11 -0.19695107307522597 -0.4814905381733622 -1.106304258876651 +1 0.7672584780901935 -0.27255549656041417 -1.8752091760718599 +2 -0.22113345674134757 -0.11908410141898773 -0.16990285243504102 +14 -0.3524431166553481 3.4510098598708447 2.546224330608433 +19 4.060319718410092 0.9206794154596835 0.5242942388931888 +20 0.039770587191395416 -0.2683837933674185 -0.11610400752187681 +15 -0.11842474401551648 1.336573059903346 -1.956240492935761 +21 0.18027081378915846 0.6053446724530571 -0.8984297600447511 +6 -1.6916803937384872 -0.008959901625246826 -2.0373059484516585 +18 -1.7692400294198856 -0.13234083957401252 -0.6721560749126162 +3 -0.3448513290315931 -2.428793821423444 2.5125747483397625 +9 -1.3303472717010782 -1.3667979529855936 0.8489569057185709 +5 0.6007884969188944 -2.01299620355339 -0.17850044666911968 +7 -0.2731151684439193 0.6231270095132168 -0.8738141678022208 +8 -0.46768519907928785 1.0002004184521291 -0.1650167734587818 +17 2.118599875619805 -1.0672456725498713 1.0039088013137925 +12 2.286668496859314 -0.15741993871647506 1.5181176200540754 + +Bonds + +1 1 1 2 diff --git a/testsuite/MDAnalysisTests/datafiles.py b/testsuite/MDAnalysisTests/datafiles.py index 1bb0e0db1b0..caedb9a540c 100644 --- a/testsuite/MDAnalysisTests/datafiles.py +++ b/testsuite/MDAnalysisTests/datafiles.py @@ -144,6 +144,7 @@ "LAMMPSdata2", "LAMMPSdcd2", "LAMMPScnt", "LAMMPScnt2", # triclinic box "LAMMPShyd", "LAMMPShyd2", + "LAMMPSdata_many_bonds", "LAMMPSdata_deletedatoms", # with deleted atoms "LAMMPSdata_triclinic", # lammpsdata file to test triclinic dimension parsing, albite with most atoms deleted "LAMMPSdata_PairIJ", # lammps datafile with a PairIJ Coeffs section @@ -154,6 +155,9 @@ "LAMMPSDUMP_triclinic", # lammpsdump file to test triclinic dimension parsing, albite with most atoms deleted "LAMMPSDUMP_image_vf", # Lammps dump file with image flags, velocities, and forces. "LAMMPS_image_vf", # Lammps data file to go with LAMMPSDUMP_image_vf + "LAMMPSDUMP_chain1", # Lammps dump file with chain reader + "LAMMPSDUMP_chain2", # Lammps dump file with chain reader + "LAMMPS_chain", # Lammps data file with chain reader "unordered_res", # pdb file with resids non sequential "GMS_ASYMOPT", # GAMESS C1 optimization "GMS_SYMOPT", # GAMESS D4h optimization @@ -526,6 +530,10 @@ LAMMPSDUMP_triclinic = (_data_ref / "lammps/albite_triclinic.dump").as_posix() LAMMPSDUMP_image_vf = (_data_ref / "lammps/image_vf.lammpstrj").as_posix() LAMMPS_image_vf = (_data_ref / "lammps/image_vf.data").as_posix() +LAMMPSDUMP_chain1 = (_data_ref / "lammps/chain_dump_1.lammpstrj").as_posix() +LAMMPSDUMP_chain2 = (_data_ref / "lammps/chain_dump_2.lammpstrj").as_posix() +LAMMPS_chain = (_data_ref / "lammps/chain_initial.data").as_posix() +LAMMPSdata_many_bonds = (_data_ref / "lammps/a_lot_of_bond_types.data").as_posix() unordered_res = (_data_ref / "unordered_res.pdb").as_posix() diff --git a/testsuite/MDAnalysisTests/lib/test_util.py b/testsuite/MDAnalysisTests/lib/test_util.py index e3fb4f7b93d..3a2414b47ee 100644 --- a/testsuite/MDAnalysisTests/lib/test_util.py +++ b/testsuite/MDAnalysisTests/lib/test_util.py @@ -312,7 +312,8 @@ def ref_trivecs_unsafe(self, box): ref[1, 1] = y * sin_c ref[2, 0] = z * cos_b ref[2, 1] = z * (cos_a - cos_b * cos_c) / sin_c - ref[2, 2] = np.sqrt(z * z - ref[2, 0] ** 2 - ref[2, 1] ** 2) + with np.errstate(invalid="ignore"): + ref[2, 2] = np.sqrt(z * z - ref[2, 0] ** 2 - ref[2, 1] ** 2) ref = ref.astype(np.float32) return ref diff --git a/testsuite/MDAnalysisTests/parallelism/test_multiprocessing.py b/testsuite/MDAnalysisTests/parallelism/test_multiprocessing.py index 4df5c8d0938..638132d457c 100644 --- a/testsuite/MDAnalysisTests/parallelism/test_multiprocessing.py +++ b/testsuite/MDAnalysisTests/parallelism/test_multiprocessing.py @@ -32,6 +32,7 @@ import MDAnalysis as mda import MDAnalysis.coordinates from MDAnalysis.coordinates.core import get_reader_for +from MDAnalysis.coordinates.GSD import HAS_GSD from MDAnalysis.analysis.rms import RMSD from MDAnalysisTests.datafiles import ( @@ -73,7 +74,10 @@ (XYZ_bz2,), # .bz2 (GMS_SYMOPT,), # .gms (GMS_ASYMOPT,), # .gz - (GSD_long,), + pytest.param( + (GSD_long,), + marks=pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') + ), (NCDF,), (np.arange(150).reshape(5, 10, 3).astype(np.float64),), (GRO, [GRO, GRO, GRO, GRO, GRO]), @@ -171,7 +175,10 @@ def test_creating_multiple_universe_without_offset(temp_xtc, ncopies=3): ('LAMMPSDUMP', LAMMPSDUMP, dict()), ('GMS', GMS_ASYMOPT, dict()), ('GRO', GRO, dict()), - ('GSD', GSD, dict()), + pytest.param( + ('GSD', GSD, dict()), + marks=pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') + ), ('MMTF', MMTF, dict()), ('MOL2', mol2_molecules, dict()), ('PDB', PDB_small, dict()), diff --git a/testsuite/MDAnalysisTests/topology/test_gsd.py b/testsuite/MDAnalysisTests/topology/test_gsd.py index 10a345750e9..41c3cb8b81d 100644 --- a/testsuite/MDAnalysisTests/topology/test_gsd.py +++ b/testsuite/MDAnalysisTests/topology/test_gsd.py @@ -23,6 +23,7 @@ import pytest import MDAnalysis as mda +from MDAnalysis.topology.GSDParser import HAS_GSD from MDAnalysisTests.topology.base import ParserBase from MDAnalysisTests.datafiles import GSD @@ -30,6 +31,8 @@ from numpy.testing import assert_equal import os + +@pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') class GSDBase(ParserBase): parser = mda.topology.GSDParser.GSDParser expected_attrs = ['ids', 'names', 'resids', 'resnames', 'masses', @@ -78,14 +81,15 @@ def test_impropers(self, top): assert top.impropers.values == [] +@pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') class TestGSDParser(GSDBase): ref_filename = GSD expected_n_atoms = 5832 expected_n_residues = 648 expected_n_segments = 1 - +@pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') class TestGSDParserBonds(GSDBase): ref_filename = GSD_bonds expected_n_atoms = 490 diff --git a/testsuite/MDAnalysisTests/utils/test_pickleio.py b/testsuite/MDAnalysisTests/utils/test_pickleio.py index de8f2af8ca4..d26de0aa258 100644 --- a/testsuite/MDAnalysisTests/utils/test_pickleio.py +++ b/testsuite/MDAnalysisTests/utils/test_pickleio.py @@ -38,7 +38,8 @@ ) from MDAnalysis.coordinates.GSD import ( GSDPicklable, - gsd_pickle_open + gsd_pickle_open, + HAS_GSD ) from MDAnalysis.coordinates.TRJ import ( NCDFPicklable, @@ -161,13 +162,15 @@ def test_pickle_with_write_mode(unpicklable_f, tmpdir): f_pickled = pickle.loads(pickle.dumps(f_open_by_class)) +@pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') def test_GSD_pickle(): - gsd_io = gsd_pickle_open(GSD, mode='rb') + gsd_io = gsd_pickle_open(GSD, mode='r') gsd_io_pickled = pickle.loads(pickle.dumps(gsd_io)) assert_equal(gsd_io[0].particles.position, gsd_io_pickled[0].particles.position) +@pytest.mark.skipif(not HAS_GSD, reason='gsd not installed') def test_GSD_with_write_mode(tmpdir): with pytest.raises(ValueError, match=r"Only read mode"): gsd_io = gsd_pickle_open(tmpdir.mkdir("gsd").join('t.gsd'), diff --git a/testsuite/MDAnalysisTests/utils/test_units.py b/testsuite/MDAnalysisTests/utils/test_units.py index 9545e3a3c7c..41373fb41ec 100644 --- a/testsuite/MDAnalysisTests/utils/test_units.py +++ b/testsuite/MDAnalysisTests/utils/test_units.py @@ -51,7 +51,7 @@ class TestConstants(object): ('N_Avogadro', 6.02214129e+23), # mol**-1 ('elementary_charge', 1.602176565e-19), # As ('calorie', 4.184), # J - ('Boltzman_constant', 8.314462159e-3), # KJ (mol K)**-1 + ('Boltzmann_constant', 8.314462159e-3), # KJ (mol K)**-1 ('electric_constant', 5.526350e-3), # As (Angstroms Volts)**-1 )