diff --git a/.github/actions/setup-deps/action.yaml b/.github/actions/setup-deps/action.yaml index 7523214b8fa..7f40ec146ad 100644 --- a/.github/actions/setup-deps/action.yaml +++ b/.github/actions/setup-deps/action.yaml @@ -74,6 +74,8 @@ inputs: default: 'networkx' openmm: default: 'openmm' + pooch: + default: 'pooch' pytng: default: 'pytng>=0.2.3' rdkit: @@ -145,6 +147,7 @@ runs: ${{ inputs.netcdf4 }} ${{ inputs.networkx }} ${{ inputs.openmm }} + ${{ inputs.pooch }} ${{ inputs.pytng }} ${{ inputs.rdkit }} ${{ inputs.scikit-learn }} diff --git a/.gitignore b/.gitignore index ed6eebde889..3ef0b03a60f 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,5 @@ benchmarks/results .idea .vscode *.lock +venv/ +package/doc/sphinx/_build/ \ No newline at end of file diff --git a/benchmarks/benchmarks/ag_methods.py b/benchmarks/benchmarks/ag_methods.py index 7909b425891..fe50ed3f529 100644 --- a/benchmarks/benchmarks/ag_methods.py +++ b/benchmarks/benchmarks/ag_methods.py @@ -195,6 +195,7 @@ def time_wrap_compound(self, num_atoms): """ self.ag.wrap(compound="residues") + class AtomGroupAttrsBench(object): """Benchmarks for the various MDAnalysis atomgroup attributes. diff --git a/benchmarks/benchmarks/analysis/msd.py b/benchmarks/benchmarks/analysis/msd.py new file mode 100644 index 00000000000..b4a1f596911 --- /dev/null +++ b/benchmarks/benchmarks/analysis/msd.py @@ -0,0 +1,85 @@ +""" +Benchmarks for the EinsteinMSD analysis module. +""" + +import numpy as np +import MDAnalysis as mda +from MDAnalysis.analysis import msd +from MDAnalysis.tests.datafiles import RANDOM_WALK_TOPO, RANDOM_WALK + + +class EinsteinMSDCustom: + """ + Benchmark for Mean-Squared Displacement (EinsteinMSD). + + The trajectory is created by using random forces + that are generated from a normal distribution + and then cumulatively summed to simulate a real random walk. + """ + + unit = "ms" + description = ( + "Performance of EinsteinMSD calculation using " + "custom n_atoms and range of n_frames." + ) + + timeout = 300.0 + + param_names = ["n_frames", "fft"] + params = ([100, 1000, 5000], [True, False]) + + def setup(self, n_frames, fft): + """Setup method for MSD benchmark with custom number of frames.""" + n_atoms = 100 + + rng = np.random.default_rng(42) + + # Random forces are sampled from a normal distribution + steps = rng.standard_normal((n_frames, n_atoms, 3), dtype=np.float32) + + # Cumulative sum is taken to simulate positions over time + res = np.cumsum(steps, axis=0) + + self.u = mda.Universe.empty(n_atoms, n_frames=n_frames, trajectory=True) + self.u.trajectory.set_array(res) + + def time_msd_run_custom(self, n_frames, fft): + """ + Benchmark calculation of Mean-Squared Displacement + using a custom trajectory. + """ + msd_var = msd.EinsteinMSD(self.u, select="all", fft=fft) + msd_var.run() + + +class EinsteinMSDExample: + """ + Benchmark for Mean-Squared Displacement (EinsteinMSD) + using the RANDOM_WALK example trajectory provided in the MDAnalysis testsuite. + + The files for the trajectory can be found in the library at : + RANDOM_WALK - mdanalysis/testsuite/xyz_random_walk.xtc + RANDOM_WALK_TOPO - mdanalysis/testsuite/RANDOM_WALK_TOPO.pdb + """ + + unit = "ms" + description = ( + "Performance of EinsteinMSD calculation using RANDOM_WALK_TOPO and RANDOM_WALK" + ) + + timeout = 300.0 + + param_names = ["fft"] + params = [True, False] + + def setup(self, fft): + """Setup method for MSD benchmark with RANDOM_WALK example.""" + self.u = mda.Universe(RANDOM_WALK_TOPO, RANDOM_WALK) + + def time_msd_run_simple(self, fft): + """ + Benchmark calculation of Mean-Squared Displacement + using the example trajectory RANDOM_WALK. + """ + msd_var = msd.EinsteinMSD(self.u, fft=fft) + msd_var.run() diff --git a/benchmarks/benchmarks/analysis/rdf.py b/benchmarks/benchmarks/analysis/rdf.py index 077f60906ce..38c8c3631e8 100644 --- a/benchmarks/benchmarks/analysis/rdf.py +++ b/benchmarks/benchmarks/analysis/rdf.py @@ -40,6 +40,7 @@ def time_interrdf(self, nbins, range_val, natoms): """ self.rdf.run() + class SimpleRdfsBench(object): """Benchmarks for MDAnalysis.analysis.rdf.InterRDF_s""" @@ -61,9 +62,8 @@ def setup(self, nbins, range_val, natoms, npairs): ags = [[self.sel, self.sel]] * npairs self.rdf_s = InterRDF_s(self.u, ags, nbins=nbins, range=range_val) - def time_interrdfs(self, nbins, range_val, natoms, npairs): """Benchmark a full trajectory parse by MDAnalysis.analysis.rdf.InterRDF_s """ - self.rdf_s.run() \ No newline at end of file + self.rdf_s.run() diff --git a/benchmarks/benchmarks/analysis/rms.py b/benchmarks/benchmarks/analysis/rms.py index 80afc15f18b..2f5b91f3994 100644 --- a/benchmarks/benchmarks/analysis/rms.py +++ b/benchmarks/benchmarks/analysis/rms.py @@ -28,7 +28,9 @@ def setup(self, num_atoms, use_weights, center, superposition): self.u.trajectory[-1] self.B = self.u.atoms.positions.copy()[:num_atoms] self.atoms = self.u.atoms[:num_atoms] - self.weights = self.atoms.masses/np.sum(self.atoms.masses) if use_weights else None + self.weights = ( + self.atoms.masses / np.sum(self.atoms.masses) if use_weights else None + ) def time_rmsd(self, num_atoms, weights, center, superposition): """Benchmark rmsd function using a setup similar to diff --git a/maintainer/update_json_stubs_sitemap.py b/maintainer/update_json_stubs_sitemap.py index 9ba36745141..e9c8cf3488e 100644 --- a/maintainer/update_json_stubs_sitemap.py +++ b/maintainer/update_json_stubs_sitemap.py @@ -59,15 +59,13 @@ def write_redirect(file, version="", outfile=None): if outfile is None: outfile = file url = os.path.join(URL, version, file) - REDIRECT = textwrap.dedent( - f""" + REDIRECT = textwrap.dedent(f""" Redirecting to {url} - """ - ) + """) with open(outfile, "w") as f: f.write(REDIRECT) print(f"Wrote redirect from {url} to {outfile}") diff --git a/package/AUTHORS b/package/AUTHORS index 19b86530505..a799200bf50 100644 --- a/package/AUTHORS +++ b/package/AUTHORS @@ -273,6 +273,8 @@ Chronological list of authors - Kushagar Garg - Jeremy M. G. Leung - Harshit Gajjela + - Kunj Sinha + - Ayush Agarwal External code ------------- diff --git a/package/CHANGELOG b/package/CHANGELOG index ad5e8522a8f..790bbbe80ff 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -16,11 +16,12 @@ The rules for this file: ------------------------------------------------------------------------------- ??/??/?? IAlibay, orbeckst, marinegor, tylerjereddy, ljwoods2, marinegor, spyke7, talagayev, tanii1125, BradyAJohnston, hejamu, jeremyleung521, - harshitgajjela-droid + harshitgajjela-droid, kunjsinha, aygarwal, jauy123 * 2.11.0 Fixes + * Fixes TypeError with np.int64 indexing in GSD Reader (Issue #5224) * Fixed bug in add_transformations allowing non-callable transformations (Issue #2558, PR #2558) * Drop/Replace lock file test in test_xdr (Issue #5236, PR #5237) @@ -41,6 +42,10 @@ Fixes DSSP by porting upstream PyDSSP 0.9.1 fix (Issue #4913) Enhancements + * Added new top-level `MDAnalysis.fetch` module (PR #4943) + * Added new function `MDAnalysis.fetch.from_PDB` to download structure files from wwPDB + using `pooch` as optional dependency (Issue #4907, PR #4943) + * Added benchmarks for package.MDAnalysis.analysis.msd.EinsteinMSD (PR #5277) * Improved performance of `AtomGroup.wrap()` with compounds (PR #5220) * Adds support for parsing `.tpr` files produced by GROMACS 2026.0 * Enables parallelization for analysis.diffusionmap.DistanceMatrix diff --git a/package/MDAnalysis/__init__.py b/package/MDAnalysis/__init__.py index 6843c3738ab..b6b2ecaf58b 100644 --- a/package/MDAnalysis/__init__.py +++ b/package/MDAnalysis/__init__.py @@ -48,10 +48,10 @@ When using MDAnalysis in published work, please cite R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler, - D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein. - MDAnalysis: A Python package for the rapid analysis of molecular dynamics - simulations. In S. Benthall and S. Rostrup, editors, Proceedings of the 15th - Python in Science Conference, pages 98-105, Austin, TX, 2016. SciPy, + D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein. + MDAnalysis: A Python package for the rapid analysis of molecular dynamics + simulations. In S. Benthall and S. Rostrup, editors, Proceedings of the 15th + Python in Science Conference, pages 98-105, Austin, TX, 2016. SciPy, doi:10.25080/majora-629e541a-00e N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and @@ -156,7 +156,6 @@ import warnings from typing import Dict - logger = logging.getLogger("MDAnalysis.__init__") from .version import __version__ @@ -179,9 +178,7 @@ _CONVERTERS: Dict = {} # Registry of TopologyAttributes _TOPOLOGY_ATTRS: Dict = {} # {attrname: cls} -_TOPOLOGY_TRANSPLANTS: Dict = ( - {} -) # {name: [attrname, method, transplant class]} +_TOPOLOGY_TRANSPLANTS: Dict = {} # {name: [attrname, method, transplant class]} _TOPOLOGY_ATTRNAMES: Dict = {} # {lower case name w/o _ : name} _GUESSERS: Dict = {} @@ -204,9 +201,7 @@ del logging # only MDAnalysis DeprecationWarnings are loud by default -warnings.filterwarnings( - action="once", category=DeprecationWarning, module="MDAnalysis" -) +warnings.filterwarnings(action="once", category=DeprecationWarning, module="MDAnalysis") from . import units diff --git a/package/MDAnalysis/analysis/align.py b/package/MDAnalysis/analysis/align.py index 3dc4f84fb1d..f976d31628b 100644 --- a/package/MDAnalysis/analysis/align.py +++ b/package/MDAnalysis/analysis/align.py @@ -89,7 +89,7 @@ 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, + >>> rmsd(mobile.select_atoms('name CA').positions, ref.select_atoms('name CA').positions, ... superposition=True) 6.809396586471815 @@ -138,7 +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 @@ -190,6 +190,7 @@ .. autofunction:: get_matching_atoms """ + import os.path import warnings import logging @@ -361,9 +362,7 @@ def _fit_to( where :math:`\bar{X}` is the center. """ - R, min_rmsd = rotation_matrix( - mobile_coordinates, ref_coordinates, weights=weights - ) + R, min_rmsd = rotation_matrix(mobile_coordinates, ref_coordinates, weights=weights) mobile_atoms.translate(-mobile_com) mobile_atoms.rotate(R) @@ -845,8 +844,7 @@ def __init__( if os.path.exists(filename) and not force: raise IOError( - "Filename already exists in path and force is not set" - " to True" + "Filename already exists in path and force is not set" " to True" ) # do this after setting the memory reader to have a reference to the @@ -1092,9 +1090,7 @@ def __init__( ) logger.exception(err) raise SelectionError(err) - logger.info( - "RMS calculation " "for {0:d} atoms.".format(len(self.ref_atoms)) - ) + logger.info("RMS calculation " "for {0:d} atoms.".format(len(self.ref_atoms))) # store reference to mobile atoms self.mobile = mobile.atoms @@ -1155,9 +1151,7 @@ def _single_frame(self): def _conclude(self): self.results.positions /= self.n_frames self.results.rmsd /= self.n_frames - self.results.universe.load_new( - self.results.positions.reshape((1, -1, 3)) - ) + self.results.universe.load_new(self.results.positions.reshape((1, -1, 3))) self._writer.write(self.results.universe.atoms) self._writer.close() if not self._verbose: @@ -1465,26 +1459,18 @@ def fasta2select( stdout, stderr = run_clustalw() except: logger.exception("ClustalW %(clustalw)r failed", vars()) - logger.info( - "(You can get clustalw2 from http://www.clustal.org/clustal2/)" - ) + logger.info("(You can get clustalw2 from http://www.clustal.org/clustal2/)") raise with open(alnfilename) as aln: alignment = Bio.AlignIO.read(aln, "clustal") + logger.info("Using clustalw sequence alignment {0!r}".format(alnfilename)) logger.info( - "Using clustalw sequence alignment {0!r}".format(alnfilename) - ) - logger.info( - "ClustalW Newick guide tree was also produced: {0!r}".format( - treefilename - ) + "ClustalW Newick guide tree was also produced: {0!r}".format(treefilename) ) nseq = len(alignment) if nseq != 2: - raise ValueError( - "Only two sequences in the alignment can be processed." - ) + raise ValueError("Only two sequences in the alignment can be processed.") # implict assertion that we only have two sequences in the alignment orig_resids = [ref_resids, target_resids] @@ -1500,9 +1486,7 @@ def fasta2select( else: orig_resids[iseq] = np.asarray(orig_resids[iseq]) # add offsets to the sequence <--> resid translation table - seq2resids = [ - resids + offset for resids, offset in zip(orig_resids, offsets) - ] + seq2resids = [resids + offset for resids, offset in zip(orig_resids, offsets)] del orig_resids del offsets @@ -1773,9 +1757,7 @@ def get_atoms_byres(g, match_mask=None): warnings.warn(msg, category=SelectionWarning) else: try: - mass_mismatches = ( - np.absolute(ag1.masses - ag2.masses) > tol_mass - ) + mass_mismatches = np.absolute(ag1.masses - ag2.masses) > tol_mass except ValueError: errmsg = ( "Failed to find matching atoms: len(reference) = {}, len(mobile) = {} " diff --git a/package/MDAnalysis/analysis/atomicdistances.py b/package/MDAnalysis/analysis/atomicdistances.py index 71292bed0d7..5cf15128d8b 100644 --- a/package/MDAnalysis/analysis/atomicdistances.py +++ b/package/MDAnalysis/analysis/atomicdistances.py @@ -150,16 +150,12 @@ class AtomicDistances(AnalysisBase): def __init__(self, ag1, ag2, pbc=True, **kwargs): # check ag1 and ag2 have the same number of atoms if ag1.atoms.n_atoms != ag2.atoms.n_atoms: - raise ValueError( - "AtomGroups do not " "have the same number of atoms" - ) + raise ValueError("AtomGroups do not " "have the same number of atoms") # check ag1 and ag2 are from the same trajectory elif ag1.universe.trajectory != ag2.universe.trajectory: raise ValueError("AtomGroups are not " "from the same trajectory") - super(AtomicDistances, self).__init__( - ag1.universe.trajectory, **kwargs - ) + super(AtomicDistances, self).__init__(ag1.universe.trajectory, **kwargs) self._ag1 = ag1 self._ag2 = ag2 diff --git a/package/MDAnalysis/analysis/base.py b/package/MDAnalysis/analysis/base.py index f18b866951f..2447be55e66 100644 --- a/package/MDAnalysis/analysis/base.py +++ b/package/MDAnalysis/analysis/base.py @@ -122,7 +122,7 @@ class MyAnalysis(AnalysisBase): def get_supported_backends(cls): return ('serial', 'multiprocessing', 'dask',) - + def _get_aggregator(self): return ResultsGroup(lookup={'timeseries': ResultsGroup.ndarray_vstack}) @@ -147,6 +147,7 @@ def _get_aggregator(self): tools if only the single-frame analysis function needs to be written. """ + import inspect import itertools import logging @@ -387,14 +388,10 @@ def _define_run_frames( self._trajectory = trajectory if frames is not None: if not all(opt is None for opt in [start, stop, step]): - raise ValueError( - "start/stop/step cannot be combined with frames" - ) + raise ValueError("start/stop/step cannot be combined with frames") slicer = frames else: - start, stop, step = trajectory.check_slice_indices( - start, stop, step - ) + start, stop, step = trajectory.check_slice_indices(start, stop, step) slicer = slice(start, stop, step) self.start, self.stop, self.step = start, stop, step return slicer @@ -417,9 +414,7 @@ def _prepare_sliced_trajectory(self, slicer: Union[slice, np.ndarray]): self.frames = np.zeros(self.n_frames, dtype=int) self.times = np.zeros(self.n_frames) - def _setup_frames( - self, trajectory, start=None, stop=None, step=None, frames=None - ): + def _setup_frames(self, trajectory, start=None, stop=None, step=None, frames=None): """Pass a Reader object and define the desired iteration pattern through the trajectory @@ -539,9 +534,7 @@ def _compute( progressbar_kwargs = {} logger.info("Choosing frames to analyze") # if verbose unchanged, use class default - verbose = ( - getattr(self, "_verbose", False) if verbose is None else verbose - ) + verbose = getattr(self, "_verbose", False) if verbose is None else verbose frames = indexed_frames[:, 1] @@ -552,9 +545,7 @@ def _compute( return self for idx, ts in enumerate( - ProgressBar( - self._sliced_trajectory, verbose=verbose, **progressbar_kwargs - ) + ProgressBar(self._sliced_trajectory, verbose=verbose, **progressbar_kwargs) ): self._frame_index = idx # accessed later by subclasses self._ts = ts @@ -607,9 +598,7 @@ def _setup_computation_groups( .. versionadded:: 2.8.0 """ if frames is None: - start, stop, step = self._trajectory.check_slice_indices( - start, stop, step - ) + start, stop, step = self._trajectory.check_slice_indices(start, stop, step) used_frames = np.arange(start, stop, step) elif not all(opt is None for opt in [start, stop, step]): raise ValueError("start/stop/step cannot be combined with frames") @@ -621,9 +610,7 @@ def _setup_computation_groups( used_frames = arange[used_frames] # similar to list(enumerate(frames)) - enumerated_frames = np.vstack( - [np.arange(len(used_frames)), used_frames] - ).T + enumerated_frames = np.vstack([np.arange(len(used_frames)), used_frames]).T if len(enumerated_frames) == 0: return [np.empty((0, 2), dtype=np.int64)] elif len(enumerated_frames) < n_parts: @@ -745,9 +732,7 @@ def _configure_backend( # or pass along an instance of the class itself # after ensuring it has apply method - if not isinstance(backend, BackendBase) or not hasattr( - backend, "apply" - ): + if not isinstance(backend, BackendBase) or not hasattr(backend, "apply"): raise ValueError( ( f"{backend=} is invalid: should have 'apply' method " @@ -835,23 +820,18 @@ def run( # default to serial execution backend = "serial" if backend is None else backend - progressbar_kwargs = ( - {} if progressbar_kwargs is None else progressbar_kwargs - ) + progressbar_kwargs = {} if progressbar_kwargs is None else progressbar_kwargs if (progressbar_kwargs or verbose) and not ( backend == "serial" or isinstance(backend, BackendSerial) ): - raise ValueError( - "Can not display progressbar with non-serial backend" - ) + raise ValueError("Can not display progressbar with non-serial backend") # if number of workers not specified, try getting the number from # the backend instance if possible, or set to 1 if n_workers is None: n_workers = ( backend.n_workers - if isinstance(backend, BackendBase) - and hasattr(backend, "n_workers") + if isinstance(backend, BackendBase) and hasattr(backend, "n_workers") else 1 ) @@ -1016,9 +996,7 @@ def _get_aggregator(self): return ResultsGroup({"timeseries": ResultsGroup.flatten_sequence}) def _single_frame(self): - self.results.timeseries.append( - self.function(*self.args, **self.kwargs) - ) + self.results.timeseries.append(self.function(*self.args, **self.kwargs)) def _conclude(self): self.results.frames = self.frames @@ -1079,9 +1057,7 @@ def RotationMatrix(mobile, ref): class WrapperClass(AnalysisFromFunction): def __init__(self, trajectory=None, *args, **kwargs): - super(WrapperClass, self).__init__( - function, trajectory, *args, **kwargs - ) + super(WrapperClass, self).__init__(function, trajectory, *args, **kwargs) @classmethod def get_supported_backends(cls): diff --git a/package/MDAnalysis/analysis/bat.py b/package/MDAnalysis/analysis/bat.py index 9b08c7dbff4..33f09616231 100644 --- a/package/MDAnalysis/analysis/bat.py +++ b/package/MDAnalysis/analysis/bat.py @@ -157,6 +157,7 @@ class to calculate dihedral angles for a given set of atoms or residues .. footbibliography:: """ + import logging import warnings @@ -216,9 +217,7 @@ def _find_torsions(root, atoms): for a1 in selected_atoms: # Find a0, which is a new atom connected to the selected atom a0_list = _sort_atoms_by_mass( - a - for a in a1.bonded_atoms - if (a in atoms) and (a not in selected_atoms) + a for a in a1.bonded_atoms if (a in atoms) and (a not in selected_atoms) ) for a0 in a0_list: # Find a2, which is connected to a1, is not a terminal atom, @@ -381,9 +380,7 @@ def __init__(self, ag, initial_atom=None, filename=None, **kwargs): self._primary_torsion_indices = [ prior_atoms.index(prior_atoms[n]) for n in range(len(prior_atoms)) ] - self._unique_primary_torsion_indices = list( - set(self._primary_torsion_indices) - ) + self._unique_primary_torsion_indices = list(set(self._primary_torsion_indices)) self._ag1 = mda.AtomGroup([ag[0] for ag in self._torsions]) self._ag2 = mda.AtomGroup([ag[1] for ag in self._torsions]) @@ -404,9 +401,9 @@ def _single_frame(self): # It is described in two degrees of freedom # by the polar angle and azimuth if self._root.dimensions is None: - (p0, p1, p2) = self._root.positions + p0, p1, p2 = self._root.positions else: - (p0, p1, p2) = make_whole(self._root, inplace=False) + p0, p1, p2 = make_whole(self._root, inplace=False) v01 = p1 - p0 v21 = p1 - p2 # Internal coordinates @@ -422,8 +419,7 @@ def _single_frame(self): 1.0, np.einsum("i,i->", v01, v21) / np.sqrt( - np.einsum("i,i->", v01, v01) - * np.einsum("i,i->", v21, v21) + np.einsum("i,i->", v01, v01) * np.einsum("i,i->", v21, v21) ), ), ) @@ -437,9 +433,7 @@ def _single_frame(self): sp = np.sin(phi) ct = np.cos(theta) st = np.sin(theta) - Rz = np.array( - [[cp * ct, ct * sp, -st], [-sp, cp, 0], [cp * st, sp * st, ct]] - ) + Rz = np.array([[cp * ct, ct * sp, -st], [-sp, cp, 0], [cp * st, sp * st, ct]]) pos2 = Rz.dot(p2 - p1) # Angle about the rotation axis omega = np.arctan2(pos2[1], pos2[0]) @@ -546,8 +540,8 @@ def Cartesian(self, bat_frame): """ # Split the bat vector into more convenient variables origin = bat_frame[:3] - (phi, theta, omega) = bat_frame[3:6] - (r01, r12, a012) = bat_frame[6:9] + phi, theta, omega = bat_frame[3:6] + r01, r12, a012 = bat_frame[6:9] n_torsions = self._ag.n_atoms - 3 bonds = bat_frame[9 : n_torsions + 9] angles = bat_frame[n_torsions + 9 : 2 * n_torsions + 9] @@ -576,9 +570,7 @@ def Cartesian(self, bat_frame): ct = np.cos(theta) st = np.sin(theta) # $R_Z(\phi) R_Y(\theta)$ - Re = np.array( - [[cp * ct, -sp, cp * st], [ct * sp, cp, sp * st], [-st, 0, ct]] - ) + Re = np.array([[cp * ct, -sp, cp * st], [ct * sp, cp, sp * st], [-st, 0, ct]]) p1 = Re.dot(p1) p2 = Re.dot(p2) # Translate the first three atoms by the origin diff --git a/package/MDAnalysis/analysis/contacts.py b/package/MDAnalysis/analysis/contacts.py index 5d63471ae7d..da7cb61a381 100644 --- a/package/MDAnalysis/analysis/contacts.py +++ b/package/MDAnalysis/analysis/contacts.py @@ -208,6 +208,7 @@ def is_any_closer(r, r0, dist=2.5): .. footbibliography:: """ + import os import errno import warnings @@ -451,9 +452,7 @@ def __init__( elif method == "soft_cut": self.fraction_contacts = soft_cut_q elif method == "radius_cut": - self.fraction_contacts = functools.partial( - radius_cut_q, radius=radius - ) + self.fraction_contacts = functools.partial(radius_cut_q, radius=radius) else: if not callable(method): raise ValueError("method has to be callable") @@ -492,9 +491,7 @@ def __init__( box=self._get_box(refA.universe), ) ) - self.initial_contacts.append( - contact_matrix(self.r0[-1], radius) - ) + self.initial_contacts.append(contact_matrix(self.r0[-1], radius)) self.n_initial_contacts = self.initial_contacts[0].sum() diff --git a/package/MDAnalysis/analysis/data/filenames.py b/package/MDAnalysis/analysis/data/filenames.py index 68ab3d96551..ff86733c2db 100644 --- a/package/MDAnalysis/analysis/data/filenames.py +++ b/package/MDAnalysis/analysis/data/filenames.py @@ -25,7 +25,7 @@ :mod:`MDAnalysis.analysis.data` contains data files that are used as part of analysis. These can be experimental or theoretical data. Files are stored -inside the package and made accessible via variables in +inside the package and made accessible via variables in :mod:`MDAnalysis.analysis.data.filenames`. These variables are documented below, including references to the literature and where they are used inside :mod:`MDAnalysis.analysis`. @@ -51,20 +51,20 @@ ax.contourf(X, Y, Z, levels=[1, 17, 15000]) The given levels will draw contours that contain 90% and 99% of the data - points.The reference data are shown in + points.The reference data are shown in :ref:`Ramachandran reference plot figure `. An example of analyzed data together with the reference data are shown in :ref:`Ramachandran plot figure ` as an example. - - + + .. _figure-rama-ref-plot: .. figure:: /images/rama_ref_plot.png :scale: 80% :alt: Ramachandran Ref Plot - - Reference Ramachandran plot, with contours that contain 90% - ("allowed region") and 99% ("generously allowed region") of the data points + + Reference Ramachandran plot, with contours that contain 90% + ("allowed region") and 99% ("generously allowed region") of the data points from the reference data set. .. data:: Janin_ref @@ -84,8 +84,8 @@ ax.contourf(X, Y, Z, levels=[1, 6, 600]) The given levels will draw contours that contain 90% and 98% of the - data. The reference data are shown in - :ref:`Janin reference plot figure `. An example of + data. The reference data are shown in + :ref:`Janin reference plot figure `. An example of analyzed data together with the reference data are shown in :ref:`Janin plot figure` as an example. @@ -95,13 +95,12 @@ :scale: 85 % :alt: Janin Ref Plot - Janin reference plot with contours that contain 90% ("allowed region") and - 98% ("generously allowed region") of the data points from the reference data + Janin reference plot with contours that contain 90% ("allowed region") and + 98% ("generously allowed region") of the data points from the reference data set. """ - __all__ = [ "Rama_ref", "Janin_ref", diff --git a/package/MDAnalysis/analysis/density.py b/package/MDAnalysis/analysis/density.py index 61c4e679899..32a658d2a6c 100644 --- a/package/MDAnalysis/analysis/density.py +++ b/package/MDAnalysis/analysis/density.py @@ -150,6 +150,7 @@ .. _`gmx trjconv`: http://manual.gromacs.org/programs/gmx-trjconv.html """ + import numpy as np import sys import os @@ -439,9 +440,7 @@ def __init__( # in _prepare(), which is executed in parallel on different # parts of the trajectory). coord = self._atomgroup.positions - if self._gridcenter is not None or any( - [self._xdim, self._ydim, self._zdim] - ): + if self._gridcenter is not None or any([self._xdim, self._ydim, self._zdim]): # Issue 2372: padding is ignored, defaults to 2.0 therefore warn if self._padding > 0: msg = ( @@ -804,24 +803,17 @@ def _check_set_unit(self, u): # all this unit crap should be a class... try: for unit_type, value in u.items(): - if ( - value is None - ): # check here, too iffy to use dictionary[None]=None + if value is None: # check here, too iffy to use dictionary[None]=None self.units[unit_type] = None continue try: units.conversion_factor[unit_type][value] self.units[unit_type] = value except KeyError: - errmsg = ( - f"Unit {value} of type {unit_type} is not " - f"recognized." - ) + errmsg = f"Unit {value} of type {unit_type} is not " f"recognized." raise ValueError(errmsg) from None except AttributeError: - errmsg = ( - '"unit" must be a dictionary with keys "length" and "density.' - ) + errmsg = '"unit" must be a dictionary with keys "length" and "density.' logger.fatal(errmsg) raise ValueError(errmsg) from None # need at least length and density (can be None) @@ -878,9 +870,7 @@ def convert_length(self, unit="Angstrom"): """ if unit == self.units["length"]: return - cvnfact = units.get_conversion_factor( - "length", self.units["length"], unit - ) + cvnfact = units.get_conversion_factor("length", self.units["length"], unit) self.edges = [x * cvnfact for x in self.edges] self.units["length"] = unit self._update() # needed to recalculate midpoints and origin @@ -947,10 +937,4 @@ def __repr__(self): grid_type = "density" else: grid_type = "histogram" - return ( - "" - ) + return "" diff --git a/package/MDAnalysis/analysis/diffusionmap.py b/package/MDAnalysis/analysis/diffusionmap.py index 594d7603a4c..6cd0b7786b5 100644 --- a/package/MDAnalysis/analysis/diffusionmap.py +++ b/package/MDAnalysis/analysis/diffusionmap.py @@ -135,6 +135,7 @@ .. footbibliography:: """ + import logging import warnings @@ -260,9 +261,7 @@ def __init__( **kwargs, ): # remember that this must be called before referencing self.n_frames - super(DistanceMatrix, self).__init__( - universe.universe.trajectory, **kwargs - ) + super(DistanceMatrix, self).__init__(universe.universe.trajectory, **kwargs) if isinstance(universe, UpdatingAtomGroup): wmsg = ( @@ -414,9 +413,7 @@ def run(self, start=None, stop=None, step=None): "be very slow to compute. Consider picking a larger " "step size in distance matrix initialization." ) - self._scaled_matrix = ( - self._dist_matrix.results.dist_matrix**2 / self._epsilon - ) + self._scaled_matrix = self._dist_matrix.results.dist_matrix**2 / self._epsilon # take negative exponent of scaled matrix to create Isotropic kernel self._kernel = np.exp(-self._scaled_matrix) D_inv = np.diag(1 / self._kernel.sum(1)) diff --git a/package/MDAnalysis/analysis/dihedrals.py b/package/MDAnalysis/analysis/dihedrals.py index 0c5ecb33cdf..260b368649f 100644 --- a/package/MDAnalysis/analysis/dihedrals.py +++ b/package/MDAnalysis/analysis/dihedrals.py @@ -239,6 +239,7 @@ .. footbibliography:: """ + import numpy as np import matplotlib.pyplot as plt @@ -295,9 +296,7 @@ def __init__(self, atomgroups, **kwargs): If any atomgroups do not contain 4 atoms """ - super(Dihedral, self).__init__( - atomgroups[0].universe.trajectory, **kwargs - ) + super(Dihedral, self).__init__(atomgroups[0].universe.trajectory, **kwargs) self.atomgroups = atomgroups if any([len(ag) != 4 for ag in atomgroups]): @@ -425,9 +424,7 @@ def __init__( check_protein=True, **kwargs, ): - super(Ramachandran, self).__init__( - atomgroup.universe.trajectory, **kwargs - ) + super(Ramachandran, self).__init__(atomgroup.universe.trajectory, **kwargs) self.atomgroup = atomgroup residues = self.atomgroup.residues @@ -454,8 +451,7 @@ def __init__( if not np.all(keep): warnings.warn( - "Some residues in selection do not have " - "phi or psi selections" + "Some residues in selection do not have " "phi or psi selections" ) prev = sum(prev[keep]) nxt = sum(nxt[keep]) @@ -464,9 +460,7 @@ def __init__( # find n, c, ca keep_prev = [sum(r.atoms.names == c_name) == 1 for r in prev] rnames = [n_name, c_name, ca_name] - keep_res = [ - all(sum(r.atoms.names == n) == 1 for n in rnames) for r in residues - ] + keep_res = [all(sum(r.atoms.names == n) == 1 for n in rnames) for r in residues] keep_next = [sum(r.atoms.names == n_name) == 1 for r in nxt] # alright we'll keep these @@ -545,22 +539,16 @@ def plot(self, ax=None, ref=False, **kwargs): xlabel=r"$\phi$", ylabel=r"$\psi$", ) - degree_formatter = plt.matplotlib.ticker.StrMethodFormatter( - r"{x:g}$\degree$" - ) + degree_formatter = plt.matplotlib.ticker.StrMethodFormatter(r"{x:g}$\degree$") ax.xaxis.set_major_formatter(degree_formatter) ax.yaxis.set_major_formatter(degree_formatter) if ref: - X, Y = np.meshgrid( - np.arange(-180, 180, 4), np.arange(-180, 180, 4) - ) + X, Y = np.meshgrid(np.arange(-180, 180, 4), np.arange(-180, 180, 4)) levels = [1, 17, 15000] colors = ["#A1D4FF", "#35A1FF"] ax.contourf(X, Y, np.load(Rama_ref), levels=levels, colors=colors) - a = self.results.angles.reshape( - np.prod(self.results.angles.shape[:2]), 2 - ) + a = self.results.angles.reshape(np.prod(self.results.angles.shape[:2]), 2) ax.scatter(a[:, 0], a[:, 1], **kwargs) return ax @@ -637,9 +625,7 @@ def __init__( :attr:`angles` results are now stored in a :class:`MDAnalysis.analysis.base.Results` instance. """ - super(Ramachandran, self).__init__( - atomgroup.universe.trajectory, **kwargs - ) + super(Ramachandran, self).__init__(atomgroup.universe.trajectory, **kwargs) self.atomgroup = atomgroup residues = atomgroup.residues protein = atomgroup.select_atoms(select_protein).residues @@ -669,8 +655,7 @@ def __init__( # must be removed before using the class, or the file is missing atoms # for some residues which must also be removed if any( - len(self.ag1) != len(ag) - for ag in [self.ag2, self.ag3, self.ag4, self.ag5] + len(self.ag1) != len(ag) for ag in [self.ag2, self.ag3, self.ag4, self.ag5] ): raise ValueError( "Too many or too few atoms selected. Check for " @@ -678,9 +663,7 @@ def __init__( ) def _conclude(self): - self.results.angles = ( - np.rad2deg(np.array(self.results.angles)) + 360 - ) % 360 + self.results.angles = (np.rad2deg(np.array(self.results.angles)) + 360) % 360 def plot(self, ax=None, ref=False, **kwargs): """Plots data into standard Janin plot. @@ -718,9 +701,7 @@ def plot(self, ax=None, ref=False, **kwargs): xlabel=r"$\chi_1$", ylabel=r"$\chi_2$", ) - degree_formatter = plt.matplotlib.ticker.StrMethodFormatter( - r"{x:g}$\degree$" - ) + degree_formatter = plt.matplotlib.ticker.StrMethodFormatter(r"{x:g}$\degree$") ax.xaxis.set_major_formatter(degree_formatter) ax.yaxis.set_major_formatter(degree_formatter) @@ -729,8 +710,6 @@ def plot(self, ax=None, ref=False, **kwargs): levels = [1, 6, 600] colors = ["#A1D4FF", "#35A1FF"] ax.contourf(X, Y, np.load(Janin_ref), levels=levels, colors=colors) - a = self.results.angles.reshape( - np.prod(self.results.angles.shape[:2]), 2 - ) + a = self.results.angles.reshape(np.prod(self.results.angles.shape[:2]), 2) ax.scatter(a[:, 0], a[:, 1], **kwargs) return ax diff --git a/package/MDAnalysis/analysis/distances.py b/package/MDAnalysis/analysis/distances.py index 44a09c4fcbd..604ab53f6b9 100644 --- a/package/MDAnalysis/analysis/distances.py +++ b/package/MDAnalysis/analysis/distances.py @@ -168,9 +168,7 @@ def dist(A, B, offset=0, box=None): """ if A.atoms.n_atoms != B.atoms.n_atoms: - raise ValueError( - "AtomGroups A and B do not have the same number of atoms" - ) + raise ValueError("AtomGroups A and B do not have the same number of atoms") try: off_A, off_B = offset except (TypeError, ValueError): diff --git a/package/MDAnalysis/analysis/dssp/dssp.py b/package/MDAnalysis/analysis/dssp/dssp.py index a3082d9315b..9a2e9d465c9 100644 --- a/package/MDAnalysis/analysis/dssp/dssp.py +++ b/package/MDAnalysis/analysis/dssp/dssp.py @@ -326,8 +326,7 @@ def __init__( } self._donor_mask: Optional[np.ndarray] = ag.residues.resnames != "PRO" self._hydrogens: list["AtomGroup"] = [ - res.atoms.select_atoms(f"name {hydrogen_name}") - for res in ag.residues + res.atoms.select_atoms(f"name {hydrogen_name}") for res in ag.residues ] # can't do it the other way because I need missing values to exist # so that I could fill them in later @@ -389,9 +388,7 @@ def _get_coords(self) -> np.ndarray: coords = np.array(positions) if not self._guess_hydrogens: - guessed_h_coords = _get_hydrogen_atom_position( - coords.swapaxes(0, 1) - ) + guessed_h_coords = _get_hydrogen_atom_position(coords.swapaxes(0, 1)) h_coords = np.array( [ diff --git a/package/MDAnalysis/analysis/dssp/pydssp_numpy.py b/package/MDAnalysis/analysis/dssp/pydssp_numpy.py index 643e510f182..f746b695af0 100644 --- a/package/MDAnalysis/analysis/dssp/pydssp_numpy.py +++ b/package/MDAnalysis/analysis/dssp/pydssp_numpy.py @@ -65,10 +65,7 @@ def _upsample(a: np.ndarray, window: int) -> np.ndarray: def _unfold(a: np.ndarray, window: int, axis: int): "Helper function for 2D array upsampling" - idx = ( - np.arange(window)[:, None] - + np.arange(a.shape[axis] - window + 1)[None, :] - ) + idx = np.arange(window)[:, None] + np.arange(a.shape[axis] - window + 1)[None, :] unfolded = np.take(a, idx, axis=axis) return np.moveaxis(unfolded, axis - 1, -1) @@ -169,9 +166,7 @@ def get_hbond_map( h_1 = coord[1:, 4] coord = coord[:, :4] else: # pragma: no cover - raise ValueError( - "Number of atoms should be 4 (N,CA,C,O) or 5 (N,CA,C,O,H)" - ) + raise ValueError("Number of atoms should be 4 (N,CA,C,O) or 5 (N,CA,C,O,H)") # after this: # h.shape == (n_residues, 3) # coord.shape == (n_residues, 4, 3) @@ -193,9 +188,7 @@ def get_hbond_map( # electrostatic interaction energy # e[i, j] = e(CO_i) - e(NH_j) e = np.pad( - CONST_Q1Q2 - * (1.0 / d_on + 1.0 / d_ch - 1.0 / d_oh - 1.0 / d_cn) - * CONST_F, + CONST_Q1Q2 * (1.0 / d_on + 1.0 / d_ch - 1.0 / d_oh - 1.0 / d_cn) * CONST_F, [[1, 0], [0, 1]], ) diff --git a/package/MDAnalysis/analysis/encore/bootstrap.py b/package/MDAnalysis/analysis/encore/bootstrap.py index 8784409c7f6..9b2fb29918c 100644 --- a/package/MDAnalysis/analysis/encore/bootstrap.py +++ b/package/MDAnalysis/analysis/encore/bootstrap.py @@ -33,11 +33,12 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + import numpy as np import logging import MDAnalysis as mda @@ -116,9 +117,7 @@ def get_distance_matrix_bootstrap_samples( confdistmatrix : list of encore.utils.TriangularMatrix """ - bs_args = [ - ([distance_matrix, ensemble_assignment]) for i in range(samples) - ] + bs_args = [([distance_matrix, ensemble_assignment]) for i in range(samples)] pc = ParallelCalculation(ncores, bootstrapped_matrix, bs_args) diff --git a/package/MDAnalysis/analysis/encore/clustering/ClusterCollection.py b/package/MDAnalysis/analysis/encore/clustering/ClusterCollection.py index 8c545c54215..5252e215716 100644 --- a/package/MDAnalysis/analysis/encore/clustering/ClusterCollection.py +++ b/package/MDAnalysis/analysis/encore/clustering/ClusterCollection.py @@ -32,11 +32,12 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + import numpy as np @@ -99,9 +100,7 @@ def __init__(self, elem_list=None, centroid=None, idn=None, metadata=None): self.metadata = {} self.elements = elem_list if centroid not in self.elements: - raise LookupError( - "Centroid of cluster not found in the element list" - ) + raise LookupError("Centroid of cluster not found in the element list") self.centroid = centroid self.size = self.elements.shape[0] @@ -130,8 +129,7 @@ def __len__(self): def add_metadata(self, name, data): if len(data) != self.size: raise TypeError( - "Size of metadata is not equal to the number of " - "cluster elements" + "Size of metadata is not equal to the number of " "cluster elements" ) self.metadata[name] = np.array(data) @@ -270,6 +268,4 @@ def __repr__(self): if self.clusters is None: return "" else: - return "".format( - len(self.clusters) - ) + return "".format(len(self.clusters)) diff --git a/package/MDAnalysis/analysis/encore/clustering/ClusteringMethod.py b/package/MDAnalysis/analysis/encore/clustering/ClusteringMethod.py index 9af8d48fa86..80a4953eab0 100644 --- a/package/MDAnalysis/analysis/encore/clustering/ClusteringMethod.py +++ b/package/MDAnalysis/analysis/encore/clustering/ClusteringMethod.py @@ -33,11 +33,12 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + import numpy as np import warnings import logging @@ -96,9 +97,7 @@ def __call__(self, x): """ raise NotImplementedError( - "Class {0} doesn't implement __call__()".format( - self.__class__.__name__ - ) + "Class {0} doesn't implement __call__()".format(self.__class__.__name__) ) @@ -247,17 +246,13 @@ def __call__(self, distance_matrix): This method no longer returns ``details`` """ logging.info( - "Starting Affinity Propagation: {0}".format( - self.ap.get_params() - ) + "Starting Affinity Propagation: {0}".format(self.ap.get_params()) ) # Convert from distance matrix to similarity matrix similarity_matrix = distance_matrix.as_array() * -1 clusters = self.ap.fit_predict(similarity_matrix) - clusters = encode_centroid_info( - clusters, self.ap.cluster_centers_indices_ - ) + clusters = encode_centroid_info(clusters, self.ap.cluster_centers_indices_) return clusters @@ -332,9 +327,7 @@ def __call__(self, distance_matrix): .. versionchanged:: 1.0.0 This method no longer returns ``details`` """ - logging.info( - "Starting DBSCAN: {0}".format(self.dbscan.get_params()) - ) + logging.info("Starting DBSCAN: {0}".format(self.dbscan.get_params())) clusters = self.dbscan.fit_predict(distance_matrix.as_array()) if np.min(clusters == -1): clusters += 1 @@ -444,9 +437,7 @@ def __call__(self, coordinates): .. versionchanged:: 1.0.0 This method no longer returns ``details`` """ - logging.info( - "Starting Kmeans: {0}".format((self.kmeans.get_params())) - ) + logging.info("Starting Kmeans: {0}".format((self.kmeans.get_params()))) clusters = self.kmeans.fit_predict(coordinates) distances = self.kmeans.transform(coordinates) cluster_center_indices = np.argmin(distances, axis=0) diff --git a/package/MDAnalysis/analysis/encore/clustering/cluster.py b/package/MDAnalysis/analysis/encore/clustering/cluster.py index 2173a8d207d..cdda081c3be 100644 --- a/package/MDAnalysis/analysis/encore/clustering/cluster.py +++ b/package/MDAnalysis/analysis/encore/clustering/cluster.py @@ -32,11 +32,12 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + import numpy as np from ..utils import ParallelCalculation, merge_universes from .ClusterCollection import ClusterCollection @@ -190,9 +191,7 @@ def cluster( if distance_matrix: if not hasattr(distance_matrix, "__iter__"): distance_matrix = [distance_matrix] - if ensembles is not None and len(distance_matrix) != len( - merged_ensembles - ): + if ensembles is not None and len(distance_matrix) != len(merged_ensembles): raise ValueError( "Dimensions of provided list of distance matrices " "does not match that of provided list of " @@ -207,9 +206,7 @@ def cluster( distance_matrix = [] for merged_ensemble in merged_ensembles: distance_matrix.append( - get_distance_matrix( - merged_ensemble, select=select, **kwargs - ) + get_distance_matrix(merged_ensemble, select=select, **kwargs) ) args = [] @@ -218,14 +215,10 @@ def cluster( args += [(d,) for d in distance_matrix] else: for merged_ensemble in merged_ensembles: - coordinates = merged_ensemble.trajectory.timeseries( - order="fac" - ) + coordinates = merged_ensemble.trajectory.timeseries(order="fac") # Flatten coordinate matrix into n_frame x n_coordinates - coordinates = np.reshape( - coordinates, (coordinates.shape[0], -1) - ) + coordinates = np.reshape(coordinates, (coordinates.shape[0], -1)) args.append((coordinates,)) @@ -246,10 +239,7 @@ def cluster( # Create clusters collections from clustering results, # one for each cluster. None if clustering didn't work. - ccs = [ - ClusterCollection(clusters[1], metadata=metadata) - for clusters in results - ] + ccs = [ClusterCollection(clusters[1], metadata=metadata) for clusters in results] if allow_collapsed_result and len(ccs) == 1: ccs = ccs[0] diff --git a/package/MDAnalysis/analysis/encore/confdistmatrix.py b/package/MDAnalysis/analysis/encore/confdistmatrix.py index 95b22bf0563..2dd7720e033 100644 --- a/package/MDAnalysis/analysis/encore/confdistmatrix.py +++ b/package/MDAnalysis/analysis/encore/confdistmatrix.py @@ -35,11 +35,12 @@ class to compute an RMSD matrix in such a way is also available. .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + from joblib import Parallel, delayed import numpy as np from getpass import getuser @@ -112,9 +113,7 @@ def conformational_distance_matrix( # framesn: number of frames framesn = len( - ensemble.trajectory.timeseries( - ensemble.select_atoms(select), order="fac" - ) + ensemble.trajectory.timeseries(ensemble.select_atoms(select), order="fac") ) # Prepare metadata recarray @@ -162,29 +161,20 @@ def conformational_distance_matrix( else: fitting_coordinates = None - if ( - not isinstance(weights, (list, tuple, np.ndarray)) - and weights == "mass" - ): + if not isinstance(weights, (list, tuple, np.ndarray)) and weights == "mass": weights = ensemble.select_atoms(select).masses.astype(np.float64) if pairwise_align: - subset_weights = ensemble.select_atoms( - subset_select - ).masses.astype(np.float64) + subset_weights = ensemble.select_atoms(subset_select).masses.astype( + np.float64 + ) else: subset_weights = None elif weights is None: weights = np.ones( - ( - ensemble.trajectory.timeseries(ensemble.select_atoms(select))[ - 0 - ].shape[0] - ) + (ensemble.trajectory.timeseries(ensemble.select_atoms(select))[0].shape[0]) ).astype(np.float64) if pairwise_align: - subset_weights = np.ones((fit_coords[0].shape[0])).astype( - np.float64 - ) + subset_weights = np.ones((fit_coords[0].shape[0])).astype(np.float64) else: subset_weights = None else: @@ -291,9 +281,7 @@ def set_rmsd_matrix_elements( com_j = np.average(fit_coords[j], axis=0, weights=fit_weights) translated_j = coords[j] - com_j subset2_coords = fit_coords[j] - com_j - rotamat = rotation_matrix( - subset1_coords, subset2_coords, subset_weights - )[0] + rotamat = rotation_matrix(subset1_coords, subset2_coords, subset_weights)[0] rotated_i = np.transpose(np.dot(rotamat, np.transpose(translated_i))) rmsdmat[(i + 1) * i // 2 + j] = PureRMSD( rotated_i.astype(np.float64), @@ -375,9 +363,7 @@ def get_distance_matrix( # Load the matrix if required if load_matrix: - logging.info( - " Loading similarity matrix from: {0}".format(load_matrix) - ) + logging.info(" Loading similarity matrix from: {0}".format(load_matrix)) confdistmatrix = TriangularMatrix( size=ensemble.trajectory.timeseries( ensemble.select_atoms(select), order="fac" @@ -387,9 +373,7 @@ def get_distance_matrix( logging.info(" Done!") for key in confdistmatrix.metadata.dtype.names: logging.info( - " {0} : {1}".format( - key, str(confdistmatrix.metadata[key][0]) - ) + " {0} : {1}".format(key, str(confdistmatrix.metadata[key][0])) ) # Check matrix size for consistency @@ -411,26 +395,17 @@ def get_distance_matrix( # Transfer universe to memory to ensure timeseries() support ensemble.transfer_to_memory() - if ( - not isinstance(weights, (list, tuple, np.ndarray)) - and weights == "mass" - ): + if not isinstance(weights, (list, tuple, np.ndarray)) and weights == "mass": weight_type = "Mass" elif weights is None: weight_type = "None" else: weight_type = "Custom" - logging.info( - " Perform pairwise alignment: {0}".format(str(superimpose)) - ) - logging.info( - " weighted alignment and RMSD: {0}".format(weight_type) - ) + logging.info(" Perform pairwise alignment: {0}".format(str(superimpose))) + logging.info(" weighted alignment and RMSD: {0}".format(weight_type)) if superimpose: logging.info( - " Atoms subset for alignment: {0}".format( - superimposition_subset - ) + " Atoms subset for alignment: {0}".format(superimposition_subset) ) logging.info(" Calculating similarity matrix . . .") diff --git a/package/MDAnalysis/analysis/encore/covariance.py b/package/MDAnalysis/analysis/encore/covariance.py index 08e014e315c..59d53d55e0f 100644 --- a/package/MDAnalysis/analysis/encore/covariance.py +++ b/package/MDAnalysis/analysis/encore/covariance.py @@ -32,11 +32,12 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + import numpy as np @@ -151,18 +152,14 @@ def shrinkage_covariance_estimator( p = 1 / float(t) * np.sum(np.dot(np.transpose(y), y)) - np.sum( np.sum(sample**2) ) - rdiag = 1 / float(t) * np.sum(np.sum(y**2)) - np.sum( - np.diag(sample) ** 2 - ) + rdiag = 1 / float(t) * np.sum(np.sum(y**2)) - np.sum(np.diag(sample) ** 2) z = x * np.repeat(xmkt[:, np.newaxis], n, axis=1) v1 = ( 1 / float(t) * np.dot(np.transpose(y), z) - np.repeat(covmkt[:, np.newaxis], n, axis=1) * sample ) roff1 = ( - np.sum( - v1 * np.transpose(np.repeat(covmkt[:, np.newaxis], n, axis=1)) - ) + np.sum(v1 * np.transpose(np.repeat(covmkt[:, np.newaxis], n, axis=1))) / varmkt - np.sum(np.diag(v1) * covmkt) / varmkt ) @@ -240,10 +237,7 @@ def covariance_matrix( # Optionally correct with weights if weights is not None: # Calculate mass-weighted covariance matrix - if ( - not isinstance(weights, (list, tuple, np.ndarray)) - and weights == "mass" - ): + if not isinstance(weights, (list, tuple, np.ndarray)) and weights == "mass": if select: weights = ensemble.select_atoms(select).masses else: @@ -255,8 +249,7 @@ def covariance_matrix( req_len = ensemble.atoms.n_atoms if req_len != len(weights): raise ValueError( - "number of weights is unequal to number of " - "atoms in ensemble" + "number of weights is unequal to number of " "atoms in ensemble" ) # broadcast to a (len(weights), 3) array diff --git a/package/MDAnalysis/analysis/encore/dimensionality_reduction/DimensionalityReductionMethod.py b/package/MDAnalysis/analysis/encore/dimensionality_reduction/DimensionalityReductionMethod.py index 3ca43202f5e..07fda4784d0 100644 --- a/package/MDAnalysis/analysis/encore/dimensionality_reduction/DimensionalityReductionMethod.py +++ b/package/MDAnalysis/analysis/encore/dimensionality_reduction/DimensionalityReductionMethod.py @@ -33,11 +33,12 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + import logging import warnings @@ -85,9 +86,7 @@ def __call__(self, x): """ raise NotImplementedError( - "Class {0} doesn't implement __call__()".format( - self.__class__.__name__ - ) + "Class {0} doesn't implement __call__()".format(self.__class__.__name__) ) @@ -150,17 +149,15 @@ def __call__(self, distance_matrix): coordinates in reduced space """ - final_stress, coordinates = ( - stochasticproxembed.StochasticProximityEmbedding( - s=distance_matrix, - rco=self.distance_cutoff, - dim=self.dimension, - minlam=self.min_lam, - maxlam=self.max_lam, - ncycle=self.ncycle, - nstep=self.nstep, - stressfreq=self.stressfreq, - ) + final_stress, coordinates = stochasticproxembed.StochasticProximityEmbedding( + s=distance_matrix, + rco=self.distance_cutoff, + dim=self.dimension, + minlam=self.min_lam, + maxlam=self.max_lam, + ncycle=self.ncycle, + nstep=self.nstep, + stressfreq=self.stressfreq, ) return coordinates, {"final_stress": final_stress} @@ -185,9 +182,7 @@ def __init__(self, dimension=2, **kwargs): Number of dimensions to which the conformational space will be reduced to (default is 3). """ - self.pca = sklearn.decomposition.PCA( - n_components=dimension, **kwargs - ) + self.pca = sklearn.decomposition.PCA(n_components=dimension, **kwargs) def __call__(self, coordinates): """ diff --git a/package/MDAnalysis/analysis/encore/dimensionality_reduction/reduce_dimensionality.py b/package/MDAnalysis/analysis/encore/dimensionality_reduction/reduce_dimensionality.py index d1e05e1cd2f..d3cf6000162 100644 --- a/package/MDAnalysis/analysis/encore/dimensionality_reduction/reduce_dimensionality.py +++ b/package/MDAnalysis/analysis/encore/dimensionality_reduction/reduce_dimensionality.py @@ -32,11 +32,12 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. """ + import numpy as np from ..confdistmatrix import get_distance_matrix from ..utils import ParallelCalculation, merge_universes @@ -187,9 +188,7 @@ def reduce_dimensionality( if distance_matrix: if not hasattr(distance_matrix, "__iter__"): distance_matrix = [distance_matrix] - if ensembles is not None and len(distance_matrix) != len( - merged_ensembles - ): + if ensembles is not None and len(distance_matrix) != len(merged_ensembles): raise ValueError( "Dimensions of provided list of distance matrices " "does not match that of provided list of " @@ -204,9 +203,7 @@ def reduce_dimensionality( distance_matrix = [] for merged_ensemble in merged_ensembles: distance_matrix.append( - get_distance_matrix( - merged_ensemble, select=select, **kwargs - ) + get_distance_matrix(merged_ensemble, select=select, **kwargs) ) args = [] @@ -215,14 +212,10 @@ def reduce_dimensionality( args += [(d,) for d in distance_matrix] else: for merged_ensemble in merged_ensembles: - coordinates = merged_ensemble.trajectory.timeseries( - order="fac" - ) + coordinates = merged_ensemble.trajectory.timeseries(order="fac") # Flatten coordinate matrix into n_frame x n_coordinates - coordinates = np.reshape( - coordinates, (coordinates.shape[0], -1) - ) + coordinates = np.reshape(coordinates, (coordinates.shape[0], -1)) args.append((coordinates,)) diff --git a/package/MDAnalysis/analysis/encore/similarity.py b/package/MDAnalysis/analysis/encore/similarity.py index 17b9fb28860..9c30295bde0 100644 --- a/package/MDAnalysis/analysis/encore/similarity.py +++ b/package/MDAnalysis/analysis/encore/similarity.py @@ -30,7 +30,7 @@ .. versionadded:: 0.16.0 .. deprecated:: 2.8.0 - This module is deprecated in favour of the + This module is deprecated in favour of the MDAKit `mdaencore `_ and will be removed in MDAnalysis 3.0.0. @@ -170,6 +170,7 @@ .. All functions are included via automodule :members:. """ + import warnings import logging @@ -302,15 +303,12 @@ def harmonic_ensemble_similarity(sigma1, sigma2, x1, x2): ) d_hes = 0.25 * ( - np.dot(np.transpose(d_avg), np.dot(sigma1_inv + sigma2_inv, d_avg)) - + trace + np.dot(np.transpose(d_avg), np.dot(sigma1_inv + sigma2_inv, d_avg)) + trace ) return d_hes -def clustering_ensemble_similarity( - cc, ens1, ens1_id, ens2, ens2_id, select="name CA" -): +def clustering_ensemble_similarity(cc, ens1, ens1_id, ens2, ens2_id, select="name CA"): """Clustering ensemble similarity: calculate the probability densities from the clusters and calculate discrete Jensen-Shannon divergence. @@ -591,19 +589,13 @@ def dimred_ensemble_similarity( ln_P1_exp_P1 = np.average(np.log(kde1.evaluate(resamples1))) ln_P2_exp_P2 = np.average(np.log(kde2.evaluate(resamples2))) ln_P1P2_exp_P1 = np.average( - np.log( - 0.5 * (kde1.evaluate(resamples1) + kde2.evaluate(resamples1)) - ) + np.log(0.5 * (kde1.evaluate(resamples1) + kde2.evaluate(resamples1))) ) ln_P1P2_exp_P2 = np.average( - np.log( - 0.5 * (kde1.evaluate(resamples2) + kde2.evaluate(resamples2)) - ) + np.log(0.5 * (kde1.evaluate(resamples2) + kde2.evaluate(resamples2))) ) - return 0.5 * ( - ln_P1_exp_P1 - ln_P1P2_exp_P1 + ln_P2_exp_P2 - ln_P1P2_exp_P2 - ) + return 0.5 * (ln_P1_exp_P1 - ln_P1P2_exp_P1 + ln_P2_exp_P2 - ln_P1P2_exp_P2) def cumulative_gen_kde_pdfs( @@ -690,9 +682,7 @@ def cumulative_gen_kde_pdfs( return (kdes, resamples, embedded_ensembles) -def write_output( - matrix, base_fname=None, header="", suffix="", extension="dat" -): +def write_output(matrix, base_fname=None, header="", suffix="", extension="dat"): """ Write output matrix with a nice format, to stdout and optionally a file. @@ -905,10 +895,7 @@ def hes( """ - if ( - not isinstance(weights, (list, tuple, np.ndarray)) - and weights == "mass" - ): + if not isinstance(weights, (list, tuple, np.ndarray)) and weights == "mass": weights = ["mass" for _ in range(len(ensembles))] elif weights is not None: if len(weights) != len(ensembles): @@ -957,9 +944,7 @@ def hes( ensembles_list = [] for i, ensemble in enumerate(ensembles): ensembles_list.append( - get_ensemble_bootstrap_samples( - ensemble, samples=bootstrapping_samples - ) + get_ensemble_bootstrap_samples(ensemble, samples=bootstrapping_samples) ) for t in range(bootstrapping_samples): logging.info("The coordinates will be bootstrapped.") @@ -1254,9 +1239,7 @@ def ces( failed_runs += 1 k += 1 continue - values[i].append( - np.zeros((len(ensembles[j]), len(ensembles[j]))) - ) + values[i].append(np.zeros((len(ensembles[j]), len(ensembles[j])))) for pair in pairs_indices: # Calculate dJS @@ -1467,16 +1450,10 @@ def dres( dimensionality_reduction_methods = [dimensionality_reduction_method] any_method_accept_distance_matrix = np.any( - [ - method.accepts_distance_matrix - for method in dimensionality_reduction_methods - ] + [method.accepts_distance_matrix for method in dimensionality_reduction_methods] ) all_methods_accept_distance_matrix = np.all( - [ - method.accepts_distance_matrix - for method in dimensionality_reduction_methods - ] + [method.accepts_distance_matrix for method in dimensionality_reduction_methods] ) # Register which ensembles the samples belong to @@ -1508,8 +1485,7 @@ def dres( ensembles = [] for j in range(bootstrapping_samples): ensembles.append( - ensembles_list[i, j] - for i in range(ensembles_list.shape[0]) + ensembles_list[i, j] for i in range(ensembles_list.shape[0]) ) else: # if all methods accept distances matrices, duplicate @@ -1540,9 +1516,7 @@ def dres( values[i] = [] for j in range(bootstrapping_samples): - values[i].append( - np.zeros((len(ensembles[j]), len(ensembles[j]))) - ) + values[i].append(np.zeros((len(ensembles[j]), len(ensembles[j])))) kdes, resamples, embedded_ensembles = gen_kde_pdfs( coordinates[k], diff --git a/package/MDAnalysis/analysis/encore/utils.py b/package/MDAnalysis/analysis/encore/utils.py index ae6407ddd19..77bc7a41896 100644 --- a/package/MDAnalysis/analysis/encore/utils.py +++ b/package/MDAnalysis/analysis/encore/utils.py @@ -128,9 +128,7 @@ def loadz(self, fname): raise TypeError self.metadata = loaded["metadata"] else: - if self.size * (self.size - 1) / 2 + self.size != len( - loaded["elements"] - ): + if self.size * (self.size - 1) / 2 + self.size != len(loaded["elements"]): raise TypeError self._elements = loaded["elements"] @@ -241,9 +239,7 @@ class description. if not hasattr(self.functions, "__iter__"): self.functions = [self.functions] * len(args) if len(self.functions) != len(args): - self.functions = self.functions[:] * ( - len(args) // len(self.functions) - ) + self.functions = self.functions[:] * (len(args) // len(self.functions)) # Arguments should be present if args is None: @@ -279,9 +275,7 @@ def worker(self, q, results): if i == "STOP": return - results.put( - (i, self.functions[i](*self.args[i], **self.kwargs[i])) - ) + results.put((i, self.functions[i](*self.args[i], **self.kwargs[i]))) def run(self): r""" diff --git a/package/MDAnalysis/analysis/gnm.py b/package/MDAnalysis/analysis/gnm.py index a767c5c5787..c5f5d0cd1f2 100644 --- a/package/MDAnalysis/analysis/gnm.py +++ b/package/MDAnalysis/analysis/gnm.py @@ -86,6 +86,7 @@ removed unused function :func:`backup_file` """ + import itertools import logging import warnings @@ -169,9 +170,7 @@ def neighbour_generator(positions, cutoff): n_x = len(grid) n_y = len(grid[0]) n_z = len(grid[0][0]) - for cell_x, cell_y, cell_z in itertools.product( - range(n_x), range(n_y), range(n_z) - ): + for cell_x, cell_y, cell_z in itertools.product(range(n_x), range(n_y), range(n_z)): atoms = grid[cell_x][cell_y][cell_z] # collect all atoms in own cell and neighboring cell all_atoms = [] @@ -281,15 +280,11 @@ def __init__( self._timesteps = None # time for each frame self.ReportVector = ReportVector self.Bonus_groups = ( - [self.u.select_atoms(item) for item in Bonus_groups] - if Bonus_groups - else [] + [self.u.select_atoms(item) for item in Bonus_groups] if Bonus_groups else [] ) self.ca = self.u.select_atoms(self.select) - def _generate_output( - self, w, v, outputobject, ReportVector=None, counter=0 - ): + def _generate_output(self, w, v, outputobject, ReportVector=None, counter=0): """Appends time, eigenvalues and eigenvectors to results. This generates the output by adding eigenvalue and @@ -476,9 +471,7 @@ def generate_kirchoff(self): ): iresidue = residue_index_map[i_atom] jresidue = residue_index_map[j_atom] - contact = ( - inv_sqrt_res_sizes[iresidue] * inv_sqrt_res_sizes[jresidue] - ) + contact = inv_sqrt_res_sizes[iresidue] * inv_sqrt_res_sizes[jresidue] matrix[iresidue][jresidue] -= contact matrix[jresidue][iresidue] -= contact matrix[iresidue][iresidue] += contact diff --git a/package/MDAnalysis/analysis/hbonds/hbond_autocorrel.py b/package/MDAnalysis/analysis/hbonds/hbond_autocorrel.py index 3f80affc814..092dc8ae1f0 100644 --- a/package/MDAnalysis/analysis/hbonds/hbond_autocorrel.py +++ b/package/MDAnalysis/analysis/hbonds/hbond_autocorrel.py @@ -42,6 +42,7 @@ :mod:`MDAnalysis.analysis.hydrogenbonds.hbond_autocorrel` """ + import warnings with warnings.catch_warnings(): @@ -57,19 +58,16 @@ from ..hydrogenbonds import hbond_autocorrel - find_hydrogen_donors = deprecate( hbond_autocorrel.find_hydrogen_donors, release="2.0.0", remove="3.0.0", - message="The function was moved to " - "MDAnalysis.analysis.hbonds.hbond_autocorrel.", + message="The function was moved to " "MDAnalysis.analysis.hbonds.hbond_autocorrel.", ) HydrogenBondAutoCorrel = deprecate( hbond_autocorrel.HydrogenBondAutoCorrel, release="2.0.0", remove="3.0.0", - message="The class was moved to " - "MDAnalysis.analysis.hbonds.hbond_autocorrel.", + message="The class was moved to " "MDAnalysis.analysis.hbonds.hbond_autocorrel.", ) diff --git a/package/MDAnalysis/analysis/helix_analysis.py b/package/MDAnalysis/analysis/helix_analysis.py index e0edf763708..7b32a2372a3 100644 --- a/package/MDAnalysis/analysis/helix_analysis.py +++ b/package/MDAnalysis/analysis/helix_analysis.py @@ -79,7 +79,7 @@ hel_xyz = hel.helix_analysis(u.atoms.positions, ref_axis=[0, 0, 1]) - + Classes ------- @@ -176,9 +176,7 @@ def local_screw_angles(global_axis, ref_axis, helix_directions): # angles from projection to perp refs = np.array([perp, ortho]) # (2, 3) - norms = _, ortho_norm = np.outer( - mdamath.pnorm(refs), mdamath.pnorm(proj_plane) - ) + norms = _, ortho_norm = np.outer(mdamath.pnorm(refs), mdamath.pnorm(proj_plane)) cos = cos_perp, cos_ortho = np.matmul(refs, proj_plane.T) / norms to_perp, to_ortho = np.arccos(np.clip(cos, -1, 1)) # (2, n_vec) to_ortho[ortho_norm == 0] = 0 # ? @@ -291,9 +289,7 @@ def helix_analysis(positions, ref_axis=(0, 0, 1)): origins[-1] -= radii[-1] * local_helix_directions[-1] helix_axes = vector_of_best_fit(origins) - screw = local_screw_angles( - helix_axes, np.asarray(ref_axis), local_helix_directions - ) + screw = local_screw_angles(helix_axes, np.asarray(ref_axis), local_helix_directions) results = { "local_twists": local_twists, @@ -401,9 +397,7 @@ def __init__( flatten_single_helix=True, split_residue_sequences=True, ): - super(HELANAL, self).__init__( - universe.universe.trajectory, verbose=verbose - ) + super(HELANAL, self).__init__(universe.universe.trajectory, verbose=verbose) selections = util.asiterable(select) atomgroups = [universe.select_atoms(s) for s in selections] consecutive = [] @@ -467,9 +461,7 @@ def _prepare(self): self.results[key] = empty self.results.global_axis = [self._zeros_per_frame((3,)) for n in n_res] - self.results.all_bends = [ - self._zeros_per_frame((n - 3, n - 3)) for n in n_res - ] + self.results.all_bends = [self._zeros_per_frame((n - 3, n - 3)) for n in n_res] def _single_frame(self): _f = self._frame_index @@ -484,9 +476,7 @@ def _conclude(self): self.results.global_tilts = tilts = [] norm_ref = (self.ref_axis**2).sum() ** 0.5 for axes in self.results.global_axis: - cos = np.matmul(self.ref_axis, axes.T) / ( - mdamath.pnorm(axes) * norm_ref - ) + cos = np.matmul(self.ref_axis, axes.T) / (mdamath.pnorm(axes) * norm_ref) cos = np.clip(cos, -1.0, 1.0) tilts.append(np.rad2deg(np.arccos(cos))) diff --git a/package/MDAnalysis/analysis/hole2/__init__.py b/package/MDAnalysis/analysis/hole2/__init__.py index 4a4188a0b37..ec5d4bcb96b 100644 --- a/package/MDAnalysis/analysis/hole2/__init__.py +++ b/package/MDAnalysis/analysis/hole2/__init__.py @@ -35,6 +35,7 @@ pathway :footcite:p:`Stelzl2014`. """ + import warnings try: diff --git a/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py b/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py index d4b941614ba..a86cdb56dd4 100644 --- a/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py +++ b/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py @@ -236,6 +236,7 @@ Will be removed in MDAnalysis 3.0.0. Please use :attr:`results.hbonds` instead. """ + import logging import warnings from collections.abc import Iterable @@ -251,14 +252,15 @@ from ...due import due, Doi - logger = logging.getLogger(__name__) -due.cite(Doi("10.1039/C9CP01532A"), - description="Hydrogen bond analysis implementation", - path="MDAnalysis.analysis.hydrogenbonds.hbond_analysis", - cite_module=True) +due.cite( + Doi("10.1039/C9CP01532A"), + description="Hydrogen bond analysis implementation", + path="MDAnalysis.analysis.hydrogenbonds.hbond_analysis", + cite_module=True, +) del Doi @@ -272,18 +274,29 @@ class HydrogenBondAnalysis(AnalysisBase): @classmethod def get_supported_backends(cls): - return ('serial', 'multiprocessing', 'dask',) + return ( + "serial", + "multiprocessing", + "dask", + ) - def __init__(self, universe, - donors_sel=None, hydrogens_sel=None, acceptors_sel=None, - between=None, d_h_cutoff=1.2, - d_a_cutoff=3.0, d_h_a_angle_cutoff=150, - update_selections=True): + def __init__( + self, + universe, + donors_sel=None, + hydrogens_sel=None, + acceptors_sel=None, + between=None, + d_h_cutoff=1.2, + d_a_cutoff=3.0, + d_h_a_angle_cutoff=150, + update_selections=True, + ): """Set up atom selections and geometric criteria for finding hydrogen bonds in a Universe. Hydrogen bond selections with `donors_sel` , `hydrogens_sel`, and - `acceptors_sel` may be achieved with either a *resname*, atom *name* + `acceptors_sel` may be achieved with either a *resname*, atom *name* combination, or when those are absent, with atom *type* selections. Parameters @@ -340,7 +353,7 @@ def __init__(self, universe, .. versionadded:: 2.0.0 Added `between` keyword .. versionchanged:: 2.4.0 - Added use of atom types in selection strings for hydrogen atoms, + Added use of atom types in selection strings for hydrogen atoms, bond donors, or bond acceptors .. versionchanged:: 2.8.0 Introduced :meth:`get_supported_backends` allowing for parallel execution on @@ -355,14 +368,19 @@ def __init__(self, universe, self._trajectory = self.u.trajectory self._donors_sel = donors_sel.strip() if donors_sel is not None else donors_sel - self._hydrogens_sel = hydrogens_sel.strip() if hydrogens_sel is not None else hydrogens_sel - self._acceptors_sel = acceptors_sel.strip() if acceptors_sel is not None else acceptors_sel - - msg = ("{} is an empty selection string - no hydrogen bonds will " - "be found. This may be intended, but please check your " - "selection." - ) - for sel in ['donors_sel', 'hydrogens_sel', 'acceptors_sel']: + self._hydrogens_sel = ( + hydrogens_sel.strip() if hydrogens_sel is not None else hydrogens_sel + ) + self._acceptors_sel = ( + acceptors_sel.strip() if acceptors_sel is not None else acceptors_sel + ) + + msg = ( + "{} is an empty selection string - no hydrogen bonds will " + "be found. This may be intended, but please check your " + "selection." + ) + for sel in ["donors_sel", "hydrogens_sel", "acceptors_sel"]: val = getattr(self, sel) if isinstance(val, str) and not val: warnings.warn(msg.format(sel)) @@ -380,7 +398,7 @@ def __init__(self, universe, between_ags.append( [ self.u.select_atoms(group1, updating=False), - self.u.select_atoms(group2, updating=False) + self.u.select_atoms(group2, updating=False), ] ) @@ -388,7 +406,6 @@ def __init__(self, universe, else: self.between_ags = None - self.d_h_cutoff = d_h_cutoff self.d_a_cutoff = d_a_cutoff self.d_h_a_angle = d_h_a_angle_cutoff @@ -403,23 +420,19 @@ def __init__(self, universe, self._hydrogens_sel = self.guess_hydrogens() # Select atom groups - self._acceptors = self.u.select_atoms(self.acceptors_sel, - updating=self.update_selections) + self._acceptors = self.u.select_atoms( + self.acceptors_sel, updating=self.update_selections + ) self._donors, self._hydrogens = self._get_dh_pairs() - def guess_hydrogens(self, - select='all', - max_mass=1.1, - min_charge=0.3, - min_mass=0.9 - ): + def guess_hydrogens(self, select="all", max_mass=1.1, min_charge=0.3, min_mass=0.9): """Guesses which hydrogen atoms should be used in the analysis. Parameters ---------- select: str (optional) - :ref:`Selection string ` for atom group - from which hydrogens will be identified. (e.g., ``(resname X and + :ref:`Selection string ` for atom group + from which hydrogens will be identified. (e.g., ``(resname X and name H1)`` or ``type 2``) max_mass: float (optional) The mass of a hydrogen atom must be less than this value. @@ -431,24 +444,24 @@ def guess_hydrogens(self, Returns ------- potential_hydrogens: str - String containing the :attr:`resname` and :attr:`name` of all + String containing the :attr:`resname` and :attr:`name` of all hydrogen atoms potentially capable of forming hydrogen bonds. Notes ----- - Hydrogen selections may be achieved with either a resname, atom + Hydrogen selections may be achieved with either a resname, atom name combination, or when those are absent, atom types. This function makes use of atomic masses and atomic charges to identify - which atoms are hydrogen atoms that are capable of participating in - hydrogen bonding. If an atom has a mass less than :attr:`max_mass` and - an atomic charge greater than :attr:`min_charge` then it is considered + which atoms are hydrogen atoms that are capable of participating in + hydrogen bonding. If an atom has a mass less than :attr:`max_mass` and + an atomic charge greater than :attr:`min_charge` then it is considered capable of participating in hydrogen bonds. - If :attr:`hydrogens_sel` is `None`, this function is called to guess + If :attr:`hydrogens_sel` is `None`, this function is called to guess the selection. - Alternatively, this function may be used to quickly generate a + Alternatively, this function may be used to quickly generate a :class:`str` of potential hydrogen atoms involved in hydrogen bonding. This str may then be modified before being used to set the attribute :attr:`hydrogens_sel`. @@ -464,25 +477,27 @@ def guess_hydrogens(self, ag = self.u.select_atoms(select) hydrogens_ag = ag[ - np.logical_and.reduce(( - ag.masses < max_mass, - ag.charges > min_charge, - ag.masses > min_mass, - )) + np.logical_and.reduce( + ( + ag.masses < max_mass, + ag.charges > min_charge, + ag.masses > min_mass, + ) + ) ] return self._group_categories(hydrogens_ag) - def guess_donors(self, select='all', max_charge=-0.5): + def guess_donors(self, select="all", max_charge=-0.5): """Guesses which atoms could be considered donors in the analysis. Only - use if the universe topology does not contain bonding information, + use if the universe topology does not contain bonding information, otherwise donor-hydrogen pairs may be incorrectly assigned. Parameters ---------- select: str (optional) - :ref:`Selection string ` for atom group - from which donors will be identified. (e.g., ``(resname X and name + :ref:`Selection string ` for atom group + from which donors will be identified. (e.g., ``(resname X and name O1)`` or ``type 2``) max_charge: float (optional) The charge of a donor atom must be less than this value. @@ -490,27 +505,27 @@ def guess_donors(self, select='all', max_charge=-0.5): Returns ------- potential_donors: str - String containing the :attr:`resname` and :attr:`name` of all atoms + String containing the :attr:`resname` and :attr:`name` of all atoms that are potentially capable of forming hydrogen bonds. Notes ----- - Donor selections may be achieved with either a resname, atom + Donor selections may be achieved with either a resname, atom name combination, or when those are absent, atom types. - This function makes use of and atomic charges to identify which atoms - could be considered donor atoms in the hydrogen bond analysis. If an - atom has an atomic charge less than :attr:`max_charge`, and it is - within :attr:`d_h_cutoff` of a hydrogen atom, then it is considered + This function makes use of and atomic charges to identify which atoms + could be considered donor atoms in the hydrogen bond analysis. If an + atom has an atomic charge less than :attr:`max_charge`, and it is + within :attr:`d_h_cutoff` of a hydrogen atom, then it is considered capable of participating in hydrogen bonds. - If :attr:`donors_sel` is `None`, and the universe topology does not - have bonding information, this function is called to guess the + If :attr:`donors_sel` is `None`, and the universe topology does not + have bonding information, this function is called to guess the selection. - Alternatively, this function may be used to quickly generate a - :class:`str` of potential donor atoms involved in hydrogen bonding. - This :class:`str` may then be modified before being used to set the + Alternatively, this function may be used to quickly generate a + :class:`str` of potential donor atoms involved in hydrogen bonding. + This :class:`str` may then be modified before being used to set the attribute :attr:`donors_sel`. @@ -520,7 +535,7 @@ def guess_donors(self, select='all', max_charge=-0.5): """ # We need to know `hydrogens_sel` before we can find donors - # Use a new variable `hydrogens_sel` so that we do not set + # Use a new variable `hydrogens_sel` so that we do not set # `self.hydrogens_sel` if it is currently `None` if self.hydrogens_sel is None: hydrogens_sel = self.guess_hydrogens() @@ -532,8 +547,10 @@ def guess_donors(self, select='all', max_charge=-0.5): # times faster to access. This is because u.bonds also calculates # properties of each bond (e.g bond length). See: # https://github.com/MDAnalysis/mdanalysis/issues/2396#issuecomment-596251787 - if (hasattr(self.u._topology, 'bonds') - and len(self.u._topology.bonds.values) != 0): + if ( + hasattr(self.u._topology, "bonds") + and len(self.u._topology.bonds.values) != 0 + ): donors_ag = find_hydrogen_donors(hydrogens_ag) donors_ag = donors_ag.intersection(self.u.select_atoms(select)) else: @@ -541,7 +558,7 @@ def guess_donors(self, select='all', max_charge=-0.5): "({donors_sel}) and around {d_h_cutoff} {hydrogens_sel}".format( donors_sel=select, d_h_cutoff=self.d_h_cutoff, - hydrogens_sel=hydrogens_sel + hydrogens_sel=hydrogens_sel, ) ) @@ -549,17 +566,17 @@ def guess_donors(self, select='all', max_charge=-0.5): return self._group_categories(donors_ag) - def guess_acceptors(self, select='all', max_charge=-0.5): + def guess_acceptors(self, select="all", max_charge=-0.5): """Guesses which atoms could be considered acceptors in the analysis. - Acceptor selections may be achieved with either a resname, atom + Acceptor selections may be achieved with either a resname, atom name combination, or when those are absent, atom types. Parameters ---------- select: str (optional) :ref:`Selection string ` for atom group - from which acceptors will be identified. (e.g., ``(resname X and + from which acceptors will be identified. (e.g., ``(resname X and name O1)`` or ``type 2``) max_charge: float (optional) The charge of an acceptor atom must be less than this value. @@ -567,25 +584,25 @@ def guess_acceptors(self, select='all', max_charge=-0.5): Returns ------- potential_acceptors: str - String containing the :attr:`resname` and :attr:`name` of all atoms + String containing the :attr:`resname` and :attr:`name` of all atoms that potentially capable of forming hydrogen bonds. Notes ----- - Acceptor selections may be achieved with either a resname, atom + Acceptor selections may be achieved with either a resname, atom name combination, or when those are absent, atom types. - This function makes use of and atomic charges to identify which atoms - could be considered acceptor atoms in the hydrogen bond analysis. If - an atom has an atomic charge less than :attr:`max_charge` then it is + This function makes use of and atomic charges to identify which atoms + could be considered acceptor atoms in the hydrogen bond analysis. If + an atom has an atomic charge less than :attr:`max_charge` then it is considered capable of participating in hydrogen bonds. - If :attr:`acceptors_sel` is `None`, this function is called to guess + If :attr:`acceptors_sel` is `None`, this function is called to guess the selection. - Alternatively, this function may be used to quickly generate a - :class:`str` of potential acceptor atoms involved in hydrogen bonding. - This :class:`str` may then be modified before being used to set the + Alternatively, this function may be used to quickly generate a + :class:`str` of potential acceptor atoms involved in hydrogen bonding. + This :class:`str` may then be modified before being used to set the attribute :attr:`acceptors_sel`. @@ -601,14 +618,14 @@ def guess_acceptors(self, select='all', max_charge=-0.5): @staticmethod def _group_categories(group): - """ Find categories according to universe constraints - + """Find categories according to universe constraints + Parameters ---------- group : AtomGroup - AtomGroups corresponding to either hydrogen bond acceptors, + AtomGroups corresponding to either hydrogen bond acceptors, donors, or hydrogen atoms that meet their respective charge - and mass constraints. + and mass constraints. Returns ------- @@ -621,16 +638,14 @@ def _group_categories(group): """ if hasattr(group, "resnames") and hasattr(group, "names"): - group_list = np.unique([ - '(resname {} and name {})'.format(r, - p) for r, p in zip(group.resnames, group.names) - ]) - else: group_list = np.unique( [ - 'type {}'.format(tp) for tp in group.types + "(resname {} and name {})".format(r, p) + for r, p in zip(group.resnames, group.names) ] ) + else: + group_list = np.unique(["type {}".format(tp) for tp in group.types]) return " or ".join(group_list) @@ -640,7 +655,7 @@ def _get_dh_pairs(self): Returns ------- donors, hydrogens: AtomGroup, AtomGroup - AtomGroups corresponding to all donors and all hydrogens. + AtomGroups corresponding to all donors and all hydrogens. AtomGroups are ordered such that, if zipped, will produce a list of donor-hydrogen pairs. """ @@ -651,15 +666,23 @@ def _get_dh_pairs(self): # We're using u._topology.bonds rather than u.bonds as it is a million times faster to access. # This is because u.bonds also calculates properties of each bond (e.g bond length). # See https://github.com/MDAnalysis/mdanalysis/issues/2396#issuecomment-596251787 - if not (hasattr(self.u._topology, 'bonds') and len(self.u._topology.bonds.values) != 0): - raise NoDataError('Cannot assign donor-hydrogen pairs via topology as no bond information is present. ' - 'Please either: load a topology file with bond information; use the guess_bonds() ' - 'topology guesser; or set HydrogenBondAnalysis.donors_sel so that a distance cutoff ' - 'can be used.') + if not ( + hasattr(self.u._topology, "bonds") + and len(self.u._topology.bonds.values) != 0 + ): + raise NoDataError( + "Cannot assign donor-hydrogen pairs via topology as no bond information is present. " + "Please either: load a topology file with bond information; use the guess_bonds() " + "topology guesser; or set HydrogenBondAnalysis.donors_sel so that a distance cutoff " + "can be used." + ) hydrogens = self.u.select_atoms(self.hydrogens_sel) - donors = sum(h.bonded_atoms[0] for h in hydrogens) if hydrogens \ + donors = ( + sum(h.bonded_atoms[0] for h in hydrogens) + if hydrogens else AtomGroup([], self.u) + ) # Otherwise, use d_h_cutoff as a cutoff distance else: @@ -671,7 +694,7 @@ def _get_dh_pairs(self): hydrogens.positions, max_cutoff=self.d_h_cutoff, box=self.u.dimensions, - return_distances=False + return_distances=False, ).T donors = donors[donors_indices] @@ -682,20 +705,20 @@ def _get_dh_pairs(self): def _filter_atoms(self, donors, acceptors): """Create a mask to filter donor, hydrogen and acceptor atoms. - This can be used to consider only hydrogen bonds between two or more - specified groups. + This can be used to consider only hydrogen bonds between two or more + specified groups. - Groups are specified with the `between` keyword when creating the - HydrogenBondAnalysis object. + Groups are specified with the `between` keyword when creating the + HydrogenBondAnalysis object. - Returns - ------- - mask: np.ndarray + Returns + ------- + mask: np.ndarray - .. versionchanged:: 2.5.0 - Change return value to a mask instead of separate AtomGroups. -`` + .. versionchanged:: 2.5.0 + Change return value to a mask instead of separate AtomGroups. + `` """ mask = np.full(donors.n_atoms, fill_value=False) @@ -703,27 +726,25 @@ def _filter_atoms(self, donors, acceptors): # Find donors in G1 and acceptors in G2 mask[ - np.logical_and( - np.isin(donors.indices, group1.indices), - np.isin(acceptors.indices, group2.indices) - ) + np.logical_and( + np.isin(donors.indices, group1.indices), + np.isin(acceptors.indices, group2.indices), + ) ] = True # Find acceptors in G1 and donors in G2 mask[ np.logical_and( np.isin(acceptors.indices, group1.indices), - np.isin(donors.indices, group2.indices) + np.isin(donors.indices, group2.indices), ) ] = True return mask - def _prepare(self): self.results.hbonds = [[], [], [], [], [], []] - def _single_frame(self): box = self._ts.dimensions @@ -770,7 +791,7 @@ def _single_frame(self): tmp_donors.positions, tmp_hydrogens.positions, tmp_acceptors.positions, - box=box + box=box, ) ) hbond_indices = np.where(d_h_a_angles > self.d_h_a_angle)[0] @@ -790,8 +811,7 @@ def _single_frame(self): hbond_angles = d_h_a_angles[hbond_indices] # Store data on hydrogen bonds found at this frame - self.results.hbonds[0].extend(np.full_like(hbond_donors, - self._ts.frame)) + self.results.hbonds[0].extend(np.full_like(hbond_donors, self._ts.frame)) self.results.hbonds[1].extend(hbond_donors.indices) self.results.hbonds[2].extend(hbond_hydrogens.indices) self.results.hbonds[3].extend(hbond_acceptors.indices) @@ -803,13 +823,15 @@ def _conclude(self): self.results.hbonds = np.asarray(self.results.hbonds).T def _get_aggregator(self): - return ResultsGroup(lookup={'hbonds': ResultsGroup.ndarray_hstack}) + return ResultsGroup(lookup={"hbonds": ResultsGroup.ndarray_hstack}) @property def hbonds(self): - wmsg = ("The `hbonds` attribute was deprecated in MDAnalysis 2.0.0 " - "and will be removed in MDAnalysis 3.0.0. Please use " - "`results.hbonds` instead.") + wmsg = ( + "The `hbonds` attribute was deprecated in MDAnalysis 2.0.0 " + "and will be removed in MDAnalysis 3.0.0. Please use " + "`results.hbonds` instead." + ) warnings.warn(wmsg, DeprecationWarning) return self.results.hbonds @@ -864,8 +886,7 @@ def lifetime(self, tau_max=20, window_step=1, intermittency=0): "before the hydrogen bonds are found" ) logger.error( - "Autocorrelation: Please use the .run() before calling this" - "function" + "Autocorrelation: Please use the .run() before calling this" "function" ) raise NoDataError(".hbonds attribute is None: use .run() first") @@ -890,13 +911,10 @@ def lifetime(self, tau_max=20, window_step=1, intermittency=0): found_hydrogen_bonds[frame_index].add(frozenset(hbond[2:4])) intermittent_hbonds = correct_intermittency( - found_hydrogen_bonds, - intermittency=intermittency + found_hydrogen_bonds, intermittency=intermittency ) tau_timeseries, timeseries, timeseries_data = autocorrelation( - intermittent_hbonds, - tau_max, - window_step=window_step + intermittent_hbonds, tau_max, window_step=window_step ) return np.vstack([tau_timeseries, timeseries]) @@ -925,13 +943,13 @@ def count_by_type(self): Returns ------- counts : numpy.ndarray - Each row of the array contains the donor resname, donor atom type, - acceptor resname, acceptor atom type and the total number of times + Each row of the array contains the donor resname, donor atom type, + acceptor resname, acceptor atom type and the total number of times the hydrogen bond was found. Note ---- - Unique hydrogen bonds are determined through a consideration of the + Unique hydrogen bonds are determined through a consideration of the resname and atom type of the donor and acceptor atoms in a hydrogen bond. """ @@ -946,12 +964,12 @@ def count_by_type(self): a_res = len(a.types) * ["None"] tmp_hbonds = np.array([d_res, d.types, a_res, a.types], dtype=str).T - hbond_type, type_counts = np.unique( - tmp_hbonds, axis=0, return_counts=True) + hbond_type, type_counts = np.unique(tmp_hbonds, axis=0, return_counts=True) hbond_type_list = [] for hb_type, hb_count in zip(hbond_type, type_counts): - hbond_type_list.append([":".join(hb_type[:2]), - ":".join(hb_type[2:4]), hb_count]) + hbond_type_list.append( + [":".join(hb_type[:2]), ":".join(hb_type[2:4]), hb_count] + ) return np.array(hbond_type_list) @@ -975,12 +993,10 @@ def count_by_ids(self): a = self.u.atoms[self.results.hbonds[:, 3].astype(np.intp)] tmp_hbonds = np.array([d.ids, h.ids, a.ids]).T - hbond_ids, ids_counts = np.unique(tmp_hbonds, axis=0, - return_counts=True) + hbond_ids, ids_counts = np.unique(tmp_hbonds, axis=0, return_counts=True) # Find unique hbonds and sort rows so that most frequent observed bonds are at the top of the array - unique_hbonds = np.concatenate((hbond_ids, ids_counts[:, None]), - axis=1) + unique_hbonds = np.concatenate((hbond_ids, ids_counts[:, None]), axis=1) unique_hbonds = unique_hbonds[unique_hbonds[:, 3].argsort()[::-1]] return unique_hbonds @@ -988,7 +1004,7 @@ def count_by_ids(self): @property def donors_sel(self): """Selection string for the hydrogen bond donor atoms. - + .. versionadded:: 2.10.0 """ return self._donors_sel @@ -1001,7 +1017,7 @@ def donors_sel(self, value): @property def hydrogens_sel(self): """Selection string for the hydrogen bond hydrogen atoms. - + .. versionadded:: 2.10.0 """ return self._hydrogens_sel @@ -1016,7 +1032,7 @@ def hydrogens_sel(self, value): @property def acceptors_sel(self): """Selection string for the hydrogen bond acceptor atoms. - + .. versionadded:: 2.10.0 """ return self._acceptors_sel @@ -1026,5 +1042,6 @@ def acceptors_sel(self, value): self._acceptors_sel = value if self._acceptors_sel is None: self._acceptors_sel = self.guess_acceptors() - self._acceptors = self.u.select_atoms(self._acceptors_sel, - updating=self.update_selections) \ No newline at end of file + self._acceptors = self.u.select_atoms( + self._acceptors_sel, updating=self.update_selections + ) diff --git a/package/MDAnalysis/analysis/hydrogenbonds/hbond_autocorrel.py b/package/MDAnalysis/analysis/hydrogenbonds/hbond_autocorrel.py index 749fe3533c1..46aa49e15e9 100644 --- a/package/MDAnalysis/analysis/hydrogenbonds/hbond_autocorrel.py +++ b/package/MDAnalysis/analysis/hydrogenbonds/hbond_autocorrel.py @@ -204,6 +204,7 @@ :members: """ + import numpy as np import scipy.optimize import warnings @@ -328,20 +329,16 @@ def __init__( if exclusions is not None: if len(exclusions[0]) != len(exclusions[1]): - raise ValueError( - "'exclusion' must be two arrays of identical length" - ) - self.exclusions = np.column_stack( - (exclusions[0], exclusions[1]) - ).astype(np.intp) + raise ValueError("'exclusion' must be two arrays of identical length") + self.exclusions = np.column_stack((exclusions[0], exclusions[1])).astype( + np.intp + ) else: self.exclusions = None self.bond_type = bond_type if self.bond_type not in ["continuous", "intermittent"]: - raise ValueError( - "bond_type must be either 'continuous' or 'intermittent'" - ) + raise ValueError("bond_type must be either 'continuous' or 'intermittent'") self.a_crit = np.deg2rad(angle_crit) self.d_crit = dist_crit @@ -371,9 +368,7 @@ def _slice_traj(self, sample_time): if req_frames > n_frames: warnings.warn( "Number of required frames ({}) greater than the" - " number of frames in trajectory ({})".format( - req_frames, n_frames - ), + " number of frames in trajectory ({})".format(req_frames, n_frames), RuntimeWarning, ) @@ -477,9 +472,7 @@ def _single_run(self, start, stop): aidx = aidx[idx2] nbonds = len(hidx) # number of hbonds at t=0 - results = np.zeros_like( - np.arange(start, stop, self._skip), dtype=np.float32 - ) + results = np.zeros_like(np.arange(start, stop, self._skip), dtype=np.float32) if self.time_cut: # counter for time criteria @@ -488,9 +481,7 @@ def _single_run(self, start, stop): for i, ts in enumerate(self.u.trajectory[start : stop : self._skip]): box = self.u.dimensions if self.pbc else None - d = calc_bonds( - self.h.positions[hidx], self.a.positions[aidx], box=box - ) + d = calc_bonds(self.h.positions[hidx], self.a.positions[aidx], box=box) a = calc_angles( self.d.positions[hidx], self.h.positions[hidx], @@ -615,9 +606,7 @@ def triple(x, A1, A2, tau1, tau2, tau3): """Sum of three exponential functions""" A3 = 1 - (A1 + A2) return ( - A1 * np.exp(-x / tau1) - + A2 * np.exp(-x / tau2) - + A3 * np.exp(-x / tau3) + A1 * np.exp(-x / tau1) + A2 * np.exp(-x / tau2) + A3 * np.exp(-x / tau3) ) if self.bond_type == "continuous": @@ -658,9 +647,7 @@ def triple(x, A1, A2, tau1, tau2, tau3): self.solution["ier"] = ier if ier in [1, 2, 3, 4]: # solution found if ier is one of these values - self.solution["estimate"] = self._my_solve( - self.solution["time"], *p - ) + self.solution["estimate"] = self._my_solve(self.solution["time"], *p) else: warnings.warn("Solution to results not found", RuntimeWarning) diff --git a/package/MDAnalysis/analysis/hydrogenbonds/wbridge_analysis.py b/package/MDAnalysis/analysis/hydrogenbonds/wbridge_analysis.py index 027c0b71255..910f8946e70 100644 --- a/package/MDAnalysis/analysis/hydrogenbonds/wbridge_analysis.py +++ b/package/MDAnalysis/analysis/hydrogenbonds/wbridge_analysis.py @@ -706,6 +706,7 @@ def analysis(current, output, u, **kwargs): Will be removed in MDAnalysis 3.0.0. Please use :attr:`results.timeseries` instead. """ + import logging import warnings from collections import defaultdict @@ -789,9 +790,7 @@ class WaterBridgeAnalysis(AnalysisBase): "OH", } ), - "GLYCAM06": tuple( - {"N", "NT", "O", "O2", "OH", "OS", "OW", "OY", "SM"} - ), + "GLYCAM06": tuple({"N", "NT", "O", "O2", "OH", "OS", "OW", "OY", "SM"}), "other": tuple(set([])), } @@ -959,9 +958,7 @@ def __init__( """ - super(WaterBridgeAnalysis, self).__init__( - universe.trajectory, **kwargs - ) + super(WaterBridgeAnalysis, self).__init__(universe.trajectory, **kwargs) self.water_selection = water_selection self.update_water_selection = update_water_selection # per-frame debugging output? @@ -1001,9 +998,7 @@ def __init__( acceptors = () self.forcefield = forcefield self.donors = tuple(set(self.DEFAULT_DONORS[forcefield]).union(donors)) - self.acceptors = tuple( - set(self.DEFAULT_ACCEPTORS[forcefield]).union(acceptors) - ) + self.acceptors = tuple(set(self.DEFAULT_ACCEPTORS[forcefield]).union(acceptors)) if self.selection1_type not in ("both", "donor", "acceptor"): raise ValueError( @@ -1092,15 +1087,11 @@ def _update_selection(self): "Size of selection 1 before filtering:" " {} atoms".format(len(self._s1)) ) - ns_selection_1 = AtomNeighborSearch( - self.u.atoms[self._s1], box=self.box - ) + ns_selection_1 = AtomNeighborSearch(self.u.atoms[self._s1], box=self.box) self._s1 = ns_selection_1.search( self.u.atoms[self._s2], self.selection_distance ).ix - self.logger_debug( - "Size of selection 1: {0} atoms".format(len(self._s1)) - ) + self.logger_debug("Size of selection 1: {0} atoms".format(len(self._s1))) if len(self._s1) == 0: logger.warning( @@ -1115,15 +1106,11 @@ def _update_selection(self): "Size of selection 2 before filtering:" " {} atoms".format(len(self._s2)) ) - ns_selection_2 = AtomNeighborSearch( - self.u.atoms[self._s2], box=self.box - ) + ns_selection_2 = AtomNeighborSearch(self.u.atoms[self._s2], box=self.box) self._s2 = ns_selection_2.search( self.u.atoms[self._s1], self.selection_distance ).ix - self.logger_debug( - "Size of selection 2: {0} atoms".format(len(self._s2)) - ) + self.logger_debug("Size of selection 2: {0} atoms".format(len(self._s2))) if len(self._s2) == 0: logger.warning( @@ -1140,16 +1127,10 @@ def _update_selection(self): .ix ) for atom_ix in self._s1_donors: - self._update_donor_h( - atom_ix, self._s1_h_donors, self._s1_donors_h - ) + self._update_donor_h(atom_ix, self._s1_h_donors, self._s1_donors_h) + self.logger_debug("Selection 1 donors: {0}".format(len(self._s1_donors))) self.logger_debug( - "Selection 1 donors: {0}".format(len(self._s1_donors)) - ) - self.logger_debug( - "Selection 1 donor hydrogens: {0}".format( - len(self._s1_h_donors) - ) + "Selection 1 donor hydrogens: {0}".format(len(self._s1_h_donors)) ) if self.selection1_type in ("acceptor", "both"): self._s1_acceptors = ( @@ -1179,16 +1160,10 @@ def _update_selection(self): .ix ) for atom_ix in self._s2_donors: - self._update_donor_h( - atom_ix, self._s2_h_donors, self._s2_donors_h - ) + self._update_donor_h(atom_ix, self._s2_h_donors, self._s2_donors_h) + self.logger_debug("Selection 2 donors: {0:d}".format(len(self._s2_donors))) self.logger_debug( - "Selection 2 donors: {0:d}".format(len(self._s2_donors)) - ) - self.logger_debug( - "Selection 2 donor hydrogens: {0:d}".format( - len(self._s2_h_donors) - ) + "Selection 2 donor hydrogens: {0:d}".format(len(self._s2_h_donors)) ) def _update_water_selection(self): @@ -1213,9 +1188,7 @@ def _update_water_selection(self): .ix ) - self.logger_debug( - "Size of water selection: {0} atoms".format(len(self._water)) - ) + self.logger_debug("Size of water selection: {0} atoms".format(len(self._water))) if len(self._water) == 0: logger.warning( @@ -1233,9 +1206,7 @@ def _update_water_selection(self): self._update_donor_h( atom_ix, self._water_h_donors, self._water_donors_h ) - self.logger_debug( - "Water donors: {0}".format(len(self._water_donors)) - ) + self.logger_debug("Water donors: {0}".format(len(self._water_donors))) self.logger_debug( "Water donor hydrogens: {0}".format(len(self._water_h_donors)) ) @@ -1244,9 +1215,7 @@ def _update_water_selection(self): .select_atoms("name {0}".format(" ".join(self.acceptors))) .ix ) - self.logger_debug( - "Water acceptors: {0}".format(len(self._water_acceptors)) - ) + self.logger_debug("Water acceptors: {0}".format(len(self._water_acceptors))) def _get_bonded_hydrogens(self, atom): """Find hydrogens bonded within cutoff to `atom`. @@ -1305,18 +1274,14 @@ def _prepare(self): if len(self._s1) and len(self._s2): self._update_water_selection() else: - logger.info( - "WaterBridgeAnalysis: " "no atoms found in the selection." - ) + logger.info("WaterBridgeAnalysis: " "no atoms found in the selection.") logger.info("WaterBridgeAnalysis: initial checks passed.") logger.info("WaterBridgeAnalysis: starting") logger.debug("WaterBridgeAnalysis: donors %r", self.donors) logger.debug("WaterBridgeAnalysis: acceptors %r", self.acceptors) - logger.debug( - "WaterBridgeAnalysis: water bridge %r", self.water_selection - ) + logger.debug("WaterBridgeAnalysis: water bridge %r", self.water_selection) if self.debug: logger.debug("Toggling debug to %r", self.debug) @@ -1430,9 +1395,7 @@ def _single_frame(self): angle, ) = line water_pool[(a_resname, a_resid)] = None - selection_1.append( - (h_index, d_index, a_index, None, dist, angle) - ) + selection_1.append((h_index, d_index, a_index, None, dist, angle)) selection_2.append((a_resname, a_resid)) if self.order > 0: self.logger_debug("Selection 1 Donors <-> Water Acceptors") @@ -1449,9 +1412,7 @@ def _single_frame(self): dist, angle, ) = line - selection_1.append( - (h_index, d_index, a_index, None, dist, angle) - ) + selection_1.append((h_index, d_index, a_index, None, dist, angle)) self.logger_debug("Water Donors <-> Selection 2 Acceptors") results = self._donor2acceptor( @@ -1490,9 +1451,7 @@ def _single_frame(self): angle, ) = line water_pool[(h_resname, h_resid)] = None - selection_1.append( - (a_index, None, h_index, d_index, dist, angle) - ) + selection_1.append((a_index, None, h_index, d_index, dist, angle)) selection_2.append((h_resname, h_resid)) if self.order > 0: @@ -1531,9 +1490,7 @@ def _single_frame(self): dist, angle, ) = line - selection_1.append( - (a_index, None, h_index, d_index, dist, angle) - ) + selection_1.append((a_index, None, h_index, d_index, dist, angle)) if self.order > 1: self.logger_debug("Water donor <-> Water Acceptors") @@ -1610,9 +1567,9 @@ def traverse_water_network(graph, node, end, route, maxdepth, result): for new_node in graph[node]: new_route = route[:] new_route.append(new_node) - new_node = self._expand_timeseries( - new_node, "sele1_sele2" - )[3][:2] + new_node = self._expand_timeseries(new_node, "sele1_sele2")[3][ + :2 + ] traverse_water_network( graph, new_node, end, new_route, maxdepth, result ) @@ -1736,8 +1693,7 @@ def _expand_timeseries(self, entry, output_format=None): atom1, atom2 = atom1, atom2 else: raise KeyError( - "Only 'sele1_sele2' or 'donor_acceptor' are allowed as output " - "format" + "Only 'sele1_sele2' or 'donor_acceptor' are allowed as output " "format" ) return ( @@ -1787,10 +1743,7 @@ def analysis(current, output, *args, **kwargs): link_func=self._compact_link, ) timeseries.append( - [ - self._expand_timeseries(entry, output_format) - for entry in new_frame - ] + [self._expand_timeseries(entry, output_format) for entry in new_frame] ) return timeseries @@ -1837,12 +1790,12 @@ def _count_by_type_analysis(self, current, output, *args, **kwargs): :return: """ - s1_index, to_index, s1, to_residue, dist, angle = ( - self._expand_timeseries(current[0]) + s1_index, to_index, s1, to_residue, dist, angle = self._expand_timeseries( + current[0] ) s1_resname, s1_resid, s1_name = s1 - from_index, s2_index, from_residue, s2, dist, angle = ( - self._expand_timeseries(current[-1]) + from_index, s2_index, from_residue, s2, dist, angle = self._expand_timeseries( + current[-1] ) s2_resname, s2_resid, s2_name = s2 key = ( @@ -1908,20 +1861,18 @@ def count_by_type(self, analysis_func=None, **kwargs): for i, key in enumerate(result_dict) ] else: - result = [ - (key, result_dict[key] / length) for key in result_dict - ] + result = [(key, result_dict[key] / length) for key in result_dict] return result else: return None def _count_by_time_analysis(self, current, output, *args, **kwargs): - s1_index, to_index, s1, to_residue, dist, angle = ( - self._expand_timeseries(current[0]) + s1_index, to_index, s1, to_residue, dist, angle = self._expand_timeseries( + current[0] ) s1_resname, s1_resid, s1_name = s1 - from_index, s2_index, from_residue, s2, dist, angle = ( - self._expand_timeseries(current[-1]) + from_index, s2_index, from_residue, s2, dist, angle = self._expand_timeseries( + current[-1] ) s2_resname, s2_resid, s2_name = s2 key = ( @@ -1963,20 +1914,18 @@ def count_by_time(self, analysis_func=None, **kwargs): link_func=self._full_link, **kwargs, ) - result.append( - (time, sum([result_dict[key] for key in result_dict])) - ) + result.append((time, sum([result_dict[key] for key in result_dict]))) return result else: return None def _timesteps_by_type_analysis(self, current, output, *args, **kwargs): - s1_index, to_index, s1, to_residue, dist, angle = ( - self._expand_timeseries(current[0]) + s1_index, to_index, s1, to_residue, dist, angle = self._expand_timeseries( + current[0] ) s1_resname, s1_resid, s1_name = s1 - from_index, s2_index, from_residue, s2, dist, angle = ( - self._expand_timeseries(current[-1]) + from_index, s2_index, from_residue, s2, dist, angle = self._expand_timeseries( + current[-1] ) s2_resname, s2_resid, s2_name = s2 key = ( @@ -2075,10 +2024,7 @@ def generate_table(self, output_format=None): logger.warning(msg) return None - if ( - self.results.timeseries is not None - and output_format == self.output_format - ): + if self.results.timeseries is not None and output_format == self.output_format: timeseries = self.results.timeseries else: # Recompute timeseries with correct output format @@ -2137,9 +2083,7 @@ def generate_table(self, output_format=None): + (distance, angle) ) cursor += 1 - assert ( - cursor == num_records - ), "Internal Error: Not all wb records stored" + assert cursor == num_records, "Internal Error: Not all wb records stored" table = out.view(np.rec.recarray) logger.debug( "WBridge: Stored results as table with %(num_records)d entries.", diff --git a/package/MDAnalysis/analysis/leaflet.py b/package/MDAnalysis/analysis/leaflet.py index 9ba5de87e7f..785ba6012ba 100644 --- a/package/MDAnalysis/analysis/leaflet.py +++ b/package/MDAnalysis/analysis/leaflet.py @@ -68,6 +68,7 @@ .. autofunction:: optimize_cutoff """ + import warnings import numpy as np @@ -77,7 +78,6 @@ from .. import selections from ..due import due, Doi - # networkx is an optional import try: import networkx as NX @@ -249,10 +249,7 @@ def update(self, cutoff=None): def sizes(self): """Dict of component index with size of component.""" return dict( - ( - (idx, len(component)) - for idx, component in enumerate(self.components) - ) + ((idx, len(component)) for idx, component in enumerate(self.components)) ) def groups(self, component_index=None): diff --git a/package/MDAnalysis/analysis/legacy/x3dna.py b/package/MDAnalysis/analysis/legacy/x3dna.py index 2365c181133..f202f95f0f5 100644 --- a/package/MDAnalysis/analysis/legacy/x3dna.py +++ b/package/MDAnalysis/analysis/legacy/x3dna.py @@ -117,6 +117,7 @@ .. autoexception:: ApplicationError """ + import errno import glob import logging @@ -330,9 +331,7 @@ def save(self, filename="x3dna.pickle"): """ import cPickle - cPickle.dump( - self.profiles, open(filename, "wb"), cPickle.HIGHEST_PROTOCOL - ) + cPickle.dump(self.profiles, open(filename, "wb"), cPickle.HIGHEST_PROTOCOL) def mean_std(self): """Returns the mean and standard deviation of base parameters. @@ -673,9 +672,7 @@ def __init__(self, filename, **kwargs): self.x3dna_param = kwargs.pop("x3dna_param", True) self.exe["xdna_ensemble"] = which(x3dna_exe_name) if self.exe["xdna_ensemble"] is None: - errmsg = "X3DNA binary {x3dna_exe_name!r} not found.".format( - **vars() - ) + errmsg = "X3DNA binary {x3dna_exe_name!r} not found.".format(**vars()) logger.fatal(errmsg) logger.fatal( "%(x3dna_exe_name)r must be on the PATH or provided as keyword argument 'executable'.", @@ -719,9 +716,7 @@ def run(self, **kwargs): f.write(inp) logger.debug("Wrote X3DNA input file %r for inspection", inpname) - logger.info( - "Starting X3DNA on %(filename)r (trajectory: %(dcd)r)", x3dnaargs - ) + logger.info("Starting X3DNA on %(filename)r (trajectory: %(dcd)r)", x3dnaargs) logger.debug("%s", self.exe["xdna_ensemble"]) with open(outname, "w") as output: x3dna = subprocess.call([inp], shell=True) @@ -772,20 +767,18 @@ def collect(self, **kwargs): outdir = kwargs.pop("outdir", os.path.curdir) logger.info("Collecting X3DNA profiles for run with id %s", run) - length = 1 # length of trajectory --- is this really needed?? No... just for info + length = ( + 1 # length of trajectory --- is this really needed?? No... just for info + ) if "*" in self.filename: import glob filenames = glob.glob(self.filename) length = len(filenames) if length == 0: - logger.error( - "Glob pattern %r did not find any files.", self.filename - ) + logger.error("Glob pattern %r did not find any files.", self.filename) raise ValueError( - "Glob pattern {0!r} did not find any files.".format( - self.filename - ) + "Glob pattern {0!r} did not find any files.".format(self.filename) ) logger.info( "Found %d input files based on glob pattern %s", @@ -842,9 +835,7 @@ def collect(self, **kwargs): run, line.strip(), ) - logger.exception( - "Check input file %r.", x3dna_output - ) + logger.exception("Check input file %r.", x3dna_output) raise records.append( [ @@ -894,9 +885,7 @@ def collect(self, **kwargs): run, line.strip(), ) - logger.exception( - "Check input file %r.", x3dna_output - ) + logger.exception("Check input file %r.", x3dna_output) raise records.append( [ @@ -941,9 +930,7 @@ def collect(self, **kwargs): os.makedirs(rundir) frame_x3dna_txt = os.path.join( rundir, - "bp_step_{0!s}_{1:04d}.dat.gz".format( - run, x3dna_profile_no - ), + "bp_step_{0!s}_{1:04d}.dat.gz".format(run, x3dna_profile_no), ) np.savetxt(frame_x3dna_txt, frame_x3dna_output) logger.debug( @@ -953,9 +940,7 @@ def collect(self, **kwargs): ) # if we get here then we haven't found anything interesting if len(self.profiles) == length: - logger.info( - "Collected X3DNA profiles for %d frames", len(self.profiles) - ) + logger.info("Collected X3DNA profiles for %d frames", len(self.profiles)) else: logger.warning( "Missing data: Found %d X3DNA profiles from %d frames.", @@ -1073,8 +1058,10 @@ def run(self, **kwargs): except OSError: pass if len(x3dna_profiles) != 1: - err_msg = "Got {0} profiles ({1}) --- should be 1 (time step {2})".format( - len(x3dna_profiles), x3dna_profiles.keys(), ts + err_msg = ( + "Got {0} profiles ({1}) --- should be 1 (time step {2})".format( + len(x3dna_profiles), x3dna_profiles.keys(), ts + ) ) logger.error(err_msg) warnings.warn(err_msg) diff --git a/package/MDAnalysis/analysis/lineardensity.py b/package/MDAnalysis/analysis/lineardensity.py index 369ade9b374..7886d1305d3 100644 --- a/package/MDAnalysis/analysis/lineardensity.py +++ b/package/MDAnalysis/analysis/lineardensity.py @@ -28,6 +28,7 @@ cartesian axes [xyz] of the simulation cell. Works only for orthorombic, fixed volume cells (thus for simulations in canonical NVT ensemble). """ + import os.path as path import numpy as np @@ -62,9 +63,7 @@ def _deprecation_warning(self, key): def __getitem__(self, key): if key in self._deprecation_dict.keys(): self._deprecation_warning(key) - return super(Results, self).__getitem__( - self._deprecation_dict[key] - ) + return super(Results, self).__getitem__(self._deprecation_dict[key]) return super(Results, self).__getitem__(key) def __getattr__(self, attr): @@ -214,9 +213,7 @@ def get_supported_backends(cls): ) def __init__(self, select, grouping="atoms", binsize=0.25, **kwargs): - super(LinearDensity, self).__init__( - select.universe.trajectory, **kwargs - ) + super(LinearDensity, self).__init__(select.universe.trajectory, **kwargs) # allows use of run(parallel=True) self._ags = [select] self._universe = select.universe @@ -267,23 +264,17 @@ def __init__(self, select, grouping="atoms", binsize=0.25, **kwargs): self.charges = self._ags[0].total_charge(compound=self.grouping) else: - raise AttributeError( - f"{self.grouping} is not a valid value for grouping." - ) + raise AttributeError(f"{self.grouping} is not a valid value for grouping.") @staticmethod def _custom_aggregator(results): # NB: the *stddev values here are not the standard deviation, # but the variance. The stddev is calculated in _conclude() - mass_density = np.sum( - [entry["mass_density"] for entry in results], axis=0 - ) + mass_density = np.sum([entry["mass_density"] for entry in results], axis=0) mass_density_stddev = np.sum( [entry["mass_density_stddev"] for entry in results], axis=0 ) - charge_density = np.sum( - [entry["charge_density"] for entry in results], axis=0 - ) + charge_density = np.sum([entry["charge_density"] for entry in results], axis=0) charge_density_stddev = np.sum( [entry["charge_density_stddev"] for entry in results], axis=0 ) @@ -316,9 +307,7 @@ def _single_frame(self): self.charges = self._ags[0].total_charge(compound=self.grouping) else: - raise AttributeError( - f"{self.grouping} is not a valid value for grouping." - ) + raise AttributeError(f"{self.grouping} is not a valid value for grouping.") self.group = getattr(self._ags[0], self.grouping) self._ags[0].wrap(compound=self.grouping) @@ -380,19 +369,17 @@ def _conclude(self): # radicand_mass and radicand_charge are therefore calculated first # and negative values set to 0 before the square root # is calculated. - radicand_mass = self.results[dim][ - "mass_density_stddev" - ] - np.square(self.results[dim]["mass_density"]) + radicand_mass = self.results[dim]["mass_density_stddev"] - np.square( + self.results[dim]["mass_density"] + ) radicand_mass[radicand_mass < 0] = 0 self.results[dim]["mass_density_stddev"] = np.sqrt(radicand_mass) - radicand_charge = self.results[dim][ - "charge_density_stddev" - ] - np.square(self.results[dim]["charge_density"]) - radicand_charge[radicand_charge < 0] = 0 - self.results[dim]["charge_density_stddev"] = np.sqrt( - radicand_charge + radicand_charge = self.results[dim]["charge_density_stddev"] - np.square( + self.results[dim]["charge_density"] ) + radicand_charge[radicand_charge < 0] = 0 + self.results[dim]["charge_density_stddev"] = np.sqrt(radicand_charge) for dim in ["x", "y", "z"]: # norming factor, units of mol^-1 cm^3 @@ -404,8 +391,7 @@ def _conclude(self): @deprecate( release="2.2.0", remove="3.0.0", - message="It will be replaced by a :meth:`_reduce` " - "method in the future", + message="It will be replaced by a :meth:`_reduce` " "method in the future", ) def _add_other_results(self, other): """For parallel analysis""" diff --git a/package/MDAnalysis/analysis/msd.py b/package/MDAnalysis/analysis/msd.py index 814ea37bed3..98ecf11caaf 100644 --- a/package/MDAnalysis/analysis/msd.py +++ b/package/MDAnalysis/analysis/msd.py @@ -64,26 +64,26 @@ .. warning:: To correctly compute the MSD using this analysis module, you must supply - coordinates in the **unwrapped** convention, also known as **no-jump**. - That is, when atoms pass the periodic boundary, they must not be wrapped + coordinates in the **unwrapped** convention, also known as **no-jump**. + That is, when atoms pass the periodic boundary, they must not be wrapped back into the primary simulation cell. - - In MDAnalysis you can use the + + In MDAnalysis you can use the :class:`~MDAnalysis.transformations.nojump.NoJump` transformation to unwrap coordinates on-the-fly. - + A minimal example: .. code-block:: python - + import MDAnalysis as mda from MDAnalysis.transformations import NoJump - + u = mda.Universe(TOP, TRAJ) - + # Apply NoJump transformation to unwrap coordinates u.trajectory.add_transformations(NoJump(u)) - + # Now the trajectory is unwrapped and MSD can be computed normally: from MDAnalysis.analysis.msd import EinsteinMSD MSD = EinsteinMSD(u, select="all", msd_type="xyz") @@ -94,11 +94,11 @@ dimensions must be defined before applying ``NoJump``, which can be accomplished by applying the :class:`~MDAnalysis.transformations.boxdimensions.set_dimensions` - transformation *before* the + transformation *before* the :class:`~MDAnalysis.transformations.nojump.NoJump` transformation. - + This replaces the need to preprocess trajectories externally. - + In GROMACS, for example, this can be done using `gmx trjconv`_ with the ``-pbc nojump`` flag. @@ -363,9 +363,7 @@ def __init__( **kwargs, ): if isinstance(u, groups.UpdatingAtomGroup): - raise TypeError( - "UpdatingAtomGroups are not valid for MSD computation" - ) + raise TypeError("UpdatingAtomGroups are not valid for MSD computation") super(EinsteinMSD, self).__init__(u.universe.trajectory, **kwargs) @@ -389,12 +387,8 @@ def __init__( def _prepare(self): # self.n_frames only available here # these need to be zeroed prior to each run() call - self.results.msds_by_particle = np.zeros( - (self.n_frames, self.n_particles) - ) - self._position_array = np.zeros( - (self.n_frames, self.n_particles, self.dim_fac) - ) + self.results.msds_by_particle = np.zeros((self.n_frames, self.n_particles)) + self._position_array = np.zeros((self.n_frames, self.n_particles, self.dim_fac)) # self.results.timeseries not set here def _parse_msd_type(self): @@ -422,9 +416,7 @@ def _single_frame(self): r"""Constructs array of positions for MSD calculation.""" # shape of position array set here, use span in last dimension # from this point on - self._position_array[self._frame_index] = self.ag.positions[ - :, self._dim - ] + self._position_array[self._frame_index] = self.ag.positions[:, self._dim] def _conclude(self): if self.non_linear: @@ -457,8 +449,7 @@ def _conclude_fft(self): # with FFT, np.float64 bit prescision required. try: import tidynamics except ImportError: - raise ImportError( - """ERROR --- tidynamics was not found! + raise ImportError("""ERROR --- tidynamics was not found! tidynamics is required to compute an FFT based MSD (default) @@ -466,8 +457,7 @@ def _conclude_fft(self): # with FFT, np.float64 bit prescision required. pip install tidynamics - or set fft=False""" - ) + or set fft=False""") positions = self._position_array.astype(np.float64) for n in ProgressBar( @@ -475,9 +465,7 @@ def _conclude_fft(self): # with FFT, np.float64 bit prescision required. verbose=self._verbose, desc="Calculating MSD with FFT per particle", ): - self.results.msds_by_particle[:, n] = tidynamics.msd( - positions[:, n, :] - ) + self.results.msds_by_particle[:, n] = tidynamics.msd(positions[:, n, :]) self.results.timeseries = self.results.msds_by_particle.mean(axis=1) self.results.delta_t_values = np.arange(self.n_frames) * ( self.times[1] - self.times[0] diff --git a/package/MDAnalysis/analysis/nucleicacids.py b/package/MDAnalysis/analysis/nucleicacids.py index bf68a954cb3..7e8fe578b93 100644 --- a/package/MDAnalysis/analysis/nucleicacids.py +++ b/package/MDAnalysis/analysis/nucleicacids.py @@ -73,7 +73,6 @@ from .base import AnalysisBase, ResultsGroup from MDAnalysis.core.groups import Residue, ResidueGroup - # Deprecation: In 3.0.0 change type to just # ResidueClass = ResidueGroup ResidueClass = Union[List[Residue], ResidueGroup] @@ -182,9 +181,7 @@ def __init__( selection2: List[mda.AtomGroup], **kwargs, ) -> None: - super(NucPairDist, self).__init__( - selection1[0].universe.trajectory, **kwargs - ) + super(NucPairDist, self).__init__(selection1[0].universe.trajectory, **kwargs) if len(selection1) != len(selection2): raise ValueError("Selections must be same length") @@ -268,9 +265,7 @@ def select_strand_atoms( elif pair[0].resname[0] in purines: a1, a2 = a1_name, a2_name else: - raise ValueError( - f"AtomGroup in {pair} is not a valid nucleic acid" - ) + raise ValueError(f"AtomGroup in {pair} is not a valid nucleic acid") ag1 = pair[0].atoms.select_atoms(f"name {a1}") ag2 = pair[1].atoms.select_atoms(f"name {a2}") @@ -293,9 +288,7 @@ def select_strand_atoms( return (sel1, sel2) def _prepare(self) -> None: - self.results.distances: np.ndarray = np.zeros( - [self.n_frames, self._n_sel] - ) + self.results.distances: np.ndarray = np.zeros([self.n_frames, self._n_sel]) def _single_frame(self) -> None: dist: np.ndarray = calc_bonds(self._s1.positions, self._s2.positions) @@ -581,9 +574,7 @@ def __init__( ) ) - super(MinorPairDist, self).__init__( - selections[0], selections[1], **kwargs - ) + super(MinorPairDist, self).__init__(selections[0], selections[1], **kwargs) class MajorPairDist(NucPairDist): @@ -679,6 +670,4 @@ def __init__( ) ) - super(MajorPairDist, self).__init__( - selections[0], selections[1], **kwargs - ) + super(MajorPairDist, self).__init__(selections[0], selections[1], **kwargs) diff --git a/package/MDAnalysis/analysis/nuclinfo.py b/package/MDAnalysis/analysis/nuclinfo.py index a6772599142..67f874c9506 100644 --- a/package/MDAnalysis/analysis/nuclinfo.py +++ b/package/MDAnalysis/analysis/nuclinfo.py @@ -92,6 +92,7 @@ .. autofunction:: pseudo_dihe_baseflip """ + import numpy as np from math import pi, sin, cos, sqrt, pow diff --git a/package/MDAnalysis/analysis/pca.py b/package/MDAnalysis/analysis/pca.py index fddbf7d0092..4dd2272009e 100644 --- a/package/MDAnalysis/analysis/pca.py +++ b/package/MDAnalysis/analysis/pca.py @@ -114,6 +114,7 @@ .. autofunction:: cumulative_overlap """ + import warnings import numpy as np @@ -614,12 +615,8 @@ def project_single_frame(self, components=None, group=None, anchor=None): non_pca_atoms = np.array([], dtype=int) for res in group.residues: # n_common is the number of pca atoms in a residue - n_common = pca_res_counts[ - np.where(pca_res_indices == res.resindex) - ][0] - non_pca_atoms = np.append( - non_pca_atoms, res.atoms.n_atoms - n_common - ) + n_common = pca_res_counts[np.where(pca_res_indices == res.resindex)][0] + non_pca_atoms = np.append(non_pca_atoms, res.atoms.n_atoms - n_common) # index_extrapolate records the anchor number for each non-PCA atom index_extrapolate = np.repeat( np.arange(anchors.atoms.n_atoms), non_pca_atoms @@ -724,9 +721,7 @@ def rmsip(self, other, n_components=None): b = other.results.p_components except AttributeError: if isinstance(other, type(self)): - raise ValueError( - "Call run() on the other PCA before using rmsip" - ) + raise ValueError("Call run() on the other PCA before using rmsip") else: raise ValueError("other must be another PCA class") @@ -773,9 +768,7 @@ def cumulative_overlap(self, other, i=0, n_components=None): try: a = self.results.p_components except AttributeError: - raise ValueError( - "Call run() on the PCA before using cumulative_overlap" - ) + raise ValueError("Call run() on the PCA before using cumulative_overlap") try: b = other.results.p_components diff --git a/package/MDAnalysis/analysis/polymer.py b/package/MDAnalysis/analysis/polymer.py index 7a0510eab03..0a7a23b768b 100644 --- a/package/MDAnalysis/analysis/polymer.py +++ b/package/MDAnalysis/analysis/polymer.py @@ -32,6 +32,7 @@ This module contains various commonly used tools in analysing polymers. """ + import numpy as np import scipy.optimize import warnings @@ -69,9 +70,7 @@ def sort_backbone(backbone): """ degrees = [len(atom.bonded_atoms & backbone) for atom in backbone] deg1_atoms = [atom for atom, d in zip(backbone, degrees) if d == 1] - wrong_atoms = [ - atom for atom, d in zip(backbone, degrees) if d not in (1, 2) - ] + wrong_atoms = [atom for atom, d in zip(backbone, degrees) if d not in (1, 2)] if len(wrong_atoms) > 0: raise ValueError( @@ -318,9 +317,7 @@ def fit(self): def _conclude(self): norm = np.linspace(self.chainlength - 1, 1, self.chainlength - 1) norm *= len(self._atomgroups) * self._trajectory.n_frames - self.results.bond_autocorrelation = ( - self.results.raw_bond_autocorr / norm - ) + self.results.bond_autocorrelation = self.results.raw_bond_autocorr / norm self._calc_bond_length() self._perform_fit() diff --git a/package/MDAnalysis/analysis/rdf.py b/package/MDAnalysis/analysis/rdf.py index eef8a6a86ea..a5b9cdaaa78 100644 --- a/package/MDAnalysis/analysis/rdf.py +++ b/package/MDAnalysis/analysis/rdf.py @@ -76,6 +76,7 @@ .. - Structure factor? .. - Coordination number """ + import warnings import numpy as np @@ -315,8 +316,7 @@ def __init__( if self.norm not in ["rdf", "density", "none"]: raise ValueError( - f"'{self.norm}' is an invalid norm. " - "Use 'rdf', 'density' or 'none'." + f"'{self.norm}' is an invalid norm. " "Use 'rdf', 'density' or 'none'." ) self.backend = backend @@ -675,9 +675,7 @@ def __init__( backend="serial", **kwargs, ): - super(InterRDF_s, self).__init__( - ags[0][0].universe.trajectory, **kwargs - ) + super(InterRDF_s, self).__init__(ags[0][0].universe.trajectory, **kwargs) warnings.warn( "The `u` attribute is superflous and will be removed " @@ -691,8 +689,7 @@ def __init__( if self.norm not in ["rdf", "density", "none"]: raise ValueError( - f"'{self.norm}' is an invalid norm. " - "Use 'rdf', 'density' or 'none'." + f"'{self.norm}' is an invalid norm. " "Use 'rdf', 'density' or 'none'." ) if density: diff --git a/package/MDAnalysis/analysis/results.py b/package/MDAnalysis/analysis/results.py index 7708f3dd881..f34e5e74f0c 100644 --- a/package/MDAnalysis/analysis/results.py +++ b/package/MDAnalysis/analysis/results.py @@ -10,7 +10,7 @@ ------- The :class:`Results` class is an extension of a built-in dictionary -type, that holds all assigned attributes in :attr:`self.data` and +type, that holds all assigned attributes in :attr:`self.data` and allows for access either via dict-like syntax, or via class-like syntax: .. code-block:: python @@ -22,7 +22,7 @@ The :class:`ResultsGroup` can merge multiple :class:`Results` objects. -It is mainly used by :class:`MDAnalysis.analysis.base.AnalysisBase` class, +It is mainly used by :class:`MDAnalysis.analysis.base.AnalysisBase` class, that uses :meth:`ResultsGroup.merge()` method to aggregate results from multiple workers, initialized during a parallel run: @@ -30,7 +30,7 @@ from MDAnalysis.analysis.results import Results, ResultsGroup import numpy as np - + r1, r2 = Results(), Results() r1.masses = [1, 2, 3, 4, 5] r2.masses = [0, 0, 0, 0] @@ -101,9 +101,7 @@ class in `scikit-learn`_. def _validate_key(self, key): if key in dir(self): - raise AttributeError( - f"'{key}' is a protected dictionary attribute" - ) + raise AttributeError(f"'{key}' is a protected dictionary attribute") elif isinstance(key, str) and not key.isidentifier(): raise ValueError(f"'{key}' is not a valid attribute") @@ -128,17 +126,13 @@ def __getattr__(self, attr): try: return self[attr] except KeyError as err: - raise AttributeError( - f"'Results' object has no attribute '{attr}'" - ) from err + raise AttributeError(f"'Results' object has no attribute '{attr}'") from err def __delattr__(self, attr): try: del self[attr] except KeyError as err: - raise AttributeError( - f"'Results' object has no attribute '{attr}'" - ) from err + raise AttributeError(f"'Results' object has no attribute '{attr}'") from err def __getstate__(self): return self.data diff --git a/package/MDAnalysis/analysis/rms.py b/package/MDAnalysis/analysis/rms.py index f589a597d0a..78c54b13778 100644 --- a/package/MDAnalysis/analysis/rms.py +++ b/package/MDAnalysis/analysis/rms.py @@ -161,6 +161,7 @@ instead. """ + import numpy as np import logging @@ -171,7 +172,6 @@ from ..exceptions import SelectionError from ..lib.util import asiterable, iterable, get_weights - logger = logging.getLogger("MDAnalysis.analysis.rmsd") @@ -312,8 +312,7 @@ def process_selection(select): select = {"mobile": select[0], "reference": select[1]} except IndexError: raise IndexError( - "select must contain two selection strings " - "(reference, mobile)" + "select must contain two selection strings " "(reference, mobile)" ) from None elif type(select) is dict: # compatability hack to use new nomenclature @@ -552,9 +551,7 @@ def __init__( ) logger.exception(err) raise SelectionError(err) - logger.info( - "RMS calculation " "for {0:d} atoms.".format(len(self.ref_atoms)) - ) + logger.info("RMS calculation " "for {0:d} atoms.".format(len(self.ref_atoms))) mass_mismatches = ( np.absolute((self.ref_atoms.masses - self.mobile_atoms.masses)) > self.tol_mass @@ -596,9 +593,7 @@ def __init__( # *groupselections* groups each a dict with reference/mobile self._groupselections_atoms = [ { - "reference": self.reference.universe.select_atoms( - *s["reference"] - ), + "reference": self.reference.universe.select_atoms(*s["reference"]), "mobile": self.atomgroup.universe.select_atoms(*s["mobile"]), } for s in self.groupselections @@ -661,23 +656,18 @@ def __init__( get_weights(atoms["mobile"], weights) except Exception as e: raise type(e)( - str(e) - + " happens in selection %s" % selection["mobile"] + str(e) + " happens in selection %s" % selection["mobile"] ) def _prepare(self): self._n_atoms = self.mobile_atoms.n_atoms if not self.weights_groupselections: - if not iterable( - self.weights - ): # apply 'mass' or 'None' to groupselections + if not iterable(self.weights): # apply 'mass' or 'None' to groupselections self.weights_groupselections = [self.weights] * len( self.groupselections ) else: - self.weights_groupselections = [None] * len( - self.groupselections - ) + self.weights_groupselections = [None] * len(self.groupselections) for igroup, (weights, atoms) in enumerate( zip(self.weights_groupselections, self._groupselections_atoms) @@ -695,9 +685,9 @@ def _prepare(self): self.weights_select = np.asarray( self.weights_select, dtype=np.float64 ) / np.mean(self.weights_select) - self.weights_ref = np.asarray( - self.weights_ref, dtype=np.float64 - ) / np.mean(self.weights_ref) + self.weights_ref = np.asarray(self.weights_ref, dtype=np.float64) / np.mean( + self.weights_ref + ) current_frame = self.reference.universe.trajectory.ts.frame @@ -712,9 +702,9 @@ def _prepare(self): if self._groupselections_atoms: self._groupselections_ref_coords64 = [ ( - self.reference.select_atoms( - *s["reference"] - ).positions.astype(np.float64) + self.reference.select_atoms(*s["reference"]).positions.astype( + np.float64 + ) ) for s in self.groupselections ] @@ -747,9 +737,7 @@ def _get_aggregator(self): return ResultsGroup(lookup={"rmsd": ResultsGroup.ndarray_vstack}) def _single_frame(self): - mobile_com = self.mobile_atoms.center(self.weights_select).astype( - np.float64 - ) + mobile_com = self.mobile_atoms.center(self.weights_select).astype(np.float64) self._mobile_coordinates64[:] = self.mobile_atoms.positions self._mobile_coordinates64 -= mobile_com @@ -765,14 +753,12 @@ def _single_frame(self): # left** so that we can easily use broadcasting and save one # expensive numpy transposition. - self.results.rmsd[self._frame_index, 2] = ( - qcp.CalcRMSDRotationalMatrix( - self._ref_coordinates64, - self._mobile_coordinates64, - self._n_atoms, - self._rot, - self.weights_select, - ) + self.results.rmsd[self._frame_index, 2] = qcp.CalcRMSDRotationalMatrix( + self._ref_coordinates64, + self._mobile_coordinates64, + self._n_atoms, + self._rot, + self.weights_select, ) self._R[:, :] = self._rot.reshape(3, 3) @@ -804,14 +790,12 @@ def _single_frame(self): else: # only calculate RMSD by setting the Rmatrix to None (no need # to carry out the rotation as we already get the optimum RMSD) - self.results.rmsd[self._frame_index, 2] = ( - qcp.CalcRMSDRotationalMatrix( - self._ref_coordinates64, - self._mobile_coordinates64, - self._n_atoms, - None, - self.weights_select, - ) + self.results.rmsd[self._frame_index, 2] = qcp.CalcRMSDRotationalMatrix( + self._ref_coordinates64, + self._mobile_coordinates64, + self._n_atoms, + None, + self.weights_select, ) @property @@ -975,9 +959,7 @@ def _prepare(self): def _single_frame(self): k = self._frame_index - self.sumsquares += (k / (k + 1.0)) * ( - self.atomgroup.positions - self.mean - ) ** 2 + self.sumsquares += (k / (k + 1.0)) * (self.atomgroup.positions - self.mean) ** 2 self.mean = (k * self.mean + self.atomgroup.positions) / (k + 1) def _conclude(self): @@ -986,8 +968,7 @@ def _conclude(self): if not (self.results.rmsf >= 0).all(): raise ValueError( - "Some RMSF values negative; overflow " - + "or underflow occurred" + "Some RMSF values negative; overflow " + "or underflow occurred" ) @property diff --git a/package/MDAnalysis/analysis/waterdynamics.py b/package/MDAnalysis/analysis/waterdynamics.py index 0068700f7cf..2440f4f61b0 100644 --- a/package/MDAnalysis/analysis/waterdynamics.py +++ b/package/MDAnalysis/analysis/waterdynamics.py @@ -39,6 +39,7 @@ -------- :mod:`waterdynamics.waterdynamics` """ + import warnings try: diff --git a/package/MDAnalysis/auxiliary/EDR.py b/package/MDAnalysis/auxiliary/EDR.py index 8b9149690eb..0e8a09ff46f 100644 --- a/package/MDAnalysis/auxiliary/EDR.py +++ b/package/MDAnalysis/auxiliary/EDR.py @@ -189,6 +189,7 @@ """ + from pathlib import Path import warnings from typing import Optional, Union, Dict, List @@ -316,9 +317,7 @@ class EDRReader(base.AuxReader): def __init__(self, filename: str, convert_units: bool = True, **kwargs): if not HAS_PYEDR: - raise ImportError( - "EDRReader: To read EDR files please install " "pyedr." - ) + raise ImportError("EDRReader: To read EDR files please install " "pyedr.") self._auxdata = Path(filename).resolve() self.data_dict = pyedr.edr_to_dict(filename) self.unit_dict = pyedr.get_unit_dictionary(filename) @@ -348,8 +347,7 @@ def _convert_units(self): self.unit_dict[term] = units.MDANALYSIS_BASE_UNITS[unit_type] if unknown_units: warnings.warn( - "Could not find unit type for the following " - f"units: {unknown_units}" + "Could not find unit type for the following " f"units: {unknown_units}" ) def _memory_usage(self): @@ -375,8 +373,7 @@ def _read_next_step(self) -> EDRStep: new_step = self.step + 1 if new_step < self.n_steps: auxstep._data = { - term: self.data_dict[term][self.step + 1] - for term in self.terms + term: self.data_dict[term][self.step + 1] for term in self.terms } auxstep.step = new_step return auxstep diff --git a/package/MDAnalysis/auxiliary/XVG.py b/package/MDAnalysis/auxiliary/XVG.py index f68d2de1c76..be3778c75b5 100644 --- a/package/MDAnalysis/auxiliary/XVG.py +++ b/package/MDAnalysis/auxiliary/XVG.py @@ -66,6 +66,7 @@ .. autofunction:: uncomment """ + import numbers import os import numpy as np diff --git a/package/MDAnalysis/auxiliary/__init__.py b/package/MDAnalysis/auxiliary/__init__.py index 5e168003d27..24a1ff3abb4 100644 --- a/package/MDAnalysis/auxiliary/__init__.py +++ b/package/MDAnalysis/auxiliary/__init__.py @@ -25,14 +25,14 @@ Auxiliary Readers --- :mod:`MDAnalysis.auxiliary` ================================================= -The auxiliary submodule contains code for reading 'auxiliary' data from a -trajectory and allowing alignment with trajectory timesteps. Additional +The auxiliary submodule contains code for reading 'auxiliary' data from a +trajectory and allowing alignment with trajectory timesteps. Additional methods in :class:`MDAnalysis.coordinates.base.ProtoReader` allow auxiliary data to be added and read alongside a trajectory. -Auxiliary data are timeseries accompanying a trajectory not stored in the -regular trajectory file to be read by the trajectory Reader. They may be stored -internally (e.g. in an array) or read from a file. In general, auxiliary data is +Auxiliary data are timeseries accompanying a trajectory not stored in the +regular trajectory file to be read by the trajectory Reader. They may be stored +internally (e.g. in an array) or read from a file. In general, auxiliary data is assumed to be time ordered and contain no duplicates. Supported formats @@ -43,7 +43,7 @@ | Reader | Format | Extension | Remarks | | | | (if file) | | +=========================+========+===========+=======================================+ - | :class:`.XVGReader` | XVG | xvg | Produced by Gromacs during simulation | + | :class:`.XVGReader` | XVG | xvg | Produced by Gromacs during simulation | | | | | or analysis. | | | | (default) | Reads full file on initialisation. | +-------------------------+--------+-----------+---------------------------------------+ @@ -61,8 +61,8 @@ Auxiliary API ------------- -Auxiliary readers inherit from the base -:class:`~MDAnalysis.auxiliary.base.AuxReader`. In stand-alone use they +Auxiliary readers inherit from the base +:class:`~MDAnalysis.auxiliary.base.AuxReader`. In stand-alone use they allow iteration over each step in a set of auxiliary data:: aux = MDAnalysis.auxiliary.XVG.XVGReader('auxdata.xvg') @@ -71,24 +71,24 @@ To iterate over only certain sections of the auxiliary:: - for auxstep in aux[100:200]: + for auxstep in aux[100:200]: # only steps 100-200 do_something(auxstep) Or to skip steps:: - for auxstep in aux[100::10]: + for auxstep in aux[100::10]: # every 10th step starting at 100 do_something(auxstep) A base :class:`~MDAnalysis.auxiliary.base.AuxFileReader` is also provided, -extending :class:`~MDAnalysis.auxiliary.base.AuxReader` with attributes/methods +extending :class:`~MDAnalysis.auxiliary.base.AuxReader` with attributes/methods for when auxiliary data is to be read from a file by keeping the file open and reading steps one-at-time as needed. -A :func:`~MDAnalysis.auxiliary.core.get_auxreader_for` function is available to +A :func:`~MDAnalysis.auxiliary.core.get_auxreader_for` function is available to return an appropriate :class:`~MDAnalysis.auxiliary.base.AuxReader` class for -a supplied format or set of auxiliary data, guessing the format from the +a supplied format or set of auxiliary data, guessing the format from the datatype/file extension:: auxreader = MDAnalysis.auxiliary.core.get_auxreader_for('auxdata.xvg') @@ -97,7 +97,7 @@ # will return the XVGFileReader class To directly load an instance of the guessed auxiliary reader class given the -supplied auxdata and any additional auxiliary reader options, the +supplied auxdata and any additional auxiliary reader options, the function :func:`~MDAnalysis.auxiliary.core.auxreader` can be used:: aux = MDAnalysis.auxiliary.auxreader('auxdata.xvg', dt=2) @@ -107,45 +107,45 @@ Auxiliaries and trajectories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -For alignment with trajectory data, auxiliary readers provide methods to +For alignment with trajectory data, auxiliary readers provide methods to assign each auxiliary step to the nearest trajectory timestep, read all steps -assigned to a trajectory timestep and calculate 'representative' value(s) of -the auxiliary data for that timestep. +assigned to a trajectory timestep and calculate 'representative' value(s) of +the auxiliary data for that timestep. -'Assignment' of auxiliary steps to trajectory timesteps is determined from the time -of the auxiliary step, ``dt`` of the trajectory and time at the first frame of the -trajectory (obtained through a :class:`~MDAnalysis.coordinates.timestep.Timestep` +'Assignment' of auxiliary steps to trajectory timesteps is determined from the time +of the auxiliary step, ``dt`` of the trajectory and time at the first frame of the +trajectory (obtained through a :class:`~MDAnalysis.coordinates.timestep.Timestep` instance from the trajectory), as:: frame = floor((time_at_step - time_at_frame_0 + dt/2)/dt) -If there are no auxiliary steps assigned to a given timestep (or none within +If there are no auxiliary steps assigned to a given timestep (or none within ``cutoff``, if set), the representative value(s) are set to ``np.nan``. Adding an auxiliary to a trajectory ................................... -Auxiliary data may be added to a trajectory Reader through the +Auxiliary data may be added to a trajectory Reader through the :meth:`~MDAnalysis.coordinates.base.ProtoReader.add_auxiliary` method. Auxiliary data -may be passed in as a AuxReader instance, or directly as e.g. a filename, in -which case :func:`~MDAnalysis.auxiliary.core.get_auxreader_for` is used to +may be passed in as a AuxReader instance, or directly as e.g. a filename, in +which case :func:`~MDAnalysis.auxiliary.core.get_auxreader_for` is used to guess an appropriate reader. e.g.:: u = MDAnalysis.Universe(PDB, XTC) u.trajectory.add_auxiliary('pullforce', './pull_force.xvg') -As the trajectory frame is updated, the auxiliary data will be read -correspondingly, +As the trajectory frame is updated, the auxiliary data will be read +correspondingly, updated, and the representative auxiliary value(s) will be available as e.g. ``u.trajectory.ts.aux.pullforce``. Iterating by an auxiliary ......................... -The trajectory :class:`~MDAnalysis.coordinates.base.ProtoReader` methods +The trajectory :class:`~MDAnalysis.coordinates.base.ProtoReader` methods :meth:`~MDAnalysis.coordinates.base.ProtoReader.next_as_aux` and :meth:`~MDAnalysis.coordinates.base.ProtoReader.iter_as_aux` allow for movement -through only trajectory timesteps to which one or more steps that fall within -``cutoff`` from a given auxiliary have been assigned. This may be used to +through only trajectory timesteps to which one or more steps that fall within +``cutoff`` from a given auxiliary have been assigned. This may be used to avoid representative values set to ``np.nan``, particularly when auxiliary data is less frequent:: @@ -154,15 +154,15 @@ do_something(ts.aux.low_f) # do something with 'low_f' auxiliary data without # worrying about having to deal with np.nan -If the auxiliary data are more frequent and the cutoff (if set) is -sufficiently high, :meth:`~MDAnalysis.coordinates.base.ProtoReader.next_as_aux` -and :meth:`~MDAnalysis.coordinates.base.ProtoReader.iter_as_aux` behave the same -as the :class:`~MDAnalysis.coordinates.base.ProtoReader` -:meth:`~MDAnalysis.coordinates.base.ProtoReader.next` and +If the auxiliary data are more frequent and the cutoff (if set) is +sufficiently high, :meth:`~MDAnalysis.coordinates.base.ProtoReader.next_as_aux` +and :meth:`~MDAnalysis.coordinates.base.ProtoReader.iter_as_aux` behave the same +as the :class:`~MDAnalysis.coordinates.base.ProtoReader` +:meth:`~MDAnalysis.coordinates.base.ProtoReader.next` and :meth:`~MDAnalysis.coordinates.base.ProtoReader.__iter__`. -In order to access auxiliary values at every individual step, including those -outside the time range of the trajectory, +In order to access auxiliary values at every individual step, including those +outside the time range of the trajectory, :meth:`~MDAnalysis.coordinates.base.ProtoReader.iter_auxiliary` allows iteration over the auxiliary independent of the trajectory:: @@ -175,12 +175,12 @@ # every 10th step from 100 do_something(auxstep) -The trajectory remains unchanged, and the auxiliary will be returned to the current +The trajectory remains unchanged, and the auxiliary will be returned to the current timestep after iteration is complete. Accessing auxiliary attributes .............................. -To check the values of attributes of an added auxiliary, use +To check the values of attributes of an added auxiliary, use :meth:`~MDAnalysis.coordinates.base.ProtoReader.get_aux_attribute`, e.g.:: pullf_dt = u.trajectory.get_aux_attribute('pullforce', 'dt') @@ -198,10 +198,10 @@ Recreating auxiliaries ~~~~~~~~~~~~~~~~~~~~~~~ -To recreate an auxiliary, the set of attributes necessary to replicate it can -first be obtained with :meth:`~MDAnalysis.auxiliary.base.AuxReader.get_description`. -The returned dictionary can then be passed to -:func:`~MDAnalysis.auxiliary.core.auxreader` to load a new copy of the +To recreate an auxiliary, the set of attributes necessary to replicate it can +first be obtained with :meth:`~MDAnalysis.auxiliary.base.AuxReader.get_description`. +The returned dictionary can then be passed to +:func:`~MDAnalysis.auxiliary.core.auxreader` to load a new copy of the original auxiliary reader:: description = aux.get_description() @@ -230,7 +230,7 @@ An AuxStep instance holds the auxiliary data for the current step. It is updated whenever a new auxiliary step is read. -AuxStep classes are derived from the base class +AuxStep classes are derived from the base class :class:`~MDAnalysis.auxiliary.base.AuxStep`. The appropriate AuxStep class for a given auxiliary reader is identified in the reader by the `_Auxstep` attribute. @@ -244,17 +244,17 @@ ``_data`` All recorded data for the current step, as a numpy array. ``time`` - Time of current auxiliary step, as a float (in ps). Determined from the - ``_data`` if time selection is enabled and a valid ``time_selector`` + Time of current auxiliary step, as a float (in ps). Determined from the + ``_data`` if time selection is enabled and a valid ``time_selector`` provided; otherwise calculated using ``dt`` and ``initial_time``. ``data`` - Auxiliary values of interest for the current step, as a numpy array. - Determined from ``_data`` id data selection is enabled at a valid + Auxiliary values of interest for the current step, as a numpy array. + Determined from ``_data`` id data selection is enabled at a valid ``data_selector`` is provided; otherwise set to ``_data``. -The following are stored in AuxStep. The parent +The following are stored in AuxStep. The parent auxiliary reader has the equivalent attributes, though non-private (no _) -(see :ref:`AuxReader API` below). +(see :ref:`AuxReader API` below). ``_dt`` Change in time between auxiliary steps (in ps). If not specified, will @@ -264,23 +264,23 @@ determine from auxiliary data; otherwise defaults to 0 ps. ``_time_selector`` Selection key to get time from full set of auxiliary data read with each - step(``_data``) (ignored if time selection is not enabled by the reader). - Type depends on the auxiliary format - e.g. where data is stored in - columns, time_selector may be an index of 'time' column. + step(``_data``) (ignored if time selection is not enabled by the reader). + Type depends on the auxiliary format - e.g. where data is stored in + columns, time_selector may be an index of 'time' column. Default value is ``None``, in which case step time is calculated from ``dt``, ``initial_time`` and ``step``. ``_data_selector`` - Selection key(s) to get data of interest from full set of auxiliary data + Selection key(s) to get data of interest from full set of auxiliary data read with each step (``_data``) (ignored if data selection is not enabled - by the reader). As for ``time_selector``, type depends on the auxiliary + by the reader). As for ``time_selector``, type depends on the auxiliary format. If ``None`` (default value), ``_data`` is returned. ``_constant_dt`` - Boolean of whether dt is constant throughout auxiliary data. Default is + Boolean of whether dt is constant throughout auxiliary data. Default is ``True``. Methods ....... -The following methods are inherited from +The following methods are inherited from :class:`~MDAnalysis.auxiliary.base.AuxStep`: ``__init__(**kwargs)`` @@ -290,21 +290,21 @@ provided: ``_select_time(key)`` - Return, as a float, the time value indicated by *key* from ``_data`` (the full - set of data read in from the current step). Raise ``ValueError`` if *key* is + Return, as a float, the time value indicated by *key* from ``_data`` (the full + set of data read in from the current step). Raise ``ValueError`` if *key* is not a valid time selector for the auxiliary format. ``_select_data(key)`` - Return, as a ndarray, the value(s) indicated by *key* (may be e.g. a list of - multiple individual 'keys') from ``_data``. Raise ``ValueError`` if *key* is + Return, as a ndarray, the value(s) indicated by *key* (may be e.g. a list of + multiple individual 'keys') from ``_data``. Raise ``ValueError`` if *key* is not a valid data selector for the auxiliary format. -Depending on the format of the auxiliary and hence the format of ``data``, it +Depending on the format of the auxiliary and hence the format of ``data``, it may be necessary to overload the following for a particular AuxStep: ``_empty_data()`` Return a np.array in the same format as ``data`` with all values set to - ``np.nan``. Used as the representative auxiliary value for a trajectory when + ``np.nan``. Used as the representative auxiliary value for a trajectory when no auxiliary steps are assigned to the current frame. @@ -324,22 +324,22 @@ Replicating auxiliaries ....................... -The names of the necessary attributes for replicating an auxiliary are stored in +The names of the necessary attributes for replicating an auxiliary are stored in `required_attrs`, initially set in the base AuxReader. If a particular -AuxReader introduces additional attributes required to reload an auxiliary, +AuxReader introduces additional attributes required to reload an auxiliary, these should be added. Attributes .......... -The following attributes are inherited from +The following attributes are inherited from :class:`~MDAnalysis.auxiliary.base.AuxReader`: ``auxname`` Name under which auxiliary data will be stored in trajectory. ``represent_ts_as`` - Method to use in calculating representative auxiliary value for a + Method to use in calculating representative auxiliary value for a timestep. Default is 'closest'. ``cutoff`` Cutoff (in ps) for ignoring auxiliary steps when calculating @@ -382,17 +382,17 @@ Each auxiliary reader subclass will additionally set: ``_auxdata`` - Value of 'auxdata' used to load the auxiliary - e.g. path to the file + Value of 'auxdata' used to load the auxiliary - e.g. path to the file containing the auxiliary data. Will be used when getting the 'description' of the auxiliary for recreating. -Each auxiliary reader class must also identify an appropriate +Each auxiliary reader class must also identify an appropriate :class:`~MDAnalysis.auxiliary.base.AuxStep` with the `_Auxstep` class attribute - + Methods ....... -The following methods are inherited from +The following methods are inherited from :class:`~MDAnalysis.auxiliary.base.AuxReader`: ``__init__(**kwargs)`` @@ -416,7 +416,7 @@ Reposition to first step. ``update_ts(ts)`` - Read auxiliary steps assigned to trajectory step `ts`, calculate and update + Read auxiliary steps assigned to trajectory step `ts`, calculate and update the representative value in `ts`. Return `ts`. ``read_ts(ts)`` @@ -425,17 +425,17 @@ ``move_to_ts(ts)`` Move to the auxiliary step before the trajectory timestep *ts*, such that - calling ``_read_next_step`` reads the first step assigned to *ts* or, when - auxiliary data are less frequent and no steps are assigned to *ts*, the + calling ``_read_next_step`` reads the first step assigned to *ts* or, when + auxiliary data are less frequent and no steps are assigned to *ts*, the first step following *ts*. ``step_to_frame(step, ts, return_time_diff=False)`` - Return the frame number of the trajectory described by `ts` to which + Return the frame number of the trajectory described by `ts` to which the auxiliary step `step` is assigned. Optionally also return the difference it time between the step and the returned frame. ``step_to_time(step)`` - Return the time of the auxiliary step `step`. + Return the time of the auxiliary step `step`. ``next_nonempty_frame(ts)`` Return the frame number of the next trajectory frame (after the current @@ -468,7 +468,7 @@ and addionally define: ``__init__(auxdata, **kwargs)`` - Additional processing of *kwargs* and any necessary initial processing of + Additional processing of *kwargs* and any necessary initial processing of *auxdata*. Must :func:`super` through :class:`~MDAnalysis.auxiliary.base.AuxReader`. @@ -477,11 +477,11 @@ appropriate. Raise `StopIteration` when attempting to read past last step. ``_go_to_step(i)`` - Move to and read step `i` (0-based) from the auxiliary data. Raise + Move to and read step `i` (0-based) from the auxiliary data. Raise ValueError when i is out of range. Update the ``auxstep`` and return. -Depending on the format of the auxiliary data, it may also be necessary to +Depending on the format of the auxiliary data, it may also be necessary to define/overwrite the following: ``read_all_times()`` diff --git a/package/MDAnalysis/auxiliary/base.py b/package/MDAnalysis/auxiliary/base.py index 29fbaf999a2..12ae24cf616 100644 --- a/package/MDAnalysis/auxiliary/base.py +++ b/package/MDAnalysis/auxiliary/base.py @@ -193,9 +193,7 @@ def _time_selector(self, new): select = self._select_time except AttributeError: warnings.warn( - "{} does not support time selection".format( - self.__class__.__name__ - ) + "{} does not support time selection".format(self.__class__.__name__) ) else: # check *new* is valid before setting; _select_time should raise @@ -234,9 +232,7 @@ def _data_selector(self, new): select = self._select_data except AttributeError: warnings.warn( - "{} does not support data selection".format( - self.__class__.__name__ - ) + "{} does not support data selection".format(self.__class__.__name__) ) else: # check *new* is valid before setting; _select_data should raise an @@ -329,9 +325,7 @@ class AuxReader(metaclass=_AuxReaderMeta): "_auxdata", ] - def __init__( - self, represent_ts_as="closest", auxname=None, cutoff=None, **kwargs - ): + def __init__(self, represent_ts_as="closest", auxname=None, cutoff=None, **kwargs): # allow auxname to be optional for when using reader separate from # trajectory. self.auxname = auxname @@ -631,9 +625,7 @@ def step_to_frame(self, step, ts, return_time_diff=False): return None time_frame_0 = ts.time - ts.frame * ts.dt # assumes ts.dt is constant time_step = self.step_to_time(step) - frame_index = int( - math.floor((time_step - time_frame_0 + ts.dt / 2.0) / ts.dt) - ) + frame_index = int(math.floor((time_step - time_frame_0 + ts.dt / 2.0) / ts.dt)) if not return_time_diff: return frame_index else: @@ -658,9 +650,7 @@ def move_to_ts(self, ts): # figure out what step we want to end up at if self.constant_dt: # if dt constant, calculate from dt/offset/etc - step = int( - math.floor((ts.time - ts.dt / 2 - self.initial_time) / self.dt) - ) + step = int(math.floor((ts.time - ts.dt / 2 - self.initial_time) / self.dt)) # if we're out of range of the number of steps, reset back step = max(min(step, self.n_steps - 1), -1) else: @@ -749,11 +739,7 @@ def __getitem__(self, i): stop = ( i.stop if i.stop == self.n_steps - else ( - self._check_index(i.stop) - if i.stop is not None - else self.n_steps - ) + else (self._check_index(i.stop) if i.stop is not None else self.n_steps) ) step = i.step or 1 if not isinstance(step, numbers.Integral) or step < 1: @@ -787,9 +773,7 @@ def _slice_iter(self, i): def _go_to_step(self, i): """Move to and read i-th auxiliary step.""" # Need to define in each auxiliary reader - raise NotImplementedError( - "BUG: Override _go_to_step() in auxiliary reader!" - ) + raise NotImplementedError("BUG: Override _go_to_step() in auxiliary reader!") def _reset_frame_data(self): self.frame_data = {} @@ -853,9 +837,7 @@ def calc_representative(self): value = cutoff_data[min_diff] elif self.represent_ts_as == "average": try: - value = np.mean( - np.array([val for val in cutoff_data.values()]), axis=0 - ) + value = np.mean(np.array([val for val in cutoff_data.values()]), axis=0) except TypeError: # for readers like EDRReader, the above does not work # because each step contains a dictionary of numpy arrays @@ -967,8 +949,7 @@ def get_description(self): AuxReader. """ description = { - attr.strip("_"): getattr(self, attr) - for attr in self.required_attrs + attr.strip("_"): getattr(self, attr) for attr in self.required_attrs } return description diff --git a/package/MDAnalysis/auxiliary/core.py b/package/MDAnalysis/auxiliary/core.py index 03e65b7c4a7..5a925393a7c 100644 --- a/package/MDAnalysis/auxiliary/core.py +++ b/package/MDAnalysis/auxiliary/core.py @@ -28,6 +28,7 @@ .. autofunction:: get_auxreader_for .. autofunction:: auxreader """ + from . import _AUXREADERS from ..lib import util diff --git a/package/MDAnalysis/converters/OpenMM.py b/package/MDAnalysis/converters/OpenMM.py index 76a743b7736..25a9b61597e 100644 --- a/package/MDAnalysis/converters/OpenMM.py +++ b/package/MDAnalysis/converters/OpenMM.py @@ -63,7 +63,6 @@ """ - import numpy as np from ..coordinates import base @@ -108,9 +107,7 @@ def _read_first_frame(self): self.ts.triclinic_dimensions = self.convert_pos_from_native( self.ts.triclinic_dimensions, inplace=False ) - self.ts.dimensions[3:] = _sanitize_box_angles( - self.ts.dimensions[3:] - ) + self.ts.dimensions[3:] = _sanitize_box_angles(self.ts.dimensions[3:]) self.convert_velocities_from_native(self.ts._velocities) self.convert_forces_from_native(self.ts._forces) self.convert_time_from_native(self.ts.dt) @@ -137,9 +134,7 @@ def _mda_timestep_from_omm_context(self): ts.data["kinetic_energy"] = ( state.getKineticEnergy().in_units_of(u.kilojoule / u.mole)._value ) - ts.triclinic_dimensions = state.getPeriodicBoxVectors( - asNumpy=True - )._value + ts.triclinic_dimensions = state.getPeriodicBoxVectors(asNumpy=True)._value ts.dimensions[3:] = _sanitize_box_angles(ts.dimensions[3:]) ts.positions = state.getPositions(asNumpy=True)._value ts.velocities = state.getVelocities(asNumpy=True)._value @@ -183,9 +178,7 @@ def _read_first_frame(self): self.ts.triclinic_dimensions = self.convert_pos_from_native( self.ts.triclinic_dimensions, inplace=False ) - self.ts.dimensions[3:] = _sanitize_box_angles( - self.ts.dimensions[3:] - ) + self.ts.dimensions[3:] = _sanitize_box_angles(self.ts.dimensions[3:]) def _mda_timestep_from_omm_app(self): """Construct Timestep object from OpenMM Application object""" diff --git a/package/MDAnalysis/converters/OpenMMParser.py b/package/MDAnalysis/converters/OpenMMParser.py index 03fa06a60bb..4851f7bac90 100644 --- a/package/MDAnalysis/converters/OpenMMParser.py +++ b/package/MDAnalysis/converters/OpenMMParser.py @@ -194,9 +194,7 @@ def _mda_topology_from_omm_topology(self, omm_topology): " but it will be removed in 3.0)." ) - attrs.append( - Elements(np.array(validated_elements, dtype=object)) - ) + attrs.append(Elements(np.array(validated_elements, dtype=object))) else: wmsg = ( diff --git a/package/MDAnalysis/converters/ParmEd.py b/package/MDAnalysis/converters/ParmEd.py index e26f880c9fc..4b6f7e7f30c 100644 --- a/package/MDAnalysis/converters/ParmEd.py +++ b/package/MDAnalysis/converters/ParmEd.py @@ -77,6 +77,7 @@ to :mod:`~MDAnalysis.converters` """ + import functools import itertools import warnings @@ -238,9 +239,7 @@ def convert(self, obj): "id", ): try: - akwargs[MDA2PMD.get(attrname, attrname)] = getattr( - atom, attrname - ) + akwargs[MDA2PMD.get(attrname, attrname)] = getattr(atom, attrname) except AttributeError: pass try: @@ -260,9 +259,7 @@ def convert(self, obj): chain_seg["inscode"] = atom.icode except AttributeError: pass - atom_kwargs.append( - (akwargs, resname, atom.resid, chain_seg, xyz, vel) - ) + atom_kwargs.append((akwargs, resname, atom.resid, chain_seg, xyz, vel)) struct = pmd.Structure() @@ -288,9 +285,7 @@ def convert(self, obj): struct.box = None if hasattr(ag_or_ts, "universe"): - atomgroup = { - atom: index for index, atom in enumerate(list(ag_or_ts)) - } + atomgroup = {atom: index for index, atom in enumerate(list(ag_or_ts))} get_atom_indices = functools.partial( get_indices_from_subset, atomgroup=atomgroup, @@ -306,9 +301,7 @@ def convert(self, obj): pass else: for p in params: - atoms = [ - struct.atoms[i] for i in map(get_atom_indices, p.indices) - ] + atoms = [struct.atoms[i] for i in map(get_atom_indices, p.indices)] try: for obj in p.type: bond = pmd.Bond(*atoms, type=obj.type, order=obj.order) @@ -328,16 +321,12 @@ def convert(self, obj): # dihedrals try: - params = ag_or_ts.dihedrals.atomgroup_intersection( - ag_or_ts, strict=True - ) + params = ag_or_ts.dihedrals.atomgroup_intersection(ag_or_ts, strict=True) except AttributeError: pass else: for p in params: - atoms = [ - struct.atoms[i] for i in map(get_atom_indices, p.indices) - ] + atoms = [struct.atoms[i] for i in map(get_atom_indices, p.indices)] try: for obj in p.type: imp = getattr(obj, "improper", False) @@ -353,9 +342,7 @@ def convert(self, obj): btype = getattr(p.type, "type", None) imp = getattr(p.type, "improper", False) ign = getattr(p.type, "ignore_end", False) - dih = pmd.Dihedral( - *atoms, type=btype, improper=imp, ignore_end=ign - ) + dih = pmd.Dihedral(*atoms, type=btype, improper=imp, ignore_end=ign) struct.dihedrals.append(dih) if isinstance(dih.type, pmd.DihedralType): struct.dihedral_types.append(dih.type) @@ -392,10 +379,7 @@ def convert(self, obj): pass else: for v in values: - atoms = [ - struct.atoms[i] - for i in map(get_atom_indices, v.indices) - ] + atoms = [struct.atoms[i] for i in map(get_atom_indices, v.indices)] try: for parmed_obj in v.type: diff --git a/package/MDAnalysis/converters/ParmEdParser.py b/package/MDAnalysis/converters/ParmEdParser.py index 331f14e279a..5d5df561aec 100644 --- a/package/MDAnalysis/converters/ParmEdParser.py +++ b/package/MDAnalysis/converters/ParmEdParser.py @@ -86,6 +86,7 @@ :mod:`~MDAnalysis.converters` """ + import logging import numpy as np @@ -311,9 +312,7 @@ def parse(self, **kwargs): bond_orders = list(map(squash_identical, bond_orders)) attrs.append( - Bonds( - bond_values, types=bond_types, guessed=False, order=bond_orders - ) + Bonds(bond_values, types=bond_types, guessed=False, order=bond_orders) ) for pmdlist, na, values, types in ( diff --git a/package/MDAnalysis/converters/RDKitInferring.py b/package/MDAnalysis/converters/RDKitInferring.py index 843986371af..6c42464b563 100644 --- a/package/MDAnalysis/converters/RDKitInferring.py +++ b/package/MDAnalysis/converters/RDKitInferring.py @@ -92,9 +92,7 @@ ) # available since 2022.09.1 -def reorder_atoms( - mol: "Chem.Mol", field: str = "_MDAnalysis_index" -) -> "Chem.Mol": +def reorder_atoms(mol: "Chem.Mol", field: str = "_MDAnalysis_index") -> "Chem.Mol": """Reorder atoms based on the given field. Defaults to sorting in the same order as the input AtomGroup. @@ -394,9 +392,7 @@ def _standardize_patterns( self._rebuild_conjugated_bonds(mol, max_iter) # list of sanitized reactions - reactions = [ - ReactionFromSmarts(rxn) for rxn in self.STANDARDIZATION_REACTIONS - ] + reactions = [ReactionFromSmarts(rxn) for rxn in self.STANDARDIZATION_REACTIONS] # fragment mol (reactions must have single reactant and product) fragments = list( @@ -485,17 +481,13 @@ def _rebuild_conjugated_bonds( # there's usually an even number of matches for this pattern = Chem.MolFromSmarts("[*-{1-2}]-,=[*+0]=,#[*+0]") # pattern used to finish fixing a series of conjugated bonds - base_end_pattern = Chem.MolFromSmarts( - "[*-{1-2}]-,=[*+0]=,#[*+0]-,=[*-{1-2}]" - ) + base_end_pattern = Chem.MolFromSmarts("[*-{1-2}]-,=[*+0]=,#[*+0]-,=[*-{1-2}]") # used when there's an odd number of matches for `pattern` odd_end_pattern = Chem.MolFromSmarts( "[*-]-[*+0]=[*+0]-[*-,$([#7;X3;v3]),$([#6+0,#7+1]=O),$([S;D4;v4]-[O-])]" ) # number of unique matches with the pattern - n_matches = len( - {match[0] for match in mol.GetSubstructMatches(pattern)} - ) + n_matches = len({match[0] for match in mol.GetSubstructMatches(pattern)}) # nothing to standardize if n_matches == 0: return @@ -523,16 +515,12 @@ def _rebuild_conjugated_bonds( # [*-]-*=*-[C,N+]=O --> *=*-*=[C,N+]-[O-] # transform the =O to -[O-] if ( - term_atom.GetAtomicNum() == 6 - and term_atom.GetFormalCharge() == 0 + term_atom.GetAtomicNum() == 6 and term_atom.GetFormalCharge() == 0 ) or ( - term_atom.GetAtomicNum() == 7 - and term_atom.GetFormalCharge() == 1 + term_atom.GetAtomicNum() == 7 and term_atom.GetFormalCharge() == 1 ): for neighbor in term_atom.GetNeighbors(): - bond = mol.GetBondBetweenAtoms( - anion2, neighbor.GetIdx() - ) + bond = mol.GetBondBetweenAtoms(anion2, neighbor.GetIdx()) if ( neighbor.GetAtomicNum() == 8 and bond.GetBondTypeAsDouble() == 2 @@ -544,13 +532,10 @@ def _rebuild_conjugated_bonds( # [*-]-*=*-[Sv4]-[O-] --> *=*-*=[Sv6]=O # transform -[O-] to =O elif ( - term_atom.GetAtomicNum() == 16 - and term_atom.GetFormalCharge() == 0 + term_atom.GetAtomicNum() == 16 and term_atom.GetFormalCharge() == 0 ): for neighbor in term_atom.GetNeighbors(): - bond = mol.GetBondBetweenAtoms( - anion2, neighbor.GetIdx() - ) + bond = mol.GetBondBetweenAtoms(anion2, neighbor.GetIdx()) if ( neighbor.GetAtomicNum() == 8 and neighbor.GetFormalCharge() == -1 diff --git a/package/MDAnalysis/converters/RDKitParser.py b/package/MDAnalysis/converters/RDKitParser.py index 90069ebfb12..22e0851b227 100644 --- a/package/MDAnalysis/converters/RDKitParser.py +++ b/package/MDAnalysis/converters/RDKitParser.py @@ -215,9 +215,7 @@ def parse(self, **kwargs): return top # check if multiple charges present - if atom.HasProp("_GasteigerCharge") and ( - atom.HasProp("_TriposPartialCharge") - ): + if atom.HasProp("_GasteigerCharge") and (atom.HasProp("_TriposPartialCharge")): warnings.warn( "Both _GasteigerCharge and _TriposPartialCharge properties " "are present. Using Gasteiger charges by default." @@ -259,9 +257,7 @@ def parse(self, **kwargs): except KeyError: # partial charge (MOL2 only) try: - charges.append( - atom.GetDoubleProp("_TriposPartialCharge") - ) + charges.append(atom.GetDoubleProp("_TriposPartialCharge")) except KeyError: pass diff --git a/package/MDAnalysis/converters/__init__.py b/package/MDAnalysis/converters/__init__.py index 7f8a3d8c572..bfe5281a026 100644 --- a/package/MDAnalysis/converters/__init__.py +++ b/package/MDAnalysis/converters/__init__.py @@ -31,6 +31,7 @@ .. versionadded:: 2.0.0 """ + from . import ParmEdParser from . import ParmEd from . import RDKitInferring diff --git a/package/MDAnalysis/converters/base.py b/package/MDAnalysis/converters/base.py index 5f3d0e32509..afd5d6959ad 100644 --- a/package/MDAnalysis/converters/base.py +++ b/package/MDAnalysis/converters/base.py @@ -21,7 +21,7 @@ # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -""" Base classes --- :mod:`MDAnalysis.converters.base` +"""Base classes --- :mod:`MDAnalysis.converters.base` ====================================================== Converters output information to other libraries. diff --git a/package/MDAnalysis/coordinates/CRD.py b/package/MDAnalysis/coordinates/CRD.py index e762c83767b..e35eb6897d2 100644 --- a/package/MDAnalysis/coordinates/CRD.py +++ b/package/MDAnalysis/coordinates/CRD.py @@ -29,6 +29,7 @@ "crd"). The CHARMM "extended format" is handled automatically. """ + import itertools import numpy as np import warnings @@ -82,10 +83,7 @@ def _read_first_frame(self): np.array(line[20:50].split()[0:3], dtype=float) ) except Exception: - errmsg = ( - f"Check CRD format at line {linenum}: " - f"{line.rstrip()}" - ) + errmsg = f"Check CRD format at line {linenum}: " f"{line.rstrip()}" raise ValueError(errmsg) from None self.n_atoms = len(coords_list) @@ -101,8 +99,7 @@ def _read_first_frame(self): if self.n_atoms != natoms: raise ValueError( "Found %d coordinates in %r but the header claims that there " - "should be %d coordinates." - % (self.n_atoms, self.filename, natoms) + "should be %d coordinates." % (self.n_atoms, self.filename, natoms) ) def Writer(self, filename, **kwargs): @@ -217,9 +214,7 @@ def write(self, selection, frame=None): frame = 0 # should catch cases when we are analyzing a single PDB (?) atoms = selection.atoms # make sure to use atoms (Issue 46) - coor = ( - atoms.positions - ) # can write from selection == Universe (Issue 49) + coor = atoms.positions # can write from selection == Universe (Issue 49) n_atoms = len(atoms) # Detect which format string we're using to output (EXT or not) @@ -271,9 +266,7 @@ def write(self, selection, frame=None): with util.openany(self.filename, "wt") as crd: # Write Title crd.write( - self.fmt["TITLE"].format( - frame=frame, where=u.trajectory.filename - ) + self.fmt["TITLE"].format(frame=frame, where=u.trajectory.filename) ) crd.write("*\n") diff --git a/package/MDAnalysis/coordinates/DCD.py b/package/MDAnalysis/coordinates/DCD.py index 672d5323b56..f144a1970c8 100644 --- a/package/MDAnalysis/coordinates/DCD.py +++ b/package/MDAnalysis/coordinates/DCD.py @@ -56,6 +56,7 @@ :inherited-members: """ + import os import errno import numpy as np @@ -123,9 +124,10 @@ class DCDReader(base.ReaderBase): .. _wiki: https://github.com/MDAnalysis/mdanalysis/wiki/FileFormats#dcd """ - format = 'DCD' - flavor = 'CHARMM' - units = {'time': 'AKMA', 'length': 'Angstrom'} + + format = "DCD" + flavor = "CHARMM" + units = {"time": "AKMA", "length": "Angstrom"} @store_init_arguments def __init__(self, filename, convert_units=True, dt=None, **kwargs): @@ -145,18 +147,16 @@ def __init__(self, filename, convert_units=True, dt=None, **kwargs): .. versionchanged:: 0.17.0 Changed to use libdcd.pyx library and removed the correl function """ - super(DCDReader, self).__init__( - filename, convert_units=convert_units, **kwargs) + super(DCDReader, self).__init__(filename, convert_units=convert_units, **kwargs) self._file = DCDFile(self.filename) - self.n_atoms = self._file.header['natoms'] + self.n_atoms = self._file.header["natoms"] - delta = mdaunits.convert(self._file.header['delta'], - self.units['time'], 'ps') + delta = mdaunits.convert(self._file.header["delta"], self.units["time"], "ps") if dt is None: - dt = delta * self._file.header['nsavc'] - self.skip_timestep = self._file.header['nsavc'] + dt = delta * self._file.header["nsavc"] + self.skip_timestep = self._file.header["nsavc"] - self._ts_kwargs['dt'] = dt + self._ts_kwargs["dt"] = dt self.ts = self._Timestep(self.n_atoms, **self._ts_kwargs) frame = self._file.read() # reset trajectory @@ -168,18 +168,20 @@ def __init__(self, filename, convert_units=True, dt=None, **kwargs): self.ts = self._frame_to_ts(frame, self.ts) # these should only be initialized once self.ts.dt = dt - warnings.warn("DCDReader currently makes independent timesteps" - " by copying self.ts while other readers update" - " self.ts inplace. This behavior will be changed in" - " 3.0 to be the same as other readers. Read more at" - " https://github.com/MDAnalysis/mdanalysis/issues/3889" - " to learn if this change in behavior might affect you.", - category=DeprecationWarning) + warnings.warn( + "DCDReader currently makes independent timesteps" + " by copying self.ts while other readers update" + " self.ts inplace. This behavior will be changed in" + " 3.0 to be the same as other readers. Read more at" + " https://github.com/MDAnalysis/mdanalysis/issues/3889" + " to learn if this change in behavior might affect you.", + category=DeprecationWarning, + ) @staticmethod def parse_n_atoms(filename, **kwargs): with DCDFile(filename) as f: - n_atoms = f.header['natoms'] + n_atoms = f.header["natoms"] return n_atoms def close(self): @@ -196,7 +198,7 @@ def _reopen(self): self.ts.frame = 0 self._frame = -1 self._file.close() - self._file.open('r') + self._file.open("r") def _read_frame(self, i): """read frame i""" @@ -207,9 +209,9 @@ def _read_frame(self, i): def _read_next_timestep(self, ts=None): """copy next frame into timestep""" if self._frame == self.n_frames - 1: - raise IOError('trying to go over trajectory limit') + raise IOError("trying to go over trajectory limit") if ts is None: - #TODO remove copying the ts in 3.0 + # TODO remove copying the ts in 3.0 ts = self.ts.copy() frame = self._file.read() self._frame += 1 @@ -226,21 +228,23 @@ def Writer(self, filename, n_atoms=None, **kwargs): n_atoms=n_atoms, dt=self.ts.dt, convert_units=self.convert_units, - **kwargs) + **kwargs + ) def _frame_to_ts(self, frame, ts): """convert a dcd-frame to a :class:`TimeStep`""" ts.frame = self._frame - ts.time = (ts.frame + self._file.header['istart']/self._file.header['nsavc']) * self.ts.dt - ts.data['step'] = self._file.tell() + ts.time = ( + ts.frame + self._file.header["istart"] / self._file.header["nsavc"] + ) * self.ts.dt + ts.data["step"] = self._file.tell() # The original unitcell is read as ``[A, gamma, B, beta, alpha, C]`` _ts_order = [0, 2, 5, 4, 3, 1] uc = np.take(frame.unitcell, _ts_order) pi_2 = np.pi / 2 - if (-1.0 <= uc[3] <= 1.0) and (-1.0 <= uc[4] <= 1.0) and ( - -1.0 <= uc[5] <= 1.0): + if (-1.0 <= uc[3] <= 1.0) and (-1.0 <= uc[4] <= 1.0) and (-1.0 <= uc[5] <= 1.0): # This file was generated by Charmm, or by NAMD > 2.5, with the # angle cosines of the periodic cell angles written to the DCD # file. This formulation improves rounding behavior for orthogonal @@ -251,7 +255,7 @@ def _frame_to_ts(self, frame, ts): uc[4] = 90.0 - np.arcsin(uc[4]) * 90.0 / pi_2 uc[5] = 90.0 - np.arcsin(uc[5]) * 90.0 / pi_2 # heuristic sanity check: uc = A,B,C,alpha,beta,gamma - elif np.any(uc < 0.) or np.any(uc[3:] > 180.): + elif np.any(uc < 0.0) or np.any(uc[3:] > 180.0): # might be new CHARMM: box matrix vectors H = frame.unitcell.copy() e1, e2, e3 = H[[0, 1, 3]], H[[1, 2, 4]], H[[3, 4, 5]] @@ -273,8 +277,7 @@ def _frame_to_ts(self, frame, ts): @property def dimensions(self): - """unitcell dimensions (*A*, *B*, *C*, *alpha*, *beta*, *gamma*) - """ + """unitcell dimensions (*A*, *B*, *C*, *alpha*, *beta*, *gamma*)""" return self.ts.dimensions @property @@ -282,13 +285,9 @@ def dt(self): """timestep between frames""" return self.ts.dt - def timeseries(self, - asel=None, - atomgroup=None, - start=None, - stop=None, - step=None, - order='afc'): + def timeseries( + self, asel=None, atomgroup=None, start=None, stop=None, step=None, order="afc" + ): """Return a subset of coordinate data for an AtomGroup Parameters @@ -297,7 +296,7 @@ def timeseries(self, The :class:`~MDAnalysis.core.groups.AtomGroup` to read the coordinates from. Defaults to None, in which case the full set of coordinate data is returned. - + .. deprecated:: 2.7.0 asel argument will be renamed to atomgroup in 3.0.0 @@ -332,7 +331,8 @@ def timeseries(self, warnings.warn( "asel argument to timeseries will be renamed to" "'atomgroup' in 3.0, see #3911", - category=DeprecationWarning) + category=DeprecationWarning, + ) if atomgroup: raise ValueError("Cannot provide both asel and atomgroup kwargs") atomgroup = asel @@ -341,14 +341,14 @@ def timeseries(self, if atomgroup is not None: if len(atomgroup) == 0: - raise ValueError( - "Timeseries requires at least one atom to analyze") + raise ValueError("Timeseries requires at least one atom to analyze") atom_numbers = list(atomgroup.indices) else: atom_numbers = list(range(self.n_atoms)) frames = self._file.readframes( - start, stop, step, order=order, indices=atom_numbers) + start, stop, step, order=order, indices=atom_numbers + ) return frames.xyz @@ -360,7 +360,7 @@ class DCDWriter(base.WriterBase): and writes positions in Å and time in AKMA time units. .. warning:: - + Multiple conventions exist for how unit cells are written to DCD files. Until 2.10.0 MDAnalysis followed the old X-PLOR/CHARMM/NAMD (≤2.5) convention of storing ``[A, gamma, B, beta, alpha, C]`` while @@ -381,7 +381,7 @@ class DCDWriter(base.WriterBase): ``[0, 0, 0, 0, 0, 0]``). As this behaviour is poorly defined, it may not match the expectations of other software. - .. versionchanged:: 2.10.0 + .. versionchanged:: 2.10.0 Up to 2.10.0 the :class:`DCDWriter` wrote a unit cell following old NAMD (≤2.5) convention, even though the docs stated that the new NAMD convention was being used. Now the modern NAMD > 2.5 format is @@ -391,21 +391,24 @@ class DCDWriter(base.WriterBase): .. _`Issue #5069`: https://github.com/MDAnalysis/mdanalysis/issues/5069 """ - format = 'DCD' + + format = "DCD" multiframe = True - flavor = 'NAMD' - units = {'time': 'AKMA', 'length': 'Angstrom'} - - def __init__(self, - filename, - n_atoms, - convert_units=True, - step=1, - dt=1, - remarks='', - nsavc=1, - istart=0, - **kwargs): + flavor = "NAMD" + units = {"time": "AKMA", "length": "Angstrom"} + + def __init__( + self, + filename, + n_atoms, + convert_units=True, + step=1, + dt=1, + remarks="", + nsavc=1, + istart=0, + **kwargs + ): """Parameters ---------- filename : str @@ -442,10 +445,10 @@ def __init__(self, if n_atoms is None: raise ValueError("n_atoms argument is required") self.n_atoms = n_atoms - self._file = DCDFile(self.filename, 'w') + self._file = DCDFile(self.filename, "w") self.step = step self.dt = dt - dt = mdaunits.convert(dt, 'ps', self.units['time']) + dt = mdaunits.convert(dt, "ps", self.units["time"]) delta = float(dt) / nsavc istart = istart if istart is not None else nsavc self._file.write_header( @@ -454,7 +457,8 @@ def __init__(self, nsavc=nsavc, delta=delta, is_periodic=1, - istart=istart) + istart=istart, + ) def _write_next_frame(self, ag): """Write information associated with ``obj`` at current frame into trajectory @@ -488,8 +492,10 @@ def _write_next_frame(self, ag): try: dimensions = ts.dimensions.copy() except AttributeError: - wmsg = ('No dimensions set for current frame, zeroed unitcell ' - 'will be written') + wmsg = ( + "No dimensions set for current frame, zeroed unitcell " + "will be written" + ) warnings.warn(wmsg) dimensions = np.zeros(6) @@ -501,7 +507,7 @@ def _write_next_frame(self, ag): # The DCD unitcell is written as [A, cos(gamma), B, cos(beta), cos(alpha), C] _ts_order = [0, 5, 1, 4, 3, 2] box = np.take(dimensions, _ts_order) - + # Convert angles (indices 1, 3, 4) from degrees to the special cosine format # used by NAMD/VMD: cos(angle) = sin(90 - angle); see Issue 5069 box[[1, 3, 4]] = np.sin(np.deg2rad(90.0 - box[[1, 3, 4]])) diff --git a/package/MDAnalysis/coordinates/DLPoly.py b/package/MDAnalysis/coordinates/DLPoly.py index 71297f978fa..4750b61f112 100644 --- a/package/MDAnalysis/coordinates/DLPoly.py +++ b/package/MDAnalysis/coordinates/DLPoly.py @@ -28,6 +28,7 @@ .. _Poly: https://www.sc.stfc.ac.uk/software/type/computational-materials-and-molecular-science/?searchquery=dl_poly """ + import numpy as np from . import base @@ -35,7 +36,7 @@ from ..lib import util from ..lib.util import cached, store_init_arguments -_DLPOLY_UNITS = {'length': 'Angstrom', 'velocity': 'Angstrom/ps', 'time': 'ps'} +_DLPOLY_UNITS = {"length": "Angstrom", "velocity": "Angstrom/ps", "time": "ps"} class ConfigReader(base.SingleFrameReaderBase): @@ -47,13 +48,14 @@ class ConfigReader(base.SingleFrameReaderBase): coordinates, velocities, and forces are no longer stored in 'F' memory layout, instead now using the numpy default of 'C'. """ - format = 'CONFIG' + + format = "CONFIG" units = _DLPOLY_UNITS def _read_first_frame(self): unitcell = np.zeros((3, 3), dtype=np.float32) - with open(self.filename, 'r') as inf: + with open(self.filename, "r") as inf: self.title = inf.readline().strip() levcfg, imcon, megatm = np.int64(inf.readline().split()[:3]) if not imcon == 0: @@ -113,10 +115,9 @@ def _read_first_frame(self): if has_forces: forces = forces[order] - ts = self.ts = self._Timestep(self.n_atoms, - velocities=has_vels, - forces=has_forces, - **self._ts_kwargs) + ts = self.ts = self._Timestep( + self.n_atoms, velocities=has_vels, forces=has_forces, **self._ts_kwargs + ) ts._pos = coords if has_vels: ts._velocities = velocities @@ -133,7 +134,8 @@ class HistoryReader(base.ReaderBase): .. versionadded:: 0.11.0 """ - format = 'HISTORY' + + format = "HISTORY" units = _DLPOLY_UNITS @store_init_arguments @@ -142,7 +144,7 @@ def __init__(self, filename, **kwargs): self._cache = {} # "private" file handle - self._file = util.anyopen(self.filename, 'r') + self._file = util.anyopen(self.filename, "r") self.title = self._file.readline().strip() header = np.int64(self._file.readline().split()[:3]) self._levcfg, self._imcon, self.n_atoms = header @@ -157,10 +159,12 @@ def __init__(self, filename, **kwargs): self._has_cell = False self._file.seek(rwnd) - self.ts = self._Timestep(self.n_atoms, - velocities=self._has_vels, - forces=self._has_forces, - **self._ts_kwargs) + self.ts = self._Timestep( + self.n_atoms, + velocities=self._has_vels, + forces=self._has_forces, + **self._ts_kwargs + ) self._read_next_timestep() def _read_next_timestep(self, ts=None): @@ -168,7 +172,7 @@ def _read_next_timestep(self, ts=None): ts = self.ts line = self._file.readline() # timestep line - if not line.startswith('timestep'): + if not line.startswith("timestep"): raise IOError if self._has_cell: @@ -176,7 +180,7 @@ def _read_next_timestep(self, ts=None): unitcell[0] = self._file.readline().split() unitcell[1] = self._file.readline().split() unitcell[2] = self._file.readline().split() - ts.dimensions = core.triclinic_box(*unitcell) + ts.dimensions = core.triclinic_box(*unitcell) # If ids are given, put them in here # and later sort by them @@ -220,17 +224,17 @@ def _read_frame(self, frame): return self._read_next_timestep() @property - @cached('n_frames') + @cached("n_frames") def n_frames(self): # Second line is traj_key, imcom, n_atoms, n_frames, n_records offsets = [] - with open(self.filename, 'r') as f: + with open(self.filename, "r") as f: f.readline() f.readline() position = f.tell() line = f.readline() - while line.startswith('timestep'): + while line.startswith("timestep"): offsets.append(position) if self._has_cell: f.readline() @@ -251,7 +255,7 @@ def n_frames(self): def _reopen(self): self.close() - self._file = open(self.filename, 'r') + self._file = open(self.filename, "r") self._file.readline() # header is 2 lines self._file.readline() self.ts.frame = -1 diff --git a/package/MDAnalysis/coordinates/DMS.py b/package/MDAnalysis/coordinates/DMS.py index 04367f438d3..867de1b4ab7 100644 --- a/package/MDAnalysis/coordinates/DMS.py +++ b/package/MDAnalysis/coordinates/DMS.py @@ -32,6 +32,7 @@ .. _Desmond: http://www.deshawresearch.com/resources_desmond.html .. _DMS: http://www.deshawresearch.com/Desmond_Users_Guide-0.7.pdf """ + import numpy as np import sqlite3 @@ -106,16 +107,12 @@ def dict_factory(cursor, row): ) self.ts.frame = 0 # 0-based frame number - self.ts.dimensions = triclinic_box( - unitcell["x"], unitcell["y"], unitcell["z"] - ) + self.ts.dimensions = triclinic_box(unitcell["x"], unitcell["y"], unitcell["z"]) if self.convert_units: self.convert_pos_from_native(self.ts._pos) # in-place ! if self.ts.dimensions is not None: - self.convert_pos_from_native( - self.ts.dimensions[:3] - ) # in-place ! + self.convert_pos_from_native(self.ts.dimensions[:3]) # in-place ! if self.ts.has_velocities: # converts nm/ps to A/ps units self.convert_velocities_from_native(self.ts._velocities) diff --git a/package/MDAnalysis/coordinates/FHIAIMS.py b/package/MDAnalysis/coordinates/FHIAIMS.py index 3aff6d97f52..2ccac3dc980 100644 --- a/package/MDAnalysis/coordinates/FHIAIMS.py +++ b/package/MDAnalysis/coordinates/FHIAIMS.py @@ -102,6 +102,7 @@ .. _FHI-AIMS format: https://doi.org/10.6084/m9.figshare.12413477.v1 """ + import re import itertools @@ -191,9 +192,7 @@ def _read_first_frame(self): if len(lattice_vectors) > 0: ts.dimensions = triclinic_box(*lattice_vectors) - ts.positions[relative] = np.matmul( - ts.positions[relative], lattice_vectors - ) + ts.positions[relative] = np.matmul(ts.positions[relative], lattice_vectors) if len(velocities) > 0: ts.velocities = velocities @@ -321,9 +320,7 @@ def _write_next_frame(self, obj): # all attributes could be infinite cycles! for atom_index, name in zip(range(ag.n_atoms), names): output_fhiaims.write( - self.fmt["xyz"].format( - pos=positions[atom_index], name=name - ) + self.fmt["xyz"].format(pos=positions[atom_index], name=name) ) if has_velocities: output_fhiaims.write( diff --git a/package/MDAnalysis/coordinates/GMS.py b/package/MDAnalysis/coordinates/GMS.py index f840b46a67e..e453c801a37 100644 --- a/package/MDAnalysis/coordinates/GMS.py +++ b/package/MDAnalysis/coordinates/GMS.py @@ -37,6 +37,7 @@ :members: """ + import os import errno import re @@ -142,9 +143,7 @@ def n_atoms(self): def _read_out_natoms(self): with util.openany(self.filename) as out: for line in out: - m = re.match( - r"\s*TOTAL NUMBER OF ATOMS\s*=\s*([0-9]+)\s*", line - ) + m = re.match(r"\s*TOTAL NUMBER OF ATOMS\s*=\s*([0-9]+)\s*", line) if m is not None: res = int(m.group(1)) break @@ -199,14 +198,11 @@ def _read_next_timestep(self, ts=None): for line in self.outfile: if self.runtyp == "optimize": - if (flag == 0) and ( - re.match(r"^.NSERCH=.*", line) is not None - ): + if (flag == 0) and (re.match(r"^.NSERCH=.*", line) is not None): flag = 1 continue if (flag == 1) and ( - re.match(r"^ COORDINATES OF ALL ATOMS ARE ", line) - is not None + re.match(r"^ COORDINATES OF ALL ATOMS ARE ", line) is not None ): flag = 2 continue @@ -222,15 +218,12 @@ def _read_next_timestep(self, ts=None): elif self.runtyp == "surface": if (flag == 0) and ( - re.match(r"^.COORD 1=\s*([-]?[0-9]+\.[0-9]+).*", line) - is not None + re.match(r"^.COORD 1=\s*([-]?[0-9]+\.[0-9]+).*", line) is not None ): flag = 1 continue if (flag == 1) and ( - re.match( - r"^\s*HAS ENERGY VALUE\s*([-]?[0-9]+\.[0-9]+)\s*", line - ) + re.match(r"^\s*HAS ENERGY VALUE\s*([-]?[0-9]+\.[0-9]+)\s*", line) is not None ): flag = 3 @@ -261,9 +254,7 @@ def _reopen(self): def open_trajectory(self): if self.outfile is not None: - raise IOError( - errno.EALREADY, "GMS file already opened", self.filename - ) + raise IOError(errno.EALREADY, "GMS file already opened", self.filename) if not os.path.exists(self.filename): # must check; otherwise might segmentation fault raise IOError(errno.ENOENT, "GMS file not found", self.filename) diff --git a/package/MDAnalysis/coordinates/GRO.py b/package/MDAnalysis/coordinates/GRO.py index f7eed70400a..47d1bc2efd1 100644 --- a/package/MDAnalysis/coordinates/GRO.py +++ b/package/MDAnalysis/coordinates/GRO.py @@ -100,6 +100,7 @@ .. _GRO format: http://chembytes.wikidot.com/g-grofile """ + import re import itertools @@ -186,13 +187,11 @@ def _read_first_frame(self): first_atomline = grofile.readline() cs = first_atomline[25:].find(".") + 1 ts._pos[0] = [ - first_atomline[20 + cs * i : 20 + cs * (i + 1)] - for i in range(3) + first_atomline[20 + cs * i : 20 + cs * (i + 1)] for i in range(3) ] try: velocities[0] = [ - first_atomline[20 + cs * i : 20 + cs * (i + 1)] - for i in range(3, 6) + first_atomline[20 + cs * i : 20 + cs * (i + 1)] for i in range(3, 6) ] except ValueError: # Remember that we got this error @@ -206,18 +205,13 @@ def _read_first_frame(self): unitcell = np.float32(line.split()) except ValueError: # Try to parse floats with 5 digits if no spaces between values... - unitcell = np.float32( - re.findall(r"(\d+\.\d{5})", line) - ) + unitcell = np.float32(re.findall(r"(\d+\.\d{5})", line)) break - ts._pos[pos] = [ - line[20 + cs * i : 20 + cs * (i + 1)] for i in range(3) - ] + ts._pos[pos] = [line[20 + cs * i : 20 + cs * (i + 1)] for i in range(3)] try: velocities[pos] = [ - line[20 + cs * i : 20 + cs * (i + 1)] - for i in range(3, 6) + line[20 + cs * i : 20 + cs * (i + 1)] for i in range(3, 6) ] except ValueError: # Remember that we got this error @@ -227,8 +221,7 @@ def _read_first_frame(self): ts.velocities = velocities if missed_vel: warnings.warn( - "Not all velocities were present. " - "Unset velocities set to zero." + "Not all velocities were present. " "Unset velocities set to zero." ) self.ts.frame = 0 # 0-based frame number @@ -255,9 +248,7 @@ def _read_first_frame(self): if self.convert_units: self.convert_pos_from_native(self.ts._pos) # in-place ! if self.ts.dimensions is not None: - self.convert_pos_from_native( - self.ts.dimensions[:3] - ) # in-place! + self.convert_pos_from_native(self.ts.dimensions[:3]) # in-place! if self.ts.has_velocities: # converts nm/ps to A/ps units self.convert_velocities_from_native(self.ts._velocities) @@ -328,9 +319,7 @@ class GROWriter(base.WriterBase): "box_orthorhombic": "{box[0]:10.5f} {box[1]:9.5f} {box[2]:9.5f}\n", "box_triclinic": "{box[0]:10.5f} {box[4]:9.5f} {box[8]:9.5f} {box[1]:9.5f} {box[2]:9.5f} {box[3]:9.5f} {box[5]:9.5f} {box[6]:9.5f} {box[7]:9.5f}\n", } - fmt["xyz_v"] = ( - fmt["xyz"][:-1] + "{vel[0]:8.4f}{vel[1]:8.4f}{vel[2]:8.4f}\n" - ) + fmt["xyz_v"] = fmt["xyz"][:-1] + "{vel[0]:8.4f}{vel[1]:8.4f}{vel[2]:8.4f}\n" def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): """Set up a GROWriter with a precision of 3 decimal places. @@ -369,9 +358,7 @@ def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): self.n_atoms = n_atoms self.reindex = kwargs.pop("reindex", True) - self.convert_units = ( - convert_units # convert length and time to base units - ) + self.convert_units = convert_units # convert length and time to base units def write(self, obj): """Write selection at current trajectory frame to file. @@ -464,9 +451,7 @@ def write(self, obj): raise ValueError( "GRO files must have coordinate values between " "{0:.3f} and {1:.3f} nm: No file was written." - "".format( - self.gro_coor_limits["min"], self.gro_coor_limits["max"] - ) + "".format(self.gro_coor_limits["min"], self.gro_coor_limits["max"]) ) with util.openany(self.filename, "wt") as output_gro: @@ -480,9 +465,7 @@ def write(self, obj): for atom_index, resid, resname, name in zip( range(ag.n_atoms), resids, resnames, names ): - truncated_atom_index = util.ltruncate_int( - atom_indices[atom_index], 5 - ) + truncated_atom_index = util.ltruncate_int(atom_indices[atom_index], 5) truncated_resid = util.ltruncate_int(resid, 5) if has_velocities: output_gro.write( @@ -518,9 +501,7 @@ def write(self, obj): warnings.warn(wmsg) box = np.zeros(3) else: - box = self.convert_pos_to_native( - ag.dimensions[:3], inplace=False - ) + box = self.convert_pos_to_native(ag.dimensions[:3], inplace=False) # orthorhombic cell, only lengths along axes needed in gro output_gro.write(self.fmt["box_orthorhombic"].format(box=box)) else: @@ -529,7 +510,5 @@ def write(self, obj): except AttributeError: # for Timestep tri_dims = obj.triclinic_dimensions # full output - box = self.convert_pos_to_native( - tri_dims.flatten(), inplace=False - ) + box = self.convert_pos_to_native(tri_dims.flatten(), inplace=False) output_gro.write(self.fmt["box_triclinic"].format(box=box)) diff --git a/package/MDAnalysis/coordinates/GSD.py b/package/MDAnalysis/coordinates/GSD.py index 8212037e929..de008e62784 100644 --- a/package/MDAnalysis/coordinates/GSD.py +++ b/package/MDAnalysis/coordinates/GSD.py @@ -50,6 +50,7 @@ .. autofunction:: gsd_pickle_open """ + import numpy as np try: @@ -128,6 +129,7 @@ def _reopen(self): self.open_trajectory() def _read_frame(self, frame): + frame = int(frame) try: myframe = self._file[frame] except IndexError: diff --git a/package/MDAnalysis/coordinates/H5MD.py b/package/MDAnalysis/coordinates/H5MD.py index c597c36e4a4..82b9efdd65b 100644 --- a/package/MDAnalysis/coordinates/H5MD.py +++ b/package/MDAnalysis/coordinates/H5MD.py @@ -207,6 +207,7 @@ :members: """ + import warnings import numpy as np @@ -399,9 +400,7 @@ class H5MDReader(base.ReaderBase): version="1.1", ) @store_init_arguments - def __init__( - self, filename, convert_units=True, driver=None, comm=None, **kwargs - ): + def __init__(self, filename, convert_units=True, driver=None, comm=None, **kwargs): """ Parameters ---------- @@ -527,17 +526,15 @@ def _translate_h5md_units(self, group, unit): if value: if "unit" in self._particle_group[name]["time"].attrs: try: - self.units["time"] = self._unit_translation[ - "time" - ][self._particle_group[name]["time"].attrs["unit"]] + self.units["time"] = self._unit_translation["time"][ + self._particle_group[name]["time"].attrs["unit"] + ] break except KeyError: raise RuntimeError( errmsg.format( unit, - self._particle_group[name]["time"].attrs[ - "unit" - ], + self._particle_group[name]["time"].attrs["unit"], ) ) from None @@ -552,33 +549,23 @@ def _translate_h5md_units(self, group, unit): raise RuntimeError( errmsg.format( unit, - self._particle_group[group]["value"].attrs[ - "unit" - ], + self._particle_group[group]["value"].attrs["unit"], ) ) from None # if position group is not provided, can still get 'length' unit # from unitcell box - if (not self._has["position"]) and ( - "edges" in self._particle_group["box"] - ): + if (not self._has["position"]) and ("edges" in self._particle_group["box"]): if "unit" in self._particle_group["box/edges/value"].attrs: try: - self.units["length"] = self._unit_translation[ - "length" - ][ - self._particle_group["box/edges/value"].attrs[ - "unit" - ] + self.units["length"] = self._unit_translation["length"][ + self._particle_group["box/edges/value"].attrs["unit"] ] except KeyError: raise RuntimeError( errmsg.format( unit, - self._particle_group["box/edges/value"].attrs[ - "unit" - ], + self._particle_group["box/edges/value"].attrs["unit"], ) ) from None @@ -647,9 +634,7 @@ def open_trajectory(self): # pulls first key out of 'particles' # allows for arbitrary name of group1 in 'particles' - self._particle_group = self._file["particles"][ - list(self._file["particles"])[0] - ] + self._particle_group = self._file["particles"][list(self._file["particles"])[0]] @property def n_frames(self): @@ -721,9 +706,9 @@ def _copy_to_data(self): try: # if has value as subkey read directly into data if "value" in self._file["observables"][key]: - self.ts.data[key] = self._file["observables"][key][ - "value" - ][self._frame] + self.ts.data[key] = self._file["observables"][key]["value"][ + self._frame + ] # if value is not a subkey, read dict of subkeys else: for subkey in self._file["observables"][key].keys(): @@ -742,9 +727,7 @@ def _copy_to_data(self): for name, value in self._has.items(): if value: if "time" in self._particle_group[name]: - self.ts.time = self._particle_group[name]["time"][ - self._frame - ] + self.ts.time = self._particle_group[name]["time"][self._frame] break for name, value in self._has.items(): if value: @@ -758,9 +741,7 @@ def _read_dataset_into_ts(self, dataset, attribute): """reads position, velocity, or force dataset array at current frame into corresponding ts attribute""" - n_atoms_now = self._particle_group[f"{dataset}/value"][ - self._frame - ].shape[0] + n_atoms_now = self._particle_group[f"{dataset}/value"][self._frame].shape[0] if n_atoms_now != self.n_atoms: raise ValueError( f"Frame {self._frame} of the {dataset} dataset" @@ -784,10 +765,7 @@ def _convert_units(self): self.ts.time = self.convert_time_from_native(self.ts.time) - if ( - "edges" in self._particle_group["box"] - and self.ts.dimensions is not None - ): + if "edges" in self._particle_group["box"] and self.ts.dimensions is not None: self.convert_pos_from_native(self.ts.dimensions[:3]) if self._has["position"]: @@ -895,9 +873,7 @@ def __getstate__(self): def __setstate__(self, state): self.__dict__ = state - self._particle_group = self._file["particles"][ - list(self._file["particles"])[0] - ] + self._particle_group = self._file["particles"][list(self._file["particles"])[0]] class H5MDWriter(base.WriterBase): @@ -1243,8 +1219,7 @@ def _write_next_frame(self, ag): if ts.n_atoms != self.n_atoms: raise IOError( - "H5MDWriter: Timestep does not have" - " the correct number of atoms" + "H5MDWriter: Timestep does not have" " the correct number of atoms" ) # This should only be called once when first timestep is read. @@ -1303,9 +1278,7 @@ def _open_file(self): """ - self.h5md_file = h5py.File( - name=self.filename, mode="w", driver=self._driver - ) + self.h5md_file = h5py.File(name=self.filename, mode="w", driver=self._driver) # fill in H5MD metadata from kwargs self.h5md_file.require_group("h5md") @@ -1340,9 +1313,7 @@ def _initialize_hdf5_datasets(self, ts): # if prompted by the writer with the self._write_* attributes self._has = { group: ( - getattr(ts, f"has_{attr}") - if getattr(self, f"_write_{attr}") - else False + getattr(ts, f"has_{attr}") if getattr(self, f"_write_{attr}") else False ) for group, attr in zip( ("position", "velocity", "force"), @@ -1493,9 +1464,7 @@ def _set_attr_unit(self, dset, unit): if self.units[unit] is None: return - dset.attrs["unit"] = self._unit_translation_dict[unit][ - self.units[unit] - ] + dset.attrs["unit"] = self._unit_translation_dict[unit][self.units[unit]] def _write_next_timestep(self, ts): """Write coordinates and unitcell information to H5MD file. @@ -1539,9 +1508,7 @@ def _write_next_timestep(self, ts): if "edges" in self._traj["box"]: self._edges.resize(self._edges.shape[0] + 1, axis=0) - self._edges.write_direct( - ts.triclinic_dimensions, dest_sel=np.s_[i, :] - ) + self._edges.write_direct(ts.triclinic_dimensions, dest_sel=np.s_[i, :]) # These datasets are not resized if n_frames was provided as an # argument, as they were initialized with their full size. if self.has_positions: @@ -1668,9 +1635,7 @@ def __getstate__(self): return {"name": self.filename, "mode": self.mode, "driver": driver} def __setstate__(self, state): - self.__init__( - name=state["name"], mode=state["mode"], driver=state["driver"] - ) + self.__init__(name=state["name"], mode=state["mode"], driver=state["driver"]) def __getnewargs__(self): """Override the h5py getnewargs to skip its error message""" diff --git a/package/MDAnalysis/coordinates/IMD.py b/package/MDAnalysis/coordinates/IMD.py index 4945d43adfc..e810ccdf67a 100644 --- a/package/MDAnalysis/coordinates/IMD.py +++ b/package/MDAnalysis/coordinates/IMD.py @@ -2,30 +2,30 @@ IMDReader --- :mod:`MDAnalysis.coordinates.IMD` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This module provides support for reading molecular dynamics simulation data via the +This module provides support for reading molecular dynamics simulation data via the `Interactive Molecular Dynamics (IMD) protocol v3 `_. The IMD protocol allows two-way communicating molecular simulation data through a socket. Via IMD, a simulation engine sends data to a receiver (in this case, the IMDClient) and the receiver can send forces and specific control -requests (such as pausing, resuming, or terminating the simulation) back to the simulation engine. +requests (such as pausing, resuming, or terminating the simulation) back to the simulation engine. .. note:: This reader only supports IMDv3, which is implemented in GROMACS, LAMMPS, and NAMD at varying - stages of development. See the `imdclient simulation engine docs`_ for more. + stages of development. See the `imdclient simulation engine docs`_ for more. While IMDv2 is widely available in simulation engines, it was designed primarily for visualization and gaps are allowed in the stream (i.e., an inconsistent number of integrator time steps between transmitted coordinate arrays is allowed) The :class:`IMDReader` connects to a simulation via a socket and receives coordinate, velocity, force, and energy data as the simulation progresses. This allows for real-time -monitoring and analysis of ongoing simulations. It uses the `imdclient package `_ +monitoring and analysis of ongoing simulations. It uses the `imdclient package `_ (dependency) to implement the IMDv3 protocol and manage the socket connection and data parsing. .. seealso:: :class:`IMDReader` Technical details and parameter options for the reader class - + `imdclient documentation `_ Complete documentation for the IMDClient package - + `IMDClient GitHub repository `_ Source code and development resources @@ -35,7 +35,7 @@ ------------- As an example of reading a stream, after configuring GROMACS to run a simulation with IMDv3 enabled -(see the `imdclient simulation engine docs`_ for +(see the `imdclient simulation engine docs`_ for up-to-date resources on configuring each simulation engine), use the following commands: .. code-block:: bash @@ -55,8 +55,8 @@ print(f'{ts.time:8.3f} {sel[0].position} {sel[0].velocity} {sel[0].force} {u.dimensions[0:3]}') .. important:: - **Jupyter Notebook Users**: When using IMDReader in Jupyter notebooks, be aware that - **kernel restarts will not gracefully close active IMD connections**. This can leave + **Jupyter Notebook Users**: When using IMDReader in Jupyter notebooks, be aware that + **kernel restarts will not gracefully close active IMD connections**. This can leave socket connections open, potentially preventing new connections to the same stream. Always use ``try/except/finally`` blocks to ensure proper cleanup: @@ -64,7 +64,7 @@ .. code-block:: python import MDAnalysis as mda - + try: u = mda.Universe("topol.tpr", "imd://localhost:8889") except Exception as e: @@ -79,19 +79,19 @@ # Ensure connection is closed u.trajectory.close() - Always explicitly call ``u.trajectory.close()`` when finished with analysis to + Always explicitly call ``u.trajectory.close()`` when finished with analysis to ensure connection is closed properly. Important Limitations --------------------- -.. warning:: - The IMDReader has some important limitations that are inherent in streaming data. +.. warning:: + The IMDReader has some important limitations that are inherent in streaming data. -Since IMD streams data in real-time from a running simulation, it has fundamental +Since IMD streams data in real-time from a running simulation, it has fundamental constraints that differ from traditional trajectory readers: -* **No random access**: Cannot jump to arbitrary frame numbers or seek backwards +* **No random access**: Cannot jump to arbitrary frame numbers or seek backwards * **Forward-only access**: You can only move forward through frames as they arrive * **No trajectory length**: The total number of frames is unknown until the simulation ends * **Single-use iteration**: Cannot restart or rewind once the stream has been consumed @@ -108,17 +108,17 @@ Multiple Client Connections --------------------------- -The ability to establish multiple simultaneous connections to the same IMD port is -**MD engine implementation dependent**. Some simulation engines may allow multiple -clients to connect concurrently, while others may reject or fail additional connection +The ability to establish multiple simultaneous connections to the same IMD port is +**MD engine implementation dependent**. Some simulation engines may allow multiple +clients to connect concurrently, while others may reject or fail additional connection attempts. -See the `imdclient simulation engine docs`_ for further details. +See the `imdclient simulation engine docs`_ for further details. .. important:: - Even when multiple connections are supported by the simulation engine, each connection - receives its own independent data stream. These streams may contain different data - depending on the simulation engine's configuration, so multiple connections should + Even when multiple connections are supported by the simulation engine, each connection + receives its own independent data stream. These streams may contain different data + depending on the simulation engine's configuration, so multiple connections should not be assumed to provide identical data streams. Classes @@ -302,9 +302,7 @@ def _load_imdframe_into_ts(self, imdf): self.ts.data["dt"] = imdf.dt self.ts.data["step"] = imdf.step if imdf.energies is not None: - self.ts.data.update( - {k: v for k, v in imdf.energies.items() if k != "step"} - ) + self.ts.data.update({k: v for k, v in imdf.energies.items() if k != "step"}) if imdf.box is not None: self.ts.dimensions = core.triclinic_box(*imdf.box) if imdf.positions is not None: diff --git a/package/MDAnalysis/coordinates/LAMMPS.py b/package/MDAnalysis/coordinates/LAMMPS.py index 6e0043321d3..f8530ed40c6 100644 --- a/package/MDAnalysis/coordinates/LAMMPS.py +++ b/package/MDAnalysis/coordinates/LAMMPS.py @@ -136,6 +136,7 @@ :inherited-members: """ + import os import numpy as np @@ -253,9 +254,7 @@ def _read_first_frame(self): if self.convert_units: self.convert_pos_from_native(self.ts._pos) # in-place ! try: - self.convert_velocities_from_native( - self.ts._velocities - ) # in-place ! + self.convert_velocities_from_native(self.ts._velocities) # in-place ! except AttributeError: pass @@ -330,9 +329,7 @@ def _write_atoms(self, atoms, data): moltags = data.get("molecule_tag", np.zeros(len(atoms), dtype=int)) if self.convert_units: - coordinates = self.convert_pos_to_native( - atoms.positions, inplace=False - ) + coordinates = self.convert_pos_to_native(atoms.positions, inplace=False) if has_charges: for index, moltag, atype, charge, coords in zip( @@ -357,9 +354,7 @@ def _write_velocities(self, atoms): self.f.write("Velocities\n") self.f.write("\n") indices = atoms.indices + 1 - velocities = self.convert_velocities_to_native( - atoms.velocities, inplace=False - ) + velocities = self.convert_velocities_to_native(atoms.velocities, inplace=False) for index, vel in zip(indices, velocities): self.f.write( "{i:d} {x:.10f} {y:.10f} {z:.10f}\n".format( @@ -376,9 +371,7 @@ def _write_masses(self, atoms): for atype in range(1, max_type + 1): # search entire universe for mass info, not just writing selection masses = set( - atoms.universe.atoms.select_atoms( - "type {:d}".format(atype) - ).masses + atoms.universe.atoms.select_atoms("type {:d}".format(atype)).masses ) if len(masses) == 0: mass_dict[atype] = 1.0 @@ -471,10 +464,7 @@ def write(self, selection, frame=None): try: atoms.types.astype(np.int32) except ValueError: - errmsg = ( - "LAMMPS.DATAWriter: atom types must be convertible to " - "integers" - ) + errmsg = "LAMMPS.DATAWriter: atom types must be convertible to " "integers" raise ValueError(errmsg) from None try: @@ -499,24 +489,18 @@ def write(self, selection, frame=None): for btype, attr_name in attrs: features[btype] = atoms.__getattribute__(attr_name) - self.f.write( - "{:>12d} {}\n".format(len(features[btype]), attr_name) - ) + self.f.write("{:>12d} {}\n".format(len(features[btype]), attr_name)) features[btype] = features[btype].atomgroup_intersection( atoms, strict=True ) self.f.write("\n") self.f.write( - "{:>12d} atom types\n".format( - max(atoms.types.astype(np.int32)) - ) + "{:>12d} atom types\n".format(max(atoms.types.astype(np.int32))) ) for btype, attr in features.items(): - self.f.write( - "{:>12d} {} types\n".format(len(attr.types()), btype) - ) + self.f.write("{:>12d} {} types\n".format(len(attr.types()), btype)) self._write_dimensions(atoms.dimensions) @@ -823,9 +807,7 @@ def _read_next_timestep(self): try: # this will automatically select in order of priority # unscaled, scaled, unwrapped, scaled_unwrapped - self.lammps_coordinate_convention = list(convention_to_col_ix)[ - 0 - ] + self.lammps_coordinate_convention = list(convention_to_col_ix)[0] except IndexError: raise ValueError("No coordinate information detected") elif not self.lammps_coordinate_convention in convention_to_col_ix: @@ -852,9 +834,7 @@ def _read_next_timestep(self): "Some of the additional columns are not present " "in the file, they will be ignored" ) - additional_keys = [ - key for key in self._additional_columns if key in attrs - ] + additional_keys = [key for key in self._additional_columns if key in attrs] else: additional_keys = [] for key in additional_keys: @@ -865,9 +845,7 @@ def _read_next_timestep(self): fields = f.readline().split() if ids: indices[i] = fields[attr_to_col_ix["id"]] - coords = np.array( - [fields[dim] for dim in coord_cols], dtype=np.float32 - ) + coords = np.array([fields[dim] for dim in coord_cols], dtype=np.float32) if self._unwrap: images = coords[3:] @@ -884,9 +862,7 @@ def _read_next_timestep(self): # Collect additional cols for attribute_key in additional_keys: - ts.data[attribute_key][i] = fields[ - attr_to_col_ix[attribute_key] - ] + ts.data[attribute_key][i] = fields[attr_to_col_ix[attribute_key]] order = np.argsort(indices) ts.positions = ts.positions[order] @@ -901,9 +877,7 @@ def _read_next_timestep(self): if self.lammps_coordinate_convention.startswith("scaled"): # if coordinates are given in scaled format, undo that - ts.positions = distances.transform_StoR( - ts.positions, ts.dimensions - ) + ts.positions = distances.transform_StoR(ts.positions, ts.dimensions) # Transform to origin after transformation of scaled variables ts.positions -= np.array([xlo, ylo, zlo])[None, :] diff --git a/package/MDAnalysis/coordinates/MMTF.py b/package/MDAnalysis/coordinates/MMTF.py index 4e28eed308a..8d3c9055372 100644 --- a/package/MDAnalysis/coordinates/MMTF.py +++ b/package/MDAnalysis/coordinates/MMTF.py @@ -40,6 +40,7 @@ .. _MMTF: https://www.rcsb.org/news/feature/65a1af31c76ca3abcc925d0c """ + import warnings import mmtf @@ -76,9 +77,7 @@ def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): ) warnings.warn(wmsg, DeprecationWarning) - super(MMTFReader, self).__init__( - filename, convert_units, n_atoms, **kwargs - ) + super(MMTFReader, self).__init__(filename, convert_units, n_atoms, **kwargs) @staticmethod def _format_hint(thing): diff --git a/package/MDAnalysis/coordinates/MOL2.py b/package/MDAnalysis/coordinates/MOL2.py index e3f4c016158..ff665228c97 100644 --- a/package/MDAnalysis/coordinates/MOL2.py +++ b/package/MDAnalysis/coordinates/MOL2.py @@ -123,6 +123,7 @@ 1 BENZENE 1 PERM 0 **** **** 0 ROOT """ + import numpy as np from . import base @@ -233,10 +234,7 @@ def _read_frame(self, frame): try: block = self.frames[frame] except IndexError: - errmsg = ( - f"Invalid frame {frame} for trajectory with length " - f"{len(self)}" - ) + errmsg = f"Invalid frame {frame} for trajectory with length " f"{len(self)}" raise IOError(errmsg) from None sections, coords = self.parse_block(block) @@ -307,9 +305,7 @@ def __init__(self, filename, n_atoms=None, convert_units=True): units are converted to the MDAnalysis base format; [``True``] """ self.filename = filename - self.convert_units = ( - convert_units # convert length and time to base units - ) + self.convert_units = convert_units # convert length and time to base units self.frames_written = 0 @@ -384,9 +380,7 @@ def encode_block(self, obj): atom_lines = "\n".join(atom_lines) try: - substructure = ["@SUBSTRUCTURE\n"] + ts.data[ - "substructure" - ] + substructure = ["@SUBSTRUCTURE\n"] + ts.data["substructure"] except KeyError: substructure = "" @@ -401,9 +395,7 @@ def encode_block(self, obj): molecule[1] = "{0}\n".format(" ".join(check_sums)) molecule.insert(0, "@MOLECULE\n") - return_val = ( - "".join(molecule) + atom_lines + bond_lines + "".join(substructure) - ) + return_val = "".join(molecule) + atom_lines + bond_lines + "".join(substructure) molecule[0] = molecule_0_store molecule[1] = molecule_1_store diff --git a/package/MDAnalysis/coordinates/NAMDBIN.py b/package/MDAnalysis/coordinates/NAMDBIN.py index 834ea346aee..219062983ac 100644 --- a/package/MDAnalysis/coordinates/NAMDBIN.py +++ b/package/MDAnalysis/coordinates/NAMDBIN.py @@ -40,6 +40,7 @@ :members: """ + from struct import pack import numpy as np @@ -66,9 +67,7 @@ def _read_first_frame(self): coord_double = np.fromfile( namdbin, dtype=np.float64, count=self.n_atoms * 3 ) - self.ts._pos[:] = np.array(coord_double, float).reshape( - self.n_atoms, 3 - ) + self.ts._pos[:] = np.array(coord_double, float).reshape(self.n_atoms, 3) @staticmethod def parse_n_atoms(filename, **kwargs): diff --git a/package/MDAnalysis/coordinates/PDB.py b/package/MDAnalysis/coordinates/PDB.py index d8d71044b4a..dfdda59bb55 100644 --- a/package/MDAnalysis/coordinates/PDB.py +++ b/package/MDAnalysis/coordinates/PDB.py @@ -140,6 +140,7 @@ http://www.wwpdb.org/documentation/file-format-content/format33/v3.3.html """ + from io import StringIO, BytesIO import os import errno @@ -157,7 +158,6 @@ from .timestep import Timestep from ..exceptions import NoDataError - logger = logging.getLogger("MDAnalysis.coordinates.PBD") # Pairs of residue name / atom name in use to deduce PDB formatted atom names @@ -774,9 +774,7 @@ def __init__( self.filename = filename # convert length and time to base units self.convert_units = convert_units - self._multiframe = ( - self.multiframe if multiframe is None else multiframe - ) + self._multiframe = self.multiframe if multiframe is None else multiframe self.bonds = bonds self._reindex = reindex @@ -819,8 +817,7 @@ def _write_pdb_title(self): ) else: self.TITLE( - "MDANALYSIS FRAME {0:d}: {1!s}" - "".format(self.start, self.remarks) + "MDANALYSIS FRAME {0:d}: {1!s}" "".format(self.start, self.remarks) ) def _write_pdb_header(self): @@ -871,12 +868,8 @@ def _write_pdb_header(self): # Add CRYST1 REMARK (285) # The SCALE record is not included # (We are only implementing a subset of the PDB standard) - self.REMARK( - "285 UNITARY VALUES FOR THE UNIT CELL AUTOMATICALLY SET" - ) - self.REMARK( - "285 BY MDANALYSIS PDBWRITER BECAUSE UNIT CELL INFORMATION" - ) + self.REMARK("285 UNITARY VALUES FOR THE UNIT CELL AUTOMATICALLY SET") + self.REMARK("285 BY MDANALYSIS PDBWRITER BECAUSE UNIT CELL INFORMATION") self.REMARK("285 WAS MISSING.") self.REMARK("285 PROTEIN DATA BANK CONVENTIONS REQUIRE THAT") self.REMARK("285 CRYST1 RECORD IS INCLUDED, BUT THE VALUES ON") @@ -942,9 +935,7 @@ def _check_pdb_coordinates(self): raise ValueError( "PDB files must have coordinate values between " "{0:.3f} and {1:.3f} Angstroem: file writing was " - "aborted.".format( - self.pdb_coor_limits["min"], self.pdb_coor_limits["max"] - ) + "aborted.".format(self.pdb_coor_limits["min"], self.pdb_coor_limits["max"]) ) def _write_pdb_bonds(self): @@ -963,8 +954,7 @@ def _write_pdb_bonds(self): if self._reindex: index_attribute = "index" mapping = { - index: i - for i, index in enumerate(self.obj.atoms.indices, start=1) + index: i for i, index in enumerate(self.obj.atoms.indices, start=1) } atoms = np.sort(self.obj.atoms.indices) else: @@ -1147,10 +1137,7 @@ def _write_next_frame(self, ts=None, **kwargs): try: ts = self.ts except AttributeError: - errmsg = ( - "PBDWriter: no coordinate data to write to " - "trajectory file" - ) + errmsg = "PBDWriter: no coordinate data to write to " "trajectory file" raise NoDataError(errmsg) from None self._check_pdb_coordinates() self._write_timestep(ts, **kwargs) @@ -1360,9 +1347,7 @@ def validate_chainids(chainids, default): vals["serial"] = util.ltruncate_int( atom_ids[i], 5 ) # check for overflow here? - vals["name"] = self._deduce_PDB_atom_name( - atomnames[i], resnames[i] - ) + vals["name"] = self._deduce_PDB_atom_name(atomnames[i], resnames[i]) vals["altLoc"] = altlocs[i][:1] vals["resName"] = resnames[i][:4] vals["resSeq"] = util.ltruncate_int(resids[i], 4) @@ -1447,9 +1432,7 @@ def MODEL(self, modelnumber): Maximum model number is enforced. """ - self.pdbfile.write( - self.fmt["MODEL"].format(int(str(modelnumber)[-4:])) - ) + self.pdbfile.write(self.fmt["MODEL"].format(int(str(modelnumber)[-4:]))) def END(self): """Write END_ record. diff --git a/package/MDAnalysis/coordinates/PDBQT.py b/package/MDAnalysis/coordinates/PDBQT.py index 5388b1ad9b8..e1e0acc578d 100644 --- a/package/MDAnalysis/coordinates/PDBQT.py +++ b/package/MDAnalysis/coordinates/PDBQT.py @@ -157,13 +157,9 @@ def _read_first_frame(self): break if line.startswith("CRYST1"): # lengths - x, y, z = np.float32( - (line[6:15], line[15:24], line[24:33]) - ) + x, y, z = np.float32((line[6:15], line[15:24], line[24:33])) # angles - A, B, G = np.float32( - (line[33:40], line[40:47], line[47:54]) - ) + A, B, G = np.float32((line[33:40], line[40:47], line[47:54])) unitcell[:] = x, y, z, A, B, G if line.startswith(("ATOM", "HETATM")): # convert all entries at the end once for optimal speed @@ -268,9 +264,7 @@ def write(self, selection, frame=None): frame = 0 # should catch cases when we are analyzing a single PDB (?) atoms = selection.atoms # make sure to use atoms (Issue 46) - coor = ( - atoms.positions - ) # can write from selection == Universe (Issue 49) + coor = atoms.positions # can write from selection == Universe (Issue 49) # Check attributes attrs = {} @@ -319,9 +313,7 @@ def write(self, selection, frame=None): raise ValueError( "PDB files must have coordinate values between {0:.3f}" " and {1:.3f} Angstroem: No file was written." - "".format( - self.pdb_coor_limits["min"], self.pdb_coor_limits["max"] - ) + "".format(self.pdb_coor_limits["min"], self.pdb_coor_limits["max"]) ) # Write title record diff --git a/package/MDAnalysis/coordinates/PQR.py b/package/MDAnalysis/coordinates/PQR.py index a2f5a119f72..bb05162454a 100644 --- a/package/MDAnalysis/coordinates/PQR.py +++ b/package/MDAnalysis/coordinates/PQR.py @@ -105,6 +105,7 @@ .. _PDB2PQR: https://pdb2pqr.readthedocs.io/en/latest/ .. _PDB: http://www.wwpdb.org/documentation/file-format """ + import itertools import numpy as np import warnings @@ -219,9 +220,7 @@ def __init__(self, filename, convert_units=True, **kwargs): top of the PQR file """ self.filename = util.filename(filename, ext="pqr", keep=True) - self.convert_units = ( - convert_units # convert length and time to base units - ) + self.convert_units = convert_units # convert length and time to base units self.remarks = kwargs.pop("remarks", "PQR file written by MDAnalysis") def write(self, selection, frame=None): @@ -256,9 +255,7 @@ def write(self, selection, frame=None): frame = 0 # should catch cases when we are analyzing a single frame(?) atoms = selection.atoms # make sure to use atoms (Issue 46) - coordinates = ( - atoms.positions - ) # can write from selection == Universe (Issue 49) + coordinates = atoms.positions # can write from selection == Universe (Issue 49) if self.convert_units: self.convert_pos_to_native( coordinates @@ -322,9 +319,7 @@ def write(self, selection, frame=None): pqrfile.write(self.fmt_remark.format(rem, 1)) pqrfile.write( self.fmt_remark.format( - "Input: frame {0} of {1}".format( - frame, u.trajectory.filename - ), + "Input: frame {0} of {1}".format(frame, u.trajectory.filename), 5, ) ) diff --git a/package/MDAnalysis/coordinates/ParmEd.py b/package/MDAnalysis/coordinates/ParmEd.py index 982231c11a6..6d8363483bf 100644 --- a/package/MDAnalysis/coordinates/ParmEd.py +++ b/package/MDAnalysis/coordinates/ParmEd.py @@ -28,7 +28,6 @@ MDA2PMD, ) - warnings.warn( "This module is deprecated as of MDAnalysis version 2.0.0. " "It will be removed in MDAnalysis version 3.0.0. " diff --git a/package/MDAnalysis/coordinates/TNG.py b/package/MDAnalysis/coordinates/TNG.py index 44c6890dcf7..a5d868360f0 100644 --- a/package/MDAnalysis/coordinates/TNG.py +++ b/package/MDAnalysis/coordinates/TNG.py @@ -148,9 +148,7 @@ class TNGReader(base.ReaderBase): _forces_blockname, ] - @due.dcite( - Doi("10.1002/jcc.23495"), description="The TNG paper", path=__name__ - ) + @due.dcite(Doi("10.1002/jcc.23495"), description="The TNG paper", path=__name__) @store_init_arguments def __init__(self, filename: str, convert_units: bool = True, **kwargs): """Initialize a TNG trajectory @@ -164,9 +162,7 @@ def __init__(self, filename: str, convert_units: bool = True, **kwargs): """ if not HAS_PYTNG: - raise ImportError( - "TNGReader: To read TNG files please install pytng" - ) + raise ImportError("TNGReader: To read TNG files please install pytng") super(TNGReader, self).__init__(filename, **kwargs) @@ -197,35 +193,27 @@ def __init__(self, filename: str, convert_units: bool = True, **kwargs): self._has_positions = self._positions_blockname in self._block_names if self._has_positions: self._special_block_present[self._positions_blockname] = True - self.ts.positions = ( - self._file_iterator.make_ndarray_for_block_from_name( - self._positions_blockname - ) + self.ts.positions = self._file_iterator.make_ndarray_for_block_from_name( + self._positions_blockname ) self._has_velocities = self._velocities_blockname in self._block_names if self._has_velocities: self._special_block_present[self._velocities_blockname] = True - self.ts.velocities = ( - self._file_iterator.make_ndarray_for_block_from_name( - self._velocities_blockname - ) + self.ts.velocities = self._file_iterator.make_ndarray_for_block_from_name( + self._velocities_blockname ) self._has_forces = self._forces_blockname in self._block_names if self._has_forces: self._special_block_present[self._forces_blockname] = True - self.ts.forces = ( - self._file_iterator.make_ndarray_for_block_from_name( - self._forces_blockname - ) + self.ts.forces = self._file_iterator.make_ndarray_for_block_from_name( + self._forces_blockname ) # check for any additional blocks that will be read into ts.data self._additional_blocks = [ - block - for block in self._block_names - if block not in self._special_blocks + block for block in self._block_names if block not in self._special_blocks ] self._check_strides_and_frames() self._frame = 0 @@ -277,9 +265,7 @@ def _check_strides_and_frames(self): " It will not be read" ) else: - self._additional_blocks_to_read.append( - block - ) # pragma: no cover + self._additional_blocks_to_read.append(block) # pragma: no cover else: self._additional_blocks_to_read.append(block) @@ -303,9 +289,7 @@ def parse_n_atoms(filename: str) -> int: """ if not HAS_PYTNG: - raise ImportError( - "TNGReader: To read TNG files please install pytng" - ) + raise ImportError("TNGReader: To read TNG files please install pytng") with pytng.TNGFileIterator(filename, "r") as tng: n_atoms = tng.n_atoms return n_atoms @@ -487,9 +471,7 @@ def _frame_to_ts( add_block_stride = self._block_strides[block] # check we are on stride for our block if not (add_block_stride % self._global_stride): - block_data = ( - self._file_iterator.make_ndarray_for_block_from_name(block) - ) + block_data = self._file_iterator.make_ndarray_for_block_from_name(block) # additional blocks read into ts.data dictionary ts.data[block] = curr_step.get_blockid( self._block_dictionary[block], block_data diff --git a/package/MDAnalysis/coordinates/TPR.py b/package/MDAnalysis/coordinates/TPR.py index 1940da4c924..9f00287890e 100644 --- a/package/MDAnalysis/coordinates/TPR.py +++ b/package/MDAnalysis/coordinates/TPR.py @@ -87,7 +87,9 @@ def _read_first_frame(self): try: th = tpr_utils.read_tpxheader(data) # tpxheader except (EOFError, ValueError): - msg = f"{self.filename}: Invalid tpr coordinate file or cannot be recognized" + msg = ( + f"{self.filename}: Invalid tpr coordinate file or cannot be recognized" + ) logger.critical(msg) raise IOError(msg) @@ -115,9 +117,7 @@ def _read_first_frame(self): if state_ngtc > 0: if th.fver < 69: # redundancy due to different versions tpr_utils.ndo_real(data, state_ngtc) - tpr_utils.ndo_real( - data, state_ngtc - ) # relevant to Berendsen tcoupl_lambda + tpr_utils.ndo_real(data, state_ngtc) # relevant to Berendsen tcoupl_lambda tpr_top = tpr_utils.do_mtop( data, th.fver, tpr_resid_from_one=True, precision=th.precision diff --git a/package/MDAnalysis/coordinates/TRC.py b/package/MDAnalysis/coordinates/TRC.py index 4c7c4009ec7..8e0e755cafc 100644 --- a/package/MDAnalysis/coordinates/TRC.py +++ b/package/MDAnalysis/coordinates/TRC.py @@ -229,9 +229,7 @@ def _read_traj_properties(self): # Timestep-block # if "TIMESTEP" == stripped_line: - l_timestep_timevalues.append( - float(f.readline().split()[1]) - ) + l_timestep_timevalues.append(float(f.readline().split()[1])) while stripped_line != "END": stripped_line = f.readline().strip() # @@ -268,9 +266,7 @@ def _read_traj_properties(self): # instead of looping over the file, looking for an END # we can seek to where the end of the block should be. current_pos = f.tell() - len(line) - f.seek( - f.tell() - len(line) + block_size["POSITIONRED"] - ) + f.seek(f.tell() - len(line) + block_size["POSITIONRED"]) # Check if we are at the correct position # If not, set inconsistent_size to true and seek back @@ -283,9 +279,7 @@ def _read_traj_properties(self): f.seek(current_pos) if frame_counter == 0: - errormsg = ( - "No supported blocks were found within the GROMOS trajectory!" - ) + errormsg = "No supported blocks were found within the GROMOS trajectory!" logger.error(errormsg) raise ValueError(errormsg) @@ -294,9 +288,7 @@ def _read_traj_properties(self): traj_properties["l_blockstart_offset"] = l_blockstart_offset if len(l_timestep_timevalues) >= 2: - traj_properties["dt"] = ( - l_timestep_timevalues[1] - l_timestep_timevalues[0] - ) + traj_properties["dt"] = l_timestep_timevalues[1] - l_timestep_timevalues[0] else: traj_properties["dt"] = 0 warnmsg = "The trajectory does not contain TIMESTEP blocks!" @@ -359,9 +351,7 @@ def _read_GROMOS11_trajectory(self): elif ntb_setting in [1, 2]: tmp_a, tmp_b, tmp_c = map(float, f.readline().split()) - tmp_alpha, tmp_beta, tmp_gamma = map( - float, f.readline().split() - ) + tmp_alpha, tmp_beta, tmp_gamma = map(float, f.readline().split()) frameDat["dimensions"] = [ tmp_a, tmp_b, @@ -373,21 +363,13 @@ def _read_GROMOS11_trajectory(self): self.periodic = True # gb_line3 - if ( - sum(abs(float(v)) for v in f.readline().split()) - > 1e-10 - ): - errormsg = ( - "This reader doesnt't support a shifted origin!" - ) + if sum(abs(float(v)) for v in f.readline().split()) > 1e-10: + errormsg = "This reader doesnt't support a shifted origin!" logger.error(errormsg) raise ValueError(errormsg) # gb_line4 - if ( - sum(abs(float(v)) for v in f.readline().split()) - > 1e-10 - ): + if sum(abs(float(v)) for v in f.readline().split()) > 1e-10: errormsg = "This reader doesnt't support yawed, pitched or rolled boxes!" logger.error(errormsg) raise ValueError(errormsg) @@ -399,8 +381,7 @@ def _read_GROMOS11_trajectory(self): break elif any( - non_supp_bn in line - for non_supp_bn in TRCReader.NOT_SUPPORTED_BLOCKS + non_supp_bn in line for non_supp_bn in TRCReader.NOT_SUPPORTED_BLOCKS ): for non_supp_bn in TRCReader.NOT_SUPPORTED_BLOCKS: if non_supp_bn == stripped_line: @@ -415,9 +396,7 @@ def _read_frame(self, i): self._frame = i - 1 # Move position in file just (-2 byte) before the start of the block - self.trcfile.seek( - self.traj_properties["l_blockstart_offset"][i] - 2, 0 - ) + self.trcfile.seek(self.traj_properties["l_blockstart_offset"][i] - 2, 0) return self._read_next_timestep() diff --git a/package/MDAnalysis/coordinates/TRJ.py b/package/MDAnalysis/coordinates/TRJ.py index e9799e4d945..227c7679ecd 100644 --- a/package/MDAnalysis/coordinates/TRJ.py +++ b/package/MDAnalysis/coordinates/TRJ.py @@ -129,6 +129,7 @@ .. _GitHub Discussions: https://github.com/MDAnalysis/mdanalysis/discussions """ + import scipy.io.netcdf import numpy as np import warnings @@ -141,6 +142,7 @@ from . import base from ..lib import util from ..lib.util import store_init_arguments + logger = logging.getLogger("MDAnalysis.coordinates.AMBER") @@ -172,8 +174,9 @@ class TRJReader(base.ReaderBase): Frames now 0-based instead of 1-based. kwarg `delta` renamed to `dt`, for uniformity with other Readers """ - format = ['TRJ', 'MDCRD', 'CRDBOX'] - units = {'time': 'ps', 'length': 'Angstrom'} + + format = ["TRJ", "MDCRD", "CRDBOX"] + units = {"time": "ps", "length": "Angstrom"} _Timestep = Timestep @store_init_arguments @@ -189,14 +192,14 @@ def __init__(self, filename, n_atoms=None, **kwargs): # FORMAT(10F8.3) (X(i), Y(i), Z(i), i=1,NATOM) self.default_line_parser = util.FORTRANReader("10F8.3") - self.lines_per_frame = int(np.ceil(3.0 * self.n_atoms / len( - self.default_line_parser))) + self.lines_per_frame = int( + np.ceil(3.0 * self.n_atoms / len(self.default_line_parser)) + ) # The last line per frame might have fewer than 10 # We determine right away what parser we need for the last # line because it will be the same for all frames. last_per_line = 3 * self.n_atoms % len(self.default_line_parser) - self.last_line_parser = util.FORTRANReader("{0:d}F8.3".format( - last_per_line)) + self.last_line_parser = util.FORTRANReader("{0:d}F8.3".format(last_per_line)) # FORMAT(10F8.3) BOX(1), BOX(2), BOX(3) # is this always on a separate line?? @@ -241,7 +244,7 @@ def _read_next_timestep(self): if self.periodic: line = next(self.trjfile) box = self.box_line_parser.read(line) - ts.dimensions = box + [90., 90., 90.] # assumed + ts.dimensions = box + [90.0, 90.0, 90.0] # assumed # probably slow ... could be optimized by storing the coordinates in # X,Y,Z lists or directly filling the array; the array/reshape is not @@ -289,7 +292,7 @@ def _detect_amber_box(self): nentries = self.default_line_parser.number_of_matches(line) if nentries == 3: self.periodic = True - ts.dimensions = self.box_line_parser.read(line) + [90., 90., 90.] + ts.dimensions = self.box_line_parser.read(line) + [90.0, 90.0, 90.0] else: self.periodic = False self.close() @@ -340,7 +343,8 @@ def open_trajectory(self): # Chimera uses this check raise OSError( "Header of AMBER formatted trajectory has more than 80 chars. " - "This is probably not a AMBER trajectory.") + "This is probably not a AMBER trajectory." + ) # reset ts ts = self.ts ts.frame = -1 @@ -425,13 +429,15 @@ class NCDFReader(base.ReaderBase): """ - format = ['NCDF', 'NC'] + format = ["NCDF", "NC"] multiframe = True version = "1.0" - units = {'time': 'ps', - 'length': 'Angstrom', - 'velocity': 'Angstrom/ps', - 'force': 'kcal/(mol*Angstrom)'} + units = { + "time": "ps", + "length": "Angstrom", + "velocity": "Angstrom/ps", + "force": "kcal/(mol*Angstrom)", + } _Timestep = Timestep @@ -443,55 +449,60 @@ def __init__(self, filename, n_atoms=None, mmap=None, **kwargs): super(NCDFReader, self).__init__(filename, **kwargs) # ensure maskandscale is off so we don't end up double scaling - self.trjfile = NCDFPicklable(self.filename, - mmap=self._mmap, - maskandscale=False) + self.trjfile = NCDFPicklable(self.filename, mmap=self._mmap, maskandscale=False) # AMBER NetCDF files should always have a convention try: conventions = self.trjfile.Conventions - if not ('AMBER' in conventions.decode('utf-8').split(',') or - 'AMBER' in conventions.decode('utf-8').split()): - errmsg = ("NCDF trajectory {0} does not conform to AMBER " - "specifications, " - "http://ambermd.org/netcdf/nctraj.xhtml " - "('AMBER' must be one of the token in attribute " - "Conventions)".format(self.filename)) + if not ( + "AMBER" in conventions.decode("utf-8").split(",") + or "AMBER" in conventions.decode("utf-8").split() + ): + errmsg = ( + "NCDF trajectory {0} does not conform to AMBER " + "specifications, " + "http://ambermd.org/netcdf/nctraj.xhtml " + "('AMBER' must be one of the token in attribute " + "Conventions)".format(self.filename) + ) logger.fatal(errmsg) raise TypeError(errmsg) except AttributeError: - errmsg = "NCDF trajectory {0} is missing Conventions".format( - self.filename) + errmsg = "NCDF trajectory {0} is missing Conventions".format(self.filename) logger.fatal(errmsg) raise ValueError(errmsg) from None # AMBER NetCDF files should also have a ConventionVersion try: - ConventionVersion = self.trjfile.ConventionVersion.decode('utf-8') + ConventionVersion = self.trjfile.ConventionVersion.decode("utf-8") if not ConventionVersion == self.version: - wmsg = ("NCDF trajectory format is {0!s} but the reader " - "implements format {1!s}".format( - ConventionVersion, self.version)) + wmsg = ( + "NCDF trajectory format is {0!s} but the reader " + "implements format {1!s}".format(ConventionVersion, self.version) + ) warnings.warn(wmsg) logger.warning(wmsg) except AttributeError: errmsg = "NCDF trajectory {0} is missing ConventionVersion".format( - self.filename) + self.filename + ) raise ValueError(errmsg) from None # The AMBER NetCDF standard enforces 64 bit offsets if not self.trjfile.version_byte == 2: - errmsg = ("NCDF trajectory {0} does not conform to AMBER " - "specifications, as detailed in " - "https://ambermd.org/netcdf/nctraj.xhtml " - "(NetCDF file does not use 64 bit offsets " - "[version_byte = 2])".format(self.filename)) + errmsg = ( + "NCDF trajectory {0} does not conform to AMBER " + "specifications, as detailed in " + "https://ambermd.org/netcdf/nctraj.xhtml " + "(NetCDF file does not use 64 bit offsets " + "[version_byte = 2])".format(self.filename) + ) logger.fatal(errmsg) raise TypeError(errmsg) # The AMBER NetCDF standard enforces 3D coordinates try: - if not self.trjfile.dimensions['spatial'] == 3: + if not self.trjfile.dimensions["spatial"] == 3: errmsg = "Incorrect spatial value for NCDF trajectory file" raise TypeError(errmsg) except KeyError: @@ -500,38 +511,46 @@ def __init__(self, filename, n_atoms=None, mmap=None, **kwargs): # AMBER NetCDF specs require program and programVersion. Warn users # if those attributes do not exist - if not (hasattr(self.trjfile, 'program') and - hasattr(self.trjfile, 'programVersion')): - wmsg = ("NCDF trajectory {0} may not fully adhere to AMBER " - "standards as either the `program` or `programVersion` " - "attributes are missing".format(self.filename)) + if not ( + hasattr(self.trjfile, "program") and hasattr(self.trjfile, "programVersion") + ): + wmsg = ( + "NCDF trajectory {0} may not fully adhere to AMBER " + "standards as either the `program` or `programVersion` " + "attributes are missing".format(self.filename) + ) warnings.warn(wmsg) logger.warning(wmsg) try: - self.n_atoms = self.trjfile.dimensions['atom'] + self.n_atoms = self.trjfile.dimensions["atom"] if n_atoms is not None and n_atoms != self.n_atoms: - errmsg = ("Supplied n_atoms ({0}) != natom from ncdf ({1}). " - "Note: n_atoms can be None and then the ncdf value " - "is used!".format(n_atoms, self.n_atoms)) + errmsg = ( + "Supplied n_atoms ({0}) != natom from ncdf ({1}). " + "Note: n_atoms can be None and then the ncdf value " + "is used!".format(n_atoms, self.n_atoms) + ) raise ValueError(errmsg) except KeyError: - errmsg = ("NCDF trajectory {0} does not contain atom " - "information".format(self.filename)) + errmsg = "NCDF trajectory {0} does not contain atom " "information".format( + self.filename + ) raise ValueError(errmsg) from None try: - self.n_frames = self.trjfile.dimensions['frame'] + self.n_frames = self.trjfile.dimensions["frame"] # example trajectory when read with scipy.io.netcdf has # dimensions['frame'] == None (indicating a record dimension that # can grow) whereas if read with netCDF4 I get # len(dimensions['frame']) == 10: in any case, we need to get # the number of frames from somewhere such as the time variable: if self.n_frames is None: - self.n_frames = self.trjfile.variables['coordinates'].shape[0] + self.n_frames = self.trjfile.variables["coordinates"].shape[0] except KeyError: - errmsg = (f"NCDF trajectory {self.filename} does not contain " - f"frame information") + errmsg = ( + f"NCDF trajectory {self.filename} does not contain " + f"frame information" + ) raise ValueError(errmsg) from None try: @@ -545,81 +564,91 @@ def __init__(self, filename, n_atoms=None, mmap=None, **kwargs): # checks for not-implemented features (other units would need to be # hacked into MDAnalysis.units) try: - self._verify_units(self.trjfile.variables['time'].units, 'picosecond') + self._verify_units(self.trjfile.variables["time"].units, "picosecond") self.has_time = True except KeyError: self.has_time = False - wmsg = ("NCDF trajectory does not contain `time` information;" - " `time` will be set as an increasing index") + wmsg = ( + "NCDF trajectory does not contain `time` information;" + " `time` will be set as an increasing index" + ) warnings.warn(wmsg) logger.warning(wmsg) - - self._verify_units(self.trjfile.variables['coordinates'].units, - 'angstrom') + self._verify_units(self.trjfile.variables["coordinates"].units, "angstrom") # Check for scale_factor attributes for all data variables and # store this to multiply through later (Issue #2323) - self.scale_factors = {'time': None, - 'cell_lengths': None, - 'cell_angles': None, - 'coordinates': None, - 'velocities': None, - 'forces': None} + self.scale_factors = { + "time": None, + "cell_lengths": None, + "cell_angles": None, + "coordinates": None, + "velocities": None, + "forces": None, + } for variable in self.trjfile.variables: - if hasattr(self.trjfile.variables[variable], 'scale_factor'): + if hasattr(self.trjfile.variables[variable], "scale_factor"): if variable in self.scale_factors: scale_factor = self.trjfile.variables[variable].scale_factor if not isinstance(scale_factor, (float, np.floating)): raise TypeError(f"{scale_factor} is not a float") self.scale_factors[variable] = scale_factor else: - errmsg = ("scale_factors for variable {0} are " - "not implemented".format(variable)) + errmsg = ( + "scale_factors for variable {0} are " + "not implemented".format(variable) + ) raise NotImplementedError(errmsg) - self.has_velocities = 'velocities' in self.trjfile.variables + self.has_velocities = "velocities" in self.trjfile.variables if self.has_velocities: - self._verify_units(self.trjfile.variables['velocities'].units, - 'angstrom/picosecond') + self._verify_units( + self.trjfile.variables["velocities"].units, "angstrom/picosecond" + ) - self.has_forces = 'forces' in self.trjfile.variables + self.has_forces = "forces" in self.trjfile.variables if self.has_forces: - self._verify_units(self.trjfile.variables['forces'].units, - 'kilocalorie/mole/angstrom') + self._verify_units( + self.trjfile.variables["forces"].units, "kilocalorie/mole/angstrom" + ) - self.periodic = 'cell_lengths' in self.trjfile.variables + self.periodic = "cell_lengths" in self.trjfile.variables if self.periodic: - self._verify_units(self.trjfile.variables['cell_lengths'].units, - 'angstrom') + self._verify_units(self.trjfile.variables["cell_lengths"].units, "angstrom") # As of v1.0.0 only `degree` is accepted as a unit - cell_angle_units = self.trjfile.variables['cell_angles'].units - self._verify_units(cell_angle_units, 'degree') + cell_angle_units = self.trjfile.variables["cell_angles"].units + self._verify_units(cell_angle_units, "degree") self._current_frame = 0 - self.ts = self._Timestep(self.n_atoms, - velocities=self.has_velocities, - forces=self.has_forces, - reader=self, # for dt - **self._ts_kwargs) + self.ts = self._Timestep( + self.n_atoms, + velocities=self.has_velocities, + forces=self.has_forces, + reader=self, # for dt + **self._ts_kwargs, + ) # load first data frame self._read_frame(0) @staticmethod def _verify_units(eval_unit, expected_units): - if eval_unit.decode('utf-8') != expected_units: - errmsg = ("NETCDFReader currently assumes that the trajectory " - "was written in units of {0} instead of {1}".format( - eval_unit.decode('utf-8'), expected_units)) + if eval_unit.decode("utf-8") != expected_units: + errmsg = ( + "NETCDFReader currently assumes that the trajectory " + "was written in units of {0} instead of {1}".format( + eval_unit.decode("utf-8"), expected_units + ) + ) raise NotImplementedError(errmsg) @staticmethod def parse_n_atoms(filename, **kwargs): with scipy.io.netcdf_file(filename, mmap=None) as f: - n_atoms = f.dimensions['atom'] + n_atoms = f.dimensions["atom"] return n_atoms def _get_var_and_scale(self, variable, frame): @@ -646,28 +675,27 @@ def _read_frame(self, frame): # convention... for netcdf could also be a slice raise TypeError("frame must be a positive integer or zero") if frame >= self.n_frames or frame < 0: - raise IndexError("frame index must be 0 <= frame < {0}".format( - self.n_frames)) + raise IndexError( + "frame index must be 0 <= frame < {0}".format(self.n_frames) + ) # note: self.trjfile.variables['coordinates'].shape == (frames, n_atoms, 3) - ts._pos[:] = self._get_var_and_scale('coordinates', frame) + ts._pos[:] = self._get_var_and_scale("coordinates", frame) if self.has_time: - ts.time = self._get_var_and_scale('time', frame) + ts.time = self._get_var_and_scale("time", frame) if self.has_velocities: - ts._velocities[:] = self._get_var_and_scale('velocities', frame) + ts._velocities[:] = self._get_var_and_scale("velocities", frame) if self.has_forces: - ts._forces[:] = self._get_var_and_scale('forces', frame) + ts._forces[:] = self._get_var_and_scale("forces", frame) if self.periodic: unitcell = np.zeros(6) - unitcell[:3] = self._get_var_and_scale('cell_lengths', frame) - unitcell[3:] = self._get_var_and_scale('cell_angles', frame) + unitcell[:3] = self._get_var_and_scale("cell_lengths", frame) + unitcell[3:] = self._get_var_and_scale("cell_angles", frame) ts.dimensions = unitcell if self.convert_units: self.convert_pos_from_native(ts._pos) # in-place ! - self.convert_time_from_native( - ts.time) # in-place ! (hope this works...) + self.convert_time_from_native(ts.time) # in-place ! (hope this works...) if self.has_velocities: - self.convert_velocities_from_native(ts._velocities, - inplace=True) + self.convert_velocities_from_native(ts._velocities, inplace=True) if self.has_forces: self.convert_forces_from_native(ts._forces, inplace=True) if self.periodic: @@ -694,8 +722,8 @@ def _get_dt(self): AttributeError which triggers the default 1 ps return of dt(). """ try: - t1 = self.trjfile.variables['time'][1] - t0 = self.trjfile.variables['time'][0] + t1 = self.trjfile.variables["time"][1] + t0 = self.trjfile.variables["time"][0] except (IndexError, KeyError): raise AttributeError return t1 - t0 @@ -749,13 +777,13 @@ def Writer(self, filename, **kwargs): ------- :class:`NCDFWriter` """ - n_atoms = kwargs.pop('n_atoms', self.n_atoms) - kwargs.setdefault('remarks', self.remarks) - kwargs.setdefault('convert_units', self.convert_units) - kwargs.setdefault('velocities', self.has_velocities) - kwargs.setdefault('forces', self.has_forces) + n_atoms = kwargs.pop("n_atoms", self.n_atoms) + kwargs.setdefault("remarks", self.remarks) + kwargs.setdefault("convert_units", self.convert_units) + kwargs.setdefault("velocities", self.has_velocities) + kwargs.setdefault("forces", self.has_forces) for key in self.scale_factors: - kwargs.setdefault(f'scale_{key}', self.scale_factors[key]) + kwargs.setdefault(f"scale_{key}", self.scale_factors[key]) return NCDFWriter(filename, n_atoms, **kwargs) @@ -888,19 +916,32 @@ class NCDFWriter(base.WriterBase): """ - format = ['NC', 'NCDF'] + format = ["NC", "NCDF"] multiframe = True version = "1.0" - units = {'time': 'ps', - 'length': 'Angstrom', - 'velocity': 'Angstrom/ps', - 'force': 'kcal/(mol*Angstrom)'} - - def __init__(self, filename, n_atoms, remarks=None, convert_units=True, - velocities=False, forces=False, scale_time=None, - scale_cell_lengths=None, scale_cell_angles=None, - scale_coordinates=None, scale_velocities=None, - scale_forces=None, **kwargs): + units = { + "time": "ps", + "length": "Angstrom", + "velocity": "Angstrom/ps", + "force": "kcal/(mol*Angstrom)", + } + + def __init__( + self, + filename, + n_atoms, + remarks=None, + convert_units=True, + velocities=False, + forces=False, + scale_time=None, + scale_cell_lengths=None, + scale_cell_angles=None, + scale_coordinates=None, + scale_velocities=None, + scale_forces=None, + **kwargs, + ): self.filename = filename if n_atoms == 0: raise ValueError("NCDFWriter: no atoms in output trajectory") @@ -908,7 +949,9 @@ def __init__(self, filename, n_atoms, remarks=None, convert_units=True, # convert length and time to base units on the fly? self.convert_units = convert_units - self.remarks = remarks or "AMBER NetCDF format (MDAnalysis.coordinates.trj.NCDFWriter)" + self.remarks = ( + remarks or "AMBER NetCDF format (MDAnalysis.coordinates.trj.NCDFWriter)" + ) self._first_frame = True # signals to open trajectory self.trjfile = None # open on first write with _init_netcdf() @@ -917,16 +960,16 @@ def __init__(self, filename, n_atoms, remarks=None, convert_units=True, self.has_forces = forces self.scale_factors = { - 'time': scale_time, - 'cell_lengths': scale_cell_lengths, - 'cell_angles': scale_cell_angles, - 'coordinates': scale_coordinates, - 'velocities': scale_velocities, - 'forces': scale_forces} + "time": scale_time, + "cell_lengths": scale_cell_lengths, + "cell_angles": scale_cell_angles, + "coordinates": scale_coordinates, + "velocities": scale_velocities, + "forces": scale_forces, + } # NCDF standard enforces float scale_factors for value in self.scale_factors.values(): - if (value is not None) and ( - not isinstance(value, (float, np.floating))): + if (value is not None) and (not isinstance(value, (float, np.floating))): errmsg = f"scale_factor {value} is not a float" raise TypeError(errmsg) @@ -953,89 +996,90 @@ def _init_netcdf(self, periodic=True): """ if not self._first_frame: raise IOError( - errno.EIO, - "Attempt to write to closed file {0}".format(self.filename)) + errno.EIO, "Attempt to write to closed file {0}".format(self.filename) + ) if netCDF4: - ncfile = netCDF4.Dataset(self.filename, 'w', - format='NETCDF3_64BIT') + ncfile = netCDF4.Dataset(self.filename, "w", format="NETCDF3_64BIT") else: - ncfile = scipy.io.netcdf_file(self.filename, - mode='w', version=2, - maskandscale=False) - wmsg = ("Could not find netCDF4 module. Falling back to MUCH " - "slower scipy.io.netcdf implementation for writing.") + ncfile = scipy.io.netcdf_file( + self.filename, mode="w", version=2, maskandscale=False + ) + wmsg = ( + "Could not find netCDF4 module. Falling back to MUCH " + "slower scipy.io.netcdf implementation for writing." + ) logger.warning(wmsg) warnings.warn(wmsg) # Set global attributes. - setattr(ncfile, 'program', 'MDAnalysis.coordinates.TRJ.NCDFWriter') - setattr(ncfile, 'programVersion', MDAnalysis.__version__) - setattr(ncfile, 'Conventions', 'AMBER') - setattr(ncfile, 'ConventionVersion', '1.0') - setattr(ncfile, 'application', 'MDAnalysis') + setattr(ncfile, "program", "MDAnalysis.coordinates.TRJ.NCDFWriter") + setattr(ncfile, "programVersion", MDAnalysis.__version__) + setattr(ncfile, "Conventions", "AMBER") + setattr(ncfile, "ConventionVersion", "1.0") + setattr(ncfile, "application", "MDAnalysis") # Create dimensions - ncfile.createDimension('frame', - None) # unlimited number of steps (can append) - ncfile.createDimension('atom', - self.n_atoms) # number of atoms in system - ncfile.createDimension('spatial', 3) # number of spatial dimensions - ncfile.createDimension('cell_spatial', 3) # unitcell lengths - ncfile.createDimension('cell_angular', 3) # unitcell angles - ncfile.createDimension('label', 5) # needed for cell_angular + ncfile.createDimension("frame", None) # unlimited number of steps (can append) + ncfile.createDimension("atom", self.n_atoms) # number of atoms in system + ncfile.createDimension("spatial", 3) # number of spatial dimensions + ncfile.createDimension("cell_spatial", 3) # unitcell lengths + ncfile.createDimension("cell_angular", 3) # unitcell angles + ncfile.createDimension("label", 5) # needed for cell_angular # Create variables. - coords = ncfile.createVariable('coordinates', 'f4', - ('frame', 'atom', 'spatial')) - setattr(coords, 'units', 'angstrom') - if self.scale_factors['coordinates']: - coords.scale_factor = self.scale_factors['coordinates'] + coords = ncfile.createVariable( + "coordinates", "f4", ("frame", "atom", "spatial") + ) + setattr(coords, "units", "angstrom") + if self.scale_factors["coordinates"]: + coords.scale_factor = self.scale_factors["coordinates"] - spatial = ncfile.createVariable('spatial', 'c', ('spatial', )) - spatial[:] = np.asarray(list('xyz')) + spatial = ncfile.createVariable("spatial", "c", ("spatial",)) + spatial[:] = np.asarray(list("xyz")) - time = ncfile.createVariable('time', 'f4', ('frame',)) - setattr(time, 'units', 'picosecond') - if self.scale_factors['time']: - time.scale_factor = self.scale_factors['time'] + time = ncfile.createVariable("time", "f4", ("frame",)) + setattr(time, "units", "picosecond") + if self.scale_factors["time"]: + time.scale_factor = self.scale_factors["time"] self.periodic = periodic if self.periodic: - cell_lengths = ncfile.createVariable('cell_lengths', 'f8', - ('frame', 'cell_spatial')) - setattr(cell_lengths, 'units', 'angstrom') - if self.scale_factors['cell_lengths']: - cell_lengths.scale_factor = self.scale_factors['cell_lengths'] - - cell_spatial = ncfile.createVariable('cell_spatial', 'c', - ('cell_spatial', )) - cell_spatial[:] = np.asarray(list('abc')) - - cell_angles = ncfile.createVariable('cell_angles', 'f8', - ('frame', 'cell_angular')) - setattr(cell_angles, 'units', 'degree') - if self.scale_factors['cell_angles']: - cell_angles.scale_factor = self.scale_factors['cell_angles'] - - cell_angular = ncfile.createVariable('cell_angular', 'c', - ('cell_angular', 'label')) - cell_angular[:] = np.asarray([list('alpha'), list('beta '), list( - 'gamma')]) + cell_lengths = ncfile.createVariable( + "cell_lengths", "f8", ("frame", "cell_spatial") + ) + setattr(cell_lengths, "units", "angstrom") + if self.scale_factors["cell_lengths"]: + cell_lengths.scale_factor = self.scale_factors["cell_lengths"] + + cell_spatial = ncfile.createVariable("cell_spatial", "c", ("cell_spatial",)) + cell_spatial[:] = np.asarray(list("abc")) + + cell_angles = ncfile.createVariable( + "cell_angles", "f8", ("frame", "cell_angular") + ) + setattr(cell_angles, "units", "degree") + if self.scale_factors["cell_angles"]: + cell_angles.scale_factor = self.scale_factors["cell_angles"] + + cell_angular = ncfile.createVariable( + "cell_angular", "c", ("cell_angular", "label") + ) + cell_angular[:] = np.asarray([list("alpha"), list("beta "), list("gamma")]) # These properties are optional, and are specified on Writer creation if self.has_velocities: - velocs = ncfile.createVariable('velocities', 'f4', - ('frame', 'atom', 'spatial')) - setattr(velocs, 'units', 'angstrom/picosecond') - if self.scale_factors['velocities']: - velocs.scale_factor = self.scale_factors['velocities'] + velocs = ncfile.createVariable( + "velocities", "f4", ("frame", "atom", "spatial") + ) + setattr(velocs, "units", "angstrom/picosecond") + if self.scale_factors["velocities"]: + velocs.scale_factor = self.scale_factors["velocities"] if self.has_forces: - forces = ncfile.createVariable('forces', 'f4', - ('frame', 'atom', 'spatial')) - setattr(forces, 'units', 'kilocalorie/mole/angstrom') - if self.scale_factors['forces']: - forces.scale_factor = self.scale_factors['forces'] + forces = ncfile.createVariable("forces", "f4", ("frame", "atom", "spatial")) + setattr(forces, "units", "kilocalorie/mole/angstrom") + if self.scale_factors["forces"]: + forces.scale_factor = self.scale_factors["forces"] # Important for netCDF4! Disable maskandscale for created variables! # Won't work if called before variable creation! @@ -1090,7 +1134,8 @@ def _write_next_frame(self, ag): if ts.n_atoms != self.n_atoms: raise IOError( - "NCDFWriter: Timestep does not have the correct number of atoms") + "NCDFWriter: Timestep does not have the correct number of atoms" + ) if self.trjfile is None: # first time step: analyze data and open trajectory accordingly @@ -1147,35 +1192,35 @@ def _write_next_timestep(self, ts): # write step # coordinates - self._set_frame_var_and_scale('coordinates', pos) + self._set_frame_var_and_scale("coordinates", pos) # time - self._set_frame_var_and_scale('time', time) + self._set_frame_var_and_scale("time", time) # unitcell if self.periodic: # cell lengths - self._set_frame_var_and_scale('cell_lengths', unitcell[:3]) + self._set_frame_var_and_scale("cell_lengths", unitcell[:3]) - self._set_frame_var_and_scale('cell_angles', unitcell[3:]) + self._set_frame_var_and_scale("cell_angles", unitcell[3:]) # velocities if self.has_velocities: velocities = ts._velocities if self.convert_units: velocities = self.convert_velocities_to_native( - velocities, inplace=False) + velocities, inplace=False + ) - self._set_frame_var_and_scale('velocities', velocities) + self._set_frame_var_and_scale("velocities", velocities) # forces if self.has_forces: forces = ts._forces if self.convert_units: - forces = self.convert_forces_to_native( - forces, inplace=False) + forces = self.convert_forces_to_native(forces, inplace=False) - self._set_frame_var_and_scale('forces', forces) + self._set_frame_var_and_scale("forces", forces) self.trjfile.sync() self.curr_frame += 1 @@ -1247,10 +1292,9 @@ class NCDFPicklable(scipy.io.netcdf_file): .. _`scipy netcdf API documentation`: https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.netcdf_file.html """ + def __getstate__(self): - return (self.filename, self.use_mmap, self.version_byte, - self.maskandscale) + return (self.filename, self.use_mmap, self.version_byte, self.maskandscale) def __setstate__(self, args): - self.__init__(args[0], mmap=args[1], version=args[2], - maskandscale=args[3]) + self.__init__(args[0], mmap=args[1], version=args[2], maskandscale=args[3]) diff --git a/package/MDAnalysis/coordinates/TRR.py b/package/MDAnalysis/coordinates/TRR.py index 91f2b03b6a7..83d49be336a 100644 --- a/package/MDAnalysis/coordinates/TRR.py +++ b/package/MDAnalysis/coordinates/TRR.py @@ -31,6 +31,7 @@ MDAnalysis.coordinates.XTC: Read and write GROMACS XTC trajectory files. MDAnalysis.coordinates.XDR: BaseReader/Writer for XDR based formats """ + import errno from . import base from .XDR import XDRBaseReader, XDRBaseWriter @@ -132,9 +133,7 @@ def _write_next_frame(self, ag): if "lambda" in ts.data: lmbda = ts.data["lambda"] - self._xdr.write( - xyz, velo, forces, box, step, time, lmbda, self.n_atoms - ) + self._xdr.write(xyz, velo, forces, box, step, time, lmbda, self.n_atoms) class TRRReader(XDRBaseReader): @@ -182,9 +181,7 @@ def _read_next_timestep(self, ts=None): ts.has_positions = True ts.has_velocities = True ts.has_forces = True - frame = self._xdr.read_direct_xvf( - ts.positions, ts.velocities, ts.forces - ) + frame = self._xdr.read_direct_xvf(ts.positions, ts.velocities, ts.forces) self._frame += 1 self._frame_to_ts(frame, ts) return ts diff --git a/package/MDAnalysis/coordinates/TRZ.py b/package/MDAnalysis/coordinates/TRZ.py index 82ada24e6a3..3c51df954cc 100644 --- a/package/MDAnalysis/coordinates/TRZ.py +++ b/package/MDAnalysis/coordinates/TRZ.py @@ -45,6 +45,7 @@ :members: """ + import warnings import numpy as np import os @@ -93,7 +94,7 @@ class TRZReader(base.ReaderBase): format = "TRZ" - units = {'time': 'ps', 'length': 'nm', 'velocity': 'nm/ps'} + units = {"time": "ps", "length": "nm", "velocity": "nm/ps"} @store_init_arguments def __init__(self, trzfilename, n_atoms=None, **kwargs): @@ -114,84 +115,93 @@ def __init__(self, trzfilename, n_atoms=None, **kwargs): If `n_atoms` or the number of atoms in the topology file do not match the number of atoms in the trajectory. """ - wmsg = ("The TRZ reader is deprecated and will be removed in " - "MDAnalysis version 3.0.0") + wmsg = ( + "The TRZ reader is deprecated and will be removed in " + "MDAnalysis version 3.0.0" + ) warnings.warn(wmsg, DeprecationWarning) - super(TRZReader, self).__init__(trzfilename, **kwargs) + super(TRZReader, self).__init__(trzfilename, **kwargs) if n_atoms is None: - raise ValueError('TRZReader requires the n_atoms keyword') + raise ValueError("TRZReader requires the n_atoms keyword") - self.trzfile = util.anyopen(self.filename, 'rb') + self.trzfile = util.anyopen(self.filename, "rb") self._cache = dict() self._n_atoms = n_atoms self._read_trz_header() - self.ts = Timestep(self.n_atoms, - velocities=True, - forces=self.has_force, - reader=self, - **self._ts_kwargs) + self.ts = Timestep( + self.n_atoms, + velocities=True, + forces=self.has_force, + reader=self, + **self._ts_kwargs + ) # structured dtype of a single trajectory frame - readarg = str(n_atoms) + ' angstroms) @@ -245,7 +256,7 @@ def n_atoms(self): return self._n_atoms @property - @cached('n_frames') + @cached("n_frames") def n_frames(self): """Total number of frames in a trajectory""" try: @@ -262,9 +273,13 @@ def _read_trz_n_frames(self, trzfile): fsize = os.fstat(trzfile.fileno()).st_size # size of file in bytes if not (fsize - self._headerdtype.itemsize) % self._dtype.itemsize == 0: - raise IOError("Trajectory has incomplete frames") # check that division is sane + raise IOError( + "Trajectory has incomplete frames" + ) # check that division is sane - nframes = int((fsize - self._headerdtype.itemsize) / self._dtype.itemsize) # returns long int otherwise + nframes = int( + (fsize - self._headerdtype.itemsize) / self._dtype.itemsize + ) # returns long int otherwise return nframes @@ -294,20 +309,20 @@ def _get_dt(self): self._read_frame(curr_frame) @property - @cached('delta') + @cached("delta") def delta(self): """MD integration timestep""" return self.dt / self.skip_timestep @property - @cached('skip_timestep') + @cached("skip_timestep") def skip_timestep(self): """Timesteps between trajectory frames""" curr_frame = self.ts.frame try: - t0 = self.ts.data['frame'] + t0 = self.ts.data["frame"] self.next() - t1 = self.ts.data['frame'] + t1 = self.ts.data["frame"] skip_timestep = t1 - t0 except StopIteration: return 0 @@ -365,13 +380,13 @@ def _reopen(self): def open_trajectory(self): """Open the trajectory file""" if self.trzfile is not None: - raise IOError(errno.EALREADY, 'TRZ file already opened', self.filename) + raise IOError(errno.EALREADY, "TRZ file already opened", self.filename) if not os.path.exists(self.filename): - raise IOError(errno.ENOENT, 'TRZ file not found', self.filename) + raise IOError(errno.ENOENT, "TRZ file not found", self.filename) - self.trzfile = util.anyopen(self.filename, 'rb') + self.trzfile = util.anyopen(self.filename, "rb") - #Reset ts + # Reset ts ts = self.ts ts.frame = -1 @@ -403,12 +418,12 @@ class TRZWriter(base.WriterBase): and will be removed in version 3.0.0. """ - format = 'TRZ' + format = "TRZ" multiframe = True - units = {'time': 'ps', 'length': 'nm', 'velocity': 'nm/ps'} + units = {"time": "ps", "length": "nm", "velocity": "nm/ps"} - def __init__(self, filename, n_atoms, title='TRZ', convert_units=True): + def __init__(self, filename, n_atoms, title="TRZ", convert_units=True): """Create a TRZWriter Parameters @@ -423,8 +438,10 @@ def __init__(self, filename, n_atoms, title='TRZ', convert_units=True): convert_units : bool (optional) units are converted to the MDAnalysis base format; [``True``] """ - wmsg = ("The TRZ writer is deprecated and will be removed in " - "MDAnalysis version 3.0.0") + wmsg = ( + "The TRZ writer is deprecated and will be removed in " + "MDAnalysis version 3.0.0" + ) warnings.warn(wmsg, DeprecationWarning) self.filename = filename @@ -439,61 +456,71 @@ def __init__(self, filename, n_atoms, title='TRZ', convert_units=True): self.convert_units = convert_units - self.trzfile = util.anyopen(self.filename, 'wb') + self.trzfile = util.anyopen(self.filename, "wb") self._writeheader(title) - floatsize = str(n_atoms) + ' int: return self.n_frames @@ -697,8 +707,9 @@ def parse_n_atoms(cls, filename, **kwargs): NotImplementedError when the number of atoms can't be deduced """ - raise NotImplementedError("{} cannot deduce the number of atoms" - "".format(cls.__name__)) + raise NotImplementedError( + "{} cannot deduce the number of atoms" "".format(cls.__name__) + ) def next(self) -> Timestep: """Forward one step to next frame.""" @@ -768,7 +779,8 @@ def Writer(self, filename, **kwargs): raise NotImplementedError( "Sorry, there is no Writer for this format in MDAnalysis. " "Please file an enhancement request at " - "https://github.com/MDAnalysis/mdanalysis/issues") + "https://github.com/MDAnalysis/mdanalysis/issues" + ) def OtherWriter(self, filename, **kwargs): """Returns a writer appropriate for *filename*. @@ -782,10 +794,10 @@ def OtherWriter(self, filename, **kwargs): :meth:`Reader.Writer` and :func:`MDAnalysis.Writer` """ - kwargs['n_atoms'] = self.n_atoms # essential - kwargs.setdefault('start', self.frame) + kwargs["n_atoms"] = self.n_atoms # essential + kwargs.setdefault("start", self.frame) try: - kwargs.setdefault('dt', self.dt) + kwargs.setdefault("dt", self.dt) except KeyError: pass return core.writer(filename, **kwargs) @@ -800,7 +812,7 @@ def _read_next_timestep(self, ts=None): ... def __iter__(self): - """ Iterate over trajectory frames. """ + """Iterate over trajectory frames.""" self._reopen() return self @@ -810,14 +822,16 @@ def _reopen(self): Calling next after this should return the first frame """ - pass # pylint: disable=unnecessary-pass + pass # pylint: disable=unnecessary-pass def _apply_limits(self, frame): if frame < 0: frame += len(self) if frame < 0 or frame >= len(self): - raise IndexError("Index {} exceeds length of trajectory ({})." - "".format(frame, len(self))) + raise IndexError( + "Index {} exceeds length of trajectory ({})." + "".format(frame, len(self)) + ) return frame def __getitem__(self, frame): @@ -845,19 +859,24 @@ def __getitem__(self, frame): return FrameIteratorIndices(self, frame) elif isinstance(frame, slice): start, stop, step = self.check_slice_indices( - frame.start, frame.stop, frame.step) + frame.start, frame.stop, frame.step + ) if start == 0 and stop == len(self) and step == 1: return FrameIteratorAll(self) else: return FrameIteratorSliced(self, frame) else: - raise TypeError("Trajectories must be an indexed using an integer," - " slice or list of indices") + raise TypeError( + "Trajectories must be an indexed using an integer," + " slice or list of indices" + ) def _read_frame(self, frame): """Move to *frame* and fill timestep with data.""" - raise TypeError("{0} does not support direct frame indexing." - "".format(self.__class__.__name__)) + raise TypeError( + "{0} does not support direct frame indexing." + "".format(self.__class__.__name__) + ) # Example implementation in the DCDReader: # self._jump_to_frame(frame) # ts = self.ts @@ -943,18 +962,18 @@ def check_slice_indices(self, start, stop, step): """ - slice_dict = {'start': start, 'stop': stop, 'step': step} + slice_dict = {"start": start, "stop": stop, "step": step} for varname, var in slice_dict.items(): if isinstance(var, numbers.Integral): slice_dict[varname] = int(var) - elif (var is None): + elif var is None: pass else: raise TypeError("{0} is not an integer".format(varname)) - start = slice_dict['start'] - stop = slice_dict['stop'] - step = slice_dict['step'] + start = slice_dict["start"] + stop = slice_dict["stop"] + step = slice_dict["step"] if step == 0: raise ValueError("Step size is zero") @@ -983,19 +1002,22 @@ def check_slice_indices(self, start, stop, step): return start, stop, step def __repr__(self): - return ("<{cls} {fname} with {nframes} frames of {natoms} atoms>" - "".format( + return "<{cls} {fname} with {nframes} frames of {natoms} atoms>" "".format( cls=self.__class__.__name__, fname=self.filename, nframes=self.n_frames, - natoms=self.n_atoms - )) - - def timeseries(self, asel: Optional['AtomGroup']=None, - atomgroup: Optional['Atomgroup']=None, - start: Optional[int]=None, stop: Optional[int]=None, - step: Optional[int]=None, - order: Optional[str]='fac') -> np.ndarray: + natoms=self.n_atoms, + ) + + def timeseries( + self, + asel: Optional["AtomGroup"] = None, + atomgroup: Optional["Atomgroup"] = None, + start: Optional[int] = None, + stop: Optional[int] = None, + step: Optional[int] = None, + order: Optional[str] = "fac", + ) -> np.ndarray: """Return a subset of coordinate data for an AtomGroup Parameters @@ -1039,7 +1061,8 @@ def timeseries(self, asel: Optional['AtomGroup']=None, warnings.warn( "asel argument to timeseries will be renamed to" "'atomgroup' in 3.0, see #3911", - category=DeprecationWarning) + category=DeprecationWarning, + ) if atomgroup: raise ValueError("Cannot provide both asel and atomgroup kwargs") atomgroup = asel @@ -1048,8 +1071,7 @@ def timeseries(self, asel: Optional['AtomGroup']=None, if atomgroup is not None: if len(atomgroup) == 0: - raise ValueError( - "Timeseries requires at least one atom to analyze") + raise ValueError("Timeseries requires at least one atom to analyze") atom_numbers = atomgroup.indices natoms = len(atom_numbers) else: @@ -1062,28 +1084,34 @@ def timeseries(self, asel: Optional['AtomGroup']=None, coordinates[i, :] = ts.positions[atom_numbers] # switch axes around - default_order = 'fac' + default_order = "fac" if order != default_order: try: newidx = [default_order.index(i) for i in order] except ValueError: - raise ValueError(f"Unrecognized order key in {order}, " - "must be permutation of 'fac'") + raise ValueError( + f"Unrecognized order key in {order}, " + "must be permutation of 'fac'" + ) try: coordinates = np.moveaxis(coordinates, newidx, [0, 1, 2]) except ValueError: - errmsg = ("Repeated or missing keys passed to argument " - f"`order`: {order}, each key must be used once") + errmsg = ( + "Repeated or missing keys passed to argument " + f"`order`: {order}, each key must be used once" + ) raise ValueError(errmsg) return coordinates -# TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 - def add_auxiliary(self, - aux_spec: Union[str, Dict[str, str]] = None, - auxdata: Union[str, AuxReader] = None, - format: str = None, - **kwargs) -> None: + # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 + def add_auxiliary( + self, + aux_spec: Union[str, Dict[str, str]] = None, + auxdata: Union[str, AuxReader] = None, + format: str = None, + **kwargs, + ) -> None: """Add auxiliary data to be read alongside trajectory. Auxiliary data may be any data timeseries from the trajectory @@ -1146,8 +1174,9 @@ def add_auxiliary(self, the :ref:`Auxiliary API`. """ if auxdata is None: - raise ValueError("No input `auxdata` specified, but it needs " - "to be provided.") + raise ValueError( + "No input `auxdata` specified, but it needs " "to be provided." + ) if type(auxdata) not in list(_AUXREADERS.values()): # i.e. if auxdata is a file, not an instance of an AuxReader reader_type = get_auxreader_for(auxdata) @@ -1171,11 +1200,11 @@ def remove_auxiliary(self, auxname): @property def aux_list(self): - """ Lists the names of added auxiliary data. """ + """Lists the names of added auxiliary data.""" return self._auxs.keys() def _check_for_aux(self, auxname): - """ Check for the existance of an auxiliary *auxname*. If present, + """Check for the existance of an auxiliary *auxname*. If present, return the AuxReader; if not, raise ValueError """ if auxname in self.aux_list: @@ -1184,7 +1213,7 @@ def _check_for_aux(self, auxname): raise ValueError("No auxiliary named {name}".format(name=auxname)) def next_as_aux(self, auxname): - """ Move to the next timestep for which there is at least one step from + """Move to the next timestep for which there is at least one step from the auxiliary *auxname* within the cutoff specified in *auxname*. This allows progression through the trajectory without encountering @@ -1216,7 +1245,7 @@ def next_as_aux(self, auxname): raise StopIteration # some readers set self._frame to -1, rather than self.frame, on # _reopen; catch here or doesn't read first frame - while self.frame != next_frame or getattr(self, '_frame', 0) == -1: + while self.frame != next_frame or getattr(self, "_frame", 0) == -1: # iterate trajectory until frame is reached ts = self.next() return ts @@ -1239,9 +1268,8 @@ def iter_as_aux(self, auxname): except StopIteration: return - def iter_auxiliary(self, auxname, start=None, stop=None, step=None, - selected=None): - """ Iterate through the auxiliary *auxname* independently of the trajectory. + def iter_auxiliary(self, auxname, start=None, stop=None, step=None, selected=None): + """Iterate through the auxiliary *auxname* independently of the trajectory. Will iterate over the specified steps of the auxiliary (defaults to all steps). Allows to access all values in an auxiliary, including those out @@ -1294,7 +1322,7 @@ def get_aux_attribute(self, auxname, attrname): return getattr(aux, attrname) def set_aux_attribute(self, auxname, attrname, new): - """ Set the value of *attrname* in the auxiliary *auxname*. + """Set the value of *attrname* in the auxiliary *auxname*. Parameters ---------- @@ -1311,13 +1339,13 @@ def set_aux_attribute(self, auxname, attrname, new): :meth:`rename_aux` - to change the *auxname* attribute """ aux = self._check_for_aux(auxname) - if attrname == 'auxname': + if attrname == "auxname": self.rename_aux(auxname, new) else: setattr(aux, attrname, new) def rename_aux(self, auxname, new): - """ Change the name of the auxiliary *auxname* to *new*. + """Change the name of the auxiliary *auxname* to *new*. Provided there is not already an auxiliary named *new*, the auxiliary name will be changed in ts.aux namespace, the trajectory's @@ -1337,8 +1365,9 @@ def rename_aux(self, auxname, new): """ aux = self._check_for_aux(auxname) if new in self.aux_list: - raise ValueError("Auxiliary data with name {name} already " - "exists".format(name=new)) + raise ValueError( + "Auxiliary data with name {name} already " "exists".format(name=new) + ) aux.auxname = new self._auxs[new] = self._auxs.pop(auxname) setattr(self.ts.aux, new, self.ts.aux[auxname]) @@ -1375,7 +1404,7 @@ def get_aux_descriptions(self, auxnames=None): @property def transformations(self): - """ Returns the list of transformations""" + """Returns the list of transformations""" return self._transformations @transformations.setter @@ -1440,18 +1469,19 @@ def add_transformations(self, *transformations): try: self.transformations = transformations except ValueError: - errmsg = ("Can't add transformations again. Please create a new " - "Universe object") + errmsg = ( + "Can't add transformations again. Please create a new " + "Universe object" + ) raise ValueError(errmsg) from None else: self.ts = self._apply_transformations(self.ts) - # call reader here to apply the newly added transformation on the # current loaded frame? def _apply_transformations(self, ts): - """Applies all the transformations given by the user """ + """Applies all the transformations given by the user""" for transform in self.transformations: ts = transform(ts) @@ -1487,6 +1517,7 @@ class ReaderBase(ProtoReader): Removed deprecated flags functionality, use convert_units kwarg instead """ + @store_init_arguments def __init__(self, filename, convert_units=True, **kwargs): super(ReaderBase, self).__init__() @@ -1498,7 +1529,7 @@ def __init__(self, filename, convert_units=True, **kwargs): self.convert_units = convert_units ts_kwargs = {} - for att in ('dt', 'time_offset'): + for att in ("dt", "time_offset"): try: val = kwargs[att] except KeyError: @@ -1551,14 +1582,14 @@ def __init__(cls, name, bases, classdict): try: # grab the string which describes this format # could be either 'PDB' or ['PDB', 'ENT'] for multiple formats - fmt = asiterable(classdict['format']) + fmt = asiterable(classdict["format"]) except KeyError: # not required however pass else: # does the Writer support single and multiframe writing? - single = classdict.get('singleframe', True) - multi = classdict.get('multiframe', False) + single = classdict.get("singleframe", True) + multi = classdict.get("multiframe", False) if single: for f in fmt: @@ -1625,7 +1656,9 @@ def __del__(self): def __repr__(self): try: - return "< {0!s} {1!r} for {2:d} atoms >".format(self.__class__.__name__, self.filename, self.n_atoms) + return "< {0!s} {1!r} for {2:d} atoms >".format( + self.__class__.__name__, self.filename, self.n_atoms + ) except (TypeError, AttributeError): # no trajectory loaded yet or a Writer that does not need e.g. # self.n_atoms @@ -1672,6 +1705,7 @@ class SingleFrameReaderBase(ProtoReader): Fixed a typo in the attribute assignment (`self.atom` → `self.atoms`), which may affect subclasses relying on this value. """ + _err = "{0} only contains a single frame" @store_init_arguments @@ -1685,7 +1719,7 @@ def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): self.n_atoms = n_atoms ts_kwargs = {} - for att in ('dt', 'time_offset'): + for att in ("dt", "time_offset"): try: val = kwargs[att] except KeyError: @@ -1760,7 +1794,7 @@ def close(self): pass def add_transformations(self, *transformations): - """ Add all transformations to be applied to the trajectory. + """Add all transformations to be applied to the trajectory. This function take as list of transformations as an argument. These transformations are functions that will be called by the Reader and given @@ -1786,17 +1820,17 @@ def add_transformations(self, *transformations): -------- :mod:`MDAnalysis.transformations` """ - #Overrides :meth:`~MDAnalysis.coordinates.base.ProtoReader.add_transformations` - #to avoid unintended behaviour where the coordinates of each frame are transformed - #multiple times when iterating over the trajectory. - #In this method, the trajectory is modified all at once and once only. + # Overrides :meth:`~MDAnalysis.coordinates.base.ProtoReader.add_transformations` + # to avoid unintended behaviour where the coordinates of each frame are transformed + # multiple times when iterating over the trajectory. + # In this method, the trajectory is modified all at once and once only. super(SingleFrameReaderBase, self).add_transformations(*transformations) for transform in self.transformations: self.ts = transform(self.ts) def _apply_transformations(self, ts): - """ Applies the transformations to the timestep.""" + """Applies the transformations to the timestep.""" # Overrides :meth:`~MDAnalysis.coordinates.base.ProtoReader.add_transformations` # to avoid applying the same transformations multiple times on each frame @@ -1804,16 +1838,17 @@ def _apply_transformations(self, ts): def range_length(start, stop, step): - if (step > 0 and start < stop): + if step > 0 and start < stop: # We go from a lesser number to a larger one. return int(1 + (stop - 1 - start) // step) - elif (step < 0 and start > stop): + elif step < 0 and start > stop: # We count backward from a larger number to a lesser one. return int(1 + (start - 1 - stop) // (-step)) else: # The range is empty. return 0 + # Verbatim copy of code from converters/base.py # Needed to avoid circular imports before removal in # MDAnalysis 3.0.0 @@ -1823,7 +1858,7 @@ class _Convertermeta(type): def __init__(cls, name, bases, classdict): type.__init__(type, name, bases, classdict) try: - fmt = asiterable(classdict['lib']) + fmt = asiterable(classdict["lib"]) except KeyError: pass else: @@ -1846,10 +1881,12 @@ class ConverterBase(IOBase, metaclass=_Convertermeta): """ def __init_subclass__(cls): - wmsg = ("ConverterBase moved from coordinates.base." - "ConverterBase to converters.base.ConverterBase " - "and will be removed from coordinates.base " - "in MDAnalysis release 3.0.0") + wmsg = ( + "ConverterBase moved from coordinates.base." + "ConverterBase to converters.base.ConverterBase " + "and will be removed from coordinates.base " + "in MDAnalysis release 3.0.0" + ) warnings.warn(wmsg, DeprecationWarning, stacklevel=2) def __repr__(self): @@ -1858,6 +1895,7 @@ def __repr__(self): def convert(self, obj): raise NotImplementedError + class StreamReaderBase(ReaderBase): """Base class for readers that read a continuous stream of data. @@ -1896,7 +1934,7 @@ class StreamReaderBase(ReaderBase): ReaderBase : Base class for standard trajectory readers - .. versionadded:: 2.10.0 + .. versionadded:: 2.10.0 """ def __init__(self, filename, convert_units=True, **kwargs): @@ -1928,26 +1966,22 @@ def _read_next_timestep(self): @property def n_frames(self): """Changes as stream is processed unlike other readers""" - raise RuntimeError( - "{}: n_frames is unknown".format(self.__class__.__name__) - ) + raise RuntimeError("{}: n_frames is unknown".format(self.__class__.__name__)) def __len__(self): - raise RuntimeError( - "{} has unknown length".format(self.__class__.__name__) - ) + raise RuntimeError("{} has unknown length".format(self.__class__.__name__)) def next(self): """Advance to the next timestep in the streaming trajectory. - + Streaming readers process frames sequentially and cannot rewind once iteration completes. Use ``for ts in trajectory`` for iteration. - + Returns ------- Timestep The next timestep in the stream - + Raises ------ StopIteration @@ -1968,7 +2002,7 @@ def next(self): def rewind(self): """Rewinding is not supported for streaming trajectories. - + Streaming readers process data continuously from streams and cannot restart or go backward in the stream once consumed. @@ -1978,19 +2012,17 @@ def rewind(self): Always raised, as rewinding is not supported for streaming trajectories """ raise RuntimeError( - "{}: Stream-based readers can't be rewound".format( - self.__class__.__name__ - ) + "{}: Stream-based readers can't be rewound".format(self.__class__.__name__) ) # Incompatible methods def copy(self): """Reader copying is not supported for streaming trajectories. - + Streaming readers maintain internal state and connection resources that cannot be duplicated. Each stream connection is unique and cannot be copied. - + Raises ------ RuntimeError @@ -2002,11 +2034,11 @@ def copy(self): def _reopen(self): """Prepare stream for iteration - can only be called once. - + Streaming readers cannot be reopened once iteration begins. This method is called internally during iteration setup and will raise an error if called multiple times. - + Raises ------ RuntimeError @@ -2021,24 +2053,26 @@ def _reopen(self): def timeseries(self, **kwargs): """Timeseries extraction is not supported for streaming trajectories. - + Streaming readers cannot randomly access frames or store bulk coordinate data in memory, which ``timeseries()`` requires. Use sequential frame iteration instead. - + Parameters ---------- **kwargs Any keyword arguments (ignored, as method is not supported) - + Raises ------ RuntimeError - Always raised, as timeseries extraction is not supported for + Always raised, as timeseries extraction is not supported for streaming trajectories """ raise RuntimeError( - "{}: cannot access timeseries for streamed trajectories".format(self.__class__.__name__) + "{}: cannot access timeseries for streamed trajectories".format( + self.__class__.__name__ + ) ) def __getitem__(self, frame): @@ -2073,31 +2107,27 @@ def __getitem__(self, frame): StreamFrameIteratorSliced """ if isinstance(frame, slice): - _, _, step = self.check_slice_indices( - frame.start, frame.stop, frame.step - ) + _, _, step = self.check_slice_indices(frame.start, frame.stop, frame.step) if step is None: return FrameIteratorAll(self) else: return StreamFrameIteratorSliced(self, step) else: - raise TypeError( - "Streamed trajectories must be an indexed using a slice" - ) + raise TypeError("Streamed trajectories must be an indexed using a slice") def check_slice_indices(self, start, stop, step): """Check and validate slice indices for streaming trajectories. - - Streaming trajectories have fundamental constraints that differ from + + Streaming trajectories have fundamental constraints that differ from traditional trajectory files: - + * **No start/stop indices**: Since streams process data continuously without knowing the total length, ``start`` and ``stop`` must be ``None`` * **Step-only slicing**: Only the ``step`` parameter is meaningful, controlling how many frames to skip during iteration * **Forward-only**: ``step`` must be positive (> 0) as streams cannot be processed backward in time - + Parameters ---------- start : int or None @@ -2105,35 +2135,35 @@ def check_slice_indices(self, start, stop, step): stop : int or None Ending frame index. Must be ``None`` for streaming readers. step : int or None - Step size for iteration. Must be positive integer or ``None`` + Step size for iteration. Must be positive integer or ``None`` (equivalent to 1). - + Returns ------- tuple (start, stop, step) with validated values - + Raises ------ ValueError - If ``start`` or ``stop`` are not ``None``, or if ``step`` is + If ``start`` or ``stop`` are not ``None``, or if ``step`` is not a positive integer. - + Examples -------- Valid streaming slices:: - + traj[:] # All frames (step=None, equivalent to step=1) - traj[::2] # Every 2nd frame + traj[::2] # Every 2nd frame traj[::10] # Every 10th frame - + Invalid streaming slices:: - + traj[5:] # Cannot specify start index - traj[:100] # Cannot specify stop index + traj[:100] # Cannot specify stop index traj[5:100:2] # Cannot specify start or stop indices traj[::-1] # Cannot go backwards (negative step) - + See Also -------- __getitem__ @@ -2164,16 +2194,14 @@ def check_slice_indices(self, start, stop, step): ) else: raise ValueError( - "{}: 'step' must be an integer".format( - self.__class__.__name__ - ) + "{}: 'step' must be an integer".format(self.__class__.__name__) ) return start, stop, step def Writer(self, filename, **kwargs): """Writer creation is not supported for streaming trajectories. - + Writer creation requires trajectory metadata that streaming readers cannot provide due to their sequential processing nature. @@ -2183,7 +2211,7 @@ def Writer(self, filename, **kwargs): Output filename (ignored, as method is not supported) **kwargs Additional keyword arguments (ignored, as method is not supported) - + Raises ------ RuntimeError @@ -2197,18 +2225,18 @@ def Writer(self, filename, **kwargs): def OtherWriter(self, filename, **kwargs): """Writer creation is not supported for streaming trajectories. - + OtherWriter initialization requires frame-based parameters and trajectory indexing information. Streaming readers process data sequentially without meaningful frame indexing, making writer setup impossible. - + Parameters ---------- filename : str Output filename (ignored, as method is not supported) **kwargs Additional keyword arguments (ignored, as method is not supported) - + Raises ------ RuntimeError @@ -2231,43 +2259,40 @@ def __setstate__(self, state: object): ) def __repr__(self): - return ( - "<{cls} {fname} with continuous stream of {natoms} atoms>" - "".format( - cls=self.__class__.__name__, - fname=self.filename, - natoms=self.n_atoms, - ) + return "<{cls} {fname} with continuous stream of {natoms} atoms>" "".format( + cls=self.__class__.__name__, + fname=self.filename, + natoms=self.n_atoms, ) class StreamFrameIteratorSliced(FrameIteratorBase): """Iterator for sliced frames in a streamed trajectory. - - Created when slicing a streaming trajectory with a step parameter - (e.g., ``trajectory[::n]``). Reads every nth frame from the continuous + + Created when slicing a streaming trajectory with a step parameter + (e.g., ``trajectory[::n]``). Reads every nth frame from the continuous stream, discarding intermediate frames for performance. - + This differs from iterating over all frames (``trajectory[:]``) which uses - :class:`FrameIteratorAll` and processes every frame sequentially without + :class:`FrameIteratorAll` and processes every frame sequentially without skipping. - + Streaming constraints apply to the sliced iterator: - + - Frames cannot be accessed randomly (no indexing support) - - The total number of frames is unknown until streaming ends + - The total number of frames is unknown until streaming ends - Rewinding or restarting iteration is not possible - Only forward iteration with a fixed step size is supported - + Parameters ---------- trajectory : StreamReaderBase - The streaming trajectory reader to iterate over. Must be a + The streaming trajectory reader to iterate over. Must be a stream-based reader that supports continuous data reading. step : int - Step size for iteration. Must be a positive integer. A step + Step size for iteration. Must be a positive integer. A step of 1 reads every frame, step of 2 reads every other frame, etc. - + See Also -------- StreamReaderBase @@ -2300,9 +2325,7 @@ def __next__(self): return self.trajectory.next() def __len__(self): - raise RuntimeError( - "{} has unknown length".format(self.__class__.__name__) - ) + raise RuntimeError("{} has unknown length".format(self.__class__.__name__)) def __getitem__(self, frame): raise RuntimeError("Sliced iterator does not support indexing") @@ -2310,15 +2333,15 @@ def __getitem__(self, frame): @property def step(self): """The step size for sliced frame iteration. - - Returns the step interval used when iterating through frames in a - streaming trajectory. For example, a step of 2 means every second + + Returns the step interval used when iterating through frames in a + streaming trajectory. For example, a step of 2 means every second frame is processed, while a step of 1 processes every frame. - + Returns ------- int Step size for iteration. Always a positive integer greater than 0. - + """ - return self._step \ No newline at end of file + return self._step diff --git a/package/MDAnalysis/coordinates/chain.py b/package/MDAnalysis/coordinates/chain.py index 930a2199fc3..f4be163f529 100644 --- a/package/MDAnalysis/coordinates/chain.py +++ b/package/MDAnalysis/coordinates/chain.py @@ -40,6 +40,7 @@ .. automethod:: _read_frame """ + import warnings import os.path @@ -336,9 +337,7 @@ def __init__( # calculate new start_frames to have a time continuous trajectory. if continuous: - check_allowed_filetypes( - self.readers, ["XTC", "TRR", "LAMMPSDUMP", "TRC"] - ) + check_allowed_filetypes(self.readers, ["XTC", "TRR", "LAMMPSDUMP", "TRC"]) if np.any(np.array(n_frames) == 1): raise RuntimeError( "ChainReader: Need at least two frames in " @@ -388,9 +387,7 @@ def __init__( start_time = r2.time r1[-1] if r1.time < start_time: - warnings.warn( - "Missing frame in continuous chain", UserWarning - ) + warnings.warn("Missing frame in continuous chain", UserWarning) # check for interleaving r1[1] @@ -466,9 +463,7 @@ def _get_local_frame(self, k) -> Tuple[int, int]: # trajectory index i i = bisect.bisect_right(self._start_frames, k) - 1 if i < 0: - raise IndexError( - "Cannot find trajectory for virtual frame {0:d}".format(k) - ) + raise IndexError("Cannot find trajectory for virtual frame {0:d}".format(k)) # local frame index f in trajectory i (frame indices are 0-based) f = k - self._start_frames[i] return i, f @@ -547,16 +542,11 @@ def time(self): # Now each reader is either already instantiated with a common dt, or # left at its default dt. In any case, we sum over individual times. trajindex, subframe = self._get_local_frame(self.frame) - return ( - self.total_times[:trajindex].sum() + subframe * self.dts[trajindex] - ) + return self.total_times[:trajindex].sum() + subframe * self.dts[trajindex] def _apply(self, method, **kwargs): """Execute `method` with `kwargs` for all readers.""" - return [ - reader.__getattribute__(method)(**kwargs) - for reader in self.readers - ] + return [reader.__getattribute__(method)(**kwargs) for reader in self.readers] def _get(self, attr): """Get value of `attr` for all readers.""" diff --git a/package/MDAnalysis/coordinates/chemfiles.py b/package/MDAnalysis/coordinates/chemfiles.py index bc1b0210cc6..00ea28f0be5 100644 --- a/package/MDAnalysis/coordinates/chemfiles.py +++ b/package/MDAnalysis/coordinates/chemfiles.py @@ -76,6 +76,7 @@ .. autofunction:: check_chemfiles_version """ + import numpy as np import warnings from packaging.version import Version @@ -156,8 +157,7 @@ def __init__(self, filename, chemfiles_format="", **kwargs): """ if not check_chemfiles_version(): raise RuntimeError( - "Please install Chemfiles > {}" - "".format(MIN_CHEMFILES_VERSION) + "Please install Chemfiles > {}" "".format(MIN_CHEMFILES_VERSION) ) super(ChemfilesReader, self).__init__(filename, **kwargs) self._format = chemfiles_format @@ -304,16 +304,13 @@ def __init__( """ if not check_chemfiles_version(): raise RuntimeError( - "Please install Chemfiles > {}" - "".format(MIN_CHEMFILES_VERSION) + "Please install Chemfiles > {}" "".format(MIN_CHEMFILES_VERSION) ) self.filename = filename self.n_atoms = n_atoms if mode != "a" and mode != "w": raise IOError("Expected 'a' or 'w' as mode in ChemfilesWriter") - self._file = chemfiles.Trajectory( - self.filename, mode, chemfiles_format - ) + self._file = chemfiles.Trajectory(self.filename, mode, chemfiles_format) self._closed = False if topology is not None: if isinstance(topology, str): @@ -428,9 +425,7 @@ def _topology_to_chemfiles(self, obj, n_atoms): if hasattr(atom, "resid"): resname = getattr(atom, "resname", "") if atom.resid not in residues.keys(): - residues[atom.resid] = chemfiles.Residue( - resname, atom.resid - ) + residues[atom.resid] = chemfiles.Residue(resname, atom.resid) residue = residues[atom.resid] atom_idx = len(topology.atoms) diff --git a/package/MDAnalysis/coordinates/memory.py b/package/MDAnalysis/coordinates/memory.py index 07c31fa2258..456591df0b3 100644 --- a/package/MDAnalysis/coordinates/memory.py +++ b/package/MDAnalysis/coordinates/memory.py @@ -181,6 +181,7 @@ :inherited-members: """ + import logging import errno import numpy as np @@ -331,19 +332,14 @@ def __init__( raise TypeError(errmsg) from None self.set_array(coordinate_array, order) - self.n_frames = self.coordinate_array.shape[ - self.stored_order.find("f") - ] + self.n_frames = self.coordinate_array.shape[self.stored_order.find("f")] self.n_atoms = self.coordinate_array.shape[self.stored_order.find("a")] if velocities is not None: try: velocities = np.asarray(velocities, dtype=np.float32) except ValueError: - errmsg = ( - f"'velocities' must be array-like got " - f"{type(velocities)}" - ) + errmsg = f"'velocities' must be array-like got " f"{type(velocities)}" raise TypeError(errmsg) from None # if single frame, make into array of 1 frame if velocities.ndim == 2: @@ -388,17 +384,12 @@ def __init__( self.ts.dt = dt if dimensions is None: - self.dimensions_array = np.zeros( - (self.n_frames, 6), dtype=np.float32 - ) + self.dimensions_array = np.zeros((self.n_frames, 6), dtype=np.float32) else: try: dimensions = np.asarray(dimensions, dtype=np.float32) except ValueError: - errmsg = ( - f"'dimensions' must be array-like got " - f"{type(dimensions)}" - ) + errmsg = f"'dimensions' must be array-like got " f"{type(dimensions)}" raise TypeError(errmsg) from None if dimensions.shape == (6,): # single box, tile this to trajectory length @@ -449,14 +440,8 @@ def parse_n_atoms(filename, order="fac", **kwargs): def copy(self): """Return a copy of this Memory Reader""" - vels = ( - self.velocity_array.copy() - if self.velocity_array is not None - else None - ) - fors = ( - self.force_array.copy() if self.force_array is not None else None - ) + vels = self.velocity_array.copy() if self.velocity_array is not None else None + fors = self.force_array.copy() if self.force_array is not None else None dims = self.dimensions_array.copy() new = self.__class__( @@ -561,9 +546,7 @@ def timeseries( category=DeprecationWarning, ) if atomgroup: - raise ValueError( - "Cannot provide both asel and atomgroup kwargs" - ) + raise ValueError("Cannot provide both asel and atomgroup kwargs") atomgroup = asel if stop != -1: @@ -609,9 +592,7 @@ def timeseries( return array else: if len(atomgroup) == 0: - raise ValueError( - "Timeseries requires at least one atom " "to analyze" - ) + raise ValueError("Timeseries requires at least one atom " "to analyze") # If selection is specified, return a copy return array.take(asel.indices, a_index) @@ -625,16 +606,12 @@ def _read_next_timestep(self, ts=None): ts.frame += 1 f_index = self.stored_order.find("f") basic_slice = ( - [slice(None)] * (f_index) - + [self.ts.frame] - + [slice(None)] * (2 - f_index) + [slice(None)] * (f_index) + [self.ts.frame] + [slice(None)] * (2 - f_index) ) _replace_positions_array(ts, self.coordinate_array[tuple(basic_slice)]) _replace_dimensions(ts, self.dimensions_array[self.ts.frame]) if self.velocity_array is not None: - _replace_velocities_array( - ts, self.velocity_array[tuple(basic_slice)] - ) + _replace_velocities_array(ts, self.velocity_array[tuple(basic_slice)]) if self.force_array is not None: _replace_forces_array(ts, self.force_array[tuple(basic_slice)]) diff --git a/package/MDAnalysis/coordinates/null.py b/package/MDAnalysis/coordinates/null.py index 5b2f4f1a3fa..87960eabbab 100644 --- a/package/MDAnalysis/coordinates/null.py +++ b/package/MDAnalysis/coordinates/null.py @@ -37,6 +37,7 @@ :members: """ + from . import base diff --git a/package/MDAnalysis/core/_get_readers.py b/package/MDAnalysis/core/_get_readers.py index 45d61b3cadf..a6bc92a4611 100644 --- a/package/MDAnalysis/core/_get_readers.py +++ b/package/MDAnalysis/core/_get_readers.py @@ -19,6 +19,7 @@ circular imports. """ + import copy import inspect @@ -192,12 +193,8 @@ def get_writer_for(filename, format=None, multiframe=None): format = format.upper() if multiframe is None: # Multiframe takes priority, else use singleframe - options = copy.copy( - _SINGLEFRAME_WRITERS - ) # do copy to avoid changing in place - options.update( - _MULTIFRAME_WRITERS - ) # update overwrites existing entries + options = copy.copy(_SINGLEFRAME_WRITERS) # do copy to avoid changing in place + options.update(_MULTIFRAME_WRITERS) # update overwrites existing entries errmsg = "No trajectory or frame writer for format '{0}'" elif multiframe is True: options = _MULTIFRAME_WRITERS diff --git a/package/MDAnalysis/core/groups.py b/package/MDAnalysis/core/groups.py index aad2fb02f34..18bce97deb4 100644 --- a/package/MDAnalysis/core/groups.py +++ b/package/MDAnalysis/core/groups.py @@ -90,6 +90,7 @@ at.level.plural # Returns AtomGroup class """ + from collections import namedtuple import numpy as np import functools @@ -160,9 +161,7 @@ def make_classes(): for cls in groups: bases[cls] = GBase._subclass(is_group=True) # CBase for patching all components - CBase = bases[ComponentBase] = _TopologyAttrContainer._subclass( - is_group=False - ) + CBase = bases[ComponentBase] = _TopologyAttrContainer._subclass(is_group=False) for cls in components: bases[cls] = CBase._subclass(is_group=False) @@ -420,14 +419,9 @@ def __getattr__(self, attr): ) # missing required topologyattr else: - err = ( - "{selfcls}.{attrname} not available; " - "this requires {topattr}" - ) + err = "{selfcls}.{attrname} not available; " "this requires {topattr}" raise NoDataError( - err.format( - selfcls=selfcls, attrname=attrname, topattr=topattr - ) + err.format(selfcls=selfcls, attrname=attrname, topattr=topattr) ) else: @@ -534,9 +528,7 @@ def wrapped(self, other): "".format(function.__name__) ) if self.universe is not other.universe: - raise ValueError( - "Can't operate on objects from different Universes" - ) + raise ValueError("Can't operate on objects from different Universes") return function(self, other) return wrapped @@ -673,10 +665,7 @@ def __getattr__(self, attr): if attr in _TOPOLOGY_ATTRS: cls = _TOPOLOGY_ATTRS[attr] if attr == cls.singular and attr != cls.attrname: - err = ( - "{selfcls} has no attribute {attr}. " - "Do you mean {plural}?" - ) + err = "{selfcls} has no attribute {attr}. " "Do you mean {plural}?" raise AttributeError( err.format(selfcls=selfcls, attr=attr, plural=cls.attrname) ) @@ -740,9 +729,7 @@ def __radd__(self, other): else: raise TypeError( "unsupported operand type(s) for +:" - " '{}' and '{}'".format( - type(self).__name__, type(other).__name__ - ) + " '{}' and '{}'".format(type(self).__name__, type(other).__name__) ) def __sub__(self, other): @@ -895,9 +882,7 @@ def _asunique(self, group, sorted=False, set_mask=False): if sorted: if set_mask: - unique_ix, restore_mask = np.unique( - self.ix, return_inverse=True - ) + unique_ix, restore_mask = np.unique(self.ix, return_inverse=True) self._unique_restore_mask = restore_mask else: unique_ix = unique_int_1d(self.ix) @@ -1173,9 +1158,7 @@ def center(self, weights, wrap=False, unwrap=False, compound="group"): if wrap: coords = atoms.pack_into_box(inplace=False) elif unwrap: - coords = atoms.unwrap( - compound=comp, reference=None, inplace=False - ) + coords = atoms.unwrap(compound=comp, reference=None, inplace=False) else: coords = atoms.positions # If there's no atom, return its (empty) coordinates unchanged. @@ -1187,17 +1170,13 @@ def center(self, weights, wrap=False, unwrap=False, compound="group"): return coords.mean(axis=0) # promote weights to dtype if required: weights = weights.astype(dtype, copy=False) - return ( - np.einsum("ij,ij->j", coords, weights[:, None]) / weights.sum() - ) + return np.einsum("ij,ij->j", coords, weights[:, None]) / weights.sum() # When compound split caching gets implemented it will be clever to # preempt at this point whether or not stable sorting will be needed # later for unwrap (so that we don't split now with non-stable sort, # only to have to re-split with stable sort if unwrap is requested). - (atom_masks, compound_masks, n_compounds) = ( - self._split_by_compound_indices(comp) - ) + atom_masks, compound_masks, n_compounds = self._split_by_compound_indices(comp) # Unwrap Atoms if unwrap: @@ -1218,9 +1197,7 @@ def center(self, weights, wrap=False, unwrap=False, compound="group"): _centers = _coords.mean(axis=1) else: _weights = weights[atom_mask] - _centers = np.einsum( - "ijk,ijk->ik", _coords, _weights[:, :, None] - ) + _centers = np.einsum("ijk,ijk->ik", _coords, _weights[:, :, None]) _centers /= _weights.sum(axis=1)[:, None] centers[compound_mask] = _centers if wrap: @@ -1406,9 +1383,7 @@ def accumulate(self, attribute, function=np.sum, compound="group"): if comp == "group": return function(attribute_values, axis=0) - (atom_masks, compound_masks, n_compounds) = ( - self._split_by_compound_indices(comp) - ) + atom_masks, compound_masks, n_compounds = self._split_by_compound_indices(comp) higher_dims = list(attribute_values.shape[1:]) @@ -1901,9 +1876,7 @@ def wrap(self, compound="atoms", center="com", box=None, inplace=True): # Build mapping from compound index to shift index unique_compound_indices = unique_int_1d(compound_indices) - index_to_shift = np.empty( - compound_indices.max() + 1, dtype=int - ) + index_to_shift = np.empty(compound_indices.max() + 1, dtype=int) index_to_shift[unique_compound_indices] = np.arange( len(unique_compound_indices) ) @@ -2014,8 +1987,7 @@ def unwrap(self, compound="fragments", reference="com", inplace=True): # ResidueGroups or SegmentGroups if reference == "com" and not hasattr(unique_atoms, "masses"): raise NoDataError( - "Cannot perform unwrap with reference='com', " - "this requires masses." + "Cannot perform unwrap with reference='com', " "this requires masses." ) # Sanity checking of the compound parameter is done downstream in @@ -2083,9 +2055,7 @@ def unwrap(self, compound="fragments", reference="com", inplace=True): refpos = positions[atom_mask].mean(axis=1) refpos = refpos.astype(np.float32, copy=False) target = distances.apply_PBC(refpos, self.dimensions) - positions[atom_mask] += ( - target[:, None, :] - refpos[:, None, :] - ) + positions[atom_mask] += target[:, None, :] - refpos[:, None, :] if inplace: unique_atoms.positions = positions if not atoms.isunique: @@ -2245,9 +2215,7 @@ def concatenate(self, other): .. versionadded:: 0.16.0 """ o_ix = other.ix_array - return self._derived_class( - np.concatenate([self.ix, o_ix]), self.universe - ) + return self._derived_class(np.concatenate([self.ix, o_ix]), self.universe) @_only_same_level def union(self, other): @@ -2334,9 +2302,7 @@ def intersection(self, other): .. versionadded:: 0.16 """ o_ix = other.ix_array - return self._derived_class( - np.intersect1d(self.ix, o_ix), self.universe - ) + return self._derived_class(np.intersect1d(self.ix, o_ix), self.universe) @_only_same_level def subtract(self, other): @@ -2840,9 +2806,7 @@ def residues(self, new): errmsg = ( "Can only set AtomGroup residues to Residue " "or ResidueGroup not {}".format( - ", ".join( - type(r) for r in new if not isinstance(r, Residue) - ) + ", ".join(type(r) for r in new if not isinstance(r, Residue)) ) ) raise TypeError(errmsg) from None @@ -2884,8 +2848,7 @@ def segments(self): @segments.setter def segments(self, new): raise NotImplementedError( - "Cannot assign Segments to AtomGroup. " - "Segments are assigned to Residues" + "Cannot assign Segments to AtomGroup. " "Segments are assigned to Residues" ) @property @@ -3014,9 +2977,7 @@ def asunique(self, sorted=False): .. versionadded:: 2.0.0 """ - return self._asunique( - sorted=sorted, group=self.universe.atoms, set_mask=True - ) + return self._asunique(sorted=sorted, group=self.universe.atoms, set_mask=True) @property def positions(self): @@ -3616,10 +3577,7 @@ def split(self, level): ) raise ValueError(errmsg) from None - return [ - self[levelindices == index] - for index in unique_int_1d(levelindices) - ] + return [self[levelindices == index] for index in unique_int_1d(levelindices)] def guess_bonds(self, vdwradii=None, fudge_factor=0.55, lower_bound=0.1): """Guess bonds, angles, and dihedrals between the atoms in this @@ -3700,9 +3658,7 @@ def bond(self): .. versionadded:: 0.11.0 """ if len(self) != 2: - raise ValueError( - "bond only makes sense for a group with exactly 2 atoms" - ) + raise ValueError("bond only makes sense for a group with exactly 2 atoms") return topologyobjects.Bond(self.ix, self.universe) @property @@ -3719,9 +3675,7 @@ def angle(self): .. versionadded:: 0.11.0 """ if len(self) != 3: - raise ValueError( - "angle only makes sense for a group with exactly 3 atoms" - ) + raise ValueError("angle only makes sense for a group with exactly 3 atoms") return topologyobjects.Angle(self.ix, self.universe) @property @@ -3795,9 +3749,7 @@ def cmap(self): .. versionadded:: 1.0.0 """ if len(self) != 5: - raise ValueError( - "cmap only makes sense for a group with exactly 5 atoms" - ) + raise ValueError("cmap only makes sense for a group with exactly 5 atoms") return topologyobjects.CMap(self.ix, self.universe) convert_to = Accessor("convert_to", ConverterWrapper) @@ -3918,9 +3870,7 @@ def write( # Try and select a Class using get_ methods (becomes `writer`) # Once (and if!) class is selected, use it in with block try: - writer = get_writer_for( - filename, format=file_format, multiframe=multiframe - ) + writer = get_writer_for(filename, format=file_format, multiframe=multiframe) except (ValueError, TypeError): pass else: @@ -4133,9 +4083,7 @@ def segments(self, new): errmsg = ( "Can only set ResidueGroup segments to Segment " "or SegmentGroup, not {}".format( - ", ".join( - type(r) for r in new if not isinstance(r, Segment) - ) + ", ".join(type(r) for r in new if not isinstance(r, Segment)) ) ) raise TypeError(errmsg) from None @@ -4454,9 +4402,7 @@ class ComponentBase(_MutableBase): def __init__(self, ix, u): # index of component if not isinstance(ix, numbers.Integral): - raise IndexError( - "Component can only be indexed by a single integer" - ) + raise IndexError("Component can only be indexed by a single integer") self._ix = ix self._u = u @@ -4466,14 +4412,9 @@ def __getattr__(self, attr): if attr in _TOPOLOGY_ATTRS: cls = _TOPOLOGY_ATTRS[attr] if attr == cls.attrname and attr != cls.singular: - err = ( - "{selfcls} has no attribute {attr}. " - "Do you mean {singular}?" - ) + err = "{selfcls} has no attribute {attr}. " "Do you mean {singular}?" raise AttributeError( - err.format( - selfcls=selfcls, attr=attr, singular=cls.singular - ) + err.format(selfcls=selfcls, attr=attr, singular=cls.singular) ) else: err = "This Universe does not contain {singular} information" @@ -4514,9 +4455,7 @@ def __add__(self, other): """ o_ix = other.ix_array - return self.level.plural( - np.concatenate([self.ix_array, o_ix]), self.universe - ) + return self.level.plural(np.concatenate([self.ix_array, o_ix]), self.universe) def __radd__(self, other): """Using built-in sum requires supporting 0 + self. If other is @@ -4537,9 +4476,7 @@ def __radd__(self, other): else: raise TypeError( "unsupported operand type(s) for +:" - " '{}' and '{}'".format( - type(self).__name__, type(other).__name__ - ) + " '{}' and '{}'".format(type(self).__name__, type(other).__name__) ) @property @@ -4616,8 +4553,7 @@ def residue(self): def residue(self, new): if not isinstance(new, Residue): raise TypeError( - "Can only set Atom residue to Residue, not {}" - "".format(type(new)) + "Can only set Atom residue to Residue, not {}" "".format(type(new)) ) self.universe._topology.tt.move_atom(self.ix, new.resindex) @@ -4748,8 +4684,7 @@ def segment(self): def segment(self, new): if not isinstance(new, Segment): raise TypeError( - "Can only set Residue segment to Segment, not {}" - "".format(type(new)) + "Can only set Residue segment to Segment, not {}" "".format(type(new)) ) self.universe._topology.tt.move_residue(self.ix, new.segindex) @@ -4798,9 +4733,7 @@ def residues(self): """A :class:`ResidueGroup` of :class:`Residues` present in this :class:`Segment`. """ - rg = self.universe.residues[ - self.universe._topology.resindices[self][0] - ] + rg = self.universe.residues[self.universe._topology.resindices[self][0]] rg._cache["isunique"] = True rg._cache["issorted"] = True rg._cache["sorted_unique"] = rg diff --git a/package/MDAnalysis/core/selection.py b/package/MDAnalysis/core/selection.py index 6acd873ee37..8ecf399a323 100644 --- a/package/MDAnalysis/core/selection.py +++ b/package/MDAnalysis/core/selection.py @@ -38,6 +38,7 @@ :class:`~MDAnalysis.core.groups.AtomGroup`. """ + import collections import re import fnmatch @@ -75,10 +76,7 @@ def is_keyword(val): - The value `None` (used as EOF in selection strings) """ return ( - val in _SELECTIONDICT - or val in _OPERATIONS - or val in ["(", ")"] - or val is None + val in _SELECTIONDICT or val in _OPERATIONS or val in ["(", ")"] or val is None ) @@ -849,9 +847,7 @@ def _apply(self, group): except (AttributeError, NoDataError): icodes = None # if no icodes and icodes are part of selection, cause a fuss - if any(v[1] for v in self.uppers) or any( - v[1] for v in self.lowers - ): + if any(v[1] for v in self.uppers) or any(v[1] for v in self.lowers): errmsg = ( "Selection specified icodes, while the topology " "doesn't have any." @@ -884,9 +880,7 @@ def _sel_with_icodes(self, vals, icodes): # Final mask that gets applied to group mask = np.zeros(len(vals), dtype=bool) - for (u_resid, u_icode), (l_resid, l_icode) in zip( - self.uppers, self.lowers - ): + for (u_resid, u_icode), (l_resid, l_icode) in zip(self.uppers, self.lowers): if u_resid is not None: # Selecting a range # Special case, if l_resid == u_resid, ie 163A-163C, this simplifies to: # all 163, and A <= icode <= C @@ -1042,9 +1036,7 @@ def _apply(self, group): "for `np.isclose`." ) warnings.warn(msg, category=SelectionWarning) - thismask = np.isclose( - vals, lower, atol=self.atol, rtol=self.rtol - ) + thismask = np.isclose(vals, lower, atol=self.atol, rtol=self.rtol) mask |= thismask return group[mask] @@ -1196,9 +1188,7 @@ def _apply(self, group): resname_attr = group.universe._topology.resnames # which values in resname attr are in prot_res? matches = [ - ix - for (nm, ix) in resname_attr.namedict.items() - if nm in self.prot_res + ix for (nm, ix) in resname_attr.namedict.items() if nm in self.prot_res ] # index of each atom's resname nmidx = resname_attr.nmidx[group.resindices] @@ -1266,9 +1256,7 @@ def _apply(self, group): resnames = group.universe._topology.resnames nmidx = resnames.nmidx[group.resindices] - matches = [ - ix for (nm, ix) in resnames.namedict.items() if nm in self.nucl_res - ] + matches = [ix for (nm, ix) in resnames.namedict.items() if nm in self.nucl_res] mask = np.isin(nmidx, matches) return group[mask] @@ -1311,11 +1299,7 @@ def _apply(self, group): resnames = group.universe._topology.resnames nmidx = resnames.nmidx[group.resindices] - matches = [ - ix - for (nm, ix) in resnames.namedict.items() - if nm in self.water_res - ] + matches = [ix for (nm, ix) in resnames.namedict.items() if nm in self.water_res] mask = np.isin(nmidx, matches) return group[mask] @@ -1342,9 +1326,7 @@ def _apply(self, group): # filter by atom names name_matches = [ - ix - for (nm, ix) in atomnames.namedict.items() - if nm in self.bb_atoms + ix for (nm, ix) in atomnames.namedict.items() if nm in self.bb_atoms ] nmidx = atomnames.nmidx[group.ix] group = group[np.isin(nmidx, name_matches)] @@ -1380,9 +1362,7 @@ def _apply(self, group): # filter by atom names name_matches = [ - ix - for (nm, ix) in atomnames.namedict.items() - if nm in self.bb_atoms + ix for (nm, ix) in atomnames.namedict.items() if nm in self.bb_atoms ] nmidx = atomnames.nmidx[group.ix] group = group[np.isin(nmidx, name_matches)] @@ -1437,9 +1417,7 @@ def _apply(self, group): # filter by atom names name_matches = [ - ix - for (nm, ix) in atomnames.namedict.items() - if nm in self.base_atoms + ix for (nm, ix) in atomnames.namedict.items() if nm in self.base_atoms ] nmidx = atomnames.nmidx[group.ix] group = group[np.isin(nmidx, name_matches)] @@ -1472,9 +1450,7 @@ def _apply(self, group): # filter by atom names name_matches = [ - ix - for (nm, ix) in atomnames.namedict.items() - if nm in self.sug_atoms + ix for (nm, ix) in atomnames.namedict.items() if nm in self.sug_atoms ] nmidx = atomnames.nmidx[group.ix] group = group[np.isin(nmidx, name_matches)] @@ -1583,10 +1559,7 @@ def __init__(self, parser, tokens): try: self.operator = self.ops[oper] except KeyError: - errmsg = ( - f"Invalid operator : '{oper}' Use one of : " - f"'{self.ops.keys()}'" - ) + errmsg = f"Invalid operator : '{oper}' Use one of : " f"'{self.ops.keys()}'" raise ValueError(errmsg) from None else: if oper == "==": diff --git a/package/MDAnalysis/core/topology.py b/package/MDAnalysis/core/topology.py index dffff294d3a..6ee8f54dd1b 100644 --- a/package/MDAnalysis/core/topology.py +++ b/package/MDAnalysis/core/topology.py @@ -56,6 +56,7 @@ .. autofunction:: make_downshift_arrays """ + import contextlib import numpy as np @@ -601,10 +602,7 @@ def add_Residue(self, segment, **new_attrs): missing = ( attr.singular for attr in self.attrs - if ( - attr.per_object == "residue" - and attr.singular not in new_attrs - ) + if (attr.per_object == "residue" and attr.singular not in new_attrs) ) raise NoDataError( "Missing the following attributes for the new" diff --git a/package/MDAnalysis/core/topologyattrs.py b/package/MDAnalysis/core/topologyattrs.py index 359bd20c9c1..7605816f781 100644 --- a/package/MDAnalysis/core/topologyattrs.py +++ b/package/MDAnalysis/core/topologyattrs.py @@ -247,18 +247,14 @@ def stub_method(self, *args, **kwargs): ) raise NoDataError(message) - annotation = textwrap.dedent( - """\ + annotation = textwrap.dedent("""\ .. note:: This requires the underlying topology to have {}. Otherwise, a :exc:`~MDAnalysis.exceptions.NoDataError` is raised. - """.format( - attribute_name - ) - ) + """.format(attribute_name)) # The original docstring is assumed to be formatted with black # (i.e., *all text* lines are already indented, the first line # is a triple quote followed by newline) @@ -396,9 +392,7 @@ def __init__(cls, name, bases, classdict): if dtype is not None: per_obj = classdict.get("per_object", bases[0].per_object) try: - selection.gen_selection_class( - singular, attrname, dtype, per_obj - ) + selection.gen_selection_class(singular, attrname, dtype, per_obj) except ValueError: msg = ( "A selection keyword could not be " @@ -476,9 +470,7 @@ def _gen_initial_values(n_atoms, n_residues, n_segments): raise NotImplementedError("No default values") @classmethod - def from_blank( - cls, n_atoms=None, n_residues=None, n_segments=None, values=None - ): + def from_blank(cls, n_atoms=None, n_residues=None, n_segments=None, values=None): """Create a blank version of this TopologyAttribute Parameters @@ -829,9 +821,7 @@ def _set_X(self, ag, values): newnames.append(val) newidx[i] = nextidx - self.nmidx[ag.ix] = ( - newidx # newidx either single value or same size array - ) + self.nmidx[ag.ix] = newidx # newidx either single value or same size array if newnames: self.name_lookup = np.concatenate([self.name_lookup, newnames]) self.values = self.name_lookup[self.nmidx] @@ -954,8 +944,7 @@ def phi_selections(residues, c_name="C", n_name="N", ca_name="CA"): keep_prev = [sum(r.atoms.names == c_name) == 1 for r in prev] keep_res = [ - all(sum(r.atoms.names == n) == 1 for n in ncac_names) - for r in residues + all(sum(r.atoms.names == n) == 1 for n in ncac_names) for r in residues ] keep = np.array(keep_prev) & np.array(keep_res) keep[invalid] = False @@ -1146,8 +1135,7 @@ def psi_selections(residues, c_name="C", n_name="N", ca_name="CA"): keep_nxt = [sum(r.atoms.names == n_name) == 1 for r in nxt] keep_res = [ - all(sum(r.atoms.names == n) == 1 for n in ncac_names) - for r in residues + all(sum(r.atoms.names == n) == 1 for n in ncac_names) for r in residues ] keep = np.array(keep_nxt) & np.array(keep_res) nxt = nxt[keep] @@ -1259,12 +1247,9 @@ def omega_selections(residues, c_name="C", n_name="N", ca_name="CA"): nxtatoms = [ca_name, n_name] resatoms = [ca_name, c_name] - keep_nxt = [ - all(sum(r.atoms.names == n) == 1 for n in nxtatoms) for r in nxt - ] + keep_nxt = [all(sum(r.atoms.names == n) == 1 for n in nxtatoms) for r in nxt] keep_res = [ - all(sum(r.atoms.names == n) == 1 for n in resatoms) - for r in residues + all(sum(r.atoms.names == n) == 1 for n in resatoms) for r in residues ] keep = np.array(keep_nxt) & np.array(keep_res) nxt = nxt[keep] @@ -1766,13 +1751,9 @@ def moment_of_inertia(group, wrap=False, unwrap=False, compound="group"): """ atomgroup = group.atoms - com = atomgroup.center_of_mass( - wrap=wrap, unwrap=unwrap, compound=compound - ) + com = atomgroup.center_of_mass(wrap=wrap, unwrap=unwrap, compound=compound) if compound != "group": - com = (com * group.masses[:, None]).sum( - axis=0 - ) / group.masses.sum() + com = (com * group.masses[:, None]).sum(axis=0) / group.masses.sum() if wrap: pos = atomgroup.pack_into_box(inplace=False) - com @@ -1903,9 +1884,7 @@ def _gyration(recenteredpos, masses): atomgroup = group.atoms masses = atomgroup.masses - com = atomgroup.center_of_mass( - wrap=wrap, unwrap=unwrap, compound=compound - ) + com = atomgroup.center_of_mass(wrap=wrap, unwrap=unwrap, compound=compound) if compound == "group": if wrap: @@ -1923,7 +1902,7 @@ def _gyration(recenteredpos, masses): recenteredpos = atomgroup.positions - com eig_vals = _gyration(recenteredpos, masses) else: - (atom_masks, compound_masks, n_compounds) = ( + atom_masks, compound_masks, n_compounds = ( atomgroup._split_by_compound_indices(compound) ) @@ -2040,8 +2019,7 @@ def asphericity(group, wrap=False, unwrap=False, compound="group"): ) else: shape = (3.0 / 2.0) * ( - np.sum((eig_vals - np.mean(eig_vals)) ** 2) - / np.sum(eig_vals) ** 2 + np.sum((eig_vals - np.mean(eig_vals)) ** 2) / np.sum(eig_vals) ** 2 ) return shape @@ -2125,9 +2103,7 @@ def align_principal_axis(group, axis, vector): # print "axis = %r, angle = %f deg" % (ax, angle) return group.rotateby(angle, ax) - transplants[GroupBase].append( - ("align_principal_axis", align_principal_axis) - ) + transplants[GroupBase].append(("align_principal_axis", align_principal_axis)) # TODO: update docs to property doc @@ -2284,9 +2260,7 @@ def total_charge(group, compound="group"): @warn_if_not_unique @_pbc_to_wrap @check_wrap_and_unwrap - def dipole_vector( - group, wrap=False, unwrap=False, compound="group", center="mass" - ): + def dipole_vector(group, wrap=False, unwrap=False, compound="group", center="mass"): r"""Dipole vector of the group. .. math:: @@ -2352,9 +2326,7 @@ def dipole_vector( if center == "mass": masses = atomgroup.masses - ref = atomgroup.center_of_mass( - wrap=wrap, unwrap=unwrap, compound=compound - ) + ref = atomgroup.center_of_mass(wrap=wrap, unwrap=unwrap, compound=compound) elif center == "charge": ref = atomgroup.center_of_charge( wrap=wrap, unwrap=unwrap, compound=compound @@ -2380,11 +2352,9 @@ def dipole_vector( ) else: recenteredpos = atomgroup.positions - ref - dipole_vector = np.einsum( - "ij,ij->j", recenteredpos, charges[:, np.newaxis] - ) + dipole_vector = np.einsum("ij,ij->j", recenteredpos, charges[:, np.newaxis]) else: - (atom_masks, compound_masks, n_compounds) = ( + atom_masks, compound_masks, n_compounds = ( atomgroup._split_by_compound_indices(compound) ) @@ -2466,13 +2436,9 @@ def dipole_moment(group, **kwargs): dipole_vector = atomgroup.dipole_vector(**kwargs) if len(dipole_vector.shape) > 1: - dipole_moment = np.sqrt( - np.einsum("ij,ij->i", dipole_vector, dipole_vector) - ) + dipole_moment = np.sqrt(np.einsum("ij,ij->i", dipole_vector, dipole_vector)) else: - dipole_moment = np.sqrt( - np.einsum("i,i->", dipole_vector, dipole_vector) - ) + dipole_moment = np.sqrt(np.einsum("i,i->", dipole_vector, dipole_vector)) return dipole_moment @@ -2565,9 +2531,7 @@ def __quadrupole_tensor(recenteredpos, charges): if center == "mass": masses = atomgroup.masses - ref = atomgroup.center_of_mass( - wrap=wrap, unwrap=unwrap, compound=compound - ) + ref = atomgroup.center_of_mass(wrap=wrap, unwrap=unwrap, compound=compound) elif center == "charge": ref = atomgroup.center_of_charge( wrap=wrap, unwrap=unwrap, compound=compound @@ -2595,7 +2559,7 @@ def __quadrupole_tensor(recenteredpos, charges): recenteredpos = atomgroup.positions - ref quad_tensor = __quadrupole_tensor(recenteredpos, charges) else: - (atom_masks, compound_masks, n_compounds) = ( + atom_masks, compound_masks, n_compounds = ( atomgroup._split_by_compound_indices(compound) ) @@ -2685,9 +2649,7 @@ def __quadrupole_moment(tensor): if len(quad_tensor.shape) == 2: quad_moment = __quadrupole_moment(quad_tensor) else: - quad_moment = np.array( - [__quadrupole_moment(x) for x in quad_tensor] - ) + quad_moment = np.array([__quadrupole_moment(x) for x in quad_tensor]) return quad_moment @@ -3011,9 +2973,7 @@ def sequence(self, **kwargs): ) ) try: - sequence = "".join( - [convert_aa_code(r) for r in self.residues.resnames] - ) + sequence = "".join([convert_aa_code(r) for r in self.residues.resnames]) except KeyError as err: errmsg = ( f"AtomGroup contains a residue name '{err.message}' that" @@ -3146,14 +3106,13 @@ def _check_connection_values(func): @functools.wraps(func) def wrapper(self, values, *args, **kwargs): if not all( - len(x) == self._n_atoms - and all(isinstance(y, (int, np.integer)) for y in x) + len(x) == self._n_atoms and all(isinstance(y, (int, np.integer)) for y in x) for x in values ): raise ValueError( - ( - "{} must be an iterable of tuples with {}" " atom indices" - ).format(self.attrname, self._n_atoms) + ("{} must be an iterable of tuples with {}" " atom indices").format( + self.attrname, self._n_atoms + ) ) clean = [] for v in values: @@ -3231,9 +3190,7 @@ def _bondDict(self): """Lazily built mapping of atoms:bonds""" bd = defaultdict(list) - for b, t, g, o in zip( - self.values, self.types, self._guessed, self.order - ): + for b, t, g, o in zip(self.values, self.types, self._guessed, self.order): for a in b: bd[a].append((b, t, g, o)) return bd @@ -3252,9 +3209,7 @@ def get_atoms(self, ag): """ try: - unique_bonds = set( - itertools.chain(*[self._bondDict[a] for a in ag.ix]) - ) + unique_bonds = set(itertools.chain(*[self._bondDict[a] for a in ag.ix])) except TypeError: # maybe we got passed an Atom unique_bonds = self._bondDict[ag.ix] diff --git a/package/MDAnalysis/core/topologyobjects.py b/package/MDAnalysis/core/topologyobjects.py index fcc37be6246..6b63d0295d7 100644 --- a/package/MDAnalysis/core/topologyobjects.py +++ b/package/MDAnalysis/core/topologyobjects.py @@ -28,6 +28,7 @@ The building blocks for MDAnalysis' description of topology """ + import numbers import numpy as np import functools @@ -603,9 +604,7 @@ def __init__( # guess what I am # difference between dihedral and improper # not really important - self.btype = {2: "bond", 3: "angle", 4: "dihedral"}[ - len(bondidx[0]) - ] + self.btype = {2: "bond", 3: "angle", 4: "dihedral"}[len(bondidx[0])] elif btype in _BTYPE_TO_SHAPE: self.btype = btype else: @@ -638,8 +637,7 @@ def __init__( # Create vertical AtomGroups self._ags = [ - universe.atoms[self._bix[:, i]] - for i in range(self._bix.shape[1]) + universe.atoms[self._bix[:, i]] for i in range(self._bix.shape[1]) ] else: # Empty TopologyGroup @@ -816,15 +814,11 @@ def __add__(self, other): np.concatenate([self.indices, other.indices[None, :]]), self.universe, btype=self.btype, - type=np.concatenate( - [self._bondtypes, np.array([other._bondtype])] - ), + type=np.concatenate([self._bondtypes, np.array([other._bondtype])]), guessed=np.concatenate( [self._guessed, np.array([other.is_guessed])] ), - order=np.concatenate( - [self._order, np.array([other.order])] - ), + order=np.concatenate([self._order, np.array([other.order])]), ) else: # add TG to me diff --git a/package/MDAnalysis/core/universe.py b/package/MDAnalysis/core/universe.py index 4b9ec247bd8..1bc1fd36778 100644 --- a/package/MDAnalysis/core/universe.py +++ b/package/MDAnalysis/core/universe.py @@ -53,6 +53,7 @@ .. autofunction:: Merge """ + import errno import numpy as np import logging @@ -174,9 +175,7 @@ def _update_topology_by_ids(universe, atomwise_resids, atomwise_segids): attrs.extend(res_attrs) # create new segment level stuff - segidx, (segids,) = change_squash( - (res_squashed_segids,), (res_squashed_segids,) - ) + segidx, (segids,) = change_squash((res_squashed_segids,), (res_squashed_segids,)) n_segments = len(segids) attrs.append(Segids(segids)) @@ -286,9 +285,7 @@ def _resolve_formats(*coordinates, format=None, topology_format=None): return format, topology_format -def _resolve_coordinates( - filename, *coordinates, format=None, all_coordinates=False -): +def _resolve_coordinates(filename, *coordinates, format=None, all_coordinates=False): if all_coordinates or not coordinates and filename is not None: try: get_reader_for(filename, format=format) @@ -319,13 +316,9 @@ def _generate_from_topology(universe): # once.) universe.atoms = AtomGroup(np.arange(universe._topology.n_atoms), universe) - universe.residues = ResidueGroup( - np.arange(universe._topology.n_residues), universe - ) + universe.residues = ResidueGroup(np.arange(universe._topology.n_residues), universe) - universe.segments = SegmentGroup( - np.arange(universe._topology.n_segments), universe - ) + universe.segments = SegmentGroup(np.arange(universe._topology.n_segments), universe) class Universe(object): @@ -648,16 +641,12 @@ def __init__( # which replaces existing bonds). to_guess = list(to_guess) + ["bonds", "angles", "dihedrals"] - self.guess_TopologyAttrs( - context, to_guess, force_guess, error_if_missing=False - ) + self.guess_TopologyAttrs(context, to_guess, force_guess, error_if_missing=False) def copy(self): """Return an independent copy of this Universe""" context = self._context.copy() - new = self.__class__( - self._topology.copy(), to_guess=(), context=context - ) + new = self.__class__(self._topology.copy(), to_guess=(), context=context) new.trajectory = self.trajectory.copy() return new @@ -933,9 +922,7 @@ def transfer_to_memory( velocities = np.zeros_like(coordinates) if has_vels else None forces = np.zeros_like(coordinates) if has_fors else None - dimensions = ( - np.zeros((n_frames, 6), dtype=np.float32) if has_dims else None - ) + dimensions = np.zeros((n_frames, 6), dtype=np.float32) if has_dims else None for i, ts in enumerate( ProgressBar( @@ -1017,9 +1004,7 @@ def __repr__(self): # n_atoms=len(self.atoms), # bonds=" and {0} bonds".format(len(self.bonds)) if self.bonds else "") - return "".format( - n_atoms=len(self.atoms) - ) + return "".format(n_atoms=len(self.atoms)) @classmethod def _unpickle_U(cls, top, traj, context): @@ -1149,9 +1134,7 @@ def add_TopologyAttr(self, topologyattr, values=None): " Possible values: '{}'\n" "To raise an issue go to: " "https://github.com/MDAnalysis/mdanalysis/issues" - "".format( - topologyattr, ", ".join(sorted(_TOPOLOGY_ATTRS.keys())) - ) + "".format(topologyattr, ", ".join(sorted(_TOPOLOGY_ATTRS.keys()))) ) raise ValueError(errmsg) from None else: @@ -1246,10 +1229,7 @@ def _process_attr(self, attr): "segment": self._topology.n_segments, } logger.debug("_process_attr: Adding {0} to topology".format(attr)) - if ( - attr.per_object is not None - and len(attr) != n_dict[attr.per_object] - ): + if attr.per_object is not None and len(attr) != n_dict[attr.per_object]: raise ValueError( "Length of {attr} does not" " match number of {obj}s.\n" @@ -1347,9 +1327,7 @@ def add_Residue(self, segment=None, **attrs): # pass this information to the topology residx = self._topology.add_Residue(segment, **attrs) # resize my residues - self.residues = ResidueGroup( - np.arange(self._topology.n_residues), self - ) + self.residues = ResidueGroup(np.arange(self._topology.n_residues), self) # return the new residue return self.residues[residx] @@ -1376,9 +1354,7 @@ def add_Segment(self, **attrs): # pass this information to the topology segidx = self._topology.add_Segment(**attrs) # resize my segments - self.segments = SegmentGroup( - np.arange(self._topology.n_segments), self - ) + self.segments = SegmentGroup(np.arange(self._topology.n_segments), self) # return the new segment return self.segments[segidx] @@ -1522,9 +1498,7 @@ def add_angles(self, values, types=None, guessed=False): .. versionadded:: 1.0.0 """ - self._add_topology_objects( - "angles", values, types=types, guessed=guessed - ) + self._add_topology_objects("angles", values, types=types, guessed=guessed) def add_dihedrals(self, values, types=None, guessed=False): """Add new Dihedrals to this Universe. @@ -1545,9 +1519,7 @@ def add_dihedrals(self, values, types=None, guessed=False): .. versionadded:: 1.0.0 """ - self._add_topology_objects( - "dihedrals", values, types=types, guessed=guessed - ) + self._add_topology_objects("dihedrals", values, types=types, guessed=guessed) def add_impropers(self, values, types=None, guessed=False): """Add new Impropers to this Universe. @@ -1568,9 +1540,7 @@ def add_impropers(self, values, types=None, guessed=False): .. versionadded:: 1.0.0 """ - self._add_topology_objects( - "impropers", values, types=types, guessed=guessed - ) + self._add_topology_objects("impropers", values, types=types, guessed=guessed) def _delete_topology_objects(self, object_type, values): """Delete TopologyObjects from this Universe @@ -1910,9 +1880,7 @@ def guess_TopologyAttrs( # from guesser methods if self._topology.n_atoms > 0: - topology_attrs = [ - att.attrname for att in self._topology.read_attributes - ] + topology_attrs = [att.attrname for att in self._topology.read_attributes] common_attrs = set(to_guess) & set(topology_attrs) common_attrs = ", ".join(attr for attr in common_attrs) @@ -1955,9 +1923,7 @@ def guess_TopologyAttrs( else: guessed_attr = _TOPOLOGY_ATTRS[attr](values, True) self.add_TopologyAttr(guessed_attr) - logger.info( - f"attribute {attr} has been guessed" " successfully." - ) + logger.info(f"attribute {attr} has been guessed" " successfully.") else: raise ValueError( @@ -1966,9 +1932,7 @@ def guess_TopologyAttrs( ) else: - warnings.warn( - "Can not guess attributes " "for universe with 0 atoms" - ) + warnings.warn("Can not guess attributes " "for universe with 0 atoms") def set_groups(self, atomwise_resids=None, atomwise_segids=None): """Set the groups (`ResidueGroup`, `SegmentGroup`) of the Universe @@ -2159,9 +2123,7 @@ def Merge(*args): # Create a new topology using the intersection of topology attributes blank_topology_attrs = set(dir(Topology(attrs=[]))) - common_attrs = set.intersection( - *[set(dir(ag.universe._topology)) for ag in args] - ) + common_attrs = set.intersection(*[set(dir(ag.universe._topology)) for ag in args]) tops = set(["bonds", "angles", "dihedrals", "impropers"]) attrs = [] @@ -2218,9 +2180,7 @@ def Merge(*args): tg = tg.atomgroup_intersection(ag, strict=True) # Map them so they refer to our new indices - new_idx = [ - tuple([mapping[x] for x in entry]) for entry in tg.indices - ] + new_idx = [tuple([mapping[x] for x in entry]) for entry in tg.indices] bondidx.extend(new_idx) if hasattr(tg, "_bondtypes"): types.extend(tg._bondtypes) diff --git a/package/MDAnalysis/due.py b/package/MDAnalysis/due.py index 7ab1e8b55a9..4d6f52e7d53 100644 --- a/package/MDAnalysis/due.py +++ b/package/MDAnalysis/due.py @@ -65,9 +65,7 @@ def _donothing_func(*args, **kwargs): from duecredit import due, BibTeX, Doi, Url if "due" in locals() and not hasattr(due, "cite"): - raise RuntimeError( - "Imported due lacks .cite. DueCredit is now disabled" - ) + raise RuntimeError("Imported due lacks .cite. DueCredit is now disabled") except Exception as err: if not isinstance(err, ImportError): import logging diff --git a/package/MDAnalysis/fetch/__init__.py b/package/MDAnalysis/fetch/__init__.py new file mode 100644 index 00000000000..1ebe1c8bd1c --- /dev/null +++ b/package/MDAnalysis/fetch/__init__.py @@ -0,0 +1,39 @@ +# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*- +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +# +# MDAnalysis --- https://www.mdanalysis.org +# Copyright (c) 2006-2017 The MDAnalysis Development Team and contributors +# (see the file AUTHORS for the full list of names) +# +# Released under the Lesser GNU Public Licence, v2.1 or any higher version +# +# Please cite your use of MDAnalysis in published work: +# +# R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler, +# D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein. +# MDAnalysis: A Python package for the rapid analysis of molecular dynamics +# simulations. In S. Benthall and S. Rostrup editors, Proceedings of the 15th +# Python in Science Conference, pages 102-109, Austin, TX, 2016. SciPy. +# doi: 10.25080/majora-629e541a-00e +# +# N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and O. Beckstein. +# MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. +# J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 +# + +""" +Web Retrieval Services --- :mod:`MDAnalysis.fetch` +================================================== + +The :mod:`MDAnalysis.fetch` module contains various functions that are able to download +resources from the internet. All functions return a :class:`~pathlib.Path` object. +:class:`~pathlib.Path` objects are able to be passed as argument to initalize an +instance of :class:`~MDAnalysis.core.universe.Universe`. + +To use these functions, the optional dependency :mod:`pooch` is required. + +""" + +__all__ = ["from_PDB"] + +from .pdb import from_PDB diff --git a/package/MDAnalysis/fetch/pdb.py b/package/MDAnalysis/fetch/pdb.py new file mode 100644 index 00000000000..3459a59d894 --- /dev/null +++ b/package/MDAnalysis/fetch/pdb.py @@ -0,0 +1,197 @@ +# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding: utf-8 -*- +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +# +# MDAnalysis --- https://www.mdanalysis.org +# Copyright (c) 2006-2017 The MDAnalysis Development Team and contributors +# (see the file AUTHORS for the full list of names) +# +# Released under the Lesser GNU Public Licence, v2.1 or any higher version +# +# Please cite your use of MDAnalysis in published work: +# +# R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler, +# D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein. +# MDAnalysis: A Python package for the rapid analysis of molecular dynamics +# simulations. In S. Benthall and S. Rostrup editors, Proceedings of the 15th +# Python in Science Conference, pages 102-109, Austin, TX, 2016. SciPy. +# doi: 10.25080/majora-629e541a-00e +# +# N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and O. Beckstein. +# MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. +# J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 +# + +""" +PDB Fetchers --- :mod:`MDAnalysis.fetch.pdb` +============================================ + +This suite of functions download structure files from the Research Collaboratory for +Structural Bioinformatics (RCSB) `Protein Data Batabank`_ (PDB). + +.. _Protein Data Batabank: https://www.rcsb.org/ + +Variables +--------- + +.. autodata:: DEFAULT_CACHE_NAME_DOWNLOADER + + +Functions +--------- + +.. autofunction:: from_PDB + +""" + +from pathlib import Path + +try: + import pooch +except ImportError: + HAS_POOCH = False +else: + HAS_POOCH = True + +#: Name of the :mod:`pooch` cache directory ``pooch.os_cache(DEFAULT_CACHE_NAME_DOWNLOADER)``; +#: see :func:`pooch.os_cache` for further details. +#: +#: .. versionadded:: 2.11.0 +DEFAULT_CACHE_NAME_DOWNLOADER = "MDAnalysis_pdbs" + +# These file formats are here https://www.rcsb.org/docs/programmatic-access/file-download-services#pdb-entry-files" +SUPPORTED_FILE_FORMATS_DOWNLOADER = ( + "cif", + "cif.gz", + "bcif", + "bcif.gz", + "xml", + "xml.gz", + "pdb", + "pdb.gz", + "pdb1", + "pdb1.gz", +) + + +def from_PDB( + pdb_ids, + cache_path=None, + progressbar=False, + file_format="cif.gz", +): + """ + Download one or more PDB files from the RCSB Protein Data Bank and cache + them locally. + + Given one or multiple PDB IDs, downloads the corresponding structure files + format and stores them in a local cache directory. If files are cached on + disk, *from_PDB* will skip the download and use the cached version instead. + + Returns the path(s) as a :class:`~pathlib.Path` to the downloaded file(s). + + Parameters + ---------- + pdb_ids : str or sequence of str + A single PDB ID as a string, or a sequence of PDB IDs to fetch. + cache_path : str or pathlib.Path + Directory where downloaded file(s) will be cached. + The default ``None`` argument uses the :mod:`pooch` default cache with + project name :data:`DEFAULT_CACHE_NAME_DOWNLOADER`. + file_format : str + The file extension/format to download (e.g., "cif", "pdb"). + See the Notes section below for a list of all supported file formats. + progressbar : bool + If True, display a progress bar during file downloads. Default is False. + + Returns + ------- + :class:`~pathlib.Path` or list of :class:`~pathlib.Path` + The path(s) to the downloaded file(s). Returns a single + :class:`~pathlib.Path` if a single pdb id is given, or a list of + :class:`~pathlib.Path` if multiple pdb ids are provided. + + Raises + ------ + ValueError + For an invalid file format. Supported file formats are under Notes. + + :class:`requests.exceptions.HTTPError` + If an invalid PDB code is specified. + + Notes + ----- + This function uses the `RCSB File Download Services`_ for directly downloading + structure files via https. + + .. _`RCSB File Download Services`: + https://www.rcsb.org/docs/programmatic-access/file-download-services + + The RCSB currently provides data in ``'cif'`` , ``'cif.gz'`` , ``'bcif'`` , + ``'bcif.gz'`` , ``'xml'`` , ``'xml.gz'`` , ``'pdb'`` , ``'pdb.gz'``, + ``'pdb1'``, ``'pdb1.gz'`` file formats and can therefore be downloaded. + Not all of these formats can be currently read with MDAnalysis. + + Caching, controlled by the `cache_path` parameter, is handled internally by + :mod:`pooch`. The default cache name is taken from + :data:`DEFAULT_CACHE_NAME_DOWNLOADER`. To clear cache (and subsequently force + re-fetching), it is required to delete the cache folder as specified by + `cache_path`. + + Examples + -------- + Download a single PDB file: + + >>> mda.fetch.from_PDB("1AKE", file_format="cif") + './MDAnalysis_pdbs/1AKE.cif' + + Download multiple PDB files with a progress bar: + + >>> mda.fetch.from_PDB(["1AKE", "4BWZ"], progressbar=True) + ['./MDAnalysis_pdbs/1AKE.pdb.gz', './MDAnalysis_pdbs/4BWZ.pdb.gz'] + + Download a single PDB file and convert it to a universe: + + >>> mda.Universe(mda.fetch.from_PDB("1AKE"), file_format="pdb.gz") + + + Download multiple PDB files and convert each of them into a universe: + + >>> [mda.Universe(pdb) for pdb in mda.fetch.from_PDB(["1AKE", "4BWZ"], progressbar=True)] + [, ] + + + .. versionadded:: 2.11.0 + """ + + if not HAS_POOCH: + raise ModuleNotFoundError("pooch is needed as a dependency for from_PDB()") + elif file_format not in SUPPORTED_FILE_FORMATS_DOWNLOADER: + raise ValueError( + "Invalid file format. Supported file formats " + f"are {SUPPORTED_FILE_FORMATS_DOWNLOADER}" + ) + + if isinstance(pdb_ids, str): + _pdb_ids = (pdb_ids,) + else: + _pdb_ids = pdb_ids + + if cache_path is None: + cache_path = pooch.os_cache(DEFAULT_CACHE_NAME_DOWNLOADER) + + # Have to do this dictionary approach instead of using pooch.retrieve in order + # to prevent the hardcoded known_hash warning from showing up. + registry_dictionary = {f"{pdb_id}.{file_format}": None for pdb_id in _pdb_ids} + + downloader = pooch.create( + path=cache_path, + base_url="https://files.wwpdb.org/download/", + registry=registry_dictionary, + ) + + paths = [ + Path(downloader.fetch(fname=file_name, progressbar=progressbar)) + for file_name in registry_dictionary.keys() + ] + + return paths if not isinstance(pdb_ids, str) else paths[0] diff --git a/package/MDAnalysis/guesser/__init__.py b/package/MDAnalysis/guesser/__init__.py index b433356290f..983aa50ef76 100644 --- a/package/MDAnalysis/guesser/__init__.py +++ b/package/MDAnalysis/guesser/__init__.py @@ -36,15 +36,16 @@ ============================================== ========== ===================== =================================================== Name Context Attributes Remarks ============================================== ========== ===================== =================================================== - :ref:`DefaultGuesser ` default types, elements, general purpose guesser + :ref:`DefaultGuesser ` default types, elements, general purpose guesser masses, bonds, angles, dihedrals, improper dihedrals ============================================== ========== ===================== =================================================== - - + + """ + from . import base from .default_guesser import DefaultGuesser diff --git a/package/MDAnalysis/guesser/base.py b/package/MDAnalysis/guesser/base.py index c7bcc21e823..3a9a4a8cc04 100644 --- a/package/MDAnalysis/guesser/base.py +++ b/package/MDAnalysis/guesser/base.py @@ -36,6 +36,7 @@ .. autofunction:: get_guesser """ + from .. import _GUESSERS, _TOPOLOGY_ATTRS from ..core.topologyattrs import _Connection import numpy as np @@ -142,8 +143,7 @@ def guess_attr(self, attr_to_guess, force_guess=False): top_attr = _TOPOLOGY_ATTRS[attr_to_guess] except KeyError: raise KeyError( - f"{attr_to_guess} is not a recognized MDAnalysis " - "topology attribute" + f"{attr_to_guess} is not a recognized MDAnalysis " "topology attribute" ) # make attribute to guess plural attr_to_guess = top_attr.attrname @@ -164,9 +164,7 @@ def guess_attr(self, attr_to_guess, force_guess=False): # check if the topology already has the attribute to partially guess it if hasattr(self._universe.atoms, attr_to_guess) and not force_guess: - attr_values = np.array( - getattr(self._universe.atoms, attr_to_guess, None) - ) + attr_values = np.array(getattr(self._universe.atoms, attr_to_guess, None)) empty_values = top_attr.are_values_missing(attr_values) diff --git a/package/MDAnalysis/guesser/default_guesser.py b/package/MDAnalysis/guesser/default_guesser.py index 2ecc64c1e66..3cd5cfa1984 100644 --- a/package/MDAnalysis/guesser/default_guesser.py +++ b/package/MDAnalysis/guesser/default_guesser.py @@ -102,6 +102,7 @@ :inherited-members: """ + from .base import GuesserBase import numpy as np import warnings @@ -438,9 +439,7 @@ def guess_bonds(self, atoms=None, coords=None): raise ValueError( ( "vdw radii for types: " - + ", ".join( - [t for t in set(atomtypes) if t not in vdwradii] - ) + + ", ".join([t for t in set(atomtypes) if t not in vdwradii]) + ". These can be defined manually using the" + f" keyword 'vdwradii'" ) @@ -464,9 +463,7 @@ def guess_bonds(self, atoms=None, coords=None): coords, max_cutoff=2.0 * max_vdw, min_cutoff=lower_bound, box=box ) for idx, (i, j) in enumerate(pairs): - d = ( - vdwradii[atomtypes[i]] + vdwradii[atomtypes[j]] - ) * fudge_factor + d = (vdwradii[atomtypes[i]] + vdwradii[atomtypes[j]]) * fudge_factor if dist[idx] < d: bonds.append((atoms[i].index, atoms[j].index)) return tuple(bonds) @@ -516,9 +513,7 @@ def guess_angles(self, bonds=None): for other_b in atom.bonds: if other_b != b: # if not the same bond I start as third_a = other_b.partner(atom) - desc = tuple( - [other_a.index, atom.index, third_a.index] - ) + desc = tuple([other_a.index, atom.index, third_a.index]) # first index always less than last if desc[0] > desc[-1]: desc = desc[::-1] @@ -569,9 +564,7 @@ def guess_dihedrals(self, angles=None): a_tup = tuple([a.index for a in b]) # angle as tuple of numbers # if searching with b[0], want tuple of (b[2], b[1], b[0], +new) # search the first and last atom of each angle - for atom, prefix in zip( - [b.atoms[0], b.atoms[-1]], [a_tup[::-1], a_tup] - ): + for atom, prefix in zip([b.atoms[0], b.atoms[-1]], [a_tup[::-1], a_tup]): for other_b in atom.bonds: if not other_b.partner(atom) in b: third_a = other_b.partner(atom) @@ -679,9 +672,6 @@ def guess_gasteiger_charges(self, atomgroup): ComputeGasteigerCharges(mol, throwOnParamFailure=True) return np.array( - [ - atom.GetDoubleProp("_GasteigerCharge") - for atom in mol.GetAtoms() - ], + [atom.GetDoubleProp("_GasteigerCharge") for atom in mol.GetAtoms()], dtype=np.float32, ) diff --git a/package/MDAnalysis/lib/NeighborSearch.py b/package/MDAnalysis/lib/NeighborSearch.py index b1f5fa7185d..2516aead8eb 100644 --- a/package/MDAnalysis/lib/NeighborSearch.py +++ b/package/MDAnalysis/lib/NeighborSearch.py @@ -28,6 +28,7 @@ This module contains classes that allow neighbor searches directly with `AtomGroup` objects from `MDAnalysis`. """ + import numpy as np from MDAnalysis.lib.distances import capped_distance from MDAnalysis.lib.util import unique_int_1d @@ -136,6 +137,4 @@ def _index2level( elif level == "S": return atomgroup.segments else: - raise NotImplementedError( - "{0}: level not implemented".format(level) - ) + raise NotImplementedError("{0}: level not implemented".format(level)) diff --git a/package/MDAnalysis/lib/_distopia.py b/package/MDAnalysis/lib/_distopia.py index a6ec059168b..ffd4b002d93 100644 --- a/package/MDAnalysis/lib/_distopia.py +++ b/package/MDAnalysis/lib/_distopia.py @@ -27,6 +27,7 @@ This module is a stub to provide distopia distance functions to `distances.py` as a selectable backend. """ + import warnings from packaging.version import Version @@ -121,9 +122,7 @@ def calc_dihedral( coords4: np.ndarray, results: np.ndarray, ) -> None: - distopia.dihedrals_no_box( - coords1, coords2, coords3, coords4, results=results - ) + distopia.dihedrals_no_box(coords1, coords2, coords3, coords4, results=results) def calc_dihedral_ortho( diff --git a/package/MDAnalysis/lib/distances.py b/package/MDAnalysis/lib/distances.py index b3f862e005b..7d15944585d 100644 --- a/package/MDAnalysis/lib/distances.py +++ b/package/MDAnalysis/lib/distances.py @@ -139,6 +139,7 @@ .. autofunction:: minimize_vectors(vectors, box) """ + import numpy as np import numpy.typing as npt @@ -154,16 +155,13 @@ from .c_distances import _minimize_vectors_ortho, _minimize_vectors_triclinic from ._distopia import HAS_DISTOPIA - # hack to select backend with backend= kwarg. Note that # the cython parallel code (prange) in parallel.distances is # independent from the OpenMP code import importlib _distances = {} -_distances["serial"] = importlib.import_module( - ".c_distances", package="MDAnalysis.lib" -) +_distances["serial"] = importlib.import_module(".c_distances", package="MDAnalysis.lib") try: _distances["openmp"] = importlib.import_module( ".c_distances_openmp", package="MDAnalysis.lib" @@ -226,9 +224,7 @@ def _run( from .c_distances_openmp import OPENMP_ENABLED as USED_OPENMP -def _check_result_array( - result: Optional[npt.NDArray], shape: tuple -) -> npt.NDArray: +def _check_result_array(result: Optional[npt.NDArray], shape: tuple) -> npt.NDArray: """Check if the result array is ok to use. The `result` array must meet the following requirements: @@ -712,12 +708,8 @@ def _determine_method( return methods["nsgrid"] else: if box is None: - min_dim = np.array( - [reference.min(axis=0), configuration.min(axis=0)] - ) - max_dim = np.array( - [reference.max(axis=0), configuration.max(axis=0)] - ) + min_dim = np.array([reference.min(axis=0), configuration.min(axis=0)]) + max_dim = np.array([reference.max(axis=0), configuration.max(axis=0)]) size = max_dim.max(axis=0) - min_dim.min(axis=0) elif np.all(box[3:] == 90.0): size = box[:3] @@ -814,13 +806,9 @@ def _bruteforce_capped( distances = np.empty((0,), dtype=np.float64) if len(reference) > 0 and len(configuration) > 0: - _distances = distance_array( - reference, configuration, box=box, backend=backend - ) + _distances = distance_array(reference, configuration, box=box, backend=backend) if min_cutoff is not None: - mask = np.where( - (_distances <= max_cutoff) & (_distances > min_cutoff) - ) + mask = np.where((_distances <= max_cutoff) & (_distances > min_cutoff)) else: mask = np.where((_distances <= max_cutoff)) if mask[0].size > 0: @@ -1044,9 +1032,7 @@ def _nsgrid_capped( # Extra padding near the origin shiftref -= lmin - 0.1 * max_cutoff shiftconf -= lmin - 0.1 * max_cutoff - gridsearch = FastNS( - max_cutoff, shiftconf, box=pseudobox, pbc=False - ) + gridsearch = FastNS(max_cutoff, shiftconf, box=pseudobox, pbc=False) results = gridsearch.search(shiftref) else: gridsearch = FastNS(max_cutoff, configuration, box=box) diff --git a/package/MDAnalysis/lib/log.py b/package/MDAnalysis/lib/log.py index d63ec547828..d51f19f7440 100644 --- a/package/MDAnalysis/lib/log.py +++ b/package/MDAnalysis/lib/log.py @@ -84,6 +84,7 @@ .. autogenerated, see Online Docs """ + import sys import logging import re diff --git a/package/MDAnalysis/lib/mdamath.py b/package/MDAnalysis/lib/mdamath.py index cef449c8f20..ec99092598b 100644 --- a/package/MDAnalysis/lib/mdamath.py +++ b/package/MDAnalysis/lib/mdamath.py @@ -57,6 +57,7 @@ Unused function :func:`_angle()` has now been removed. """ + import numpy as np from ..exceptions import NoDataError @@ -163,9 +164,7 @@ def angle(a: npt.ArrayLike, b: npt.ArrayLike) -> float: return np.arccos(x) -def stp( - vec1: npt.ArrayLike, vec2: npt.ArrayLike, vec3: npt.ArrayLike -) -> float: +def stp(vec1: npt.ArrayLike, vec2: npt.ArrayLike, vec3: npt.ArrayLike) -> float: r"""Takes the scalar triple product of three vectors. Returns the volume *V* of the parallel epiped spanned by the three @@ -251,9 +250,7 @@ def sarrus_det(matrix: npt.NDArray) -> Union[float, npt.NDArray]: return _sarrus_det_multiple(m.reshape((-1, 3, 3))).reshape(shape[:-2]) -def triclinic_box( - x: npt.ArrayLike, y: npt.ArrayLike, z: npt.ArrayLike -) -> npt.NDArray: +def triclinic_box(x: npt.ArrayLike, y: npt.ArrayLike, z: npt.ArrayLike) -> npt.NDArray: """Convert the three triclinic box vectors to ``[lx, ly, lz, alpha, beta, gamma]``. @@ -368,9 +365,7 @@ def triclinic_vectors( dim = np.asarray(dimensions, dtype=np.float64) lx, ly, lz, alpha, beta, gamma = dim # Only positive edge lengths and angles in (0, 180) are allowed: - if not ( - np.all(dim > 0.0) and alpha < 180.0 and beta < 180.0 and gamma < 180.0 - ): + if not (np.all(dim > 0.0) and alpha < 180.0 and beta < 180.0 and gamma < 180.0): # invalid box, return zero vectors: box_matrix = np.zeros((3, 3), dtype=dtype) # detect orthogonal boxes: diff --git a/package/MDAnalysis/lib/picklable_file_io.py b/package/MDAnalysis/lib/picklable_file_io.py index f8050b14e51..3857360ddc2 100644 --- a/package/MDAnalysis/lib/picklable_file_io.py +++ b/package/MDAnalysis/lib/picklable_file_io.py @@ -52,6 +52,7 @@ .. versionadded:: 2.0.0 """ + import io import os @@ -460,9 +461,7 @@ def pickle_open(name, mode="rt"): .. versionadded:: 2.0.0 """ if mode not in {"r", "rt", "rb"}: - raise ValueError( - "Only read mode ('r', 'rt', 'rb') " "files can be pickled." - ) + raise ValueError("Only read mode ('r', 'rt', 'rb') " "files can be pickled.") name = os.fspath(name) raw = FileIOPicklable(name) if mode == "rb": @@ -533,9 +532,7 @@ def bz2_pickle_open(name, mode="rb"): .. versionadded:: 2.0.0 """ if mode not in {"r", "rt", "rb"}: - raise ValueError( - "Only read mode ('r', 'rt', 'rb') " "files can be pickled." - ) + raise ValueError("Only read mode ('r', 'rt', 'rb') " "files can be pickled.") bz_mode = mode.replace("t", "") binary_file = BZ2Picklable(name, bz_mode) if "t" in mode: @@ -606,9 +603,7 @@ def gzip_pickle_open(name, mode="rb"): .. versionadded:: 2.0.0 """ if mode not in {"r", "rt", "rb"}: - raise ValueError( - "Only read mode ('r', 'rt', 'rb') " "files can be pickled." - ) + raise ValueError("Only read mode ('r', 'rt', 'rb') " "files can be pickled.") gz_mode = mode.replace("t", "") binary_file = GzipPicklable(name, gz_mode) if "t" in mode: diff --git a/package/MDAnalysis/lib/pkdtree.py b/package/MDAnalysis/lib/pkdtree.py index 952b4672e32..b125a7a4787 100644 --- a/package/MDAnalysis/lib/pkdtree.py +++ b/package/MDAnalysis/lib/pkdtree.py @@ -62,9 +62,7 @@ class PeriodicKDTree(object): """ - def __init__( - self, box: Optional[npt.ArrayLike] = None, leafsize: int = 10 - ) -> None: + def __init__(self, box: Optional[npt.ArrayLike] = None, leafsize: int = 10) -> None: """ Parameters @@ -98,9 +96,7 @@ def pbc(self): """ return self.box is not None - def set_coords( - self, coords: npt.ArrayLike, cutoff: Optional[float] = None - ) -> None: + def set_coords(self, coords: npt.ArrayLike, cutoff: Optional[float] = None) -> None: """Constructs KDTree from the coordinates Wrapping of coordinates to the primary unit cell is enforced @@ -147,9 +143,7 @@ def set_coords( # Bring the coordinates in the central cell self.coords = apply_PBC(coords, self.box) # generate duplicate images - self.aug, self.mapping = augment_coordinates( - self.coords, self.box, cutoff - ) + self.aug, self.mapping = augment_coordinates(self.coords, self.box, cutoff) # Images + coords self.all_coords = np.concatenate([self.coords, self.aug]) self.ckdt = cKDTree(self.all_coords, leafsize=self.leafsize) @@ -157,8 +151,7 @@ def set_coords( # if cutoff distance is provided for non PBC calculations if cutoff is not None: raise RuntimeError( - "Donot provide cutoff distance for" - " non PBC aware calculations" + "Donot provide cutoff distance for" " non PBC aware calculations" ) self.coords = coords self.ckdt = cKDTree(self.coords, self.leafsize) @@ -189,13 +182,9 @@ def search(self, centers: npt.ArrayLike, radius: float) -> npt.NDArray: # Sanity check if self.pbc: if self.cutoff is None: - raise ValueError( - "Cutoff needs to be provided when working with PBC." - ) + raise ValueError("Cutoff needs to be provided when working with PBC.") if self.cutoff < radius: - raise RuntimeError( - "Set cutoff greater or equal to the radius." - ) + raise RuntimeError("Set cutoff greater or equal to the radius.") # Bring all query points to the central cell wrapped_centers = apply_PBC(centers, self.box) indices = list(self.ckdt.query_ball_point(wrapped_centers, radius)) @@ -243,23 +232,15 @@ def search_pairs(self, radius: float) -> npt.NDArray: if self.pbc: if self.cutoff is None: - raise ValueError( - "Cutoff needs to be provided when working with PBC." - ) + raise ValueError("Cutoff needs to be provided when working with PBC.") if self.cutoff < radius: - raise RuntimeError( - "Set cutoff greater or equal to the radius." - ) + raise RuntimeError("Set cutoff greater or equal to the radius.") pairs = np.array(list(self.ckdt.query_pairs(radius)), dtype=np.intp) if self.pbc: if len(pairs) > 1: - pairs[:, 0] = undo_augment( - pairs[:, 0], self.mapping, len(self.coords) - ) - pairs[:, 1] = undo_augment( - pairs[:, 1], self.mapping, len(self.coords) - ) + pairs[:, 0] = undo_augment(pairs[:, 0], self.mapping, len(self.coords)) + pairs[:, 1] = undo_augment(pairs[:, 1], self.mapping, len(self.coords)) if pairs.size > 0: # First sort the pairs then pick the unique pairs pairs = np.sort(pairs, axis=1) @@ -307,13 +288,9 @@ class initialization # Sanity check if self.pbc: if self.cutoff is None: - raise ValueError( - "Cutoff needs to be provided when working with PBC." - ) + raise ValueError("Cutoff needs to be provided when working with PBC.") if self.cutoff < radius: - raise RuntimeError( - "Set cutoff greater or equal to the radius." - ) + raise RuntimeError("Set cutoff greater or equal to the radius.") # Bring all query points to the central cell wrapped_centers = apply_PBC(centers, self.box) other_tree = cKDTree(wrapped_centers, leafsize=self.leafsize) @@ -323,9 +300,7 @@ class initialization dtype=np.intp, ) if pairs.size > 0: - pairs[:, 1] = undo_augment( - pairs[:, 1], self.mapping, len(self.coords) - ) + pairs[:, 1] = undo_augment(pairs[:, 1], self.mapping, len(self.coords)) else: other_tree = cKDTree(centers, leafsize=self.leafsize) pairs = other_tree.query_ball_tree(self.ckdt, radius) diff --git a/package/MDAnalysis/lib/transformations.py b/package/MDAnalysis/lib/transformations.py index 27e5f01db9f..627f09db76b 100644 --- a/package/MDAnalysis/lib/transformations.py +++ b/package/MDAnalysis/lib/transformations.py @@ -377,17 +377,11 @@ def rotation_from_matrix(matrix): # rotation angle depending on direction cosa = (np.trace(R33) - 1.0) / 2.0 if abs(direction[2]) > 1e-8: - sina = ( - R[1, 0] + (cosa - 1.0) * direction[0] * direction[1] - ) / direction[2] + sina = (R[1, 0] + (cosa - 1.0) * direction[0] * direction[1]) / direction[2] elif abs(direction[1]) > 1e-8: - sina = ( - R[0, 2] + (cosa - 1.0) * direction[0] * direction[2] - ) / direction[1] + sina = (R[0, 2] + (cosa - 1.0) * direction[0] * direction[2]) / direction[1] else: - sina = ( - R[2, 1] + (cosa - 1.0) * direction[1] * direction[2] - ) / direction[0] + sina = (R[2, 1] + (cosa - 1.0) * direction[1] * direction[2]) / direction[0] angle = math.atan2(sina, cosa) return angle, direction, point @@ -482,9 +476,7 @@ def scale_from_matrix(matrix): return factor, origin, direction -def projection_matrix( - point, normal, direction=None, perspective=None, pseudo=False -): +def projection_matrix(point, normal, direction=None, perspective=None, pseudo=False): """Return matrix to project onto plane defined by point and normal. Using either perspective point, projection direction, or none of both. @@ -536,9 +528,7 @@ def projection_matrix( M[3, 3] = np.dot(perspective, normal) elif direction is not None: # parallel projection - direction = np.array( - direction[:3], dtype=np.float64, copy=no_copy_shim - ) + direction = np.array(direction[:3], dtype=np.float64, copy=no_copy_shim) scale = np.dot(direction, normal) M[:3, :3] -= np.outer(direction, normal) / scale M[:3, 3] = direction * (np.dot(point, normal) / scale) @@ -614,9 +604,7 @@ def projection_from_matrix(matrix, pseudo=False): # perspective projection i = np.where(abs(np.real(l)) > 1e-8)[0] if not len(i): - raise ValueError( - "no eigenvector not corresponding to eigenvalue 0" - ) + raise ValueError("no eigenvector not corresponding to eigenvalue 0") point = np.real(V[:, i[-1]]).squeeze() point /= point[3] normal = -M[3, :3] @@ -742,9 +730,7 @@ def shear_from_matrix(matrix): l, V = np.linalg.eig(M33) i = np.where(abs(np.real(l) - 1.0) < 1e-4)[0] if len(i) < 2: - raise ValueError( - "no two linear independent eigenvectors found {0!s}".format(l) - ) + raise ValueError("no two linear independent eigenvectors found {0!s}".format(l)) V = np.real(V[:, i]).squeeze().T lenorm = -1.0 for i0, i1 in ((0, 1), (0, 2), (1, 2)): diff --git a/package/MDAnalysis/lib/util.py b/package/MDAnalysis/lib/util.py index 0f497892f13..da44ed4d230 100644 --- a/package/MDAnalysis/lib/util.py +++ b/package/MDAnalysis/lib/util.py @@ -193,6 +193,7 @@ underlying stream and ``NamedStream.close(force=True)`` will also close it. """ + import sys __docformat__ = "restructuredtext en" @@ -411,14 +412,10 @@ def anyopen(datasource, mode="rt", reset=True): if stream is None: raise IOError( errno.EIO, - "Cannot open file or stream in mode={mode!r}.".format( - **vars() - ), + "Cannot open file or stream in mode={mode!r}.".format(**vars()), repr(filename), ) - elif mode.startswith("w") or mode.startswith( - "a" - ): # append 'a' not tested... + elif mode.startswith("w") or mode.startswith("a"): # append 'a' not tested... if isstream(datasource): stream = datasource try: @@ -438,9 +435,7 @@ def anyopen(datasource, mode="rt", reset=True): if stream is None: raise IOError( errno.EIO, - "Cannot open file or stream in mode={mode!r}.".format( - **vars() - ), + "Cannot open file or stream in mode={mode!r}.".format(**vars()), repr(filename), ) else: @@ -705,9 +700,7 @@ def __init__(self, stream, filename, reset=True, close=False): # on __del__ and super on python 3. Let's warn the user and ensure the # class works normally. if isinstance(stream, NamedStream): - warnings.warn( - "Constructed NamedStream from a NamedStream", RuntimeWarning - ) + warnings.warn("Constructed NamedStream from a NamedStream", RuntimeWarning) stream = stream.stream self.stream = stream self.name = filename @@ -959,9 +952,7 @@ def realpath(*args): """ if None in args: return None - return os.path.realpath( - os.path.expanduser(os.path.expandvars(os.path.join(*args))) - ) + return os.path.realpath(os.path.expanduser(os.path.expandvars(os.path.join(*args)))) def get_ext(filename): @@ -1179,10 +1170,7 @@ def read(self, line): try: return self.convertor(line[self.start : self.stop]) except ValueError: - errmsg = ( - f"{self}: Failed to read&convert " - f"{line[self.start:self.stop]}" - ) + errmsg = f"{self}: Failed to read&convert " f"{line[self.start:self.stop]}" raise ValueError(errmsg) from None def __len__(self): @@ -1233,18 +1221,14 @@ def __init__(self, fmt): """ self.fmt = fmt.split(",") - descriptors = [ - self.parse_FORTRAN_format(descriptor) for descriptor in self.fmt - ] + descriptors = [self.parse_FORTRAN_format(descriptor) for descriptor in self.fmt] start = 0 self.entries = [] for d in descriptors: if d["format"] != "X": for x in range(d["repeat"]): stop = start + d["length"] - self.entries.append( - FixedcolumnEntry(start, stop, d["format"]) - ) + self.entries.append(FixedcolumnEntry(start, stop, d["format"])) start = stop else: start += d["totallength"] @@ -1315,9 +1299,7 @@ def parse_FORTRAN_format(self, edit_descriptor): m = _FORTRAN_format_pattern.match(edit_descriptor.upper()) if m is None: try: - m = _FORTRAN_format_pattern.match( - "1" + edit_descriptor.upper() - ) + m = _FORTRAN_format_pattern.match("1" + edit_descriptor.upper()) if m is None: raise ValueError # really no idea what the descriptor is supposed to mean except: @@ -1480,9 +1462,7 @@ def get_weights(atoms, weights): } #: translation table for 1-letter codes --> *canonical* 3-letter codes. #: The table is used for :func:`convert_aa_code`. -amino_acid_codes = { - one: three for three, one in canonical_inverse_aa_codes.items() -} +amino_acid_codes = {one: three for three, one in canonical_inverse_aa_codes.items()} #: non-default charge state amino acids or special charge state descriptions #: (Not fully synchronized with :class:`MDAnalysis.core.selection.ProteinSelection`.) # fmt: off @@ -1757,9 +1737,7 @@ def unique_rows(arr, return_index=False): ) return u.view(arr.dtype).reshape(-1, m), r_idx else: - u = np.unique( - arr.view(dtype=np.dtype([(str(i), arr.dtype) for i in range(m)])) - ) + u = np.unique(arr.view(dtype=np.dtype([(str(i), arr.dtype) for i in range(m)]))) return u.view(arr.dtype).reshape(-1, m) @@ -2026,9 +2004,7 @@ def wrapper(group, *args, **kwargs): if group.isunique or warn_if_not_unique.warned: return groupmethod(group, *args, **kwargs) # Otherwise, throw a DuplicateWarning and execute the method. - method_name = ".".join( - (group.__class__.__name__, groupmethod.__name__) - ) + method_name = ".".join((group.__class__.__name__, groupmethod.__name__)) # Try to get the group's variable name(s): caller_locals = inspect.currentframe().f_back.f_locals.items() group_names = [] @@ -2045,9 +2021,8 @@ def wrapper(group, *args, **kwargs): else: group_name = " a.k.a. ".join(sorted(group_names)) group_repr = repr(group) - msg = ( - "{}(): {} {} contains duplicates. Results might be biased!" - "".format(method_name, group_name, group_repr) + msg = "{}(): {} {} contains duplicates. Results might be biased!" "".format( + method_name, group_name, group_repr ) warnings.warn(message=msg, category=DuplicateWarning, stacklevel=2) warn_if_not_unique.warned = True @@ -2183,14 +2158,11 @@ def check_coords(*coord_names, **options): allow_single = options.get("allow_single", True) convert_single = options.get("convert_single", True) reduce_result_if_single = options.get("reduce_result_if_single", True) - check_lengths_match = options.get( - "check_lengths_match", len(coord_names) > 1 - ) + check_lengths_match = options.get("check_lengths_match", len(coord_names) > 1) allow_atomgroup = options.get("allow_atomgroup", False) if not coord_names: raise ValueError( - "Decorator check_coords() cannot be used without " - "positional arguments." + "Decorator check_coords() cannot be used without " "positional arguments." ) def check_coords_decorator(func): @@ -2236,9 +2208,7 @@ def _check_coords(coords, argname): raise ValueError(errmsg) if enforce_dtype: try: - coords = coords.astype( - np.float32, order="C", copy=enforce_copy - ) + coords = coords.astype(np.float32, order="C", copy=enforce_copy) except ValueError: errmsg = ( f"{fname}(): {argname}.dtype must be" @@ -2298,15 +2268,11 @@ def wrapper(*args, **kwargs): for name in coord_names: idx = posargnames.index(name) if idx < len(args): - args[idx], is_single, ncoord = _check_coords( - args[idx], name - ) + args[idx], is_single, ncoord = _check_coords(args[idx], name) all_single &= is_single ncoords.append(ncoord) else: - kwargs[name], is_single, ncoord = _check_coords( - kwargs[name], name - ) + kwargs[name], is_single, ncoord = _check_coords(kwargs[name], name) all_single &= is_single ncoords.append(ncoord) if check_lengths_match and ncoords: @@ -2394,8 +2360,7 @@ def __init__( self.new_name = new_name if release is None: raise ValueError( - "deprecate: provide release in which " - "feature was deprecated." + "deprecate: provide release in which " "feature was deprecated." ) self.release = str(release) self.remove = str(remove) if remove is not None else remove @@ -2454,15 +2419,11 @@ def newfunc(*args, **kwds): except TypeError: doc = "" - deprecation_text = dedent_docstring( - """\n\n + deprecation_text = dedent_docstring("""\n\n .. deprecated:: {0} {1} {2} - """.format( - release, message if message else depdoc, remove_text - ) - ) + """.format(release, message if message else depdoc, remove_text)) doc = "{0}\n\n{1}\n{2}\n".format(depdoc, doc, deprecation_text) diff --git a/package/MDAnalysis/selections/__init__.py b/package/MDAnalysis/selections/__init__.py index acb552b7cac..c99ce4dec3c 100644 --- a/package/MDAnalysis/selections/__init__.py +++ b/package/MDAnalysis/selections/__init__.py @@ -44,6 +44,7 @@ .. autofunction:: get_writer """ + import os.path from .. import _SELECTION_WRITERS diff --git a/package/MDAnalysis/selections/base.py b/package/MDAnalysis/selections/base.py index d9b49e516de..3db5aa89a32 100644 --- a/package/MDAnalysis/selections/base.py +++ b/package/MDAnalysis/selections/base.py @@ -37,6 +37,7 @@ .. autofunction:: join """ + import os.path from ..lib import util @@ -108,9 +109,7 @@ class SelectionWriterBase(metaclass=_Selectionmeta): commentfmt = None default_numterms = 8 - def __init__( - self, filename, mode="w", numterms=None, preamble=None, **kwargs - ): + def __init__(self, filename, mode="w", numterms=None, preamble=None, **kwargs): """Set up for writing to *filename*. Parameters @@ -130,9 +129,7 @@ def __init__( """ self.filename = util.filename(filename, ext=self.ext) if not mode in ("a", "w"): - raise ValueError( - "mode must be one of 'w', 'a', not {0!r}".format(mode) - ) + raise ValueError("mode must be one of 'w', 'a', not {0!r}".format(mode)) self.mode = mode self._current_mode = mode[0] if numterms is None or numterms < 0: @@ -212,9 +209,7 @@ def write(self, selection, number=None, name=None, frame=None, mode=None): out.write(" ".join(line)) if len(line) == step and not iatom + step == len(selection.atoms): out.write(" " + self.continuation + "\n") - out.write( - " " - ) # safe so that we don't have to put a space at the start of tail + out.write(" ") # safe so that we don't have to put a space at the start of tail self._write_tail(out) out.write("\n") # always terminate with newline diff --git a/package/MDAnalysis/selections/charmm.py b/package/MDAnalysis/selections/charmm.py index 62bbbd04975..bedb4d4d2f1 100644 --- a/package/MDAnalysis/selections/charmm.py +++ b/package/MDAnalysis/selections/charmm.py @@ -39,6 +39,7 @@ .. _CHARMM: http://www.charmm.org .. _CHARMM selection: http://www.charmm.org/documentation/c34b1/select.html """ + from . import base @@ -47,9 +48,7 @@ class SelectionWriter(base.SelectionWriterBase): ext = "str" continuation = "-" commentfmt = "! %s" - default_numterms = ( - 4 # be conservative because CHARMM only reads 72 columns - ) + default_numterms = 4 # be conservative because CHARMM only reads 72 columns def _translate(self, atoms, **kwargs): # CHARMM index is 1-based @@ -60,11 +59,7 @@ def _index(atom): def _write_head(self, out, **kwargs): out.write(self.comment("MDAnalysis CHARMM selection")) - out.write( - "DEFINE {name!s} SELECT ".format(**kwargs) - + self.continuation - + "\n" - ) + out.write("DEFINE {name!s} SELECT ".format(**kwargs) + self.continuation + "\n") def _write_tail(self, out, **kwargs): out.write("END") diff --git a/package/MDAnalysis/selections/gromacs.py b/package/MDAnalysis/selections/gromacs.py index 785bda76c73..3a622ea3dda 100644 --- a/package/MDAnalysis/selections/gromacs.py +++ b/package/MDAnalysis/selections/gromacs.py @@ -39,6 +39,7 @@ .. autoclass:: SelectionWriter :inherited-members: """ + from . import base diff --git a/package/MDAnalysis/selections/jmol.py b/package/MDAnalysis/selections/jmol.py index ed293668845..1927e178e66 100644 --- a/package/MDAnalysis/selections/jmol.py +++ b/package/MDAnalysis/selections/jmol.py @@ -39,6 +39,7 @@ .. _Jmol: http://wiki.jmol.org/index.php/Main_Page .. _Jmol selection: http://chemapps.stolaf.edu/jmol/docs/#define """ + from . import base diff --git a/package/MDAnalysis/selections/pymol.py b/package/MDAnalysis/selections/pymol.py index d528a1394b1..1951e81a1c9 100644 --- a/package/MDAnalysis/selections/pymol.py +++ b/package/MDAnalysis/selections/pymol.py @@ -40,6 +40,7 @@ .. autoclass:: SelectionWriter :inherited-members: """ + from . import base @@ -59,6 +60,4 @@ def _index(atom): def _write_head(self, out, **kwargs): out.write(self.comment("MDAnalysis PyMol selection")) - out.write( - "select {name!s}, ".format(**kwargs) + self.continuation + "\n" - ) + out.write("select {name!s}, ".format(**kwargs) + self.continuation + "\n") diff --git a/package/MDAnalysis/selections/vmd.py b/package/MDAnalysis/selections/vmd.py index 11081d6ebb1..6cd9c10fdf9 100644 --- a/package/MDAnalysis/selections/vmd.py +++ b/package/MDAnalysis/selections/vmd.py @@ -47,6 +47,7 @@ :inherited-members: """ + from . import base diff --git a/package/MDAnalysis/topology/CRDParser.py b/package/MDAnalysis/topology/CRDParser.py index c0322824baa..7ec4ebb5757 100644 --- a/package/MDAnalysis/topology/CRDParser.py +++ b/package/MDAnalysis/topology/CRDParser.py @@ -50,6 +50,7 @@ :inherited-members: """ + import numpy as np from ..lib.util import openany, FORTRANReader @@ -103,9 +104,7 @@ def parse(self, **kwargs): ---- Could use the resnum and temp factor better """ - extformat = FORTRANReader( - "2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10" - ) + extformat = FORTRANReader("2I10,2X,A8,2X,A8,3F20.10,2X,A8,2X,A8,F20.10") stdformat = FORTRANReader("2I5,1X,A4,1X,A4,3F10.5,1X,A4,1X,A4,F10.5") atomids = [] @@ -124,10 +123,7 @@ def parse(self, **kwargs): elif line.split()[-1] == "EXT" and int(line.split()[0]): r = extformat continue - elif ( - line.split()[0] == line.split()[-1] - and line.split()[0] != "*" - ): + elif line.split()[0] == line.split()[-1] and line.split()[0] != "*": r = stdformat continue # anything else should be an atom @@ -146,8 +142,7 @@ def parse(self, **kwargs): ) = r.read(line) except Exception: errmsg = ( - f"Check CRD format at line {linenum + 1}: " - f"{line.rstrip()}" + f"Check CRD format at line {linenum + 1}: " f"{line.rstrip()}" ) raise ValueError(errmsg) from None @@ -169,9 +164,7 @@ def parse(self, **kwargs): segids = np.array(segids, dtype=object) atom_residx, (res_resids, res_resnames, res_resnums, res_segids) = ( - change_squash( - (resids, resnames), (resids, resnames, resnums, segids) - ) + change_squash((resids, resnames), (resids, resnames, resnums, segids)) ) res_segidx, (seg_segids,) = change_squash((res_segids,), (res_segids,)) diff --git a/package/MDAnalysis/topology/DLPolyParser.py b/package/MDAnalysis/topology/DLPolyParser.py index 6c03ed62c2d..fc64122b012 100644 --- a/package/MDAnalysis/topology/DLPolyParser.py +++ b/package/MDAnalysis/topology/DLPolyParser.py @@ -47,6 +47,7 @@ """ + import numpy as np from .base import TopologyReaderBase diff --git a/package/MDAnalysis/topology/DMSParser.py b/package/MDAnalysis/topology/DMSParser.py index 691b47eed64..6832923ea24 100644 --- a/package/MDAnalysis/topology/DMSParser.py +++ b/package/MDAnalysis/topology/DMSParser.py @@ -40,6 +40,7 @@ :inherited-members: """ + import numpy as np import sqlite3 import os @@ -201,9 +202,7 @@ def dict_factory(cursor, row): topattrs.append(Resnames(res_resnames)) if any(res_segids) and not any(val is None for val in res_segids): - res_segidx, (res_segids,) = change_squash( - (res_segids,), (res_segids,) - ) + res_segidx, (res_segids,) = change_squash((res_segids,), (res_segids,)) uniq_seg = np.unique(res_segids) idx2seg = {idx: res_segids[idx] for idx in res_segidx} diff --git a/package/MDAnalysis/topology/FHIAIMSParser.py b/package/MDAnalysis/topology/FHIAIMSParser.py index c3aa80aced4..fd486c3ffab 100644 --- a/package/MDAnalysis/topology/FHIAIMSParser.py +++ b/package/MDAnalysis/topology/FHIAIMSParser.py @@ -45,6 +45,7 @@ :inherited-members: """ + import numpy as np from ..lib.util import openany diff --git a/package/MDAnalysis/topology/GMSParser.py b/package/MDAnalysis/topology/GMSParser.py index 41e85f73ec8..655323ac89c 100644 --- a/package/MDAnalysis/topology/GMSParser.py +++ b/package/MDAnalysis/topology/GMSParser.py @@ -45,6 +45,7 @@ :inherited-members: """ + import re import numpy as np @@ -100,9 +101,7 @@ def parse(self, **kwargs): line = inf.readline() if not line: raise EOFError - if re.match( - r"^\s+ATOM\s+ATOMIC\s+COORDINATES\s*\(BOHR\).*", line - ): + if re.match(r"^\s+ATOM\s+ATOMIC\s+COORDINATES\s*\(BOHR\).*", line): break line = inf.readline() # skip diff --git a/package/MDAnalysis/topology/GROParser.py b/package/MDAnalysis/topology/GROParser.py index dab8ef691cd..8e7327c6d7c 100644 --- a/package/MDAnalysis/topology/GROParser.py +++ b/package/MDAnalysis/topology/GROParser.py @@ -43,6 +43,7 @@ :inherited-members: """ + import numpy as np from ..lib.util import openany diff --git a/package/MDAnalysis/topology/GSDParser.py b/package/MDAnalysis/topology/GSDParser.py index 45f7e570b07..c7b9a486e0c 100644 --- a/package/MDAnalysis/topology/GSDParser.py +++ b/package/MDAnalysis/topology/GSDParser.py @@ -51,6 +51,7 @@ :inherited-members: """ + import os import numpy as np @@ -139,9 +140,7 @@ def parse(self, **kwargs): # set radii, masses, charges p = snap.particles - attrs["diameter"] = Radii( - np.array(p.diameter / 2.0, dtype=np.float32) - ) + attrs["diameter"] = Radii(np.array(p.diameter / 2.0, dtype=np.float32)) attrs["mass"] = Masses(np.array(p.mass, dtype=np.float64)) attrs["charge"] = Charges(np.array(p.charge, dtype=np.float32)) diff --git a/package/MDAnalysis/topology/HoomdXMLParser.py b/package/MDAnalysis/topology/HoomdXMLParser.py index 7b57bb59002..60131ef7de9 100644 --- a/package/MDAnalysis/topology/HoomdXMLParser.py +++ b/package/MDAnalysis/topology/HoomdXMLParser.py @@ -46,6 +46,7 @@ :inherited-members: """ + import xml.etree.ElementTree as ET import numpy as np diff --git a/package/MDAnalysis/topology/ITPParser.py b/package/MDAnalysis/topology/ITPParser.py index 1aa87b3864b..97aee1b252e 100644 --- a/package/MDAnalysis/topology/ITPParser.py +++ b/package/MDAnalysis/topology/ITPParser.py @@ -31,9 +31,9 @@ Any masses that are in the file will be read; any missing values will be guessed. Bonds, angles, dihedrals and impropers are also read from the file. -If an ITP file is passed without a ``[ molecules ]`` directive, passing -``infer_system=True`` (the default option) will create a Universe with -1 molecule of each defined ``moleculetype``. +If an ITP file is passed without a ``[ molecules ]`` directive, passing +``infer_system=True`` (the default option) will create a Universe with +1 molecule of each defined ``moleculetype``. If a ``[ molecules ]`` section is present, ``infer_system`` is ignored. If files are included with the `#include` directive, they will also be read. @@ -70,7 +70,7 @@ Preprocessor variables ---------------------- -ITP files are often defined with lines that depend on +ITP files are often defined with lines that depend on whether a keyword flag is given. For example, this modified TIP5P water file: .. code-block:: none @@ -98,8 +98,8 @@ #endif -Define these preprocessor variables by passing keyword arguments. Any arguments that you -pass in *override* any variables defined in the file. For example, the universe below +Define these preprocessor variables by passing keyword arguments. Any arguments that you +pass in *override* any variables defined in the file. For example, the universe below will have charges of 3 for the HW1 and HW2 atoms:: import MDAnalysis as mda @@ -127,6 +127,7 @@ :inherited-members: """ + from collections import defaultdict import os @@ -368,9 +369,7 @@ def parse_dihedrals(self, line): funct_values=(1, 3, 5, 8, 9, 10, 11), ) if not dih: - self.add_param( - line, self.impropers, n_funct=4, funct_values=(2, 4) - ) + self.add_param(line, self.impropers, n_funct=4, funct_values=(2, 4)) def parse_constraints(self, line): self.add_param(line, self.bonds, n_funct=2, funct_values=(1, 2)) @@ -407,9 +406,7 @@ def resolve_residue_attrs(self): self.resolved_residue_attrs = True - def shift_indices( - self, atomid=0, resid=0, molnum=0, cgnr=0, n_res=0, n_atoms=0 - ): + def shift_indices(self, atomid=0, resid=0, molnum=0, cgnr=0, n_res=0, n_atoms=0): """ Get attributes ready for adding onto a larger topology. @@ -577,9 +574,7 @@ def parse( self.parser = self.parse_molecules elif self.current_mol: - self.parser = self.current_mol.parsers.get( - section, self._pass - ) + self.parser = self.current_mol.parsers.get(section, self._pass) else: self.parser = self._pass @@ -599,22 +594,14 @@ def parse( if not all(self.charges): empty = self.charges == "" self.charges[empty] = [ - ( - self.atomtypes.get(x)["charge"] - if x in self.atomtypes.keys() - else "" - ) + (self.atomtypes.get(x)["charge"] if x in self.atomtypes.keys() else "") for x in self.types[empty] ] if not all(self.masses): empty = self.masses == "" self.masses[empty] = [ - ( - self.atomtypes.get(x)["mass"] - if x in self.atomtypes.keys() - else "" - ) + (self.atomtypes.get(x)["mass"] if x in self.atomtypes.keys() else "") for x in self.types[empty] ] @@ -634,15 +621,11 @@ def parse( empty = self.masses == "" self.masses[empty] = Masses.missing_value_label - attrs.append( - Masses(np.array(self.masses, dtype=np.float64), guessed=False) - ) + attrs.append(Masses(np.array(self.masses, dtype=np.float64), guessed=False)) self.elements = DefaultGuesser(None).guess_types(self.types) if all(e.capitalize() in SYMB2Z for e in self.elements): - attrs.append( - Elements(np.array(self.elements, dtype=object), guessed=True) - ) + attrs.append(Elements(np.array(self.elements, dtype=object), guessed=True)) warnings.warn( "The elements attribute has been populated by guessing " "elements from atom types. This behaviour has been " diff --git a/package/MDAnalysis/topology/LAMMPSParser.py b/package/MDAnalysis/topology/LAMMPSParser.py index 61404fbbe70..f5682e4b0a4 100644 --- a/package/MDAnalysis/topology/LAMMPSParser.py +++ b/package/MDAnalysis/topology/LAMMPSParser.py @@ -81,6 +81,7 @@ """ + import numpy as np import logging import string @@ -229,9 +230,7 @@ def grab_datafile(self): header[token] = line.split(token)[0] continue - sects = { - f[l]: f[l + 1 : starts[i + 1]] for i, l in enumerate(starts[:-1]) - } + sects = {f[l]: f[l + 1 : starts[i + 1]] for i, l in enumerate(starts[:-1])} return header, sects @@ -317,9 +316,7 @@ def parse(self, **kwargs): (Impropers, "Impropers", 4), ]: try: - type, sect = self._parse_bond_section( - sects[L], nentries, mapping - ) + type, sect = self._parse_bond_section(sects[L], nentries, mapping) except KeyError: type, sect = [], [] @@ -327,9 +324,7 @@ def parse(self, **kwargs): return top - def read_DATA_timestep( - self, n_atoms, TS_class, TS_kwargs, atom_style=None - ): + def read_DATA_timestep(self, n_atoms, TS_class, TS_kwargs, atom_style=None): """Read a DATA file and try and extract x, v, box. - positions @@ -362,9 +357,7 @@ def read_DATA_timestep( else: velocities = None - ts = TS_class.from_coordinates( - positions, velocities=velocities, **TS_kwargs - ) + ts = TS_class.from_coordinates(positions, velocities=velocities, **TS_kwargs) ts.dimensions = unitcell return ts @@ -451,9 +444,7 @@ def _parse_bond_section(self, datalines, nentries, mapping): for line in datalines: line = line.split() # map to 0 based int - section.append( - tuple([mapping[int(x)] for x in line[2 : 2 + nentries]]) - ) + section.append(tuple([mapping[int(x)] for x in line[2 : 2 + nentries]])) type.append(line[1]) return tuple(type), tuple(section) @@ -554,9 +545,7 @@ def _parse_atoms(self, datalines, massdict=None): attrs.append(Resnums(resids.copy())) attrs.append(Segids(np.array(["SYSTEM"], dtype=object))) - top = Topology( - n_atoms, n_residues, 1, attrs=attrs, atom_resindex=residx - ) + top = Topology(n_atoms, n_residues, 1, attrs=attrs, atom_resindex=residx) return top @@ -729,9 +718,7 @@ def parse(self, **kwargs): attrs.append(DUMP_HEADERS[key]["attr_class"](value[order])) attrs.append(Segids(np.array(["SYSTEM"], dtype=object))) - return Topology( - natoms, n_residues, 1, attrs=attrs, atom_resindex=residx - ) + return Topology(natoms, n_residues, 1, attrs=attrs, atom_resindex=residx) @functools.total_ordering diff --git a/package/MDAnalysis/topology/MMTFParser.py b/package/MDAnalysis/topology/MMTFParser.py index 38711115bc0..87829f7830d 100644 --- a/package/MDAnalysis/topology/MMTFParser.py +++ b/package/MDAnalysis/topology/MMTFParser.py @@ -78,6 +78,7 @@ .. _Macromolecular Transmission Format (MMTF) format: https://www.rcsb.org/news/feature/65a1af31c76ca3abcc925d0c """ + from collections import defaultdict import mmtf import numpy as np @@ -204,12 +205,7 @@ def iter_atoms(field): attrs.append(Atomids(np.arange(natoms), guessed=True)) if mtop.alt_loc_list: attrs.append( - AltLocs( - [ - val.replace("\x00", "").strip() - for val in mtop.alt_loc_list - ] - ) + AltLocs([val.replace("\x00", "").strip() for val in mtop.alt_loc_list]) ) else: attrs.append(AltLocs([""] * natoms)) @@ -234,12 +230,7 @@ def iter_atoms(field): # mmtf empty icode is '\x00' rather than '' if mtop.ins_code_list: attrs.append( - ICodes( - [ - val.replace("\x00", "").strip() - for val in mtop.ins_code_list - ] - ) + ICodes([val.replace("\x00", "").strip() for val in mtop.ins_code_list]) ) else: attrs.append(ICodes([""] * nresidues)) @@ -286,9 +277,7 @@ def iter_atoms(field): offset += groupID_2_natoms[gtype] # add inter group bonds if not mtop.bond_atom_list is None: # optional field - for x, y in zip( - mtop.bond_atom_list[1::2], mtop.bond_atom_list[::2] - ): + for x, y in zip(mtop.bond_atom_list[1::2], mtop.bond_atom_list[::2]): if x > y: x, y = y, x bonds.append((x, y)) diff --git a/package/MDAnalysis/topology/MOL2Parser.py b/package/MDAnalysis/topology/MOL2Parser.py index 114633c0c41..5c31749b2b4 100644 --- a/package/MDAnalysis/topology/MOL2Parser.py +++ b/package/MDAnalysis/topology/MOL2Parser.py @@ -41,6 +41,7 @@ :inherited-members: """ + import os import numpy as np @@ -197,9 +198,7 @@ def parse(self, **kwargs): for a in atom_lines: columns = a.split() if len(columns) >= 9: - aid, name, x, y, z, atom_type, resid, resname, charge = ( - columns[:9] - ) + aid, name, x, y, z, atom_type, resid, resname, charge = columns[:9] elif len(columns) < 6: raise ValueError( f"The @ATOM block in mol2 file" @@ -305,8 +304,6 @@ def parse(self, **kwargs): bonds.append(bond) attrs.append(Bonds(bonds, order=bondorder)) - top = Topology( - n_atoms, n_residues, 1, attrs=attrs, atom_resindex=residx - ) + top = Topology(n_atoms, n_residues, 1, attrs=attrs, atom_resindex=residx) return top diff --git a/package/MDAnalysis/topology/PDBParser.py b/package/MDAnalysis/topology/PDBParser.py index b168b0a67ae..0fb2df4b63f 100644 --- a/package/MDAnalysis/topology/PDBParser.py +++ b/package/MDAnalysis/topology/PDBParser.py @@ -65,6 +65,7 @@ :inherited-members: """ + import numpy as np import warnings import logging @@ -149,16 +150,22 @@ def hy36decode(width, s): int Base-10 integer corresponding to hybrid36. """ - if (len(s) == width): + if len(s) == width: f = s[0] - if (f == "-" or f == " " or f.isdigit()): + if f == "-" or f == " " or f.isdigit(): return int(s) - elif (f in DIGITS_UPPER_VALUES): - return decode_pure(digits_values=DIGITS_UPPER_VALUES, - s=s) - 10 * 36 ** (width - 1) + 10 ** width - elif (f in DIGITS_LOWER_VALUES): - return decode_pure(digits_values=DIGITS_LOWER_VALUES, - s=s) + 16 * 36 ** (width - 1) + 10 ** width + elif f in DIGITS_UPPER_VALUES: + return ( + decode_pure(digits_values=DIGITS_UPPER_VALUES, s=s) + - 10 * 36 ** (width - 1) + + 10**width + ) + elif f in DIGITS_LOWER_VALUES: + return ( + decode_pure(digits_values=DIGITS_LOWER_VALUES, s=s) + + 16 * 36 ** (width - 1) + + 10**width + ) raise ValueError("invalid number literal.") @@ -217,7 +224,8 @@ class PDBParser(TopologyReaderBase): be generated if the segids is not present or if the chainids are not completely equal to segids. """ - format = ['PDB', 'ENT'] + + format = ["PDB", "ENT"] def parse(self, **kwargs): """Parse atom information from PDB file @@ -231,11 +239,11 @@ def parse(self, **kwargs): try: bonds = self._parsebonds(top.ids.values) except AttributeError: - warnings.warn("Invalid atom serials were present, " - "bonds will not be parsed") + warnings.warn( + "Invalid atom serials were present, " "bonds will not be parsed" + ) except RuntimeError: - warnings.warn("CONECT records was corrupt, " - "bonds will not be parsed") + warnings.warn("CONECT records was corrupt, " "bonds will not be parsed") else: # Issue 2832: don't append Bonds if there are no bonds if bonds: @@ -268,9 +276,9 @@ def _parseatoms(self, **kwargs): line = line.strip() # Remove extra spaces if not line: # Skip line if empty continue - if line.startswith('END'): + if line.startswith("END"): break - if not line.startswith(('ATOM', 'HETATM')): + if not line.startswith(("ATOM", "HETATM")): continue record_types.append(line[:6].strip()) @@ -306,8 +314,9 @@ def _parseatoms(self, **kwargs): resid += 10000 resid_prev = resid except ValueError: - warnings.warn("PDB file is missing resid information. " - "Defaulted to '1'") + warnings.warn( + "PDB file is missing resid information. " "Defaulted to '1'" + ) resid = 1 finally: resids.append(resid) @@ -320,8 +329,9 @@ def _parseatoms(self, **kwargs): # Warn about wrapped serials if self._wrapped_serials: - warnings.warn("Serial numbers went over 100,000. " - "Higher serials have been guessed") + warnings.warn( + "Serial numbers went over 100,000. " "Higher serials have been guessed" + ) # If segids is not equal to chainids, warn the user if any([a != b for a, b in zip(segids, chainids)]): @@ -329,14 +339,17 @@ def _parseatoms(self, **kwargs): # If segids not present, try to use chainids if not any(segids): - logger.info("Setting segids from chainIDs because no segids " - "found in the PDB file.") + logger.info( + "Setting segids from chainIDs because no segids " + "found in the PDB file." + ) segids = chainids # If force_chainids_to_segids is set, use chainids as segids if kwargs.get("force_chainids_to_segids", False): - logger.info("force_chainids_to_segids is set. " - "Using chain IDs as segment IDs.") + logger.info( + "force_chainids_to_segids is set. " "Using chain IDs as segment IDs." + ) segids = chainids n_atoms = len(serials) @@ -344,13 +357,13 @@ def _parseatoms(self, **kwargs): attrs = [] # Make Atom TopologyAttrs for vals, Attr, dtype in ( - (names, Atomnames, object), - (altlocs, AltLocs, object), - (chainids, ChainIDs, object), - (record_types, RecordTypes, object), - (serials, Atomids, np.int32), - (tempfactors, Tempfactors, np.float32), - (occupancies, Occupancies, np.float32), + (names, Atomnames, object), + (altlocs, AltLocs, object), + (chainids, ChainIDs, object), + (record_types, RecordTypes, object), + (serials, Atomids, np.int32), + (tempfactors, Tempfactors, np.float32), + (occupancies, Occupancies, np.float32), ): attrs.append(Attr(np.array(vals, dtype=dtype))) # OPT: We do this check twice, maybe could refactor to avoid this @@ -364,41 +377,47 @@ def _parseatoms(self, **kwargs): if elem.capitalize() in SYMB2Z: validated_elements.append(elem.capitalize()) else: - wmsg = (f"Unknown element {elem} found for some atoms. " - f"These have been given an empty element record. " - f"If needed they can be guessed using " - f"universe.guess_TopologyAttrs(context='default'," - " to_guess=['elements']).") + wmsg = ( + f"Unknown element {elem} found for some atoms. " + f"These have been given an empty element record. " + f"If needed they can be guessed using " + f"universe.guess_TopologyAttrs(context='default'," + " to_guess=['elements'])." + ) warnings.warn(wmsg) - validated_elements.append('') + validated_elements.append("") attrs.append(Elements(np.array(validated_elements, dtype=object))) else: - warnings.warn("Element information is missing, elements attribute " - "will not be populated. If needed these can be" - " guessed using universe.guess_TopologyAttrs(" - "context='default', to_guess=['elements']).") + warnings.warn( + "Element information is missing, elements attribute " + "will not be populated. If needed these can be" + " guessed using universe.guess_TopologyAttrs(" + "context='default', to_guess=['elements'])." + ) if any(formalcharges): try: for i, entry in enumerate(formalcharges): - if not entry == '': - if entry == '0': + if not entry == "": + if entry == "0": # Technically a lack of charge shouldn't be in the # PDB but MDA has a few files that specifically # have 0 entries, indicating that some folks # interpret 0 as an allowed entry formalcharges[i] = 0 - elif ('+' in entry) or ('-' in entry): + elif ("+" in entry) or ("-" in entry): formalcharges[i] = int(entry[::-1]) else: raise ValueError else: formalcharges[i] = 0 except ValueError: - wmsg = (f"Unknown entry {entry} encountered in formal charge " - "field. This likely indicates that the PDB file is " - "not fully standard compliant. The formalcharges " - "attribute will not be populated.") + wmsg = ( + f"Unknown entry {entry} encountered in formal charge " + "field. This likely indicates that the PDB file is " + "not fully standard compliant. The formalcharges " + "attribute will not be populated." + ) warnings.warn(wmsg) else: attrs.append(FormalCharges(np.array(formalcharges, dtype=int))) @@ -406,38 +425,45 @@ def _parseatoms(self, **kwargs): # Residue level stuff from here resids = np.array(resids, dtype=np.int32) resnames = np.array(resnames, dtype=object) - if self.format == 'XPDB': # XPDB doesn't have icodes - icodes = [''] * n_atoms + if self.format == "XPDB": # XPDB doesn't have icodes + icodes = [""] * n_atoms icodes = np.array(icodes, dtype=object) resnums = resids.copy() segids = np.array(segids, dtype=object) residx, (resids, resnames, icodes, resnums, segids) = change_squash( - (resids, resnames, icodes, segids), (resids, resnames, icodes, resnums, segids)) + (resids, resnames, icodes, segids), + (resids, resnames, icodes, resnums, segids), + ) n_residues = len(resids) attrs.append(Resnums(resnums)) attrs.append(Resids(resids)) attrs.append(ICodes(icodes)) attrs.append(Resnames(resnames)) - if ( - kwargs.get("force_chainids_to_segids", False) or - (any(segids) and not any(val is None for val in segids)) + if kwargs.get("force_chainids_to_segids", False) or ( + any(segids) and not any(val is None for val in segids) ): segidx, (segids,) = change_squash((segids,), (segids,)) n_segments = len(segids) attrs.append(Segids(segids)) else: n_segments = 1 - attrs.append(Segids(np.array(['SYSTEM'], dtype=object))) + attrs.append(Segids(np.array(["SYSTEM"], dtype=object))) segidx = None - logger.info("Segment/chain ID is empty, " - "setting segids to default value 'SYSTEM'.") - - top = Topology(n_atoms, n_residues, n_segments, - attrs=attrs, - atom_resindex=residx, - residue_segindex=segidx) + logger.info( + "Segment/chain ID is empty, " + "setting segids to default value 'SYSTEM'." + ) + + top = Topology( + n_atoms, + n_residues, + n_segments, + attrs=attrs, + atom_resindex=residx, + residue_segindex=segidx, + ) return top @@ -450,8 +476,9 @@ def _parsebonds(self, serials): # If the serials wrapped, this won't work if self._wrapped_serials: - warnings.warn("Invalid atom serials were present, bonds will not" - " be parsed") + warnings.warn( + "Invalid atom serials were present, bonds will not" " be parsed" + ) raise AttributeError # gets caught in parse # Mapping between the atom array indicies a.index and atom ids @@ -471,7 +498,8 @@ def _parsebonds(self, serials): # Ignore these as they are not real atoms warnings.warn( "PDB file contained CONECT record to TER entry. " - "These are not included in bonds.") + "These are not included in bonds." + ) else: bonds.add(bond) @@ -505,13 +533,14 @@ def _parse_conect(conect): try: if len(conect[11:]) % n_bond_atoms != 0: - raise RuntimeError("Bond atoms aren't aligned proberly for CONECT " - "record: {}".format(conect)) + raise RuntimeError( + "Bond atoms aren't aligned proberly for CONECT " + "record: {}".format(conect) + ) except ZeroDivisionError: # Conect record with only one entry (CONECT A\n) warnings.warn("Found CONECT record with single entry, ignoring this") return atom_id, [] # return empty list to allow iteration over nothing - bond_atoms = (int(conect[11 + i * 5: 16 + i * 5]) for i in - range(n_bond_atoms)) + bond_atoms = (int(conect[11 + i * 5 : 16 + i * 5]) for i in range(n_bond_atoms)) return atom_id, bond_atoms diff --git a/package/MDAnalysis/topology/PDBQTParser.py b/package/MDAnalysis/topology/PDBQTParser.py index 4591e46529e..de41e4baffd 100644 --- a/package/MDAnalysis/topology/PDBQTParser.py +++ b/package/MDAnalysis/topology/PDBQTParser.py @@ -57,10 +57,11 @@ .. _PDBQT: - https://autodock.scripps.edu/wp-content/uploads/sites/56/2021/10/AutoDock4.2.6_UserGuide.pdf + https://autodock.scripps.edu/wp-content/uploads/sites/56/2021/10/AutoDock4.2.6_UserGuide.pdf .. _AutoDock: http://autodock.scripps.edu/ """ + import numpy as np from ..lib import util diff --git a/package/MDAnalysis/topology/PQRParser.py b/package/MDAnalysis/topology/PQRParser.py index 54f3b81b057..dbe28de856e 100644 --- a/package/MDAnalysis/topology/PQRParser.py +++ b/package/MDAnalysis/topology/PQRParser.py @@ -47,6 +47,7 @@ .. _PDB: http://www.wwpdb.org/documentation/file-format """ + import numpy as np from ..lib.util import openany diff --git a/package/MDAnalysis/topology/PSFParser.py b/package/MDAnalysis/topology/PSFParser.py index 531c2ae592d..cdd7c19f3e4 100644 --- a/package/MDAnalysis/topology/PSFParser.py +++ b/package/MDAnalysis/topology/PSFParser.py @@ -43,6 +43,7 @@ :inherited-members: """ + import logging import functools from math import ceil @@ -132,8 +133,7 @@ def parse(self, **kwargs): for _ in range(int(title[0])): next(psffile) logger.debug( - "PSF file {0}: format {1}" - "".format(self.filename, self._format) + "PSF file {0}: format {1}" "".format(self.filename, self._format) ) # Atoms first and mandatory @@ -178,9 +178,7 @@ def _parse_sec(self, psffile, section_info): sect_type = header[1].strip("!:") # Make sure the section type matches the desc if not sect_type == desc: - err = "Expected section {0} but found {1}" "".format( - desc, sect_type - ) + err = "Expected section {0} but found {1}" "".format(desc, sect_type) logger.error(err) raise ValueError(err) # Now figure out how many lines to read @@ -319,8 +317,7 @@ def _parseatoms(self, lines, atoms_per, numlines): " continuing with fingers crossed!" ) logger.debug( - "First NAMD-type line: {0}: {1}" - "".format(i, line.rstrip()) + "First NAMD-type line: {0}: {1}" "".format(i, line.rstrip()) ) atomids[i] = vals[0] diff --git a/package/MDAnalysis/topology/TOPParser.py b/package/MDAnalysis/topology/TOPParser.py index ba61bea0b06..0bc5612a048 100644 --- a/package/MDAnalysis/topology/TOPParser.py +++ b/package/MDAnalysis/topology/TOPParser.py @@ -88,6 +88,7 @@ :inherited-members: """ + import numpy as np import itertools @@ -256,9 +257,9 @@ def parse(self, **kwargs): while next_section is not None: try: - (num_per_record, per_line, func, name, sect_num) = ( - sections[next_section] - ) + num_per_record, per_line, func, name, sect_num = sections[ + next_section + ] except KeyError: def next_getter(): @@ -305,12 +306,7 @@ def next_getter(): # Deal with recreating bonds and angle records here attrs["bonds"] = Bonds( - [ - i - for i in itertools.chain( - attrs.pop("bonda"), attrs.pop("bondh") - ) - ] + [i for i in itertools.chain(attrs.pop("bonda"), attrs.pop("bondh"))] ) attrs["angles"] = Angles( @@ -349,9 +345,7 @@ def next_getter(): # Amber's 'RESIDUE_CHAINID' is a by-residue attribute, turn it into # a by-atom attribute when present. See PR #4007. if "segids" in attrs and len(attrs["segids"]) == n_res: - segidx, (segids,) = change_squash( - (attrs["segids"],), (attrs["segids"],) - ) + segidx, (segids,) = change_squash((attrs["segids"],), (attrs["segids"],)) chainids = [attrs["segids"][r] for r in residx] attrs["segids"] = Segids(segids) @@ -594,8 +588,7 @@ def parse_chunks(self, data, chunksize): into chunks of size num_per_record, and only extract the atom ids. """ vals = [ - tuple(data[x : x + chunksize - 1]) - for x in range(0, len(data), chunksize) + tuple(data[x : x + chunksize - 1]) for x in range(0, len(data), chunksize) ] return vals diff --git a/package/MDAnalysis/topology/TPRParser.py b/package/MDAnalysis/topology/TPRParser.py index 09cbdcdf6e4..deea28325d5 100644 --- a/package/MDAnalysis/topology/TPRParser.py +++ b/package/MDAnalysis/topology/TPRParser.py @@ -160,11 +160,12 @@ topology. .. versionchanged:: 2.7.0 - If the TPR molblock is named "Protein_chain_XXX" then we assume that XXX is + If the TPR molblock is named "Protein_chain_XXX" then we assume that XXX is describing the chain of a protein (in the sense of the PDB chainID) and set the topology attribute `chainID` to "XXX". In all other cases, the chainID remains the full molblock name. The `segID` is never changed. """ + __author__ = "Zhuyi Xue" __copyright__ = "GNU Public Licence, v2" @@ -243,9 +244,7 @@ def parse(self, tpr_resid_from_one=True, **kwargs): if state_ngtc > 0: if th.fver < 69: # redundancy due to different versions tpr_utils.ndo_real(data, state_ngtc) - tpr_utils.ndo_real( - data, state_ngtc - ) # relevant to Berendsen tcoupl_lambda + tpr_utils.ndo_real(data, state_ngtc) # relevant to Berendsen tcoupl_lambda if th.bTop: tpr_top = tpr_utils.do_mtop( diff --git a/package/MDAnalysis/topology/XYZParser.py b/package/MDAnalysis/topology/XYZParser.py index 45683a1a714..46be0abd3f0 100644 --- a/package/MDAnalysis/topology/XYZParser.py +++ b/package/MDAnalysis/topology/XYZParser.py @@ -38,6 +38,7 @@ :members: """ + import numpy as np from ..lib.util import openany diff --git a/package/MDAnalysis/topology/__init__.py b/package/MDAnalysis/topology/__init__.py index 945deaf4369..5adc807adc6 100644 --- a/package/MDAnalysis/topology/__init__.py +++ b/package/MDAnalysis/topology/__init__.py @@ -311,10 +311,24 @@ """ -__all__ = ['core', 'PSFParser', 'PDBParser', 'PQRParser', 'GROParser', - 'CRDParser', 'TOPParser', 'PDBQTParser', 'TPRParser', - 'LAMMPSParser', 'XYZParser', 'GMSParser', 'DLPolyParser', - 'HoomdXMLParser','GSDParser', 'ITPParser'] +__all__ = [ + "core", + "PSFParser", + "PDBParser", + "PQRParser", + "GROParser", + "CRDParser", + "TOPParser", + "PDBQTParser", + "TPRParser", + "LAMMPSParser", + "XYZParser", + "GMSParser", + "DLPolyParser", + "HoomdXMLParser", + "GSDParser", + "ITPParser", +] from . import core from . import PSFParser diff --git a/package/MDAnalysis/topology/base.py b/package/MDAnalysis/topology/base.py index e07c0257eaa..530cd0f5a5a 100644 --- a/package/MDAnalysis/topology/base.py +++ b/package/MDAnalysis/topology/base.py @@ -36,6 +36,7 @@ :inherited-members: """ + from functools import reduce import itertools @@ -90,9 +91,7 @@ def __init__(cls, name, bases, classdict): _PARSERS[fmt_name] = cls if "_format_hint" in classdict: - _PARSER_HINTS[fmt_name] = classdict[ - "_format_hint" - ].__func__ + _PARSER_HINTS[fmt_name] = classdict["_format_hint"].__func__ class TopologyReaderBase(IOBase, metaclass=_Topologymeta): @@ -185,16 +184,12 @@ def change_squash(criteria, to_squash): def get_borders(*arrays): """Generator of indices to slice arrays when they change""" - borders = np.nonzero( - reduce(np.logical_or, (a[:-1] != a[1:] for a in arrays)) - ) + borders = np.nonzero(reduce(np.logical_or, (a[:-1] != a[1:] for a in arrays))) # Add Nones so we can slice from start to end return [None] + list(borders[0] + 1) + [None] l0 = len(criteria[0]) - if not all( - len(other) == l0 for other in itertools.chain(criteria[1:], to_squash) - ): + if not all(len(other) == l0 for other in itertools.chain(criteria[1:], to_squash)): raise ValueError("All arrays must be equally sized") # 1) Detect where resids change diff --git a/package/MDAnalysis/topology/guessers.py b/package/MDAnalysis/topology/guessers.py index 6ae316cd026..424c2b03059 100644 --- a/package/MDAnalysis/topology/guessers.py +++ b/package/MDAnalysis/topology/guessers.py @@ -26,7 +26,7 @@ .. deprecated:: 2.8.0 The :mod:`MDAnalysis.topology.guessers` module will be removed in release 3.0.0. - It is deprecated in favor of the new Guessers API. See + It is deprecated in favor of the new Guessers API. See :mod:`MDAnalysis.guesser.default_guesser` for more details. In general `guess_atom_X` returns the guessed value for a single value, @@ -101,6 +101,7 @@ .. _user guide: https://www.mdanalysis.org/UserGuide/examples/constructing_universe.html#Adding-topology-attributes """ + import numpy as np import warnings import re @@ -109,7 +110,6 @@ from MDAnalysis.guesser import tables from MDAnalysis.lib.util import deprecate - deprecation_msg = ( "MDAnalysis.topology.guessers is deprecated in favour of " "the new Guessers API. " @@ -180,9 +180,7 @@ def guess_types(atom_names): ------- atom_types : np.ndarray dtype object """ - return np.array( - [guess_atom_element(name) for name in atom_names], dtype=object - ) + return np.array([guess_atom_element(name) for name in atom_names], dtype=object) @deprecate(release="2.8.0", remove="3.0.0", message=deprecation_msg) @@ -426,9 +424,7 @@ def guess_dihedrals(angles): a_tup = tuple([a.index for a in b]) # angle as tuple of numbers # if searching with b[0], want tuple of (b[2], b[1], b[0], +new) # search the first and last atom of each angle - for atom, prefix in zip( - [b.atoms[0], b.atoms[-1]], [a_tup[::-1], a_tup] - ): + for atom, prefix in zip([b.atoms[0], b.atoms[-1]], [a_tup[::-1], a_tup]): for other_b in atom.bonds: if not other_b.partner(atom) in b: third_a = other_b.partner(atom) diff --git a/package/MDAnalysis/topology/tpr/__init__.py b/package/MDAnalysis/topology/tpr/__init__.py index 19d53190853..aa5b8fc8a02 100644 --- a/package/MDAnalysis/topology/tpr/__init__.py +++ b/package/MDAnalysis/topology/tpr/__init__.py @@ -38,6 +38,7 @@ * :mod:`MDAnalysis.topology.tpr.utils` """ + from .setting import SUPPORTED_VERSIONS __all__ = ["obj", "setting", "utils"] diff --git a/package/MDAnalysis/topology/tpr/obj.py b/package/MDAnalysis/topology/tpr/obj.py index 93c5a83ee75..7c1402fa0c4 100644 --- a/package/MDAnalysis/topology/tpr/obj.py +++ b/package/MDAnalysis/topology/tpr/obj.py @@ -31,6 +31,7 @@ =================================== """ + from collections import namedtuple from ...guesser.tables import Z2SYMB @@ -139,9 +140,7 @@ def remap_impr(self, atom_start_ndx): class AtomKind(object): - def __init__( - self, id, name, type, resid, resname, mass, charge, atomic_number - ): + def __init__(self, id, name, type, resid, resname, mass, charge, atomic_number): # id is only within the scope of a single molecule, not the whole system self.id = id self.name = name diff --git a/package/MDAnalysis/topology/tpr/utils.py b/package/MDAnalysis/topology/tpr/utils.py index a6158333de2..aca685e3dd8 100644 --- a/package/MDAnalysis/topology/tpr/utils.py +++ b/package/MDAnalysis/topology/tpr/utils.py @@ -79,6 +79,7 @@ class TPXUnpacker(xdrlib.Unpacker): """ Extend the standard XDR unpacker for the specificity of TPX files. """ + def __init__(self, data): super().__init__(data) self._buf = self.get_buffer() @@ -103,10 +104,10 @@ def _unpack_value(self, item_size, struct_template): return struct.unpack(struct_template, content)[0] def unpack_int64(self): - return self._unpack_value(8, '>q') + return self._unpack_value(8, ">q") def unpack_uint64(self): - return self._unpack_value(8, '>Q') + return self._unpack_value(8, ">Q") def unpack_ushort(self): return self.unpack_uint() @@ -114,7 +115,7 @@ def unpack_ushort(self): def unpack_uchar(self): # TPX files prior to gromacs 2020 (tpx version < 119) use unsigned ints # (4 bytes) instead of unsigned chars. - return self._unpack_value(4, '>I') + return self._unpack_value(4, ">I") def do_string(self): """ @@ -138,11 +139,12 @@ class TPXUnpacker2020(TPXUnpacker): gromacs 2020, changes le meaning of some types in the file body (the header keep using the previous implementation of the serializer). """ + @classmethod def from_unpacker(cls, unpacker): new_unpacker = cls(unpacker.get_buffer()) new_unpacker._pos = unpacker.get_position() - if hasattr(unpacker, 'unpack_real'): + if hasattr(unpacker, "unpack_real"): if unpacker.unpack_real == unpacker.unpack_float: new_unpacker.unpack_real = new_unpacker.unpack_float elif unpacker.unpack_real == unpacker.unpack_double: @@ -153,7 +155,7 @@ def from_unpacker(cls, unpacker): def unpack_fstring(self, n): if n < 0: - raise ValueError('Size of fstring cannot be negative.') + raise ValueError("Size of fstring cannot be negative.") start_position = self._pos end_position = self._pos = start_position + n if end_position > len(self._buf): @@ -164,12 +166,12 @@ def unpack_fstring(self, n): def unpack_ushort(self): # The InMemorySerializer implements ushort according to the XDR standard # on the contrary to the IO serializer. - return self._unpack_value(2, '>H') + return self._unpack_value(2, ">H") def unpack_uchar(self): # The InMemorySerializer implements uchar according to the XDR standard # on the contrary to the IO serializer. - return self._unpack_value(1, '>B') + return self._unpack_value(1, ">B") def do_string(self): """ @@ -221,12 +223,11 @@ def define_unpack_real(prec, data): def read_tpxheader(data): - """this function is now compatible with do_tpxheader in tpxio.cpp - """ + """this function is now compatible with do_tpxheader in tpxio.cpp""" # Last compatibility check with gromacs-2016 ver_str = data.do_string() # version string e.g. VERSION 4.0.5 - if not ver_str.startswith(b'VERSION'): - raise ValueError('Input does not look like a TPR file.') + if not ver_str.startswith(b"VERSION"): + raise ValueError("Input does not look like a TPR file.") precision = data.unpack_int() # e.g. 4 define_unpack_real(precision, data) fileVersion = data.unpack_int() # version of tpx file @@ -239,7 +240,9 @@ def read_tpxheader(data): data.unpack_int() # the value is 8, but haven't found the file_tag = data.do_string() - fileGeneration = data.unpack_int() if fileVersion >= 26 else 0 # generation of tpx file, e.g. 17 + fileGeneration = ( + data.unpack_int() if fileVersion >= 26 else 0 + ) # generation of tpx file, e.g. 17 # Versions before 77 don't have the tag, set it to TPX_TAG_RELEASE file_tag # file_tag is used for comparing with tpx_tag. Only tpr files with a @@ -249,7 +252,9 @@ def read_tpxheader(data): file_tag = data.do_string() if fileVersion >= 81 else setting.TPX_TAG_RELEASE natoms = data.unpack_int() # total number of atoms - ngtc = data.unpack_int() if fileVersion >= 28 else 0 # number of groups for T-coupling + ngtc = ( + data.unpack_int() if fileVersion >= 28 else 0 + ) # number of groups for T-coupling if fileVersion < 62: # not sure what these two are for. @@ -272,9 +277,24 @@ def read_tpxheader(data): if fileVersion >= setting.tpxv_AddSizeField and fileGeneration >= 27: sizeOfTprBody = data.unpack_int64() - th = obj.TpxHeader(ver_str, precision, fileVersion, fileGeneration, - file_tag, natoms, ngtc, fep_state, lamb, - bIr, bTop, bX, bV, bF, bBox, sizeOfTprBody) + th = obj.TpxHeader( + ver_str, + precision, + fileVersion, + fileGeneration, + file_tag, + natoms, + ngtc, + fep_state, + lamb, + bIr, + bTop, + bX, + bV, + bF, + bBox, + sizeOfTprBody, + ) return th @@ -328,7 +348,7 @@ def do_mtop(data, fver, tpr_resid_from_one=False, precision=4): mb = do_molblock(data) # segment is made to correspond to the molblock as in gromacs, the # naming is kind of arbitrary - molblock = mtop.moltypes[mb.molb_type].name.decode('utf-8') + molblock = mtop.moltypes[mb.molb_type].name.decode("utf-8") segid = f"seg_{i}_{molblock}" chainID = molblock[14:] if molblock[:14] == "Protein_chain_" else molblock for j in range(mb.molb_nmol): @@ -372,17 +392,9 @@ def do_mtop(data, fver, tpr_resid_from_one=False, precision=4): resids += 1 resnames = np.array(resnames, dtype=object) - (residx, new_resids, - (new_resnames, - new_moltypes, - new_molnums, - perres_segids - ) - ) = squash_by(resids, - resnames, - moltypes, - molnums, - segids) + residx, new_resids, (new_resnames, new_moltypes, new_molnums, perres_segids) = ( + squash_by(resids, resnames, moltypes, molnums, segids) + ) residueids = Resids(new_resids) residuenames = Resnames(new_resnames) residue_moltypes = Moltypes(new_moltypes) @@ -414,10 +426,8 @@ def do_mtop(data, fver, tpr_resid_from_one=False, precision=4): ) top.add_TopologyAttr(Bonds([bond for bond in bonds if bond])) top.add_TopologyAttr(Angles([angle for angle in angles if angle])) - top.add_TopologyAttr(Dihedrals([dihedral for dihedral in dihedrals - if dihedral])) - top.add_TopologyAttr(Impropers([improper for improper in impropers - if improper])) + top.add_TopologyAttr(Dihedrals([dihedral for dihedral in dihedrals if dihedral])) + top.add_TopologyAttr(Impropers([improper for improper in impropers if improper])) if any(elements): elements = Elements(np.array(elements, dtype=object)) @@ -467,7 +477,7 @@ def do_mtop(data, fver, tpr_resid_from_one=False, precision=4): if fver > 58: ngrid = data.unpack_int() grid_spacing = data.unpack_int() - n_elements = grid_spacing ** 2 + n_elements = grid_spacing**2 for i in range(ngrid): for j in range(n_elements): ndo_real(data, 4) @@ -547,9 +557,12 @@ def do_iparams(data, functypes, fver): # Not all elif cases in this function has been used and tested for k, i in enumerate(functypes): if i in [ - setting.F_ANGLES, setting.F_G96ANGLES, - setting.F_BONDS, setting.F_G96BONDS, - setting.F_HARMONIC, setting.F_IDIHS + setting.F_ANGLES, + setting.F_G96ANGLES, + setting.F_BONDS, + setting.F_G96BONDS, + setting.F_HARMONIC, + setting.F_IDIHS, ]: do_harm(data) elif i in [setting.F_RESTRANGLES]: @@ -577,8 +590,10 @@ def do_iparams(data, functypes, fver): data.unpack_real() # restraint.up2B data.unpack_real() # restraint.kB elif i in [ - setting.F_TABBONDS, setting.F_TABBONDSNC, - setting.F_TABANGLES, setting.F_TABDIHS, + setting.F_TABBONDS, + setting.F_TABBONDSNC, + setting.F_TABANGLES, + setting.F_TABDIHS, ]: data.unpack_real() # tab.kA data.unpack_int() # tab.table @@ -604,7 +619,7 @@ def do_iparams(data, functypes, fver): data.unpack_real() # u_b.kUBB elif i in [setting.F_QUARTIC_ANGLES]: data.unpack_real() # qangle.theta - ndo_real(data, 5) # qangle.c + ndo_real(data, 5) # qangle.c elif i in [setting.F_BHAM]: data.unpack_real() # bham.a data.unpack_real() # bham.b @@ -664,8 +679,10 @@ def do_iparams(data, functypes, fver): data.unpack_real() # ljcnb.c12 elif i in [ - setting.F_PIDIHS, setting.F_ANGRES, - setting.F_ANGRESZ, setting.F_PDIHS, + setting.F_PIDIHS, + setting.F_ANGRES, + setting.F_ANGRESZ, + setting.F_PDIHS, ]: data.unpack_real() # pdihs_phiA data.unpack_real() # pdihs_cpA @@ -714,8 +731,8 @@ def do_iparams(data, functypes, fver): do_rvec(data) # posres.fcB elif i in [setting.F_FBPOSRES]: - data.unpack_int() # fbposres.geom - do_rvec(data) # fbposres.pos0 + data.unpack_int() # fbposres.geom + do_rvec(data) # fbposres.pos0 data.unpack_real() # fbposres.r data.unpack_real() # fbposres.k @@ -794,16 +811,18 @@ def do_moltype(data, symtab, fver): #### start: MDAnalysis specific atomkinds = [] for k, a in enumerate(atoms_obj.atoms): - atomkinds.append(obj.AtomKind( - k, - atoms_obj.atomnames[k], - atoms_obj.type[k], - a.resind, - atoms_obj.resnames[a.resind], - a.m, - a.q, - a.atomnumber, - )) + atomkinds.append( + obj.AtomKind( + k, + atoms_obj.atomnames[k], + atoms_obj.type[k], + a.resind, + atoms_obj.resnames[a.resind], + a.m, + a.q, + a.atomnumber, + ) + ) #### end: MDAnalysis specific # key info: about bonds, angles, dih, improp dih. @@ -819,21 +838,44 @@ def do_moltype(data, symtab, fver): # the following if..elif..else statement needs to be updated as new # type of interactions become interested - if ik_obj.name in ['BONDS', 'G96BONDS', 'MORSE', 'CUBICBONDS', - 'CONNBONDS', 'HARMONIC', 'FENEBONDS', - 'RESTRAINTPOT', 'CONSTR', 'CONSTRNC', - 'TABBONDS', 'TABBONDSNC']: + if ik_obj.name in [ + "BONDS", + "G96BONDS", + "MORSE", + "CUBICBONDS", + "CONNBONDS", + "HARMONIC", + "FENEBONDS", + "RESTRAINTPOT", + "CONSTR", + "CONSTRNC", + "TABBONDS", + "TABBONDSNC", + ]: bonds += list(ik_obj.process(ias)) - elif ik_obj.name in ['ANGLES', 'G96ANGLES', 'CROSS_BOND_BOND', - 'CROSS_BOND_ANGLE', 'UREY_BRADLEY', 'QANGLES', - 'RESTRANGLES', 'TABANGLES']: + elif ik_obj.name in [ + "ANGLES", + "G96ANGLES", + "CROSS_BOND_BOND", + "CROSS_BOND_ANGLE", + "UREY_BRADLEY", + "QANGLES", + "RESTRANGLES", + "TABANGLES", + ]: angles += list(ik_obj.process(ias)) - elif ik_obj.name in ['PDIHS', 'RBDIHS', 'RESTRDIHS', 'CBTDIHS', - 'FOURDIHS', 'TABDIHS']: + elif ik_obj.name in [ + "PDIHS", + "RBDIHS", + "RESTRDIHS", + "CBTDIHS", + "FOURDIHS", + "TABDIHS", + ]: dihs += list(ik_obj.process(ias)) - elif ik_obj.name in ['IDIHS', 'PIDIHS']: + elif ik_obj.name in ["IDIHS", "PIDIHS"]: impr += list(ik_obj.process(ias)) - elif ik_obj.name == 'SETTLE': + elif ik_obj.name == "SETTLE": # SETTLE interactions are optimized triangular constraints for # water molecules. They should be counted as a pair of bonds # between the oxygen and the hydrogens. In older versions of @@ -940,8 +982,7 @@ def do_ilists(data, fver): iatoms.append(l_) return [ - obj.Ilist(n, it, i) - for n, it, i in zip(nr, setting.interaction_types, iatoms) + obj.Ilist(n, it, i) for n, it, i in zip(nr, setting.interaction_types, iatoms) ] @@ -956,8 +997,9 @@ def do_molblock(data): if molb_nposres_xB > 0: ndo_rvec(data, molb_nposres_xB) - return obj.Molblock(molb_type, molb_nmol, molb_natoms_mol, - molb_nposres_xA, molb_nposres_xB) + return obj.Molblock( + molb_type, molb_nmol, molb_natoms_mol, molb_nposres_xA, molb_nposres_xB + ) def do_block(data): diff --git a/package/MDAnalysis/transformations/base.py b/package/MDAnalysis/transformations/base.py index ab0f6ea8990..37c4da47b60 100644 --- a/package/MDAnalysis/transformations/base.py +++ b/package/MDAnalysis/transformations/base.py @@ -27,6 +27,7 @@ .. autoclass:: TransformationBase """ + from threadpoolctl import threadpool_limits diff --git a/package/MDAnalysis/transformations/boxdimensions.py b/package/MDAnalysis/transformations/boxdimensions.py index c18cdc36a7a..e680bfa14f9 100644 --- a/package/MDAnalysis/transformations/boxdimensions.py +++ b/package/MDAnalysis/transformations/boxdimensions.py @@ -30,6 +30,7 @@ .. autoclass:: set_dimensions """ + import numpy as np from .base import TransformationBase @@ -87,9 +88,7 @@ class set_dimensions(TransformationBase): """ def __init__(self, dimensions, max_threads=None, parallelizable=True): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.dimensions = dimensions try: diff --git a/package/MDAnalysis/transformations/fit.py b/package/MDAnalysis/transformations/fit.py index 89336128cbf..0efdc676ec5 100644 --- a/package/MDAnalysis/transformations/fit.py +++ b/package/MDAnalysis/transformations/fit.py @@ -32,6 +32,7 @@ .. autoclass:: fit_rot_trans """ + import numpy as np from ..analysis import align @@ -100,9 +101,7 @@ def __init__( max_threads=None, parallelizable=True, ): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.ag = ag self.reference = reference @@ -114,9 +113,7 @@ def __init__( try: self.plane = axes[self.plane] except (TypeError, KeyError): - raise ValueError( - f"{self.plane} is not a valid plane" - ) from None + raise ValueError(f"{self.plane} is not a valid plane") from None try: if self.ag.atoms.n_residues != self.reference.atoms.n_residues: errmsg = ( @@ -126,10 +123,7 @@ def __init__( raise ValueError(errmsg) except AttributeError: - errmsg = ( - f"{self.ag} or {self.reference} is not valid" - f"Universe/AtomGroup" - ) + errmsg = f"{self.ag} or {self.reference} is not valid" f"Universe/AtomGroup" raise AttributeError(errmsg) from None self.ref, self.mobile = align.get_matching_atoms( self.reference.atoms, self.ag.atoms @@ -138,9 +132,7 @@ def __init__( self.ref_com = self.ref.center(self.weights) def _transform(self, ts): - mobile_com = np.asarray( - self.mobile.atoms.center(self.weights), np.float32 - ) + mobile_com = np.asarray(self.mobile.atoms.center(self.weights), np.float32) vector = self.ref_com - mobile_com if self.plane is not None: vector[self.plane] = 0 @@ -219,9 +211,7 @@ def __init__( max_threads=1, parallelizable=True, ): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.ag = ag self.reference = reference @@ -233,9 +223,7 @@ def __init__( try: self.plane = axes[self.plane] except (TypeError, KeyError): - raise ValueError( - f"{self.plane} is not a valid plane" - ) from None + raise ValueError(f"{self.plane} is not a valid plane") from None try: if self.ag.atoms.n_residues != self.reference.atoms.n_residues: errmsg = ( @@ -245,8 +233,7 @@ def __init__( raise ValueError(errmsg) except AttributeError: errmsg = ( - f"{self.ag} or {self.reference} is not valid " - f"Universe/AtomGroup" + f"{self.ag} or {self.reference} is not valid " f"Universe/AtomGroup" ) raise AttributeError(errmsg) from None self.ref, self.mobile = align.get_matching_atoms( @@ -266,13 +253,9 @@ def _transform(self, ts): if self.plane is not None: matrix = np.r_[rotation, np.zeros(3).reshape(1, 3)] matrix = np.c_[matrix, np.zeros(4)] - euler_angs = np.asarray( - euler_from_matrix(matrix, axes="sxyz"), np.float32 - ) + euler_angs = np.asarray(euler_from_matrix(matrix, axes="sxyz"), np.float32) for i in range(0, euler_angs.size): - euler_angs[i] = ( - euler_angs[self.plane] if i == self.plane else 0 - ) + euler_angs[i] = euler_angs[self.plane] if i == self.plane else 0 rotation = euler_matrix( euler_angs[0], euler_angs[1], euler_angs[2], axes="sxyz" )[:3, :3] diff --git a/package/MDAnalysis/transformations/nojump.py b/package/MDAnalysis/transformations/nojump.py index b14be3a97b1..4f541fef16a 100644 --- a/package/MDAnalysis/transformations/nojump.py +++ b/package/MDAnalysis/transformations/nojump.py @@ -35,6 +35,7 @@ .. autoclass:: NoJump """ + import numpy as np import warnings @@ -140,8 +141,7 @@ def _transform(self, ts): if ( self.check_c and self.older_frame != "A" - and (self.old_frame - self.older_frame) - != (ts.frame - self.old_frame) + and (self.old_frame - self.older_frame) != (ts.frame - self.old_frame) ): warnings.warn( "NoJump detected that the interval between frames is unequal." @@ -163,9 +163,7 @@ def _transform(self, ts): ) # Convert into reduced coordinate space fcurrent = ts.positions @ Linverse - fprev = ( - self.prev - ) # Previous unwrapped coordinates in reduced box coordinates. + fprev = self.prev # Previous unwrapped coordinates in reduced box coordinates. # Calculate the new positions in reduced coordinate space (Equation B6 from # 10.1021/acs.jctc.2c00327). As it turns out, the displacement term can # be moved inside the round function in this coordinate space, as the @@ -174,9 +172,7 @@ def _transform(self, ts): # Convert back into real space ts.positions = newpositions @ L # Set things we need to save for the next frame. - self.prev = ( - newpositions # Note that this is in reduced coordinate space. - ) + self.prev = newpositions # Note that this is in reduced coordinate space. self.older_frame = self.old_frame self.old_frame = ts.frame diff --git a/package/MDAnalysis/transformations/positionaveraging.py b/package/MDAnalysis/transformations/positionaveraging.py index d091dd9bbf8..f62894221e9 100644 --- a/package/MDAnalysis/transformations/positionaveraging.py +++ b/package/MDAnalysis/transformations/positionaveraging.py @@ -32,6 +32,7 @@ .. autoclass:: PositionAverager """ + import numpy as np import warnings @@ -148,9 +149,7 @@ def __init__( max_threads=None, parallelizable=False, ): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.avg_frames = avg_frames self.check_reset = check_reset self.current_avg = 0 diff --git a/package/MDAnalysis/transformations/rotate.py b/package/MDAnalysis/transformations/rotate.py index 4d8fa71d0b1..15d6150bdc5 100644 --- a/package/MDAnalysis/transformations/rotate.py +++ b/package/MDAnalysis/transformations/rotate.py @@ -31,6 +31,7 @@ .. autoclass:: rotateby """ + import numpy as np from functools import partial @@ -134,9 +135,7 @@ def __init__( max_threads=1, parallelizable=True, ): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.angle = angle self.direction = direction @@ -149,16 +148,12 @@ def __init__( try: self.direction = np.asarray(self.direction, np.float32) if self.direction.shape != (3,) and self.direction.shape != (1, 3): - raise ValueError( - "{} is not a valid direction".format(self.direction) - ) + raise ValueError("{} is not a valid direction".format(self.direction)) self.direction = self.direction.reshape( 3, ) except ValueError: - raise ValueError( - f"{self.direction} is not a valid direction" - ) from None + raise ValueError(f"{self.direction} is not a valid direction") from None if self.point is not None: self.point = np.asarray(self.point, np.float32) if self.point.shape != (3,) and self.point.shape != (1, 3): @@ -170,14 +165,10 @@ def __init__( try: self.atoms = self.ag.atoms except AttributeError: - raise ValueError( - f"{self.ag} is not an AtomGroup object" - ) from None + raise ValueError(f"{self.ag} is not an AtomGroup object") from None else: try: - self.weights = get_weights( - self.atoms, weights=self.weights - ) + self.weights = get_weights(self.atoms, weights=self.weights) except (ValueError, TypeError): errmsg = ( "weights must be {'mass', None} or an iterable " diff --git a/package/MDAnalysis/transformations/translate.py b/package/MDAnalysis/transformations/translate.py index c28fffd404f..afbf90ad6d9 100644 --- a/package/MDAnalysis/transformations/translate.py +++ b/package/MDAnalysis/transformations/translate.py @@ -36,6 +36,7 @@ """ + import numpy as np from functools import partial @@ -72,9 +73,7 @@ class translate(TransformationBase): """ def __init__(self, vector, max_threads=None, parallelizable=True): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.vector = vector @@ -141,9 +140,7 @@ def __init__( max_threads=None, parallelizable=True, ): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.ag = ag self.center = center @@ -157,13 +154,9 @@ def __init__( raise ValueError("{} is not a valid point".format(self.point)) try: if self.center == "geometry": - self.center_method = partial( - self.ag.center_of_geometry, wrap=pbc_arg - ) + self.center_method = partial(self.ag.center_of_geometry, wrap=pbc_arg) elif self.center == "mass": - self.center_method = partial( - self.ag.center_of_mass, wrap=pbc_arg - ) + self.center_method = partial(self.ag.center_of_mass, wrap=pbc_arg) else: raise ValueError(f"{self.center} is valid for center") except AttributeError: @@ -171,9 +164,7 @@ def __init__( errmsg = f"{self.ag} is not an AtomGroup object with masses" raise AttributeError(errmsg) from None else: - raise ValueError( - f"{self.ag} is not an AtomGroup object" - ) from None + raise ValueError(f"{self.ag} is not an AtomGroup object") from None def _transform(self, ts): if self.point is None: diff --git a/package/MDAnalysis/transformations/wrap.py b/package/MDAnalysis/transformations/wrap.py index f8c1d8dbaeb..1605925932d 100644 --- a/package/MDAnalysis/transformations/wrap.py +++ b/package/MDAnalysis/transformations/wrap.py @@ -91,12 +91,8 @@ class wrap(TransformationBase): limiting threads and checking if it can be used in parallel analysis. """ - def __init__( - self, ag, compound="atoms", max_threads=None, parallelizable=True - ): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + def __init__(self, ag, compound="atoms", max_threads=None, parallelizable=True): + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.ag = ag self.compound = compound @@ -156,9 +152,7 @@ class unwrap(TransformationBase): """ def __init__(self, ag, max_threads=None, parallelizable=True): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) self.ag = ag diff --git a/package/MDAnalysis/units.py b/package/MDAnalysis/units.py index d52e46d86c1..7122a294745 100644 --- a/package/MDAnalysis/units.py +++ b/package/MDAnalysis/units.py @@ -263,14 +263,12 @@ def __getitem__(self, key): "nm^{-3}": 1 / 1e-3, "nanometer^{-3}": 1 / 1e-3, "Molar": 1 / (1e-27 * constants["N_Avogadro"]), - "SPC": 1 - / (1e-24 * constants["N_Avogadro"] * water["SPC"] / water["MolarMass"]), + "SPC": 1 / (1e-24 * constants["N_Avogadro"] * water["SPC"] / water["MolarMass"]), "TIP3P": 1 / (1e-24 * constants["N_Avogadro"] * water["TIP3P"] / water["MolarMass"]), "TIP4P": 1 / (1e-24 * constants["N_Avogadro"] * water["TIP4P"] / water["MolarMass"]), - "water": 1 - / (1e-24 * constants["N_Avogadro"] * water["exp"] / water["MolarMass"]), + "water": 1 / (1e-24 * constants["N_Avogadro"] * water["exp"] / water["MolarMass"]), } @@ -287,7 +285,7 @@ def __getitem__(self, key): "millisecond": 1e-9, # 1/1e9, "us": 1e-6, "microsecond": 1e-6, - "\u03BCs": 1e-6, # 1/1e6, + "\u03bcs": 1e-6, # 1/1e6, "second": 1e-12, "sec": 1e-12, "s": 1e-12, # 1/1e12, @@ -316,12 +314,12 @@ def __getitem__(self, key): "Angstrom/us": 1.0 * 1e6, "angstrom/us": 1.0 * 1e6, "A/us": 1.0 * 1e6, - "A/\u03BCs": 1.0 * 1e6, - "\u212b/\u03BCs": 1.0 * 1e6, + "A/\u03bcs": 1.0 * 1e6, + "\u212b/\u03bcs": 1.0 * 1e6, "Angstrom/microsecond": 1.0 * 1e6, "angstrom/microsecond": 1.0 * 1e6, - "Angstrom/\u03BCs": 1.0 * 1e6, - "angstrom/\u03BCs": 1.0 * 1e6, + "Angstrom/\u03bcs": 1.0 * 1e6, + "angstrom/\u03bcs": 1.0 * 1e6, "Angstrom/ms": 1.0 * 1e9, "Angstrom/millisecond": 1.0 * 1e9, "angstrom/millisecond": 1.0 * 1e9, diff --git a/package/MDAnalysis/visualization/streamlines.py b/package/MDAnalysis/visualization/streamlines.py index 12534a2e77c..05e73e1233e 100644 --- a/package/MDAnalysis/visualization/streamlines.py +++ b/package/MDAnalysis/visualization/streamlines.py @@ -42,6 +42,7 @@ .. autofunction:: generate_streamlines """ + import multiprocessing import numpy as np @@ -166,9 +167,7 @@ def split_grid(grid, num_cores): list_square_vertex_arrays_per_core = np.array_split( list_all_squares_in_grid, num_cores ) - list_parent_index_values = np.array_split( - list_parent_index_values, num_cores - ) + list_parent_index_values = np.array_split(list_parent_index_values, num_cores) return [ list_square_vertex_arrays_per_core, list_parent_index_values, @@ -214,14 +213,16 @@ def _produce_list_centroids_this_frame( ): # if there are no particles of interest in this particular square list_centroids_this_frame.append(None) else: - current_coordinate_array_in_square = ( - relevant_particle_coordinate_array_xy[indices] - ) + current_coordinate_array_in_square = relevant_particle_coordinate_array_xy[ + indices + ] current_square_indices_centroid = np.average( current_coordinate_array_in_square, axis=0 ) list_centroids_this_frame.append(current_square_indices_centroid) - return list_centroids_this_frame # a list of numpy xy centroid arrays for this frame + return ( + list_centroids_this_frame # a list of numpy xy centroid arrays for this frame + ) def per_core_work( @@ -239,9 +240,7 @@ def per_core_work( The code to perform on a given core given the list of square vertices assigned to it. """ # obtain the relevant coordinates for particles of interest - universe_object = MDAnalysis.Universe( - topology_file_path, trajectory_file_path - ) + universe_object = MDAnalysis.Universe(topology_file_path, trajectory_file_path) list_previous_frame_centroids = [] list_previous_frame_indices = [] for ts in universe_object.trajectory: @@ -259,11 +258,9 @@ def per_core_work( ) ) # likewise, I will need a list of centroids of particles in each square (same order as above list): - list_centroids_in_squares_this_frame = ( - _produce_list_centroids_this_frame( - list_indices_in_squares_this_frame, - relevant_particle_coordinate_array_xy, - ) + list_centroids_in_squares_this_frame = _produce_list_centroids_this_frame( + list_indices_in_squares_this_frame, + relevant_particle_coordinate_array_xy, ) if ( list_previous_frame_indices @@ -285,9 +282,7 @@ def per_core_work( xy_deltas_to_write.append([0, 0]) else: xy_deltas_to_write.append( - np.subtract( - square_1_centroid, square_2_centroid - ).tolist() + np.subtract(square_1_centroid, square_2_centroid).tolist() ) # xy_deltas_to_write = np.subtract(np.array( @@ -303,15 +298,11 @@ def per_core_work( # with the xy and dx,dy values calculated I need to set the values from this frame to previous frame # values in anticipation of the next frame: - list_previous_frame_centroids = ( - list_centroids_in_squares_this_frame[:] - ) + list_previous_frame_centroids = list_centroids_in_squares_this_frame[:] list_previous_frame_indices = list_indices_in_squares_this_frame[:] else: # either no points in squares or after the first frame I'll just reset the 'previous' values so they # can be used when consecutive frames have proper values - list_previous_frame_centroids = ( - list_centroids_in_squares_this_frame[:] - ) + list_previous_frame_centroids = list_centroids_in_squares_this_frame[:] list_previous_frame_indices = list_indices_in_squares_this_frame[:] if ts.frame > end_frame: break # stop here @@ -427,9 +418,7 @@ def log_result_to_parent(delta_array): parent_list_deltas.extend(delta_array) tuple_of_limits = (xmin, xmax, ymin, ymax) - grid = produce_grid( - tuple_of_limits=tuple_of_limits, grid_spacing=grid_spacing - ) + grid = produce_grid(tuple_of_limits=tuple_of_limits, grid_spacing=grid_spacing) ( list_square_vertex_arrays_per_core, list_parent_index_values, diff --git a/package/MDAnalysis/visualization/streamlines_3D.py b/package/MDAnalysis/visualization/streamlines_3D.py index 4d2dace77bb..88f098c8d82 100644 --- a/package/MDAnalysis/visualization/streamlines_3D.py +++ b/package/MDAnalysis/visualization/streamlines_3D.py @@ -46,6 +46,7 @@ .. autofunction:: generate_streamlines_3d """ + import multiprocessing import numpy as np @@ -56,9 +57,7 @@ import MDAnalysis -def determine_container_limits( - topology_file_path, trajectory_file_path, buffer_value -): +def determine_container_limits(topology_file_path, trajectory_file_path, buffer_value): """Calculate the extent of the atom coordinates + buffer. A function for the parent process which should take the input trajectory @@ -74,12 +73,8 @@ def determine_container_limits( buffer_value : float buffer value (padding) in +/- {x, y, z} """ - universe_object = MDAnalysis.Universe( - topology_file_path, trajectory_file_path - ) - all_atom_selection = universe_object.select_atoms( - "all" - ) # select all particles + universe_object = MDAnalysis.Universe(topology_file_path, trajectory_file_path) + all_atom_selection = universe_object.select_atoms("all") # select all particles all_atom_coordinate_array = all_atom_selection.positions x_min, x_max, y_min, y_max, z_min, z_max = [ all_atom_coordinate_array[..., 0].min(), @@ -164,21 +159,15 @@ def split_grid(grid, num_cores): x ): # each x_sheet should have shape (25,23) and the same x value in each element array_all_x_values_current_sheet = x_sheet.flatten() - ordered_list_per_sheet_x_values.append( - array_all_x_values_current_sheet - ) + ordered_list_per_sheet_x_values.append(array_all_x_values_current_sheet) ordered_list_per_sheet_y_values = [] for y_columns in y: array_all_y_values_current_sheet = y_columns.flatten() - ordered_list_per_sheet_y_values.append( - array_all_y_values_current_sheet - ) + ordered_list_per_sheet_y_values.append(array_all_y_values_current_sheet) ordered_list_per_sheet_z_values = [] for z_slices in z: array_all_z_values_current_sheet = z_slices.flatten() - ordered_list_per_sheet_z_values.append( - array_all_z_values_current_sheet - ) + ordered_list_per_sheet_z_values.append(array_all_z_values_current_sheet) ordered_list_cartesian_coordinates_per_sheet = [] for x_sheet_coords, y_sheet_coords, z_sheet_coords in zip( @@ -221,17 +210,11 @@ def split_grid(grid, num_cores): current_index : current_index + 2, ... ].tolist() next_two_vertices_base_sheet = current_base_sheet_array[ - current_index - + num_z_values : 2 - + num_z_values - + current_index, + current_index + num_z_values : 2 + num_z_values + current_index, ..., ].tolist() next_two_vertices_top_sheet = current_top_sheet_array[ - current_index - + num_z_values : 2 - + num_z_values - + current_index, + current_index + num_z_values : 2 + num_z_values + current_index, ..., ].tolist() for vertex_set in [ @@ -246,9 +229,7 @@ def split_grid(grid, num_cores): 8, 3, ), "vertex_array has incorrect shape" - cube_centroid = np.average( - np.array(current_list_cube_vertices), axis=0 - ) + cube_centroid = np.average(np.array(current_list_cube_vertices), axis=0) dictionary_cubes_centroids_indices[cube_counter] = { "centroid": cube_centroid, "vertex_list": current_list_cube_vertices, @@ -266,9 +247,7 @@ def split_grid(grid, num_cores): # produce an array of pseudo cube indices (actually the dictionary keys which are cube numbers in string format): pseudo_cube_indices = np.arange(0, total_cubes) - sublist_of_cube_indices_per_core = np.array_split( - pseudo_cube_indices, num_cores - ) + sublist_of_cube_indices_per_core = np.array_split(pseudo_cube_indices, num_cores) # now, the split of pseudoindices seems to work well, and the above sublist_of_cube_indices_per_core is a list of # arrays of cube numbers / keys in the original dictionary # now I think I'll try to produce a list of dictionaries that each contain their assigned cubes based on the above @@ -309,23 +288,16 @@ def per_core_work( list_previous_frame_indices = [] # define some utility functions for trajectory iteration: - def point_in_cube( - array_point_coordinates, list_cube_vertices, cube_centroid - ): + def point_in_cube(array_point_coordinates, list_cube_vertices, cube_centroid): """Determine if an array of coordinates are within a cube.""" # the simulation particle point can't be more than half the cube side length away from the cube centroid in # any given dimension: array_cube_vertices = np.array(list_cube_vertices) cube_half_side_length = ( - scipy.spatial.distance.pdist( - array_cube_vertices, "euclidean" - ).min() - / 2.0 + scipy.spatial.distance.pdist(array_cube_vertices, "euclidean").min() / 2.0 ) - array_cube_vertex_distances_from_centroid = ( - scipy.spatial.distance.cdist( - array_cube_vertices, cube_centroid[np.newaxis, :] - ) + array_cube_vertex_distances_from_centroid = scipy.spatial.distance.cdist( + array_cube_vertices, cube_centroid[np.newaxis, :] ) np.testing.assert_allclose( array_cube_vertex_distances_from_centroid.min(), @@ -380,9 +352,7 @@ def update_dictionary_point_in_cube_start_frame( array_simulation_particle_coordinates[index_list_in_cube], axis=0, ) - cube["centroid_of_particles_first_frame"] = ( - centroid_particles_in_cube - ) + cube["centroid_of_particles_first_frame"] = centroid_particles_in_cube else: # empty cube cube["centroid_of_particles_first_frame"] = None cube_counter += 1 @@ -427,9 +397,7 @@ def update_dictionary_end_frame( update_dictionary_point_in_cube_start_frame( start_frame_coord_array, dictionary_cube_data_this_core ) - update_dictionary_end_frame( - end_frame_coord_array, dictionary_cube_data_this_core - ) + update_dictionary_end_frame(end_frame_coord_array, dictionary_cube_data_this_core) return dictionary_cube_data_this_core @@ -448,9 +416,7 @@ def produce_coordinate_arrays_single_process( waste memory. """ - universe_object = MDAnalysis.Universe( - topology_file_path, trajectory_file_path - ) + universe_object = MDAnalysis.Universe(topology_file_path, trajectory_file_path) relevant_particles = universe_object.select_atoms(MDA_selection) # pull out coordinate arrays from desired frames: for ts in universe_object.trajectory: @@ -605,9 +571,7 @@ def log_result_to_parent(process_dict): tuple_of_limits = (xmin, xmax, ymin, ymax, zmin, zmax) # step 2: produce a suitable grid (will assume that grid size / container size does not vary during simulation--or # at least not beyond the buffer limit, such that this grid can be used for all subsequent frames) - grid = produce_grid( - tuple_of_limits=tuple_of_limits, grid_spacing=grid_spacing - ) + grid = produce_grid(tuple_of_limits=tuple_of_limits, grid_spacing=grid_spacing) # step 3: split the grid into a dictionary of cube information that can be sent to each core for processing: list_dictionaries_for_cores, total_cubes, num_sheets, delta_array_shape = ( split_grid(grid=grid, num_cores=num_cores) @@ -655,15 +619,15 @@ def log_result_to_parent(process_dict): z_index_current_column = 0 # column total_cubes_current_sheet = 0 for cube_number in range(0, total_cubes): - dx_array[ - current_sheet, y_index_current_sheet, z_index_current_column - ] = parent_cube_dictionary[cube_number]["dx"] - dy_array[ - current_sheet, y_index_current_sheet, z_index_current_column - ] = parent_cube_dictionary[cube_number]["dy"] - dz_array[ - current_sheet, y_index_current_sheet, z_index_current_column - ] = parent_cube_dictionary[cube_number]["dz"] + dx_array[current_sheet, y_index_current_sheet, z_index_current_column] = ( + parent_cube_dictionary[cube_number]["dx"] + ) + dy_array[current_sheet, y_index_current_sheet, z_index_current_column] = ( + parent_cube_dictionary[cube_number]["dy"] + ) + dz_array[current_sheet, y_index_current_sheet, z_index_current_column] = ( + parent_cube_dictionary[cube_number]["dz"] + ) z_index_current_column += 1 total_cubes_current_sheet += 1 if z_index_current_column == delta_array_shape[2]: diff --git a/package/doc/sphinx/source/conf.py b/package/doc/sphinx/source/conf.py index 0aba418eb3b..cab1ffc0ea5 100644 --- a/package/doc/sphinx/source/conf.py +++ b/package/doc/sphinx/source/conf.py @@ -176,9 +176,7 @@ class KeyStyle(UnsrtStyle): # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -html_context = { - "versions_json_url": "https://docs.mdanalysis.org/versions.json" -} +html_context = {"versions_json_url": "https://docs.mdanalysis.org/versions.json"} # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". @@ -350,4 +348,6 @@ class KeyStyle(UnsrtStyle): "mdahole2": ("https://www.mdanalysis.org/mdahole2/", None), "dask": ("https://docs.dask.org/en/stable/", None), "imdclient": ("https://imdclient.readthedocs.io/en/stable/", None), + "pooch": ("https://www.fatiando.org/pooch/latest/", None), + "requests": ("https://requests.readthedocs.io/en/latest/", None), } diff --git a/package/doc/sphinx/source/documentation_pages/fetchers/PDB.rst b/package/doc/sphinx/source/documentation_pages/fetchers/PDB.rst new file mode 100644 index 00000000000..fa49714a39b --- /dev/null +++ b/package/doc/sphinx/source/documentation_pages/fetchers/PDB.rst @@ -0,0 +1 @@ +.. automodule:: MDAnalysis.fetch.pdb \ No newline at end of file diff --git a/package/doc/sphinx/source/documentation_pages/fetchers/init.rst b/package/doc/sphinx/source/documentation_pages/fetchers/init.rst new file mode 100644 index 00000000000..213a1e375aa --- /dev/null +++ b/package/doc/sphinx/source/documentation_pages/fetchers/init.rst @@ -0,0 +1 @@ +.. automodule:: MDAnalysis.fetch.__init__ \ No newline at end of file diff --git a/package/doc/sphinx/source/documentation_pages/fetchers_modules.rst b/package/doc/sphinx/source/documentation_pages/fetchers_modules.rst new file mode 100644 index 00000000000..bdcff49164b --- /dev/null +++ b/package/doc/sphinx/source/documentation_pages/fetchers_modules.rst @@ -0,0 +1,18 @@ +.. Contains the formatted docstrings from the fetch modules located in 'mdanalysis/MDAnalysis/fetch' + +************************** +Fetchers modules +************************** + +The fetch module contains code that are able to retrieve data from +the internet. All code in this module currently depends on the +dependency :mod:`pooch` which is required in order to run this +module. + +.. rubric:: Fetcher functions + +.. toctree:: + :maxdepth: 1 + + fetchers/init + fetchers/PDB diff --git a/package/doc/sphinx/source/index.rst b/package/doc/sphinx/source/index.rst index 243464ef138..9367a0bad89 100644 --- a/package/doc/sphinx/source/index.rst +++ b/package/doc/sphinx/source/index.rst @@ -125,6 +125,7 @@ Thank you! ./documentation_pages/guesser_modules ./documentation_pages/coordinates_modules ./documentation_pages/converters + ./documentation_pages/fetchers_modules ./documentation_pages/trajectory_transformations ./documentation_pages/selections_modules ./documentation_pages/auxiliary_modules diff --git a/package/pyproject.toml b/package/pyproject.toml index 3dc32092fcb..283980b1332 100644 --- a/package/pyproject.toml +++ b/package/pyproject.toml @@ -72,6 +72,7 @@ extra_formats = [ "h5py>=2.10", "chemfiles>=0.10", "parmed", + "pooch", "pyedr>=0.7.0", "pytng>=0.2.3", "gsd>3.0.0", diff --git a/package/requirements.txt b/package/requirements.txt index a196a9fe0f7..17c3961a5ef 100644 --- a/package/requirements.txt +++ b/package/requirements.txt @@ -13,6 +13,7 @@ networkx numpy>=1.23.2 packaging parmed +pooch pytest scikit-learn scipy diff --git a/package/setup.py b/package/setup.py index f9b7b4a9e70..bcb6efa1f6b 100755 --- a/package/setup.py +++ b/package/setup.py @@ -78,9 +78,7 @@ print( "Cython version {0} was found but won't be used: version {1} " "or greater is required because it offers a handy " - "parallelization module".format( - Cython.__version__, required_version - ) + "parallelization module".format(Cython.__version__, required_version) ) cython_found = False cython_linetrace = bool(os.environ.get("CYTHON_TRACE_NOGIL", False)) @@ -179,9 +177,7 @@ def get_numpy_include(): import numpy as np except ImportError: print('*** package "numpy" not found ***') - print( - "MDAnalysis requires a version of NumPy (>=1.21.0), even for setup." - ) + print("MDAnalysis requires a version of NumPy (>=1.21.0), even for setup.") print( "Please get it from http://numpy.scipy.org/ or install it through " "your package manager." @@ -456,12 +452,10 @@ def extensions(config): ap_clustering = MDAExtension( "MDAnalysis.analysis.encore.clustering.affinityprop", sources=[ - "MDAnalysis/analysis/encore/clustering/affinityprop" - + source_suffix, + "MDAnalysis/analysis/encore/clustering/affinityprop" + source_suffix, "MDAnalysis/analysis/encore/clustering/src/ap.c", ], - include_dirs=include_dirs - + ["MDAnalysis/analysis/encore/clustering/include"], + include_dirs=include_dirs + ["MDAnalysis/analysis/encore/clustering/include"], libraries=mathlib, define_macros=define_macros, extra_compile_args=encore_compile_args, @@ -605,9 +599,7 @@ def dynamic_author_list(): # Write the list of authors as a python list template = "__authors__ = [\n{}\n]" - author_string = ",\n".join( - ' u"{}"'.format(name) for name in authors - ) + author_string = ",\n".join(' u"{}"'.format(name) for name in authors) print(template.format(author_string), file=outfile) @@ -617,9 +609,7 @@ def long_description(readme): with open(abspath(readme)) as summary: buffer = summary.read() # remove top heading that messes up pypi display - m = re.search( - "====*\n[^\n]*README[^\n]*\n=====*\n", buffer, flags=re.DOTALL - ) + m = re.search("====*\n[^\n]*README[^\n]*\n=====*\n", buffer, flags=re.DOTALL) assert m, "README.rst does not contain a level-1 heading" return buffer[m.end() :] @@ -656,10 +646,7 @@ def long_description(readme): ) # Releases keep their cythonized stuff for shipping. - if ( - not config.get("keep_cythonized", default=is_release) - and not cython_linetrace - ): + if not config.get("keep_cythonized", default=is_release) and not cython_linetrace: for cythonized in cythonfiles: try: os.unlink(cythonized) diff --git a/testsuite/MDAnalysisTests/__init__.py b/testsuite/MDAnalysisTests/__init__.py index 66f78aa2676..f6f67e981b5 100644 --- a/testsuite/MDAnalysisTests/__init__.py +++ b/testsuite/MDAnalysisTests/__init__.py @@ -90,6 +90,7 @@ .. _Gromacs: http://www.gromacs.org """ + import logging import pytest diff --git a/testsuite/MDAnalysisTests/analysis/test_align.py b/testsuite/MDAnalysisTests/analysis/test_align.py index fbda36b1580..37a5bccfea0 100644 --- a/testsuite/MDAnalysisTests/analysis/test_align.py +++ b/testsuite/MDAnalysisTests/analysis/test_align.py @@ -99,14 +99,10 @@ def reference(): @staticmethod @pytest.fixture() def reference_small(reference): - return mda.Merge( - reference.select_atoms("not name H* and not atom 4AKE 1 CA") - ) + return mda.Merge(reference.select_atoms("not name H* and not atom 4AKE 1 CA")) @pytest.mark.parametrize("strict", (True, False)) - def test_match( - self, universe, reference, strict, selection="protein and backbone" - ): + def test_match(self, universe, reference, strict, selection="protein and backbone"): ref = reference.select_atoms(selection) mobile = universe.select_atoms(selection) groups = align.get_matching_atoms(ref, mobile, strict=strict) @@ -126,9 +122,7 @@ def test_nomatch_atoms_raise( else: with pytest.warns(SelectionWarning): with pytest.raises(SelectionError): - groups = align.get_matching_atoms( - ref, mobile, strict=strict - ) + groups = align.get_matching_atoms(ref, mobile, strict=strict) @pytest.mark.parametrize("strict", (True, False)) def test_nomatch_residues_raise_empty( @@ -149,9 +143,7 @@ def test_nomatch_residues_raise_empty( else: with pytest.warns(SelectionWarning): with pytest.raises(SelectionError): - groups = align.get_matching_atoms( - ref, mobile, strict=strict - ) + groups = align.get_matching_atoms(ref, mobile, strict=strict) def test_toggle_atom_mismatch_default_error(self, universe, reference): selection = ("resname ALA and name CA", "resname ALA and name O") @@ -167,9 +159,7 @@ def test_toggle_atom_mismatch_kwarg_error(self, universe, reference): def test_toggle_atom_nomatch(self, universe, reference): selection = ("resname ALA and name CA", "resname ALA and name O") - rmsd = align.alignto( - universe, reference, select=selection, match_atoms=False - ) + rmsd = align.alignto(universe, reference, select=selection, match_atoms=False) assert rmsd[0] > 0.01 def test_toggle_atom_nomatch_mismatch_atoms(self, universe, reference): @@ -191,28 +181,20 @@ def test_toggle_atom_nomatch_mismatch_atoms(self, universe, reference): (1234, pytest.raises(TypeError)), ], ) - def test_subselection_alignto( - self, universe, reference, subselection, expectation - ): + def test_subselection_alignto(self, universe, reference, subselection, expectation): with expectation: - rmsd = align.alignto( - universe, reference, subselection=subselection - ) + rmsd = align.alignto(universe, reference, subselection=subselection) assert_allclose(rmsd[1], 0.0, rtol=0, atol=1.5e-9) def test_no_atom_masses(self, universe): # if no masses are present - u = mda.Universe.empty( - 6, 2, atom_resindex=[0, 0, 0, 1, 1, 1], trajectory=True - ) + u = mda.Universe.empty(6, 2, atom_resindex=[0, 0, 0, 1, 1, 1], trajectory=True) with pytest.warns(SelectionWarning): align.get_matching_atoms(u.atoms, u.atoms) def test_one_universe_has_masses(self, universe): - u = mda.Universe.empty( - 6, 2, atom_resindex=[0, 0, 0, 1, 1, 1], trajectory=True - ) + u = mda.Universe.empty(6, 2, atom_resindex=[0, 0, 0, 1, 1, 1], trajectory=True) ref = mda.Universe.empty( 6, 2, atom_resindex=[0, 0, 0, 1, 1, 1], trajectory=True ) @@ -277,9 +259,7 @@ def test_rmsd_custom_mass_weights(self, universe, reference): last_atoms_weight = universe.atoms.masses A = universe.trajectory[0] B = reference.trajectory[-1] - rmsd = align.alignto( - universe, reference, weights=reference.atoms.masses - ) + rmsd = align.alignto(universe, reference, weights=reference.atoms.masses) rmsd_sup_weight = rms.rmsd( A, B, weights=last_atoms_weight, center=True, superposition=True ) @@ -302,9 +282,7 @@ def test_AlignTraj_outfile_default(self, universe, reference, tmpdir): finally: x._writer.close() - def test_AlignTraj_outfile_default_exists( - self, universe, reference, tmpdir - ): + def test_AlignTraj_outfile_default_exists(self, universe, reference, tmpdir): reference.trajectory[-1] outfile = str(tmpdir.join("align_test.dcd")) align.AlignTraj(universe, reference, filename=outfile).run() @@ -356,16 +334,12 @@ def test_AlignTraj(self, universe, reference, tmpdir): def test_AlignTraj_weighted(self, universe, reference, tmpdir): outfile = str(tmpdir.join("align_test.dcd")) - x = align.AlignTraj( - universe, reference, filename=outfile, weights="mass" - ).run() + x = align.AlignTraj(universe, reference, filename=outfile, weights="mass").run() fitted = mda.Universe(PSF, outfile) assert_allclose(x.results.rmsd[0], 0, rtol=0, atol=1.5e-3) assert_allclose(x.results.rmsd[-1], 6.9033, rtol=0, atol=1.5e-3) - self._assert_rmsd( - reference, fitted, 0, 0.0, weights=universe.atoms.masses - ) + self._assert_rmsd(reference, fitted, 0, 0.0, weights=universe.atoms.masses) self._assert_rmsd( reference, fitted, @@ -388,9 +362,7 @@ def test_AlignTraj_custom_weights(self, universe, reference, tmpdir): universe, reference, filename=outfile, weights=weights ).run() - assert_allclose( - x.results.rmsd, x_weights.results.rmsd, rtol=0, atol=1.5e-7 - ) + assert_allclose(x.results.rmsd, x_weights.results.rmsd, rtol=0, atol=1.5e-7) def test_AlignTraj_custom_mass_weights(self, universe, reference, tmpdir): outfile = str(tmpdir.join("align_test.dcd")) @@ -404,9 +376,7 @@ def test_AlignTraj_custom_mass_weights(self, universe, reference, tmpdir): assert_allclose(x.results.rmsd[0], 0, rtol=0, atol=1.5e-3) assert_allclose(x.results.rmsd[-1], 6.9033, rtol=0, atol=1.5e-3) - self._assert_rmsd( - reference, fitted, 0, 0.0, weights=universe.atoms.masses - ) + self._assert_rmsd(reference, fitted, 0, 0.0, weights=universe.atoms.masses) self._assert_rmsd( reference, fitted, @@ -430,9 +400,7 @@ def test_AlignTraj_partial_fit(self, universe, reference, tmpdir): def test_AlignTraj_in_memory(self, universe, reference, tmpdir): outfile = str(tmpdir.join("align_test.dcd")) reference.trajectory[-1] - x = align.AlignTraj( - universe, reference, filename=outfile, in_memory=True - ).run() + x = align.AlignTraj(universe, reference, filename=outfile, in_memory=True).run() assert x.filename is None assert_allclose(x.results.rmsd[0], 6.9290, rtol=0, atol=1.5e-3) assert_allclose(x.results.rmsd[-1], 5.2797e-07, rtol=0, atol=1.5e-3) @@ -467,8 +435,7 @@ def _assert_rmsd(self, reference, fitted, frame, desired, weights=None): desired, rtol=0, atol=1.5e-5, - err_msg="frame {0:d} of fit does not have " - "expected RMSD".format(frame), + err_msg="frame {0:d} of fit does not have " "expected RMSD".format(frame), ) def test_alignto_checks_selections(self, universe, reference): @@ -502,9 +469,7 @@ def test_alignto_partial_universe(self, universe, reference): segB_free.translate(segB_bound.centroid() - segB_free.centroid()) align.alignto(u_free, u_bound, select=selection) - assert_allclose( - segB_bound.positions, segB_free.positions, rtol=0, atol=1.5e-3 - ) + assert_allclose(segB_bound.positions, segB_free.positions, rtol=0, atol=1.5e-3) def _get_aligned_average_positions(ref_files, ref, select="all", **kwargs): @@ -550,9 +515,7 @@ def test_average_structure_deprecated_attrs(self, universe, reference): def test_average_structure(self, universe, reference): ref, rmsd = _get_aligned_average_positions(self.ref_files, reference) avg = align.AverageStructure(universe, reference).run() - assert_allclose( - avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4 - ) + assert_allclose(avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4) assert_allclose(avg.results.rmsd, rmsd, rtol=0, atol=1.5e-7) def test_average_structure_mass_weighted(self, universe, reference): @@ -560,9 +523,7 @@ def test_average_structure_mass_weighted(self, universe, reference): self.ref_files, reference, weights="mass" ) avg = align.AverageStructure(universe, reference, weights="mass").run() - assert_allclose( - avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4 - ) + assert_allclose(avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4) assert_allclose(avg.results.rmsd, rmsd, rtol=0, atol=1.5e-7) def test_average_structure_select(self, universe, reference): @@ -571,17 +532,13 @@ def test_average_structure_select(self, universe, reference): self.ref_files, reference, select=select ) avg = align.AverageStructure(universe, reference, select=select).run() - assert_allclose( - avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4 - ) + assert_allclose(avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4) assert_allclose(avg.results.rmsd, rmsd, rtol=0, atol=1.5e-7) def test_average_structure_no_ref(self, universe): ref, rmsd = _get_aligned_average_positions(self.ref_files, universe) avg = align.AverageStructure(universe).run() - assert_allclose( - avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4 - ) + assert_allclose(avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4) assert_allclose(avg.results.rmsd, rmsd, rtol=0, atol=1.5e-7) def test_average_structure_no_msf(self, universe): @@ -605,9 +562,7 @@ def test_average_structure_ref_frame(self, universe): universe.trajectory[0] ref, rmsd = _get_aligned_average_positions(self.ref_files, u) avg = align.AverageStructure(universe, ref_frame=ref_frame).run() - assert_allclose( - avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4 - ) + assert_allclose(avg.results.universe.atoms.positions, ref, rtol=0, atol=1.5e-4) assert_allclose(avg.results.rmsd, rmsd, rtol=0, atol=1.5e-7) def test_average_structure_in_memory(self, universe): diff --git a/testsuite/MDAnalysisTests/analysis/test_atomicdistances.py b/testsuite/MDAnalysisTests/analysis/test_atomicdistances.py index 4697485470b..9e8341bf7da 100644 --- a/testsuite/MDAnalysisTests/analysis/test_atomicdistances.py +++ b/testsuite/MDAnalysisTests/analysis/test_atomicdistances.py @@ -79,9 +79,7 @@ def ad_ag4(): @staticmethod @pytest.fixture() def expected_dist(ad_ag1, ad_ag2): - expected = np.zeros( - (len(ad_ag1.universe.trajectory), ad_ag1.atoms.n_atoms) - ) + expected = np.zeros((len(ad_ag1.universe.trajectory), ad_ag1.atoms.n_atoms)) # calculate distances without PBCs using dist() for i, ts in enumerate(ad_ag1.universe.trajectory): @@ -91,9 +89,7 @@ def expected_dist(ad_ag1, ad_ag2): @staticmethod @pytest.fixture() def expected_pbc_dist(ad_ag1, ad_ag2): - expected = np.zeros( - (len(ad_ag1.universe.trajectory), ad_ag1.atoms.n_atoms) - ) + expected = np.zeros((len(ad_ag1.universe.trajectory), ad_ag1.atoms.n_atoms)) # calculate distances with PBCs using dist() for i, ts in enumerate(ad_ag1.universe.trajectory): diff --git a/testsuite/MDAnalysisTests/analysis/test_base.py b/testsuite/MDAnalysisTests/analysis/test_base.py index 0dd872bde57..eada5551746 100644 --- a/testsuite/MDAnalysisTests/analysis/test_base.py +++ b/testsuite/MDAnalysisTests/analysis/test_base.py @@ -56,9 +56,7 @@ def _conclude(self): self.found_frames = list(self.results.found_frames) def _get_aggregator(self): - return base.ResultsGroup( - {"found_frames": base.ResultsGroup.ndarray_hstack} - ) + return base.ResultsGroup({"found_frames": base.ResultsGroup.ndarray_hstack}) class IncompleteAnalysis(base.AnalysisBase): @@ -173,9 +171,7 @@ def test_n_workers_conflict_raises_value_error(u): def test_backend_configuration_fails(u, run_class, backend, n_workers): u = mda.Universe(TPR, XTC) # dt = 100 with pytest.raises(ValueError): - _ = run_class(u.trajectory).run( - backend=backend, n_workers=n_workers, stop=0 - ) + _ = run_class(u.trajectory).run(backend=backend, n_workers=n_workers, stop=0) @pytest.mark.parametrize( @@ -221,9 +217,7 @@ def test_custom_backend_works(u, run_class, backend, n_workers): (ParallelizableWithDaskOnly, object, 1), ], ) -def test_fails_incorrect_custom_backend( - u, run_class, backend_instance, n_workers -): +def test_fails_incorrect_custom_backend(u, run_class, backend_instance, n_workers): u = mda.Universe(TPR, XTC) # dt = 100 with pytest.raises(ValueError): _ = run_class(u.trajectory).run( @@ -233,9 +227,7 @@ def test_fails_incorrect_custom_backend( ) with pytest.raises(ValueError): - _ = run_class(u.trajectory).run( - backend=backend_instance, n_workers=n_workers - ) + _ = run_class(u.trajectory).run(backend=backend_instance, n_workers=n_workers) @pytest.mark.parametrize( @@ -289,9 +281,7 @@ def test_reset_n_parts_to_n_frames(u): """ a = FrameAnalysis(u.trajectory) with pytest.warns(UserWarning, match="Set `n_parts` to"): - a.run( - backend="multiprocessing", start=0, stop=1, n_workers=2, n_parts=2 - ) + a.run(backend="multiprocessing", start=0, stop=1, n_workers=2, n_parts=2) @pytest.mark.parametrize( @@ -308,9 +298,7 @@ def test_start_stop_step(u, run_kwargs, frames): assert an.n_frames == len(frames) assert_equal(an.found_frames, frames) assert_equal(an.frames, frames, err_msg=FRAMES_ERR) - assert_allclose( - an.times, frames + 1, rtol=0, atol=1.5e-4, err_msg=TIMES_ERR - ) + assert_allclose(an.times, frames + 1, rtol=0, atol=1.5e-4, err_msg=TIMES_ERR) @pytest.mark.parametrize( @@ -438,9 +426,7 @@ def test_frame_bool_fail(client_FrameAnalysis): def test_rewind(client_FrameAnalysis): u = mda.Universe(TPR, XTC) # dt = 100 - an = FrameAnalysis(u.trajectory).run( - **client_FrameAnalysis, frames=[0, 2, 3, 5, 9] - ) + an = FrameAnalysis(u.trajectory).run(**client_FrameAnalysis, frames=[0, 2, 3, 5, 9]) assert_equal(u.trajectory.ts.frame, 0) @@ -453,9 +439,7 @@ def test_frames_times(client_FrameAnalysis): assert an.n_frames == len(frames) assert_equal(an.found_frames, frames) assert_equal(an.frames, frames, err_msg=FRAMES_ERR) - assert_allclose( - an.times, frames * 100, rtol=0, atol=1.5e-4, err_msg=TIMES_ERR - ) + assert_allclose(an.times, frames * 100, rtol=0, atol=1.5e-4, err_msg=TIMES_ERR) def test_verbose(u): @@ -498,9 +482,7 @@ def test_verbose_progressbar_run(u, capsys): def test_verbose_progressbar_run_with_kwargs(u, capsys): - FrameAnalysis(u.trajectory).run( - verbose=True, progressbar_kwargs={"desc": "custom"} - ) + FrameAnalysis(u.trajectory).run(verbose=True, progressbar_kwargs={"desc": "custom"}) _, err = capsys.readouterr() expected = "custom: 100%|██████████" actual = err.strip().split("\r")[-1] @@ -509,9 +491,7 @@ def test_verbose_progressbar_run_with_kwargs(u, capsys): def test_progressbar_multiprocessing(u): with pytest.raises(ValueError): - FrameAnalysis(u.trajectory).run( - backend="multiprocessing", verbose=True - ) + FrameAnalysis(u.trajectory).run(backend="multiprocessing", verbose=True) def test_incomplete_defined_analysis(u): @@ -626,9 +606,7 @@ def test_analysis_class(client_AnalysisFromFunctionAnalysisClass): u = mda.Universe(PSF, DCD) step = 2 - ana = ana_class(u.atoms).run( - step=step, **client_AnalysisFromFunctionAnalysisClass - ) + ana = ana_class(u.atoms).run(step=step, **client_AnalysisFromFunctionAnalysisClass) results = [] for ts in u.trajectory[::step]: diff --git a/testsuite/MDAnalysisTests/analysis/test_bat.py b/testsuite/MDAnalysisTests/analysis/test_bat.py index 704cf616cb7..91c040646a4 100644 --- a/testsuite/MDAnalysisTests/analysis/test_bat.py +++ b/testsuite/MDAnalysisTests/analysis/test_bat.py @@ -70,9 +70,7 @@ def test_bat_root_selection(self, selected_residues): ) def test_bat_number_of_frames(self, bat): - assert_equal( - len(bat), 2, err_msg="error: list is not length of trajectory" - ) + assert_equal(len(bat), 2, err_msg="error: list is not length of trajectory") def test_bat_coordinates(self, bat): test_bat = np.load(BATArray) @@ -85,11 +83,7 @@ def test_bat_coordinates(self, bat): ) def test_bat_coordinates_single_frame(self, selected_residues, client_BAT): - bat = ( - BAT(selected_residues) - .run(start=1, stop=2, **client_BAT) - .results.bat - ) + bat = BAT(selected_residues).run(start=1, stop=2, **client_BAT).results.bat test_bat = [np.load(BATArray)[1]] assert_allclose( bat, @@ -135,9 +129,7 @@ def test_bat_bad_initial_atom(self, selected_residues): def test_bat_disconnected_atom_group(self): u = mda.Universe(PSF, DCD) - selected_residues = u.select_atoms("resid 1-3") + u.select_atoms( - "resid 5-7" - ) + selected_residues = u.select_atoms("resid 1-3") + u.select_atoms("resid 5-7") errmsg = "Additional torsions not found." with pytest.raises(ValueError, match=errmsg): R = BAT(selected_residues) diff --git a/testsuite/MDAnalysisTests/analysis/test_contacts.py b/testsuite/MDAnalysisTests/analysis/test_contacts.py index 7f4a5b69ecc..7868acc5e9d 100644 --- a/testsuite/MDAnalysisTests/analysis/test_contacts.py +++ b/testsuite/MDAnalysisTests/analysis/test_contacts.py @@ -206,9 +206,7 @@ def test_contacts_selections(self, universe, client_Contacts): aga = universe.select_atoms(self.sel_acidic) agb = universe.select_atoms(self.sel_basic) - cag = contacts.Contacts( - universe, select=(aga, agb), refgroup=(aga, agb) - ) + cag = contacts.Contacts(universe, select=(aga, agb), refgroup=(aga, agb)) csel = contacts.Contacts( universe, @@ -244,9 +242,7 @@ def test_startframe(self, universe, client_Contacts): def test_end_zero(self, universe, client_Contacts): """test_end_zero: TestContactAnalysis1: stop frame 0 is not ignored""" - CA1 = self._run_Contacts( - universe, client_Contacts=client_Contacts, stop=0 - ) + CA1 = self._run_Contacts(universe, client_Contacts=client_Contacts, stop=0) assert len(CA1.results.timeseries) == 0 def test_slicing(self, universe, client_Contacts): @@ -275,9 +271,7 @@ def test_villin_folded(self, client_Contacts): q.run(**client_Contacts) results = soft_cut(f, u, sel, sel) - assert_allclose( - q.results.timeseries[:, 1], results[:, 1], rtol=0, atol=1.5e-7 - ) + assert_allclose(q.results.timeseries[:, 1], results[:, 1], rtol=0, atol=1.5e-7) def test_villin_unfolded(self, client_Contacts): # both folded @@ -293,9 +287,7 @@ def test_villin_unfolded(self, client_Contacts): q.run(**client_Contacts) results = soft_cut(f, u, sel, sel) - assert_allclose( - q.results.timeseries[:, 1], results[:, 1], rtol=0, atol=1.5e-7 - ) + assert_allclose(q.results.timeseries[:, 1], results[:, 1], rtol=0, atol=1.5e-7) def test_hard_cut_method(self, universe, client_Contacts): ca = self._run_Contacts(universe, client_Contacts=client_Contacts) @@ -324,9 +316,7 @@ def test_hard_cut_method(self, universe, client_Contacts): ] # fmt: on assert len(ca.results.timeseries) == len(expected) - assert_allclose( - ca.results.timeseries[:, 1], expected, rtol=0, atol=1.5e-7 - ) + assert_allclose(ca.results.timeseries[:, 1], expected, rtol=0, atol=1.5e-7) def test_radius_cut_method(self, universe, client_Contacts): acidic = universe.select_atoms(self.sel_acidic) @@ -438,16 +428,12 @@ def test_distance_box(self, pbc, expected, client_Contacts): pbc=pbc, ) r.run(**client_Contacts) - assert_allclose( - r.results.timeseries[:, 1], expected, rtol=0, atol=1.5e-7 - ) + assert_allclose(r.results.timeseries[:, 1], expected, rtol=0, atol=1.5e-7) def test_warn_deprecated_attr(self, universe, client_Contacts): """Test for warning message emitted on using deprecated `timeseries` attribute""" - CA1 = self._run_Contacts( - universe, client_Contacts=client_Contacts, stop=1 - ) + CA1 = self._run_Contacts(universe, client_Contacts=client_Contacts, stop=1) wmsg = "The `timeseries` attribute was deprecated in MDAnalysis" with pytest.warns(DeprecationWarning, match=wmsg): assert_equal(CA1.timeseries, CA1.results.timeseries) @@ -494,9 +480,7 @@ def test_q1q2(client_Contacts): 0.93006358, 0.9346049, 0.93188011, ] # fmt: on - assert_allclose( - q1q2.results.timeseries[:, 1], q1_expected, rtol=0, atol=1.5e-7 - ) + assert_allclose(q1q2.results.timeseries[:, 1], q1_expected, rtol=0, atol=1.5e-7) # fmt: off q2_expected = [ @@ -522,6 +506,4 @@ def test_q1q2(client_Contacts): 0.98616236, 0.9898524, 1.0, ] # fmt: on - assert_allclose( - q1q2.results.timeseries[:, 2], q2_expected, rtol=0, atol=1.5e-7 - ) + assert_allclose(q1q2.results.timeseries[:, 2], q2_expected, rtol=0, atol=1.5e-7) diff --git a/testsuite/MDAnalysisTests/analysis/test_density.py b/testsuite/MDAnalysisTests/analysis/test_density.py index daaf3325d6d..2fd4c57a966 100644 --- a/testsuite/MDAnalysisTests/analysis/test_density.py +++ b/testsuite/MDAnalysisTests/analysis/test_density.py @@ -51,9 +51,7 @@ def bins(self): def h_and_edges(self, bins): return np.histogramdd( self.Lmax - * np.sin(np.linspace(0, 1, self.counts * 3)).reshape( - self.counts, 3 - ), + * np.sin(np.linspace(0, 1, self.counts * 3)).reshape(self.counts, 3), bins=bins, ) @@ -237,9 +235,7 @@ class DensityParameters(object): @pytest.fixture() def universe(self): - return mda.Universe( - self.topology, self.trajectory, tpr_resid_from_one=False - ) + return mda.Universe(self.topology, self.trajectory, tpr_resid_from_one=False) class TestDensityAnalysis(DensityParameters): @@ -364,9 +360,7 @@ def test_ValueError_userdefn_gridcenter_shape( self, universe, client_DensityAnalysis ): # Test len(gridcenter) != 3 - with pytest.raises( - ValueError, match="Gridcenter must be a 3D coordinate" - ): + with pytest.raises(ValueError, match="Gridcenter must be a 3D coordinate"): D = density.DensityAnalysis( universe.select_atoms(self.selections["static"]), delta=self.delta, @@ -380,9 +374,7 @@ def test_ValueError_userdefn_gridcenter_type( self, universe, client_DensityAnalysis ): # Test gridcenter includes non-numeric strings - with pytest.raises( - ValueError, match="Gridcenter must be a 3D coordinate" - ): + with pytest.raises(ValueError, match="Gridcenter must be a 3D coordinate"): D = density.DensityAnalysis( universe.select_atoms(self.selections["static"]), delta=self.delta, @@ -406,13 +398,9 @@ def test_ValueError_userdefn_gridcenter_missing( zdim=10.0, ).run(step=5, **client_DensityAnalysis) - def test_ValueError_userdefn_xdim_type( - self, universe, client_DensityAnalysis - ): + def test_ValueError_userdefn_xdim_type(self, universe, client_DensityAnalysis): # Test xdim != int or float - with pytest.raises( - ValueError, match="xdim, ydim, and zdim must be numbers" - ): + with pytest.raises(ValueError, match="xdim, ydim, and zdim must be numbers"): D = density.DensityAnalysis( universe.select_atoms(self.selections["static"]), delta=self.delta, @@ -422,9 +410,7 @@ def test_ValueError_userdefn_xdim_type( gridcenter=self.gridcenters["static_defined"], ).run(step=5, **client_DensityAnalysis) - def test_ValueError_userdefn_xdim_nanvalue( - self, universe, client_DensityAnalysis - ): + def test_ValueError_userdefn_xdim_nanvalue(self, universe, client_DensityAnalysis): # Test xdim set to NaN value regex = "Gridcenter or grid dimensions have NaN element" with pytest.raises(ValueError, match=regex): @@ -471,9 +457,7 @@ def test_ValueError_noatomgroup(self, universe, client_DensityAnalysis): ).run(step=5, **client_DensityAnalysis) def test_warn_results_deprecated(self, universe, client_DensityAnalysis): - D = density.DensityAnalysis( - universe.select_atoms(self.selections["static"]) - ) + D = density.DensityAnalysis(universe.select_atoms(self.selections["static"])) D.run(stop=1, **client_DensityAnalysis) wmsg = "The `density` attribute was deprecated in MDAnalysis 2.0.0" with pytest.warns(DeprecationWarning, match=wmsg): @@ -509,7 +493,5 @@ def test_presence_griddata(self): try: import MDAnalysis.analysis.density except ImportError: - pytest.fail( - msg="""MDAnalysis.analysis.density should not raise - an ImportError if gridData is available.""" - ) + pytest.fail(msg="""MDAnalysis.analysis.density should not raise + an ImportError if gridData is available.""") diff --git a/testsuite/MDAnalysisTests/analysis/test_dielectric.py b/testsuite/MDAnalysisTests/analysis/test_dielectric.py index 45d8e722cdb..ba19e407807 100644 --- a/testsuite/MDAnalysisTests/analysis/test_dielectric.py +++ b/testsuite/MDAnalysisTests/analysis/test_dielectric.py @@ -58,9 +58,7 @@ def test_temperature(self, ag): def test_non_charges(self): u = mda.Universe(DCD_TRICLINIC, to_guess=()) - with pytest.raises( - NoDataError, match="No charges defined given atomgroup." - ): + with pytest.raises(NoDataError, match="No charges defined given atomgroup."): DielectricConstant(u.atoms).run() def test_non_neutral(self, ag): diff --git a/testsuite/MDAnalysisTests/analysis/test_diffusionmap.py b/testsuite/MDAnalysisTests/analysis/test_diffusionmap.py index 27805abfbcf..a2b2c4ad1f7 100644 --- a/testsuite/MDAnalysisTests/analysis/test_diffusionmap.py +++ b/testsuite/MDAnalysisTests/analysis/test_diffusionmap.py @@ -55,9 +55,7 @@ def test_eg(dist, dmap): def test_dist_weights(u, client_DistanceMatrix): backbone = u.select_atoms("backbone") weights_atoms = np.ones(len(backbone.atoms)) - dist = diffusionmap.DistanceMatrix( - u, select="backbone", weights=weights_atoms - ) + dist = diffusionmap.DistanceMatrix(u, select="backbone", weights=weights_atoms) dist.run(**client_DistanceMatrix, step=3) dmap = diffusionmap.DiffusionMap(dist) dmap.run() @@ -107,9 +105,7 @@ def test_distvalues_ag_universe(u, client_DistanceMatrix): ) ag = u.select_atoms("backbone") dist_ag = diffusionmap.DistanceMatrix(ag).run(**client_DistanceMatrix) - assert_allclose( - dist_universe.results.dist_matrix, dist_ag.results.dist_matrix - ) + assert_allclose(dist_universe.results.dist_matrix, dist_ag.results.dist_matrix) def test_distvalues_ag_select(u, client_DistanceMatrix): @@ -120,9 +116,7 @@ def test_distvalues_ag_select(u, client_DistanceMatrix): dist_ag = diffusionmap.DistanceMatrix(ag, select="backbone").run( **client_DistanceMatrix ) - assert_allclose( - dist_universe.results.dist_matrix, dist_ag.results.dist_matrix - ) + assert_allclose(dist_universe.results.dist_matrix, dist_ag.results.dist_matrix) def test_different_steps(u): diff --git a/testsuite/MDAnalysisTests/analysis/test_dihedrals.py b/testsuite/MDAnalysisTests/analysis/test_dihedrals.py index 82625dfb934..62efb550b50 100644 --- a/testsuite/MDAnalysisTests/analysis/test_dihedrals.py +++ b/testsuite/MDAnalysisTests/analysis/test_dihedrals.py @@ -48,9 +48,7 @@ class TestDihedral(object): @pytest.fixture() def atomgroup(self): u = mda.Universe(GRO, XTC) - ag = u.select_atoms( - "(resid 4 and name N CA C) or (resid 5 and name N)" - ) + ag = u.select_atoms("(resid 4 and name N CA C) or (resid 5 and name N)") return ag def test_dihedral(self, atomgroup, client_Dihedral): @@ -72,9 +70,7 @@ def test_dihedral(self, atomgroup, client_Dihedral): ) def test_dihedral_single_frame(self, atomgroup, client_Dihedral): - dihedral = Dihedral([atomgroup]).run( - start=5, stop=6, **client_Dihedral - ) + dihedral = Dihedral([atomgroup]).run(start=5, stop=6, **client_Dihedral) test_dihedral = [np.load(DihedralArray)[5]] assert_allclose( @@ -120,9 +116,7 @@ def rama_ref_array(self): return np.load(RamaArray) def test_ramachandran(self, universe, rama_ref_array, client_Ramachandran): - rama = Ramachandran(universe.select_atoms("protein")).run( - **client_Ramachandran - ) + rama = Ramachandran(universe.select_atoms("protein")).run(**client_Ramachandran) assert_allclose( rama.results.angles, @@ -147,9 +141,7 @@ def test_ramachandran_single_frame( err_msg="error: dihedral angles should " "match test values", ) - def test_ramachandran_residue_selections( - self, universe, client_Ramachandran - ): + def test_ramachandran_residue_selections(self, universe, client_Ramachandran): rama = Ramachandran(universe.select_atoms("resname GLY")).run( **client_Ramachandran ) @@ -187,11 +179,7 @@ def test_None_removal(self): rama = Ramachandran(u.select_atoms("protein").residues[1:-1]) def test_plot(self, universe): - ax = ( - Ramachandran(universe.select_atoms("resid 5-10")) - .run() - .plot(ref=True) - ) + ax = Ramachandran(universe.select_atoms("resid 5-10")).run().plot(ref=True) assert isinstance( ax, matplotlib.axes.Axes ), "Ramachandran.plot() did not return and Axes instance" @@ -272,9 +260,7 @@ def test_atom_selection(self): with pytest.raises(ValueError): u = mda.Universe(PDB_janin) janin = Janin( - u.select_atoms( - "protein and not resname ALA CYS GLY " "PRO SER THR VAL" - ) + u.select_atoms("protein and not resname ALA CYS GLY " "PRO SER THR VAL") ) def test_plot(self, universe): diff --git a/testsuite/MDAnalysisTests/analysis/test_distances.py b/testsuite/MDAnalysisTests/analysis/test_distances.py index 60c362d5cd6..b8c8ca0c8f2 100644 --- a/testsuite/MDAnalysisTests/analysis/test_distances.py +++ b/testsuite/MDAnalysisTests/analysis/test_distances.py @@ -93,36 +93,28 @@ def test_np(self, coord, shape, res_no_pbc): contacts = MDAnalysis.analysis.distances.contact_matrix( coord, cutoff=1, returntype="numpy" ) - assert contacts.shape == shape, "wrong shape (should be {0})".format( - shape - ) + assert contacts.shape == shape, "wrong shape (should be {0})".format(shape) assert_array_equal(contacts, res_no_pbc) def test_sparse(self, coord, shape, res_no_pbc): contacts = MDAnalysis.analysis.distances.contact_matrix( coord, cutoff=1.5, returntype="sparse" ) - assert contacts.shape == shape, "wrong shape (should be {0})".format( - shape - ) + assert contacts.shape == shape, "wrong shape (should be {0})".format(shape) assert_array_equal(contacts.toarray(), res_no_pbc) def test_box_numpy(self, coord, box, shape, res_pbc): contacts = MDAnalysis.analysis.distances.contact_matrix( coord, box=box, cutoff=1 ) - assert contacts.shape == shape, "wrong shape (should be {0})".format( - shape - ) + assert contacts.shape == shape, "wrong shape (should be {0})".format(shape) assert_array_equal(contacts, res_pbc) def test_box_sparse(self, coord, box, shape, res_pbc): contacts = MDAnalysis.analysis.distances.contact_matrix( coord, box=box, cutoff=1, returntype="sparse" ) - assert contacts.shape == shape, "wrong shape (should be {0})".format( - shape - ) + assert contacts.shape == shape, "wrong shape (should be {0})".format(shape) assert_array_equal(contacts.toarray(), res_pbc) @@ -150,9 +142,7 @@ def box(): @pytest.fixture() def expected(ag, ag2): - return np.diag( - scipy.spatial.distance.cdist(ag.positions, ag2.positions) - ) + return np.diag(scipy.spatial.distance.cdist(ag.positions, ag2.positions)) @staticmethod @pytest.fixture() @@ -220,9 +210,7 @@ def group(u): @pytest.fixture() def expected(self, group, ag, ag2): - distance_matrix_1 = scipy.spatial.distance.cdist( - group.positions, ag.positions - ) + distance_matrix_1 = scipy.spatial.distance.cdist(group.positions, ag.positions) mask_1 = np.unique(np.where(distance_matrix_1 <= self.distance)[0]) group_filtered = group[mask_1] distance_matrix_2 = scipy.spatial.distance.cdist( diff --git a/testsuite/MDAnalysisTests/analysis/test_dssp.py b/testsuite/MDAnalysisTests/analysis/test_dssp.py index 93596ebdeaa..11730c369c0 100644 --- a/testsuite/MDAnalysisTests/analysis/test_dssp.py +++ b/testsuite/MDAnalysisTests/analysis/test_dssp.py @@ -10,9 +10,7 @@ # Files that match glob pattern '????.pdb.gz' and matching '????.pdb.dssp' files, # containing the secondary structure assignment string, will be tested automatically. -@pytest.mark.parametrize( - "pdb_filename", glob.glob(f"{DSSP_FOLDER}/?????.pdb.gz") -) +@pytest.mark.parametrize("pdb_filename", glob.glob(f"{DSSP_FOLDER}/?????.pdb.gz")) def test_file_guess_hydrogens(pdb_filename, client_DSSP): u = mda.Universe(pdb_filename) with open(f"{pdb_filename.rstrip('.gz')}.dssp", "r") as fin: @@ -30,9 +28,7 @@ def test_trajectory(client_DSSP): last_frame = "".join(run.results.dssp[-1]) avg_frame = "".join(translate(run.results.dssp_ndarray.mean(axis=0))) - assert ( - first_frame[:10] != last_frame[:10] == avg_frame[:10] == "-EEEEEE---" - ) + assert first_frame[:10] != last_frame[:10] == avg_frame[:10] == "-EEEEEE---" def test_atomgroup(client_DSSP): @@ -42,9 +38,7 @@ def test_atomgroup(client_DSSP): last_frame = "".join(run.results.dssp[-1]) avg_frame = "".join(translate(run.results.dssp_ndarray.mean(axis=0))) - assert ( - first_frame[:10] != last_frame[:10] == avg_frame[:10] == "-EEEEEE---" - ) + assert first_frame[:10] != last_frame[:10] == avg_frame[:10] == "-EEEEEE---" def test_trajectory_with_hydrogens(client_DSSP): @@ -54,14 +48,10 @@ def test_trajectory_with_hydrogens(client_DSSP): last_frame = "".join(run.results.dssp[-1]) avg_frame = "".join(translate(run.results.dssp_ndarray.mean(axis=0))) - assert ( - first_frame[:10] == last_frame[:10] == avg_frame[:10] == "-EEEEEE---" - ) + assert first_frame[:10] == last_frame[:10] == avg_frame[:10] == "-EEEEEE---" -@pytest.mark.parametrize( - "pdb_filename", glob.glob(f"{DSSP_FOLDER}/2xdgA.pdb.gz") -) +@pytest.mark.parametrize("pdb_filename", glob.glob(f"{DSSP_FOLDER}/2xdgA.pdb.gz")) def test_trajectory_without_hydrogen_fails(pdb_filename, client_DSSP): u = mda.Universe(pdb_filename) with pytest.raises(ValueError): @@ -71,9 +61,7 @@ def test_trajectory_without_hydrogen_fails(pdb_filename, client_DSSP): @pytest.mark.parametrize( "pdb_filename", glob.glob(f"{DSSP_FOLDER}/1mr1D_failing.pdb.gz") ) -def test_trajectory_with_uneven_number_of_atoms_fails( - pdb_filename, client_DSSP -): +def test_trajectory_with_uneven_number_of_atoms_fails(pdb_filename, client_DSSP): u = mda.Universe(pdb_filename) with pytest.raises(ValueError): DSSP(u, guess_hydrogens=True).run(**client_DSSP) diff --git a/testsuite/MDAnalysisTests/analysis/test_encore.py b/testsuite/MDAnalysisTests/analysis/test_encore.py index 9204352f480..3dbc3271ce2 100644 --- a/testsuite/MDAnalysisTests/analysis/test_encore.py +++ b/testsuite/MDAnalysisTests/analysis/test_encore.py @@ -90,9 +90,7 @@ def test_triangular_matrix(self): triangular_matrix[0, 1] = expected_value - err_msg = ( - "Data error in TriangularMatrix: read/write are not consistent" - ) + err_msg = "Data error in TriangularMatrix: read/write are not consistent" assert_equal(triangular_matrix[0, 1], expected_value, err_msg) assert_equal( @@ -169,23 +167,18 @@ def test_parallel_calculation(self): ) def test_rmsd_matrix_with_superimposition(self, ens1): - conf_dist_matrix = ( - encore.confdistmatrix.conformational_distance_matrix( - ens1, - encore.confdistmatrix.set_rmsd_matrix_elements, - select="name CA", - pairwise_align=True, - weights="mass", - n_jobs=1, - ) + conf_dist_matrix = encore.confdistmatrix.conformational_distance_matrix( + ens1, + encore.confdistmatrix.set_rmsd_matrix_elements, + select="name CA", + pairwise_align=True, + weights="mass", + n_jobs=1, ) reference = rms.RMSD(ens1, select="name CA") reference.run() - err_msg = ( - "Calculated RMSD values differ from " - "the reference implementation" - ) + err_msg = "Calculated RMSD values differ from " "the reference implementation" for i, rmsd in enumerate(reference.results.rmsd): assert_allclose( conf_dist_matrix[0, i], @@ -196,29 +189,25 @@ def test_rmsd_matrix_with_superimposition(self, ens1): ) def test_rmsd_matrix_with_superimposition_custom_weights(self, ens1): - conf_dist_matrix = ( - encore.confdistmatrix.conformational_distance_matrix( - ens1, - encore.confdistmatrix.set_rmsd_matrix_elements, - select="name CA", - pairwise_align=True, - weights="mass", - n_jobs=1, - ) + conf_dist_matrix = encore.confdistmatrix.conformational_distance_matrix( + ens1, + encore.confdistmatrix.set_rmsd_matrix_elements, + select="name CA", + pairwise_align=True, + weights="mass", + n_jobs=1, ) - conf_dist_matrix_custom = ( - encore.confdistmatrix.conformational_distance_matrix( - ens1, - encore.confdistmatrix.set_rmsd_matrix_elements, - select="name CA", - pairwise_align=True, - weights=( - ens1.select_atoms("name CA").masses, - ens1.select_atoms("name CA").masses, - ), - n_jobs=1, - ) + conf_dist_matrix_custom = encore.confdistmatrix.conformational_distance_matrix( + ens1, + encore.confdistmatrix.set_rmsd_matrix_elements, + select="name CA", + pairwise_align=True, + weights=( + ens1.select_atoms("name CA").masses, + ens1.select_atoms("name CA").masses, + ), + n_jobs=1, ) for i in range(conf_dist_matrix_custom.size): @@ -235,9 +224,7 @@ def test_rmsd_matrix_without_superimposition(self, ens1): reference_rmsd = [] coordinates = ens1.trajectory.timeseries(selection, order="fac") for coord in coordinates: - reference_rmsd.append( - rms.rmsd(coordinates[0], coord, superposition=False) - ) + reference_rmsd.append(rms.rmsd(coordinates[0], coord, superposition=False)) confdist_matrix = encore.confdistmatrix.conformational_distance_matrix( ens1, @@ -360,12 +347,8 @@ def test_covariance_matrix_with_reference(self, ens1): estimator=encore.covariance.shrinkage_covariance_estimator, reference=ens1, ) - err_msg = ( - "Covariance matrix from covariance estimation not as expected" - ) - assert_allclose( - covariance, reference_cov, rtol=0, atol=1.5e-4, err_msg=err_msg - ) + err_msg = "Covariance matrix from covariance estimation not as expected" + assert_allclose(covariance, reference_cov, rtol=0, atol=1.5e-4, err_msg=err_msg) def test_hes_to_self(self, ens1): results, details = encore.hes([ens1, ens1]) @@ -377,9 +360,7 @@ def test_hes_to_self(self, ens1): rtol=0, atol=1.5e-7, err_msg="Harmonic Ensemble Similarity to itself\ - not zero:{0:f}".format( - result_value - ), + not zero:{0:f}".format(result_value), ) def test_hes(self, ens1, ens2): @@ -425,9 +406,7 @@ def test_hes_align(self, ens1, ens2): def test_ces_to_self(self, ens1): results, details = encore.ces( [ens1, ens1], - clustering_method=encore.AffinityPropagationNative( - preference=-3.0 - ), + clustering_method=encore.AffinityPropagationNative(preference=-3.0), ) result_value = results[0, 1] expected_value = 0.0 @@ -470,9 +449,7 @@ def test_dres_to_self(self, ens1): ) def test_dres(self, ens1, ens2): - results, details = encore.dres( - [ens1, ens2], select="name CA and resnum 1-10" - ) + results, details = encore.dres([ens1, ens2], select="name CA and resnum 1-10") result_value = results[0, 1] upper_bound = 0.6 assert result_value < upper_bound, ( @@ -487,9 +464,7 @@ def test_dres_without_superimposition(self, ens1, ens2): distance_matrix = encore.get_distance_matrix( encore.merge_universes([ens1, ens2]), superimpose=False ) - results, details = encore.dres( - [ens1, ens2], distance_matrix=distance_matrix - ) + results, details = encore.dres([ens1, ens2], distance_matrix=distance_matrix) result_value = results[0, 1] expected_value = 0.68 assert_allclose( @@ -521,9 +496,7 @@ def test_dres_convergence(self, ens1): expected_values = [0.3, 0.0] results = encore.dres_convergence(ens1, 10) try: - assert_allclose( - results[:, 0], expected_values, rtol=0, atol=1.5e-1 - ) + assert_allclose(results[:, 0], expected_values, rtol=0, atol=1.5e-1) except AssertionError: # Random test failure is very rare, but repeating the failed test # just once would only assert that the test passes with 50% @@ -566,12 +539,8 @@ def test_hes_error_estimation(self, ens1): "Unexpected standard deviation for bootstrapped samples in" " Harmonic Ensemble similarity" ) - assert_allclose( - average, expected_average, rtol=0, atol=1.5e2, err_msg=err_msg - ) - assert_allclose( - stdev, expected_stdev, rtol=0, atol=1.5e2, err_msg=error_msg - ) + assert_allclose(average, expected_average, rtol=0, atol=1.5e2, err_msg=err_msg) + assert_allclose(stdev, expected_stdev, rtol=0, atol=1.5e2, err_msg=error_msg) def test_ces_error_estimation(self, ens1): expected_average = 0.03 @@ -580,9 +549,7 @@ def test_ces_error_estimation(self, ens1): [ens1, ens1], estimate_error=True, bootstrapping_samples=10, - clustering_method=encore.AffinityPropagationNative( - preference=-2.0 - ), + clustering_method=encore.AffinityPropagationNative(preference=-2.0), select="name CA and resnum 1-10", ) average = averages[0, 1] @@ -625,16 +592,12 @@ def test_ces_error_estimation_ensemble_bootstrap(self, ens1): "Unexpected average value for bootstrapped samples in" " Clustering Ensemble similarity" ) - assert_allclose( - average, expected_average, rtol=0, atol=1.5e-1, err_msg=err_msg - ) + assert_allclose(average, expected_average, rtol=0, atol=1.5e-1, err_msg=err_msg) error_msg = ( "Unexpected standard deviation for bootstrapped samples in" " Clustering Ensemble similarity" ) - assert_allclose( - stdev, expected_stdev, rtol=0, atol=1.5e-1, err_msg=error_msg - ) + assert_allclose(stdev, expected_stdev, rtol=0, atol=1.5e-1, err_msg=error_msg) def test_dres_error_estimation(self, ens1): average_upper_bound = 0.3 @@ -806,9 +769,7 @@ def test_clustering_two_methods_one_w_no_distance_matrix(self, ens1): def test_sklearn_affinity_propagation(self, ens1): pytest.importorskip("sklearn") cc1 = encore.cluster([ens1]) - cc2 = encore.cluster( - [ens1], method=encore.AffinityPropagation(random_state=0) - ) + cc2 = encore.cluster([ens1], method=encore.AffinityPropagation(random_state=0)) assert len(cc1) == len(cc2), ( "Native and sklearn implementations of affinity " "propagation don't agree: mismatch in number of " @@ -852,8 +813,7 @@ def test_cluster_add_metadata(self, cluster): ) metadata = np.append(metadata, 9) error_message = ( - "Size of metadata is not equal to the " - "number of cluster elements" + "Size of metadata is not equal to the " "number of cluster elements" ) with pytest.raises(TypeError, match=error_message): cluster.add_metadata("test2", metadata) @@ -876,9 +836,7 @@ def test_metadata_size_error(self): "not equal to the number of cluster elements" ) with pytest.raises(TypeError, match=error_message): - encore.Cluster( - np.array([1, 1, 1]), 1, None, {"label": [1, 1, 1, 1]} - ) + encore.Cluster(np.array([1, 1, 1]), 1, None, {"label": [1, 1, 1, 1]}) def test_cluster_iteration(self, cluster): test = [] @@ -988,9 +946,7 @@ def distance_matrix(self): def test_one(self, distance_matrix): preference = -float(np.median(distance_matrix.as_array()) * 10.0) - clustering_method = encore.AffinityPropagationNative( - preference=preference - ) + clustering_method = encore.AffinityPropagationNative(preference=preference) ccs = encore.cluster( None, distance_matrix=distance_matrix, method=clustering_method ) @@ -1051,16 +1007,10 @@ def test_dimensionality_reduction_two_ensembles(self, ens1, ens2): ), ) - def test_dimensionality_reduction_three_ensembles_two_identical( - self, ens1, ens2 - ): + def test_dimensionality_reduction_three_ensembles_two_identical(self, ens1, ens2): coordinates, details = encore.reduce_dimensionality([ens1, ens2, ens1]) - coordinates_ens1 = coordinates[ - :, np.where(details["ensemble_membership"] == 1) - ] - coordinates_ens3 = coordinates[ - :, np.where(details["ensemble_membership"] == 3) - ] + coordinates_ens1 = coordinates[:, np.where(details["ensemble_membership"] == 1)] + coordinates_ens3 = coordinates[:, np.where(details["ensemble_membership"] == 3)] assert_allclose( coordinates_ens1, coordinates_ens3, @@ -1075,9 +1025,7 @@ def test_dimensionality_reduction_specified_dimension(self, ens1, ens2): dimension = 3 coordinates, details = encore.reduce_dimensionality( [ens1, ens2], - method=encore.StochasticProximityEmbeddingNative( - dimension=dimension - ), + method=encore.StochasticProximityEmbeddingNative(dimension=dimension), ) assert_equal( coordinates.shape[0], diff --git a/testsuite/MDAnalysisTests/analysis/test_gnm.py b/testsuite/MDAnalysisTests/analysis/test_gnm.py index 19d5a000937..31d34c8a720 100644 --- a/testsuite/MDAnalysisTests/analysis/test_gnm.py +++ b/testsuite/MDAnalysisTests/analysis/test_gnm.py @@ -27,7 +27,7 @@ import MDAnalysis.analysis.gnm import numpy as np import pytest -from numpy.testing import assert_almost_equal +from numpy.testing import assert_almost_equal, assert_allclose from MDAnalysisTests.datafiles import GRO, XTC @@ -43,8 +43,10 @@ def test_gnm(universe, tmpdir, client_GNMAnalysis): gnm.run(**client_GNMAnalysis) result = gnm.results assert len(result.times) == 10 - assert_almost_equal(gnm.results.times, np.arange(0, 1000, 100), decimal=4) - assert_almost_equal( + assert_allclose( + gnm.results.times, np.arange(0, 1000, 100), atol=1e-4 + ) + assert_allclose( gnm.results.eigenvalues, [ 2.0287113e-15, @@ -58,6 +60,7 @@ def test_gnm(universe, tmpdir, client_GNMAnalysis): 4.2058769e-15, 3.9839431e-15, ], + atol=1e-4, ) @@ -66,10 +69,13 @@ def test_gnm_run_step(universe, client_GNMAnalysis): gnm.run(step=3, **client_GNMAnalysis) result = gnm.results assert len(result.times) == 4 - assert_almost_equal(gnm.results.times, np.arange(0, 1200, 300), decimal=4) - assert_almost_equal( + assert_allclose( + gnm.results.times, np.arange(0, 1200, 300), atol=1e-4 + ) + assert_allclose( gnm.results.eigenvalues, [2.0287113e-15, 4.3810359e-15, 2.5501084e-15, 3.9839431e-15], + atol=1e-4, ) @@ -77,7 +83,7 @@ def test_generate_kirchoff(universe): gnm = mda.analysis.gnm.GNMAnalysis(universe) gen = gnm.generate_kirchoff() # fmt: off - assert_almost_equal( + assert_allclose( gen[0], [ 7,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -111,11 +117,13 @@ def test_closeContactGNMAnalysis(universe, client_GNMAnalysis): gnm.run(stop=2, **client_GNMAnalysis) result = gnm.results assert len(result.times) == 2 - assert_almost_equal(gnm.results.times, (0, 100), decimal=4) - assert_almost_equal(gnm.results.eigenvalues, [0.1502614, 0.1426407]) + assert_allclose(gnm.results.times, (0, 100), atol=1e-4) + assert_allclose( + gnm.results.eigenvalues, [0.1502614, 0.1426407], atol=1e-4 + ) gen = gnm.generate_kirchoff() # fmt: off - assert_almost_equal( + assert_allclose( gen[0], [ 16.326744128018923, -2.716098853586913, -1.94736842105263, 0.0, @@ -148,11 +156,13 @@ def test_closeContactGNMAnalysis_weights_None(universe, client_GNMAnalysis): gnm.run(stop=2, **client_GNMAnalysis) result = gnm.results assert len(result.times) == 2 - assert_almost_equal(gnm.results.times, (0, 100), decimal=4) - assert_almost_equal(gnm.results.eigenvalues, [2.4328739, 2.2967251]) + assert_allclose(gnm.results.times, (0, 100), atol=1e-4) + assert_allclose( + gnm.results.eigenvalues, [2.4328739, 2.2967251], atol=1e-4 + ) gen = gnm.generate_kirchoff() # fmt: off - assert_almost_equal( + assert_allclose( gen[0], [ 303.0, -58.0, -37.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -185,18 +195,17 @@ def test_closeContactGNMAnalysis_select_CA(universe, client_GNMAnalysis): gnm.run(stop=2, **client_GNMAnalysis) result = gnm.results assert len(result.times) == 2 - assert_almost_equal(gnm.results.times, (0, 100), decimal=4) + assert_allclose(gnm.results.times, (0, 100), atol=1e-4) # without Issue #4924 fix, eigenvalues are [3.20010632e-16, 4.27574601e-16] # but use big totolerance to make sure PASS in each platform - assert_almost_equal( - gnm.results.eigenvalues, - [3.57984776e-16, 3.53892581e-16], + assert_allclose( + gnm.results.eigenvalues, [3.57984776e-16, 3.53892581e-16], atol=1e-4 ) gen = gnm.generate_kirchoff() # without Issue #4924 fix, gnm only use 0~14 residues for this data assert np.abs(gen[15]).sum() > 0 # fmt: off - assert_almost_equal( + assert_allclose( gen[0], [ 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, diff --git a/testsuite/MDAnalysisTests/analysis/test_helix_analysis.py b/testsuite/MDAnalysisTests/analysis/test_helix_analysis.py index e8e50717a24..51ff5e7a16b 100644 --- a/testsuite/MDAnalysisTests/analysis/test_helix_analysis.py +++ b/testsuite/MDAnalysisTests/analysis/test_helix_analysis.py @@ -160,9 +160,7 @@ def test_local_screw_angles_plane_circle(): """ angdeg = np.arange(0, 360, 12, dtype=np.int32) angrad = np.deg2rad(angdeg, dtype=np.float64) - xyz = np.array( - [[np.cos(a), np.sin(a), 0] for a in angrad], dtype=np.float64 - ) + xyz = np.array([[np.cos(a), np.sin(a), 0] for a in angrad], dtype=np.float64) xyz[15, 1] = 0 # because np.sin(np.deg2rad(180)) = 1e-16 ?! screw = hel.local_screw_angles([1, 0, 0], [0, 1, 0], xyz) correct = np.zeros_like(angdeg) @@ -178,9 +176,7 @@ def test_local_screw_angles_ortho_circle(): """ angdeg = np.arange(0, 360, 12, dtype=np.int32) angrad = np.deg2rad(angdeg, dtype=np.float64) - xyz = np.array( - [[np.cos(a), np.sin(a), 0] for a in angrad], dtype=np.float64 - ) + xyz = np.array([[np.cos(a), np.sin(a), 0] for a in angrad], dtype=np.float64) xyz[15, 1] = 0 # because np.sin(np.deg2rad(180)) = 1e-16 ?! screw = hel.local_screw_angles([1, 0, 0], [0, 0, 1], xyz) correct = np.zeros_like(angdeg) @@ -246,9 +242,7 @@ def zigzag(): x x x x x """ n_atoms = 100 - u = mda.Universe.empty( - 100, atom_resindex=np.arange(n_atoms), trajectory=True - ) + u = mda.Universe.empty(100, atom_resindex=np.arange(n_atoms), trajectory=True) xyz = np.array( list( zip( @@ -307,9 +301,7 @@ def test_helix_analysis_zigzag(zigzag, ref_axis, screw_angles): origins = zigzag.atoms.positions[1:-1].copy() origins[:, 0] = 0 assert_almost_equal(properties["local_origins"], origins, decimal=4) - assert_almost_equal( - properties["local_screw_angles"], screw_angles * 49, decimal=4 - ) + assert_almost_equal(properties["local_screw_angles"], screw_angles * 49, decimal=4) def square_oct(n_rep=10): @@ -348,9 +340,7 @@ def test_helix_analysis_square_oct(): properties = hel.helix_analysis(u.atoms.positions, ref_axis=[0, 0, 1]) twist_trans = [102.76438, 32.235607] twists = ([90] * 2 + twist_trans + [45] * 6 + twist_trans[::-1]) * n_rep - assert_almost_equal( - properties["local_twists"], twists[: n_atoms - 3], decimal=4 - ) + assert_almost_equal(properties["local_twists"], twists[: n_atoms - 3], decimal=4) res_trans = [3.503159, 11.167775] res = ([4] * 2 + res_trans + [8] * 6 + res_trans[::-1]) * n_rep assert_almost_equal( @@ -418,9 +408,7 @@ def test_helix_analysis_square_oct(): ] * n_rep # not quite 0, comes out as 1.32e-06 - assert_almost_equal( - properties["local_screw_angles"], screw[:-2], decimal=3 - ) + assert_almost_equal(properties["local_screw_angles"], screw[:-2], decimal=3) class TestHELANAL(object): @@ -433,17 +421,13 @@ def psf_ca(self): @pytest.fixture() def helanal(self, psf_ca): - ha = hel.HELANAL( - psf_ca, select="resnum 161-187", flatten_single_helix=True - ) + ha = hel.HELANAL(psf_ca, select="resnum 161-187", flatten_single_helix=True) return ha.run(start=10, stop=80) def test_regression_summary(self, helanal): bends = helanal.results.summary["all_bends"] old_helanal = read_bending_matrix(HELANAL_BENDING_MATRIX_SUBSET) - assert_almost_equal( - np.triu(bends["mean"], 1), old_helanal["Mean"], decimal=1 - ) + assert_almost_equal(np.triu(bends["mean"], 1), old_helanal["Mean"], decimal=1) assert_almost_equal( np.triu(bends["sample_sd"], 1), old_helanal["SD"], decimal=1 ) @@ -470,9 +454,7 @@ def test_regression_values(self): calculated = ha.results[key][0] msg = "Mismatch between calculated and reference {}" - assert_almost_equal( - calculated, value, decimal=4, err_msg=msg.format(key) - ) + assert_almost_equal(calculated, value, decimal=4, err_msg=msg.format(key)) def test_multiple_selections(self, psf_ca): ha = hel.HELANAL( diff --git a/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel.py b/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel.py index 97eeb6cc016..b3b3bd34f25 100644 --- a/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel.py +++ b/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel.py @@ -245,9 +245,7 @@ def actual_function_int(t): tau2 = 1 tau3 = 0.1 return ( - A1 * np.exp(-t / tau1) - + A2 * np.exp(-t / tau2) - + A3 * np.exp(-t / tau3) + A1 * np.exp(-t / tau1) + A2 * np.exp(-t / tau2) + A3 * np.exp(-t / tau3) ) hbond.solution["time"] = time = np.arange(0, 6.0, 0.01) @@ -321,9 +319,7 @@ def test_solve_before_run_VE(self, u, hydrogens, oxygens, nitrogens): hbond.solve() @mock.patch("MDAnalysis.coordinates.TRZ.TRZReader._read_frame") - def test_unslicable_traj_VE( - self, mock_read, u, hydrogens, oxygens, nitrogens - ): + def test_unslicable_traj_VE(self, mock_read, u, hydrogens, oxygens, nitrogens): mock_read.side_effect = TypeError with pytest.raises(ValueError): diff --git a/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel_deprecated.py b/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel_deprecated.py index e1822b62fa0..70b67e08df3 100644 --- a/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel_deprecated.py +++ b/testsuite/MDAnalysisTests/analysis/test_hydrogenbondautocorrel_deprecated.py @@ -248,9 +248,7 @@ def actual_function_int(t): tau2 = 1 tau3 = 0.1 return ( - A1 * np.exp(-t / tau1) - + A2 * np.exp(-t / tau2) - + A3 * np.exp(-t / tau3) + A1 * np.exp(-t / tau1) + A2 * np.exp(-t / tau2) + A3 * np.exp(-t / tau3) ) hbond.solution["time"] = time = np.arange(0, 6.0, 0.01) @@ -324,9 +322,7 @@ def test_solve_before_run_VE(self, u, hydrogens, oxygens, nitrogens): hbond.solve() @mock.patch("MDAnalysis.coordinates.TRZ.TRZReader._read_frame") - def test_unslicable_traj_VE( - self, mock_read, u, hydrogens, oxygens, nitrogens - ): + def test_unslicable_traj_VE(self, mock_read, u, hydrogens, oxygens, nitrogens): mock_read.side_effect = TypeError with pytest.raises(ValueError): diff --git a/testsuite/MDAnalysisTests/analysis/test_hydrogenbonds_analysis.py b/testsuite/MDAnalysisTests/analysis/test_hydrogenbonds_analysis.py index 59b090c5497..1d0fc894db5 100644 --- a/testsuite/MDAnalysisTests/analysis/test_hydrogenbonds_analysis.py +++ b/testsuite/MDAnalysisTests/analysis/test_hydrogenbonds_analysis.py @@ -89,18 +89,10 @@ def test_hbond_analysis(self, h): "angle": {"mean": 158.9038039, "std": 12.0362826}, } - assert_allclose( - np.mean(h.results.hbonds[:, 4]), reference["distance"]["mean"] - ) - assert_allclose( - np.std(h.results.hbonds[:, 4]), reference["distance"]["std"] - ) - assert_allclose( - np.mean(h.results.hbonds[:, 5]), reference["angle"]["mean"] - ) - assert_allclose( - np.std(h.results.hbonds[:, 5]), reference["angle"]["std"] - ) + assert_allclose(np.mean(h.results.hbonds[:, 4]), reference["distance"]["mean"]) + assert_allclose(np.std(h.results.hbonds[:, 4]), reference["distance"]["std"]) + assert_allclose(np.mean(h.results.hbonds[:, 5]), reference["angle"]["mean"]) + assert_allclose(np.std(h.results.hbonds[:, 5]), reference["angle"]["std"]) def test_count_by_time(self, h): @@ -211,9 +203,7 @@ def universe(): @staticmethod @pytest.fixture(scope="class") def hydrogen_bonds(universe, client_HydrogenBondAnalysis): - h = HydrogenBondAnalysis( - universe, **TestHydrogenBondAnalysisIdeal.kwargs - ) + h = HydrogenBondAnalysis(universe, **TestHydrogenBondAnalysisIdeal.kwargs) h.run(**client_HydrogenBondAnalysis) return h @@ -289,9 +279,7 @@ def test_hydrogen_bond_lifetime(self, hydrogen_bonds): assert_array_equal(timeseries, [1, 0, 0]) def test_hydrogen_bond_lifetime_intermittency(self, hydrogen_bonds): - tau_timeseries, timeseries = hydrogen_bonds.lifetime( - tau_max=2, intermittency=1 - ) + tau_timeseries, timeseries = hydrogen_bonds.lifetime(tau_max=2, intermittency=1) assert_array_equal(timeseries, 1) def test_no_attr_hbonds(self, universe): @@ -300,9 +288,7 @@ def test_no_attr_hbonds(self, universe): with pytest.raises(NoDataError, match=".hbonds attribute is None"): hbonds.lifetime(tau_max=2, intermittency=1) - def test_logging_step_not_1( - self, universe, caplog, client_HydrogenBondAnalysis - ): + def test_logging_step_not_1(self, universe, caplog, client_HydrogenBondAnalysis): hbonds = HydrogenBondAnalysis(universe, **self.kwargs) # using step 2 hbonds.run(**client_HydrogenBondAnalysis, step=2) @@ -310,9 +296,7 @@ def test_logging_step_not_1( caplog.set_level(logging.WARNING) hbonds.lifetime(tau_max=2, intermittency=1) - warning = ( - "Autocorrelation: Hydrogen bonds were computed with " "step > 1." - ) + warning = "Autocorrelation: Hydrogen bonds were computed with " "step > 1." assert any(warning in rec.getMessage() for rec in caplog.records) @@ -387,9 +371,7 @@ def universe(): @staticmethod @pytest.fixture(scope="class") def hydrogen_bonds(universe, client_HydrogenBondAnalysis): - h = HydrogenBondAnalysis( - universe, **TestHydrogenBondAnalysisNoRes.kwargs - ) + h = HydrogenBondAnalysis(universe, **TestHydrogenBondAnalysisNoRes.kwargs) h.run(**client_HydrogenBondAnalysis) return h @@ -497,9 +479,7 @@ def test_between_all(self, universe, client_HydrogenBondAnalysis): [6, 7, 8], # protein-protein ] expected_hbond_distances = [2.5, 3.0, 3.0] - assert_array_equal( - hbonds.results.hbonds[:, 1:4], expected_hbond_indices - ) + assert_array_equal(hbonds.results.hbonds[:, 1:4], expected_hbond_indices) assert_allclose(hbonds.results.hbonds[:, 4], expected_hbond_distances) def test_between_PW(self, universe, client_HydrogenBondAnalysis): @@ -512,9 +492,7 @@ def test_between_PW(self, universe, client_HydrogenBondAnalysis): # indices of [donor, hydrogen, acceptor] for each hydrogen bond expected_hbond_indices = [[3, 4, 6]] # protein-water expected_hbond_distances = [3.0] - assert_array_equal( - hbonds.results.hbonds[:, 1:4], expected_hbond_indices - ) + assert_array_equal(hbonds.results.hbonds[:, 1:4], expected_hbond_indices) assert_allclose(hbonds.results.hbonds[:, 4], expected_hbond_distances) def test_between_PW_PP(self, universe, client_HydrogenBondAnalysis): @@ -536,9 +514,7 @@ def test_between_PW_PP(self, universe, client_HydrogenBondAnalysis): [6, 7, 8], # protein-protein ] expected_hbond_distances = [3.0, 3.0] - assert_array_equal( - hbonds.results.hbonds[:, 1:4], expected_hbond_indices - ) + assert_array_equal(hbonds.results.hbonds[:, 1:4], expected_hbond_indices) assert_allclose(hbonds.results.hbonds[:, 4], expected_hbond_distances) @@ -629,9 +605,7 @@ def h(self, universe): def test_guess_hydrogens(self, h): - ref_hydrogens = ( - "(resname TIP3 and name H1) or (resname TIP3 and name H2)" - ) + ref_hydrogens = "(resname TIP3 and name H1) or (resname TIP3 and name H2)" hydrogens = h.guess_hydrogens(select="all") assert hydrogens == ref_hydrogens @@ -689,18 +663,10 @@ def test_hbond_analysis(self, h): "angle": {"mean": 157.07768079, "std": 9.72636682}, } - assert_allclose( - np.mean(h.results.hbonds[:, 4]), reference["distance"]["mean"] - ) - assert_allclose( - np.std(h.results.hbonds[:, 4]), reference["distance"]["std"] - ) - assert_allclose( - np.mean(h.results.hbonds[:, 5]), reference["angle"]["mean"] - ) - assert_allclose( - np.std(h.results.hbonds[:, 5]), reference["angle"]["std"] - ) + assert_allclose(np.mean(h.results.hbonds[:, 4]), reference["distance"]["mean"]) + assert_allclose(np.std(h.results.hbonds[:, 4]), reference["distance"]["std"]) + assert_allclose(np.mean(h.results.hbonds[:, 5]), reference["angle"]["mean"]) + assert_allclose(np.std(h.results.hbonds[:, 5]), reference["angle"]["std"]) def test_count_by_time(self, h): @@ -777,6 +743,4 @@ def test_frame_iterator(self, universe): update_selections=False, ) hbonds.run(frames=frames) - assert np.array_equal( - hbonds.count_by_time(), np.array([2, 1, 4, 3, 3, 2, 2]) - ) + assert np.array_equal(hbonds.count_by_time(), np.array([2, 1, 4, 3, 3, 2, 2])) diff --git a/testsuite/MDAnalysisTests/analysis/test_leaflet.py b/testsuite/MDAnalysisTests/analysis/test_leaflet.py index e968bbf8c9c..3052d21da34 100644 --- a/testsuite/MDAnalysisTests/analysis/test_leaflet.py +++ b/testsuite/MDAnalysisTests/analysis/test_leaflet.py @@ -29,7 +29,6 @@ from MDAnalysis.analysis.leaflet import LeafletFinder, optimize_cutoff, HAS_NX from MDAnalysisTests.datafiles import Martini_membrane_gro - LIPID_HEAD_STRING = "name PO4" @@ -61,10 +60,7 @@ def test_leaflet_finder(self, universe, lipid_heads): lfls = LeafletFinder(universe, lipid_heads, pbc=True) top_heads, bottom_heads = lfls.groups() # Make top be... on top. - if ( - top_heads.center_of_geometry()[2] - < bottom_heads.center_of_geometry()[2] - ): + if top_heads.center_of_geometry()[2] < bottom_heads.center_of_geometry()[2]: top_heads, bottom_heads = (bottom_heads, top_heads) assert_equal( top_heads.indices, @@ -99,9 +95,7 @@ def test_pbc_on_off_difference(self, universe, lipid_heads): import networkx lfls_pbc_on = LeafletFinder(universe, lipid_heads, cutoff=7, pbc=True) - lfls_pbc_off = LeafletFinder( - universe, lipid_heads, cutoff=7, pbc=False - ) + lfls_pbc_off = LeafletFinder(universe, lipid_heads, cutoff=7, pbc=False) pbc_on_graph = lfls_pbc_on.graph pbc_off_graph = lfls_pbc_off.graph diff_graph = networkx.difference(pbc_on_graph, pbc_off_graph) @@ -189,13 +183,8 @@ def test_write_selection(self, universe, lipid_heads, tmpdir): ] ) - assert ( - self.lines2one(open("leaflet.vmd").readlines()) - == expected_output - ) + assert self.lines2one(open("leaflet.vmd").readlines()) == expected_output def test_component_index_is_not_none(self, universe, lipid_heads): lfls_ag = LeafletFinder(universe, lipid_heads, cutoff=15.0, pbc=True) - assert_almost_equal( - len(lfls_ag.groups(component_index=0)), 180, decimal=4 - ) + assert_almost_equal(len(lfls_ag.groups(component_index=0)), 180, decimal=4) diff --git a/testsuite/MDAnalysisTests/analysis/test_lineardensity.py b/testsuite/MDAnalysisTests/analysis/test_lineardensity.py index f775e6073a5..67ea3f67aaf 100644 --- a/testsuite/MDAnalysisTests/analysis/test_lineardensity.py +++ b/testsuite/MDAnalysisTests/analysis/test_lineardensity.py @@ -90,16 +90,12 @@ def test_invalid_grouping(client_LinearDensity): ) # test data for grouping='residues' -expected_masses_residues = np.array( - [18.0154, 18.0154, 18.0154, 18.0154, 18.0154] -) +expected_masses_residues = np.array([18.0154, 18.0154, 18.0154, 18.0154, 18.0154]) expected_charges_residues = np.array([0, 0, 0, 0, 0]) expected_xmass_residues = np.array( [0.0, 0.0, 0.0, 0.00717967, 0.00478644, 0.0, 0.0, 0.0, 0.0, 0.0] ) -expected_xcharge_residues = np.array( - [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] -) +expected_xcharge_residues = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) # test data for grouping='segments' expected_masses_segments = np.array([90.0770]) @@ -107,14 +103,10 @@ def test_invalid_grouping(client_LinearDensity): expected_xmass_segments = np.array( [0.0, 0.0, 0.0, 0.01196611, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] ) -expected_xcharge_segments = np.array( - [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] -) +expected_xcharge_segments = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) # test data for grouping='fragments' -expected_masses_fragments = np.array( - [18.0154, 18.0154, 18.0154, 18.0154, 18.0154] -) +expected_masses_fragments = np.array([18.0154, 18.0154, 18.0154, 18.0154, 18.0154]) expected_charges_fragments = np.array([0, 0, 0, 0, 0]) expected_xmass_fragments = np.array( [0.0, 0.0, 0.0, 0.00717967, 0.00478644, 0.0, 0.0, 0.0, 0.0, 0.0] @@ -168,9 +160,7 @@ def test_lineardensity( universe = mda.Universe(waterPSF, waterDCD) sel_string = "all" selection = universe.select_atoms(sel_string) - ld = LinearDensity(selection, grouping, binsize=5).run( - **client_LinearDensity - ) + ld = LinearDensity(selection, grouping, binsize=5).run(**client_LinearDensity) assert_allclose(ld.masses, expected_masses) assert_allclose(ld.charges, expected_charges) # rtol changed here due to floating point imprecision @@ -241,13 +231,9 @@ def test_old_name_deprecations(): assert_allclose(ld.results.x.pos, ld.results.x.mass_density) assert_allclose(ld.results.x.pos_std, ld.results.x.mass_density_stddev) assert_allclose(ld.results.x.char, ld.results.x.charge_density) - assert_allclose( - ld.results.x.char_std, ld.results.x.charge_density_stddev - ) + assert_allclose(ld.results.x.char_std, ld.results.x.charge_density_stddev) for key in testdict.keys(): - assert_allclose( - ld.results["x"][key], ld.results["x"][testdict[key]] - ) + assert_allclose(ld.results["x"][key], ld.results["x"][testdict[key]]) # Check that no DeprecationWarning is raised with new attributes with no_deprecated_call(): @@ -271,16 +257,10 @@ def test_parallel_analysis(testing_Universe): ld1 = LinearDensity(selection1, binsize=1).run() ld2 = LinearDensity(selection2, binsize=1).run() ld_whole = LinearDensity(selection_whole, binsize=1).run() - with pytest.warns( - DeprecationWarning, match="`_add_other_results` is deprecated!" - ): + with pytest.warns(DeprecationWarning, match="`_add_other_results` is deprecated!"): ld1._add_other_results(ld2) - assert_allclose( - ld1.results.z.mass_density, ld_whole.results.z.mass_density - ) - assert_allclose( - ld1.results.x.mass_density, ld_whole.results.x.mass_density - ) + assert_allclose(ld1.results.z.mass_density, ld_whole.results.z.mass_density) + assert_allclose(ld1.results.x.mass_density, ld_whole.results.x.mass_density) def test_class_is_parallelizable(): @@ -291,11 +271,8 @@ def test_class_is_parallelizable(): def test_supported_backends(): - assert ( - mda.analysis.lineardensity.LinearDensity.get_supported_backends() - == ( - "serial", - "multiprocessing", - "dask", - ) + assert mda.analysis.lineardensity.LinearDensity.get_supported_backends() == ( + "serial", + "multiprocessing", + "dask", ) diff --git a/testsuite/MDAnalysisTests/analysis/test_msd.py b/testsuite/MDAnalysisTests/analysis/test_msd.py index 4a0a5717a38..14d8a801b1e 100644 --- a/testsuite/MDAnalysisTests/analysis/test_msd.py +++ b/testsuite/MDAnalysisTests/analysis/test_msd.py @@ -117,9 +117,7 @@ def test_updating_ag_rejected(self, u): with pytest.raises(TypeError, match=errmsg): m = MSD(updating_ag, msd_type="xyz", fft=False) - @pytest.mark.parametrize( - "msdtype", ["foo", "bar", "yx", "zyx", 123, "", " xy "] - ) + @pytest.mark.parametrize("msdtype", ["foo", "bar", "yx", "zyx", 123, "", " xy "]) def test_msdtype_error(self, u, SELECTION, msdtype): errmsg = f"Invalid msd_type {msdtype}, must be a string and one of: xyz, xy, xz, yz, x, y, z" with pytest.raises(ValueError, match=errmsg): @@ -137,9 +135,7 @@ def test_msdtype_error(self, u, SELECTION, msdtype): ("z", 1), ], ) - def test_simple_step_traj_all_dims( - self, step_traj, NSTEP, dim, dim_factor - ): + def test_simple_step_traj_all_dims(self, step_traj, NSTEP, dim, dim_factor): # testing the "simple" algorithm on constant velocity trajectory # should fit the polynomial y=dim_factor*x**2 m_simple = MSD(step_traj, "all", msd_type=dim, fft=False) @@ -159,18 +155,14 @@ def test_simple_step_traj_all_dims( ("z", 1), ], ) - def test_simple_start_stop_step_all_dims( - self, step_traj, NSTEP, dim, dim_factor - ): + def test_simple_start_stop_step_all_dims(self, step_traj, NSTEP, dim, dim_factor): # testing the "simple" algorithm on constant velocity trajectory # test start stop step is working correctly m_simple = MSD(step_traj, "all", msd_type=dim, fft=False) m_simple.run(start=10, stop=1000, step=10) poly = characteristic_poly(NSTEP, dim_factor) # polynomial must take offset start into account - assert_almost_equal( - m_simple.results.timeseries, poly[0:990:10], decimal=4 - ) + assert_almost_equal(m_simple.results.timeseries, poly[0:990:10], decimal=4) def test_random_walk_u_simple(self, random_walk_u): # regress against random_walk test data @@ -265,18 +257,14 @@ def test_fft_step_traj_all_dims(self, step_traj, NSTEP, dim, dim_factor): ("z", 1), ], ) - def test_fft_start_stop_step_all_dims( - self, step_traj, NSTEP, dim, dim_factor - ): + def test_fft_start_stop_step_all_dims(self, step_traj, NSTEP, dim, dim_factor): # testing the fft algorithm on constant velocity trajectory # test start stop step is working correctly m_simple = MSD(step_traj, "all", msd_type=dim, fft=True) m_simple.run(start=10, stop=1000, step=10) poly = characteristic_poly(NSTEP, dim_factor) # polynomial must take offset start into account - assert_almost_equal( - m_simple.results.timeseries, poly[0:990:10], decimal=3 - ) + assert_almost_equal(m_simple.results.timeseries, poly[0:990:10], decimal=3) def test_random_walk_u_fft(self, random_walk_u): # regress against random_walk test data @@ -1756,9 +1744,7 @@ def test_msds_per_particle(self, u_nonlinear): ] ) assert result_msd_per_particle.shape == expected_msd_per_particle.shape - assert_allclose( - result_msd_per_particle, expected_msd_per_particle, rtol=1e-5 - ) + assert_allclose(result_msd_per_particle, expected_msd_per_particle, rtol=1e-5) def test_start_stop_step(self, u_nonlinear): msd = MSD(u_nonlinear, select="all", msd_type="xyz", non_linear=True) @@ -1845,6 +1831,4 @@ def test_start_stop_step(self, u_nonlinear): assert result_msd_per_particle.shape == expected_msd_per_particle.shape assert_allclose(result_msd, expected_msd, rtol=1e-5) assert_allclose(result_delta_t, expected_delta_t, rtol=1e-5) - assert_allclose( - result_msd_per_particle, expected_msd_per_particle, rtol=1e-5 - ) + assert_allclose(result_msd_per_particle, expected_msd_per_particle, rtol=1e-5) diff --git a/testsuite/MDAnalysisTests/analysis/test_nuclinfo.py b/testsuite/MDAnalysisTests/analysis/test_nuclinfo.py index 61577599a00..140dba89b18 100644 --- a/testsuite/MDAnalysisTests/analysis/test_nuclinfo.py +++ b/testsuite/MDAnalysisTests/analysis/test_nuclinfo.py @@ -234,8 +234,6 @@ def test_hydroxyl(u, seg, i, expected_value): (8, 9, 10, "RNAA", "RNAA", "RNAA", 34.50106), ), ) -def test_pseudo_dihe_baseflip( - u, bp1, bp2, i, seg1, seg2, seg3, expected_value -): +def test_pseudo_dihe_baseflip(u, bp1, bp2, i, seg1, seg2, seg3, expected_value): val = nuclinfo.pseudo_dihe_baseflip(u, bp1, bp2, i, seg1, seg2, seg3) assert_almost_equal(val, expected_value, decimal=3) diff --git a/testsuite/MDAnalysisTests/analysis/test_pca.py b/testsuite/MDAnalysisTests/analysis/test_pca.py index 663aa5e68ff..b0400e5dea0 100644 --- a/testsuite/MDAnalysisTests/analysis/test_pca.py +++ b/testsuite/MDAnalysisTests/analysis/test_pca.py @@ -99,17 +99,13 @@ def test_cum_var(pca): def test_pcs(pca): - assert_equal( - pca.results.p_components.shape, (pca._n_atoms * 3, pca._n_atoms * 3) - ) + assert_equal(pca.results.p_components.shape, (pca._n_atoms * 3, pca._n_atoms * 3)) def test_pcs_n_components(u): pca = PCA(u, select=SELECTION).run() assert_equal(pca.n_components, pca._n_atoms * 3) - assert_equal( - pca.results.p_components.shape, (pca._n_atoms * 3, pca._n_atoms * 3) - ) + assert_equal(pca.results.p_components.shape, (pca._n_atoms * 3, pca._n_atoms * 3)) pca.n_components = 10 assert_equal(pca.n_components, 10) assert_equal(pca.results.p_components.shape, (pca._n_atoms * 3, 10)) @@ -191,9 +187,7 @@ def test_project_none_anchor(u, pca): group = u.select_atoms("resnum 1") with pytest.raises(ValueError) as exc: func = pca.project_single_frame(0, group=group, anchor=None) - assert ("'anchor' cannot be 'None'" + " if 'group' is not 'None'") in str( - exc.value - ) + assert ("'anchor' cannot be 'None'" + " if 'group' is not 'None'") in str(exc.value) def test_project_more_anchor(u, pca): @@ -207,9 +201,7 @@ def test_project_less_anchor(u, pca): group = u.select_atoms("all") with pytest.raises(ValueError) as exc: project = pca.project_single_frame(0, group=group, anchor="name CB") - assert ("Some residues in 'group'" + " do not have an 'anchor'") in str( - exc.value - ) + assert ("Some residues in 'group'" + " do not have an 'anchor'") in str(exc.value) def test_project_invalid_anchor(u): @@ -275,9 +267,7 @@ def test_project_extrapolate_translation(u_fresh): project = pca.project_single_frame(0, group=group, anchor="name CA") distances_original = mda.lib.distances.self_distance_array(group.positions) - distances_new = mda.lib.distances.self_distance_array( - project(group).positions - ) + distances_new = mda.lib.distances.self_distance_array(project(group).positions) assert_allclose(distances_original, distances_new, rtol=1e-05) @@ -386,9 +376,7 @@ def test_compare_wrong_class(u, pca, method): assert "must be another PCA class" in str(exc.value) -@pytest.mark.parametrize( - "attr", ("p_components", "variance", "cumulated_variance") -) +@pytest.mark.parametrize("attr", ("p_components", "variance", "cumulated_variance")) def test_pca_attr_warning(u, attr): pca = PCA(u, select=SELECTION).run(stop=2) wmsg = f"The `{attr}` attribute was deprecated in MDAnalysis 2.0.0" diff --git a/testsuite/MDAnalysisTests/analysis/test_persistencelength.py b/testsuite/MDAnalysisTests/analysis/test_persistencelength.py index 54005c8a667..e0fa0665a3b 100644 --- a/testsuite/MDAnalysisTests/analysis/test_persistencelength.py +++ b/testsuite/MDAnalysisTests/analysis/test_persistencelength.py @@ -77,9 +77,7 @@ def test_lb(self, p_run): def test_fit(self, p_run): assert_almost_equal(p_run.results.lp, 6.504, 3) - assert len(p_run.results.fit) == len( - p_run.results.bond_autocorrelation - ) + assert len(p_run.results.fit) == len(p_run.results.bond_autocorrelation) def test_raise_NoDataError(self, p): # Ensure that a NoDataError is raised if perform_fit() diff --git a/testsuite/MDAnalysisTests/analysis/test_rdf.py b/testsuite/MDAnalysisTests/analysis/test_rdf.py index b438b73b7fe..c895dbc1b24 100644 --- a/testsuite/MDAnalysisTests/analysis/test_rdf.py +++ b/testsuite/MDAnalysisTests/analysis/test_rdf.py @@ -97,9 +97,7 @@ def test_exclusion(sels, client_InterRDF): assert rdf.results.count.sum() == 4 -@pytest.mark.parametrize( - "attr, count", [("residue", 8), ("segment", 0), ("chain", 8)] -) +@pytest.mark.parametrize("attr, count", [("residue", 8), ("segment", 0), ("chain", 8)]) def test_ignore_same_residues(sels, attr, count, client_InterRDF): # should see two distances with 4 counts each s1, s2 = sels diff --git a/testsuite/MDAnalysisTests/analysis/test_rdf_s.py b/testsuite/MDAnalysisTests/analysis/test_rdf_s.py index 5095c4d4326..f5779c24125 100644 --- a/testsuite/MDAnalysisTests/analysis/test_rdf_s.py +++ b/testsuite/MDAnalysisTests/analysis/test_rdf_s.py @@ -122,9 +122,7 @@ def test_density(u, sels, density, value, client_InterRDF_s): assert_almost_equal(max(rdf.results.rdf[0][0][0]), value) if not density: s1 = u.select_atoms("name ZND and resid 289") - s2 = u.select_atoms( - "name OD1 and resid 51 and sphzone 5.0 (resid 289)" - ) + s2 = u.select_atoms("name OD1 and resid 51 and sphzone 5.0 (resid 289)") rdf_ref = InterRDF(s1, s2).run(**client_InterRDF_s) assert_almost_equal(rdf_ref.results.rdf, rdf.results.rdf[0][0][0]) @@ -147,9 +145,7 @@ def test_norm(u, sels, norm, value, client_InterRDF_s): assert_allclose(max(rdf.results.rdf[0][0][0]), value) if norm == "rdf": s1 = u.select_atoms("name ZND and resid 289") - s2 = u.select_atoms( - "name OD1 and resid 51 and sphzone 5.0 (resid 289)" - ) + s2 = u.select_atoms("name OD1 and resid 51 and sphzone 5.0 (resid 289)") rdf_ref = InterRDF(s1, s2).run(**client_InterRDF_s) assert_almost_equal(rdf_ref.results.rdf, rdf.results.rdf[0][0][0]) diff --git a/testsuite/MDAnalysisTests/analysis/test_results.py b/testsuite/MDAnalysisTests/analysis/test_results.py index adfbc4b5063..61773c1a477 100644 --- a/testsuite/MDAnalysisTests/analysis/test_results.py +++ b/testsuite/MDAnalysisTests/analysis/test_results.py @@ -156,9 +156,7 @@ def merger(self): @pytest.mark.parametrize("n", [1, 2, 5, 14]) def test_all_results(self, results_0, results_1, merger, n): - objects = [ - obj for obj, _ in zip(cycle([results_0, results_1]), range(n)) - ] + objects = [obj for obj, _ in zip(cycle([results_0, results_1]), range(n))] arr = [i for _, i in zip(range(n), cycle([0, 1]))] answers = { @@ -181,9 +179,7 @@ def test_missing_aggregator(self, results_0, results_1, merger): original_float_lookup = merger._lookup.get("float") merger._lookup["float"] = None - with pytest.raises( - ValueError, match="No aggregation function for key='float'" - ): + with pytest.raises(ValueError, match="No aggregation function for key='float'"): merger.merge([results_0, results_1], require_all_aggregators=True) merger._lookup["float"] = original_float_lookup diff --git a/testsuite/MDAnalysisTests/analysis/test_rms.py b/testsuite/MDAnalysisTests/analysis/test_rms.py index f39baa68f12..e1feb883e5e 100644 --- a/testsuite/MDAnalysisTests/analysis/test_rms.py +++ b/testsuite/MDAnalysisTests/analysis/test_rms.py @@ -72,8 +72,7 @@ def p_last(self, u2): def test_p_frames(self, p_first, p_last): # check that these fixtures are really different assert ( - p_first.universe.trajectory.ts.frame - != p_last.universe.trajectory.ts.frame + p_first.universe.trajectory.ts.frame != p_last.universe.trajectory.ts.frame ) assert not np.allclose(p_first.positions, p_last.positions) @@ -117,9 +116,7 @@ def test_weights_and_superposition_1(self, u): weights=weights, superposition=True, ) - firstCoords = rms.rmsd( - u.trajectory[0], u.trajectory[1], superposition=True - ) + firstCoords = rms.rmsd(u.trajectory[0], u.trajectory[1], superposition=True) assert_almost_equal(weighted, firstCoords, decimal=5) def test_weights_and_superposition_2(self, u): @@ -219,9 +216,7 @@ def test_rmsd_frames(self, universe, correct_values, client_RMSD): err_msg="error: rmsd profile should match" + "test values", ) - def test_rmsd_unicode_selection( - self, universe, correct_values, client_RMSD - ): + def test_rmsd_unicode_selection(self, universe, correct_values, client_RMSD): RMSD = MDAnalysis.analysis.rms.RMSD(universe, select="name CA") RMSD.run(step=49, **client_RMSD) assert_almost_equal( @@ -233,9 +228,9 @@ def test_rmsd_unicode_selection( def test_rmsd_atomgroup_selections(self, universe, client_RMSD): # see Issue #1684 - R1 = MDAnalysis.analysis.rms.RMSD( - universe.atoms, select="resid 1-30" - ).run(**client_RMSD) + R1 = MDAnalysis.analysis.rms.RMSD(universe.atoms, select="resid 1-30").run( + **client_RMSD + ) R2 = MDAnalysis.analysis.rms.RMSD( universe.atoms.select_atoms("name CA"), select="resid 1-30" ).run(**client_RMSD) @@ -295,13 +290,11 @@ def test_weights_mass_is_mass_weighted(self, universe, client_RMSD): "and universe.atoms.masses", ) - def test_custom_weighted_list( - self, universe, correct_values_mass, client_RMSD - ): + def test_custom_weighted_list(self, universe, correct_values_mass, client_RMSD): weights = universe.atoms.masses - RMSD = MDAnalysis.analysis.rms.RMSD( - universe, weights=list(weights) - ).run(step=49, **client_RMSD) + RMSD = MDAnalysis.analysis.rms.RMSD(universe, weights=list(weights)).run( + step=49, **client_RMSD + ) assert_almost_equal( RMSD.results.rmsd, correct_values_mass, @@ -361,9 +354,7 @@ def test_rmsd_mismatched_weights_raises_ValueError(self, universe): universe, weights=universe.atoms.masses[:-1] ) - def test_rmsd_misuse_weights_for_groupselection_raises_TypeError( - self, universe - ): + def test_rmsd_misuse_weights_for_groupselection_raises_TypeError(self, universe): with pytest.raises(TypeError): RMSD = MDAnalysis.analysis.rms.RMSD( universe, @@ -391,9 +382,7 @@ def test_rmsd_list_of_weights_wrong_length(self, universe): weights_groupselections=[None], ) - def test_rmsd_group_selections( - self, universe, correct_values_group, client_RMSD - ): + def test_rmsd_group_selections(self, universe, correct_values_group, client_RMSD): RMSD = MDAnalysis.analysis.rms.RMSD( universe, groupselections=["backbone", "name CA"] ).run(step=49, **client_RMSD) @@ -519,9 +508,7 @@ def test_rmsf_identical_frames(self, universe, tmpdir, client_RMSF): ) def test_rmsf_attr_warning(self, universe, client_RMSF): - rmsfs = rms.RMSF(universe.select_atoms("name CA")).run( - stop=2, **client_RMSF - ) + rmsfs = rms.RMSF(universe.select_atoms("name CA")).run(stop=2, **client_RMSF) wmsg = "The `rmsf` attribute was deprecated in MDAnalysis 2.0.0" with pytest.warns(DeprecationWarning, match=wmsg): diff --git a/testsuite/MDAnalysisTests/analysis/test_wbridge.py b/testsuite/MDAnalysisTests/analysis/test_wbridge.py index 2b53d2f1d35..aae5626129c 100644 --- a/testsuite/MDAnalysisTests/analysis/test_wbridge.py +++ b/testsuite/MDAnalysisTests/analysis/test_wbridge.py @@ -287,9 +287,7 @@ def wb_multiframe(): wb.results.network.append( { (0, None, 3, 2, 2.0, 180.0): { - (4, 2, 5, None, 2.0, 180.0): { - (5, None, 11, 12, 2.0, 180.0): None - } + (4, 2, 5, None, 2.0, 180.0): {(5, None, 11, 12, 2.0, 180.0): None} } } ) @@ -691,18 +689,10 @@ def test_timeseries_wba(self, universe_branch): wb.run(verbose=False) timeseries = sorted(wb.results.timeseries[0]) - assert_equal( - timeseries[0][:4], (0, 2, ("ALA", 1, "O"), ("SOL", 2, "HW1")) - ) - assert_equal( - timeseries[1][:4], (3, 4, ("SOL", 2, "HW2"), ("SOL", 3, "OW")) - ) - assert_equal( - timeseries[2][:4], (5, 7, ("SOL", 3, "HW1"), ("ALA", 4, "O")) - ) - assert_equal( - timeseries[3][:4], (6, 8, ("SOL", 3, "HW2"), ("ALA", 5, "O")) - ) + assert_equal(timeseries[0][:4], (0, 2, ("ALA", 1, "O"), ("SOL", 2, "HW1"))) + assert_equal(timeseries[1][:4], (3, 4, ("SOL", 2, "HW2"), ("SOL", 3, "OW"))) + assert_equal(timeseries[2][:4], (5, 7, ("SOL", 3, "HW1"), ("ALA", 4, "O"))) + assert_equal(timeseries[3][:4], (6, 8, ("SOL", 3, "HW2"), ("ALA", 5, "O"))) def test_timeseries_hba(self, universe_branch): """Test if the time series data is correctly generated in hydrogen bond analysis format""" @@ -716,18 +706,10 @@ def test_timeseries_hba(self, universe_branch): wb.run(verbose=False) timeseries = sorted(wb.results.timeseries[0]) - assert_equal( - timeseries[0][:4], (2, 0, ("SOL", 2, "HW1"), ("ALA", 1, "O")) - ) - assert_equal( - timeseries[1][:4], (3, 4, ("SOL", 2, "HW2"), ("SOL", 3, "OW")) - ) - assert_equal( - timeseries[2][:4], (5, 7, ("SOL", 3, "HW1"), ("ALA", 4, "O")) - ) - assert_equal( - timeseries[3][:4], (6, 8, ("SOL", 3, "HW2"), ("ALA", 5, "O")) - ) + assert_equal(timeseries[0][:4], (2, 0, ("SOL", 2, "HW1"), ("ALA", 1, "O"))) + assert_equal(timeseries[1][:4], (3, 4, ("SOL", 2, "HW2"), ("SOL", 3, "OW"))) + assert_equal(timeseries[2][:4], (5, 7, ("SOL", 3, "HW1"), ("ALA", 4, "O"))) + assert_equal(timeseries[3][:4], (6, 8, ("SOL", 3, "HW2"), ("ALA", 5, "O"))) @pytest.mark.parametrize("distance_type", ["hydrogen", "heavy"]) def test_acceptor_12water_accepter(self, universe_AWA_AWWA, distance_type): @@ -768,9 +750,7 @@ def test_count_by_type_single_link(self, universe_DWA): universe_DWA, "protein and (resid 1)", "protein and (resid 4)" ) wb.run(verbose=False) - assert_equal( - wb.count_by_type(), [(1, 4, "ALA", 1, "H", "ALA", 4, "O", 1.0)] - ) + assert_equal(wb.count_by_type(), [(1, 4, "ALA", 1, "H", "ALA", 4, "O", 1.0)]) def test_count_by_type_multiple_link(self, universe_AWA_AWWA): """ @@ -812,20 +792,18 @@ def test_count_by_type_filter(self, wb_multiframe): """ def analysis(current, output, u): - sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = ( - current[0] - ) - atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = ( - current[-1] - ) + sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = current[0] + atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = current[ + -1 + ] sele1 = u.atoms[sele1_index] sele2 = u.atoms[sele2_index] - (s1_resname, s1_resid, s1_name) = ( + s1_resname, s1_resid, s1_name = ( sele1.resname, sele1.resid, sele1.name, ) - (s2_resname, s2_resid, s2_name) = ( + s2_resname, s2_resid, s2_name = ( sele2.resname, sele2.resid, sele2.name, @@ -856,20 +834,18 @@ def test_count_by_type_merge(self, wb_multiframe): """ def analysis(current, output, u): - sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = ( - current[0] - ) - atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = ( - current[-1] - ) + sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = current[0] + atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = current[ + -1 + ] sele1 = u.atoms[sele1_index] sele2 = u.atoms[sele2_index] - (s1_resname, s1_resid, s1_name) = ( + s1_resname, s1_resid, s1_name = ( sele1.resname, sele1.resid, sele1.name, ) - (s2_resname, s2_resid, s2_name) = ( + s2_resname, s2_resid, s2_name = ( sele2.resname, sele2.resid, sele2.name, @@ -891,20 +867,18 @@ def test_count_by_type_order(self, wb_multiframe): """ def analysis(current, output, u): - sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = ( - current[0] - ) - atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = ( - current[-1] - ) + sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = current[0] + atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = current[ + -1 + ] sele1 = u.atoms[sele1_index] sele2 = u.atoms[sele2_index] - (s1_resname, s1_resid, s1_name) = ( + s1_resname, s1_resid, s1_name = ( sele1.resname, sele1.resid, sele1.name, ) - (s2_resname, s2_resid, s2_name) = ( + s2_resname, s2_resid, s2_name = ( sele2.resname, sele2.resid, sele2.name, @@ -932,9 +906,7 @@ def test_count_by_time(self, wb_multiframe): This test tests if count_by_times() works. :return: """ - assert_equal( - wb_multiframe.count_by_time(), [(0, 1), (1, 1), (2, 1), (3, 1)] - ) + assert_equal(wb_multiframe.count_by_time(), [(0, 1), (1, 1), (2, 1), (3, 1)]) def test_count_by_time_weight(self, universe_AWA_AWWA): """ @@ -951,20 +923,18 @@ def test_count_by_time_weight(self, universe_AWA_AWWA): wb.run(verbose=False) def analysis(current, output, u): - sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = ( - current[0] - ) - atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = ( - current[-1] - ) + sele1_index, sele1_heavy_index, atom2, heavy_atom2, dist, angle = current[0] + atom1, heavy_atom1, sele2_index, sele2_heavy_index, dist, angle = current[ + -1 + ] sele1 = u.atoms[sele1_index] sele2 = u.atoms[sele2_index] - (s1_resname, s1_resid, s1_name) = ( + s1_resname, s1_resid, s1_name = ( sele1.resname, sele1.resid, sele1.name, ) - (s2_resname, s2_resid, s2_name) = ( + s2_resname, s2_resid, s2_name = ( sele2.resname, sele2.resid, sele2.name, @@ -1022,9 +992,7 @@ def test_timesteps_by_type(self, wb_multiframe): """Test the timesteps_by_type function""" timesteps = sorted(wb_multiframe.timesteps_by_type()) - assert_array_equal( - timesteps[3], [1, 12, "ALA", 1, "H", "ALA", 6, "O", 0, 2] - ) + assert_array_equal(timesteps[3], [1, 12, "ALA", 1, "H", "ALA", 6, "O", 0, 2]) def test_duplicate_water(self): """A case #3119 where diff --git a/testsuite/MDAnalysisTests/auxiliary/base.py b/testsuite/MDAnalysisTests/auxiliary/base.py index e3e82a01610..03daaebe02f 100644 --- a/testsuite/MDAnalysisTests/auxiliary/base.py +++ b/testsuite/MDAnalysisTests/auxiliary/base.py @@ -116,9 +116,7 @@ def reference_timestep(dt=1, offset=0): # for 'average': use low frequenct timestep, only step 2 within 0ps cutoff self.lowf_cutoff_average_rep = self.format_data([2, 2 * 2, 2**2]) # for 'closest': use offset timestep; no timestep within 0ps cutoff - self.offset_cutoff_closest_rep = self.format_data( - [np.nan, np.nan, np.nan] - ) + self.offset_cutoff_closest_rep = self.format_data([np.nan, np.nan, np.nan]) ## testing selection of time/data. Overload for each auxilairy format ## as appropraite. @@ -150,9 +148,7 @@ def test_dt(self, ref, reader): assert reader.dt == ref.dt, "dt does not match" def test_initial_time(self, ref, reader): - assert ( - reader.initial_time == ref.initial_time - ), "initial time does not match" + assert reader.initial_time == ref.initial_time, "initial time does not match" def test_first_step(self, ref, reader): # on first loading we should start at step 0 @@ -327,8 +323,7 @@ def test_represent_as_average_with_cutoff(self, ref, reader): assert_almost_equal( ts.aux.test, ref.lowf_cutoff_average_rep, - err_msg="Representative value does not match when " - "applying cutoff", + err_msg="Representative value does not match when " "applying cutoff", ) def test_read_offset_timestep(self, ref, reader): @@ -352,8 +347,7 @@ def test_represent_as_closest_with_cutoff(self, ref, reader): assert_almost_equal( ts.aux.test, ref.offset_cutoff_closest_rep, - err_msg="Representative value does not match when " - "applying cutoff", + err_msg="Representative value does not match when " "applying cutoff", ) def test_read_higher_freq_timestep(self, ref, reader): @@ -405,8 +399,7 @@ def test_auxiliary_read_ts_rewind(self, ref_universe): assert_equal( aux_info_0, aux_info_0_rewind, - "aux info was retrieved incorrectly " - "after reading the last step", + "aux info was retrieved incorrectly " "after reading the last step", ) def test_get_description(self, ref, reader): @@ -419,9 +412,7 @@ def test_get_description(self, ref, reader): def test_load_from_description(self, reader): description = reader.get_description() new = mda.auxiliary.core.auxreader(**description) - assert ( - new == reader - ), "AuxReader reloaded from description does not match" + assert new == reader, "AuxReader reloaded from description does not match" def test_step_to_frame_out_of_bounds(self, reader, ref): @@ -446,9 +437,7 @@ def test_step_to_frame_time_diff(self, reader, ref): # Test all 5 frames for idx in range(5): - frame, time_diff = reader.step_to_frame( - idx, ts, return_time_diff=True - ) + frame, time_diff = reader.step_to_frame(idx, ts, return_time_diff=True) assert frame == idx np.testing.assert_almost_equal(time_diff, idx * 0.1) diff --git a/testsuite/MDAnalysisTests/auxiliary/test_core.py b/testsuite/MDAnalysisTests/auxiliary/test_core.py index 8a630c6e48d..b17637daaf6 100644 --- a/testsuite/MDAnalysisTests/auxiliary/test_core.py +++ b/testsuite/MDAnalysisTests/auxiliary/test_core.py @@ -28,16 +28,12 @@ def test_get_auxreader_for_none(): - with pytest.raises( - ValueError, match="Must provide either auxdata or format" - ): + with pytest.raises(ValueError, match="Must provide either auxdata or format"): mda.auxiliary.core.get_auxreader_for() def test_get_auxreader_for_wrong_auxdata(): - with pytest.raises( - ValueError, match="Unknown auxiliary data format for auxdata:" - ): + with pytest.raises(ValueError, match="Unknown auxiliary data format for auxdata:"): mda.auxiliary.core.get_auxreader_for(auxdata="test.none") @@ -47,9 +43,7 @@ def test_get_auxreader_for_wrong_format(): def test_notimplemented_read_next_timestep(): - with pytest.raises( - NotImplementedError, match="BUG: Override " "_read_next_step()" - ): + with pytest.raises(NotImplementedError, match="BUG: Override " "_read_next_step()"): reader = mda.auxiliary.base.AuxReader() @@ -59,8 +53,6 @@ def _read_next_step(self): def test_notimplemented_memory_usage(): - with pytest.raises( - NotImplementedError, match="BUG: Override " "_memory_usage()" - ): + with pytest.raises(NotImplementedError, match="BUG: Override " "_memory_usage()"): reader = No_Memory_Usage() reader._memory_usage() diff --git a/testsuite/MDAnalysisTests/auxiliary/test_edr.py b/testsuite/MDAnalysisTests/auxiliary/test_edr.py index 8668c8a056b..9da63cf2a74 100644 --- a/testsuite/MDAnalysisTests/auxiliary/test_edr.py +++ b/testsuite/MDAnalysisTests/auxiliary/test_edr.py @@ -105,9 +105,7 @@ def __init__(self): def reference_auxstep(i): # create a reference AuxStep for step i t_init = self.initial_time - auxstep = mda.auxiliary.EDR.EDRStep( - dt=self.dt, initial_time=t_init - ) + auxstep = mda.auxiliary.EDR.EDRStep(dt=self.dt, initial_time=t_init) auxstep.step = i auxstep._data = get_auxstep_data(i) return auxstep @@ -228,9 +226,7 @@ def reader(ref): data = reader.data_dict[term] reader_unit = reader.unit_dict[term] try: - reader.data_dict[term] = units.convert( - data, reader_unit, ref_unit - ) + reader.data_dict[term] = units.convert(data, reader_unit, ref_unit) except ValueError: continue # some units not supported yet reader.rewind() @@ -241,9 +237,7 @@ def test_time_non_constant_dt(self, reader): reader.time_selector = None with pytest.raises( ValueError, - match="If dt is not constant, " - "must have a valid time " - "selector", + match="If dt is not constant, " "must have a valid time " "selector", ): reader.time @@ -269,9 +263,7 @@ def test_step_to_frame_time_diff(self, reader, ref): # Test all 4 frames for idx in range(4): - frame, time_diff = reader.step_to_frame( - idx, ts, return_time_diff=True - ) + frame, time_diff = reader.step_to_frame(idx, ts, return_time_diff=True) assert frame == idx assert_allclose(time_diff, idx * 0.002) @@ -334,8 +326,7 @@ def test_represent_as_average_with_cutoff(self, ref, reader): assert_allclose( ts.aux.test["Bond"], ref.lowf_cutoff_average_rep, - err_msg="Representative value does not match when " - "applying cutoff", + err_msg="Representative value does not match when " "applying cutoff", ) # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 @@ -363,9 +354,7 @@ def test_add_term_list_custom_names_from_file(self, ref, ref_universe): assert ref_universe.trajectory.ts.aux.temp == ref_dict["Temperature"] # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 - def test_add_term_list_custom_names_from_reader( - self, ref_universe, reader - ): + def test_add_term_list_custom_names_from_reader(self, ref_universe, reader): ref_universe.trajectory.add_auxiliary( {"bond": "Bond", "temp": "Temperature"}, reader ) @@ -374,24 +363,18 @@ def test_add_term_list_custom_names_from_reader( assert ref_universe.trajectory.ts.aux.temp == ref_dict["Temperature"] # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 - def test_raise_error_if_auxname_already_assigned( - self, ref_universe, reader - ): + def test_raise_error_if_auxname_already_assigned(self, ref_universe, reader): with pytest.raises(ValueError, match="Auxiliary data with name"): ref_universe.trajectory.add_auxiliary("test", reader, "Bond") # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 def test_add_single_term_custom_name_from_file(self, ref, ref_universe): - ref_universe.trajectory.add_auxiliary( - {"temp": "Temperature"}, ref.testdata - ) + ref_universe.trajectory.add_auxiliary({"temp": "Temperature"}, ref.testdata) ref_dict = get_auxstep_data(0) assert ref_universe.trajectory.ts.aux.temp == ref_dict["Temperature"] # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 - def test_add_single_term_custom_name_from_reader( - self, ref_universe, reader - ): + def test_add_single_term_custom_name_from_reader(self, ref_universe, reader): ref_universe.trajectory.add_auxiliary({"temp": "Temperature"}, reader) ref_dict = get_auxstep_data(0) assert ref_universe.trajectory.ts.aux.temp == ref_dict["Temperature"] @@ -412,9 +395,7 @@ def test_terms_update_on_iter(self, ref_universe, reader): # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 def test_invalid_data_selector(self, ref, ref_universe): with pytest.raises(KeyError, match="'Nonsense' is not a key"): - ref_universe.trajectory.add_auxiliary( - {"something": "Nonsense"}, AUX_EDR - ) + ref_universe.trajectory.add_auxiliary({"something": "Nonsense"}, AUX_EDR) def test_read_all_times(self, reader): all_times_expected = np.array([0.0, 0.02, 0.04, 0.06]) @@ -452,9 +433,7 @@ def test_get_data_invalid_selections(self, reader, get_data_input): # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 def test_warning_when_space_in_aux_spec(self, ref_universe, reader): with pytest.warns(UserWarning, match="Auxiliary name"): - ref_universe.trajectory.add_auxiliary( - {"Pres. DC": "Pres. DC"}, reader - ) + ref_universe.trajectory.add_auxiliary({"Pres. DC": "Pres. DC"}, reader) # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 def test_warn_too_much_memory_usage(self, ref_universe, reader): @@ -483,9 +462,7 @@ def test_units_are_converted_by_EDRReader(self, reader): # TODO: Change order of aux_spec and auxdata for 3.0 release, cf. Issue #3811 def test_warning_when_unknown_unit(self, ref_universe, reader): with pytest.warns(UserWarning, match="Could not find"): - ref_universe.trajectory.add_auxiliary( - {"temp": "Temperature"}, reader - ) + ref_universe.trajectory.add_auxiliary({"temp": "Temperature"}, reader) def test_unit_conversion_is_optional(self, ref): reader = ref.reader( @@ -508,9 +485,7 @@ def test_unit_conversion_is_optional(self, ref): def test_single_frame_input_file(): """Previously, EDRReader could not handle EDR input files with only one frame. See Issue #3999.""" - reader = mda.auxiliary.EDR.EDRReader( - AUX_EDR_SINGLE_FRAME, convert_units=False - ) + reader = mda.auxiliary.EDR.EDRReader(AUX_EDR_SINGLE_FRAME, convert_units=False) ref_dict = get_auxstep_data(0) reader_data_dict = reader.auxstep.data assert ref_dict == reader_data_dict diff --git a/testsuite/MDAnalysisTests/auxiliary/test_xvg.py b/testsuite/MDAnalysisTests/auxiliary/test_xvg.py index 8926cabe320..2fdaf524053 100644 --- a/testsuite/MDAnalysisTests/auxiliary/test_xvg.py +++ b/testsuite/MDAnalysisTests/auxiliary/test_xvg.py @@ -75,9 +75,7 @@ def test_select_time_none(self, step): assert st is None def test_select_time_invalid_index(self, step): - with pytest.raises( - ValueError, match="Time selector must be single index" - ): + with pytest.raises(ValueError, match="Time selector must be single index"): step._select_time([0]) def test_select_data_none(self, step): @@ -170,9 +168,7 @@ def reader(ref): def test_get_auxreader_for(self, ref, reader): # Default reader of .xvg files is intead XVGReader, not XVGFileReader # so test specifying format - reader = mda.auxiliary.core.get_auxreader_for( - ref.testdata, format=ref.format - ) + reader = mda.auxiliary.core.get_auxreader_for(ref.testdata, format=ref.format) assert reader == ref.reader def test_reopen(self, reader): diff --git a/testsuite/MDAnalysisTests/converters/test_base.py b/testsuite/MDAnalysisTests/converters/test_base.py index a8bebca0c31..6d6f9f4d331 100644 --- a/testsuite/MDAnalysisTests/converters/test_base.py +++ b/testsuite/MDAnalysisTests/converters/test_base.py @@ -41,9 +41,7 @@ class DerivedConverter(ConverterBase): pass assert issubclass(DerivedConverter, ConverterBase) - assert not issubclass( - DerivedConverter, MDAnalysis.converters.base.ConverterBase - ) + assert not issubclass(DerivedConverter, MDAnalysis.converters.base.ConverterBase) def test_converters_converterbase_no_warning(): diff --git a/testsuite/MDAnalysisTests/converters/test_openmm_parser.py b/testsuite/MDAnalysisTests/converters/test_openmm_parser.py index 7188499fd8d..5b56ba01e40 100644 --- a/testsuite/MDAnalysisTests/converters/test_openmm_parser.py +++ b/testsuite/MDAnalysisTests/converters/test_openmm_parser.py @@ -28,7 +28,6 @@ from MDAnalysisTests.topology.base import ParserBase from MDAnalysisTests.datafiles import CONECT, PDBX, PDB - try: from openmm.app import Element, Topology from openmm.unit import daltons @@ -131,17 +130,13 @@ def test_masses(self, top): assert len(top.masses.values) == self.expected_n_atoms if self.expected_n_atoms: assert isinstance(top.masses.values, np.ndarray) - assert all( - isinstance(mass, np.float64) for mass in top.masses.values - ) + assert all(isinstance(mass, np.float64) for mass in top.masses.values) else: assert top.masses.values == [] def test_guessed_attributes(self, filename): u = mda.Universe(filename, topology_format="OPENMMTOPOLOGY") - u_guessed_attrs = [ - attr.attrname for attr in u._topology.guessed_attributes - ] + u_guessed_attrs = [attr.attrname for attr in u._topology.guessed_attributes] for attr in self.guessed_attrs: assert hasattr(u.atoms, attr) assert attr in u_guessed_attrs diff --git a/testsuite/MDAnalysisTests/converters/test_parmed.py b/testsuite/MDAnalysisTests/converters/test_parmed.py index 261d389603f..e1ce71e7103 100644 --- a/testsuite/MDAnalysisTests/converters/test_parmed.py +++ b/testsuite/MDAnalysisTests/converters/test_parmed.py @@ -41,7 +41,6 @@ PRM_UreyBradley, ) - pmd = pytest.importorskip("parmed") @@ -57,9 +56,7 @@ def test_dimensions(self): self.ref.trajectory.ts.dimensions, rtol=0, atol=1e-3, - err_msg=( - "ParmEdReader failed to get unitcell dimensions " "from ParmEd" - ), + err_msg=("ParmEdReader failed to get unitcell dimensions " "from ParmEd"), ) def test_coordinates(self): @@ -79,9 +76,7 @@ def test_dimensions(self): self.ref.trajectory.ts.dimensions, rtol=0, atol=1e-3, - err_msg=( - "ParmEdReader failed to get unitcell dimensions " "from ParmEd" - ), + err_msg=("ParmEdReader failed to get unitcell dimensions " "from ParmEd"), ) def test_coordinates(self): @@ -203,9 +198,9 @@ def test_equivalent_atoms(self, ref, output): for attr in self.equal_atom_attrs: ra = getattr(r, attr) oa = getattr(o, attr) - assert ( - ra == oa - ), "atom {} not equal for atoms {} and {}".format(attr, r, o) + assert ra == oa, "atom {} not equal for atoms {} and {}".format( + attr, r, o + ) for attr in self.almost_equal_atom_attrs: ra = getattr(r, attr) @@ -215,10 +210,7 @@ def test_equivalent_atoms(self, ref, output): oa, rtol=0, atol=1e-2, - err_msg=( - f"atom {attr} not almost equal for atoms " - f"{r} and {o}" - ), + err_msg=(f"atom {attr} not almost equal for atoms " f"{r} and {o}"), ) @pytest.mark.parametrize("attr", ("bonds", "angles", "impropers", "cmaps")) diff --git a/testsuite/MDAnalysisTests/converters/test_parmed_parser.py b/testsuite/MDAnalysisTests/converters/test_parmed_parser.py index 1a11876fd4f..e4a6e1c892f 100644 --- a/testsuite/MDAnalysisTests/converters/test_parmed_parser.py +++ b/testsuite/MDAnalysisTests/converters/test_parmed_parser.py @@ -90,9 +90,7 @@ def test_bonds_total_counts(self, top, filename): assert len(top.bonds.values) == len(unique) def test_angles_total_counts(self, top, filename): - unique = set( - [(a.atom1.idx, a.atom2.idx, a.atom3.idx) for a in filename.angles] - ) + unique = set([(a.atom1.idx, a.atom2.idx, a.atom3.idx) for a in filename.angles]) assert len(top.angles.values) == len(unique) def test_dihedrals_total_counts(self, top, filename): @@ -129,9 +127,7 @@ def test_cmaps_total_counts(self, top, filename): assert len(top.cmaps.values) == len(unique) def test_ureybradleys_total_counts(self, top, filename): - unique = set( - [(a.atom1.idx, a.atom2.idx) for a in filename.urey_bradleys] - ) + unique = set([(a.atom1.idx, a.atom2.idx) for a in filename.urey_bradleys]) assert len(top.ureybradleys.values) == len(unique) def test_elements(self, top): @@ -217,9 +213,7 @@ def test_dihedrals_identity(self, top, value): vals = top.dihedrals.values assert value in vals or value[::-1] in vals - @pytest.mark.parametrize( - "value", ((17, 19, 21, 41, 43), (60, 62, 64, 79, 81)) - ) + @pytest.mark.parametrize("value", ((17, 19, 21, 41, 43), (60, 62, 64, 79, 81))) def test_cmaps_identity(self, top, value): vals = top.cmaps.values assert value in vals or value[::-1] in vals diff --git a/testsuite/MDAnalysisTests/converters/test_rdkit.py b/testsuite/MDAnalysisTests/converters/test_rdkit.py index 31bc390b4f6..5dc77889a0e 100644 --- a/testsuite/MDAnalysisTests/converters/test_rdkit.py +++ b/testsuite/MDAnalysisTests/converters/test_rdkit.py @@ -154,9 +154,7 @@ def test_compare_mol2reader(self): universe = mda.Universe(MolFactory.mol2_mol()) mol2 = mda.Universe(mol2_molecule) assert universe.trajectory.n_frames == mol2.trajectory.n_frames - assert_equal( - universe.trajectory.ts.positions, mol2.trajectory.ts.positions - ) + assert_equal(universe.trajectory.ts.positions, mol2.trajectory.ts.positions) @requires_rdkit @@ -195,9 +193,7 @@ def test_no_atoms_attr(self): @pytest.mark.parametrize("smi", ["[H]", "C", "O", "[He]"]) def test_single_atom_mol(self, smi): - u = mda.Universe.from_smiles( - smi, addHs=False, generate_coordinates=False - ) + u = mda.Universe.from_smiles(smi, addHs=False, generate_coordinates=False) mol = u.atoms.convert_to.rdkit(inferrer=None) assert mol.GetNumAtoms() == 1 assert mol.GetAtomWithIdx(0).GetSymbol() == smi.strip("[]") @@ -240,9 +236,7 @@ def test_monomer_info(self, pdb, sel_str, atom_index): assert mda_atom.segindex == mi.GetSegmentNumber() assert mda_atom.tempfactor == mi.GetTempFactor() - @pytest.mark.parametrize( - "rdmol", ["mol2_mol", "smiles_mol"], indirect=True - ) + @pytest.mark.parametrize("rdmol", ["mol2_mol", "smiles_mol"], indirect=True) def test_identical_topology(self, rdmol): u = mda.Universe(rdmol) umol = u.atoms.convert_to("RDKIT") @@ -251,9 +245,7 @@ def test_identical_topology(self, rdmol): assert_equal(u.atoms.bonds, u2.atoms.bonds) assert_equal(u.atoms.elements, u2.atoms.elements) assert_equal(u.atoms.names, u2.atoms.names) - assert_allclose( - u.atoms.positions, u2.atoms.positions, rtol=0, atol=1e-7 - ) + assert_allclose(u.atoms.positions, u2.atoms.positions, rtol=0, atol=1e-7) def test_raise_requires_elements(self): u = mda.Universe(mol2_molecule) @@ -269,9 +261,7 @@ def test_raise_requires_elements(self): def test_warn_guess_bonds(self): u = mda.Universe(PDB_helix) - with pytest.warns( - UserWarning, match="No `bonds` attribute in this AtomGroup" - ): + with pytest.warns(UserWarning, match="No `bonds` attribute in this AtomGroup"): u.atoms.convert_to("RDKIT") def test_bonds_outside_sel(self): @@ -292,9 +282,7 @@ def test_error_no_hydrogen_implicit(self, uo2): uo2.atoms.convert_to.rdkit(inferrer=None) def test_warning_no_hydrogen_force(self, uo2): - with pytest.warns( - UserWarning, match="Forcing to continue the conversion" - ): + with pytest.warns(UserWarning, match="Forcing to continue the conversion"): uo2.atoms.convert_to.rdkit(force=True) @pytest.mark.parametrize( @@ -443,30 +431,20 @@ def test_sanitize_fail_warning(self): def test_deprecation_max_iter(self, mol2, monkeypatch): mock = Mock(wraps=atomgroup_to_mol) - monkeypatch.setattr( - "MDAnalysis.converters.RDKit.atomgroup_to_mol", mock - ) - with pytest.warns( - DeprecationWarning, match="Using `max_iter` is deprecated" - ): + monkeypatch.setattr("MDAnalysis.converters.RDKit.atomgroup_to_mol", mock) + with pytest.warns(DeprecationWarning, match="Using `max_iter` is deprecated"): mol2.atoms.convert_to.rdkit(max_iter=2) assert mock.call_args.kwargs["inferrer"].max_iter == 2 def test_deprecation_NoImplicit(self, mol2, monkeypatch): mock = Mock(wraps=atomgroup_to_mol) - monkeypatch.setattr( - "MDAnalysis.converters.RDKit.atomgroup_to_mol", mock - ) - with pytest.warns( - DeprecationWarning, match="Using `NoImplicit` is deprecated" - ): + monkeypatch.setattr("MDAnalysis.converters.RDKit.atomgroup_to_mol", mock) + with pytest.warns(DeprecationWarning, match="Using `NoImplicit` is deprecated"): mol2.atoms.convert_to.rdkit(NoImplicit=False) assert mock.call_args.kwargs["inferrer"] is None def test_deprecation_atomgroup_to_mol_NoImplicit(self, mol2): - with pytest.warns( - DeprecationWarning, match="Using `NoImplicit` is deprecated" - ): + with pytest.warns(DeprecationWarning, match="Using `NoImplicit` is deprecated"): atomgroup_to_mol(mol2.atoms, NoImplicit=False) def test_atomgroup_to_mol_unexpected_kwargs(self, mol2): @@ -491,8 +469,7 @@ def test_sanitize_mol_error(self): mol = Chem.MolFromSmiles("[NH4]", sanitize=False) with pytest.raises( Chem.AtomValenceException, - match="Explicit valence for atom # 0 N, 4, is " - "greater than permitted", + match="Explicit valence for atom # 0 N, 4, is " "greater than permitted", ): sanitize_mol(mol) @@ -525,12 +502,8 @@ def assert_isomorphic_resonance_structure(self, mol, ref): """ isomorphic = mol.HasSubstructMatch(ref) if not isomorphic: - isomorphic = bool( - Chem.ResonanceMolSupplier(mol).GetSubstructMatch(ref) - ) - assert ( - isomorphic - ), f"{Chem.MolToSmiles(ref)} != {Chem.MolToSmiles(mol)}" + isomorphic = bool(Chem.ResonanceMolSupplier(mol).GetSubstructMatch(ref)) + assert isomorphic, f"{Chem.MolToSmiles(ref)} != {Chem.MolToSmiles(mol)}" @requires_rdkit @@ -793,9 +766,7 @@ def test_warn_conjugated_max_iter(self): smi = "[C-]C=CC=CC=CC=CC=CC=C[C-]" mol = Chem.MolFromSmiles(smi) inferrer = MDAnalysisInferrer(max_iter=2) - with pytest.warns( - UserWarning, match="reasonable number of iterations" - ): + with pytest.warns(UserWarning, match="reasonable number of iterations"): inferrer._rebuild_conjugated_bonds(mol) def test_deprecation_warning_max_iter(self): @@ -875,9 +846,7 @@ def test_pdb_names(self): u = mda.Universe(PDB_helix) mol = u.atoms.convert_to.rdkit() names = u.atoms.names - rd_names = np.array( - [a.GetProp("_MDAnalysis_name") for a in mol.GetAtoms()] - ) + rd_names = np.array([a.GetProp("_MDAnalysis_name") for a in mol.GetAtoms()]) assert (names == rd_names).all() @pytest.mark.parametrize( @@ -896,9 +865,7 @@ def test_bond_stereo_not_stereoany(self, smi): assert bond.GetStereo() != Chem.BondStereo.STEREOANY def test_atom_sorter(self): - mol = Chem.MolFromSmiles( - "[H]-[C](-[H])-[C](-[H])-[C]-[C]-[H]", sanitize=False - ) + mol = Chem.MolFromSmiles("[H]-[C](-[H])-[C](-[H])-[C]-[C]-[H]", sanitize=False) # corresponding mol: C=C-C#C # atom indices: 1 3 5 6 mol.UpdatePropertyCache() @@ -914,9 +881,7 @@ def test_atom_sorter(self): [ pytest.param( True, - marks=pytest.mark.xfail( - reason="Invalid charge/valence", strict=True - ), + marks=pytest.mark.xfail(reason="Invalid charge/valence", strict=True), ), False, ], diff --git a/testsuite/MDAnalysisTests/converters/test_rdkit_parser.py b/testsuite/MDAnalysisTests/converters/test_rdkit_parser.py index f82d74a5615..a55ad8a4493 100644 --- a/testsuite/MDAnalysisTests/converters/test_rdkit_parser.py +++ b/testsuite/MDAnalysisTests/converters/test_rdkit_parser.py @@ -120,9 +120,7 @@ def test_bond_orders(self, top, filename): expected = [bond.GetBondTypeAsDouble() for bond in filename.GetBonds()] assert top.bonds.order == expected - def test_multiple_charge_priority( - self, top_gas_tripos, filename_gasteiger - ): + def test_multiple_charge_priority(self, top_gas_tripos, filename_gasteiger): expected = np.array( [ a.GetDoubleProp("_GasteigerCharge") @@ -141,9 +139,7 @@ def test_multiple_charge_props_warning(self): top = self.parser(mol).parse() # Verify the warning assert len(w) == 1 - assert "_GasteigerCharge and _TriposPartialCharge" in str( - w[-1].message - ) + assert "_GasteigerCharge and _TriposPartialCharge" in str(w[-1].message) def test_gasteiger_charges(self, top_gasteiger, filename_gasteiger): expected = np.array( @@ -157,18 +153,13 @@ def test_gasteiger_charges(self, top_gasteiger, filename_gasteiger): def test_tripos_charges(self, top, filename): expected = np.array( - [ - a.GetDoubleProp("_TriposPartialCharge") - for a in filename.GetAtoms() - ], + [a.GetDoubleProp("_TriposPartialCharge") for a in filename.GetAtoms()], dtype=np.float32, ) assert_equal(expected, top.charges.values) def test_aromaticity(self, top, filename): - expected = np.array( - [atom.GetIsAromatic() for atom in filename.GetAtoms()] - ) + expected = np.array([atom.GetIsAromatic() for atom in filename.GetAtoms()]) assert_equal(expected, top.aromaticities.values) def test_guessed_types(self, filename): @@ -203,9 +194,7 @@ def filename(self): def test_partial_residueinfo_raise_error(self, filename): mol = Chem.RemoveHs(filename) mh = Chem.AddHs(mol) - with pytest.raises( - ValueError, match="ResidueInfo is only partially available" - ): + with pytest.raises(ValueError, match="ResidueInfo is only partially available"): mda.Universe(mh) mh = Chem.AddHs(mol, addResidueInfo=True) mda.Universe(mh) diff --git a/testsuite/MDAnalysisTests/coordinates/base.py b/testsuite/MDAnalysisTests/coordinates/base.py index 3a4fa5162ba..bafb38c98d1 100644 --- a/testsuite/MDAnalysisTests/coordinates/base.py +++ b/testsuite/MDAnalysisTests/coordinates/base.py @@ -69,9 +69,7 @@ def test_n_atoms(self): ) def test_numres(self): - assert_equal( - self.universe.atoms.n_residues, 214, "wrong number of residues" - ) + assert_equal(self.universe.atoms.n_residues, 214, "wrong number of residues") def test_n_frames(self): assert_equal( @@ -81,16 +79,13 @@ def test_n_frames(self): ) def test_time(self): - assert_equal( - self.universe.trajectory.time, 0.0, "wrong time of the frame" - ) + assert_equal(self.universe.trajectory.time, 0.0, "wrong time of the frame") def test_frame(self): assert_equal( self.universe.trajectory.frame, 0, - "wrong frame number (0-based, should be 0 for single frame " - "readers)", + "wrong frame number (0-based, should be 0 for single frame " "readers)", ) def test_frame_index_0(self): @@ -206,9 +201,7 @@ def __init__(self): [2**8], # frame 4 = 4ps = step 8 ] self.aux_highf_n_steps = 10 - self.aux_highf_all_data = [ - [2**i] for i in range(self.aux_highf_n_steps) - ] + self.aux_highf_all_data = [[2**i] for i in range(self.aux_highf_n_steps)] self.aux_offset_by = 0.25 @@ -239,9 +232,7 @@ def __init__(self): self.jump_to_frame.aux.lowf = self.aux_lowf_data[3] self.jump_to_frame.aux.highf = self.aux_highf_data[3] - self.dimensions = np.array( - [81.1, 82.2, 83.3, 75, 80, 85], dtype=np.float32 - ) + self.dimensions = np.array([81.1, 82.2, 83.3, 75, 80, 85], dtype=np.float32) self.dimensions_second_frame = np.array( [82.1, 83.2, 84.3, 75.1, 80.1, 85.1], dtype=np.float32 ) @@ -285,16 +276,12 @@ def reader(ref): @pytest.fixture() def transformed(ref): transformed = ref.reader(ref.trajectory) - transformed.add_transformations( - translate([1, 1, 1]), translate([0, 0, 0.33]) - ) + transformed.add_transformations(translate([1, 1, 1]), translate([0, 0, 0.33])) return transformed def test_add_transformations_rejects_non_callable(self): u = mda.Universe.empty(1, trajectory=True) - with pytest.raises( - TypeError, match="All transformations must be callable" - ): + with pytest.raises(TypeError, match="All transformations must be callable"): u.trajectory.add_transformations([1, 2, 3]) def test_n_atoms(self, ref, reader): @@ -305,9 +292,7 @@ def test_n_frames(self, ref, reader): def test_first_frame(self, ref, reader): reader.rewind() - assert_timestep_almost_equal( - reader.ts, ref.first_frame, decimal=ref.prec - ) + assert_timestep_almost_equal(reader.ts, ref.first_frame, decimal=ref.prec) def test_double_close(self, reader): reader.close() @@ -335,9 +320,7 @@ def test_ts_dt_matches_reader(self, reader): assert_equal(reader.ts.dt, reader.dt) def test_total_time(self, ref, reader): - assert_allclose( - reader.totaltime, ref.totaltime, atol=10 ** (-ref.prec), rtol=0 - ) + assert_allclose(reader.totaltime, ref.totaltime, atol=10 ** (-ref.prec), rtol=0) def test_first_dimensions(self, ref, reader): reader.rewind() @@ -408,8 +391,7 @@ def test_iter_auxiliary(self, ref, reader): ref.aux_highf_all_data[i], atol=1e-7, rtol=0, - err_msg="Auxiliary data does not match for " - "step {}".format(i), + err_msg="Auxiliary data does not match for " "step {}".format(i), ) def test_get_aux_attribute(self, ref, reader): @@ -432,8 +414,7 @@ def test_iter_as_aux_cutoff(self, ref, reader): assert_equal( num_frames, 0, - "iter_as_aux should iterate over 0 frames," - " not {}".format(num_frames), + "iter_as_aux should iterate over 0 frames," " not {}".format(num_frames), ) def test_reload_auxiliaries_from_description(self, ref, reader): @@ -496,9 +477,7 @@ def test_transformations_slice(self, ref, transformed): v2 = np.float32((0, 0, 0.33)) for i, ts in enumerate(transformed[2:3:1]): idealcoords = ref.iter_ts(ts.frame).positions + v1 + v2 - assert_allclose( - ts.positions, idealcoords, atol=10 ** (-ref.prec), rtol=0 - ) + assert_allclose(ts.positions, idealcoords, atol=10 ** (-ref.prec), rtol=0) def test_transformations_switch_frame(self, ref, transformed): # This test checks if the transformations are applied and if the coordinates @@ -572,9 +551,7 @@ def test_transformations_copy(self, ref, transformed): ) for i, ts in enumerate(new): ideal_coords = ref.iter_ts(i).positions + v1 + v2 - assert_allclose( - ts.positions, ideal_coords, atol=10 ** (-ref.prec), rtol=0 - ) + assert_allclose(ts.positions, ideal_coords, atol=10 ** (-ref.prec), rtol=0) def test_add_another_transformations_raises_ValueError(self, transformed): # After defining the transformations, the workflow cannot be changed @@ -584,9 +561,7 @@ def test_add_another_transformations_raises_ValueError(self, transformed): def test_pickle_reader(self, reader): reader_p = pickle.loads(pickle.dumps(reader)) assert_equal(len(reader), len(reader_p)) - assert_equal( - reader.ts, reader_p.ts, "Timestep is changed after pickling" - ) + assert_equal(reader.ts, reader_p.ts, "Timestep is changed after pickling") reader_p_p = pickle.loads(pickle.dumps(reader_p)) assert_equal(len(reader), len(reader_p_p)) assert_equal( @@ -620,9 +595,7 @@ def test_frame_collect_all_same(self, reader): for array in collected_ts: assert_allclose(array, collected_ts[0]) - @pytest.mark.parametrize( - "order", ("fac", "fca", "afc", "acf", "caf", "cfa") - ) + @pytest.mark.parametrize("order", ("fac", "fca", "afc", "acf", "caf", "cfa")) def test_timeseries_shape(self, reader, order): timeseries = reader.timeseries(order=order) a_index = order.index("a") @@ -664,9 +637,7 @@ def test_timeseries_empty_asel(self, reader): UserWarning, match="Empty string to select atoms, empty group returned.", ): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms( - None - ) + atoms = mda.Universe(reader.filename, to_guess=()).select_atoms(None) with pytest.raises(ValueError, match="Timeseries requires at least"): reader.timeseries(asel=atoms) @@ -675,33 +646,23 @@ def test_timeseries_empty_atomgroup(self, reader): UserWarning, match="Empty string to select atoms, empty group returned.", ): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms( - None - ) + atoms = mda.Universe(reader.filename, to_guess=()).select_atoms(None) with pytest.raises(ValueError, match="Timeseries requires at least"): reader.timeseries(atomgroup=atoms) def test_timeseries_asel_warns_deprecation(self, reader): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms( - "index 1" - ) + atoms = mda.Universe(reader.filename, to_guess=()).select_atoms("index 1") with pytest.warns(DeprecationWarning, match="asel argument to"): timeseries = reader.timeseries(asel=atoms, order="fac") def test_timeseries_atomgroup(self, reader): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms( - "index 1" - ) + atoms = mda.Universe(reader.filename, to_guess=()).select_atoms("index 1") timeseries = reader.timeseries(atomgroup=atoms, order="fac") def test_timeseries_atomgroup_asel_mutex(self, reader): - atoms = mda.Universe(reader.filename, to_guess=()).select_atoms( - "index 1" - ) + atoms = mda.Universe(reader.filename, to_guess=()).select_atoms("index 1") with pytest.raises(ValueError, match="Cannot provide both"): - timeseries = reader.timeseries( - atomgroup=atoms, asel=atoms, order="fac" - ) + timeseries = reader.timeseries(atomgroup=atoms, asel=atoms, order="fac") class MultiframeReaderTest(BaseReaderTest): @@ -804,9 +765,7 @@ def test_pickle_last_ts_reader(self, reader): len(reader_p), "Last timestep is changed after pickling", ) - assert_equal( - reader.ts, reader_p.ts, "Last timestep is changed after pickling" - ) + assert_equal(reader.ts, reader_p.ts, "Last timestep is changed after pickling") class BaseWriterTest(object): @@ -1002,9 +961,7 @@ def assert_timestep_almost_equal(A, B, decimal=6, verbose=True): if A.has_forces != B.has_forces: raise AssertionError( "Only one Timestep has forces:" - "A.has_forces = {}, B.has_forces = {}".format( - A.has_forces, B.has_forces - ) + "A.has_forces = {}, B.has_forces = {}".format(A.has_forces, B.has_forces) ) if A.has_forces: assert_allclose( diff --git a/testsuite/MDAnalysisTests/coordinates/reference.py b/testsuite/MDAnalysisTests/coordinates/reference.py index 5f74a64dd04..df0c7266f30 100644 --- a/testsuite/MDAnalysisTests/coordinates/reference.py +++ b/testsuite/MDAnalysisTests/coordinates/reference.py @@ -228,9 +228,7 @@ class RefTRZ(object): class RefLAMMPSData(object): filename = LAMMPSdata n_atoms = 18364 - pos_atom1 = np.array( - [11.89985657, 48.4455719, 19.09719849], dtype=np.float32 - ) + pos_atom1 = np.array([11.89985657, 48.4455719, 19.09719849], dtype=np.float32) vel_atom1 = np.array( [-5667.59300232, 7913.80977631, -3007.79533386], dtype=np.float32 ) @@ -256,15 +254,11 @@ class RefLAMMPSDataDCD(object): class RefLAMMPSDataMini(object): filename = LAMMPSdata_mini n_atoms = 1 - pos_atom1 = np.array( - [11.89985657, 48.4455719, 19.09719849], dtype=np.float32 - ) + pos_atom1 = np.array([11.89985657, 48.4455719, 19.09719849], dtype=np.float32) vel_atom1 = np.array( [-5667.59300232, 7913.80977631, -3007.79533386], dtype=np.float32 ) - dimensions = np.array( - [60.0, 50.0, 30.0, 90.0, 90.0, 90.0], dtype=np.float32 - ) + dimensions = np.array([60.0, 50.0, 30.0, 90.0, 90.0, 90.0], dtype=np.float32) class RefLAMMPSDataAdditionalColumns(object): diff --git a/testsuite/MDAnalysisTests/coordinates/test_chainreader.py b/testsuite/MDAnalysisTests/coordinates/test_chainreader.py index 4614e3e4d1a..a54a92681e3 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_chainreader.py +++ b/testsuite/MDAnalysisTests/coordinates/test_chainreader.py @@ -82,9 +82,7 @@ def test_next_trajectory(self, universe): assert_equal(universe.trajectory.ts.frame, 1, "loading frame 2") def test_n_atoms(self, universe): - assert_equal( - universe.trajectory.n_atoms, 3341, "wrong number of atoms" - ) + assert_equal(universe.trajectory.n_atoms, 3341, "wrong number of atoms") def test_n_frames(self, universe): assert_equal( @@ -161,9 +159,7 @@ def test_write_dcd(self, universe, tmpdir): ts_orig._pos, ts_new._pos, self.prec, - err_msg="Coordinates disagree at frame {0:d}".format( - ts_orig.frame - ), + err_msg="Coordinates disagree at frame {0:d}".format(ts_orig.frame), ) def test_transform_iteration(self, universe, transformed): @@ -193,26 +189,18 @@ def test_transform_switch(self, universe, transformed): vector = np.float32([10, 10, 10]) # grab a frame: ref = universe.trajectory[2].positions + vector - assert_almost_equal( - transformed.trajectory[2].positions, ref, decimal=6 - ) + assert_almost_equal(transformed.trajectory[2].positions, ref, decimal=6) # now switch to another frame newref = universe.trajectory[10].positions + vector - assert_almost_equal( - transformed.trajectory[10].positions, newref, decimal=6 - ) + assert_almost_equal(transformed.trajectory[10].positions, newref, decimal=6) # what happens when we comeback to the previous frame? - assert_almost_equal( - transformed.trajectory[2].positions, ref, decimal=6 - ) + assert_almost_equal(transformed.trajectory[2].positions, ref, decimal=6) def test_transfrom_rewind(self, universe, transformed): vector = np.float32([10, 10, 10]) ref = universe.trajectory[0].positions + vector transformed.trajectory.rewind() - assert_almost_equal( - transformed.trajectory.ts.positions, ref, decimal=6 - ) + assert_almost_equal(transformed.trajectory.ts.positions, ref, decimal=6) class TestChainReaderCommonDt(object): @@ -242,9 +230,7 @@ class TestChainReaderFormats(object): """Test of ChainReader with explicit formats (Issue 76).""" def test_set_all_format_tuples(self): - universe = mda.Universe( - GRO, [(PDB, "pdb"), (XTC, "xtc"), (TRR, "trr")] - ) + universe = mda.Universe(GRO, [(PDB, "pdb"), (XTC, "xtc"), (TRR, "trr")]) assert universe.trajectory.n_frames == 21 assert_equal(universe.trajectory.filenames, [PDB, XTC, TRR]) @@ -390,9 +376,7 @@ def __init__(self, seq, n_frames, order): ) def test_order(self, seq_info, tmpdir, fmt): folder = str(tmpdir) - utop, fnames = build_trajectories( - folder, sequences=seq_info.seq, fmt=fmt - ) + utop, fnames = build_trajectories(folder, sequences=seq_info.seq, fmt=fmt) u = mda.Universe(utop._topology, fnames, continuous=True, to_guess=()) assert u.trajectory.n_frames == seq_info.n_frames for i, ts in enumerate(u.trajectory): @@ -457,12 +441,8 @@ def test_easy_trigger_warning(self, tmpdir): # TODO: remove when we no longer have a dependency # that still imports six if sys.version_info >= (3, 10): - warnings.filterwarnings( - action="ignore", category=ImportWarning - ) - mda.Universe( - utop._topology, fnames, continuous=True, to_guess=() - ) + warnings.filterwarnings(action="ignore", category=ImportWarning) + mda.Universe(utop._topology, fnames, continuous=True, to_guess=()) def test_single_frames(self, tmpdir): folder = str(tmpdir) diff --git a/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py b/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py index a556414de30..1b5572d881b 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py +++ b/testsuite/MDAnalysisTests/coordinates/test_chemfiles.py @@ -37,7 +37,6 @@ ) from MDAnalysisTests.coordinates.test_xyz import XYZReference - # skip entire test module if no appropriate chemfiles chemfiles = pytest.importorskip("chemfiles") @@ -54,9 +53,7 @@ def test_version_check(version, monkeypatch): ChemfilesWriter("") -@pytest.mark.skipif( - not check_chemfiles_version(), reason="Wrong version of chemfiles" -) +@pytest.mark.skipif(not check_chemfiles_version(), reason="Wrong version of chemfiles") class TestChemfileXYZ(MultiframeReaderTest): @staticmethod @pytest.fixture @@ -99,9 +96,7 @@ def __init__(self): self.dimensions = None -@pytest.mark.skipif( - not check_chemfiles_version(), reason="Wrong version of chemfiles" -) +@pytest.mark.skipif(not check_chemfiles_version(), reason="Wrong version of chemfiles") class TestChemfilesReader(MultiframeReaderTest): @staticmethod @pytest.fixture() @@ -146,9 +141,7 @@ def test_copy(self, ref): assert_allclose(original.ts.positions, copy.ts.positions) -@pytest.mark.skipif( - not check_chemfiles_version(), reason="Wrong version of chemfiles" -) +@pytest.mark.skipif(not check_chemfiles_version(), reason="Wrong version of chemfiles") class TestChemfilesWriter(BaseWriterTest): @staticmethod @pytest.fixture() @@ -165,9 +158,7 @@ def test_no_extension_raises(self, ref): ref.writer("foo") -@pytest.mark.skipif( - not check_chemfiles_version(), reason="Wrong version of chemfiles" -) +@pytest.mark.skipif(not check_chemfiles_version(), reason="Wrong version of chemfiles") class TestChemfiles(object): def test_read_chemfiles_format(self): u = mda.Universe( @@ -191,9 +182,7 @@ def test_changing_system_size(self, tmpdir): with open(outfile, "w") as fd: fd.write(VARYING_XYZ) - u = mda.Universe( - outfile, format="chemfiles", topology_format="XYZ" - ) + u = mda.Universe(outfile, format="chemfiles", topology_format="XYZ") with pytest.raises(IOError): u.trajectory._read_next_timestep() @@ -204,9 +193,7 @@ def test_wrong_open_mode(self): def check_topology(self, reference, file): u = mda.Universe(reference) - atoms = set( - [(atom.name, atom.type, atom.record_type) for atom in u.atoms] - ) + atoms = set([(atom.name, atom.type, atom.record_type) for atom in u.atoms]) bonds = set([(bond.atoms[0].ix, bond.atoms[1].ix) for bond in u.bonds]) check = mda.Universe(file) diff --git a/testsuite/MDAnalysisTests/coordinates/test_copying.py b/testsuite/MDAnalysisTests/coordinates/test_copying.py index 6a6cd865906..c8d32ac721d 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_copying.py +++ b/testsuite/MDAnalysisTests/coordinates/test_copying.py @@ -288,9 +288,7 @@ def test_timestep_copied(ref_reader): assert new.ts.positions.dtype == np.float32 -@pytest.mark.skipif( - shares_memory == False, reason="old numpy lacked shares_memory" -) +@pytest.mark.skipif(shares_memory == False, reason="old numpy lacked shares_memory") def test_positions_share_memory(original_and_copy): # check that the memory in Timestep objects is unique original, copy = original_and_copy diff --git a/testsuite/MDAnalysisTests/coordinates/test_crd.py b/testsuite/MDAnalysisTests/coordinates/test_crd.py index be68d82eae8..edbd4886b98 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_crd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_crd.py @@ -41,9 +41,7 @@ def u(self): def outfile(self, tmpdir): return os.path.join(str(tmpdir), "test.crd") - @pytest.mark.parametrize( - "testfile", ["test.crd", "test.crd.bz2", "test.crd.gz"] - ) + @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 with tmpdir.as_cwd(): @@ -137,6 +135,4 @@ def test_write(self, missing_attr, tmpdir): for attr in attrs: assert_equal(getattr(u.atoms, attr), getattr(u2.atoms, attr)) # Check missing attr is as expected - assert_equal( - getattr(u2.atoms, missing_attr), self.req_attrs[missing_attr] - ) + assert_equal(getattr(u2.atoms, missing_attr), self.req_attrs[missing_attr]) diff --git a/testsuite/MDAnalysisTests/coordinates/test_dcd.py b/testsuite/MDAnalysisTests/coordinates/test_dcd.py index 636f81759d8..d8dd128b8f5 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_dcd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_dcd.py @@ -146,9 +146,7 @@ def ref(): def test_write_random_unitcell(tmpdir): testname = str(tmpdir.join("test.dcd")) rstate = np.random.RandomState(1178083) - random_unitcells = rstate.uniform(low=5, high=120, size=(98, 6)).astype( - np.float64 - ) + random_unitcells = rstate.uniform(low=5, high=120, size=(98, 6)).astype(np.float64) u = mda.Universe(PSF, DCD) with mda.Writer(testname, n_atoms=u.atoms.n_atoms) as w: @@ -215,9 +213,7 @@ def test_array_like(universe_dcd, array_like): assert_array_equal(frames, ar) -@pytest.mark.parametrize( - "indices", ([0, 4, 2, 3, 0, 1], [0, 0, 1, 1, 2, 1, 1]) -) +@pytest.mark.parametrize("indices", ([0, 4, 2, 3, 0, 1], [0, 0, 1, 1, 2, 1, 1])) def test_list_indices(universe_dcd, indices): frames = [ts.frame for ts in universe_dcd.trajectory[indices]] assert_array_equal(frames, indices) @@ -273,9 +269,7 @@ def test_timeseries_order(order, shape, universe_dcd): assert x.shape == shape -@pytest.mark.parametrize( - "indices", [[1, 2, 3, 4], [5, 10, 15, 19], [9, 4, 2, 0, 50]] -) +@pytest.mark.parametrize("indices", [[1, 2, 3, 4], [5, 10, 15, 19], [9, 4, 2, 0, 50]]) def test_timeseries_atomindices(indices, universe_dcd): allframes = universe_dcd.trajectory.timeseries(order="afc") asel = universe_dcd.atoms[indices] @@ -361,9 +355,7 @@ def test_other_writer(universe_dcd, tmpdir, ext, decimal): decimal, err_msg="coordinate mismatch between " "original and written trajectory at " - "frame {} (orig) vs {} (written)".format( - orig_ts.frame, written_ts.frame - ), + "frame {} (orig) vs {} (written)".format(orig_ts.frame, written_ts.frame), ) @@ -510,8 +502,7 @@ def test_ts_time(universe): u = universe header = u.trajectory._file.header ref_times = [ - (ts.frame + header["istart"] / header["nsavc"]) * ts.dt - for ts in u.trajectory + (ts.frame + header["istart"] / header["nsavc"]) * ts.dt for ts in u.trajectory ] times = [ts.time for ts in u.trajectory] assert_almost_equal(times, ref_times, decimal=5) diff --git a/testsuite/MDAnalysisTests/coordinates/test_dlpoly.py b/testsuite/MDAnalysisTests/coordinates/test_dlpoly.py index 63d0a09464c..786a362e2fb 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_dlpoly.py +++ b/testsuite/MDAnalysisTests/coordinates/test_dlpoly.py @@ -58,9 +58,7 @@ def test_read_unitcell(self, ts): [0.0000000000, 0.0000000000, 18.6960000000], ] ) - assert_allclose( - ts.dimensions, mda.coordinates.core.triclinic_box(*ref) - ) + assert_allclose(ts.dimensions, mda.coordinates.core.triclinic_box(*ref)) def test_positions(self, ts): ref = np.array([-7.608595309, -7.897790000, -7.892053559]) @@ -220,9 +218,7 @@ def test_unitcell(self, u): ] ) for ts, r in zip(u.trajectory, [ref1, ref2, ref3]): - assert_allclose( - ts.dimensions, mda.coordinates.core.triclinic_box(*r) - ) + assert_allclose(ts.dimensions, mda.coordinates.core.triclinic_box(*r)) class TestDLPolyHistory(_DLHistory): diff --git a/testsuite/MDAnalysisTests/coordinates/test_dms.py b/testsuite/MDAnalysisTests/coordinates/test_dms.py index e4d9ac1ee64..820703761f7 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_dms.py +++ b/testsuite/MDAnalysisTests/coordinates/test_dms.py @@ -67,9 +67,7 @@ def test_coords_atom_0(self, universe): assert_equal(universe.atoms[0].position, coords_0) def test_n_frames(self, universe): - assert_equal( - universe.trajectory.n_frames, 1, "wrong number of frames in pdb" - ) + assert_equal(universe.trajectory.n_frames, 1, "wrong number of frames in pdb") def test_time(self, universe): assert_equal(universe.trajectory.time, 0.0, "wrong time of the frame") @@ -78,8 +76,7 @@ def test_frame(self, universe): assert_equal( universe.trajectory.frame, 0, - "wrong frame number " - "(0-based, should be 0 for single frame readers)", + "wrong frame number " "(0-based, should be 0 for single frame readers)", ) def test_frame_index_0(self, universe): diff --git a/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py b/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py index f1ec55b1917..187c9c5cea0 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py +++ b/testsuite/MDAnalysisTests/coordinates/test_fhiaims.py @@ -69,9 +69,7 @@ class RefFHIAIMS(object): filename, trajectory, topology = [FHIAIMS] * 3 reader, writer = FHIAIMSReader, FHIAIMSWriter pos_atom1 = np.asarray([6.861735, 2.103823, 37.753513], dtype=np.float32) - dimensions = np.asarray( - [18.6, 18.6, 55.8, 90.0, 90.0, 90.0], dtype=np.float32 - ) + dimensions = np.asarray([18.6, 18.6, 55.8, 90.0, 90.0, 90.0], dtype=np.float32) n_atoms = 6 n_frames = 1 time = 0.0 @@ -87,7 +85,9 @@ class TestFHIAIMSReader(object): @pytest.fixture(scope="class") def bad_input_missing_periodicity(self): - buffer = "lattice_vector 1.0 0.0 0.0\nlattice_vector 0.0 1.0 0.0\natom 0.1 0.1 0.1 H" + buffer = ( + "lattice_vector 1.0 0.0 0.0\nlattice_vector 0.0 1.0 0.0\natom 0.1 0.1 0.1 H" + ) return StringIO(buffer) @pytest.fixture(scope="class") @@ -162,13 +162,9 @@ def test_n_frames(self, ref, universe): ) def test_time(self, ref, universe): - assert_equal( - ref.time, universe.trajectory.time, "wrong time of the frame" - ) + assert_equal(ref.time, universe.trajectory.time, "wrong time of the frame") - def test_bad_input_missing_periodicity( - self, bad_input_missing_periodicity - ): + def test_bad_input_missing_periodicity(self, bad_input_missing_periodicity): with pytest.raises(ValueError, match="Found partial periodicity"): u = mda.Universe(bad_input_missing_periodicity, format="FHIAIMS") @@ -179,25 +175,17 @@ def test_bad_input_relative_positions_no_box( ValueError, match="Found relative coordinates in FHI-AIMS file without lattice info", ): - u = mda.Universe( - bad_input_relative_positions_no_box, format="FHIAIMS" - ) + u = mda.Universe(bad_input_relative_positions_no_box, format="FHIAIMS") def test_bad_input_missing_velocity(self, bad_input_missing_velocity): - with pytest.raises( - ValueError, match="Found incorrect number of velocity tags" - ): + with pytest.raises(ValueError, match="Found incorrect number of velocity tags"): u = mda.Universe(bad_input_missing_velocity, format="FHIAIMS") - def test_bad_input_velocity_wrong_position( - self, bad_input_velocity_wrong_position - ): + def test_bad_input_velocity_wrong_position(self, bad_input_velocity_wrong_position): with pytest.raises( ValueError, match="Non-conforming line .velocity must follow" ): - u = mda.Universe( - bad_input_velocity_wrong_position, format="FHIAIMS" - ) + u = mda.Universe(bad_input_velocity_wrong_position, format="FHIAIMS") def test_bad_input_wrong_input_line(self, bad_input_wrong_input_line): with pytest.raises(ValueError, match="Non-conforming line"): @@ -212,9 +200,7 @@ def test_good_input_with_velocity(self, good_input_with_velocity): "FHIAIMSReader failed to read velocities properly", ) - def test_mixed_units( - self, good_input_natural_units, good_input_mixed_units - ): + def test_mixed_units(self, good_input_natural_units, good_input_mixed_units): u_natural = mda.Universe(good_input_natural_units, format="FHIAIMS") u_mixed = mda.Universe(good_input_mixed_units, format="FHIAIMS") print(u_natural.atoms.positions) @@ -234,9 +220,7 @@ class TestFHIAIMSWriter(BaseWriterTest): @pytest.fixture def outfile(self, tmpdir): return str( - tmpdir.mkdir("FHIAIMSWriter").join( - "primitive-fhiaims-writer" + self.ext - ) + tmpdir.mkdir("FHIAIMSWriter").join("primitive-fhiaims-writer" + self.ext) ) def test_writer(self, universe, outfile): @@ -279,9 +263,7 @@ def test_writer_with_n_atoms_none(self, good_input_natural_units, outfile): assert line.startswith( "atom" ), "Line written incorrectly with FHIAIMSWriter" - assert line.endswith( - "H" - ), "Line written incorrectly with FHIAIMSWriter" + assert line.endswith("H"), "Line written incorrectly with FHIAIMSWriter" line = np.asarray(line.split()[1:-1], dtype=np.float32) assert_almost_equal( line, diff --git a/testsuite/MDAnalysisTests/coordinates/test_gms.py b/testsuite/MDAnalysisTests/coordinates/test_gms.py index 355e0658ba2..4b7ee7c7e3f 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gms.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gms.py @@ -78,9 +78,7 @@ def test_next(self, u): assert_equal(u.trajectory.ts.frame, 1, "loading frame 1") def test_dt(self, u): - assert_almost_equal( - u.trajectory.dt, 1.0, 4, err_msg="wrong timestep dt" - ) + assert_almost_equal(u.trajectory.dt, 1.0, 4, err_msg="wrong timestep dt") def test_step5distances(self, u): assert_almost_equal( diff --git a/testsuite/MDAnalysisTests/coordinates/test_gro.py b/testsuite/MDAnalysisTests/coordinates/test_gro.py index c307bdc8ca6..5f3d7f9123c 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gro.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gro.py @@ -61,9 +61,7 @@ def universe(self): def test_load_gro(self, universe): U = universe - assert_equal( - len(U.atoms), self.ref_n_atoms, "load Universe from small GRO" - ) + assert_equal(len(U.atoms), self.ref_n_atoms, "load Universe from small GRO") assert_equal( U.atoms.select_atoms("resid 150 and name HA2").atoms[0], U.atoms[self.ref_E151HA2_index], @@ -330,9 +328,7 @@ def reader(ref): @pytest.fixture(scope="class") def transformed(ref): transformed = ref.reader(ref.trajectory, convert_units=False) - transformed.add_transformations( - translate([1, 1, 1]), translate([0, 0, 0.33]) - ) + transformed.add_transformations(translate([1, 1, 1]), translate([0, 0, 0.33])) return transformed @@ -424,9 +420,7 @@ def test_writer_large(self, ref, tmpdir): u.atoms.write(outfile) with open(outfile, "rt") as mda_output: - with mda.lib.util.anyopen( - ref.topology, "rt" - ) as expected_output: + with mda.lib.util.anyopen(ref.topology, "rt") as expected_output: produced_lines = mda_output.readlines()[1:] expected_lines = expected_output.readlines()[1:] assert_equal( @@ -531,9 +525,7 @@ def test_multiframe_gro(): # for now, single frame read assert len(u.trajectory) == 1 - assert_equal( - u.dimensions, np.array([100, 100, 100, 90, 90, 90], dtype=np.float32) - ) + assert_equal(u.dimensions, np.array([100, 100, 100, 90, 90, 90], dtype=np.float32)) def test_huge_box_gro(): diff --git a/testsuite/MDAnalysisTests/coordinates/test_gsd.py b/testsuite/MDAnalysisTests/coordinates/test_gsd.py index 102b8391df9..2386d7f4edb 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gsd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gsd.py @@ -22,6 +22,7 @@ # import os +import numpy as np import pytest from numpy.testing import assert_almost_equal @@ -73,3 +74,19 @@ def test_gsd_dimensions(self, GSD_U): def test_gsd_data_step(self, GSD_U): assert GSD_U.trajectory[0].data["step"] == 0 assert GSD_U.trajectory[1].data["step"] == 500 + + def test_gsd_indexing_with_numpy_int(self, GSD_U): + traj = GSD_U.trajectory + ts = traj[np.int64(0)] + assert ts.frame == 0 + assert_almost_equal( + ts.positions[0], + [-5.4000001, -10.19999981, -10.19999981], + err_msg="positions changed unexpectedly at frame 0", + ) + frame_idx = np.int64(1) + traj._read_frame(frame_idx) + assert traj.ts.frame == 1 + for i in range(len(traj)): + ts = traj[np.int64(i)] + assert ts.frame == i diff --git a/testsuite/MDAnalysisTests/coordinates/test_h5md.py b/testsuite/MDAnalysisTests/coordinates/test_h5md.py index 1524ca7f62c..3587de1ef19 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_h5md.py +++ b/testsuite/MDAnalysisTests/coordinates/test_h5md.py @@ -311,24 +311,19 @@ def test_jump_last_frame(self, universe): @pytest.mark.parametrize("start, stop, step", ((0, 2, 1), (1, 2, 1))) def test_slice(self, universe, start, stop, step): frames = [ - universe.trajectory.ts.frame - for ts in universe.trajectory[start:stop:step] + universe.trajectory.ts.frame for ts in universe.trajectory[start:stop:step] ] assert_equal(frames, np.arange(start, stop, step)) @pytest.mark.parametrize("array_like", [list, np.array]) def test_array_like(self, universe, array_like): array = array_like([0, 2]) - frames = [ - universe.trajectory.ts.frame for ts in universe.trajectory[array] - ] + frames = [universe.trajectory.ts.frame for ts in universe.trajectory[array]] assert_equal(frames, array) def test_list_indices(self, universe): indices = [0, 1, 2, 1, 2, 2, 0] - frames = [ - universe.trajectory.ts.frame for ts in universe.trajectory[indices] - ] + frames = [universe.trajectory.ts.frame for ts in universe.trajectory[indices]] assert_equal(frames, indices) @pytest.mark.parametrize( @@ -358,12 +353,8 @@ def test_unknown_unit(self, h5md_file, outfile, dset): with h5py.File(outfile, "w") as g: f.copy(source="particles", dest=g) f.copy(source="h5md", dest=g) - g["particles" "/trajectory" f"/{dset}"].attrs[ - "unit" - ] = "random string" - with pytest.raises( - RuntimeError, match=" is not recognized by H5MDReader." - ): + g["particles" "/trajectory" f"/{dset}"].attrs["unit"] = "random string" + with pytest.raises(RuntimeError, match=" is not recognized by H5MDReader."): u = mda.Universe(TPR_xvf, outfile) def test_length_unit_from_box(self, h5md_file, universe, outfile): @@ -374,14 +365,10 @@ def test_length_unit_from_box(self, h5md_file, universe, outfile): del g["particles/trajectory/position"] ref_u = universe uw = mda.Universe(TPR_xvf, outfile) - assert_equal( - ref_u.trajectory.units["length"], uw.trajectory.units["length"] - ) + assert_equal(ref_u.trajectory.units["length"], uw.trajectory.units["length"]) for ref_ts, new_ts in zip(ref_u.trajectory, uw.trajectory): assert_equal(ref_ts.dimensions, new_ts.dimensions) - assert_equal( - ref_ts.triclinic_dimensions, new_ts.triclinic_dimensions - ) + assert_equal(ref_ts.triclinic_dimensions, new_ts.triclinic_dimensions) @pytest.mark.parametrize("group", ("position", "velocity", "force")) def test_changing_n_atoms(self, h5md_file, outfile, group): @@ -406,9 +393,7 @@ def test_2D_box(self, h5md_file, outfile): g["particles/trajectory" "/box/edges"].create_dataset( "value", data=new_box ) - with pytest.raises( - ValueError, match="MDAnalysis only supports 3-dimensional" - ): + with pytest.raises(ValueError, match="MDAnalysis only supports 3-dimensional"): u = mda.Universe(TPR_xvf, outfile) def test_box_vector(self, h5md_file, outfile): @@ -444,9 +429,7 @@ def test_no_groups(self, h5md_file, outfile): del g["particles/trajectory/position"] del g["particles/trajectory/velocity"] del g["particles/trajectory/force"] - with pytest.raises( - NoDataError, match="Provide at least a position, velocity" - ): + with pytest.raises(NoDataError, match="Provide at least a position, velocity"): u = mda.Universe(TPR_xvf, outfile) def test_no_convert_units(self, h5md_file, outfile): @@ -472,9 +455,7 @@ def test_no_units_but_convert_units_true_error(self, h5md_file, outfile): del g["particles/trajectory"][name]["value"].attrs["unit"] del g["particles/trajectory/position/time"].attrs["unit"] del g["particles/trajectory/box/edges/value"].attrs["unit"] - with pytest.raises( - ValueError, match="H5MD file must have readable units if" - ): + with pytest.raises(ValueError, match="H5MD file must have readable units if"): u = mda.Universe(TPR_xvf, outfile, convert_units=True) @pytest.mark.xfail(reason="Issue #2884") @@ -583,9 +564,7 @@ def outtop(self, tmpdir): (0.5, IOError, "H5MDWriter: Timestep does not have"), ), ) - def test_n_atoms_errors( - self, universe, Writer, outfile, scalar, error, match - ): + def test_n_atoms_errors(self, universe, Writer, outfile, scalar, error, match): n_atoms = universe.atoms.n_atoms * scalar with pytest.raises(error, match=match): with Writer(outfile, n_atoms) as W: @@ -665,9 +644,7 @@ def test_has_property(self, universe, Writer, outfile): (False, False, False), ), ) - def test_write_trajectory( - self, universe, Writer, outfile, pos, vel, force - ): + def test_write_trajectory(self, universe, Writer, outfile, pos, vel, force): try: with Writer( outfile, @@ -685,31 +662,21 @@ def test_write_trajectory( # check the trajectory contents match reference universes for ts, ref_ts in zip(uw.trajectory, universe.trajectory): - assert_almost_equal( - ts.dimensions, ref_ts.dimensions, self.prec - ) + assert_almost_equal(ts.dimensions, ref_ts.dimensions, self.prec) if pos: assert_almost_equal(ts._pos, ref_ts._pos, self.prec) else: - with pytest.raises( - NoDataError, match="This Timestep has no" - ): + with pytest.raises(NoDataError, match="This Timestep has no"): getattr(ts, "positions") if vel: - assert_almost_equal( - ts._velocities, ref_ts._velocities, self.prec - ) + assert_almost_equal(ts._velocities, ref_ts._velocities, self.prec) else: - with pytest.raises( - NoDataError, match="This Timestep has no" - ): + with pytest.raises(NoDataError, match="This Timestep has no"): getattr(ts, "velocities") if force: assert_almost_equal(ts._forces, ref_ts._forces, self.prec) else: - with pytest.raises( - NoDataError, match="This Timestep has no" - ): + with pytest.raises(NoDataError, match="This Timestep has no"): getattr(ts, "forces") # when (False, False, False) @@ -743,14 +710,10 @@ def test_write_AtomGroup_with(self, universe, outfile, outtop, Writer): for orig_ts, written_ts in zip(universe.trajectory, uw.trajectory): assert_almost_equal(ca.positions, caw.positions, self.prec) assert_almost_equal(orig_ts.time, written_ts.time, self.prec) - assert_almost_equal( - written_ts.dimensions, orig_ts.dimensions, self.prec - ) + assert_almost_equal(written_ts.dimensions, orig_ts.dimensions, self.prec) @pytest.mark.parametrize("frames, n_frames", ((None, 1), ("all", 3))) - def test_ag_write( - self, universe, outfile, outtop, Writer, frames, n_frames - ): + def test_ag_write(self, universe, outfile, outtop, Writer, frames, n_frames): """test to write with ag.write()""" ca = universe.select_atoms("protein and name CA") ca.write(outtop) @@ -764,9 +727,7 @@ def test_ag_write( for orig_ts, written_ts in zip(universe.trajectory, uw.trajectory): assert_almost_equal(ca.positions, caw.positions, self.prec) assert_almost_equal(orig_ts.time, written_ts.time, self.prec) - assert_almost_equal( - written_ts.dimensions, orig_ts.dimensions, self.prec - ) + assert_almost_equal(written_ts.dimensions, orig_ts.dimensions, self.prec) @pytest.mark.parametrize( "timeunit, lengthunit, velocityunit, forceunit", @@ -853,12 +814,8 @@ def test_no_units_w_convert_true(self, universe_no_units, outfile, Writer): for ts in universe_no_units.trajectory: W.write(universe_no_units) - def test_no_units_w_convert_false( - self, universe_no_units, outfile, Writer - ): - with Writer( - outfile, universe_no_units.atoms.n_atoms, convert_units=False - ) as W: + def test_no_units_w_convert_false(self, universe_no_units, outfile, Writer): + with Writer(outfile, universe_no_units.atoms.n_atoms, convert_units=False) as W: for ts in universe_no_units.trajectory: W.write(universe_no_units) @@ -868,9 +825,7 @@ def test_no_units_w_convert_false( @pytest.mark.parametrize("convert_units", (True, False)) def test_convert_units(self, universe, outfile, Writer, convert_units): - with Writer( - outfile, universe.atoms.n_atoms, convert_units=convert_units - ) as W: + with Writer(outfile, universe.atoms.n_atoms, convert_units=convert_units) as W: for ts in universe.trajectory: W.write(universe) @@ -880,9 +835,7 @@ def test_convert_units(self, universe, outfile, Writer, convert_units): for u1, u2 in zip(ref_units, uw_units): assert_equal(u1, u2) - @pytest.mark.parametrize( - "chunks", ((3, 1000, 1), (1, 1000, 3), (100, 100, 3)) - ) + @pytest.mark.parametrize("chunks", ((3, 1000, 1), (1, 1000, 3), (100, 100, 3))) def test_write_chunks(self, universe, outfile, Writer, chunks): with Writer(outfile, universe.atoms.n_atoms, chunks=chunks) as W: for ts in universe.trajectory: @@ -924,9 +877,7 @@ def test_write_chunks_with_nframes(self, universe, outfile, Writer): def test_write_contiguous1(self, universe, Writer, outfile): n_atoms = universe.atoms.n_atoms n_frames = len(universe.trajectory) - with Writer( - outfile, n_atoms=n_atoms, n_frames=n_frames, chunks=False - ) as W: + with Writer(outfile, n_atoms=n_atoms, n_frames=n_frames, chunks=False) as W: for ts in universe.trajectory: W.write(universe) @@ -951,12 +902,8 @@ def test_write_contiguous2(self, universe, Writer, outfile): ): assert_equal(dset.chunks, None) - @pytest.mark.parametrize( - "filter, opts", (("gzip", 1), ("gzip", 9), ("lzf", None)) - ) - def test_write_with_compression( - self, universe, outfile, Writer, filter, opts - ): + @pytest.mark.parametrize("filter, opts", (("gzip", 1), ("gzip", 9), ("lzf", None))) + def test_write_with_compression(self, universe, outfile, Writer, filter, opts): with Writer( outfile, universe.atoms.n_atoms, @@ -971,9 +918,7 @@ def test_write_with_compression( assert_equal(dset.compression, filter) assert_equal(dset.compression_opts, opts) - @pytest.mark.xfail( - os.name == "nt", reason="occasional PermissionError on windows" - ) + @pytest.mark.xfail(os.name == "nt", reason="occasional PermissionError on windows") @pytest.mark.parametrize("driver", ("core", "stdio")) def test_write_with_drivers(self, universe, outfile, Writer, driver): with Writer(outfile, universe.atoms.n_atoms, driver=driver) as W: @@ -1010,9 +955,7 @@ def test_timestep_not_modified_by_writer(self, universe, Writer, outfile): x, err_msg="Positions in Timestep were modified by writer.", ) - assert_equal( - ts.time, time, err_msg="Time in Timestep was modified by writer." - ) + assert_equal(ts.time, time, err_msg="Time in Timestep was modified by writer.") class TestH5PYNotInstalled(object): @@ -1038,9 +981,7 @@ def test_reader_no_h5py(self): def test_writer_no_h5py(self, Writer, outfile): u = mda.Universe(TPR_xvf, TRR_xvf) - with pytest.raises( - RuntimeError, match="H5MDWriter: Please install h5py" - ): + with pytest.raises(RuntimeError, match="H5MDWriter: Please install h5py"): with Writer(outfile, u.atoms.n_atoms) as W: for ts in u.trajectory: W.write(universe) diff --git a/testsuite/MDAnalysisTests/coordinates/test_imd.py b/testsuite/MDAnalysisTests/coordinates/test_imd.py index 2fed2f761fd..64e20720cdb 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_imd.py +++ b/testsuite/MDAnalysisTests/coordinates/test_imd.py @@ -1,5 +1,4 @@ -"""Test for MDAnalysis trajectory reader expectations -""" +"""Test for MDAnalysis trajectory reader expectations""" import importlib import pickle @@ -84,9 +83,7 @@ class TestImport: def _setup_mock_imdclient(self, monkeypatch, version): """Helper method to set up mock imdclient with specified version.""" # Remove IMD and imdclient modules to force fresh import - monkeypatch.delitem( - sys.modules, "MDAnalysis.coordinates.IMD", raising=False - ) + monkeypatch.delitem(sys.modules, "MDAnalysis.coordinates.IMD", raising=False) monkeypatch.delitem(sys.modules, "imdclient", raising=False) module_name = "imdclient" @@ -105,9 +102,7 @@ class MockIMDClient: mocked_module.utils = utils_module monkeypatch.setitem(sys.modules, module_name, mocked_module) - monkeypatch.setitem( - sys.modules, f"{module_name}.IMDClient", IMDClient_module - ) + monkeypatch.setitem(sys.modules, f"{module_name}.IMDClient", IMDClient_module) monkeypatch.setitem(sys.modules, f"{module_name}.utils", utils_module) return mocked_module @@ -134,9 +129,7 @@ def test_no_minversion(self, monkeypatch): import MDAnalysis.coordinates.IMD from MDAnalysis.coordinates.IMD import HAS_IMDCLIENT - assert ( - not HAS_IMDCLIENT - ), "HAS_IMDCLIENT should be False with version 0.0.0" + assert not HAS_IMDCLIENT, "HAS_IMDCLIENT should be False with version 0.0.0" def test_missing_ImportError(self, monkeypatch): """Test that IMDReader raises ImportError when HAS_IMDCLIENT=False.""" @@ -148,9 +141,7 @@ def test_missing_ImportError(self, monkeypatch): from MDAnalysis.coordinates.IMD import IMDReader # IMDReader should raise ImportError when HAS_IMDCLIENT=False - with pytest.raises( - ImportError, match="IMDReader requires the imdclient" - ): + with pytest.raises(ImportError, match="IMDReader requires the imdclient"): IMDReader("imd://localhost:12345", n_atoms=5) @@ -249,9 +240,7 @@ def transformed(ref): ) # Send the rest of the frames- small enough to all fit in socket itself ref.server.send_frames(1, 5) - transformed.add_transformations( - translate([1, 1, 1]), translate([0, 0, 0.33]) - ) + transformed.add_transformations(translate([1, 1, 1]), translate([0, 0, 0.33])) return transformed def test_n_frames(self, ref, reader): @@ -260,9 +249,7 @@ def test_n_frames(self, ref, reader): def test_first_frame(self, ref, reader): # don't rewind here as in inherited base test - assert_timestep_almost_equal( - reader.ts, ref.first_frame, decimal=ref.prec - ) + assert_timestep_almost_equal(reader.ts, ref.first_frame, decimal=ref.prec) def test_get_writer_1(self, ref, reader, tmpdir): with pytest.raises( @@ -289,9 +276,7 @@ def test_total_time(self, ref, reader): pytest.skip("`total_time` is unknown for IMDReader") def test_changing_dimensions(self, ref, reader): - with pytest.raises( - RuntimeError, match="Stream-based readers can't be rewound" - ): + with pytest.raises(RuntimeError, match="Stream-based readers can't be rewound"): reader.rewind() def test_iter(self, ref, reader): @@ -327,9 +312,7 @@ def test_reload_auxiliaries_from_description(self, ref, reader): pytest.skip("Cannot create two IMDReaders on the same stream") def test_stop_iter(self, reader): - with pytest.raises( - RuntimeError, match="Stream-based readers can't be rewound" - ): + with pytest.raises(RuntimeError, match="Stream-based readers can't be rewound"): reader.rewind() def test_iter_rewinds(self, reader): @@ -357,9 +340,7 @@ def test_transformation_rewind(self, ref, transformed): pytest.skip("IMDReader cannot be reopened") def test_pickle_reader(self, reader): - with pytest.raises( - NotImplementedError, match="does not support pickling" - ): + with pytest.raises(NotImplementedError, match="does not support pickling"): pickle.dumps(reader) def test_pickle_next_ts_reader(self, reader): diff --git a/testsuite/MDAnalysisTests/coordinates/test_lammps.py b/testsuite/MDAnalysisTests/coordinates/test_lammps.py index 3b203f5bae2..c20f39ecf91 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_lammps.py +++ b/testsuite/MDAnalysisTests/coordinates/test_lammps.py @@ -222,18 +222,14 @@ def test_Writer_atoms_types(self, LAMMPSDATAWriter): err_msg="attributes different after writing", ) - @pytest.mark.parametrize( - "attr", ["bonds", "angles", "dihedrals", "impropers"] - ) + @pytest.mark.parametrize("attr", ["bonds", "angles", "dihedrals", "impropers"]) def test_Writer_atoms(self, attr, LAMMPSDATAWriter): u_ref, u_new = LAMMPSDATAWriter ref = getattr(u_ref.atoms, attr) new = getattr(u_new.atoms, attr) assert ref == new, "attributes different after writing" - @pytest.mark.parametrize( - "attr", ["masses", "charges", "velocities", "positions"] - ) + @pytest.mark.parametrize("attr", ["masses", "charges", "velocities", "positions"]) def test_Writer_numerical_attrs(self, attr, LAMMPSDATAWriter): u_ref, u_new = LAMMPSDATAWriter try: @@ -260,9 +256,7 @@ def test_molecule_tag(self, LAMMPSDATAWriter_molecule_tag): ) -@pytest.mark.parametrize( - "filename", ["out.data", "out.data.bz2", "out.data.gz"] -) +@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 @@ -300,9 +294,7 @@ def LAMMPSDATA_partial(tmpdir): return u, u_new - @pytest.mark.parametrize( - "attr", ["masses", "charges", "velocities", "positions"] - ) + @pytest.mark.parametrize("attr", ["masses", "charges", "velocities", "positions"]) def test_Writer_atoms(self, attr, LAMMPSDATA_partial): u_ref, u_new = LAMMPSDATA_partial if hasattr(u_ref.atoms, attr): @@ -350,9 +342,7 @@ def test_n_frames(self, u): assert_equal(u.trajectory.n_frames, self.n_frames) def test_dimensions(self, u): - mean_dimensions = np.mean( - [ts.dimensions.copy() for ts in u.trajectory], axis=0 - ) + mean_dimensions = np.mean([ts.dimensions.copy() for ts in u.trajectory], axis=0) assert_allclose(mean_dimensions, self.mean_dimensions) def test_dt(self, u): @@ -367,15 +357,11 @@ def test_Timestep_time(self, u): assert_allclose( u.trajectory[iframe].time, iframe * self.dt, - err_msg="Time for frame {0} (dt={1}) is wrong.".format( - iframe, self.dt - ), + err_msg="Time for frame {0} (dt={1}) is wrong.".format(iframe, self.dt), ) def test_LAMMPSDCDReader_set_dt(self, u, dt=1500.0): - u = mda.Universe( - self.topology, self.trajectory, format=self.format, dt=dt - ) + u = mda.Universe(self.topology, self.trajectory, format=self.format, dt=dt) iframe = self.get_frame_from_end(1, u) assert_allclose( u.trajectory[iframe].time, @@ -419,18 +405,14 @@ def u(self): def test_Writer_is_LAMMPS(self, u, tmpdir): ext = os.path.splitext(self.trajectory)[1] outfile = str(tmpdir.join("lammps-writer-test" + ext)) - with mda.Writer( - outfile, n_atoms=u.atoms.n_atoms, format=self.format - ) as W: + with mda.Writer(outfile, n_atoms=u.atoms.n_atoms, format=self.format) as W: assert W.flavor, self.flavor def test_Writer(self, u, tmpdir, n_frames=3): ext = os.path.splitext(self.trajectory)[1] outfile = str(tmpdir.join("lammps-writer-test" + ext)) - with mda.Writer( - outfile, n_atoms=u.atoms.n_atoms, format=self.format - ) as w: + with mda.Writer(outfile, n_atoms=u.atoms.n_atoms, format=self.format) as w: for ts in u.trajectory[:n_frames]: w.write(u) @@ -506,9 +488,7 @@ def test_open(self, tmpdir): def test_wrong_time_unit(self, tmpdir): outfile = str(tmpdir.join("lammps-writer-test.dcd")) with pytest.raises(TypeError): - with mda.coordinates.LAMMPS.DCDWriter( - outfile, n_atoms=10, timeunit="nm" - ): + with mda.coordinates.LAMMPS.DCDWriter(outfile, n_atoms=10, timeunit="nm"): pass def test_wrong_unit(self, tmpdir): @@ -583,9 +563,7 @@ def u(self, tmpdir, request): with gzip.GzipFile(f, "wb") as fout: fout.write(data) - yield mda.Universe( - f, format="LAMMPSDUMP", lammps_coordinate_convention="auto" - ) + yield mda.Universe(f, format="LAMMPSDUMP", lammps_coordinate_convention="auto") @pytest.fixture() def u_additional_columns_true(self): @@ -703,15 +681,9 @@ def test_seeking(self, u, reference_positions): u.trajectory[1] assert_allclose(u.dimensions, reference_positions["box"][1], atol=1e-5) - pos = ( - reference_positions["atom1_pos"][1] - - reference_positions["mins"][1] - ) + pos = reference_positions["atom1_pos"][1] - reference_positions["mins"][1] assert_allclose(u.atoms[0].position, pos, atol=1e-5) - pos = ( - reference_positions["atom13_pos"][1] - - reference_positions["mins"][1] - ) + pos = reference_positions["atom13_pos"][1] - reference_positions["mins"][1] assert_allclose(u.atoms[12].position, pos, atol=1e-5) def test_boxsize(self, u, reference_positions): @@ -742,9 +714,7 @@ def test_additional_columns(self, system, fields, request): u = request.getfixturevalue(system) for field in fields: data = u.trajectory[0].data[field] - assert_allclose( - data, getattr(RefLAMMPSDataAdditionalColumns, field) - ) + assert_allclose(data, getattr(RefLAMMPSDataAdditionalColumns, field)) @pytest.mark.parametrize( "system", @@ -753,9 +723,7 @@ def test_additional_columns(self, system, fields, request): ], ) def test_wrong_format_additional_colums(self, system, request): - with pytest.raises( - ValueError, match="Please provide an iterable containing" - ): + with pytest.raises(ValueError, match="Please provide an iterable containing"): request.getfixturevalue(system) @pytest.mark.parametrize( @@ -769,9 +737,7 @@ def test_warning(self, system, request): request.getfixturevalue(system) -@pytest.mark.parametrize( - "convention", ["unscaled", "unwrapped", "scaled_unwrapped"] -) +@pytest.mark.parametrize("convention", ["unscaled", "unwrapped", "scaled_unwrapped"]) def test_open_absent_convention_fails(convention): with pytest.raises(ValueError, match="No coordinates following"): mda.Universe( @@ -783,9 +749,7 @@ def test_open_absent_convention_fails(convention): def test_open_incorrect_convention_fails(): with pytest.raises(ValueError, match="is not a valid option"): - mda.Universe( - LAMMPSDUMP, format="LAMMPSDUMP", lammps_coordinate_convention="42" - ) + mda.Universe(LAMMPSDUMP, format="LAMMPSDUMP", lammps_coordinate_convention="42") @pytest.mark.parametrize( @@ -887,9 +851,7 @@ def reference_unwrapped_positions(self): ] ) - def test_unwrapped_scaled_reference( - self, universes, reference_unwrapped_positions - ): + def test_unwrapped_scaled_reference(self, universes, reference_unwrapped_positions): atom_340 = universes["unwrapped"].atoms[339] for i, ts_u in enumerate(universes["unwrapped"].trajectory[0:3]): assert_allclose( @@ -898,14 +860,10 @@ def test_unwrapped_scaled_reference( atol=1e-5, ) - def test_unwrapped_scaled_reference( - self, universes, reference_unwrapped_positions - ): + def test_unwrapped_scaled_reference(self, universes, reference_unwrapped_positions): # NOTE use of unscaled positions here due to S->R transform atom_340 = universes["scaled_unwrapped"].atoms[339] - for i, ts_u in enumerate( - universes["scaled_unwrapped"].trajectory[0:3] - ): + for i, ts_u in enumerate(universes["scaled_unwrapped"].trajectory[0:3]): assert_allclose( atom_340.position, reference_unwrapped_positions[i, :], @@ -985,8 +943,6 @@ def test_box(self, u_dump, u_data, reference_box): assert_allclose(ts.dimensions, reference_box, rtol=1e-5, atol=0) for ts in u_dump.trajectory: - assert_allclose( - ts.dimensions, u_data.dimensions, rtol=1e-5, atol=0 - ) + assert_allclose(ts.dimensions, u_data.dimensions, rtol=1e-5, atol=0) assert_allclose(u_data.dimensions, reference_box, rtol=1e-5, atol=0) diff --git a/testsuite/MDAnalysisTests/coordinates/test_memory.py b/testsuite/MDAnalysisTests/coordinates/test_memory.py index 5d020d43d2e..27c7e09216f 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_memory.py +++ b/testsuite/MDAnalysisTests/coordinates/test_memory.py @@ -73,9 +73,7 @@ def __init__(self): self.jump_to_frame.time = self.jump_to_frame.frame * self.dt def reader(self, trajectory): - return mda.Universe( - self.topology, trajectory, in_memory=True - ).trajectory + return mda.Universe(self.topology, trajectory, in_memory=True).trajectory def iter_ts(self, i): ts = self.universe.trajectory[i] @@ -100,9 +98,7 @@ def test_filename_array(self): # filename attribute of MemoryReader should be None when generated from an array universe = mda.Universe(PSF, DCD) coordinates = universe.trajectory.timeseries(universe.atoms) - universe2 = mda.Universe( - PSF, coordinates, format=MemoryReader, order="afc" - ) + universe2 = mda.Universe(PSF, coordinates, format=MemoryReader, order="afc") assert universe2.trajectory.filename is None def test_default_memory_layout(self): @@ -141,9 +137,7 @@ def test_extract_array_caf(self, reader): assert_equal(reader.timeseries(order="caf").shape, (3, 3341, 98)) def test_timeseries_skip1(self, ref, reader): - assert_equal( - reader.timeseries(ref.universe.atoms).shape, (3341, 98, 3) - ) + assert_equal(reader.timeseries(ref.universe.atoms).shape, (3341, 98, 3)) def test_timeseries_skip10(self, reader): # Check that timeseries skip works similar to numpy slicing @@ -174,9 +168,7 @@ def test_timeseries_view_from_select_all(self, ref, reader): # timeseries() is expected to provide a view of the underlying array # also in the special case when using "all" in selections. selection = ref.universe.select_atoms("all") - assert_equal( - reader.timeseries(asel=selection).base is reader.get_array(), True - ) + assert_equal(reader.timeseries(asel=selection).base is reader.get_array(), True) def test_timeseries_noview(self, ref, reader): # timeseries() is expected NOT to provide a view of the underlying array @@ -200,12 +192,8 @@ def test_float32(self, ref): coordinates = np.random.uniform( size=(100, ref.universe.atoms.n_atoms, 3) ).cumsum(0) - universe = mda.Universe( - ref.universe.filename, coordinates, format=MemoryReader - ) - assert_equal( - universe.trajectory.get_array().dtype, np.dtype("float32") - ) + universe = mda.Universe(ref.universe.filename, coordinates, format=MemoryReader) + assert_equal(universe.trajectory.get_array().dtype, np.dtype("float32")) def test_position_assignation(self, reader): # When coordinates are assigned to a timestep, is the change persistent? diff --git a/testsuite/MDAnalysisTests/coordinates/test_mol2.py b/testsuite/MDAnalysisTests/coordinates/test_mol2.py index 494b2ace2af..cc6761fd488 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_mol2.py +++ b/testsuite/MDAnalysisTests/coordinates/test_mol2.py @@ -55,9 +55,7 @@ def test_read(self): assert_equal(u.trajectory.n_frames, 200) u.trajectory[199] - assert_array_almost_equal( - u.atoms.positions[0], [1.7240, 11.2730, 14.1200] - ) + assert_array_almost_equal(u.atoms.positions[0], [1.7240, 11.2730, 14.1200]) def test_read_statusbit(self): u = Universe(mol2_ligand) @@ -113,9 +111,7 @@ def test_comments_header(self): assert_equal(len(u.atoms), 9) assert_equal(u.trajectory.n_frames, 2) u.trajectory[1] - assert_array_almost_equal( - u.atoms.positions[2], [-12.2710, -1.9540, -16.0480] - ) + assert_array_almost_equal(u.atoms.positions[2], [-12.2710, -1.9540, -16.0480]) def test_no_bonds(self, tmpdir): # Issue #3057 @@ -163,9 +159,7 @@ def test_slice_traj(self): def test_reverse_traj(self): frames = [ts.frame for ts in self.traj[20:5:-1]] - assert_equal( - frames, list(range(20, 5, -1)), "reversing traj [20:5:-1]" - ) + assert_equal(frames, list(range(20, 5, -1)), "reversing traj [20:5:-1]") def test_n_frames(self): assert_equal( diff --git a/testsuite/MDAnalysisTests/coordinates/test_netcdf.py b/testsuite/MDAnalysisTests/coordinates/test_netcdf.py index 1ebad11665c..0f84a386e60 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_netcdf.py +++ b/testsuite/MDAnalysisTests/coordinates/test_netcdf.py @@ -79,9 +79,7 @@ def test_get_writer(self, universe): assert w.remarks.startswith("AMBER NetCDF format") def test_get_writer_custom_n_atoms(self, universe): - with universe.trajectory.Writer( - "out.ncdf", n_atoms=42, remarks="Hi!" - ) as w: + with universe.trajectory.Writer("out.ncdf", n_atoms=42, remarks="Hi!") as w: assert w.n_atoms == 42 assert w.remarks == "Hi!" @@ -341,9 +339,7 @@ def test_velocities(self, universe, index, expected): @pytest.mark.parametrize("index,expected", ((0, 1.0), (8, 9.0))) def test_time(self, universe, index, expected): - assert_almost_equal( - expected, universe.trajectory[index].time, self.prec - ) + assert_almost_equal(expected, universe.trajectory[index].time, self.prec) def test_nframes(self, universe): assert_equal(10, universe.trajectory.n_frames) @@ -427,16 +423,12 @@ def create_ncdf(self, params): time = ncdf.createVariable("time", "d", ("time",)) setattr(time, "units", params["time"]) time[:] = 1.0 - cell_spatial = ncdf.createVariable( - "cell_spatial", "c", ("cell_spatial",) - ) + cell_spatial = ncdf.createVariable("cell_spatial", "c", ("cell_spatial",)) cell_spatial[:] = np.asarray(list("abc")) cell_angular = ncdf.createVariable( "cell_angular", "c", ("cell_angular", "label") ) - cell_angular[:] = np.asarray( - [list("alpha"), list("beta "), list("gamma")] - ) + cell_angular[:] = np.asarray([list("alpha"), list("beta "), list("gamma")]) # Spatial or atom dependent variables if (params["spatial"]) and (params["n_atoms"]): @@ -473,9 +465,7 @@ def create_ncdf(self, params): velocs = ncdf.createVariable( "velocities", "f8", ("atom", "spatial") ) - forces = ncdf.createVariable( - "forces", "f8", ("atom", "spatial") - ) + forces = ncdf.createVariable("forces", "f8", ("atom", "spatial")) # Set units if params["coordinates"]: @@ -509,18 +499,10 @@ def create_ncdf(self, params): coords[:] = np.asarray( range(params["spatial"]), dtype=np.float32 ) - cell_lengths[:] = np.array( - [20.0, 20.0, 20.0], dtype=np.float32 - ) - cell_angles[:] = np.array( - [90.0, 90.0, 90.0], dtype=np.float32 - ) - velocs[:] = np.asarray( - range(params["spatial"]), dtype=np.float32 - ) - forces[:] = np.asarray( - range(params["spatial"]), dtype=np.float32 - ) + cell_lengths[:] = np.array([20.0, 20.0, 20.0], dtype=np.float32) + cell_angles[:] = np.array([90.0, 90.0, 90.0], dtype=np.float32) + velocs[:] = np.asarray(range(params["spatial"]), dtype=np.float32) + forces[:] = np.asarray(range(params["spatial"]), dtype=np.float32) # self.scale_factor overrides which variable gets a scale_factor if params["scale_factor"]: @@ -710,14 +692,11 @@ def test_conventionversion_warn(self, tmpdir): assert len(record) == 1 wmsg = ( - "NCDF trajectory format is 2.0 but the reader " - "implements format 1.0" + "NCDF trajectory format is 2.0 but the reader " "implements format 1.0" ) assert str(record[0].message.args[0]) == wmsg - @pytest.mark.parametrize( - "mutation", [{"program": None}, {"programVersion": None}] - ) + @pytest.mark.parametrize("mutation", [{"program": None}, {"programVersion": None}]) def test_program_warn(self, tmpdir, mutation): params = self.gen_params(keypair=mutation, restart=False) with tmpdir.as_cwd(): @@ -791,14 +770,12 @@ def _test_write_trajectory(self, universe, outfile): assert_equal( coords[:].dtype.name, np.dtype(np.float32).name, - err_msg="ncdf coord output not float32 " - "but {}".format(coords[:].dtype), + err_msg="ncdf coord output not float32 " "but {}".format(coords[:].dtype), ) assert_equal( time[:].dtype.name, np.dtype(np.float32).name, - err_msg="ncdf time output not float32 " - "but {}".format(time[:].dtype), + err_msg="ncdf time output not float32 " "but {}".format(time[:].dtype), ) def test_write_trajectory_netCDF4(self, universe, outfile): @@ -842,16 +819,14 @@ def _check_new_traj(self, universe, outfile): self.prec, err_msg="coordinate mismatch between " "original and written trajectory at " - "frame %d (orig) vs %d (written)" - % (orig_ts.frame, written_ts.frame), + "frame %d (orig) vs %d (written)" % (orig_ts.frame, written_ts.frame), ) # not a good test because in the example trajectory all times are 0 assert_almost_equal( orig_ts.time, written_ts.time, self.prec, - err_msg="Time for step {0} are not the " - "same.".format(orig_ts.frame), + err_msg="Time for step {0} are not the " "same.".format(orig_ts.frame), ) assert_almost_equal( written_ts.dimensions, @@ -892,15 +867,13 @@ def _check_new_traj(self, universe, outfile): v[:], v_new[:], self.prec, - err_msg="Variable '{0}' not " - "written correctly".format(k), + err_msg="Variable '{0}' not " "written correctly".format(k), ) except TypeError: assert_equal( v[:], v_new[:], - err_msg="Variable {0} not written " - "correctly".format(k), + err_msg="Variable {0} not written " "correctly".format(k), ) def test_TRR2NCDF(self, outfile): @@ -938,8 +911,7 @@ def test_TRR2NCDF(self, outfile): orig_ts.time, written_ts.time, self.prec, - err_msg="Time for step {0} are not the " - "same.".format(orig_ts.frame), + err_msg="Time for step {0} are not the " "same.".format(orig_ts.frame), ) assert_almost_equal( written_ts.dimensions, @@ -967,15 +939,13 @@ def test_write_AtomGroup(self, universe, outfile, outtop): self.prec, err_msg="coordinate mismatch between " "original and written trajectory at " - "frame %d (orig) vs %d (written)" - % (orig_ts.frame, written_ts.frame), + "frame %d (orig) vs %d (written)" % (orig_ts.frame, written_ts.frame), ) assert_almost_equal( orig_ts.time, written_ts.time, self.prec, - err_msg="Time for step {0} are not the " - "same.".format(orig_ts.frame), + err_msg="Time for step {0} are not the " "same.".format(orig_ts.frame), ) assert_almost_equal( written_ts.dimensions, @@ -1057,18 +1027,14 @@ def test_write_u(self, pos, vel, force, tmpdir, u1, u2): u = mda.Universe(self.top, outfile) # check the trajectory contents match reference universes - for ts, ref_ts in zip( - u.trajectory, [u1.trajectory.ts, u2.trajectory.ts] - ): + for ts, ref_ts in zip(u.trajectory, [u1.trajectory.ts, u2.trajectory.ts]): if pos: assert_almost_equal(ts._pos, ref_ts._pos, self.prec) else: with pytest.raises(mda.NoDataError): getattr(ts, "positions") if vel: - assert_almost_equal( - ts._velocities, ref_ts._velocities, self.prec - ) + assert_almost_equal(ts._velocities, ref_ts._velocities, self.prec) else: with pytest.raises(mda.NoDataError): getattr(ts, "velocities") @@ -1229,15 +1195,11 @@ def test_write_read_write( for ts1, ts3 in zip(universe.trajectory, universe3.trajectory): assert_almost_equal(ts1.time, ts3.time) assert_almost_equal(ts1.dimensions, ts3.dimensions) - assert_almost_equal( - universe.atoms.positions, universe3.atoms.positions, 4 - ) + assert_almost_equal(universe.atoms.positions, universe3.atoms.positions, 4) assert_almost_equal( universe.atoms.velocities, universe3.atoms.velocities, 4 ) - assert_almost_equal( - universe.atoms.forces, universe3.atoms.forces, 4 - ) + assert_almost_equal(universe.atoms.forces, universe3.atoms.forces, 4) class TestScipyScaleFactors(TestNCDFWriterScaleFactors): @@ -1246,9 +1208,7 @@ class TestScipyScaleFactors(TestNCDFWriterScaleFactors): @pytest.fixture(autouse=True) def block_netcdf4(self, monkeypatch): - monkeypatch.setattr( - sys.modules["MDAnalysis.coordinates.TRJ"], "netCDF4", None - ) + monkeypatch.setattr(sys.modules["MDAnalysis.coordinates.TRJ"], "netCDF4", None) def test_ncdf4_not_present(self, outfile, universe): # whilst we're here, let's also test this warning diff --git a/testsuite/MDAnalysisTests/coordinates/test_pdb.py b/testsuite/MDAnalysisTests/coordinates/test_pdb.py index 9c88b97ffd1..9ef3c52d3c9 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pdb.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pdb.py @@ -64,9 +64,7 @@ assert_allclose, ) -IGNORE_NO_INFORMATION_WARNING = ( - "ignore:Found no information for attr:UserWarning" -) +IGNORE_NO_INFORMATION_WARNING = "ignore:Found no information for attr:UserWarning" @pytest.fixture @@ -116,8 +114,7 @@ def test_ENT(self): class TestPDBMetadata(object): header = "HYDROLASE 11-MAR-12 4E43" title = [ - "HIV PROTEASE (PR) DIMER WITH ACETATE IN EXO SITE AND PEPTIDE " - "IN ACTIVE", + "HIV PROTEASE (PR) DIMER WITH ACETATE IN EXO SITE AND PEPTIDE " "IN ACTIVE", "2 SITE", ] compnd = [ @@ -165,9 +162,7 @@ def test_TITLE(self, universe): len(self.title), err_msg="TITLE does not contain same number of lines", ) - for lineno, (parsed, reference) in enumerate( - zip(title, self.title), start=1 - ): + for lineno, (parsed, reference) in enumerate(zip(title, self.title), start=1): assert_equal( parsed, reference, @@ -178,9 +173,7 @@ def test_COMPND(self, universe): try: compound = universe.trajectory.compound except AttributeError: - raise AssertionError( - "Reader does not have a 'compound' attribute." - ) + raise AssertionError("Reader does not have a 'compound' attribute.") assert_equal( len(compound), len(self.compnd), @@ -207,9 +200,7 @@ def test_REMARK(self, universe): ) # only look at the first 5 entries for lineno, (parsed, reference) in enumerate( - zip( - remarks[: self.nmax_remarks], self.remarks[: self.nmax_remarks] - ), + zip(remarks[: self.nmax_remarks], self.remarks[: self.nmax_remarks]), start=1, ): assert_equal( @@ -223,9 +214,7 @@ class TestExtendedPDBReader(_SingleFrameReader): __test__ = True def setUp(self): - self.universe = mda.Universe( - PDB_small, topology_format="XPDB", format="XPDB" - ) + self.universe = mda.Universe(PDB_small, topology_format="XPDB", format="XPDB") # 3 decimals in PDB spec # http://www.wwpdb.org/documentation/format32/sect9.html#ATOM self.prec = 3 @@ -277,9 +266,7 @@ def universe_and_expected_dims(self, request): @pytest.fixture def outfile(self, tmpdir): - return str( - tmpdir.mkdir("PDBWriter").join("primitive-pdb-writer" + self.ext) - ) + return str(tmpdir.mkdir("PDBWriter").join("primitive-pdb-writer" + self.ext)) @pytest.fixture def u_no_ids(self): @@ -298,9 +285,7 @@ def u_no_ids(self): trajectory=True, ) universe.add_TopologyAttr("icodes", [" "] * len(universe.residues)) - universe.add_TopologyAttr( - "record_types", ["ATOM"] * len(universe.atoms) - ) + universe.add_TopologyAttr("record_types", ["ATOM"] * len(universe.atoms)) universe.dimensions = [10, 10, 10, 90, 90, 90] return universe @@ -407,8 +392,7 @@ def test_write_single_frame_AtomGroup(self, universe2, outfile): u.atoms.positions, self.prec, err_msg="Written coordinates do not " - "agree with original coordinates from frame %d" - % u.trajectory.frame, + "agree with original coordinates from frame %d" % u.trajectory.frame, ) def test_write_nodims(self, universe_and_expected_dims, outfile): @@ -428,7 +412,9 @@ def test_write_nodims(self, universe_and_expected_dims, outfile): else: assert np.allclose(u.dimensions, expected_dims) - expected_msg = "Unit cell dimensions not found. CRYST1 record set to unitary values." + expected_msg = ( + "Unit cell dimensions not found. CRYST1 record set to unitary values." + ) with pytest.warns(UserWarning, match=expected_msg): u.atoms.write(outfile) @@ -451,8 +437,7 @@ def test_write_nodims(self, universe_and_expected_dims, outfile): uout.atoms.positions, self.prec, err_msg="Written coordinates do not " - "agree with original coordinates from frame %d" - % u.trajectory.frame, + "agree with original coordinates from frame %d" % u.trajectory.frame, ) def test_check_coordinate_limits_min(self, universe, outfile): @@ -495,9 +480,7 @@ def test_check_HEADER_TITLE_multiframe(self, universe2, outfile): assert got_title <= 1, "There should be only one TITLE." @pytest.mark.parametrize("startframe,maxframes", [(0, 12), (9997, 12)]) - def test_check_MODEL_multiframe( - self, universe2, outfile, startframe, maxframes - ): + def test_check_MODEL_multiframe(self, universe2, outfile, startframe, maxframes): """Check whether MODEL number is in the right column (Issue #1950)""" u = universe2 protein = u.select_atoms("protein and name CA") @@ -567,18 +550,12 @@ def test_hetatm_written(self, universe4, tmpdir, outfile): u.atoms.write(outfile) written = mda.Universe(outfile) - written_atoms = written.select_atoms( - "resname ETA and " "record_type HETATM" - ) + written_atoms = written.select_atoms("resname ETA and " "record_type HETATM") assert len(u_hetatms) == len(written_atoms), "mismatched HETATM number" - assert_almost_equal( - u_hetatms.atoms.positions, written_atoms.atoms.positions - ) + assert_almost_equal(u_hetatms.atoms.positions, written_atoms.atoms.positions) - def test_default_atom_record_type_written( - self, universe5, tmpdir, outfile - ): + def test_default_atom_record_type_written(self, universe5, tmpdir, outfile): """ Checks that ATOM record types are written when there is no record_type attribute. @@ -1025,9 +1002,7 @@ def universe(): def test_load_pdb(self, universe): U = universe - assert_equal( - len(U.atoms), self.ref_n_atoms, "load Universe from big PDB" - ) + assert_equal(len(U.atoms), self.ref_n_atoms, "load Universe from big PDB") assert_equal( U.atoms.select_atoms("resid 150 and name HA2").atoms[0], U.atoms[self.ref_E151HA2_index], @@ -1323,9 +1298,9 @@ def test_deduce_PDB_atom_name(atom, refname): # The Pair named tuple is used to mock atoms as we only need them to have a # ``resname`` and a ``name`` attribute. dummy_file = StringIO() - name = mda.coordinates.PDB.PDBWriter( - dummy_file, n_atoms=1 - )._deduce_PDB_atom_name(atom.name, atom.resname) + name = mda.coordinates.PDB.PDBWriter(dummy_file, n_atoms=1)._deduce_PDB_atom_name( + atom.name, atom.resname + ) assert_equal(name, refname) @@ -1365,9 +1340,7 @@ def test_len(self, pdbfile): def test_order(self, pdbfile): u = mda.Universe(pdbfile) - for ts, refbox, refpos in zip( - u.trajectory, self.boxsize, self.position - ): + for ts, refbox, refpos in zip(u.trajectory, self.boxsize, self.position): assert_almost_equal(u.dimensions[0], refbox) assert_almost_equal(u.atoms[0].position[0], refpos) @@ -1411,9 +1384,7 @@ def test_write_pdb_zero_atoms(tmpdir): def test_atom_not_match(tmpdir): # issue 1998 - outfile = str( - tmpdir.mkdir("PDBReader").join("test_atom_not_match" + ".pdb") - ) + outfile = str(tmpdir.mkdir("PDBReader").join("test_atom_not_match" + ".pdb")) u = mda.Universe(PSF, DCD) # select two groups of atoms protein = u.select_atoms("protein and name CA") @@ -1437,11 +1408,7 @@ def test_partially_missing_cryst(): # mangle the cryst lines so that only box angles are left # this mimics '6edu' from PDB raw = [ - ( - line - if not line.startswith("CRYST") - else line[:6] + " " * 28 + line[34:] - ) + (line if not line.startswith("CRYST") else line[:6] + " " * 28 + line[34:]) for line in raw ] @@ -1463,9 +1430,7 @@ def test_write_no_atoms_elements(dummy_universe_without_elements): writer.write(dummy_universe_without_elements.atoms) content = destination.getvalue() element_symbols = [ - line[76:78].strip() - for line in content.splitlines() - if line[:6] == "ATOM " + line[76:78].strip() for line in content.splitlines() if line[:6] == "ATOM " ] expectation = ["", "", "", "", ""] assert element_symbols == expectation @@ -1487,9 +1452,7 @@ def test_write_atom_elements(dummy_universe_without_elements): writer.write(dummy_universe_without_elements.atoms) content = destination.getvalue() element_symbols = [ - line[76:78].strip() - for line in content.splitlines() - if line[:6] == "ATOM " + line[76:78].strip() for line in content.splitlines() if line[:6] == "ATOM " ] assert element_symbols == expectation @@ -1513,9 +1476,7 @@ def test_elements_roundtrip(tmpdir): def test_cryst_meaningless_warning(): # issue 2599 # FIXME: This message might change with Issue #2698 - with pytest.warns( - UserWarning, match="Unit cell dimensions will be set to None." - ): + with pytest.warns(UserWarning, match="Unit cell dimensions will be set to None."): mda.Universe(PDB_CRYOEM_BOX) @@ -1588,9 +1549,7 @@ def test_read_segids(): ATOM 665 OG1 THR A 315 21.047 13.922 1.304 1.00 15.14 B O """ - u_invalid_segid = mda.Universe( - StringIO(invalid_seg_format_str), format="PDB" - ) + u_invalid_segid = mda.Universe(StringIO(invalid_seg_format_str), format="PDB") u_acceptable = mda.Universe(StringIO(acceptable_format_str), format="PDB") u_standard = mda.Universe(StringIO(standard_format_str), format="PDB") @@ -1598,9 +1557,7 @@ def test_read_segids(): # Thus, segids existed and were set to "B" for all atoms. # After version 2.10.0, segid is read from column 73-76. # segid is expected to set by chainID "A" for all atoms. - assert_equal( - u_invalid_segid.atoms.segids, ["A"] * len(u_invalid_segid.atoms) - ) + assert_equal(u_invalid_segid.atoms.segids, ["A"] * len(u_invalid_segid.atoms)) # Before version 2.10.0, segid was set to read from column 67-76. # Due to misalignment in b-factor column, diff --git a/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py b/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py index 06bc62830b7..c358f77570b 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pdbqt.py @@ -79,9 +79,7 @@ def test_neighborhood(self, universe): assert_equal(len(residue_neighbors), 80) def test_n_frames(self, universe): - assert_equal( - universe.trajectory.n_frames, 1, "wrong number of frames in pdb" - ) + assert_equal(universe.trajectory.n_frames, 1, "wrong number of frames in pdb") def test_time(self, universe): assert_equal(universe.trajectory.time, 0.0, "wrong time of the frame") diff --git a/testsuite/MDAnalysisTests/coordinates/test_pqr.py b/testsuite/MDAnalysisTests/coordinates/test_pqr.py index fc69337ddbe..9f6798c5b9a 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_pqr.py +++ b/testsuite/MDAnalysisTests/coordinates/test_pqr.py @@ -93,9 +93,7 @@ def universe(): prec = 3 - @pytest.mark.parametrize( - "filename", ["test.pqr", "test.pqr.bz2", "test.pqr.gz"] - ) + @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) diff --git a/testsuite/MDAnalysisTests/coordinates/test_reader_api.py b/testsuite/MDAnalysisTests/coordinates/test_reader_api.py index 2e6e29c852a..c9d9eb20a96 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_reader_api.py +++ b/testsuite/MDAnalysisTests/coordinates/test_reader_api.py @@ -122,9 +122,7 @@ def test_required_attributes(self, reader): "units", "format", ]: - assert_equal( - hasattr(reader, attr), True, "Missing attr: {0}".format(attr) - ) + assert_equal(hasattr(reader, attr), True, "Missing attr: {0}".format(attr)) def test_iter(self, reader): l = [ts for ts in reader] diff --git a/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py b/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py index 1b2bc468b3e..3ff2db42710 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py +++ b/testsuite/MDAnalysisTests/coordinates/test_timestep_api.py @@ -26,6 +26,7 @@ _TestTimestepInterface tests the Readers are correctly using Timesteps """ + import itertools import numpy as np from numpy.testing import ( @@ -175,9 +176,7 @@ def test_volume(self, ts): assert_equal(ts.volume, self.ref_volume) def test_triclinic_vectors(self, ts): - assert_allclose( - ts.triclinic_dimensions, triclinic_vectors(ts.dimensions) - ) + assert_allclose(ts.triclinic_dimensions, triclinic_vectors(ts.dimensions)) def test_set_triclinic_vectors(self, ts): ref_vec = triclinic_vectors(self.newbox) @@ -406,9 +405,7 @@ def _check_copy(self, name, ref_ts): """Check basic copy""" ts2 = ref_ts.copy() - err_msg = ( - "Timestep copy failed for format {form}" " on attribute {att}" - ) + err_msg = "Timestep copy failed for format {form}" " on attribute {att}" # eq method checks: # - frame @@ -417,9 +414,7 @@ def _check_copy(self, name, ref_ts): assert ref_ts == ts2 if not ref_ts.dimensions is None: - assert_array_almost_equal( - ref_ts.dimensions, ts2.dimensions, decimal=4 - ) + assert_array_almost_equal(ref_ts.dimensions, ts2.dimensions, decimal=4) else: assert ref_ts.dimensions == ts2.dimensions @@ -511,9 +506,7 @@ def test_copy(self, func, ts): ts = u.trajectory.ts func(self, self.name, ts) - @pytest.fixture( - params=filter(any, itertools.product([True, False], repeat=3)) - ) + @pytest.fixture(params=filter(any, itertools.product([True, False], repeat=3))) def some_ts(self, request): p, v, f = request.param return self._from_coords(p, v, f) @@ -719,9 +712,7 @@ class TestBaseTimestepInterface(object): ) ) def universe(self, request): - topology, trajectory, trajectory_format, topology_format = ( - request.param - ) + topology, trajectory, trajectory_format, topology_format = request.param if trajectory_format is not None and topology_format is not None: return mda.Universe( topology, diff --git a/testsuite/MDAnalysisTests/coordinates/test_tng.py b/testsuite/MDAnalysisTests/coordinates/test_tng.py index 8eaa64d5ec2..905f612bc45 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_tng.py +++ b/testsuite/MDAnalysisTests/coordinates/test_tng.py @@ -241,9 +241,7 @@ def test_initial_frame_is_0(self, universe): assert_equal( universe.trajectory.ts.frame, 0, - "initial frame is not 0 but {0}".format( - universe.trajectory.ts.frame - ), + "initial frame is not 0 but {0}".format(universe.trajectory.ts.frame), ) def test_starts_with_first_frame(self, universe): @@ -255,9 +253,7 @@ def test_rewind(self, universe): trj = universe.trajectory trj.next() trj.next() # for readers that do not support indexing - assert_equal( - trj.ts.frame, 2, "failed to forward to frame 2 (frameindex 2)" - ) + assert_equal(trj.ts.frame, 2, "failed to forward to frame 2 (frameindex 2)") trj.rewind() assert_equal(trj.ts.frame, 0, "failed to rewind to first frame") assert np.any(universe.atoms.positions > 0) @@ -293,9 +289,7 @@ def test_positions_first_frame(self, universe): def test_box_first_frame(self, universe): dims = universe.trajectory[0].dimensions - assert_allclose( - dims, triclinic_box(*self._box_frame_0), rtol=10**-self.prec - ) + assert_allclose(dims, triclinic_box(*self._box_frame_0), rtol=10**-self.prec) def test_positions_last_frame(self, universe): pos = universe.trajectory[100].positions @@ -307,9 +301,7 @@ def test_positions_last_frame(self, universe): def test_box_last_frame(self, universe): dims = universe.trajectory[100].dimensions - assert_allclose( - dims, triclinic_box(*self._box_frame_100), rtol=10**-self.prec - ) + assert_allclose(dims, triclinic_box(*self._box_frame_100), rtol=10**-self.prec) @pytest.mark.parametrize("frame", [0, 20, 50, 100]) def test_step(self, universe, frame): @@ -321,29 +313,21 @@ def test_lambda_in_ts(self, universe): ts = universe.trajectory[10] assert "TNG_GMX_LAMBDA" in ts.data.keys() assert isinstance(ts.data["TNG_GMX_LAMBDA"], np.ndarray) - assert_equal( - ts.data["TNG_GMX_LAMBDA"], np.asarray([[0]], dtype=np.float32) - ) + assert_equal(ts.data["TNG_GMX_LAMBDA"], np.asarray([[0]], dtype=np.float32)) def test_read_box_fail_strange_step(self, universe): stepnum = 123 # step number with no data iterator_step = universe.trajectory._file_iterator.read_step(stepnum) with pytest.raises(IOError, match="Failed to read box from TNG file"): - universe.trajectory._frame_to_ts( - iterator_step, universe.trajectory.ts - ) + universe.trajectory._frame_to_ts(iterator_step, universe.trajectory.ts) def test_read_pos_fail_strange_step(self, universe): stepnum = 123 # step number with no data iterator_step = universe.trajectory._file_iterator.read_step(stepnum) # set _has_box to False to trigger position reading error universe.trajectory._has_box = False - with pytest.raises( - IOError, match="Failed to read positions from TNG file" - ): - universe.trajectory._frame_to_ts( - iterator_step, universe.trajectory.ts - ) + with pytest.raises(IOError, match="Failed to read positions from TNG file"): + universe.trajectory._frame_to_ts(iterator_step, universe.trajectory.ts) def test_additional_block_read_fails(self, universe): stepnum = 123 # step number with no data @@ -355,9 +339,7 @@ def test_additional_block_read_fails(self, universe): with pytest.raises( IOError, match="Failed to read additional block TNG_GMX_LAMBDA" ): - universe.trajectory._frame_to_ts( - iterator_step, universe.trajectory.ts - ) + universe.trajectory._frame_to_ts(iterator_step, universe.trajectory.ts) def test_parse_n_atoms(self, universe): assert universe.trajectory.parse_n_atoms(TNG_traj) == self._n_atoms @@ -412,12 +394,8 @@ def test_read_vels_fail_strange_step(self, universe): # set _has_* attrs to False to trigger velocities reading error universe.trajectory._has_box = False universe.trajectory._has_positions = False - with pytest.raises( - IOError, match="Failed to read velocities from TNG file" - ): - universe.trajectory._frame_to_ts( - iterator_step, universe.trajectory.ts - ) + with pytest.raises(IOError, match="Failed to read velocities from TNG file"): + universe.trajectory._frame_to_ts(iterator_step, universe.trajectory.ts) def test_read_force_fail_strange_step(self, universe): stepnum = 123 # step number with no data @@ -426,12 +404,8 @@ def test_read_force_fail_strange_step(self, universe): universe.trajectory._has_box = False universe.trajectory._has_positions = False universe.trajectory._has_velocities = False - with pytest.raises( - IOError, match="Failed to read forces from TNG file" - ): - universe.trajectory._frame_to_ts( - iterator_step, universe.trajectory.ts - ) + with pytest.raises(IOError, match="Failed to read forces from TNG file"): + universe.trajectory._frame_to_ts(iterator_step, universe.trajectory.ts) @pytest.mark.skipif(not HAS_PYTNG, reason="pytng not installed") diff --git a/testsuite/MDAnalysisTests/coordinates/test_trc.py b/testsuite/MDAnalysisTests/coordinates/test_trc.py index 5069fe3ed31..f9fde47aa35 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_trc.py +++ b/testsuite/MDAnalysisTests/coordinates/test_trc.py @@ -53,9 +53,7 @@ def test_trc_positions(self, TRC_U): ) # fith frame first particle TRC_U.trajectory[4] - assert_allclose( - TRC_U.atoms.positions[0], [0.37026654, 22.78805010, 3.69695262] - ) + assert_allclose(TRC_U.atoms.positions[0], [0.37026654, 22.78805010, 3.69695262]) def test_trc_dimensions(self, TRC_U): assert TRC_U.trajectory[0].dimensions is None @@ -96,13 +94,9 @@ def test_rewind(self, TRC_U): trc.next() trc.next() trc.next() - assert ( - trc.ts.frame == 4 - ), "trajectory.next() did not forward to frameindex 4" + assert trc.ts.frame == 4, "trajectory.next() did not forward to frameindex 4" trc.rewind() - assert ( - trc.ts.frame == 0 - ), "trajectory.rewind() failed to rewind to first frame" + assert trc.ts.frame == 0, "trajectory.rewind() failed to rewind to first frame" assert np.any( TRC_U.atoms.positions != 0 @@ -221,14 +215,8 @@ def test_trc_distances(self, TRC_U): ag1 = atom_1a + atom_1b + atom_1c + atom_1d ag2 = atom_2a + atom_2b + atom_2c + atom_2d - dist_A = distances.dist(ag1, ag2, box=ts.dimensions)[ - 2 - ] # return distance - dist_B = ( - atomicdistances.AtomicDistances(ag1, ag2, pbc=True) - .run() - .results[0] - ) + dist_A = distances.dist(ag1, ag2, box=ts.dimensions)[2] # return distance + dist_B = atomicdistances.AtomicDistances(ag1, ag2, pbc=True).run().results[0] assert_allclose( dist_A, [5.9488481, 4.4777278, 20.8165518, 7.5727112], rtol=1e-06 @@ -246,9 +234,7 @@ def test_universe(self): class TestTRCGenboxOrigin: def test_universe(self): - with pytest.raises( - ValueError, match="doesnt't support a shifted origin!" - ): + with pytest.raises(ValueError, match="doesnt't support a shifted origin!"): mda.Universe(TRC_PDB_VAC, TRC_GENBOX_ORIGIN) @@ -265,9 +251,7 @@ class TestTRCEmptyFile: def test_universe(self): with pytest.raises( ValueError, - match=( - "No supported blocks were found within the GROMOS trajectory!" - ), + match=("No supported blocks were found within the GROMOS trajectory!"), ): mda.Universe(TRC_PDB_VAC, TRC_EMPTY) @@ -306,16 +290,12 @@ def test_trc_n_frames(self, TRC_U): assert TRC_U.trajectory.n_frames == 3 def test_trc_frame(self, TRC_U): - with pytest.warns( - UserWarning, match="POSITION block is not supported!" - ): + with pytest.warns(UserWarning, match="POSITION block is not supported!"): assert TRC_U.trajectory[0].frame == 0 assert TRC_U.trajectory[2].frame == 2 def test_trc_time(self, TRC_U): - with pytest.warns( - UserWarning, match="POSITION block is not supported!" - ): + with pytest.warns(UserWarning, match="POSITION block is not supported!"): assert TRC_U.trajectory[0].time == 0 assert TRC_U.trajectory[2].time == 0 diff --git a/testsuite/MDAnalysisTests/coordinates/test_trj.py b/testsuite/MDAnalysisTests/coordinates/test_trj.py index 65c1e62dba0..b6de892335f 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_trj.py +++ b/testsuite/MDAnalysisTests/coordinates/test_trj.py @@ -69,24 +69,19 @@ def test_amber_proteinselection(self, universe): def test_sum_centres_of_geometry(self, universe): protein = universe.select_atoms("protein") - total = np.sum( - [protein.center_of_geometry() for ts in universe.trajectory] - ) + total = np.sum([protein.center_of_geometry() for ts in universe.trajectory]) assert_almost_equal( total, self.ref_sum_centre_of_geometry, self.prec, - err_msg="sum of centers of geometry over the " - "trajectory do not match", + err_msg="sum of centers of geometry over the " "trajectory do not match", ) def test_initial_frame_is_0(self, universe): assert_equal( universe.trajectory.ts.frame, 0, - "initial frame is not 0 but {0}".format( - universe.trajectory.ts.frame - ), + "initial frame is not 0 but {0}".format(universe.trajectory.ts.frame), ) def test_starts_with_first_frame(self, universe): @@ -100,9 +95,7 @@ def test_rewind(self, universe): trj = universe.trajectory trj.next() trj.next() # for readers that do not support indexing - assert_equal( - trj.ts.frame, 2, "failed to forward to frame 2 (frameindex 2)" - ) + assert_equal(trj.ts.frame, 2, "failed to forward to frame 2 (frameindex 2)") trj.rewind() assert_equal(trj.ts.frame, 0, "failed to rewind to first frame") assert np.any(universe.atoms.positions > 0), ( diff --git a/testsuite/MDAnalysisTests/coordinates/test_trz.py b/testsuite/MDAnalysisTests/coordinates/test_trz.py index 8e42bc644fe..aef058a6200 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_trz.py +++ b/testsuite/MDAnalysisTests/coordinates/test_trz.py @@ -60,16 +60,12 @@ def universe(self): def test_load_trz(self, universe): U = universe - assert_equal( - len(U.atoms), self.ref_n_atoms, "load Universe from PSF and TRZ" - ) + assert_equal(len(U.atoms), self.ref_n_atoms, "load Universe from PSF and TRZ") def test_next_trz(self, universe): assert_equal(universe.trajectory.ts.frame, 0, "starts at first frame") universe.trajectory.next() - assert_equal( - universe.trajectory.ts.frame, 1, "next returns frame index 1" - ) + assert_equal(universe.trajectory.ts.frame, 1, "next returns frame index 1") def test_rewind_trz(self, universe): # move to different frame and rewind to get first frame back @@ -155,9 +151,7 @@ def test_time(self, universe): ) def test_title(self, universe): - assert_equal( - self.ref_title, universe.trajectory.title, "wrong title in trz" - ) + assert_equal(self.ref_title, universe.trajectory.title, "wrong title in trz") def test_get_writer(self, universe, tmpdir): self.outfile = os.path.join(str(tmpdir), "test-trz-writer.trz") @@ -260,9 +254,7 @@ def test_no_box_warning(self, outfile): u = mda.Universe.empty(10, trajectory=True) u.dimensions = None - with pytest.warns( - UserWarning, match="box will be written as all zero values" - ): + with pytest.warns(UserWarning, match="box will be written as all zero values"): with mda.Writer(outfile, n_atoms=10) as w: w.write(u.atoms) diff --git a/testsuite/MDAnalysisTests/coordinates/test_txyz.py b/testsuite/MDAnalysisTests/coordinates/test_txyz.py index 66cd38067e9..770af1a8a15 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_txyz.py +++ b/testsuite/MDAnalysisTests/coordinates/test_txyz.py @@ -44,23 +44,17 @@ def ARC_PBC_U(): def test_txyz_positions(TXYZ_U): - assert_almost_equal( - TXYZ_U.atoms.positions[0], [-6.553398, -1.854369, 0.000000] - ) + assert_almost_equal(TXYZ_U.atoms.positions[0], [-6.553398, -1.854369, 0.000000]) def test_arc_positions(ARC_U): - assert_almost_equal( - ARC_U.atoms.positions[0], [-6.553398, -1.854369, 0.000000] - ) + assert_almost_equal(ARC_U.atoms.positions[0], [-6.553398, -1.854369, 0.000000]) def test_arc_positions_frame_2(ARC_U): ARC_U.trajectory[1] - assert_almost_equal( - ARC_U.atoms.positions[0], [-0.231579, -0.350841, -0.037475] - ) + assert_almost_equal(ARC_U.atoms.positions[0], [-0.231579, -0.350841, -0.037475]) def test_arc_traj_length(ARC_U): diff --git a/testsuite/MDAnalysisTests/coordinates/test_writer_api.py b/testsuite/MDAnalysisTests/coordinates/test_writer_api.py index 4c3ac08cb5b..aae717ab941 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_writer_api.py +++ b/testsuite/MDAnalysisTests/coordinates/test_writer_api.py @@ -24,12 +24,10 @@ import MDAnalysis as mda - # grab all known writers # sort so test order is predictable for parallel tests writers = sorted( - set(mda._MULTIFRAME_WRITERS.values()) - | set(mda._SINGLEFRAME_WRITERS.values()), + set(mda._MULTIFRAME_WRITERS.values()) | set(mda._SINGLEFRAME_WRITERS.values()), key=lambda x: x.__name__, ) known_ts_haters = [ @@ -55,8 +53,7 @@ def test_ts_error(writer, tmpdir): elif writer == mda.coordinates.LAMMPS.DATAWriter: pytest.skip("DATAWriter requires integer atom types") elif ( - writer == mda.coordinates.H5MD.H5MDWriter - and not mda.coordinates.H5MD.HAS_H5PY + writer == mda.coordinates.H5MD.H5MDWriter and not mda.coordinates.H5MD.HAS_H5PY ): pytest.skip("skipping H5MDWriter test because h5py is not installed") else: @@ -89,8 +86,7 @@ def test_write_with_atomgroup(writer, tmpdir): elif writer == mda.coordinates.LAMMPS.DATAWriter: pytest.skip("DATAWriter requires integer atom types") elif ( - writer == mda.coordinates.H5MD.H5MDWriter - and not mda.coordinates.H5MD.HAS_H5PY + writer == mda.coordinates.H5MD.H5MDWriter and not mda.coordinates.H5MD.HAS_H5PY ): pytest.skip("skipping H5MDWriter test because h5py is not installed") else: @@ -118,8 +114,7 @@ def test_write_with_universe(writer, tmpdir): elif writer == mda.coordinates.LAMMPS.DATAWriter: pytest.skip("DATAWriter requires integer atom types") elif ( - writer == mda.coordinates.H5MD.H5MDWriter - and not mda.coordinates.H5MD.HAS_H5PY + writer == mda.coordinates.H5MD.H5MDWriter and not mda.coordinates.H5MD.HAS_H5PY ): pytest.skip("skipping H5MDWriter test because h5py is not installed") else: diff --git a/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py b/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py index 616bae0ef64..984799bfc28 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py +++ b/testsuite/MDAnalysisTests/coordinates/test_writer_registration.py @@ -47,9 +47,7 @@ def test_default_multiframe(self): def test_singleframe(self): # check that singleframe=False has been respected - assert isinstance( - mda.Writer("this.magic", multiframe=False), self.MagicWriter - ) + assert isinstance(mda.Writer("this.magic", multiframe=False), self.MagicWriter) def test_multiframe_magic2(self): # this will work as we go for multiframe diff --git a/testsuite/MDAnalysisTests/coordinates/test_xdr.py b/testsuite/MDAnalysisTests/coordinates/test_xdr.py index c23fbf47da4..a7585469158 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_xdr.py +++ b/testsuite/MDAnalysisTests/coordinates/test_xdr.py @@ -142,9 +142,7 @@ def test_jump_xdrtrj(self, universe): def test_jump_lastframe_xdrtrj(self, universe): universe.trajectory[-1] - assert_equal( - universe.coord.frame, 9, "indexing last frame with trajectory[-1]" - ) + assert_equal(universe.coord.frame, 9, "indexing last frame with trajectory[-1]") def test_slice_xdrtrj(self, universe): frames = [ts.frame for ts in universe.trajectory[2:9:3]] @@ -155,9 +153,7 @@ def test_reverse_xdrtrj(self, universe): assert_equal(frames, list(range(9, -1, -1)), "slicing xdrtrj [::-1]") def test_coordinates(self, universe): - ca_nm = np.array( - [[6.043369675, 7.385184479, 1.381425762]], dtype=np.float32 - ) + ca_nm = np.array([[6.043369675, 7.385184479, 1.381425762]], dtype=np.float32) # coordinates in the base unit (needed for True) ca_Angstrom = ca_nm * 10.0 universe.trajectory.rewind() @@ -272,9 +268,7 @@ def test_Writer(self, tmpdir, dt): assert_equal(u.trajectory.n_frames, 2) # prec = 6: TRR test fails; here I am generous and take self.prec = # 3... - assert_almost_equal( - u.atoms.positions, universe.atoms.positions, self.prec - ) + assert_almost_equal(u.atoms.positions, universe.atoms.positions, self.prec) if dt: # test total trajectory length assert_almost_equal( @@ -282,8 +276,7 @@ def test_Writer(self, tmpdir, dt): dt, 3, err_msg=( - "wrong total length of trajectory upon setting dt " - "explicitly" + "wrong total length of trajectory upon setting dt " "explicitly" ), ) @@ -364,8 +357,7 @@ def test_velocities(self, universe): universe.atoms.velocities[[47675, 47676]], v_base, self.prec, - err_msg="velocities for indices 47675,47676 do not " - "match known values", + err_msg="velocities for indices 47675,47676 do not " "match known values", ) for index, v_known in zip([47675, 47676], v_base): @@ -388,15 +380,11 @@ def universe(self): def test_coordinates(self, universe): # note: these are the native coordinates in nm - ca_nm = np.array( - [[6.043369675, 7.385184479, 1.381425762]], dtype=np.float32 - ) + ca_nm = np.array([[6.043369675, 7.385184479, 1.381425762]], dtype=np.float32) universe.trajectory.rewind() universe.trajectory.next() universe.trajectory.next() - assert_equal( - universe.trajectory.ts.frame, 2, "failed to step to frame 3" - ) + assert_equal(universe.trajectory.ts.frame, 2, "failed to step to frame 3") ca = universe.select_atoms("name CA and resid 122") # low precision match because we also look at the trr: only 3 decimals # in nm in xtc! @@ -441,9 +429,7 @@ def outfile(self, tmpdir): def test_write_trajectory(self, universe, Writer, outfile): """Test writing Gromacs trajectories (Issue 38)""" - with Writer( - outfile, universe.atoms.n_atoms, dt=universe.trajectory.dt - ) as W: + with Writer(outfile, universe.atoms.n_atoms, dt=universe.trajectory.dt) as W: for ts in universe.trajectory: W.write(universe) @@ -457,8 +443,7 @@ def test_write_trajectory(self, universe, Writer, outfile): 3, err_msg="coordinate mismatch between " "original and written trajectory at " - "frame %d (orig) vs %d (written)" - % (orig_ts.frame, written_ts.frame), + "frame %d (orig) vs %d (written)" % (orig_ts.frame, written_ts.frame), ) def test_timestep_not_modified_by_writer(self, universe, Writer, outfile): @@ -479,9 +464,7 @@ def test_timestep_not_modified_by_writer(self, universe, Writer, outfile): x, err_msg="Positions in Timestep were modified by writer.", ) - assert_equal( - ts.time, time, err_msg="Time in Timestep was modified by writer." - ) + assert_equal(ts.time, time, err_msg="Time in Timestep was modified by writer.") class TestXTCWriter(_GromacsWriter): @@ -494,9 +477,7 @@ class TestTRRWriter(_GromacsWriter): infilename = TRR def test_velocities(self, universe, Writer, outfile): - with Writer( - outfile, universe.atoms.n_atoms, dt=universe.trajectory.dt - ) as W: + with Writer(outfile, universe.atoms.n_atoms, dt=universe.trajectory.dt) as W: for ts in universe.trajectory: W.write(universe) @@ -510,16 +491,13 @@ def test_velocities(self, universe, Writer, outfile): 3, err_msg="velocities mismatch between " "original and written trajectory at " - "frame %d (orig) vs %d (written)" - % (orig_ts.frame, written_ts.frame), + "frame %d (orig) vs %d (written)" % (orig_ts.frame, written_ts.frame), ) def test_gaps(self, universe, Writer, outfile): """Tests the writing and reading back of TRRs with gaps in any of the coordinates/velocities properties.""" - with Writer( - outfile, universe.atoms.n_atoms, dt=universe.trajectory.dt - ) as W: + with Writer(outfile, universe.atoms.n_atoms, dt=universe.trajectory.dt) as W: for ts in universe.trajectory: # Inset some gaps in the properties: coords every 4 steps, vels # every 2. @@ -591,9 +569,7 @@ def test_data_preservation(self, universe, Writer, outfile): # check that each value is the same for k in orig_ts.data: - assert_allclose( - orig_ts.data[k], written_ts.data[k], err_msg=err_msg - ) + assert_allclose(orig_ts.data[k], written_ts.data[k], err_msg=err_msg) class _GromacsWriterIssue101(object): @@ -804,9 +780,7 @@ def test_lambda(self, ref, universe, tmpdir): reader = ref.reader(outfile) for i, ts in enumerate(reader): - assert_almost_equal( - ts.data["lambda"], i / float(reader.n_frames) - ) + assert_almost_equal(ts.data["lambda"], i / float(reader.n_frames)) class _GromacsReader_offsets(object): @@ -882,9 +856,7 @@ def test_nonexistent_offsets_file(self, traj): np_load_mock.side_effect = IOError with pytest.warns( UserWarning, - match=re.escape( - f"Failed to load offsets file {outfile_offsets}" - ), + match=re.escape(f"Failed to load offsets file {outfile_offsets}"), ): saved_offsets = XDR.read_numpy_offsets(outfile_offsets) assert saved_offsets == False @@ -897,9 +869,7 @@ def test_corrupted_offsets_file(self, traj): np_load_mock.side_effect = ValueError with pytest.warns( UserWarning, - match=re.escape( - f"Failed to load offsets file {outfile_offsets}" - ), + match=re.escape(f"Failed to load offsets file {outfile_offsets}"), ): saved_offsets = XDR.read_numpy_offsets(outfile_offsets) assert saved_offsets == False diff --git a/testsuite/MDAnalysisTests/core/test_accessors.py b/testsuite/MDAnalysisTests/core/test_accessors.py index 8084fa105ae..f8076618da3 100644 --- a/testsuite/MDAnalysisTests/core/test_accessors.py +++ b/testsuite/MDAnalysisTests/core/test_accessors.py @@ -24,7 +24,6 @@ import MDAnalysis as mda from MDAnalysisTests.util import import_not_available - requires_rdkit = pytest.mark.skipif( import_not_available("rdkit"), reason="requires RDKit" ) @@ -53,18 +52,13 @@ def test_convert_to_lib_method_kwargs(self, u): class TestAccessor: def test_access_from_class(self): - assert ( - mda.core.AtomGroup.convert_to - is mda.core.accessors.ConverterWrapper - ) + assert mda.core.AtomGroup.convert_to is mda.core.accessors.ConverterWrapper class TestConverterWrapper: def test_raises_valueerror(self): u = mda.Universe.empty(1) - with pytest.raises( - ValueError, match="No 'mdanalysis' converter found" - ): + with pytest.raises(ValueError, match="No 'mdanalysis' converter found"): u.atoms.convert_to("mdanalysis") @requires_rdkit diff --git a/testsuite/MDAnalysisTests/core/test_accumulate.py b/testsuite/MDAnalysisTests/core/test_accumulate.py index 2aa1fd29099..61805a2cca0 100644 --- a/testsuite/MDAnalysisTests/core/test_accumulate.py +++ b/testsuite/MDAnalysisTests/core/test_accumulate.py @@ -41,9 +41,7 @@ def group(self, request): return getattr(u, request.param) def test_accumulate_str_attribute(self, group): - assert_almost_equal( - group.accumulate("masses"), np.sum(group.atoms.masses) - ) + assert_almost_equal(group.accumulate("masses"), np.sum(group.atoms.masses)) def test_accumulate_different_func(self, group): assert_almost_equal( @@ -114,9 +112,7 @@ def test_accumulate_array_attribute_compounds(self, name, compound, level): for a in group.atoms.groupby(name).values() ] assert_equal( - group.accumulate( - np.ones((len(group.atoms), 2, 5)), compound=compound - ), + group.accumulate(np.ones((len(group.atoms), 2, 5)), compound=compound), ref, ) @@ -252,7 +248,7 @@ def test_dipole_moment_no_center(self, group): def test_dipole_moment_residues_com_coc(self, group): compound = "residues" - (_, _, n_compounds) = group.atoms._split_by_compound_indices(compound) + _, _, n_compounds = group.atoms._split_by_compound_indices(compound) dipoles_com = group.dipole_moment(compound=compound, unwrap=False) dipoles_coc = group.dipole_moment( compound=compound, unwrap=False, center="charge" @@ -267,15 +263,13 @@ def test_dipole_moment_residues_com_coc(self, group): def test_dipole_moment_segment(self, methane): compound = "segments" - (_, _, n_compounds) = methane.atoms._split_by_compound_indices( - compound - ) + _, _, n_compounds = methane.atoms._split_by_compound_indices(compound) dipoles = methane.dipole_moment(compound=compound, unwrap=True) assert_almost_equal(dipoles, [0.0]) and len(dipoles) == n_compounds def test_dipole_moment_fragments(self, group): compound = "fragments" - (_, _, n_compounds) = group.atoms._split_by_compound_indices(compound) + _, _, n_compounds = group.atoms._split_by_compound_indices(compound) dipoles = group.dipole_moment(compound=compound, unwrap=False) assert_almost_equal( dipoles, np.array([0.0, 0.0010198, 0.1209898, 0.5681058]) @@ -304,7 +298,7 @@ def test_quadrupole_moment_no_center(self, group): def test_quadrupole_moment_residues(self, group): compound = "residues" - (_, _, n_compounds) = group.atoms._split_by_compound_indices(compound) + _, _, n_compounds = group.atoms._split_by_compound_indices(compound) quadrupoles = group.quadrupole_moment(compound=compound, unwrap=False) assert_almost_equal( @@ -313,17 +307,13 @@ def test_quadrupole_moment_residues(self, group): def test_quadrupole_moment_segment(self, methane): compound = "segments" - (_, _, n_compounds) = methane.atoms._split_by_compound_indices( - compound - ) + _, _, n_compounds = methane.atoms._split_by_compound_indices(compound) quadrupoles = methane.quadrupole_moment(compound=compound, unwrap=True) - assert_almost_equal(quadrupoles, [0.0]) and len( - quadrupoles - ) == n_compounds + assert_almost_equal(quadrupoles, [0.0]) and len(quadrupoles) == n_compounds def test_quadrupole_moment_fragments(self, group): compound = "fragments" - (_, _, n_compounds) = group.atoms._split_by_compound_indices(compound) + _, _, n_compounds = group.atoms._split_by_compound_indices(compound) quadrupoles = group.quadrupole_moment(compound=compound, unwrap=False) assert_almost_equal( diff --git a/testsuite/MDAnalysisTests/core/test_atom.py b/testsuite/MDAnalysisTests/core/test_atom.py index 1d114c5a176..83080ce4b48 100644 --- a/testsuite/MDAnalysisTests/core/test_atom.py +++ b/testsuite/MDAnalysisTests/core/test_atom.py @@ -73,9 +73,7 @@ def test_setting_attributes_charge(self, atom): assert atom.charge == 6 def test_attributes_positions(self, atom): - known_pos = np.array( - [3.94543672, -12.4060812, -7.26820087], dtype=np.float32 - ) + known_pos = np.array([3.94543672, -12.4060812, -7.26820087], dtype=np.float32) a = atom # new position property (mutable) assert_almost_equal(a.position, known_pos) diff --git a/testsuite/MDAnalysisTests/core/test_atomgroup.py b/testsuite/MDAnalysisTests/core/test_atomgroup.py index 38432e65c42..99f05d76194 100644 --- a/testsuite/MDAnalysisTests/core/test_atomgroup.py +++ b/testsuite/MDAnalysisTests/core/test_atomgroup.py @@ -87,9 +87,7 @@ def test_improper(self, u): imp = ag.improper assert isinstance(imp, ImproperDihedral) - @pytest.mark.parametrize( - "btype,", ["bond", "angle", "dihedral", "improper"] - ) + @pytest.mark.parametrize("btype,", ["bond", "angle", "dihedral", "improper"]) def test_VE(self, btype, u): ag = u.atoms[:10] with pytest.raises(ValueError): @@ -135,9 +133,7 @@ def test_write_frames(self, u, tmpdir, frames): u.atoms.write(destination, frames=frames) u_new = mda.Universe(destination, to_guess=()) - new_positions = np.stack( - [ts.positions.copy() for ts in u_new.trajectory] - ) + new_positions = np.stack([ts.positions.copy() for ts in u_new.trajectory]) assert_array_almost_equal(new_positions, ref_positions) @@ -156,9 +152,7 @@ def test_write_frame_iterator(self, u, tmpdir, frames): u.atoms.write(destination, frames=selection) u_new = mda.Universe(destination, to_guess=()) - new_positions = np.stack( - [ts.positions.copy() for ts in u_new.trajectory] - ) + new_positions = np.stack([ts.positions.copy() for ts in u_new.trajectory]) assert_array_almost_equal(new_positions, ref_positions) @@ -181,9 +175,7 @@ def test_write_frames_all(self, u, tmpdir, compression): u_new = mda.Universe(destination, to_guess=()) ref_positions = np.stack([ts.positions.copy() for ts in u.trajectory]) - new_positions = np.stack( - [ts.positions.copy() for ts in u_new.trajectory] - ) + new_positions = np.stack([ts.positions.copy() for ts in u_new.trajectory]) assert_array_almost_equal(new_positions, ref_positions) @pytest.mark.parametrize("frames", ("invalid", 8, True, False, 3.2)) @@ -280,9 +272,7 @@ def test_write_selection(self, universe, outfile, selection): def test_write_Residue(self, universe, outfile): G = ( - universe.select_atoms("segid 4AKE and resname ARG") - .residues[-2] - .atoms + universe.select_atoms("segid 4AKE and resname ARG").residues[-2].atoms ) # 2nd to last Arg G.write(outfile) u2 = self.universe_from_tmp(outfile) @@ -295,8 +285,7 @@ def test_write_Residue(self, universe, outfile): G2.positions, G.positions, self.precision, - err_msg="written Residue R206 coordinates do not " - "agree with original", + err_msg="written Residue R206 coordinates do not " "agree with original", ) def test_write_Universe(self, universe, outfile): @@ -305,16 +294,13 @@ def test_write_Universe(self, universe, outfile): W.write(U) u2 = self.universe_from_tmp(outfile) assert len(u2.atoms) == len(U.atoms), ( - "written 4AKE universe does " - "not match original universe " - "in size" + "written 4AKE universe does " "not match original universe " "in size" ) assert_almost_equal( u2.atoms.positions, U.atoms.positions, self.precision, - err_msg="written universe 4AKE coordinates do not " - "agree with original", + err_msg="written universe 4AKE coordinates do not " "agree with original", ) @@ -376,9 +362,7 @@ def test_rotate(self, u, coords): ag.positions = vec.copy() res_ag = ag.rotate(R[:3, :3]) assert_equal(ag, res_ag) - assert_almost_equal( - ag.positions[0], [np.cos(angle), np.sin(angle), 0] - ) + assert_almost_equal(ag.positions[0], [np.cos(angle), np.sin(angle), 0]) ag.positions = vec.copy() ag.rotate(R[:3, :3], vec[0]) @@ -405,9 +389,7 @@ def test_rotateby(self, u, coords): # needs to be rotated about origin res_ag = ag.rotateby(np.rad2deg(angle), axis) assert_equal(res_ag, ag) - assert_almost_equal( - ag.positions[0], [np.cos(angle), np.sin(angle), 0] - ) + assert_almost_equal(ag.positions[0], [np.cos(angle), np.sin(angle), 0]) ag.positions = vec.copy() ag.rotateby(np.rad2deg(angle), axis, point=vec[0]) @@ -432,9 +414,7 @@ def test_transform_rotation_only(self, u, coords): R = transformations.rotation_matrix(angle, axis) ag.positions = vec.copy() ag.transform(R) - assert_almost_equal( - ag.positions[0], [np.cos(angle), np.sin(angle), 0] - ) + assert_almost_equal(ag.positions[0], [np.cos(angle), np.sin(angle), 0]) def test_transform_translation_only(self, u, center_of_geometry): disp = np.ones(3) @@ -457,9 +437,7 @@ def test_transform_translation_and_rotation(self, u): ag.positions = [[1, 0, 0], [-1, 0, 0]] ag.transform(T) - assert_almost_equal( - ag.positions[0], [np.cos(angle) + 1, np.sin(angle) + 1, 1] - ) + assert_almost_equal(ag.positions[0], [np.cos(angle) + 1, np.sin(angle) + 1, 1]) class TestCenter(object): @@ -520,9 +498,7 @@ def test_center_unwrap(self, level, compound, is_triclinic): group = group.segments # get the expected results - center = group.center( - weights=None, wrap=False, compound=compound, unwrap=True - ) + center = group.center(weights=None, wrap=False, compound=compound, unwrap=True) ref_center = u.center(compound=compound) assert_almost_equal(ref_center, center, decimal=4) @@ -532,9 +508,7 @@ def test_center_unwrap_wrap_true_group(self): # select group appropriate for compound: group = u.atoms[39:47] # molecule 12 with pytest.raises(ValueError): - group.center( - weights=None, compound="group", unwrap=True, wrap=True - ) + group.center(weights=None, compound="group", unwrap=True, wrap=True) class TestSplit(object): @@ -542,9 +516,7 @@ class TestSplit(object): @pytest.fixture() def ag(self): universe = mda.Universe(PSF, DCD) - return universe.select_atoms( - "resid 1:50 and not resname LYS and " "name CA CB" - ) + return universe.select_atoms("resid 1:50 and not resname LYS and " "name CA CB") def test_split_atoms(self, ag): sg = ag.split("atom") @@ -641,8 +613,7 @@ def test_ag_matches_atom(self, att, atts, ag, att_type): assert_equal( ref, getattr(ag, atts), - err_msg="AtomGroup doesn't match Atoms for property: " - "{0}".format(att), + err_msg="AtomGroup doesn't match Atoms for property: " "{0}".format(att), ) @pytest.mark.parametrize("att, atts, att_type", attributes) @@ -1226,9 +1197,7 @@ def test_residues(self, ag, unwrap, ref, method_name): result = method(compound="residues") assert_almost_equal(result, ref[method_name], self.prec) - @pytest.mark.parametrize( - "unwrap, ref", ((True, ref_Unwrap), (False, ref_noUnwrap)) - ) + @pytest.mark.parametrize("unwrap, ref", ((True, ref_Unwrap), (False, ref_noUnwrap))) @pytest.mark.parametrize( "method_name", ( @@ -1327,9 +1296,7 @@ def ag(self): universe = mda.Universe(TRZ_psf, TRZ) return universe.residues[0:3] - @pytest.mark.parametrize( - "wrap, ref", ((True, ref_PBC), (False, ref_noPBC)) - ) + @pytest.mark.parametrize("wrap, ref", ((True, ref_PBC), (False, ref_noPBC))) @pytest.mark.parametrize( "method_name", ( @@ -1463,9 +1430,7 @@ def test_center_of_mass(self, ag): decimal=5, ) - @pytest.mark.parametrize( - "method_name", ("center_of_geometry", "center_of_mass") - ) + @pytest.mark.parametrize("method_name", ("center_of_geometry", "center_of_mass")) def test_center_duplicates(self, ag, method_name): ag2 = ag + ag[0] ref = getattr(ag, method_name)() @@ -1473,9 +1438,7 @@ def test_center_duplicates(self, ag, method_name): assert not np.allclose(getattr(ag2, method_name)(), ref) assert len(w) == 1 - @pytest.mark.parametrize( - "method_name", ("center_of_geometry", "center_of_mass") - ) + @pytest.mark.parametrize("method_name", ("center_of_geometry", "center_of_mass")) @pytest.mark.parametrize( "name, compound", (("resids", "residues"), ("segids", "segments")) ) @@ -1484,43 +1447,30 @@ def test_center_compounds(self, ag, name, compound, method_name): vals = getattr(ag, method_name)(wrap=False, compound=compound) assert_almost_equal(vals, ref, decimal=5) - @pytest.mark.parametrize( - "method_name", ("center_of_geometry", "center_of_mass") - ) + @pytest.mark.parametrize("method_name", ("center_of_geometry", "center_of_mass")) @pytest.mark.parametrize( "name, compound", (("resids", "residues"), ("segids", "segments")) ) @pytest.mark.parametrize("unwrap", (True, False)) - def test_center_compounds_pbc( - self, ag, name, compound, unwrap, method_name - ): + def test_center_compounds_pbc(self, ag, name, compound, unwrap, method_name): ag.dimensions = [50, 50, 50, 90, 90, 90] ref = [ - getattr(a, method_name)(unwrap=unwrap) - for a in ag.groupby(name).values() + getattr(a, method_name)(unwrap=unwrap) for a in ag.groupby(name).values() ] vals = getattr(ag, method_name)(compound=compound, unwrap=unwrap) assert_almost_equal(vals, ref, decimal=5) - @pytest.mark.parametrize( - "method_name", ("center_of_geometry", "center_of_mass") - ) + @pytest.mark.parametrize("method_name", ("center_of_geometry", "center_of_mass")) @pytest.mark.parametrize( "name, compound", (("molnums", "molecules"), ("fragindices", "fragments")), ) - def test_center_compounds_special( - self, ag_molfrg, name, compound, method_name - ): - ref = [ - getattr(a, method_name)() for a in ag_molfrg.groupby(name).values() - ] + def test_center_compounds_special(self, ag_molfrg, name, compound, method_name): + ref = [getattr(a, method_name)() for a in ag_molfrg.groupby(name).values()] vals = getattr(ag_molfrg, method_name)(wrap=False, compound=compound) assert_almost_equal(vals, ref, decimal=5) - @pytest.mark.parametrize( - "method_name", ("center_of_geometry", "center_of_mass") - ) + @pytest.mark.parametrize("method_name", ("center_of_geometry", "center_of_mass")) @pytest.mark.parametrize( "name, compound", (("molnums", "molecules"), ("fragindices", "fragments")), @@ -1534,9 +1484,7 @@ def test_center_compounds_special_pbc( getattr(a, method_name)(unwrap=unwrap) for a in ag_molfrg.groupby(name).values() ] - vals = getattr(ag_molfrg, method_name)( - compound=compound, unwrap=unwrap - ) + vals = getattr(ag_molfrg, method_name)(compound=compound, unwrap=unwrap) assert_almost_equal(vals, ref, decimal=5) def test_center_wrong_compound(self, ag): @@ -1548,9 +1496,7 @@ def test_center_compounds_special_fail(self, ag_no_molfrg, compound): with pytest.raises(NoDataError): ag_no_molfrg.center(weights=None, compound=compound) - @pytest.mark.parametrize( - "weights", (None, np.array([0.0]), np.array([2.0])) - ) + @pytest.mark.parametrize("weights", (None, np.array([0.0]), np.array([2.0]))) @pytest.mark.parametrize( "compound", ("group", "residues", "segments", "molecules", "fragments") ) @@ -1591,18 +1537,14 @@ def test_center_compounds_empty(self, ag_molfrg, wrap, weights, compound): ("fragindices", "fragments"), ), ) - def test_center_compounds_zero_weights( - self, ag_molfrg, wrap, name, compound - ): + def test_center_compounds_zero_weights(self, ag_molfrg, wrap, name, compound): if compound == "group": ref = np.full((3,), np.nan) else: n_compounds = len(ag_molfrg.groupby(name)) ref = np.full((n_compounds, 3), np.nan, dtype=np.float64) weights = np.zeros(len(ag_molfrg)) - assert_equal( - ref, ag_molfrg.center(weights, wrap=wrap, compound=compound) - ) + assert_equal(ref, ag_molfrg.center(weights, wrap=wrap, compound=compound)) def test_coordinates(self, ag): assert_almost_equal( @@ -1785,17 +1727,14 @@ def test_packintobox(self, universe): # Check with duplicates: ag += ag ag.pack_into_box(box=box) - assert_almost_equal( - ag.positions, np.vstack((packed_coords, packed_coords)) - ) + assert_almost_equal(ag.positions, np.vstack((packed_coords, packed_coords))) def test_residues(self, universe): u = universe assert_equal( u.residues[100].atoms.ix, u.select_atoms("resname ILE and resid 101").atoms.ix, - "Direct selection from residue group does not match " - "expected I101.", + "Direct selection from residue group does not match " "expected I101.", ) def test_index_integer(self, universe): @@ -2073,9 +2012,7 @@ def test_sort(self, ag, inputs, expected): assert np.array_equal(expected, agsort.ix) def test_sort_bonds(self, ag): - with pytest.raises( - ValueError, match=r"The array returned by the " "attribute" - ): + with pytest.raises(ValueError, match=r"The array returned by the " "attribute"): ag.sort("bonds") def test_sort_positions_2D(self, ag): diff --git a/testsuite/MDAnalysisTests/core/test_atomselections.py b/testsuite/MDAnalysisTests/core/test_atomselections.py index 214b97e1cee..33ea6b341db 100644 --- a/testsuite/MDAnalysisTests/core/test_atomselections.py +++ b/testsuite/MDAnalysisTests/core/test_atomselections.py @@ -127,9 +127,7 @@ def test_resid_single(self, universe): def test_resid_range(self, universe): sel = universe.select_atoms("resid 100:105") assert_equal(sel.n_atoms, 89) - assert_equal( - sel.residues.resnames, ["GLY", "ILE", "ASN", "VAL", "ASP", "TYR"] - ) + assert_equal(sel.residues.resnames, ["GLY", "ILE", "ASN", "VAL", "ASP", "TYR"]) def test_selgroup(self, universe): sel = universe.select_atoms("not resid 100") @@ -156,23 +154,15 @@ def test_resnum_range(self, universe): sel = universe.select_atoms("resnum 100:105") assert_equal(sel.n_atoms, 89) assert_equal(sel.residues.resids, range(100, 106)) - assert_equal( - sel.residues.resnames, ["GLY", "ILE", "ASN", "VAL", "ASP", "TYR"] - ) + assert_equal(sel.residues.resnames, ["GLY", "ILE", "ASN", "VAL", "ASP", "TYR"]) def test_resname(self, universe): sel = universe.select_atoms("resname LEU") - assert_equal( - sel.n_atoms, 304, "Failed to find all 'resname LEU' atoms." - ) - assert_equal( - sel.n_residues, 16, "Failed to find all 'resname LEU' residues." - ) + assert_equal(sel.n_atoms, 304, "Failed to find all 'resname LEU' atoms.") + assert_equal(sel.n_residues, 16, "Failed to find all 'resname LEU' residues.") assert_equal( sorted(sel.indices), - sorted( - universe.select_atoms("segid 4AKE and resname LEU").indices - ), + sorted(universe.select_atoms("segid 4AKE and resname LEU").indices), "selected 'resname LEU' atoms are not the same as auto-generated s4AKE.LEU", ) @@ -186,9 +176,7 @@ def test_atom(self, universe): assert_equal(sel.resnames, ["GLY"]) assert_equal( sel.positions, - np.array( - [[20.38685226, -3.44224262, -5.92158318]], dtype=np.float32 - ), + np.array([[20.38685226, -3.44224262, -5.92158318]], dtype=np.float32), ) def test_atom_empty(self, universe): @@ -330,10 +318,7 @@ def test_same_resname(self, universe): assert_equal( len(sel), 331, - ( - "Found a wrong number of atoms with same resname as " - "resids 10 or 11" - ), + ("Found a wrong number of atoms with same resname as " "resids 10 or 11"), ) # fmt: off target_resids = np.array( @@ -428,9 +413,7 @@ def test_no_space_around_parentheses(self, universe): def test_concatenated_selection(self, universe): E151 = universe.select_atoms("segid 4AKE").select_atoms("resid 151") # note that this is not quite phi... HN should be C of prec. residue - phi151 = E151.atoms.select_atoms( - "name HN", "name N", "name CA", "name CB" - ) + phi151 = E151.atoms.select_atoms("name HN", "name N", "name CA", "name CB") assert_equal(len(phi151), 4) assert_equal( phi151[0].name, @@ -442,9 +425,7 @@ def test_global(self, universe): """Test the `global` modifier keyword (Issue 268)""" ag = universe.select_atoms("resname LYS and name NZ") # Lys amines within 4 angstrom of the backbone. - ag1 = universe.select_atoms( - "resname LYS and name NZ and around 4 backbone" - ) + ag1 = universe.select_atoms("resname LYS and name NZ and around 4 backbone") ag2 = ag.select_atoms("around 4 global backbone") assert_equal(ag2.indices, ag1.indices) @@ -495,12 +476,8 @@ def universe(self): def test_protein(self, universe): # must include non-standard residues sel = universe.select_atoms("protein or resname HAO or resname ORT") - assert_equal( - sel.n_atoms, universe.atoms.n_atoms, "failed to select peptide" - ) - assert_equal( - sel.n_residues, 6, "failed to select all peptide residues" - ) + assert_equal(sel.n_atoms, universe.atoms.n_atoms, "failed to select peptide") + assert_equal(sel.n_residues, 6, "failed to select all peptide residues") def test_resid_single(self, universe): sel = universe.select_atoms("resid 12") @@ -590,9 +567,7 @@ def test_same_fragment(self, universe, selstr): # This test comes here because it's a system with solvent, # and thus multiple fragments. sel = universe.select_atoms(selstr) - errmsg = ( - "Found a wrong number of atoms " "on the same fragment as id 1" - ) + errmsg = "Found a wrong number of atoms " "on the same fragment as id 1" assert_equal(len(sel), 3341, errmsg) errmsg = ( "Found a differ set of atoms when using the 'same " @@ -695,9 +670,7 @@ def test_passing_rdkit_kwargs_to_converter(self): def test_passing_max_matches_to_converter(self, u2): with pytest.warns(UserWarning, match="Your smarts-based") as wsmg: sel = u2.select_atoms("smarts C", smarts_kwargs=dict(maxMatches=2)) - sel2 = u2.select_atoms( - "smarts C", smarts_kwargs=dict(maxMatches=1000) - ) + sel2 = u2.select_atoms("smarts C", smarts_kwargs=dict(maxMatches=1000)) assert sel.n_atoms == 2 assert sel2.n_atoms == 3 @@ -908,9 +881,7 @@ class TestOrthogonalDistanceSelections(BaseDistanceSelection): def u(self): return mda.Universe(TRZ_psf, TRZ) - @pytest.mark.parametrize( - "meth, periodic", [("distmat", True), ("distmat", False)] - ) + @pytest.mark.parametrize("meth, periodic", [("distmat", True), ("distmat", False)]) def test_cyzone(self, u, meth, periodic): sel = Parser.parse("cyzone 5 4 -4 resid 2", u.atoms) sel.periodic = periodic @@ -1178,9 +1149,7 @@ def test_flip(self, prop, ag, op): # reference group, doing things forwards ref = ag[func(getattr(ag, self.plurals[prop]), 1.5)] - selstr = "prop 1.5 {op} {prop}".format( - op=self.opposites[op], prop=prop - ) + selstr = "prop 1.5 {op} {prop}".format(op=self.opposites[op], prop=prop) sel = ag.select_atoms(selstr) assert_equal(set(ref.indices), set(sel.indices)) @@ -1211,9 +1180,7 @@ class TestSelectionErrors(object): @staticmethod @pytest.fixture() def universe(): - return make_Universe( - ("names", "masses", "resids", "resnames", "resnums") - ) + return make_Universe(("names", "masses", "resids", "resnames", "resnums")) @pytest.mark.parametrize( "selstr", @@ -1316,9 +1283,7 @@ def test_string_selections(self, ref, sel, universe): ], ) def test_range_selections(self, seltype, ref, sel, universe): - self._check_sels( - ref.format(typ=seltype), sel.format(typ=seltype), universe - ) + self._check_sels(ref.format(typ=seltype), sel.format(typ=seltype), universe) class TestICodeSelection(object): @@ -1662,9 +1627,7 @@ def test_bool_sel_error(): def test_error_selection_for_strange_dtype(): with pytest.raises(ValueError, match="No base class defined for dtype"): - MDAnalysis.core.selection.gen_selection_class( - "star", "stars", dict, "atom" - ) + MDAnalysis.core.selection.gen_selection_class("star", "stars", dict, "atom") @pytest.mark.parametrize( @@ -1731,9 +1694,7 @@ def test_chirality(smi, chirality): assert u.atoms[0].chirality == "" assert u.atoms[1].chirality == chirality - assert_equal( - u.atoms[:3].chiralities, np.array(["", chirality, ""], dtype="U1") - ) + assert_equal(u.atoms[:3].chiralities, np.array(["", chirality, ""], dtype="U1")) @pytest.mark.parametrize( diff --git a/testsuite/MDAnalysisTests/core/test_group_traj_access.py b/testsuite/MDAnalysisTests/core/test_group_traj_access.py index f7061177f4d..0939f52b567 100644 --- a/testsuite/MDAnalysisTests/core/test_group_traj_access.py +++ b/testsuite/MDAnalysisTests/core/test_group_traj_access.py @@ -125,9 +125,7 @@ def test_atomgroup_velocities_access(self, u, vel): else: with pytest.raises(NoDataError): getattr(ag, "velocities") - assert_correct_errormessage( - (getattr, ag, "velocities"), "velocities" - ) + assert_correct_errormessage((getattr, ag, "velocities"), "velocities") def test_atomgroup_forces_access(self, u, force): ag = u.atoms[10:20] @@ -167,9 +165,7 @@ def test_atom_velocity_access(self, u, vel): else: with pytest.raises(NoDataError): getattr(at, "velocity") - assert_correct_errormessage( - (getattr, at, "velocity"), "velocities" - ) + assert_correct_errormessage((getattr, at, "velocity"), "velocities") def test_atom_force_access(self, u, force): at = u.atoms[55] @@ -189,25 +185,18 @@ def test_atom_force_access(self, u, force): def test_atomgroup_positions_setting(self, u): ag = u.atoms[[101, 107, 109]] - new = np.array( - [[72.4, 64.5, 74.7], [124.6, 15.6, -1.11], [25.2, -66.6, 0]] - ) + new = np.array([[72.4, 64.5, 74.7], [124.6, 15.6, -1.11], [25.2, -66.6, 0]]) ag.positions = new assert_almost_equal(ag.positions, new, decimal=5) - assert_almost_equal( - u.trajectory.ts.positions[[101, 107, 109]], new, decimal=5 - ) + assert_almost_equal(u.trajectory.ts.positions[[101, 107, 109]], new, decimal=5) def test_atomgroup_velocities_setting(self, u, vel): ag = u.atoms[[101, 107, 109]] new = ( - np.array( - [[72.4, 64.5, 74.7], [124.6, 15.6, -1.11], [25.2, -66.6, 0]] - ) - + 0.1 + np.array([[72.4, 64.5, 74.7], [124.6, 15.6, -1.11], [25.2, -66.6, 0]]) + 0.1 ) if vel: @@ -220,27 +209,20 @@ def test_atomgroup_velocities_setting(self, u, vel): else: with pytest.raises(NoDataError): setattr(ag, "velocities", new) - assert_correct_errormessage( - (setattr, ag, "velocities", new), "velocities" - ) + assert_correct_errormessage((setattr, ag, "velocities", new), "velocities") def test_atomgroup_forces_setting(self, u, force): ag = u.atoms[[101, 107, 109]] new = ( - np.array( - [[72.4, 64.5, 74.7], [124.6, 15.6, -1.11], [25.2, -66.6, 0]] - ) - + 0.2 + np.array([[72.4, 64.5, 74.7], [124.6, 15.6, -1.11], [25.2, -66.6, 0]]) + 0.2 ) if force: ag.forces = new assert_almost_equal(ag.forces, new, decimal=5) - assert_almost_equal( - u.trajectory.ts.forces[[101, 107, 109]], new, decimal=5 - ) + assert_almost_equal(u.trajectory.ts.forces[[101, 107, 109]], new, decimal=5) else: with pytest.raises(NoDataError): setattr(ag, "forces", new) @@ -269,9 +251,7 @@ def test_atom_velocity_setting(self, u, vel): else: with pytest.raises(NoDataError): setattr(at, "velocity", new) - assert_correct_errormessage( - (setattr, at, "velocity", new), "velocities" - ) + assert_correct_errormessage((setattr, at, "velocity", new), "velocities") def test_atom_force_setting(self, u, force): at = u.atoms[94] @@ -479,9 +459,7 @@ def test_velocities(self, universe): ] ) v = ag.velocities - assert_almost_equal( - v, ref_v, err_msg="velocities were not read correctly" - ) + assert_almost_equal(v, ref_v, err_msg="velocities were not read correctly") def test_set_velocities(self, ag): ag = ag @@ -516,6 +494,4 @@ def test_forces(self, universe): def test_set_forces(self, ag): v = ag.forces - 2.7271 ag.forces = v - assert_almost_equal( - ag.forces, v, err_msg="messages were not set to new value" - ) + assert_almost_equal(ag.forces, v, err_msg="messages were not set to new value") diff --git a/testsuite/MDAnalysisTests/core/test_groups.py b/testsuite/MDAnalysisTests/core/test_groups.py index 7cd890b046f..ef8c8c85e8e 100644 --- a/testsuite/MDAnalysisTests/core/test_groups.py +++ b/testsuite/MDAnalysisTests/core/test_groups.py @@ -142,9 +142,7 @@ def test_create_unique_group_from_unique(self, group): # check if caches of group.sorted_unique have been set correctly: assert group.sorted_unique._cache["isunique"] is True - assert ( - group.sorted_unique._cache["sorted_unique"] is group.sorted_unique - ) + assert group.sorted_unique._cache["sorted_unique"] is group.sorted_unique # assert that repeated access yields the same object (not a copy): unique_group = group.sorted_unique assert unique_group is group.sorted_unique @@ -509,9 +507,7 @@ def test_sum(self, a, b, c, refclass): assert_equal( len(summed), len(self.itr(a)) + len(self.itr(b)) + len(self.itr(c)) ) - for x, y in zip( - summed, itertools.chain(self.itr(a), self.itr(b), self.itr(c)) - ): + for x, y in zip(summed, itertools.chain(self.itr(a), self.itr(b), self.itr(c))): assert x == y @pytest.mark.parametrize( @@ -531,11 +527,7 @@ def test_contains_false(self, group): @pytest.mark.parametrize( "one_level, other_level", - [ - (l1, l2) - for l1, l2 in itertools.product(levels, repeat=2) - if l1 != l2 - ], + [(l1, l2) for l1, l2 in itertools.product(levels, repeat=2) if l1 != l2], ) def test_contains_wronglevel(self, one_level, other_level): group = self.group_dict[one_level] @@ -993,8 +985,7 @@ def u(self): def test_atom_repr(self, u): at = u.atoms[0] assert ( - repr(at) - == "" + repr(at) == "" ) def test_residue_repr(self, u): @@ -1018,9 +1009,7 @@ def test_atomgroup_str_short(self, u): def test_atomgroup_str_long(self, u): ag = u.atoms[:11] - assert str(ag).startswith( - "]>") @@ -1122,9 +1111,7 @@ def test_len(self, groups_simple): assert_equal(len(d), 0) assert_equal(len(e), 3) - def test_len_duplicated_and_scrambled( - self, groups_duplicated_and_scrambled - ): + def test_len_duplicated_and_scrambled(self, groups_duplicated_and_scrambled): a, b, c, d, e = groups_duplicated_and_scrambled assert_equal(len(a), 7) assert_equal(len(b), 8) @@ -1137,13 +1124,9 @@ def test_equal(self, groups): assert a == a assert a != b assert not a == b - assert ( - not a[0:1] == a[0] - ), "Element should not equal single element group." + assert not a[0:1] == a[0], "Element should not equal single element group." - @pytest.mark.parametrize( - "group", (u.atoms[:2], u.residues[:2], u.segments[:2]) - ) + @pytest.mark.parametrize("group", (u.atoms[:2], u.residues[:2], u.segments[:2])) def test_copy(self, group): # make sure uniqueness caches of group are empty: with pytest.raises(KeyError): @@ -1399,9 +1382,7 @@ def test_hash_difference(self, u, level): b = getattr(u, level)[1:] assert hash(a) != hash(b) - @pytest.mark.parametrize( - "level_a, level_b", itertools.permutations(levels, 2) - ) + @pytest.mark.parametrize("level_a, level_b", itertools.permutations(levels, 2)) def test_hash_difference_cross(self, u, level_a, level_b): a = getattr(u, level_a)[0:-1] b = getattr(u, level_b)[0:-1] @@ -1579,9 +1560,7 @@ def test_unwrap_without_bonds(self, universe): def test_get_absent_attr_method(self, universe): with pytest.raises(NoDataError) as exc: universe.atoms.total_charge() - err = ( - "AtomGroup.total_charge() not available; " "this requires charges" - ) + err = "AtomGroup.total_charge() not available; " "this requires charges" assert str(exc.value) == err def test_get_absent_attrprop(self, universe): @@ -1606,9 +1585,7 @@ def test_attrmethod_wrong_group(self, universe): def test_wrong_name(self, universe, attr): with pytest.raises(AttributeError) as exc: getattr(universe.atoms, attr) - err = ( - "AtomGroup has no attribute {}. " "Did you mean altLocs?" - ).format(attr) + err = ("AtomGroup has no attribute {}. " "Did you mean altLocs?").format(attr) assert str(exc.value) == err @@ -1685,9 +1662,7 @@ def test_wrap_and_unwrap_deprecation(self, compound, pbc, unwrap): # deprecation. We need to tell the linter. assert ( # pylint: disable-next=unexpected-keyword-arg - self.dummy_funtion( - compound=compound, pbc=pbc, unwrap=unwrap - ) + self.dummy_funtion(compound=compound, pbc=pbc, unwrap=unwrap) == 0 ) @@ -1702,10 +1677,7 @@ def test_wrap_and_unwrap(self, compound, wrap, unwrap): with pytest.raises(ValueError): self.dummy_funtion(compound=compound, wrap=wrap, unwrap=unwrap) else: - assert ( - self.dummy_funtion(compound=compound, wrap=wrap, unwrap=unwrap) - == 0 - ) + assert self.dummy_funtion(compound=compound, wrap=wrap, unwrap=unwrap) == 0 @pytest.fixture() @@ -1718,9 +1690,7 @@ def tpr(): class TestGetConnectionsAtoms(object): """Test Atom and AtomGroup.get_connections""" - @pytest.mark.parametrize( - "typename", ["bonds", "angles", "dihedrals", "impropers"] - ) + @pytest.mark.parametrize("typename", ["bonds", "angles", "dihedrals", "impropers"]) def test_connection_from_atom_not_outside(self, tpr, typename): cxns = tpr.atoms[1].get_connections(typename, outside=False) assert len(cxns) == 0 @@ -1818,9 +1788,7 @@ def test_connection_from_res_outside(self, tpr, typename, n_atoms): ("dihedrals", 351), ], ) - def test_connection_from_residues_not_outside( - self, tpr, typename, n_atoms - ): + def test_connection_from_residues_not_outside(self, tpr, typename, n_atoms): ag = tpr.residues[:10] cxns = ag.get_connections(typename, outside=False) assert len(cxns) == n_atoms diff --git a/testsuite/MDAnalysisTests/core/test_index_dtype.py b/testsuite/MDAnalysisTests/core/test_index_dtype.py index 1500430f69f..bd3d0ac0a3c 100644 --- a/testsuite/MDAnalysisTests/core/test_index_dtype.py +++ b/testsuite/MDAnalysisTests/core/test_index_dtype.py @@ -27,6 +27,7 @@ This dtype is important for platform independent indexing of other arrays. """ + import numpy as np import pytest from MDAnalysisTests import make_Universe diff --git a/testsuite/MDAnalysisTests/core/test_requires.py b/testsuite/MDAnalysisTests/core/test_requires.py index 1dea033b7eb..bf8d643526f 100644 --- a/testsuite/MDAnalysisTests/core/test_requires.py +++ b/testsuite/MDAnalysisTests/core/test_requires.py @@ -1,6 +1,4 @@ -"""Tests for core.groups.requires decorator - -""" +"""Tests for core.groups.requires decorator""" import numpy as np diff --git a/testsuite/MDAnalysisTests/core/test_residuegroup.py b/testsuite/MDAnalysisTests/core/test_residuegroup.py index 06d0e22e9a0..4a2efc9469c 100644 --- a/testsuite/MDAnalysisTests/core/test_residuegroup.py +++ b/testsuite/MDAnalysisTests/core/test_residuegroup.py @@ -56,9 +56,7 @@ def u(self): def test_string(self, u): p = u.select_atoms("protein") - assert_equal( - p.residues.sequence(format="string"), self.ref_adk_sequence - ) + assert_equal(p.residues.sequence(format="string"), self.ref_adk_sequence) def test_SeqRecord(self, u): p = u.select_atoms("protein") @@ -190,8 +188,7 @@ def test_set_resids_updates_self(self, universe): assert_equal( rg.resids, resids, - err_msg="old selection was not changed in place " - "after set_resid", + err_msg="old selection was not changed in place " "after set_resid", ) def test_set_resnum_single(self, universe): @@ -297,9 +294,7 @@ def test_set_masses(self, universe): assert_equal( [a.mass for a in rg.atoms], mass * np.ones(rg.n_atoms), - err_msg="failed to set_mass H* atoms in resid 12:42 to {0}".format( - mass - ), + err_msg="failed to set_mass H* atoms in resid 12:42 to {0}".format(mass), ) # VALID diff --git a/testsuite/MDAnalysisTests/core/test_topology.py b/testsuite/MDAnalysisTests/core/test_topology.py index d1154f5c4e0..b34666f7745 100644 --- a/testsuite/MDAnalysisTests/core/test_topology.py +++ b/testsuite/MDAnalysisTests/core/test_topology.py @@ -722,9 +722,7 @@ def names(self): @pytest.fixture() def types(self): - return ta.Atomtypes( - np.array(["X", "Y", "Z"], dtype=object), guessed=True - ) + return ta.Atomtypes(np.array(["X", "Y", "Z"], dtype=object), guessed=True) @pytest.fixture() def resids(self): diff --git a/testsuite/MDAnalysisTests/core/test_topologyattrs.py b/testsuite/MDAnalysisTests/core/test_topologyattrs.py index 5155933c2e4..8467c2b0cd7 100644 --- a/testsuite/MDAnalysisTests/core/test_topologyattrs.py +++ b/testsuite/MDAnalysisTests/core/test_topologyattrs.py @@ -20,9 +20,8 @@ # MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -"""Tests for MDAnalysis.core.topologyattrs objects. +"""Tests for MDAnalysis.core.topologyattrs objects.""" -""" import numpy as np from numpy.testing import ( @@ -233,9 +232,7 @@ class AggregationMixin(TestAtomAttr): def test_get_residues(self, attr): assert_equal( attr.get_residues(DummyGroup([2, 1])), - np.array( - [self.values[[2, 3, 9]].sum(), self.values[[4, 5, 8]].sum()] - ), + np.array([self.values[[2, 3, 9]].sum(), self.values[[4, 5, 8]].sum()]), ) def test_get_segments(self, attr): @@ -281,9 +278,7 @@ def test_set_residue_VE(self, universe): setattr(res, self.attrclass.singular, self.values[:2]) def test_get_atoms(self, attr): - assert_equal( - attr.get_atoms(DummyGroup([7, 3, 9])), self.values[[3, 2, 2]] - ) + assert_equal(attr.get_atoms(DummyGroup([7, 3, 9])), self.values[[3, 2, 2]]) def test_get_atom(self, universe): attr = getattr(universe.atoms[0], self.attrclass.singular) @@ -375,9 +370,7 @@ def test_set_segment_VE(self): setattr(seg, "segid", [1, 2, 3]) def test_get_atoms(self, attr): - assert_equal( - attr.get_atoms(DummyGroup([2, 4, 1])), self.values[[1, 1, 0]] - ) + assert_equal(attr.get_atoms(DummyGroup([2, 4, 1])), self.values[[1, 1, 0]]) def test_get_residues(self, attr): assert_equal( @@ -390,9 +383,7 @@ def test_get_segments(self, attr): atoms in segments. """ - assert_equal( - attr.get_segments(DummyGroup([1, 0, 0])), self.values[[1, 0, 0]] - ) + assert_equal(attr.get_segments(DummyGroup([1, 0, 0])), self.values[[1, 0, 0]]) def test_set_segments_singular(self, attr): dg = DummyGroup([0, 1]) @@ -434,9 +425,7 @@ def universe_pa(self): def test_principal_axes_handedness(self, universe_pa): e_vec = universe_pa.atoms.principal_axes() - assert_almost_equal( - np.dot(np.cross(e_vec[0], e_vec[1]), e_vec[2]), 1.0 - ) + assert_almost_equal(np.dot(np.cross(e_vec[0], e_vec[1]), e_vec[2]), 1.0) def test_align_principal_axes_with_self(self, ag): pa = ag.principal_axes() diff --git a/testsuite/MDAnalysisTests/core/test_topologyobjects.py b/testsuite/MDAnalysisTests/core/test_topologyobjects.py index 196b91364df..7c54eeb16e2 100644 --- a/testsuite/MDAnalysisTests/core/test_topologyobjects.py +++ b/testsuite/MDAnalysisTests/core/test_topologyobjects.py @@ -221,9 +221,7 @@ def test_ureybradley_partner(self, PSFDCD): assert ub.partner(PSFDCD.atoms[10]) == PSFDCD.atoms[30] def test_ureybradley_distance(self, b): - assert_almost_equal( - b.atoms.ureybradley.distance(), b.length(), self.precision - ) + assert_almost_equal(b.atoms.ureybradley.distance(), b.length(), self.precision) def test_cmap_repr(self, PSFDCD): cmap = PSFDCD.atoms[[4, 7, 8, 1, 2]].cmap @@ -299,9 +297,7 @@ def test_bond_uniqueness(self, PSFDCD): bondtypes = PSFDCD.atoms.bonds.types() # check that a key doesn't appear in reversed format in keylist # have to exclude case of b[::-1] == b as this is false positive - assert not any( - [b[::-1] in bondtypes for b in bondtypes if b[::-1] != b] - ) + assert not any([b[::-1] in bondtypes for b in bondtypes if b[::-1] != b]) def test_bond_reversal(self, PSFDCD, b_td): bondtypes = PSFDCD.atoms.bonds.types() @@ -439,9 +435,7 @@ def test_create_TopologyGroup(self, res1, PSFDCD): res1_tg2 = res1.atoms.bonds.select_bonds(("23", "3")) assert res1_tg == res1_tg2 - @pytest.mark.parametrize( - "attr", ["bonds", "angles", "dihedrals", "impropers"] - ) + @pytest.mark.parametrize("attr", ["bonds", "angles", "dihedrals", "impropers"]) def test_TG_loose_intersection(self, PSFDCD, attr): """Pull bonds from a TG which are at least partially in an AG""" ag = PSFDCD.atoms[10:60] @@ -486,9 +480,7 @@ def manual(topg, atomg): # dihedrals assert check_strict_intersection(PSFDCD.atoms.dihedrals, testinput) assert manual(PSFDCD.atoms.dihedrals, testinput) == set( - PSFDCD.atoms.dihedrals.atomgroup_intersection( - testinput, strict=True - ) + PSFDCD.atoms.dihedrals.atomgroup_intersection(testinput, strict=True) ) def test_add_TopologyGroups(self, res1, res2, PSFDCD): diff --git a/testsuite/MDAnalysisTests/core/test_universe.py b/testsuite/MDAnalysisTests/core/test_universe.py index 15ff1aeb862..5d997373f85 100644 --- a/testsuite/MDAnalysisTests/core/test_universe.py +++ b/testsuite/MDAnalysisTests/core/test_universe.py @@ -100,9 +100,7 @@ def test_load(self): def test_load_topology_stringio(self): u = mda.Universe(StringIO(CHOL_GRO), format="GRO") - assert_equal( - len(u.atoms), 8, "Loading universe from StringIO failed somehow" - ) + assert_equal(len(u.atoms), 8, "Loading universe from StringIO failed somehow") assert_equal( u.trajectory.ts.positions[0], np.array([65.580002, 29.360001, 40.050003], dtype=np.float32), @@ -115,9 +113,7 @@ def test_load_trajectory_stringio(self): format="GRO", topology_format="GRO", ) - assert_equal( - len(u.atoms), 8, "Loading universe from StringIO failed somehow" - ) + assert_equal(len(u.atoms), 8, "Loading universe from StringIO failed somehow") def test_make_universe_stringio_no_format(self): # Loading from StringIO without format arg should raise TypeError @@ -177,9 +173,7 @@ def test_Universe_invalidfile_IE_msg(self, tmpdir): else: raise AssertionError - @pytest.mark.skipif( - get_userid() == 0, reason="cannot permisssionerror as root" - ) + @pytest.mark.skipif(get_userid() == 0, reason="cannot permisssionerror as root") def test_Universe_invalidpermissionfile_IE_msg(self, tmpdir): # check for file with invalid permissions (eg. no read access) with tmpdir.as_cwd(): @@ -189,9 +183,7 @@ def test_Universe_invalidpermissionfile_IE_msg(self, tmpdir): if os.name == "nt": subprocess.call( - "icacls {filename} /deny Users:RX".format( - filename=temp_file - ), + "icacls {filename} /deny Users:RX".format(filename=temp_file), shell=True, ) else: @@ -212,9 +204,7 @@ def test_load_new_memory_reader_success(self): prot = u.select_atoms("protein") u2 = mda.Merge(prot) assert ( - u2.load_new( - [prot.positions], format=mda.coordinates.memory.MemoryReader - ) + u2.load_new([prot.positions], format=mda.coordinates.memory.MemoryReader) is u2 ) @@ -223,9 +213,7 @@ def load(): u = mda.Universe(GRO) prot = u.select_atoms("protein") u2 = mda.Merge(prot) - u2.load_new( - [[prot.positions]], format=mda.coordinates.memory.MemoryReader - ) + u2.load_new([[prot.positions]], format=mda.coordinates.memory.MemoryReader) with pytest.raises(TypeError): load() @@ -262,9 +250,7 @@ def test_Universe_top_format_no_coords(self): topology_format=MDAnalysis.topology.PDBParser.PDBParser, format=None, ) - assert not isinstance( - u.trajectory, MDAnalysis.topology.PDBParser.PDBParser - ) + assert not isinstance(u.trajectory, MDAnalysis.topology.PDBParser.PDBParser) def test_Universe_traj_format_no_coords(self): # Issue #5147- ensure top format is not set to traj format @@ -333,9 +319,7 @@ def test_rdkit_kwargs(self): u1 = mda.Universe.from_smiles("C", rdkit_kwargs=dict(randomSeed=42)) u2 = mda.Universe.from_smiles("C", rdkit_kwargs=dict(randomSeed=51)) with pytest.raises(AssertionError) as e: - assert_equal( - u1.trajectory.coordinate_array, u2.trajectory.coordinate_array - ) + assert_equal(u1.trajectory.coordinate_array, u2.trajectory.coordinate_array) assert "Mismatched elements: 15 / 15 (100%)" in str(e.value) def test_coordinates(self): @@ -352,9 +336,7 @@ def test_coordinates(self): expected = [c.GetPositions() for c in mol.GetConformers()] # now the mda way - u = mda.Universe.from_smiles( - "C", numConfs=2, rdkit_kwargs=dict(randomSeed=42) - ) + u = mda.Universe.from_smiles("C", numConfs=2, rdkit_kwargs=dict(randomSeed=42)) assert u.trajectory.n_frames == 2 assert_allclose(u.trajectory.coordinate_array, expected, rtol=1e-7) @@ -667,9 +649,7 @@ def test_frame_interval_convention(self): array1 = universe1.trajectory.timeseries(step=10) universe2 = mda.Universe(PSF, DCD, in_memory=True, in_memory_step=10) array2 = universe2.trajectory.timeseries() - assert_equal( - array1, array2, err_msg="Unexpected differences between arrays." - ) + assert_equal(array1, array2, err_msg="Unexpected differences between arrays.") def test_slicing_with_start_stop(self): universe = MDAnalysis.Universe(PDB_small, DCD) @@ -774,17 +754,13 @@ class TestCustomReaders(object): def test_custom_reader(self): # check that reader passing works - u = mda.Universe( - TRZ_psf, TRZ, format=MDAnalysis.coordinates.TRZ.TRZReader - ) + u = mda.Universe(TRZ_psf, TRZ, format=MDAnalysis.coordinates.TRZ.TRZReader) assert_equal(len(u.atoms), 8184) def test_custom_reader_singleframe(self): T = MDAnalysis.topology.GROParser.GROParser R = MDAnalysis.coordinates.GRO.GROReader - u = mda.Universe( - two_water_gro, two_water_gro, topology_format=T, format=R - ) + u = mda.Universe(two_water_gro, two_water_gro, topology_format=T, format=R) assert_equal(len(u.atoms), 6) def test_custom_reader_singleframe_2(self): @@ -911,9 +887,7 @@ def test_add_connection_error(self, universe, attr, values): def test_add_attr_length_error(self, universe): with pytest.raises(ValueError): - universe.add_TopologyAttr( - "masses", np.array([1, 2, 3], dtype=np.float64) - ) + universe.add_TopologyAttr("masses", np.array([1, 2, 3], dtype=np.float64)) class TestDelTopologyAttr(object): @@ -1080,20 +1054,14 @@ def test_add_atomgroup_to_populated(self, universe, attr, values): self._check_valid_added_to_populated(universe, attr, values, ag) @pytest.mark.parametrize("attr,values", small_atom_indices) - def test_add_atomgroup_wrong_universe_error( - self, universe, empty, attr, values - ): + def test_add_atomgroup_wrong_universe_error(self, universe, empty, attr, values): ag = [empty.atoms[x] for x in values] self._check_invalid_addition(universe, attr, ag, "different Universes") @pytest.mark.parametrize("attr,values", large_atom_indices) def test_add_topologyobjects_to_populated(self, universe, attr, values): - topologyobjects = [ - getattr(universe.atoms[x], attr[:-1]) for x in values - ] - self._check_valid_added_to_populated( - universe, attr, values, topologyobjects - ) + topologyobjects = [getattr(universe.atoms[x], attr[:-1]) for x in values] + self._check_valid_added_to_populated(universe, attr, values, topologyobjects) @pytest.mark.parametrize("attr,values", small_atom_indices) def test_add_topologyobjects_wrong_universe_error( @@ -1107,9 +1075,7 @@ def test_add_topologygroups_to_populated(self, universe, attr, values): topologygroup = mda.core.topologyobjects.TopologyGroup( np.array(values), universe ) - self._check_valid_added_to_populated( - universe, attr, values, topologygroup - ) + self._check_valid_added_to_populated(universe, attr, values, topologygroup) @pytest.mark.parametrize("attr,values", small_atom_indices) def test_add_topologygroup_wrong_universe_error( @@ -1119,9 +1085,7 @@ def test_add_topologygroup_wrong_universe_error( self._check_invalid_addition(empty, attr, tg, "different Universes") @pytest.mark.parametrize("attr,values", small_atom_indices) - def test_add_topologygroup_different_universe( - self, universe, empty, attr, values - ): + def test_add_topologygroup_different_universe(self, universe, empty, attr, values): tg = mda.core.topologyobjects.TopologyGroup(np.array(values), universe) self._check_valid_added_to_empty(empty, attr, values, tg.to_indices()) @@ -1137,9 +1101,7 @@ def test_add_topologygroup_different_universe( def test_add_wrong_topologygroup_error(self, universe, attr, values): arr = np.array(values) tg = mda.core.topologyobjects.TopologyGroup(arr, universe) - self._check_invalid_addition( - universe, attr, tg, "iterable of tuples with" - ) + self._check_invalid_addition(universe, attr, tg, "iterable of tuples with") @pytest.mark.parametrize( "attr,values", @@ -1154,9 +1116,7 @@ def test_add_wrong_topologygroup_error(self, universe, attr, values): ), ) def test_add_nonexistent_indices_error(self, universe, attr, values): - self._check_invalid_addition( - universe, attr, values, "nonexistent atom indices" - ) + self._check_invalid_addition(universe, attr, values, "nonexistent atom indices") @pytest.mark.parametrize( "attr,n", @@ -1168,9 +1128,9 @@ def test_add_nonexistent_indices_error(self, universe, attr, values): ), ) def test_add_wrong_number_of_atoms_error(self, universe, attr, n): - errmsg = ( - "{} must be an iterable of " "tuples with {} atom indices" - ).format(attr, n) + errmsg = ("{} must be an iterable of " "tuples with {} atom indices").format( + attr, n + ) idx = [(0, 1), (0, 1, 2), (8, 22, 1, 3), (5, 3, 4, 2)] self._check_invalid_addition(universe, attr, idx, errmsg) @@ -1256,10 +1216,7 @@ def _check_valid_deleted(self, u, attr, values, to_delete): not_deleted = [x for x in self.TOP[attr] if list(x) not in values] assert all( - [ - x in u_attr.indices or x[::-1] in u_attr.indices - for x in not_deleted - ] + [x in u_attr.indices or x[::-1] in u_attr.indices for x in not_deleted] ) def _check_invalid_deleted(self, u, attr, to_delete, err_msg): @@ -1277,9 +1234,7 @@ def test_delete_valid_indices(self, universe, attr, values): @pytest.mark.parametrize("attr,values", nonexisting_atom_indices) def test_delete_missing_indices(self, universe, attr, values): - self._check_invalid_deleted( - universe, attr, values, "Cannot delete nonexistent" - ) + self._check_invalid_deleted(universe, attr, values, "Cannot delete nonexistent") @pytest.mark.parametrize("attr,values", existing_atom_indices) def test_delete_valid_atomgroup(self, universe, attr, values): @@ -1296,9 +1251,7 @@ def test_delete_atomgroup_wrong_universe_error( @pytest.mark.parametrize("attr,values", nonexisting_atom_indices) def test_delete_missing_atomgroup(self, universe, attr, values): ag = [universe.atoms[x] for x in values] - self._check_invalid_deleted( - universe, attr, ag, "Cannot delete nonexistent" - ) + self._check_invalid_deleted(universe, attr, ag, "Cannot delete nonexistent") @pytest.mark.parametrize("attr,values", existing_atom_indices) def test_delete_mixed_type(self, universe, attr, values): @@ -1316,9 +1269,7 @@ def test_delete_topologyobjects_wrong_universe( ): u1 = [getattr(universe.atoms[x], attr[:-1]) for x in values[:-1]] u2 = [getattr(universe2.atoms[values[-1]], attr[:-1])] - self._check_invalid_deleted( - universe, attr, u1 + u2, "different Universes" - ) + self._check_invalid_deleted(universe, attr, u1 + u2, "different Universes") @pytest.mark.parametrize("attr,values", existing_atom_indices) def test_delete_valid_topologygroup(self, universe, attr, values): @@ -1353,9 +1304,9 @@ def test_delete_topologygroup_different_universe( ) def test_delete_wrong_number_of_atoms_error(self, universe, attr, n): idx = [(0, 1), (0, 1, 2), (8, 22, 1, 3), (5, 3, 4, 2)] - errmsg = ( - "{} must be an iterable of " "tuples with {} atom indices" - ).format(attr, n) + errmsg = ("{} must be an iterable of " "tuples with {} atom indices").format( + attr, n + ) self._check_invalid_deleted(universe, attr, idx, errmsg) @pytest.mark.parametrize("attr,values", existing_atom_indices) @@ -1372,9 +1323,7 @@ def test_delete_bonds_refresh_fragments(self, universe): universe.delete_bonds([universe.atoms[[2, 3]]]) assert len(universe.atoms.fragments) == n_fragments + 1 - @pytest.mark.parametrize( - "filename, n_bonds", [(CONECT, 72), (PDB_conect, 8)] - ) + @pytest.mark.parametrize("filename, n_bonds", [(CONECT, 72), (PDB_conect, 8)]) def test_delete_all_bonds(self, filename, n_bonds): u = mda.Universe(filename) assert len(u.bonds) == n_bonds @@ -1415,16 +1364,12 @@ def u_GRO(self): def test_all_coordinates_length(self, u_GRO_TRR, u_GRO_TRR_allcoords): # length with all_coords should be +1 - assert len(u_GRO_TRR.trajectory) + 1 == len( - u_GRO_TRR_allcoords.trajectory - ) + assert len(u_GRO_TRR.trajectory) + 1 == len(u_GRO_TRR_allcoords.trajectory) def test_all_coordinates_frame(self, u_GRO_TRR_allcoords, u_GRO): # check that first frame in u(GRO, TRR, allcords) # are the coordinates from GRO - assert_array_equal( - u_GRO_TRR_allcoords.atoms.positions, u_GRO.atoms.positions - ) + assert_array_equal(u_GRO_TRR_allcoords.atoms.positions, u_GRO.atoms.positions) def test_second_frame(self, u_GRO_TRR_allcoords, u_GRO_TRR): # check that second frame in u(GRO, TRR, allcoords) @@ -1636,20 +1581,14 @@ def test_set_segments(self, bad_seg, good): assert_equal(["A", "", "A", "B", ""], bad_seg.segments.segids) assert len(bad_seg.residues) == 5 # 5 residues assert_equal([315, 315, 316, 314, 315], bad_seg.residues.resids) - assert_equal( - ["THR", "THR", "THR", "THR", "THR"], bad_seg.residues.resnames - ) + assert_equal(["THR", "THR", "THR", "THR", "THR"], bad_seg.residues.resnames) assert_equal(["A", "", "A", "B", ""], bad_seg.residues.segids) assert len(bad_seg.atoms) == 7 # 7 atoms assert_equal([315, 315, 315, 316, 314, 315, 315], bad_seg.atoms.resids) assert_equal(["THR"] * 7, bad_seg.atoms.resnames) assert_equal(["A", "", "", "A", "B", "", ""], bad_seg.atoms.segids) - assert_equal( - ["N", "CA", "C", "O", "CB", "CG2", "OG1"], bad_seg.atoms.names - ) - assert_equal( - ["A", "A", "A", "A", "B", "B", "B"], bad_seg.atoms.chainIDs - ) + assert_equal(["N", "CA", "C", "O", "CB", "CG2", "OG1"], bad_seg.atoms.names) + assert_equal(["A", "A", "A", "A", "B", "B", "B"], bad_seg.atoms.chainIDs) original_attrs = bad_seg._topology.attrs # [ACT] set new segids @@ -1796,9 +1735,7 @@ def test_with_ITP(self, itp): def test_with_TPR(self, tpr): # [BEFORE] assert len(tpr.segments) == 3 - assert_equal( - ["seg_0_AKeco", "seg_1_SOL", "seg_2_NA+"], tpr.segments.segids - ) + assert_equal(["seg_0_AKeco", "seg_1_SOL", "seg_2_NA+"], tpr.segments.segids) assert len(tpr.residues) == 11302 assert_equal(range(1, 11303, 1), tpr.residues.resids) orignial_res_molnums = tpr.residues.molnums diff --git a/testsuite/MDAnalysisTests/core/test_unwrap.py b/testsuite/MDAnalysisTests/core/test_unwrap.py index e6da223ee2b..ecff4d68f9e 100644 --- a/testsuite/MDAnalysisTests/core/test_unwrap.py +++ b/testsuite/MDAnalysisTests/core/test_unwrap.py @@ -70,17 +70,13 @@ def test_unwrap_pass(self, level, compound, reference, is_triclinic): if compound == "group": ref_unwrapped_pos = ref_unwrapped_pos[39:47] # molecule 12 elif compound == "segments": - ref_unwrapped_pos = ref_unwrapped_pos[ - 23:47 - ] # molecules 10, 11, 12 + ref_unwrapped_pos = ref_unwrapped_pos[23:47] # molecules 10, 11, 12 # first, do the unwrapping out-of-place: unwrapped_pos = group.unwrap( compound=compound, reference=reference, inplace=False ) # check for correct result: - assert_almost_equal( - unwrapped_pos, ref_unwrapped_pos, decimal=self.precision - ) + assert_almost_equal(unwrapped_pos, ref_unwrapped_pos, decimal=self.precision) # make sure atom positions are unchanged: assert_array_equal(group.atoms.positions, orig_pos) # now, do the unwrapping inplace: @@ -143,9 +139,7 @@ def test_unwrap_partial_frags(self, compound, reference, is_triclinic): # first, do the unwrapping out-of-place: group.unwrap(compound=compound, reference=reference, inplace=True) # check for correct result: - assert_almost_equal( - group.positions, ref_unwrapped_pos, decimal=self.precision - ) + assert_almost_equal(group.positions, ref_unwrapped_pos, decimal=self.precision) # make sure the position of molecule 12's last atom is unchanged: assert_array_equal(u.atoms[46].position, orig_pos) @@ -155,9 +149,7 @@ def test_unwrap_partial_frags(self, compound, reference, is_triclinic): ) @pytest.mark.parametrize("reference", ("com", "cog", None)) @pytest.mark.parametrize("is_triclinic", (False, True)) - def test_unwrap_empty_group( - self, level, compound, reference, is_triclinic - ): + def test_unwrap_empty_group(self, level, compound, reference, is_triclinic): # get a pristine test universe: u = UnWrapUniverse(is_triclinic=is_triclinic) if level == "atoms": @@ -168,9 +160,7 @@ def test_unwrap_empty_group( group = mda.SegmentGroup([], u) group.unwrap(compound=compound, reference=reference, inplace=True) # check for correct (empty) result: - assert_array_equal( - group.atoms.positions, np.empty((0, 3), dtype=np.float32) - ) + assert_array_equal(group.atoms.positions, np.empty((0, 3), dtype=np.float32)) @pytest.mark.parametrize("level", ("atoms", "residues", "segments")) @pytest.mark.parametrize( @@ -350,9 +340,7 @@ def test_unwrap_no_masses_exception_safety(self, level, compound): "compound", ("fragments", "molecules", "residues", "group", "segments") ) @pytest.mark.parametrize("reference", ("com", "cog", None)) - def test_unwrap_no_bonds_exception_safety( - self, level, compound, reference - ): + def test_unwrap_no_bonds_exception_safety(self, level, compound, reference): # universe without bonds: u = UnWrapUniverse(have_bonds=False) # select group appropriate for compound: @@ -394,9 +382,7 @@ def test_unwrap_no_molnums_exception_safety(self, level, reference): # store original positions: orig_pos = group.atoms.positions with pytest.raises(NoDataError): - group.unwrap( - compound="molecules", reference=reference, inplace=True - ) + group.unwrap(compound="molecules", reference=reference, inplace=True) assert_array_equal(group.atoms.positions, orig_pos) @@ -421,6 +407,4 @@ def test_uncontiguous(): ) # Ok, let's make it whole again and check that we're good u.atoms.unwrap() - assert_almost_equal( - ref_pos, ag.positions + displacement_vec, decimal=precision - ) + assert_almost_equal(ref_pos, ag.positions + displacement_vec, decimal=precision) diff --git a/testsuite/MDAnalysisTests/core/test_updating_atomgroup.py b/testsuite/MDAnalysisTests/core/test_updating_atomgroup.py index fc41670a6ee..3d4ace4cba1 100644 --- a/testsuite/MDAnalysisTests/core/test_updating_atomgroup.py +++ b/testsuite/MDAnalysisTests/core/test_updating_atomgroup.py @@ -44,9 +44,7 @@ def ag(self, u): @pytest.fixture() def ag_updating(self, u): - return u.select_atoms( - "prop x < 5 and prop y < 5 and prop z < 5", updating=True - ) + return u.select_atoms("prop x < 5 and prop y < 5 and prop z < 5", updating=True) @pytest.fixture() def ag_updating_compounded(self, u, ag): @@ -54,9 +52,7 @@ def ag_updating_compounded(self, u, ag): @pytest.fixture() def ag_updating_chained(self, u, ag_updating): - return u.select_atoms( - "around 2 group sele", sele=ag_updating, updating=True - ) + return u.select_atoms("around 2 group sele", sele=ag_updating, updating=True) @pytest.fixture() def ag_updating_chained2(self, ag_updating): @@ -91,9 +87,7 @@ def test_update(self, u, ag, ag_updating): assert ag_updating._lastupdate is None def test_compounded_update(self, u, ag_updating_compounded): - target_idxs0 = np.array( - [3650, 7406, 22703, 31426, 40357, 40360, 41414] - ) + target_idxs0 = np.array([3650, 7406, 22703, 31426, 40357, 40360, 41414]) target_idxs1 = np.array( [3650, 8146, 23469, 23472, 31426, 31689, 31692, 34326, 41414] ) @@ -101,13 +95,9 @@ def test_compounded_update(self, u, ag_updating_compounded): next(u.trajectory) assert_equal(ag_updating_compounded.indices, target_idxs1) - def test_chained_update( - self, u, ag_updating_chained, ag_updating_compounded - ): + def test_chained_update(self, u, ag_updating_chained, ag_updating_compounded): target_idxs = np.array([4471, 7406, 11973, 11975, 34662, 44042]) - assert_equal( - ag_updating_chained.indices, ag_updating_compounded.indices - ) + assert_equal(ag_updating_chained.indices, ag_updating_compounded.indices) next(u.trajectory) assert_equal(ag_updating_chained.indices, target_idxs) @@ -295,9 +285,7 @@ def test_representations(): rep = repr(ag_updating) assert "1 atom," in rep - ag_updating = u.atoms[:-1].select_atoms( - "bynum 1", "bynum 2", updating=True - ) + ag_updating = u.atoms[:-1].select_atoms("bynum 1", "bynum 2", updating=True) rep = repr(ag_updating) assert "2 atoms," in rep assert "selections 'bynum 1' + 'bynum 2'" in rep diff --git a/testsuite/MDAnalysisTests/core/test_wrap.py b/testsuite/MDAnalysisTests/core/test_wrap.py index 96332a2a088..8850691e952 100644 --- a/testsuite/MDAnalysisTests/core/test_wrap.py +++ b/testsuite/MDAnalysisTests/core/test_wrap.py @@ -58,19 +58,13 @@ def test_wrap_pass(self, level, compound, center, is_triclinic): # get the expected result: ref_wrapped_pos = u.wrapped_coords(compound, center) # first, do the wrapping out-of-place: - wrapped_pos = group.wrap( - compound=compound, center=center, inplace=False - ) + wrapped_pos = group.wrap(compound=compound, center=center, inplace=False) # check for correct result: - assert_almost_equal( - wrapped_pos, ref_wrapped_pos, decimal=self.precision - ) + assert_almost_equal(wrapped_pos, ref_wrapped_pos, decimal=self.precision) # make sure atom positions are unchanged: assert_array_equal(group.atoms.positions, orig_pos) # now, do the wrapping inplace: - wrapped_pos2 = group.wrap( - compound=compound, center=center, inplace=True - ) + wrapped_pos2 = group.wrap(compound=compound, center=center, inplace=True) # check that result is the same as for out-of-place computation: assert_array_equal(wrapped_pos, wrapped_pos2) # check that wrapped positions are applied: @@ -83,9 +77,7 @@ def test_wrap_pass(self, level, compound, center, is_triclinic): compos = group.atoms.center_of_mass(wrap=False, compound=compound) assert_in_box(compos, group.dimensions) else: - cogpos = group.atoms.center_of_geometry( - wrap=False, compound=compound - ) + cogpos = group.atoms.center_of_geometry(wrap=False, compound=compound) assert_in_box(cogpos, group.dimensions) @pytest.mark.parametrize("level", ("atoms", "residues", "segments")) @@ -126,9 +118,7 @@ def test_unwrap_wrap_cycle(self, level, compound, center, is_triclinic): ) @pytest.mark.parametrize("center", ("com", "cog")) @pytest.mark.parametrize("is_triclinic", (False, True)) - def test_wrap_partial_compound( - self, level, compound, center, is_triclinic - ): + def test_wrap_partial_compound(self, level, compound, center, is_triclinic): # get a pristine test universe: u = UnWrapUniverse(is_triclinic=is_triclinic) group = u.atoms @@ -183,9 +173,7 @@ def test_wrap_empty_group(self, level, compound, center, is_triclinic): group = group.segments group.wrap(compound=compound, center=center, inplace=True) # check for correct (empty) result: - assert_array_equal( - group.atoms.positions, np.empty((0, 3), dtype=np.float32) - ) + assert_array_equal(group.atoms.positions, np.empty((0, 3), dtype=np.float32)) @pytest.mark.parametrize("level", ("atoms", "residues", "segments")) @pytest.mark.parametrize( @@ -244,19 +232,13 @@ def test_wrap_com_cog_difference(self, compound, is_triclinic): # the first unit cell in negative x-direction. group.masses = [100.0, 1.0, 1.0] # wrap with center='cog': - wrapped_pos_cog = group.wrap( - compound=compound, center="cog", inplace=False - ) + wrapped_pos_cog = group.wrap(compound=compound, center="cog", inplace=False) # get expected result: ref_wrapped_pos = u.wrapped_coords(compound, "cog")[6:9] # check for correctness: - assert_almost_equal( - wrapped_pos_cog, ref_wrapped_pos, decimal=self.precision - ) + assert_almost_equal(wrapped_pos_cog, ref_wrapped_pos, decimal=self.precision) # wrap with center='com': - wrapped_pos_com = group.wrap( - compound=compound, center="com", inplace=False - ) + wrapped_pos_com = group.wrap(compound=compound, center="com", inplace=False) # assert that the com result is shifted with respect to the cog result # by one box length in the x-direction: shift = np.array([10.0, 0.0, 0.0], dtype=np.float32) @@ -460,13 +442,9 @@ def test_wrap_shuffled_index(self, compound, center, is_triclinic): # get expected wrapped coordinates in shuffled order ref_wrapped_pos = u.wrapped_coords(compound, center)[shuffle] # wrap the shuffled group: - wrapped_pos = group.wrap( - compound=compound, center=center, inplace=False - ) + wrapped_pos = group.wrap(compound=compound, center=center, inplace=False) # check for correct result: - assert_almost_equal( - wrapped_pos, ref_wrapped_pos, decimal=self.precision - ) + assert_almost_equal(wrapped_pos, ref_wrapped_pos, decimal=self.precision) class TestWrapTRZ(object): diff --git a/testsuite/MDAnalysisTests/core/util.py b/testsuite/MDAnalysisTests/core/util.py index 52b83d64d62..4cbe3d20ca7 100644 --- a/testsuite/MDAnalysisTests/core/util.py +++ b/testsuite/MDAnalysisTests/core/util.py @@ -376,9 +376,7 @@ def unwrapped_coords(self, compound, reference): if reference is not None: ref = reference.lower() if ref not in ["com", "cog"]: - raise ValueError( - "Unknown unwrap reference: {}" "".format(reference) - ) + raise ValueError("Unknown unwrap reference: {}" "".format(reference)) comp = compound.lower() if comp not in [ "group", diff --git a/testsuite/MDAnalysisTests/datafiles.py b/testsuite/MDAnalysisTests/datafiles.py index 396bdbd86ab..b8588f8ff9b 100644 --- a/testsuite/MDAnalysisTests/datafiles.py +++ b/testsuite/MDAnalysisTests/datafiles.py @@ -403,9 +403,7 @@ _data_ref = resources.files("MDAnalysisTests.data") -WIN_PDB_multiframe = ( - _data_ref / "windows/WIN_nmr_neopetrosiamide.pdb" -).as_posix() +WIN_PDB_multiframe = (_data_ref / "windows/WIN_nmr_neopetrosiamide.pdb").as_posix() WIN_DLP_HISTORY = (_data_ref / "windows/WIN_HISTORY").as_posix() WIN_TRJ = (_data_ref / "windows/WIN_ache.mdcrd").as_posix() WIN_ARC = (_data_ref / "windows/WIN_test.arc").as_posix() @@ -454,9 +452,7 @@ PSF_NAMD = (_data_ref / "namd_cgenff.psf").as_posix() PDB_NAMD = (_data_ref / "namd_cgenff.pdb").as_posix() -PDB_multipole = ( - _data_ref / "water_methane_acetic-acid_ammonia.pdb" -).as_posix() +PDB_multipole = (_data_ref / "water_methane_acetic-acid_ammonia.pdb").as_posix() PSF_NAMD_TRICLINIC = (_data_ref / "SiN_tric_namd.psf").as_posix() DCD_NAMD_TRICLINIC = (_data_ref / "SiN_tric_namd.dcd").as_posix() PSF_NAMD_GBIS = (_data_ref / "adk_closed_NAMD.psf").as_posix() @@ -484,9 +480,7 @@ PDB_mc_gz = (_data_ref / "model_then_cryst.pdb.gz").as_posix() PDB_mc_bz2 = (_data_ref / "model_then_cryst.pdb.bz2").as_posix() PDB_chainidnewres = (_data_ref / "chainIDnewres.pdb.gz").as_posix() -PDB_sameresid_diffresname = ( - _data_ref / "sameresid_diffresname.pdb" -).as_posix() +PDB_sameresid_diffresname = (_data_ref / "sameresid_diffresname.pdb").as_posix() PDB_chainidrepeat = (_data_ref / "chainIDrepeat.pdb.gz").as_posix() PDB_multiframe = (_data_ref / "nmr_neopetrosiamide.pdb").as_posix() PDB_helix = (_data_ref / "A6PA6_alpha.pdb").as_posix() @@ -504,9 +498,7 @@ GRO_large = (_data_ref / "bigbox.gro.bz2").as_posix() GRO_residwrap = (_data_ref / "residwrap.gro").as_posix() GRO_residwrap_0base = (_data_ref / "residwrap_0base.gro").as_posix() -GRO_sameresid_diffresname = ( - _data_ref / "sameresid_diffresname.gro" -).as_posix() +GRO_sameresid_diffresname = (_data_ref / "sameresid_diffresname.gro").as_posix() PDB = (_data_ref / "adk_oplsaa.pdb").as_posix() XTC = (_data_ref / "adk_oplsaa.xtc").as_posix() TRR = (_data_ref / "adk_oplsaa.trr").as_posix() @@ -518,20 +510,12 @@ PDB_xlserial = (_data_ref / "xl_serial.pdb").as_posix() GRO_MEMPROT = (_data_ref / "analysis/YiiP_lipids.gro.gz").as_posix() XTC_MEMPROT = (_data_ref / "analysis/YiiP_lipids.xtc").as_posix() -XTC_multi_frame = ( - _data_ref / "xtc_test_only_10_frame_10_atoms.xtc" -).as_posix() -TRR_multi_frame = ( - _data_ref / "trr_test_only_10_frame_10_atoms.trr" -).as_posix() +XTC_multi_frame = (_data_ref / "xtc_test_only_10_frame_10_atoms.xtc").as_posix() +TRR_multi_frame = (_data_ref / "trr_test_only_10_frame_10_atoms.trr").as_posix() TNG_traj = (_data_ref / "argon_npt_compressed.tng").as_posix() TNG_traj_gro = (_data_ref / "argon_npt_compressed.gro.gz").as_posix() -TNG_traj_uneven_blocks = ( - _data_ref / "argon_npt_compressed_uneven.tng" -).as_posix() -TNG_traj_vels_forces = ( - _data_ref / "argon_npt_compressed_vels_forces.tng" -).as_posix() +TNG_traj_uneven_blocks = (_data_ref / "argon_npt_compressed_uneven.tng").as_posix() +TNG_traj_vels_forces = (_data_ref / "argon_npt_compressed_vels_forces.tng").as_posix() PDB_xvf = (_data_ref / "cobrotoxin.pdb").as_posix() TPR_xvf = (_data_ref / "cobrotoxin.tpr").as_posix() TPR_xvf_2024_4 = (_data_ref / "cobrotoxin_2024_4.tpr").as_posix() @@ -584,23 +568,13 @@ TPR510_bonded = (_data_ref / "tprs/all_bonded/dummy_5.1.tpr").as_posix() TPR2016_bonded = (_data_ref / "tprs/all_bonded/dummy_2016.tpr").as_posix() TPR2018_bonded = (_data_ref / "tprs/all_bonded/dummy_2018.tpr").as_posix() -TPR2019B3_bonded = ( - _data_ref / "tprs/all_bonded/dummy_2019-beta3.tpr" -).as_posix() -TPR2020B2_bonded = ( - _data_ref / "tprs/all_bonded/dummy_2020-beta2.tpr" -).as_posix() +TPR2019B3_bonded = (_data_ref / "tprs/all_bonded/dummy_2019-beta3.tpr").as_posix() +TPR2020B2_bonded = (_data_ref / "tprs/all_bonded/dummy_2020-beta2.tpr").as_posix() TPR2020_bonded = (_data_ref / "tprs/all_bonded/dummy_2020.tpr").as_posix() -TPR2020_double_bonded = ( - _data_ref / "tprs/all_bonded/dummy_2020_double.tpr" -).as_posix() +TPR2020_double_bonded = (_data_ref / "tprs/all_bonded/dummy_2020_double.tpr").as_posix() TPR2021_bonded = (_data_ref / "tprs/all_bonded/dummy_2021.tpr").as_posix() -TPR2021_double_bonded = ( - _data_ref / "tprs/all_bonded/dummy_2021_double.tpr" -).as_posix() -TPR2022RC1_bonded = ( - _data_ref / "tprs/all_bonded/dummy_2022-rc1.tpr" -).as_posix() +TPR2021_double_bonded = (_data_ref / "tprs/all_bonded/dummy_2021_double.tpr").as_posix() +TPR2022RC1_bonded = (_data_ref / "tprs/all_bonded/dummy_2022-rc1.tpr").as_posix() TPR2023_bonded = (_data_ref / "tprs/all_bonded/dummy_2023.tpr").as_posix() TPR2024_bonded = (_data_ref / "tprs/all_bonded/dummy_2024.tpr").as_posix() TPR2024_4_bonded = (_data_ref / "tprs/all_bonded/dummy_2024_4.tpr").as_posix() @@ -738,9 +712,7 @@ mol2_molecule = (_data_ref / "mol2/Molecule.mol2").as_posix() mol2_ligand = (_data_ref / "mol2/Ligand.mol2").as_posix() mol2_broken_molecule = (_data_ref / "mol2/BrokenMolecule.mol2").as_posix() -mol2_comments_header = ( - _data_ref / "mol2/Molecule_comments_header.mol2" -).as_posix() +mol2_comments_header = (_data_ref / "mol2/Molecule_comments_header.mol2").as_posix() # MOL2 file without substructure field mol2_zinc = (_data_ref / "mol2/zinc_856218.mol2").as_posix() # MOL2 file without bonds @@ -751,12 +723,8 @@ capping_ace = (_data_ref / "capping/ace.pdb").as_posix() capping_nma = (_data_ref / "capping/nma.pdb").as_posix() -contacts_villin_folded = ( - _data_ref / "contacts/villin_folded.gro.bz2" -).as_posix() -contacts_villin_unfolded = ( - _data_ref / "contacts/villin_unfolded.gro.bz2" -).as_posix() +contacts_villin_folded = (_data_ref / "contacts/villin_folded.gro.bz2").as_posix() +contacts_villin_unfolded = (_data_ref / "contacts/villin_unfolded.gro.bz2").as_posix() contacts_file = (_data_ref / "contacts/2F4K_qlist5_remap.dat").as_posix() trz4data = (_data_ref / "lammps/datatest.trz").as_posix() @@ -774,33 +742,23 @@ LAMMPSDUMP = (_data_ref / "lammps/wat.lammpstrj.bz2").as_posix() LAMMPSDUMP_long = (_data_ref / "lammps/wat.lammpstrj_long.bz2").as_posix() LAMMPSDUMP_allinfo = (_data_ref / "lammps/mass_q_elem.lammpstrj").as_posix() -LAMMPSDUMP_nomass_elemx = ( - _data_ref / "lammps/nomass_elemx.lammpstrj" -).as_posix() -LAMMPSDUMP_allcoords = ( - _data_ref / "lammps/spce_all_coords.lammpstrj.bz2" -).as_posix() -LAMMPSDUMP_nocoords = ( - _data_ref / "lammps/spce_no_coords.lammpstrj.bz2" -).as_posix() +LAMMPSDUMP_nomass_elemx = (_data_ref / "lammps/nomass_elemx.lammpstrj").as_posix() +LAMMPSDUMP_allcoords = (_data_ref / "lammps/spce_all_coords.lammpstrj.bz2").as_posix() +LAMMPSDUMP_nocoords = (_data_ref / "lammps/spce_no_coords.lammpstrj.bz2").as_posix() 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() +LAMMPSdata_many_bonds = (_data_ref / "lammps/a_lot_of_bond_types.data").as_posix() LAMMPSdata_additional_columns = ( _data_ref / "lammps/additional_columns.data" ).as_posix() LAMMPSDUMP_additional_columns = ( _data_ref / "lammps/additional_columns.lammpstrj" ).as_posix() -LAMMPSDUMP_non_linear = ( - _data_ref / "analysis/msd/test_non_linear.dump.bz2" -).as_posix() +LAMMPSDUMP_non_linear = (_data_ref / "analysis/msd/test_non_linear.dump.bz2").as_posix() unordered_res = (_data_ref / "unordered_res.pdb").as_posix() @@ -809,9 +767,7 @@ GMS_ASYMSURF = (_data_ref / "gms/surf2wat.gms").as_posix() two_water_gro = (_data_ref / "two_water_gro.gro").as_posix() -two_water_gro_multiframe = ( - _data_ref / "two_water_gro_multiframe.gro" -).as_posix() +two_water_gro_multiframe = (_data_ref / "two_water_gro_multiframe.gro").as_posix() two_water_gro_nonames = (_data_ref / "two_water_gro_nonames.gro").as_posix() two_water_gro_widebox = (_data_ref / "two_water_gro_widebox.gro").as_posix() @@ -821,9 +777,7 @@ DLP_HISTORY = (_data_ref / "dlpoly/HISTORY").as_posix() DLP_HISTORY_order = (_data_ref / "dlpoly/HISTORY_order").as_posix() DLP_HISTORY_minimal = (_data_ref / "dlpoly/HISTORY_minimal").as_posix() -DLP_HISTORY_minimal_cell = ( - _data_ref / "dlpoly/HISTORY_minimal_cell" -).as_posix() +DLP_HISTORY_minimal_cell = (_data_ref / "dlpoly/HISTORY_minimal_cell").as_posix() DLP_HISTORY_classic = (_data_ref / "dlpoly/HISTORY_classic").as_posix() waterPSF = (_data_ref / "watdyn.psf").as_posix() @@ -872,21 +826,11 @@ TRC_TRAJ2_VAC = (_data_ref / "gromos11/gromos11_traj_vac_2.trc.gz").as_posix() TRC_PDB_SOLV = (_data_ref / "gromos11/gromos11_traj_solv.pdb.gz").as_posix() TRC_TRAJ_SOLV = (_data_ref / "gromos11/gromos11_traj_solv.trc.gz").as_posix() -TRC_CLUSTER_VAC = ( - _data_ref / "gromos11/gromos11_cluster_vac.trj.gz" -).as_posix() -TRC_TRICLINIC_SOLV = ( - _data_ref / "gromos11/gromos11_triclinic_solv.trc.gz" -).as_posix() -TRC_TRUNCOCT_VAC = ( - _data_ref / "gromos11/gromos11_truncOcta_vac.trc.gz" -).as_posix() -TRC_GENBOX_ORIGIN = ( - _data_ref / "gromos11/gromos11_genbox_origin.trc.gz" -).as_posix() -TRC_GENBOX_EULER = ( - _data_ref / "gromos11/gromos11_genbox_euler.trc.gz" -).as_posix() +TRC_CLUSTER_VAC = (_data_ref / "gromos11/gromos11_cluster_vac.trj.gz").as_posix() +TRC_TRICLINIC_SOLV = (_data_ref / "gromos11/gromos11_triclinic_solv.trc.gz").as_posix() +TRC_TRUNCOCT_VAC = (_data_ref / "gromos11/gromos11_truncOcta_vac.trc.gz").as_posix() +TRC_GENBOX_ORIGIN = (_data_ref / "gromos11/gromos11_genbox_origin.trc.gz").as_posix() +TRC_GENBOX_EULER = (_data_ref / "gromos11/gromos11_genbox_euler.trc.gz").as_posix() TRC_EMPTY = (_data_ref / "gromos11/gromos11_empty.trc").as_posix() DihedralArray = (_data_ref / "adk_oplsaa_dihedral.npy").as_posix() diff --git a/testsuite/MDAnalysisTests/dummy.py b/testsuite/MDAnalysisTests/dummy.py index 7bfa11fdb86..47efa686f07 100644 --- a/testsuite/MDAnalysisTests/dummy.py +++ b/testsuite/MDAnalysisTests/dummy.py @@ -20,15 +20,12 @@ # MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # -"""Mock Universe and Topology generated from scratch with default values - -""" +"""Mock Universe and Topology generated from scratch with default values""" import numpy as np import string import itertools - # Elements of the standard mock Universe # 5 atoms per residue, 5 residues per segment _N_ATOMS = 125 @@ -83,9 +80,7 @@ def make_Universe( n_residues=n_residues, n_segments=n_segments, atom_resindex=np.repeat(np.arange(n_residues), n_atoms // n_residues), - residue_segindex=np.repeat( - np.arange(n_segments), n_residues // n_segments - ), + residue_segindex=np.repeat(np.arange(n_segments), n_residues // n_segments), # trajectory things trajectory=trajectory, velocities=velocities, @@ -154,9 +149,7 @@ def make_types(size): """Atoms are given types TypeA -> TypeE on a loop""" na, nr, ns = size types = itertools.cycle(string.ascii_uppercase[:5]) - return np.array( - ["Type{}".format(next(types)) for _ in range(na)], dtype=object - ) + return np.array(["Type{}".format(next(types)) for _ in range(na)], dtype=object) def make_names(size): diff --git a/testsuite/MDAnalysisTests/fetch/test_from_PDB.py b/testsuite/MDAnalysisTests/fetch/test_from_PDB.py new file mode 100644 index 00000000000..b89731ca1c3 --- /dev/null +++ b/testsuite/MDAnalysisTests/fetch/test_from_PDB.py @@ -0,0 +1,152 @@ +# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*- +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 fileencoding=utf-8 +# +# MDAnalysis --- https://www.mdanalysis.org +# Copyright (c) 2006-2017 The MDAnalysis Development Team and contributors +# (see the file AUTHORS for the full list of names) +# +# Released under the Lesser GNU Public Licence, v2.1 or any higher version +# +# Please cite your use of MDAnalysis in published work: +# +# R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler, +# D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein. +# MDAnalysis: A Python package for the rapid analysis of molecular dynamics +# simulations. In S. Benthall and S. Rostrup editors, Proceedings of the 15th +# Python in Science Conference, pages 102-109, Austin, TX, 2016. SciPy. +# doi: 10.25080/majora-629e541a-00e +# +# N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and O. Beckstein. +# MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations. +# J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 +# + +import pytest + +import MDAnalysis as mda +from MDAnalysis.fetch.pdb import ( + DEFAULT_CACHE_NAME_DOWNLOADER, + HAS_POOCH, + SUPPORTED_FILE_FORMATS_DOWNLOADER, +) + +import re +from urllib import request +from shutil import rmtree +from pathlib import Path + +if HAS_POOCH: + from requests.exceptions import HTTPError + import pooch + +try: + request.urlopen("https://files.wwpdb.org/", timeout=2) + HAS_ACCESS_TO_WWPDB = True +except request.URLError: + HAS_ACCESS_TO_WWPDB = False + + +@pytest.mark.skipif( + HAS_POOCH, + reason="Pooch is installed.", +) +def test_pooch_installation(tmp_path): + with pytest.raises( + ModuleNotFoundError, + match="pooch is needed as a dependency for from_PDB()", + ): + mda.fetch.from_PDB("1AKE", cache_path=tmp_path, file_format="cif") + + +@pytest.mark.skipif(not HAS_POOCH, reason="Pooch is not installed.") +@pytest.mark.skipif( + not HAS_ACCESS_TO_WWPDB, + reason="Can not connect to https://files.wwpdb.org/", +) +class TestDocstringExamples: + """This class tests all the examples found in from_PDB's docstring""" + + @pytest.mark.parametrize("pdb_id", ["1AKE", "4BWZ"]) + def test_one_file_download(self, tmp_path, pdb_id): + path = mda.fetch.from_PDB(pdb_id, cache_path=tmp_path, file_format="cif") + assert isinstance(path, Path) + assert Path(path).name == f"{pdb_id}.cif" + + def test_multiple_files_download(self, tmp_path): + list_of_path_strings = mda.fetch.from_PDB( + ["1AKE", "4BWZ"], cache_path=tmp_path, progressbar=True + ) + assert all(isinstance(pdb_id, Path) for pdb_id in list_of_path_strings) + assert all( + [ + Path(path).name == f"{name}.cif.gz" + for path, name in zip( + list_of_path_strings, ["1AKE", "4BWZ"], strict=True + ) + ] + ) + + @pytest.mark.parametrize("pdb_id, n_atoms", [("1AKE", 3816), ("4BWZ", 2824)]) + def test_files_to_universe(self, tmp_path, pdb_id, n_atoms): + u = mda.Universe( + mda.fetch.from_PDB( + pdb_id, + file_format="pdb.gz", + cache_path=tmp_path, + progressbar=True, + ) + ) + assert isinstance(u, mda.Universe) and (len(u.atoms) == n_atoms) + + +@pytest.fixture() +def clean_up_default_cache(): + rmtree(pooch.os_cache(DEFAULT_CACHE_NAME_DOWNLOADER), ignore_errors=True) + yield + rmtree(pooch.os_cache(DEFAULT_CACHE_NAME_DOWNLOADER)) + + +@pytest.mark.skipif(not HAS_POOCH, reason="Pooch is not installed.") +@pytest.mark.skipif( + not HAS_ACCESS_TO_WWPDB, + reason="Can not connect to https://files.wwpdb.org/", +) +class TestExpectedBehaviors: + + def test_no_cache_path(self, clean_up_default_cache): + assert isinstance(mda.fetch.from_PDB("1AKE", cache_path=None), Path) + + def test_str_input_gives_path_output(self, tmp_path): + assert isinstance( + mda.fetch.from_PDB(pdb_ids="1AKE", cache_path=tmp_path, file_format="cif"), + Path, + ) + + def test_list_input_gives_list_output(self, tmp_path): + assert isinstance( + mda.fetch.from_PDB(pdb_ids=["1AKE"], cache_path=tmp_path), list + ) + + +@pytest.mark.skipif(not HAS_POOCH, reason="Pooch is not installed.") +@pytest.mark.skipif( + not HAS_ACCESS_TO_WWPDB, + reason="Can not connect to https://files.wwpdb.org/", +) +class TestExpectedErrors: + + def test_invalid_pdb(self, tmp_path): + with pytest.raises(HTTPError): + mda.fetch.from_PDB(pdb_ids="foobar", cache_path=tmp_path) + + def test_invalid_file_format(self, tmp_path): + with pytest.raises( + ValueError, + match=re.escape( + "Invalid file format. Supported file formats " + f"are {SUPPORTED_FILE_FORMATS_DOWNLOADER}" + ), + ): + mda.fetch.from_PDB( + pdb_ids="1AKE", cache_path=tmp_path, file_format="barfoo" + ) diff --git a/testsuite/MDAnalysisTests/formats/test_libdcd.py b/testsuite/MDAnalysisTests/formats/test_libdcd.py index 63a9d83622c..fd47b443d7d 100644 --- a/testsuite/MDAnalysisTests/formats/test_libdcd.py +++ b/testsuite/MDAnalysisTests/formats/test_libdcd.py @@ -397,16 +397,13 @@ def write_dcd(in_name, out_name, remarks="testing", header=None): @pytest.mark.xfail( - (os.name == "nt" and sys.maxsize <= 2**32) - or platform.machine() == "aarch64", + (os.name == "nt" and sys.maxsize <= 2**32) or platform.machine() == "aarch64", reason="occasional fail on 32-bit windows and ARM", ) # occasionally fails due to unreliable test timings @hypothesis.settings(deadline=None) # see Issue 3096 @given( - remarks=strategies.text( - alphabet=string.printable, min_size=0, max_size=239 - ) + remarks=strategies.text(alphabet=string.printable, min_size=0, max_size=239) ) # handle the printable ASCII strings @example(remarks="") def test_written_remarks_property(remarks, tmpdir_factory): @@ -647,9 +644,7 @@ def test_readframes_order(order, shape, dcd): assert x.shape == shape -@pytest.mark.parametrize( - "indices", [[1, 2, 3, 4], [5, 10, 15, 19], [9, 4, 2, 0, 50]] -) +@pytest.mark.parametrize("indices", [[1, 2, 3, 4], [5, 10, 15, 19], [9, 4, 2, 0, 50]]) def test_readframes_atomindices(indices, dcd): allframes = dcd.readframes(order="afc").xyz frames = dcd.readframes(indices=indices, order="afc") diff --git a/testsuite/MDAnalysisTests/formats/test_libmdaxdr.py b/testsuite/MDAnalysisTests/formats/test_libmdaxdr.py index 64748e3088e..23eb6536d39 100644 --- a/testsuite/MDAnalysisTests/formats/test_libmdaxdr.py +++ b/testsuite/MDAnalysisTests/formats/test_libmdaxdr.py @@ -497,9 +497,7 @@ def test_write_trr_dtype(tmpdir, dtype, trr): v = frame.v.astype(dtype) f = frame.f.astype(dtype) box = frame.box.astype(dtype) - fout.write( - x, v, f, box, frame.step, frame.time, frame.lmbda, natoms - ) + fout.write(x, v, f, box, frame.step, frame.time, frame.lmbda, natoms) @pytest.mark.parametrize("array_like", (np.array, list)) @@ -512,9 +510,7 @@ def test_write_trr_array_like(tmpdir, array_like, trr): v = array_like(frame.v) f = array_like(frame.f) box = array_like(frame.box) - fout.write( - x, v, f, box, frame.step, frame.time, frame.lmbda, natoms - ) + fout.write(x, v, f, box, frame.step, frame.time, frame.lmbda, natoms) def test_write_different_box_trr(tmpdir, trr): diff --git a/testsuite/MDAnalysisTests/guesser/test_base.py b/testsuite/MDAnalysisTests/guesser/test_base.py index e890ca9957b..b22246d99d0 100644 --- a/testsuite/MDAnalysisTests/guesser/test_base.py +++ b/testsuite/MDAnalysisTests/guesser/test_base.py @@ -58,16 +58,13 @@ class TestGuesser1(GuesserBase): def test_guess_invalid_attribute(self): with pytest.raises( ValueError, - match="default guesser can not guess " - "the following attribute: foo", + match="default guesser can not guess " "the following attribute: foo", ): mda.Universe(datafiles.PDB_xsmall, to_guess=["foo"]) def test_guess_attribute_with_missing_parent_attr(self): names = Atomnames(np.array(["C", "HB", "HA", "O"], dtype=object)) - masses = Masses( - np.array([np.nan, np.nan, np.nan, np.nan], dtype=np.float64) - ) + masses = Masses(np.array([np.nan, np.nan, np.nan, np.nan], dtype=np.float64)) top = Topology(4, 1, 1, attrs=[names, masses]) u = mda.Universe(top, to_guess=["masses"]) assert_allclose( @@ -88,9 +85,7 @@ def test_partial_guessing(self): masses = Masses(np.array([0, np.nan, np.nan, 0], dtype=np.float64)) top = Topology(4, 1, 1, attrs=[types, masses]) u = mda.Universe(top, to_guess=["masses"]) - assert_allclose( - u.atoms.masses, np.array([0, 1.00800, 1.00800, 0]), atol=0 - ) + assert_allclose(u.atoms.masses, np.array([0, 1.00800, 1.00800, 0]), atol=0) def test_force_guess_priority(self): "check that passing the attribute to force_guess have higher power" @@ -185,9 +180,7 @@ def test_guess_topology_objects_out_of_order_guess(self): with pytest.raises(NoDataError): u.atoms.angles - u.guess_TopologyAttrs( - "default", to_guess=["dihedrals", "angles", "bonds"] - ) + u.guess_TopologyAttrs("default", to_guess=["dihedrals", "angles", "bonds"]) assert len(u.atoms.angles) == 290 assert len(u.atoms.dihedrals) == 411 @@ -249,9 +242,7 @@ def test_guess_singular(self): def test_Universe_guess_bonds_deprecated(): - with pytest.warns( - DeprecationWarning, match="`guess_bonds` keyword is deprecated" - ): + with pytest.warns(DeprecationWarning, match="`guess_bonds` keyword is deprecated"): u = mda.Universe(datafiles.PDB_xsmall, guess_bonds=True) diff --git a/testsuite/MDAnalysisTests/guesser/test_default_guesser.py b/testsuite/MDAnalysisTests/guesser/test_default_guesser.py index 92c24593c35..9aa6c2e27e4 100644 --- a/testsuite/MDAnalysisTests/guesser/test_default_guesser.py +++ b/testsuite/MDAnalysisTests/guesser/test_default_guesser.py @@ -57,9 +57,7 @@ def test_guess_masses_from_universe(self): u = mda.Universe(topology) assert isinstance(u.atoms.masses, np.ndarray) - assert_allclose( - u.atoms.masses, np.array([12.011, 12.011, 1.008]), atol=0 - ) + assert_allclose(u.atoms.masses, np.array([12.011, 12.011, 1.008]), atol=0) def test_guess_masses_from_guesser_object(self, default_guesser): elements = ["H", "Ca", "Am"] @@ -90,9 +88,7 @@ def test_guess_atom_mass(self, default_guesser): def test_guess_masses_with_no_reference_elements(self): u = mda.Universe.empty(3) - with pytest.raises( - NoDataError, match=("there is no reference attributes ") - ): + with pytest.raises(NoDataError, match=("there is no reference attributes ")): u.guess_TopologyAttrs("default", ["masses"]) @@ -127,10 +123,7 @@ def test_partial_guess_elements(self, default_guesser): def test_guess_elements_from_no_data(self): top = Topology(5) - msg = ( - "there is no reference attributes in this " - "universe to guess types from" - ) + msg = "there is no reference attributes in this " "universe to guess types from" with pytest.warns(UserWarning, match=msg): mda.Universe(top, to_guess=["types"]) @@ -212,9 +205,7 @@ def test_guess_dihedrals_with_no_angles(): def test_guess_impropers_with_angles(): "Test guessing impropers for atoms with angles" "and bonds information " - u = mda.Universe( - datafiles.two_water_gro, to_guess=["bonds", "angles", "impropers"] - ) + u = mda.Universe(datafiles.two_water_gro, to_guess=["bonds", "angles", "impropers"]) u.guess_TopologyAttrs(to_guess=["impropers"]) assert hasattr(u, "impropers") assert hasattr(u, "angles") @@ -245,16 +236,12 @@ def bond_sort(arr): def test_guess_bonds_water(): u = mda.Universe(datafiles.two_water_gro) bonds = bond_sort( - DefaultGuesser(None, box=u.dimensions).guess_bonds( - u.atoms, u.atoms.positions - ) + DefaultGuesser(None, box=u.dimensions).guess_bonds(u.atoms, u.atoms.positions) ) assert_equal(bonds, ((0, 1), (0, 2), (3, 4), (3, 5))) -@pytest.mark.parametrize( - "fudge_factor, n_bonds", [(0, 0), (0.55, 4), (200, 6)] -) +@pytest.mark.parametrize("fudge_factor, n_bonds", [(0, 0), (0.55, 4), (200, 6)]) def test_guess_bonds_water_fudge_factor_passed(fudge_factor, n_bonds): u = mda.Universe( datafiles.two_water_gro, @@ -330,8 +317,6 @@ def test_guess_gasteiger_charges(smi): @requires_rdkit def test_aromaticity(): - u = mda.Universe( - datafiles.PDB_small, to_guess=["elements", "aromaticities"] - ) + u = mda.Universe(datafiles.PDB_small, to_guess=["elements", "aromaticities"]) c_aromatic = u.select_atoms("resname PHE and name CD1") assert_equal(c_aromatic.aromaticities[0], True) diff --git a/testsuite/MDAnalysisTests/lib/test_cutil.py b/testsuite/MDAnalysisTests/lib/test_cutil.py index 47c4d7f905c..d583551881d 100644 --- a/testsuite/MDAnalysisTests/lib/test_cutil.py +++ b/testsuite/MDAnalysisTests/lib/test_cutil.py @@ -99,7 +99,5 @@ def test_in2d(): ], ) def test_in2d_VE(arr1, arr2): - with pytest.raises( - ValueError, match=r"Both arrays must be \(n, 2\) arrays" - ): + with pytest.raises(ValueError, match=r"Both arrays must be \(n, 2\) arrays"): _in2d(arr1, arr2) diff --git a/testsuite/MDAnalysisTests/lib/test_distances.py b/testsuite/MDAnalysisTests/lib/test_distances.py index 06abe0a99c7..6d93ff3fbe5 100644 --- a/testsuite/MDAnalysisTests/lib/test_distances.py +++ b/testsuite/MDAnalysisTests/lib/test_distances.py @@ -63,9 +63,7 @@ def test_check_result_array_wrong_dtype(self): wrong_dtype = np.int64 ref_wrong_dtype = self.ref.astype(wrong_dtype) with pytest.raises(TypeError) as err: - res = distances._check_result_array( - ref_wrong_dtype, self.ref.shape - ) + res = distances._check_result_array(ref_wrong_dtype, self.ref.shape) assert err.msg == ( "Result array must be of type numpy.float64, " "got {}.".format(wrong_dtype) @@ -126,9 +124,7 @@ def test_capped_distance_noresults(self): point1 = np.array([0.1, 0.1, 0.1], dtype=np.float32) point2 = np.array([0.95, 0.1, 0.1], dtype=np.float32) - pairs, dists = distances.capped_distance( - point1, point2, max_cutoff=0.2 - ) + pairs, dists = distances.capped_distance(point1, point2, max_cutoff=0.2) assert_equal(len(pairs), 0) @@ -311,9 +307,9 @@ def test_self_capped_distance( ) def test_method_selfselection(self, box, npoints, cutoff, meth): np.random.seed(90003) - points = ( - np.random.uniform(low=0, high=1.0, size=(npoints, 3)) - ).astype(np.float32) + points = (np.random.uniform(low=0, high=1.0, size=(npoints, 3))).astype( + np.float32 + ) method = distances._determine_method_self(points, cutoff, box=box) assert_equal(method.__name__, meth) @@ -408,9 +404,7 @@ def test_noPBC(self, backend, ref_system, pos, request): # cycle through combinations of numpy array and AtomGroup @pytest.mark.parametrize("pos0", ["ref_system", "ref_system_universe"]) @pytest.mark.parametrize("pos1", ["ref_system", "ref_system_universe"]) - def test_noPBC_mixed_combinations( - self, backend, ref_system, pos0, pos1, request - ): + def test_noPBC_mixed_combinations(self, backend, ref_system, pos0, pos1, request): _, points, reference, _ = ref_system # reference values _, _, ref_val, _ = request.getfixturevalue(pos0) _, points_val, _, _ = request.getfixturevalue(pos1) @@ -445,15 +439,11 @@ def test_PBC(self, backend, ref_system, pos, request): # cycle through combinations of numpy array and AtomGroup @pytest.mark.parametrize("pos0", ["ref_system", "ref_system_universe"]) @pytest.mark.parametrize("pos1", ["ref_system", "ref_system_universe"]) - def test_PBC_mixed_combinations( - self, backend, ref_system, pos0, pos1, request - ): + def test_PBC_mixed_combinations(self, backend, ref_system, pos0, pos1, request): box, points, _, _ = ref_system _, _, ref_val, _ = request.getfixturevalue(pos0) _, points_val, _, _ = request.getfixturevalue(pos1) - d = distances.distance_array( - ref_val, points_val, box=box, backend=backend - ) + d = distances.distance_array(ref_val, points_val, box=box, backend=backend) assert_almost_equal( d, np.array([[0.0, 0.0, 0.0, self._dist(points[3], ref=[1, 1, 2])]]), @@ -542,9 +532,7 @@ def test_simple(self, DCD_Universe, backend): trajectory[10] x1 = U.atoms.positions d = distances.distance_array(x0, x1, backend=backend) - assert_equal( - d.shape, (3341, 3341), "wrong shape (should be" "(Natoms,Natoms))" - ) + assert_equal(d.shape, (3341, 3341), "wrong shape (should be" "(Natoms,Natoms))") assert_almost_equal( d.min(), 0.11981228170520701, @@ -594,9 +582,7 @@ def test_periodic(self, DCD_Universe, backend): x0 = U.atoms.positions trajectory[10] x1 = U.atoms.positions - d = distances.distance_array( - x0, x1, box=U.coord.dimensions, backend=backend - ) + d = distances.distance_array(x0, x1, box=U.coord.dimensions, backend=backend) assert_equal( d.shape, (3341, 3341), @@ -653,18 +639,14 @@ def test_atomgroup_simple(self, DCD_Universe, DCD_Universe2, backend): ("index 9", np.s_[8, :]), ], ) - def test_atomgroup_matches_numpy( - self, DCD_Universe, backend, sel, np_slice, box - ): + def test_atomgroup_matches_numpy(self, DCD_Universe, backend, sel, np_slice, box): U = DCD_Universe x0_ag = U.select_atoms(sel) x0_arr = U.atoms.positions[np_slice] x1_ag = U.select_atoms(sel) x1_arr = U.atoms.positions[np_slice] d_ag = distances.distance_array(x0_ag, x1_ag, box=box, backend=backend) - d_arr = distances.distance_array( - x0_arr, x1_arr, box=box, backend=backend - ) + d_arr = distances.distance_array(x0_arr, x1_arr, box=box, backend=backend) assert_allclose( d_ag, d_arr, err_msg="AtomGroup and NumPy distances do not match" ) @@ -708,9 +690,7 @@ def test_simple(self, DCD_Universe, backend): x0 = U.atoms.positions d = distances.self_distance_array(x0, backend=backend) N = 3341 * (3341 - 1) / 2 - assert_equal( - d.shape, (N,), "wrong shape (should be (Natoms*(Natoms-1)/2,))" - ) + assert_equal(d.shape, (N,), "wrong shape (should be (Natoms*(Natoms-1)/2,))") assert_almost_equal( d.min(), 0.92905562402529318, @@ -733,9 +713,7 @@ def test_outarray(self, DCD_Universe, backend): N = natoms * (natoms - 1) // 2 d = np.zeros((N,), np.float64) distances.self_distance_array(x0, result=d, backend=backend) - assert_equal( - d.shape, (N,), "wrong shape (should be (Natoms*(Natoms-1)/2,))" - ) + assert_equal(d.shape, (N,), "wrong shape (should be (Natoms*(Natoms-1)/2,))") assert_almost_equal( d.min(), 0.92905562402529318, @@ -757,12 +735,8 @@ def test_periodic(self, DCD_Universe, backend): x0 = U.atoms.positions natoms = len(U.atoms) N = natoms * (natoms - 1) / 2 - d = distances.self_distance_array( - x0, box=U.coord.dimensions, backend=backend - ) - assert_equal( - d.shape, (N,), "wrong shape (should be (Natoms*(Natoms-1)/2,))" - ) + d = distances.self_distance_array(x0, box=U.coord.dimensions, backend=backend) + assert_equal(d.shape, (N,), "wrong shape (should be (Natoms*(Natoms-1)/2,))") assert_almost_equal( d.min(), 0.92905562402529318, @@ -783,9 +757,7 @@ def test_atomgroup_simple(self, DCD_Universe, backend): x0 = U.select_atoms("all") d = distances.self_distance_array(x0, backend=backend) N = 3341 * (3341 - 1) / 2 - assert_equal( - d.shape, (N,), "wrong shape (should be" " (Natoms*(Natoms-1)/2,))" - ) + assert_equal(d.shape, (N,), "wrong shape (should be" " (Natoms*(Natoms-1)/2,))") assert_almost_equal( d.min(), 0.92905562402529318, @@ -809,9 +781,7 @@ def test_atomgroup_simple(self, DCD_Universe, backend): ("index 9", np.s_[8, :]), ], ) - def test_atomgroup_matches_numpy( - self, DCD_Universe, backend, sel, np_slice, box - ): + def test_atomgroup_matches_numpy(self, DCD_Universe, backend, sel, np_slice, box): U = DCD_Universe x0_ag = U.select_atoms(sel) @@ -936,9 +906,7 @@ def test_selfdist(self, S_mol, box, tri_vec_box, backend): # distopia backend support R_coords = distances.transform_StoR(S_mol1, box, backend="serial") # Transform functions are tested elsewhere so taken as working here - dists = distances.self_distance_array( - R_coords, box=box, backend=backend - ) + dists = distances.self_distance_array(R_coords, box=box, backend=backend) # Manually calculate self_distance_array manual = np.zeros(len(dists), dtype=np.float64) distpos = 0 @@ -964,9 +932,7 @@ def test_selfdist(self, S_mol, box, tri_vec_box, backend): # distopia backend support R_coords = distances.transform_StoR(S_mol2, box, backend="serial") # Transform functions are tested elsewhere so taken as working here - dists = distances.self_distance_array( - R_coords, box=box, backend=backend - ) + dists = distances.self_distance_array(R_coords, box=box, backend=backend) # Manually calculate self_distance_array manual = np.zeros(len(dists), dtype=np.float64) distpos = 0 @@ -996,9 +962,7 @@ def test_distarray(self, S_mol, tri_vec_box, box, backend): R_mol2 = distances.transform_StoR(S_mol2, box, backend="serial") # Try with box - dists = distances.distance_array( - R_mol1, R_mol2, box=box, backend=backend - ) + dists = distances.distance_array(R_mol1, R_mol2, box=box, backend=backend) # Manually calculate distance_array manual = np.zeros((len(R_mol1), len(R_mol2))) for i, Ri in enumerate(R_mol1): @@ -1018,9 +982,7 @@ def test_distarray(self, S_mol, tri_vec_box, box, backend): def test_pbc_dist(self, S_mol, box, backend): S_mol1, S_mol2 = S_mol results = np.array([[37.629944]]) - dists = distances.distance_array( - S_mol1, S_mol2, box=box, backend=backend - ) + dists = distances.distance_array(S_mol1, S_mol2, box=box, backend=backend) assert_almost_equal( dists, @@ -1036,9 +998,7 @@ def test_pbc_wrong_wassenaar_distance(self, backend): a, b, c = tri_vec_box point_a = a + b point_b = 0.5 * point_a - dist = distances.distance_array( - point_a, point_b, box=box, backend=backend - ) + dist = distances.distance_array(point_a, point_b, box=box, backend=backend) assert_almost_equal(dist[0, 0], 1) # check that our distance is different from the wassenaar distance as # expected. @@ -1185,8 +1145,7 @@ def positions_atomgroups(positions): a, b, c, d = positions arrs = [a, b, c, d] universes = [ - MDAnalysis.Universe.empty(arr.shape[0], trajectory=True) - for arr in arrs + MDAnalysis.Universe.empty(arr.shape[0], trajectory=True) for arr in arrs ] for u, a in zip(universes, arrs): u.atoms.positions = a @@ -1213,9 +1172,7 @@ def test_bonds(self, box, backend, dtype, pos, request): a, b, c, d = request.getfixturevalue(pos) a, b, c, d = convert_position_dtype_if_ndarray(a, b, c, d, dtype) dists = distances.calc_bonds(a, b, backend=backend) - assert_equal( - len(dists), 4, err_msg="calc_bonds results have wrong length" - ) + assert_equal(len(dists), 4, err_msg="calc_bonds results have wrong length") dists_pbc = distances.calc_bonds(a, b, box=box, backend=backend) # tests 0 length assert_almost_equal( @@ -1294,9 +1251,7 @@ def test_bonds_badresult(self, positions, backend): @pytest.mark.parametrize("dtype", (np.float32, np.float64)) @pytest.mark.parametrize("pos", ["positions", "positions_atomgroups"]) @pytest.mark.parametrize("backend", distopia_conditional_backend()) - def test_bonds_triclinic( - self, triclinic_box, backend, dtype, pos, request - ): + def test_bonds_triclinic(self, triclinic_box, backend, dtype, pos, request): a, b, c, d = request.getfixturevalue(pos) a, b, c, d = convert_position_dtype_if_ndarray(a, b, c, d, dtype) dists = distances.calc_bonds(a, b, box=triclinic_box, backend=backend) @@ -1322,9 +1277,7 @@ def test_bonds_single_coords(self, shift, periodic, backend): coords[1] += shift2 * box[:3] box = box if periodic else None - result = distances.calc_bonds( - coords[0], coords[1], box, backend=backend - ) + result = distances.calc_bonds(coords[0], coords[1], box, backend=backend) reference = 2.0 if periodic else np.linalg.norm(coords[0] - coords[1]) @@ -1338,9 +1291,7 @@ def test_angles(self, backend, dtype, pos, request): a, b, c, d = convert_position_dtype_if_ndarray(a, b, c, d, dtype) angles = distances.calc_angles(a, b, c, backend=backend) # Check calculated values - assert_equal( - len(angles), 4, err_msg="calc_angles results have wrong length" - ) + assert_equal(len(angles), 4, err_msg="calc_angles results have wrong length") # assert_almost_equal(angles[0], 0.0, self.prec, # err_msg="Zero length angle calculation failed") # What should this be? assert_almost_equal( @@ -1476,9 +1427,7 @@ def test_calc_dihedrals_results_inplace_all_backends( c3[:, 1] = 3 result = np.zeros(N, dtype=np.float64) - distances.calc_dihedrals( - c0, c1, c2, c3, result=result, backend=backend - ) + distances.calc_dihedrals(c0, c1, c2, c3, result=result, backend=backend) expected = np.ones(N, dtype=dtype) * 0 # test the result array is updated in place assert_almost_equal( @@ -1509,9 +1458,7 @@ def test_dihedrals_bad_result(self, positions, backend): badresult = np.zeros(len(a) - 1) # Bad result array with pytest.raises(ValueError): - distances.calc_dihedrals( - a, b, c, d, result=badresult, backend=backend - ) + distances.calc_dihedrals(a, b, c, d, result=badresult, backend=backend) @pytest.mark.parametrize( "case", @@ -1604,9 +1551,7 @@ def test_numpy_compliance_angles(self, positions, backend): angles = distances.calc_angles(a, b, c, backend=backend) vec1 = a - b vec2 = c - b - angles_numpy = np.array( - [mdamath.angle(x, y) for x, y in zip(vec1, vec2)] - ) + angles_numpy = np.array([mdamath.angle(x, y) for x, y in zip(vec1, vec2)]) # numpy 0 angle returns NaN rather than 0 assert_almost_equal( angles[1:], @@ -1677,9 +1622,7 @@ def test_ortho_PBC(self, backend, pos, request, DCD_universe_pos): with pytest.raises(ValueError): cyth1 = distances.apply_PBC(positions, box[:3], backend=backend) cyth2 = distances.apply_PBC(positions, box, backend=backend) - reference = ( - DCD_universe_pos - np.floor(DCD_universe_pos / box[:3]) * box[:3] - ) + reference = DCD_universe_pos - np.floor(DCD_universe_pos / box[:3]) * box[:3] assert_almost_equal( cyth2, @@ -1843,9 +1786,7 @@ def test_dihedrals(self, positions, backend): test2 = distances.calc_dihedrals(a, b2, c, d, box=box, backend=backend) test3 = distances.calc_dihedrals(a, b, c2, d, box=box, backend=backend) test4 = distances.calc_dihedrals(a, b, c, d2, box=box, backend=backend) - test5 = distances.calc_dihedrals( - a2, b2, c2, d2, box=box, backend=backend - ) + test5 = distances.calc_dihedrals(a2, b2, c2, d2, box=box, backend=backend) for val in [test1, test2, test3, test4, test5]: assert_almost_equal( @@ -1892,8 +1833,7 @@ def coords(): @pytest.fixture() def coords_atomgroups(coords): universes = [ - MDAnalysis.Universe.empty(arr.shape[0], trajectory=True) - for arr in coords + MDAnalysis.Universe.empty(arr.shape[0], trajectory=True) for arr in coords ] for u, a in zip(universes, coords): u.atoms.positions = a @@ -1904,9 +1844,7 @@ def coords_atomgroups(coords): def test_input_unchanged_distance_array(self, coords, box, backend): crds = coords[:2] refs = [crd.copy() for crd in crds] - res = distances.distance_array( - crds[0], crds[1], box=box, backend=backend - ) + res = distances.distance_array(crds[0], crds[1], box=box, backend=backend) assert_equal(crds, refs) @pytest.mark.parametrize("box", boxes) @@ -1916,9 +1854,7 @@ def test_input_unchanged_distance_array_atomgroup( ): crds = coords_atomgroups[:2] refs = [crd.positions.copy() for crd in crds] - res = distances.distance_array( - crds[0], crds[1], box=box, backend=backend - ) + res = distances.distance_array(crds[0], crds[1], box=box, backend=backend) assert_equal([crd.positions for crd in crds], refs) @pytest.mark.parametrize("box", boxes) @@ -1958,9 +1894,7 @@ def test_input_unchanged_capped_distance(self, coords, box, met, backend): @pytest.mark.parametrize("box", boxes) @pytest.mark.parametrize("met", ["bruteforce", "pkdtree", "nsgrid", None]) @pytest.mark.parametrize("backend", distopia_conditional_backend()) - def test_input_unchanged_self_capped_distance( - self, coords, box, met, backend - ): + def test_input_unchanged_self_capped_distance(self, coords, box, met, backend): crd = coords[0] ref = crd.copy() r_cut = 0.25 @@ -1971,9 +1905,7 @@ def test_input_unchanged_self_capped_distance( @pytest.mark.parametrize("box", boxes[:2]) @pytest.mark.parametrize("backend", ["serial", "openmp"]) - def test_input_unchanged_transform_RtoS_and_StoR( - self, coords, box, backend - ): + def test_input_unchanged_transform_RtoS_and_StoR(self, coords, box, backend): crd = coords[0] ref = crd.copy() res = distances.transform_RtoS(crd, box, backend=backend) @@ -2006,9 +1938,7 @@ def test_input_unchanged_calc_bonds_atomgroup( def test_input_unchanged_calc_angles(self, coords, box, backend): crds = coords[:3] refs = [crd.copy() for crd in crds] - res = distances.calc_angles( - crds[0], crds[1], crds[2], box=box, backend=backend - ) + res = distances.calc_angles(crds[0], crds[1], crds[2], box=box, backend=backend) assert_equal(crds, refs) @pytest.mark.parametrize("box", boxes) @@ -2018,9 +1948,7 @@ def test_input_unchanged_calc_angles_atomgroup( ): crds = coords_atomgroups[:3] refs = [crd.positions.copy() for crd in crds] - res = distances.calc_angles( - crds[0], crds[1], crds[2], box=box, backend=backend - ) + res = distances.calc_angles(crds[0], crds[1], crds[2], box=box, backend=backend) assert_equal([crd.positions for crd in crds], refs) @pytest.mark.parametrize("box", boxes) @@ -2055,9 +1983,7 @@ def test_input_unchanged_apply_PBC(self, coords, box, backend): @pytest.mark.parametrize("box", boxes[:2]) @pytest.mark.parametrize("backend", ["serial", "openmp"]) - def test_input_unchanged_apply_PBC_atomgroup( - self, coords_atomgroups, box, backend - ): + def test_input_unchanged_apply_PBC_atomgroup(self, coords_atomgroups, box, backend): crd = coords_atomgroups[0] ref = crd.positions.copy() res = distances.apply_PBC(crd, box, backend=backend) @@ -2105,9 +2031,7 @@ def test_empty_input_distance_array(self, empty_coord, box, backend): @pytest.mark.parametrize("box", boxes) @pytest.mark.parametrize("backend", distopia_conditional_backend()) def test_empty_input_self_distance_array(self, empty_coord, box, backend): - res = distances.self_distance_array( - empty_coord, box=box, backend=backend - ) + res = distances.self_distance_array(empty_coord, box=box, backend=backend) assert_equal(res, np.empty((0,), dtype=np.float64)) @pytest.mark.parametrize("box", boxes) @@ -2172,9 +2096,7 @@ def test_empty_input_transform_StoR(self, empty_coord, box, backend): @pytest.mark.parametrize("box", boxes) @pytest.mark.parametrize("backend", distopia_conditional_backend()) def test_empty_input_calc_bonds(self, empty_coord, box, backend): - res = distances.calc_bonds( - empty_coord, empty_coord, box=box, backend=backend - ) + res = distances.calc_bonds(empty_coord, empty_coord, box=box, backend=backend) assert_equal(res, np.empty((0,), dtype=np.float64)) @pytest.mark.parametrize("box", boxes) @@ -2354,9 +2276,7 @@ def test_output_dtype_transform_RtoS(self, incoords, box, backend): assert res.shape == incoords.shape @pytest.mark.parametrize("box", boxes) - @pytest.mark.parametrize( - "incoords", [2 * [coords[0]]] + list(comb(coords[1:], 2)) - ) + @pytest.mark.parametrize("incoords", [2 * [coords[0]]] + list(comb(coords[1:], 2))) @pytest.mark.parametrize("backend", distopia_conditional_backend()) def test_output_type_calc_bonds(self, incoords, box, backend): res = distances.calc_bonds(*incoords, box=box, backend=backend) @@ -2370,9 +2290,7 @@ def test_output_type_calc_bonds(self, incoords, box, backend): assert res.shape == (coord.shape[0],) @pytest.mark.parametrize("box", boxes) - @pytest.mark.parametrize( - "incoords", [3 * [coords[0]]] + list(comb(coords[1:], 3)) - ) + @pytest.mark.parametrize("incoords", [3 * [coords[0]]] + list(comb(coords[1:], 3))) @pytest.mark.parametrize("backend", distopia_conditional_backend()) def test_output_type_calc_angles(self, incoords, box, backend): res = distances.calc_angles(*incoords, box=box, backend=backend) @@ -2386,9 +2304,7 @@ def test_output_type_calc_angles(self, incoords, box, backend): assert res.shape == (coord.shape[0],) @pytest.mark.parametrize("box", boxes) - @pytest.mark.parametrize( - "incoords", [4 * [coords[0]]] + list(comb(coords[1:], 4)) - ) + @pytest.mark.parametrize("incoords", [4 * [coords[0]]] + list(comb(coords[1:], 4))) @pytest.mark.parametrize("backend", distopia_conditional_backend()) def test_output_type_calc_dihedrals(self, incoords, box, backend): res = distances.calc_dihedrals(*incoords, box=box, backend=backend) diff --git a/testsuite/MDAnalysisTests/lib/test_mdamath.py b/testsuite/MDAnalysisTests/lib/test_mdamath.py index fd2d770d49d..219c24307f8 100644 --- a/testsuite/MDAnalysisTests/lib/test_mdamath.py +++ b/testsuite/MDAnalysisTests/lib/test_mdamath.py @@ -81,9 +81,7 @@ def test_normal_unit(self, x): else: assert np.allclose(np.linalg.norm(n), 1) - @pytest.mark.parametrize( - "vec1, vec2, value", [(e1, e2, e3), (e1, null, 0.0)] - ) + @pytest.mark.parametrize("vec1, vec2, value", [(e1, e2, e3), (e1, null, 0.0)]) def test_normal(self, vec1, vec2, value): n = mdamath.normal(vec1, vec2) if isinstance(value, float): @@ -185,9 +183,7 @@ def ref_tribox(self, tri_vecs): return box @pytest.mark.parametrize("lengths", comb_wr([-1, 0, 1, 2], 3)) - @pytest.mark.parametrize( - "angles", comb_wr([-10, 0, 20, 70, 90, 120, 180], 3) - ) + @pytest.mark.parametrize("angles", comb_wr([-10, 0, 20, 70, 90, 120, 180], 3)) def test_triclinic_vectors(self, lengths, angles): box = lengths + angles ref = self.ref_trivecs(box) @@ -263,9 +259,7 @@ def test_triclinic_vectors_box_cycle(self): for b in range(10, 91, 10): for g in range(10, 91, 10): ref = np.array([1, 1, 1, a, b, g], dtype=np.float32) - res = mdamath.triclinic_box( - *mdamath.triclinic_vectors(ref) - ) + res = mdamath.triclinic_box(*mdamath.triclinic_vectors(ref)) if not np.all(res == 0.0): assert_almost_equal(res, ref, 5) @@ -288,9 +282,7 @@ def test_triclinic_vectors_box_cycle_exact(self, angles): assert_allclose(res, ref) @pytest.mark.parametrize("lengths", comb_wr([-1, 0, 1, 2], 3)) - @pytest.mark.parametrize( - "angles", comb_wr([-10, 0, 20, 70, 90, 120, 180], 3) - ) + @pytest.mark.parametrize("angles", comb_wr([-10, 0, 20, 70, 90, 120, 180], 3)) def test_triclinic_box(self, lengths, angles): tri_vecs = self.ref_trivecs_unsafe(lengths + angles) ref = self.ref_tribox(tri_vecs) @@ -299,9 +291,7 @@ def test_triclinic_box(self, lengths, angles): assert res.dtype == ref.dtype @pytest.mark.parametrize("lengths", comb_wr([-1, 0, 1, 2], 3)) - @pytest.mark.parametrize( - "angles", comb_wr([-10, 0, 20, 70, 90, 120, 180], 3) - ) + @pytest.mark.parametrize("angles", comb_wr([-10, 0, 20, 70, 90, 120, 180], 3)) def test_box_volume(self, lengths, angles): box = np.array(lengths + angles, dtype=np.float32) assert_almost_equal( @@ -580,15 +570,11 @@ def test_make_whole_fullerene(self): blengths = u.atoms.bonds.values() # kaboom u.atoms[::2].translate([u.dimensions[0], -2 * u.dimensions[1], 0.0]) - u.atoms[1::2].translate( - [0.0, 7 * u.dimensions[1], -5 * u.dimensions[2]] - ) + u.atoms[1::2].translate([0.0, 7 * u.dimensions[1], -5 * u.dimensions[2]]) mdamath.make_whole(u.atoms) - assert_array_almost_equal( - u.atoms.bonds.values(), blengths, decimal=self.prec - ) + assert_array_almost_equal(u.atoms.bonds.values(), blengths, decimal=self.prec) def test_make_whole_multiple_molecules(self): u = mda.Universe(two_water_gro, guess_bonds=True) diff --git a/testsuite/MDAnalysisTests/lib/test_neighborsearch.py b/testsuite/MDAnalysisTests/lib/test_neighborsearch.py index 29a179350d9..50a118ef7d6 100644 --- a/testsuite/MDAnalysisTests/lib/test_neighborsearch.py +++ b/testsuite/MDAnalysisTests/lib/test_neighborsearch.py @@ -42,9 +42,7 @@ def test_search(universe): """simply check that for a centered protein in a large box periodic and non-periodic return the same result""" ns = NeighborSearch.AtomNeighborSearch(universe.atoms) - pns = NeighborSearch.AtomNeighborSearch( - universe.atoms, universe.atoms.dimensions - ) + pns = NeighborSearch.AtomNeighborSearch(universe.atoms, universe.atoms.dimensions) ns_res = ns.search(universe.atoms[20], 20) pns_res = pns.search(universe.atoms[20], 20) diff --git a/testsuite/MDAnalysisTests/lib/test_nsgrid.py b/testsuite/MDAnalysisTests/lib/test_nsgrid.py index 582e780172b..bde9b1079fa 100644 --- a/testsuite/MDAnalysisTests/lib/test_nsgrid.py +++ b/testsuite/MDAnalysisTests/lib/test_nsgrid.py @@ -134,9 +134,7 @@ def test_nsgrid_PBC_rect(): cutoff = 7 # FastNS is called differently to max coverage - searcher = nsgrid.FastNS( - cutoff, universe.atoms.positions, box=universe.dimensions - ) + searcher = nsgrid.FastNS(cutoff, universe.atoms.positions, box=universe.dimensions) results_grid = searcher.search( universe.atoms.positions[ref_id][None, :] @@ -208,9 +206,7 @@ def test_nsgrid_pairs(universe): results_grid = run_grid_search(universe, ref_id).get_pairs() - assert_equal( - np.sort(neighbors, axis=0), np.sort(results_grid[:, 1], axis=0) - ) + assert_equal(np.sort(neighbors, axis=0), np.sort(results_grid[:, 1], axis=0)) def test_nsgrid_pair_distances(universe): @@ -284,9 +280,9 @@ def test_nsgrid_distances(universe): ) def test_nsgrid_search(box, results): np.random.seed(90003) - points = ( - np.random.uniform(low=0, high=1.0, size=(100, 3)) * (10.0) - ).astype(np.float32) + points = (np.random.uniform(low=0, high=1.0, size=(100, 3)) * (10.0)).astype( + np.float32 + ) cutoff = 2.0 query = np.array([1.0, 1.0, 1.0], dtype=np.float32).reshape((1, 3)) @@ -320,9 +316,9 @@ def test_nsgrid_search(box, results): ) def test_nsgrid_selfsearch(box, result): np.random.seed(90003) - points = ( - np.random.uniform(low=0, high=1.0, size=(100, 3)) * (10.0) - ).astype(np.float32) + points = (np.random.uniform(low=0, high=1.0, size=(100, 3)) * (10.0)).astype( + np.float32 + ) cutoff = 1.0 if box is None or np.allclose(box[:3], 0): # create a pseudobox @@ -350,9 +346,7 @@ def test_nsgrid_probe_close_to_box_boundary(): # coordinate prior to PR #2136, so we ensure that this remains fixed. # See Issue #2132 for further information. ref = np.array([[55.783722, 44.190044, -54.16671]], dtype=np.float32) - box = np.array( - [53.785854, 43.951054, 57.17597, 90.0, 90.0, 90.0], dtype=np.float32 - ) + box = np.array([53.785854, 43.951054, 57.17597, 90.0, 90.0, 90.0], dtype=np.float32) cutoff = 3.0 # search within a configuration where we know the expected outcome: conf = np.ones((1, 3), dtype=np.float32) @@ -432,9 +426,7 @@ def test_issue_2229_part2(): u.atoms[0].position = [0, 0, 29.29] u.atoms[1].position = [0, 0, 28.23] - g = mda.lib.nsgrid.FastNS( - 3.0, u.atoms[[0]].positions, box=u.dimensions, pbc=False - ) + g = mda.lib.nsgrid.FastNS(3.0, u.atoms[[0]].positions, box=u.dimensions, pbc=False) assert len(g.search(u.atoms[[1]].positions).get_pairs()) == 1 g = mda.lib.nsgrid.FastNS(3.0, u.atoms[[1]].positions, box=u.dimensions) @@ -526,9 +518,9 @@ def high_mem_tests_enabled(): @pytest.mark.skipif(not high_mem_tests_enabled(), reason=reason) def test_issue_3183(): np.random.seed(90003) - points = ( - np.random.uniform(low=0, high=1.0, size=(100, 3)) * (10.0) - ).astype(np.float32) + points = (np.random.uniform(low=0, high=1.0, size=(100, 3)) * (10.0)).astype( + np.float32 + ) cutoff = 2.0 query = np.array([1.0, 1.0, 1.0], dtype=np.float32).reshape((1, 3)) box = np.array([10000.0, 10000.0, 10000.0, 90.0, 90.0, 90.0]) diff --git a/testsuite/MDAnalysisTests/lib/test_pkdtree.py b/testsuite/MDAnalysisTests/lib/test_pkdtree.py index ec4e586b380..807f76c320e 100644 --- a/testsuite/MDAnalysisTests/lib/test_pkdtree.py +++ b/testsuite/MDAnalysisTests/lib/test_pkdtree.py @@ -29,7 +29,6 @@ from MDAnalysis.lib.pkdtree import PeriodicKDTree from MDAnalysis.lib.distances import transform_StoR - # fractional coordinates for data points f_dataset = np.array( [ diff --git a/testsuite/MDAnalysisTests/lib/test_util.py b/testsuite/MDAnalysisTests/lib/test_util.py index c4efe43da01..fc4204070b5 100644 --- a/testsuite/MDAnalysisTests/lib/test_util.py +++ b/testsuite/MDAnalysisTests/lib/test_util.py @@ -79,10 +79,8 @@ def test_presence_cutil(): try: import MDAnalysis.lib._cutil except ImportError: - pytest.fail( - msg="""MDAnalysis.lib._cutil should not raise - an ImportError if cutil is available.""" - ) + pytest.fail(msg="""MDAnalysis.lib._cutil should not raise + an ImportError if cutil is available.""") def convert_aa_code_long_data(): @@ -740,9 +738,7 @@ def test_get_parser(self, extention, parser): ], ) @pytest.mark.parametrize("compression_extention", compressed_extensions) - def test_get_parser_compressed( - self, extention, parser, compression_extention - ): + def test_get_parser_compressed(self, extention, parser, compression_extention): file_name = "file.{0}{1}".format(extention, compression_extention) a = mda.topology.core.get_parser_for(file_name) @@ -784,9 +780,7 @@ def test_get_reader(self, extention, reader): ], ) @pytest.mark.parametrize("compression_extention", compressed_extensions) - def test_get_reader_compressed( - self, extention, reader, compression_extention - ): + def test_get_reader_compressed(self, extention, reader, compression_extention): file_name = "file.{0}{1}".format(extention, compression_extention) a = mda.coordinates.core.get_reader_for(file_name) @@ -829,16 +823,12 @@ class TestUniqueRows(object): def test_unique_rows_2(self): a = np.array([[0, 1], [1, 2], [2, 1], [0, 1], [0, 1], [2, 1]]) - assert_array_equal( - util.unique_rows(a), np.array([[0, 1], [1, 2], [2, 1]]) - ) + assert_array_equal(util.unique_rows(a), np.array([[0, 1], [1, 2], [2, 1]])) def test_unique_rows_3(self): a = np.array([[0, 1, 2], [0, 1, 2], [2, 3, 4], [0, 1, 2]]) - assert_array_equal( - util.unique_rows(a), np.array([[0, 1, 2], [2, 3, 4]]) - ) + assert_array_equal(util.unique_rows(a), np.array([[0, 1, 2], [2, 3, 4]])) def test_unique_rows_with_view(self): # unique_rows doesn't work when flags['OWNDATA'] is False, @@ -884,9 +874,7 @@ def test_file_no_extension(self): def test_wrong_format(self): # Make sure ``get_writer_for`` fails if the format is unknown with pytest.raises(TypeError): - mda.coordinates.core.get_writer_for( - filename="fail_me", format="UNK" - ) + mda.coordinates.core.get_writer_for(filename="fail_me", format="UNK") def test_compressed_extension(self): for ext in (".gz", ".bz2"): @@ -905,9 +893,7 @@ def test_compressed_extension_fail(self): def test_non_string_filename(self): # Does ``get_writer_for`` fails with non string filename, no format with pytest.raises(ValueError): - mda.coordinates.core.get_writer_for( - filename=StringIO(), format=None - ) + mda.coordinates.core.get_writer_for(filename=StringIO(), format=None) def test_multiframe_failure(self): # does ``get_writer_for`` fail with invalid format and multiframe not None @@ -955,9 +941,7 @@ def test_multiframe_nonsense(self): ) def test_singleframe(self, format, writer): assert ( - mda.coordinates.core.get_writer_for( - "this", format=format, multiframe=False - ) + mda.coordinates.core.get_writer_for("this", format=format, multiframe=False) == writer ) @@ -971,9 +955,7 @@ def test_singleframe(self, format, writer): ) def test_singleframe_fails(self, format): with pytest.raises(TypeError): - mda.coordinates.core.get_writer_for( - "this", format=format, multiframe=False - ) + mda.coordinates.core.get_writer_for("this", format=format, multiframe=False) @pytest.mark.parametrize( "format, writer", @@ -985,49 +967,33 @@ def test_singleframe_fails(self, format): ) def test_multiframe(self, format, writer): assert ( - mda.coordinates.core.get_writer_for( - "this", format=format, multiframe=True - ) + mda.coordinates.core.get_writer_for("this", format=format, multiframe=True) == writer ) @pytest.mark.parametrize( "format", - [ - format_tuple[0] - for format_tuple in formats - if format_tuple[3] is False - ], + [format_tuple[0] for format_tuple in formats if format_tuple[3] is False], ) def test_multiframe_fails(self, format): with pytest.raises(TypeError): - mda.coordinates.core.get_writer_for( - "this", format=format, multiframe=True - ) + mda.coordinates.core.get_writer_for("this", format=format, multiframe=True) def test_get_writer_for_pdb(self): assert ( - mda.coordinates.core.get_writer_for( - "this", format="PDB", multiframe=False - ) + mda.coordinates.core.get_writer_for("this", format="PDB", multiframe=False) == mda.coordinates.PDB.PDBWriter ) assert ( - mda.coordinates.core.get_writer_for( - "this", format="PDB", multiframe=True - ) + mda.coordinates.core.get_writer_for("this", format="PDB", multiframe=True) == mda.coordinates.PDB.MultiPDBWriter ) assert ( - mda.coordinates.core.get_writer_for( - "this", format="ENT", multiframe=False - ) + mda.coordinates.core.get_writer_for("this", format="ENT", multiframe=False) == mda.coordinates.PDB.PDBWriter ) assert ( - mda.coordinates.core.get_writer_for( - "this", format="ENT", multiframe=True - ) + mda.coordinates.core.get_writer_for("this", format="ENT", multiframe=True) == mda.coordinates.PDB.MultiPDBWriter ) @@ -1039,9 +1005,7 @@ def test_blocks_of_1(self): view = util.blocks_of(arr, 1, 1) assert view.shape == (4, 1, 1) - assert_array_almost_equal( - view, np.array([[[0]], [[5]], [[10]], [[15]]]) - ) + assert_array_almost_equal(view, np.array([[[0]], [[5]], [[10]], [[15]]])) # Change my view, check changes are reflected in arr view[:] = 1001 @@ -1264,14 +1228,11 @@ class TestWarnIfNotUnique(object): """Tests concerning the decorator @warn_if_not_unique""" def warn_msg(self, func, group, group_name): - msg = ( - "{}.{}(): {} {} contains duplicates. Results might be " - "biased!".format( - group.__class__.__name__, - func.__name__, - group_name, - group.__repr__(), - ) + msg = "{}.{}(): {} {} contains duplicates. Results might be " "biased!".format( + group.__class__.__name__, + func.__name__, + group_name, + group.__repr__(), ) return msg @@ -1644,9 +1605,7 @@ def test_atomgroup_mismatched_lengths(self): ag1 = u.select_atoms("index 0 to 10") ag2 = u.atoms - @check_coords( - "ag1", "ag2", check_lengths_match=True, allow_atomgroup=True - ) + @check_coords("ag1", "ag2", check_lengths_match=True, allow_atomgroup=True) def func(ag1, ag2): return ag1, ag2 @@ -1676,21 +1635,16 @@ def func(a): with pytest.raises(TypeError) as err: func(a_inv_type) assert err.msg == ( - "func(): Parameter 'a' must be a numpy.ndarray, " - "got ." + "func(): Parameter 'a' must be a numpy.ndarray, " "got ." ) with pytest.raises(ValueError) as err: func(a_inv_shape_1d) - assert err.msg == ( - "func(): a.shape must be (3,) or (n, 3), got " "(6,)." - ) + assert err.msg == ("func(): a.shape must be (3,) or (n, 3), got " "(6,).") with pytest.raises(ValueError) as err: func(a_inv_shape_2d) - assert err.msg == ( - "func(): a.shape must be (3,) or (n, 3), got " "(3, 2)." - ) + assert err.msg == ("func(): a.shape must be (3,) or (n, 3), got " "(3, 2).") def test_usage_with_kwargs(self): @@ -1852,9 +1806,7 @@ def AlternateUniverse(anything): assert re.search(deprecation_line_2, doc) if remove: - deprecation_line_3 = "`{0}` will be removed in release {1}".format( - name, remove - ) + deprecation_line_3 = "`{0}` will be removed in release {1}".format(name, remove) assert re.search(deprecation_line_3, doc) # check that the old docs are still present @@ -1908,9 +1860,7 @@ class TestCheckBox(object): np.array(["1", "1", 1, 90, "90", "90"]), np.array([1, 1, 1, 90, 90, 90], dtype=np.float32), np.array([1, 1, 1, 90, 90, 90], dtype=np.float64), - np.array( - [1, 1, 1, 1, 1, 1, 90, 90, 90, 90, 90, 90], dtype=np.float32 - )[::2], + np.array([1, 1, 1, 1, 1, 1, 90, 90, 90, 90, 90, 90], dtype=np.float32)[::2], ), ) def test_check_box_ortho(self, box): @@ -1934,9 +1884,7 @@ def test_check_box_None(self): np.array(["1", "1", 2, 45, "90", "90"]), np.array([1, 1, 2, 45, 90, 90], dtype=np.float32), np.array([1, 1, 2, 45, 90, 90], dtype=np.float64), - np.array( - [1, 1, 1, 1, 2, 2, 45, 45, 90, 90, 90, 90], dtype=np.float32 - )[::2], + np.array([1, 1, 1, 1, 2, 2, 45, 45, 90, 90, 90, 90], dtype=np.float32)[::2], ), ) def test_check_box_tri_vecs(self, box): diff --git a/testsuite/MDAnalysisTests/test_api.py b/testsuite/MDAnalysisTests/test_api.py index 2819cd549a7..be46d34b5df 100644 --- a/testsuite/MDAnalysisTests/test_api.py +++ b/testsuite/MDAnalysisTests/test_api.py @@ -75,8 +75,7 @@ def test_all_import(submodule): name for name in module.__all__ if name not in module.__dict__.keys() - and name - not in [os.path.splitext(f)[0] for f in os.listdir(module_path)] + and name not in [os.path.splitext(f)[0] for f in os.listdir(module_path)] ] assert_equal( missing, diff --git a/testsuite/MDAnalysisTests/topology/base.py b/testsuite/MDAnalysisTests/topology/base.py index e7649d65f86..7aa48d3d077 100644 --- a/testsuite/MDAnalysisTests/topology/base.py +++ b/testsuite/MDAnalysisTests/topology/base.py @@ -57,16 +57,12 @@ def test_mandatory_attributes(self, top): # attributes required as part of the API # ALL parsers must provide these for attr in mandatory_attrs: - assert hasattr(top, attr), "Missing required attribute: {}".format( - attr - ) + assert hasattr(top, attr), "Missing required attribute: {}".format(attr) def test_expected_attributes(self, top): # Extra attributes as declared in specific implementations for attr in self.expected_attrs: - assert hasattr(top, attr), "Missing expected attribute: {}".format( - attr - ) + assert hasattr(top, attr), "Missing expected attribute: {}".format(attr) def test_no_unexpected_attributes(self, top): attrs = set( @@ -117,9 +113,7 @@ def test_guessed_attributes(self, filename): """check that the universe created with certain parser have the same guessed attributes as when it was guessed inside the parser""" u = mda.Universe(filename) - u_guessed_attrs = [ - attr.attrname for attr in u._topology.guessed_attributes - ] + u_guessed_attrs = [attr.attrname for attr in u._topology.guessed_attributes] for attr in self.guessed_attrs: assert hasattr(u.atoms, attr) assert attr in u_guessed_attrs diff --git a/testsuite/MDAnalysisTests/topology/test_fhiaims.py b/testsuite/MDAnalysisTests/topology/test_fhiaims.py index 4086c107dff..c7c46486f28 100644 --- a/testsuite/MDAnalysisTests/topology/test_fhiaims.py +++ b/testsuite/MDAnalysisTests/topology/test_fhiaims.py @@ -46,9 +46,7 @@ def test_guessed_types(self, filename): def test_guessed_masses(self, filename): u = mda.Universe(filename) - assert_allclose( - u.atoms.masses, [15.999, 1.008, 1.008, 15.999, 1.008, 1.008] - ) + assert_allclose(u.atoms.masses, [15.999, 1.008, 1.008, 15.999, 1.008, 1.008]) def test_elements(self, top): assert_equal(top.elements.values, ["O", "H", "H", "O", "H", "H"]) diff --git a/testsuite/MDAnalysisTests/topology/test_gms.py b/testsuite/MDAnalysisTests/topology/test_gms.py index 8becdfda6f8..1597ec2e952 100644 --- a/testsuite/MDAnalysisTests/topology/test_gms.py +++ b/testsuite/MDAnalysisTests/topology/test_gms.py @@ -66,9 +66,7 @@ class TestGMSSYMOPT(GMSBase): ref_filename = GMS_SYMOPT def test_names(self, top): - assert_equal( - top.names.values, ["CARBON", "CARBON", "HYDROGEN", "HYDROGEN"] - ) + assert_equal(top.names.values, ["CARBON", "CARBON", "HYDROGEN", "HYDROGEN"]) def test_types(self, top): assert_equal(top.atomiccharges.values, [6, 6, 1, 1]) diff --git a/testsuite/MDAnalysisTests/topology/test_guessers.py b/testsuite/MDAnalysisTests/topology/test_guessers.py index 69b1046f826..087fdefd6ef 100644 --- a/testsuite/MDAnalysisTests/topology/test_guessers.py +++ b/testsuite/MDAnalysisTests/topology/test_guessers.py @@ -35,7 +35,6 @@ from MDAnalysisTests.util import import_not_available - try: from rdkit import Chem from rdkit.Chem.rdPartialCharges import ComputeGasteigerCharges @@ -160,9 +159,7 @@ def bond_sort(arr): def test_guess_bonds_water(): u = mda.Universe(datafiles.two_water_gro) - bonds = bond_sort( - guessers.guess_bonds(u.atoms, u.atoms.positions, u.dimensions) - ) + bonds = bond_sort(guessers.guess_bonds(u.atoms, u.atoms.positions, u.dimensions)) assert_equal(bonds, ((0, 1), (0, 2), (3, 4), (3, 5))) diff --git a/testsuite/MDAnalysisTests/topology/test_itp.py b/testsuite/MDAnalysisTests/topology/test_itp.py index 5b3cf93411a..6d305b549dd 100644 --- a/testsuite/MDAnalysisTests/topology/test_itp.py +++ b/testsuite/MDAnalysisTests/topology/test_itp.py @@ -367,9 +367,7 @@ def test_defines(self, top): def test_guessed_masses(self, filename): u = mda.Universe(filename) - assert_allclose( - u.atoms.masses, [15.999, 15.999, 15.999, 15.999, 15.999] - ) + assert_allclose(u.atoms.masses, [15.999, 15.999, 15.999, 15.999, 15.999]) class TestITPKeywords(TestITPNoKeywords): @@ -394,9 +392,7 @@ def universe(self, filename): @pytest.fixture() def top(self, filename): with self.parser(filename) as p: - yield p.parse( - FLEXIBLE=True, EXTRA_ATOMS=True, HW1_CHARGE=1, HW2_CHARGE=3 - ) + yield p.parse(FLEXIBLE=True, EXTRA_ATOMS=True, HW1_CHARGE=1, HW2_CHARGE=3) def test_whether_settles_types(self, universe): for param in list(universe.bonds) + list(universe.angles): @@ -429,9 +425,7 @@ class TestNestedIfs(BaseITP): @pytest.fixture def universe(self, filename): - return mda.Universe( - filename, HEAVY_H=True, EXTRA_ATOMS=True, HEAVY_SIX=True - ) + return mda.Universe(filename, HEAVY_H=True, EXTRA_ATOMS=True, HEAVY_SIX=True) @pytest.fixture() def top(self, filename): @@ -465,9 +459,7 @@ def top(self, filename): @pytest.fixture() def universe(self, filename): - return mda.Universe( - filename, topology_format="ITP", include_dir=GMX_DIR - ) + return mda.Universe(filename, topology_format="ITP", include_dir=GMX_DIR) def test_output(self, filename): """Testing the call signature""" @@ -488,9 +480,7 @@ def test_guessed_attributes(self, filename): def test_sequential(self, universe): resids = np.array(list(range(2, 12)) + list(range(13, 23))) assert_equal(universe.residues.resids[:20], resids) - assert_equal( - universe.residues.resindices, np.arange(self.expected_n_residues) - ) + assert_equal(universe.residues.resindices, np.arange(self.expected_n_residues)) assert_equal(universe.atoms.chargegroups[-1], 63) diff --git a/testsuite/MDAnalysisTests/topology/test_lammpsdata.py b/testsuite/MDAnalysisTests/topology/test_lammpsdata.py index d384941237a..96c40eefabf 100644 --- a/testsuite/MDAnalysisTests/topology/test_lammpsdata.py +++ b/testsuite/MDAnalysisTests/topology/test_lammpsdata.py @@ -300,9 +300,7 @@ def test_interpret_atom_style(): def test_interpret_atom_style_missing(): - with pytest.raises( - ValueError, match="atom_style string missing required.+?" - ): + with pytest.raises(ValueError, match="atom_style string missing required.+?"): style = mda.topology.LAMMPSParser.DATAParser._interpret_atom_style( "id charge z y x" ) diff --git a/testsuite/MDAnalysisTests/topology/test_minimal.py b/testsuite/MDAnalysisTests/topology/test_minimal.py index 2d0e1ffd87d..29c763522ea 100644 --- a/testsuite/MDAnalysisTests/topology/test_minimal.py +++ b/testsuite/MDAnalysisTests/topology/test_minimal.py @@ -39,7 +39,6 @@ XTC, ) - working_readers = pytest.mark.parametrize( "filename,expected_n_atoms", [ @@ -104,9 +103,7 @@ def memory_possibilities(): yield array, order -memory_reader = pytest.mark.parametrize( - "array,order", list(memory_possibilities()) -) +memory_reader = pytest.mark.parametrize("array,order", list(memory_possibilities())) @memory_reader diff --git a/testsuite/MDAnalysisTests/topology/test_mol2.py b/testsuite/MDAnalysisTests/topology/test_mol2.py index 4157e8273a1..6e0b15a90ab 100644 --- a/testsuite/MDAnalysisTests/topology/test_mol2.py +++ b/testsuite/MDAnalysisTests/topology/test_mol2.py @@ -34,7 +34,6 @@ mol2_molecules, ) - mol2_wo_opt_col = """\ @MOLECULE mol2_wo_opt_col @@ -224,9 +223,7 @@ def test_bond_orders(): def test_elements(): u = mda.Universe(mol2_molecule) - assert_equal( - u.atoms.elements[:5], np.array(["N", "S", "N", "N", "O"], dtype="U3") - ) + assert_equal(u.atoms.elements[:5], np.array(["N", "S", "N", "N", "O"], dtype="U3")) # Test for #2927 @@ -305,9 +302,7 @@ def test_partial_optional_columns(): def test_mol2_wo_required_columns(): - with pytest.raises( - ValueError, match="The @ATOM block in mol2 file" - ): + with pytest.raises(ValueError, match="The @ATOM block in mol2 file"): u = mda.Universe(StringIO(mol2_wo_required_col), format="MOL2") diff --git a/testsuite/MDAnalysisTests/topology/test_pdb.py b/testsuite/MDAnalysisTests/topology/test_pdb.py index 736e0f25f3b..ab740939bba 100644 --- a/testsuite/MDAnalysisTests/topology/test_pdb.py +++ b/testsuite/MDAnalysisTests/topology/test_pdb.py @@ -302,10 +302,7 @@ def test_missing_elements_noattribute(): 1) a warning is raised if elements are missing 2) the elements attribute is not set """ - wmsg = ( - "Element information is missing, elements attribute will not be " - "populated" - ) + wmsg = "Element information is missing, elements attribute will not be " "populated" with pytest.warns(UserWarning, match=wmsg): u = mda.Universe(PDB_small) with pytest.raises(AttributeError): diff --git a/testsuite/MDAnalysisTests/topology/test_pqr.py b/testsuite/MDAnalysisTests/topology/test_pqr.py index df3790b7a75..5efffff96cc 100644 --- a/testsuite/MDAnalysisTests/topology/test_pqr.py +++ b/testsuite/MDAnalysisTests/topology/test_pqr.py @@ -113,6 +113,4 @@ def test_gromacs_flavour(): assert_almost_equal(u.atoms[0].radius, 1.48, decimal=5) assert_almost_equal(u.atoms[0].charge, -0.67, decimal=5) # coordinatey things - assert_almost_equal( - u.atoms[0].position, [15.710, 17.670, 23.340], decimal=4 - ) + assert_almost_equal(u.atoms[0].position, [15.710, 17.670, 23.340], decimal=4) diff --git a/testsuite/MDAnalysisTests/topology/test_top.py b/testsuite/MDAnalysisTests/topology/test_top.py index a67c9283b77..653ace458ba 100644 --- a/testsuite/MDAnalysisTests/topology/test_top.py +++ b/testsuite/MDAnalysisTests/topology/test_top.py @@ -90,18 +90,12 @@ def test_angles_atom_counts(self, filename): def test_dihedrals_atom_counts(self, filename): u = mda.Universe(filename) assert len(u.atoms[[0]].dihedrals) == self.expected_n_zero_dihedrals - assert ( - len(u.atoms[[self.atom_i]].dihedrals) - == self.expected_n_i_dihedrals - ) + assert len(u.atoms[[self.atom_i]].dihedrals) == self.expected_n_i_dihedrals def test_impropers_atom_counts(self, filename): u = mda.Universe(filename) assert len(u.atoms[[0]].impropers) == self.expected_n_zero_impropers - assert ( - len(u.atoms[[self.atom_i]].impropers) - == self.expected_n_i_impropers - ) + assert len(u.atoms[[self.atom_i]].impropers) == self.expected_n_i_impropers def test_bonds_identity(self, top): vals = top.bonds.values @@ -150,10 +144,7 @@ def test_improper_atoms_bonded(self, top): backward = ((imp[0], imp[1]), (imp[1], imp[2]), (imp[1], imp[3])) for a, b in zip(forward, backward): assert ( - (b in vals) - or (b[::-1] in vals) - or (a in vals) - or (a[::-1] in vals) + (b in vals) or (b[::-1] in vals) or (a in vals) or (a[::-1] in vals) ) def test_elements(self, top): @@ -403,9 +394,7 @@ def test_chainIDs(self, filename): u = mda.Universe(filename) if hasattr(self, "expected_chainIDs"): - reschainIDs = [ - atomchainIDs[0] for atomchainIDs in u.residues.chainIDs - ] + reschainIDs = [atomchainIDs[0] for atomchainIDs in u.residues.chainIDs] assert_equal( reschainIDs, self.expected_chainIDs, "unexpected element match" ) @@ -790,7 +779,9 @@ class TestPRMEP(TOPBase): class TestErrorsAndWarnings(object): - ATOMIC_NUMBER_MSG = "ATOMIC_NUMBER record not found, elements attribute will not be populated" + ATOMIC_NUMBER_MSG = ( + "ATOMIC_NUMBER record not found, elements attribute will not be populated" + ) MISSING_ELEM_MSG = ( "Unknown ATOMIC_NUMBER value found for some atoms, " "these have been given an empty element record" diff --git a/testsuite/MDAnalysisTests/topology/test_topology_base.py b/testsuite/MDAnalysisTests/topology/test_topology_base.py index 33d03258f96..16a7842e15c 100644 --- a/testsuite/MDAnalysisTests/topology/test_topology_base.py +++ b/testsuite/MDAnalysisTests/topology/test_topology_base.py @@ -6,9 +6,7 @@ class TestSquash(object): atom_resids = np.array([2, 2, 1, 1, 5, 5, 4, 4]) - atom_resnames = np.array( - ["A", "A", "B", "B", "C", "C", "D", "D"], dtype=object - ) + atom_resnames = np.array(["A", "A", "B", "B", "C", "C", "D", "D"], dtype=object) def test_squash(self): atom_residx, resids, (resnames,) = squash_by( diff --git a/testsuite/MDAnalysisTests/topology/test_tprparser.py b/testsuite/MDAnalysisTests/topology/test_tprparser.py index 354b41cbedc..18d661d5826 100644 --- a/testsuite/MDAnalysisTests/topology/test_tprparser.py +++ b/testsuite/MDAnalysisTests/topology/test_tprparser.py @@ -117,9 +117,7 @@ def test_molnums(self, top): def test_chainIDs(self, top): if hasattr(self, "ref_chainIDs"): - assert_equal( - self.ref_chainIDs, getattr(top, "chainIDs").name_lookup - ) + assert_equal(self.ref_chainIDs, getattr(top, "chainIDs").name_lookup) class TestTPR(TPRAttrs): @@ -346,9 +344,7 @@ def bonds_water(request): # The index of the first water atom is 1960 first = 1960 bonds = [ - bond - for bond in parser.bonds.values - if bond[0] >= first and bond[1] >= first + bond for bond in parser.bonds.values if bond[0] >= first and bond[1] >= first ] return bonds diff --git a/testsuite/MDAnalysisTests/topology/test_txyz.py b/testsuite/MDAnalysisTests/topology/test_txyz.py index 5615bdc985a..307beb7cb2b 100644 --- a/testsuite/MDAnalysisTests/topology/test_txyz.py +++ b/testsuite/MDAnalysisTests/topology/test_txyz.py @@ -61,9 +61,7 @@ def test_TXYZ_elements(): properly given a TXYZ file with valid elements record. """ u = mda.Universe(TXYZ, format="TXYZ") - element_list = np.array( - ["C", "H", "H", "O", "H", "C", "H", "H", "H"], dtype=object - ) + element_list = np.array(["C", "H", "H", "O", "H", "C", "H", "H", "H"], dtype=object) assert_equal(u.atoms.elements, element_list) diff --git a/testsuite/MDAnalysisTests/transformations/test_base.py b/testsuite/MDAnalysisTests/transformations/test_base.py index 492c2825b44..feb00838c5e 100644 --- a/testsuite/MDAnalysisTests/transformations/test_base.py +++ b/testsuite/MDAnalysisTests/transformations/test_base.py @@ -52,9 +52,7 @@ class CustomTransformation(TransformationBase): """Custom value for max_threads and parallelizable""" def __init__(self, max_threads=1, parallelizable=False): - super().__init__( - max_threads=max_threads, parallelizable=parallelizable - ) + super().__init__(max_threads=max_threads, parallelizable=parallelizable) def _transform(self, ts): self.runtime_info = threadpool_info() diff --git a/testsuite/MDAnalysisTests/transformations/test_boxdimensions.py b/testsuite/MDAnalysisTests/transformations/test_boxdimensions.py index a1d88b78405..06989267edb 100644 --- a/testsuite/MDAnalysisTests/transformations/test_boxdimensions.py +++ b/testsuite/MDAnalysisTests/transformations/test_boxdimensions.py @@ -51,9 +51,7 @@ def variable_boxdimensions_universe(): def test_boxdimensions_dims(boxdimensions_universe): new_dims = np.float32([2, 2, 2, 90, 90, 90]) set_dimensions(new_dims)(boxdimensions_universe.trajectory.ts) - assert_array_almost_equal( - boxdimensions_universe.dimensions, new_dims, decimal=6 - ) + assert_array_almost_equal(boxdimensions_universe.dimensions, new_dims, decimal=6) @pytest.mark.parametrize( @@ -83,9 +81,7 @@ def test_dimensions_vector(boxdimensions_universe, dim_vector_shapes): "abcd", ), ) -def test_dimensions_vector_asarray( - boxdimensions_universe, dim_vector_forms_dtypes -): +def test_dimensions_vector_asarray(boxdimensions_universe, dim_vector_forms_dtypes): # box dimension input type not convertible into array ts = boxdimensions_universe.trajectory.ts with pytest.raises(ValueError, match="cannot be converted"): @@ -142,9 +138,5 @@ def test_varying_dimensions_no_data( ] ) transform = set_dimensions(new_dims) - with pytest.raises( - ValueError, match="Dimensions array has no data for frame 2" - ): - variable_boxdimensions_universe.trajectory.add_transformations( - transform - ) + with pytest.raises(ValueError, match="Dimensions array has no data for frame 2"): + variable_boxdimensions_universe.trajectory.add_transformations(transform) diff --git a/testsuite/MDAnalysisTests/transformations/test_fit.py b/testsuite/MDAnalysisTests/transformations/test_fit.py index ecd4a87dd7a..e74d9f66769 100644 --- a/testsuite/MDAnalysisTests/transformations/test_fit.py +++ b/testsuite/MDAnalysisTests/transformations/test_fit.py @@ -155,9 +155,7 @@ def test_fit_translation_all_options(fit_universe): test_u = fit_universe[0] ref_u = fit_universe[1] # translate the test universe on the x and y coordinates only - fit_translation(test_u, ref_u, plane="xy", weights="mass")( - test_u.trajectory.ts - ) + fit_translation(test_u, ref_u, plane="xy", weights="mass")(test_u.trajectory.ts) # the reference is 10 angstrom in the z coordinate above the test universe shiftz = np.asanyarray([0, 0, -10], np.float32) ref_coordinates = ref_u.trajectory.ts.positions + shiftz diff --git a/testsuite/MDAnalysisTests/transformations/test_nojump.py b/testsuite/MDAnalysisTests/transformations/test_nojump.py index afb47c34f99..3ea7b697c9f 100644 --- a/testsuite/MDAnalysisTests/transformations/test_nojump.py +++ b/testsuite/MDAnalysisTests/transformations/test_nojump.py @@ -125,12 +125,8 @@ def nojump_universe_npt_2nd_frame_from_file(tmp_path_factory): mda.transformations.boxdimensions.set_dimensions(dim), ] u.trajectory.add_transformations(*workflow) - tmp_pdb = ( - tmp_path_factory.getbasetemp() / "nojump_npt_2nd_frame.pdb" - ).as_posix() - tmp_xtc = ( - tmp_path_factory.getbasetemp() / "nojump_npt_2nd_frame.xtc" - ).as_posix() + tmp_pdb = (tmp_path_factory.getbasetemp() / "nojump_npt_2nd_frame.pdb").as_posix() + tmp_xtc = (tmp_path_factory.getbasetemp() / "nojump_npt_2nd_frame.xtc").as_posix() u.atoms.write(tmp_pdb) with mda.Writer(tmp_xtc) as f: for ts in u.trajectory: @@ -203,9 +199,7 @@ def test_nojump_constantvel(nojump_constantvel_universe): values when iterating forwards over the sample trajectory. """ ref = nojump_constantvel_universe - towrap = ( - ref.copy() - ) # This copy of the universe will be wrapped, then unwrapped, + towrap = ref.copy() # This copy of the universe will be wrapped, then unwrapped, # and should be equal to ref. dim = np.asarray([5, 5, 5, 54, 60, 90], np.float32) workflow = [ @@ -303,9 +297,7 @@ def test_nojump_iterate_twice(nojump_universe_npt_2nd_frame_from_file): u.trajectory.add_transformations(NoJump()) timeseries_first_iteration = u.trajectory.timeseries() timeseries_second_iteration = u.trajectory.timeseries() - np.testing.assert_allclose( - timeseries_first_iteration, timeseries_second_iteration - ) + np.testing.assert_allclose(timeseries_first_iteration, timeseries_second_iteration) def test_nojump_constantvel_skip(nojump_universes_fromfile): @@ -390,7 +382,5 @@ def test_nojump_fails_when_not_at_frame_0(frame_index): u = mda.Universe(data.PSF_TRICLINIC, data.DCD_TRICLINIC) u.trajectory[frame_index] - with pytest.raises( - ValueError, match="must be applied starting from frame 0" - ): + with pytest.raises(ValueError, match="must be applied starting from frame 0"): u.trajectory.add_transformations(NoJump()) diff --git a/testsuite/MDAnalysisTests/transformations/test_positionaveraging.py b/testsuite/MDAnalysisTests/transformations/test_positionaveraging.py index f3ae050f6b5..0fbda82741d 100644 --- a/testsuite/MDAnalysisTests/transformations/test_positionaveraging.py +++ b/testsuite/MDAnalysisTests/transformations/test_positionaveraging.py @@ -101,9 +101,7 @@ def test_posavging_specific(posaveraging_universes): for ts in posaveraging_universes.trajectory[fr_list]: np.copyto(specr_avgd[..., idx], ts.positions) idx += 1 - assert_array_almost_equal( - ref_matrix_specr, specr_avgd[1, :, -1], decimal=5 - ) + assert_array_almost_equal(ref_matrix_specr, specr_avgd[1, :, -1], decimal=5) def test_posavging_specific_noreset(posaveraging_universes_noreset): @@ -124,6 +122,4 @@ def test_posavging_specific_noreset(posaveraging_universes_noreset): for ts in posaveraging_universes_noreset.trajectory[fr_list]: np.copyto(specr_avgd[..., idx], ts.positions) idx += 1 - assert_array_almost_equal( - ref_matrix_specr, specr_avgd[1, :, -1], decimal=5 - ) + assert_array_almost_equal(ref_matrix_specr, specr_avgd[1, :, -1], decimal=5) diff --git a/testsuite/MDAnalysisTests/transformations/test_rotate.py b/testsuite/MDAnalysisTests/transformations/test_rotate.py index 4f8fd9867b5..db2220fa4ca 100644 --- a/testsuite/MDAnalysisTests/transformations/test_rotate.py +++ b/testsuite/MDAnalysisTests/transformations/test_rotate.py @@ -36,9 +36,7 @@ def rotate_universes(): # create the Universe objects for the tests reference = make_Universe(trajectory=True) transformed = make_Universe(["masses"], trajectory=True) - transformed.trajectory.ts.dimensions = np.array( - [372.0, 373.0, 374.0, 90, 90, 90] - ) + transformed.trajectory.ts.dimensions = np.array([372.0, 373.0, 374.0, 90, 90, 90]) return reference, transformed @@ -74,9 +72,7 @@ def test_rotation_matrix(): assert_array_almost_equal(matrix, ref_matrix, decimal=6) -@pytest.mark.parametrize( - "point", (np.asarray([0, 0, 0]), np.asarray([[0, 0, 0]])) -) +@pytest.mark.parametrize("point", (np.asarray([0, 0, 0]), np.asarray([[0, 0, 0]]))) def test_rotateby_custom_point(rotate_universes, point): # what happens when we use a custom point for the axis of rotation? ref_u = rotate_universes[0] @@ -92,9 +88,7 @@ def test_rotateby_custom_point(rotate_universes, point): assert_array_almost_equal(transformed.positions, ref.positions, decimal=6) -@pytest.mark.parametrize( - "vector", (np.asarray([1, 0, 0]), np.asarray([[1, 0, 0]])) -) +@pytest.mark.parametrize("vector", (np.asarray([1, 0, 0]), np.asarray([[1, 0, 0]]))) def test_rotateby_vector(rotate_universes, vector): # what happens when we use a custom point for the axis of rotation? ref_u = rotate_universes[0] @@ -157,9 +151,7 @@ def test_rotateby_atomgroup_cog_pbc(rotate_universes): center_pos = selection.center_of_geometry(pbc=True) matrix = rotation_matrix(np.deg2rad(angle), vector, center_pos) ref_u.atoms.transform(matrix) - transformed = rotateby( - angle, vector, ag=selection, weights=None, wrap=True - )(trans) + transformed = rotateby(angle, vector, ag=selection, weights=None, wrap=True)(trans) assert_array_almost_equal(transformed.positions, ref.positions, decimal=6) @@ -176,9 +168,9 @@ def test_rotateby_atomgroup_com_pbc(rotate_universes): center_pos = selection.center_of_mass(pbc=True) matrix = rotation_matrix(np.deg2rad(angle), vector, center_pos) ref_u.atoms.transform(matrix) - transformed = rotateby( - angle, vector, ag=selection, weights="mass", wrap=True - )(trans) + transformed = rotateby(angle, vector, ag=selection, weights="mass", wrap=True)( + trans + ) assert_array_almost_equal(transformed.positions, ref.positions, decimal=6) diff --git a/testsuite/MDAnalysisTests/transformations/test_translate.py b/testsuite/MDAnalysisTests/transformations/test_translate.py index ccb431f3c52..3961d88dffa 100644 --- a/testsuite/MDAnalysisTests/transformations/test_translate.py +++ b/testsuite/MDAnalysisTests/transformations/test_translate.py @@ -36,9 +36,7 @@ def translate_universes(): # this universe has no masses and some tests need it as such reference = make_Universe(trajectory=True) transformed = make_Universe(["masses"], trajectory=True) - transformed.trajectory.ts.dimensions = np.array( - [372.0, 373.0, 374.0, 90, 90, 90] - ) + transformed.trajectory.ts.dimensions = np.array([372.0, 373.0, 374.0, 90, 90, 90]) return reference, transformed @@ -78,9 +76,7 @@ def test_translate_transformations_api(translate_universes): vector = np.float32([1, 2, 3]) ref.positions += vector trans_u.trajectory.add_transformations(translate(vector)) - assert_array_almost_equal( - trans_u.trajectory.ts.positions, ref.positions, decimal=6 - ) + assert_array_almost_equal(trans_u.trajectory.ts.positions, ref.positions, decimal=6) def test_center_in_box_bad_ag(translate_universes): @@ -219,6 +215,4 @@ def test_center_transformations_api(translate_universes): ref.positions += box_center - ref_center ag = trans_u.residues[0].atoms trans_u.trajectory.add_transformations(center_in_box(ag)) - assert_array_almost_equal( - trans_u.trajectory.ts.positions, ref.positions, decimal=6 - ) + assert_array_almost_equal(trans_u.trajectory.ts.positions, ref.positions, decimal=6) diff --git a/testsuite/MDAnalysisTests/transformations/test_wrap.py b/testsuite/MDAnalysisTests/transformations/test_wrap.py index a3439fb95cb..a35b03644cd 100644 --- a/testsuite/MDAnalysisTests/transformations/test_wrap.py +++ b/testsuite/MDAnalysisTests/transformations/test_wrap.py @@ -93,15 +93,11 @@ def test_wrap_no_options(wrap_universes): ) -@pytest.mark.parametrize( - "compound", ("group", "residues", "segments", "fragments") -) +@pytest.mark.parametrize("compound", ("group", "residues", "segments", "fragments")) def test_wrap_with_compounds(compound_wrap_universes, compound): trans, ref = compound_wrap_universes ref.select_atoms("not resname SOL").wrap(compound=compound) - wrap(trans.select_atoms("not resname SOL"), compound=compound)( - trans.trajectory.ts - ) + wrap(trans.select_atoms("not resname SOL"), compound=compound)(trans.trajectory.ts) assert_array_almost_equal( trans.trajectory.ts.positions, ref.trajectory.ts.positions, decimal=6 ) diff --git a/testsuite/MDAnalysisTests/util.py b/testsuite/MDAnalysisTests/util.py index 58cec2cbac1..27c4daef53c 100644 --- a/testsuite/MDAnalysisTests/util.py +++ b/testsuite/MDAnalysisTests/util.py @@ -254,13 +254,10 @@ def __exit__(self, exc_type, exc_val, exc_tb): PendingDeprecationWarning, ) if any( - issubclass(c, deprecation_categories) - for c in self._captured_categories + issubclass(c, deprecation_categories) for c in self._captured_categories ): __tracebackhide__ = True - msg = ( - "Produced DeprecationWarning or PendingDeprecationWarning" - ) + msg = "Produced DeprecationWarning or PendingDeprecationWarning" raise AssertionError(msg) diff --git a/testsuite/MDAnalysisTests/utils/test_authors.py b/testsuite/MDAnalysisTests/utils/test_authors.py index 13563dadfdf..eff77586d58 100644 --- a/testsuite/MDAnalysisTests/utils/test_authors.py +++ b/testsuite/MDAnalysisTests/utils/test_authors.py @@ -26,6 +26,4 @@ def test_package_authors(): - assert ( - len(MDAnalysis.__authors__) > 0 - ), "Could not find the list of authors" + assert len(MDAnalysis.__authors__) > 0, "Could not find the list of authors" diff --git a/testsuite/MDAnalysisTests/utils/test_duecredit.py b/testsuite/MDAnalysisTests/utils/test_duecredit.py index c99f14dbf93..fe07d6d1b07 100644 --- a/testsuite/MDAnalysisTests/utils/test_duecredit.py +++ b/testsuite/MDAnalysisTests/utils/test_duecredit.py @@ -40,10 +40,7 @@ @pytest.mark.skipif( - ( - os.environ.get("DUECREDIT_ENABLE", "yes").lower() - in ("no", "0", "false") - ), + (os.environ.get("DUECREDIT_ENABLE", "yes").lower() in ("no", "0", "false")), reason="duecredit is explicitly disabled with DUECREDIT_ENABLE=no", ) class TestDuecredit(object): diff --git a/testsuite/MDAnalysisTests/utils/test_failure.py b/testsuite/MDAnalysisTests/utils/test_failure.py index 494e84cdb9f..29ff10b8466 100644 --- a/testsuite/MDAnalysisTests/utils/test_failure.py +++ b/testsuite/MDAnalysisTests/utils/test_failure.py @@ -28,6 +28,4 @@ def test_failure(): if "MDA_FAILURE_TEST" in os.environ: # Have a file open to trigger an output from the open_files plugin. f = open("./failure.txt", "w") - raise AssertionError( - "the MDA_FAILURE_TEST environment variable is set" - ) + raise AssertionError("the MDA_FAILURE_TEST environment variable is set") diff --git a/testsuite/MDAnalysisTests/utils/test_imports.py b/testsuite/MDAnalysisTests/utils/test_imports.py index 016388e3244..aefbf59fa05 100644 --- a/testsuite/MDAnalysisTests/utils/test_imports.py +++ b/testsuite/MDAnalysisTests/utils/test_imports.py @@ -61,7 +61,5 @@ def test_relative_import(testing_module): ): raise AssertionError( "A relative import statement was found in " - "module {testing_module} at linenumber {lineno}.".format( - **vars() - ) + "module {testing_module} at linenumber {lineno}.".format(**vars()) ) diff --git a/testsuite/MDAnalysisTests/utils/test_meta.py b/testsuite/MDAnalysisTests/utils/test_meta.py index b6e536ef009..a9790fe8115 100644 --- a/testsuite/MDAnalysisTests/utils/test_meta.py +++ b/testsuite/MDAnalysisTests/utils/test_meta.py @@ -55,9 +55,7 @@ def test_version_format(version=None): r"(?P\d+)\.(?P\d+)\.(?P\d+)(-(?P\w+))?$", version, ) - assert ( - m - ), "version {0} does not match the MAJOR.MINOR.PATCH(-suffix) format".format( + assert m, "version {0} does not match the MAJOR.MINOR.PATCH(-suffix) format".format( version ) diff --git a/testsuite/MDAnalysisTests/utils/test_modelling.py b/testsuite/MDAnalysisTests/utils/test_modelling.py index c014c9f4d03..a316fa2a646 100644 --- a/testsuite/MDAnalysisTests/utils/test_modelling.py +++ b/testsuite/MDAnalysisTests/utils/test_modelling.py @@ -71,9 +71,7 @@ def capping(ref, ace, nma, output): "mobile": "resid {0} and backbone and not (resname NMA NME)".format( resid_max ), - "reference": "resid {0} and (backbone or name OT2)".format( - resid_max - ), + "reference": "resid {0} and (backbone or name OT2)".format(resid_max), }, strict=True, ) @@ -118,9 +116,7 @@ def test_capping_file(self, tmpdir): assert_equal(ace.resids[0], 1) assert_equal(nma.resids[0], 16) - assert_array_equal( - peptide.trajectory.ts.dimensions, u.trajectory.ts.dimensions - ) + assert_array_equal(peptide.trajectory.ts.dimensions, u.trajectory.ts.dimensions) def test_capping_inmemory(self, tmpdir): peptide = MDAnalysis.Universe(capping_input) @@ -142,9 +138,7 @@ def test_capping_inmemory(self, tmpdir): assert_equal(ace.resids[0], 1) assert_equal(nma.resids[0], 16) - assert_array_equal( - peptide.trajectory.ts.dimensions, u.trajectory.ts.dimensions - ) + assert_array_equal(peptide.trajectory.ts.dimensions, u.trajectory.ts.dimensions) @pytest.fixture() @@ -169,9 +163,7 @@ def u_without_coords(): class TestMerge(object): def test_merge(self, u_protein, u_ligand, u_water, tmpdir): - ids_before = [ - a.index for u in [u_protein, u_ligand, u_water] for a in u.atoms - ] + ids_before = [a.index for u in [u_protein, u_ligand, u_water] for a in u.atoms] # Do the merge u0 = MDAnalysis.Merge(u_protein.atoms, u_ligand.atoms, u_water.atoms) # Check that the output Universe has the same number of atoms as the @@ -184,19 +176,11 @@ def test_merge(self, u_protein, u_ligand, u_water, tmpdir): # segments as the starting AtomGroups assert_equal( len(u0.residues), - ( - len(u_protein.residues) - + len(u_ligand.residues) - + len(u_water.residues) - ), + (len(u_protein.residues) + len(u_ligand.residues) + len(u_water.residues)), ) assert_equal( len(u0.segments), - ( - len(u_protein.segments) - + len(u_ligand.segments) - + len(u_water.segments) - ), + (len(u_protein.segments) + len(u_ligand.segments) + len(u_water.segments)), ) # Make sure that all the atoms in the new universe are assigned to only @@ -208,9 +192,7 @@ def test_merge(self, u_protein, u_ligand, u_water, tmpdir): # Make sure that the atom ids of the original universes are unchanged, # ie we didn't make the original Universes 'dirty' - ids_after = [ - a.index for u in [u_protein, u_ligand, u_water] for a in u.atoms - ] + ids_after = [a.index for u in [u_protein, u_ligand, u_water] for a in u.atoms] assert_equal( len(ids_after), (len(u_protein.atoms) + len(u_ligand.atoms) + len(u_water.atoms)), @@ -229,9 +211,7 @@ def test_merge(self, u_protein, u_ligand, u_water, tmpdir): assert_equal(ids_new, ids_new2) def test_merge_same_universe(self, u_protein): - u0 = MDAnalysis.Merge( - u_protein.atoms, u_protein.atoms, u_protein.atoms - ) + u0 = MDAnalysis.Merge(u_protein.atoms, u_protein.atoms, u_protein.atoms) assert_equal(len(u0.atoms), 3 * len(u_protein.atoms)) assert_equal(len(u0.residues), 3 * len(u_protein.residues)) assert_equal(len(u0.segments), 3 * len(u_protein.segments)) @@ -307,18 +287,9 @@ def test_merge_with_topology_from_different_universes(self, u, u_ligand): # PDB reader yields empty Bonds group, which means bonds from # PSF/DCD survive the merge # assert(not hasattr(u_merge.atoms, 'bonds') or len(u_merge.atoms.bonds) == 0) - assert ( - not hasattr(u_merge.atoms, "angles") - or len(u_merge.atoms.bonds) == 0 - ) - assert ( - not hasattr(u_merge.atoms, "dihedrals") - or len(u_merge.atoms.bonds) == 0 - ) - assert ( - not hasattr(u_merge.atoms, "impropers") - or len(u_merge.atoms.bonds) == 0 - ) + assert not hasattr(u_merge.atoms, "angles") or len(u_merge.atoms.bonds) == 0 + assert not hasattr(u_merge.atoms, "dihedrals") or len(u_merge.atoms.bonds) == 0 + assert not hasattr(u_merge.atoms, "impropers") or len(u_merge.atoms.bonds) == 0 def test_merge_without_topology(self, u): # This shouldn't have topology as we merged single atoms diff --git a/testsuite/MDAnalysisTests/utils/test_pickleio.py b/testsuite/MDAnalysisTests/utils/test_pickleio.py index ae6c342cec1..00c5b7307ce 100644 --- a/testsuite/MDAnalysisTests/utils/test_pickleio.py +++ b/testsuite/MDAnalysisTests/utils/test_pickleio.py @@ -163,9 +163,7 @@ def test_pickle_with_write_mode(unpicklable_f, tmpdir): def test_GSD_pickle(): 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 - ) + assert_equal(gsd_io[0].particles.position, gsd_io_pickled[0].particles.position) @pytest.mark.skipif(not HAS_GSD, reason="gsd not installed") @@ -189,9 +187,7 @@ def test_NCDF_mmap_pickle(): assert_equal(ncdf_io_pickled.use_mmap, False) -@pytest.mark.skipif( - not check_chemfiles_version(), reason="Wrong version of chemfiles" -) +@pytest.mark.skipif(not check_chemfiles_version(), reason="Wrong version of chemfiles") def test_Chemfiles_pickle(): chemfiles_io = ChemfilesPicklable(XYZ) chemfiles_io_pickled = pickle.loads(pickle.dumps(chemfiles_io)) @@ -202,14 +198,10 @@ def test_Chemfiles_pickle(): assert_equal(frame.positions[:], frame_pickled.positions[:]) -@pytest.mark.skipif( - not check_chemfiles_version(), reason="Wrong version of chemfiles" -) +@pytest.mark.skipif(not check_chemfiles_version(), reason="Wrong version of chemfiles") def test_Chemfiles_with_write_mode(tmpdir): with pytest.raises(ValueError, match=r"Only read mode"): - chemfiles_io = ChemfilesPicklable( - tmpdir.mkdir("xyz").join("t.xyz"), mode="w" - ) + chemfiles_io = ChemfilesPicklable(tmpdir.mkdir("xyz").join("t.xyz"), mode="w") @pytest.mark.skipif(not HAS_H5PY, reason="h5py not installed") diff --git a/testsuite/MDAnalysisTests/utils/test_qcprot.py b/testsuite/MDAnalysisTests/utils/test_qcprot.py index 8ee971c227e..622a4bb0c23 100644 --- a/testsuite/MDAnalysisTests/utils/test_qcprot.py +++ b/testsuite/MDAnalysisTests/utils/test_qcprot.py @@ -36,6 +36,7 @@ [-0.0271479 -0.67963547 0.73304748]] """ + import numpy as np import MDAnalysis.lib.qcprot as qcp @@ -47,9 +48,7 @@ @pytest.fixture() def atoms_a(): - return np.array( - [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], dtype=np.float64 - ) + return np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], dtype=np.float64) @pytest.fixture() diff --git a/testsuite/MDAnalysisTests/utils/test_selections.py b/testsuite/MDAnalysisTests/utils/test_selections.py index 212bce97dae..256afe7c0bb 100644 --- a/testsuite/MDAnalysisTests/utils/test_selections.py +++ b/testsuite/MDAnalysisTests/utils/test_selections.py @@ -42,9 +42,7 @@ class _SelectionWriter(object): filename = None - max_number = ( - 357 # to keep fixtures smallish, only select CAs up to number 357 - ) + max_number = 357 # to keep fixtures smallish, only select CAs up to number 357 @staticmethod @pytest.fixture() @@ -139,9 +137,7 @@ class TestSelectionWriter_Charmm(_SelectionWriter): writer = MDAnalysis.selections.charmm.SelectionWriter filename = "CA.str" ref_name = "CA_selection" - ref_selectionstring = lines2one( - [ - """! MDAnalysis CHARMM selection + ref_selectionstring = lines2one(["""! MDAnalysis CHARMM selection DEFINE CA_selection SELECT - BYNUM 5 .or. BYNUM 22 .or. BYNUM 46 .or. BYNUM 65 .or. - BYNUM 84 .or. BYNUM 103 .or. BYNUM 122 .or. BYNUM 129 .or. - @@ -149,9 +145,7 @@ class TestSelectionWriter_Charmm(_SelectionWriter): BYNUM 177 .or. BYNUM 199 .or. BYNUM 206 .or. BYNUM 220 .or. - BYNUM 237 .or. BYNUM 247 .or. BYNUM 264 .or. BYNUM 284 .or. - BYNUM 303 .or. BYNUM 320 .or. BYNUM 335 .or. BYNUM 357 END - """ - ] - ) + """]) def _assert_selectionstring(self, namedfile): selectionstring = lines2one(namedfile.readlines()) @@ -168,14 +162,12 @@ class TestSelectionWriter_PyMOL(_SelectionWriter): filename = "CA.pml" ref_name = "CA_selection" ref_selectionstring = lines2one( - [ - """# MDAnalysis PyMol selection\n select CA_selection, \\ + ["""# MDAnalysis PyMol selection\n select CA_selection, \\ index 5 | index 22 | index 46 | index 65 | index 84 | index 103 | \\ index 122 | index 129 | index 141 | index 153 | index 160 | index 170 | \\ index 177 | index 199 | index 206 | index 220 | index 237 | index 247 | \\ index 264 | index 284 | index 303 | index 320 | index 335 | index 357 - """ - ] + """] ) def _assert_selectionstring(self, namedfile): @@ -229,9 +221,7 @@ class TestSelectionWriter_Jmol(_SelectionWriter): def _assert_selectionstring(self, namedfile): header, indices = spt2array(namedfile.readline()) - assert_equal( - header, self.ref_name, err_msg="SPT file has wrong selection name" - ) + assert_equal(header, self.ref_name, err_msg="SPT file has wrong selection name") assert_array_equal( indices, self.ref_indices, diff --git a/testsuite/MDAnalysisTests/utils/test_streamio.py b/testsuite/MDAnalysisTests/utils/test_streamio.py index 869ea317ff4..93770550891 100644 --- a/testsuite/MDAnalysisTests/utils/test_streamio.py +++ b/testsuite/MDAnalysisTests/utils/test_streamio.py @@ -227,9 +227,7 @@ def test_join(self, tmpdir, funcname="join"): ) def test_expanduser_noexpansion_returns_NamedStream(self): - ns = self.create_NamedStream( - "de/zipferlack.txt" - ) # no tilde ~ in name! + ns = self.create_NamedStream("de/zipferlack.txt") # no tilde ~ in name! reference = ns.name value = os.path.expanduser(ns) assert_equal( @@ -306,9 +304,7 @@ def __init__(self): with open(fn) as filed: self.buffers[name] = "".join(filed.readlines()) self.filenames["XYZ_PSF"] = "bogus/path/mini.psf" - self.buffers[ - "XYZ_PSF" - ] = """\ + self.buffers["XYZ_PSF"] = """\ PSF CMAP 1 !NTITLE @@ -325,9 +321,7 @@ def __init__(self): 8 A 380 THR O O -0.510000 15.9990 0 """ self.filenames["XYZ"] = "bogus/path/mini.xyz" - self.buffers[ - "XYZ" - ] = """\ + self.buffers["XYZ"] = """\ 8 frame 1 N 0.93100 17.31800 16.42300 @@ -446,9 +440,7 @@ def test_MOL2Reader(self, streamData): assert_equal(len(u.atoms), 49) assert_equal(u.trajectory.n_frames, 200) u.trajectory[199] - assert_array_almost_equal( - u.atoms.positions[0], [1.7240, 11.2730, 14.1200] - ) + assert_array_almost_equal(u.atoms.positions[0], [1.7240, 11.2730, 14.1200]) def test_XYZReader(self, streamData): u = MDAnalysis.Universe( @@ -457,9 +449,7 @@ def test_XYZReader(self, streamData): ) assert_equal(len(u.atoms), 8) assert_equal(u.trajectory.n_frames, 3) - assert_equal( - u.trajectory.frame, 0 - ) # weird, something odd with XYZ reader + assert_equal(u.trajectory.frame, 0) # weird, something odd with XYZ reader u.trajectory.next() # (should really only need one next()... ) assert_equal(u.trajectory.frame, 1) # !!!! ??? u.trajectory.next() # frame 2 diff --git a/testsuite/MDAnalysisTests/utils/test_transformations.py b/testsuite/MDAnalysisTests/utils/test_transformations.py index 72d6831cd1f..7a665362184 100644 --- a/testsuite/MDAnalysisTests/utils/test_transformations.py +++ b/testsuite/MDAnalysisTests/utils/test_transformations.py @@ -35,7 +35,6 @@ from unittest import TestCase - """ Testing transformations is weird because there are 2 versions of many of these functions. This is because both python and Cython versions of @@ -230,9 +229,7 @@ def test_projection_from_matrix_2(self, data): def test_projection_from_matrix_3(self, data): point, normal, direct, persp = data - P0 = t.projection_matrix( - point, normal, perspective=persp, pseudo=False - ) + P0 = t.projection_matrix(point, normal, perspective=persp, pseudo=False) result = t.projection_from_matrix(P0, pseudo=False) P1 = t.projection_matrix(*result) assert_equal(t.is_same_transform(P0, P1), True) @@ -537,9 +534,7 @@ def test_quaternion_from_matrix_2(self, f): def test_quaternion_from_matrix_3(self, f): R = t.rotation_matrix(0.123, (1, 2, 3)) q = f(R, True) - assert_allclose( - q, [0.9981095, 0.0164262, 0.0328524, 0.0492786], atol=_ATOL - ) + assert_allclose(q, [0.9981095, 0.0164262, 0.0328524, 0.0492786], atol=_ATOL) def test_quaternion_from_matrix_4(self, f): R = [ diff --git a/testsuite/MDAnalysisTests/utils/test_units.py b/testsuite/MDAnalysisTests/utils/test_units.py index dad63d6b11c..be6f1754f4e 100644 --- a/testsuite/MDAnalysisTests/utils/test_units.py +++ b/testsuite/MDAnalysisTests/utils/test_units.py @@ -39,9 +39,7 @@ def test_unicode_encoding_with_symbol(self): try: assert_equal(units.lengthUnit_factor["Å"], 1.0) except KeyError: - raise AssertionError( - "UTF-8-encoded symbol for Angtrom not supported" - ) + raise AssertionError("UTF-8-encoded symbol for Angtrom not supported") class TestConstants(object): @@ -103,7 +101,7 @@ def test_length(self, quantity, unit1, unit2, ref): (1, "ms", "ps", 1e9), (1, "ps", "us", 1e-6), (1, "us", "ps", 1e6), - (1, "\u03BCs", "ps", 1e6), + (1, "\u03bcs", "ps", 1e6), (1, "fs", "ns", 1e-6), ), ) @@ -139,8 +137,8 @@ def test_force(self, quantity, unit1, unit2, ref): (1, "A/ps", "pm/ps", 1e2), (1, "A/ms", "A/ps", 1e-9), (1, "A/us", "A/ps", 1e-6), - (1, "A/\u03BCs", "A/ps", 1e-6), - (1, "\u212b/\u03BCs", "A/ps", 1e-6), + (1, "A/\u03bcs", "A/ps", 1e-6), + (1, "\u212b/\u03bcs", "A/ps", 1e-6), (1, "A/fs", "A/ps", 1e3), (1, "A/ps", "A/fs", 1e-3), (1, "A/ns", "A/ms", 1e6), diff --git a/testsuite/MDAnalysisTests/visualization/test_streamlines.py b/testsuite/MDAnalysisTests/visualization/test_streamlines.py index 80bd4299cff..6902bed6710 100644 --- a/testsuite/MDAnalysisTests/visualization/test_streamlines.py +++ b/testsuite/MDAnalysisTests/visualization/test_streamlines.py @@ -172,9 +172,7 @@ def test_per_core_work_2D(membrane_xtc, univ): ymin = univ.atoms.positions[..., 1].min() ymax = univ.atoms.positions[..., 1].max() tuple_of_limits = (xmin, xmax, ymin, ymax) - grid = streamlines.produce_grid( - tuple_of_limits=tuple_of_limits, grid_spacing=20 - ) + grid = streamlines.produce_grid(tuple_of_limits=tuple_of_limits, grid_spacing=20) ( list_square_vertex_arrays_per_core, list_parent_index_values, @@ -184,9 +182,7 @@ def test_per_core_work_2D(membrane_xtc, univ): values = streamlines.per_core_work( topology_file_path=Martini_membrane_gro, trajectory_file_path=membrane_xtc, - list_square_vertex_arrays_this_core=list_square_vertex_arrays_per_core[ - 0 - ], + list_square_vertex_arrays_this_core=list_square_vertex_arrays_per_core[0], MDA_selection="name PO4", start_frame=1, end_frame=2, diff --git a/testsuite/setup.py b/testsuite/setup.py index ef6b19560cd..20d43eef6db 100755 --- a/testsuite/setup.py +++ b/testsuite/setup.py @@ -39,6 +39,7 @@ https://github.com/MDAnalysis/mdanalysis/discussions """ + from setuptools import setup from setuptools.command import sdist